Example #1
0
def make_stuff_for_part_2():
    ''' Find C/N vs. n '''
    #===============================================================================
    # Adjustable parameters for the problem 
    J = 1.5
    n_list = [5, 10, 20, 30, 50, 75, 100, 200, 500] #TODO: make this array-able... in B) we need to compare results for different n.
    # TODO: comment out the following
#    n_list = [10]
    kT_min = 1.5
    kT_max = 4.5
    kT_step = 0.1
    #===============================================================================
    # make array of temps
    kT_array = np.arange( kT_min, kT_max + kT_step, kT_step )
    # make an empty array to store lattice simulations
    lattices = []
    for n in n_list:
        n_steps = int( ( n ** 2 ) * 100 )
        lattice = Lattice( J, n, n_steps, kT_array )
        lattice.run_metropolous_algorithm()
        lattices.append( lattice )
    # save the list of lattice simulations to a pickle:
    fp = filepath_for_now( local_data_directory )
    print "Save to "
    print fp
    pickle.dump( lattices, open( fp + '.p' , "wb" ) ) 
Example #2
0
    def visualise(project_id=str(),
                  max_distance=False,
                  critical_concentration=None,
                  heatmap=False,
                  simulation_number=str(),
                  concentration=False):

        if max_distance:
            maximal_distances = json.load(
                open(
                    'Dataset/Maximal_distances/' + str(project_id) + '/' +
                    str(critical_concentration), 'r'))
            Visualiser.plot_scatter_2d(x=numpy.arange(
                len(maximal_distances['concentrated'])),
                                       y=maximal_distances['concentrated'],
                                       project_id=project_id,
                                       info=str(critical_concentration))

        if heatmap:
            info = json.load(open(project_id, 'r'))
            lattice = Lattice.load(project_id=project_id,
                                   simulation_number=simulation_number)
            print(lattice.cells)
            # critical_concentration = str(critical_concentration)

            if critical_concentration:
                Visualiser.concentration_heatmap(
                    lattice=lattice,
                    simulation_number=simulation_number,
                    critical_concentration=critical_concentration)
            else:
                Visualiser.concentration_heatmap(
                    lattice=lattice, simulation_number=simulation_number)
        if concentration:
            data = []
            # for simulation_number in [50, 100, 150, 300, 400, 450, 499]:
            # for simulation_number in [50, 100, 150, 200, 250, 300, 350, 400, 450, 499]:
            info = json.load(open(project_id, 'r')),
            lattice = Lattice.load(project_id=project_id,
                                   simulation_number=str(300))

            # lattice.critical_concentration = 3500
            # lattice.update_critical()

            val = dict()
            for cell in lattice.cells.values():
                val[cell.index.x_axis] = cell.get_concentration()
            od = OrderedDict(sorted(val.items()))
            x = []
            y = []
            for key, val in od.items():
                x.append(key)
                y.append(val)
            # if x or y:
            #     x.insert(0,x[0])
            #     y.insert(0,0)
            #     x.append(x[-1])
            #     y.append(0)
            data.append([x, y, simulation_number])
            Visualiser.plot_scatter_2d(data=data, project_id=project_id)
Example #3
0
    def __init__(self,
                 atoms=[],
                 lattice=None,
                 sgid=1,
                 description=None,
                 filename=None,
                 primitive_unitcell=None):
        """define group of atoms in a specified lattice.

        atoms    -- list of Atom instances to be included in this Structure.
                    When atoms argument is an existing Structure instance,
                    the new Structure is its copy.
        lattice  -- instance of Lattice defining coordinate systems, property.
        sgid     -- space group symbol, either short_name or pdb_name,
                    whatever it means in mmlib.  Can be also an integer.
        description -- string description of the structure
        filename -- optional, name of a file to load the structure from.
                    Overrides atoms argument when specified.

        Structure(stru)     create a copy of Structure instance stru.

        Because Structure is inherited from a list it can use list expansions,
        for example:
            oxygen_atoms = [ for a in stru if a.symbol == "O" ]
            oxygen_stru = Structure(oxygen_atoms, lattice=stru.lattice)
        """

        self._labels = {}
        self._labels_cached = False
        if isinstance(atoms, Structure):
            stru = atoms
            # create a shallow copy of all source attributes
            self.__dict__.update(stru.__dict__)
            # make a deep copy of source lattice
            self.lattice = Lattice(stru.lattice)

        self.description = description
        self.sg = sgid
        # check if data should be loaded from file
        if filename is not None:
            self.read(filename)
        # otherwise assign list of atoms to self
        else:
            self[:] = atoms

        # override from lattice argument
        if lattice is None:
            if not self.lattice: self.lattice = Lattice()
        #elif not isinstance(lattice, Lattice):
        #   emsg = "expected instance of Lattice"
        #    raise TypeError(emsg)
        else:
            self.lattice = lattice

        self._primitive_unitcell = primitive_unitcell
        import time
        self.date = time.ctime()
Example #4
0
    def inspect_lattice(self, critical_concentration):
        info = dict()
        info = json.load(open(str(self.id) + self.sub_id + 'info', 'r'))

        lattice = Lattice()
        lattice.critical_concentration = critical_concentration

        i = 0
        while True:
            if os.path.exists(self.id + self.sub_id + 'Lattices/' + str(i)):
                print(str(i))

                lattice.cells = Lattice.load(cells_only=True,
                                             project_id=self.id,
                                             sub_id=self.sub_id,
                                             simulation_number=i,
                                             implementation=True)

                lattice.update_critical()

                lattice.update_maximal_distances(dimension=info['dimension'],
                                                 check_area=False)

                i += 1

            else:
                break

        json.dump(
            lattice.maximal_distances['concentrated'],
            open(
                self.id + self.sub_id + 'Maximal_distances/' +
                str(critical_concentration) + 'n2', 'w'))
Example #5
0
    def __init__(self, atoms=[], lattice=None, sgid=1, description=None, filename=None,
                 primitive_unitcell=None
                 ):
        """define group of atoms in a specified lattice.

        atoms    -- list of Atom instances to be included in this Structure.
                    When atoms argument is an existing Structure instance,
                    the new Structure is its copy.
        lattice  -- instance of Lattice defining coordinate systems, property.
        sgid     -- space group symbol, either short_name or pdb_name,
                    whatever it means in mmlib.  Can be also an integer.
        description -- string description of the structure
        filename -- optional, name of a file to load the structure from.
                    Overrides atoms argument when specified.

        Structure(stru)     create a copy of Structure instance stru.

        Because Structure is inherited from a list it can use list expansions,
        for example:
            oxygen_atoms = [ for a in stru if a.symbol == "O" ]
            oxygen_stru = Structure(oxygen_atoms, lattice=stru.lattice)
        """

        self._labels = {}
        self._labels_cached = False
        if isinstance(atoms, Structure):
            stru = atoms
            # create a shallow copy of all source attributes
            self.__dict__.update(stru.__dict__)
            # make a deep copy of source lattice
            self.lattice = Lattice(stru.lattice)

        self.description = description
        self.sg = sgid
        # check if data should be loaded from file
        if filename is not None:
            self.read(filename)
        # otherwise assign list of atoms to self
        else:
            self[:] = atoms
            
        # override from lattice argument
        if lattice is None:
            if not self.lattice:    self.lattice = Lattice()
        #elif not isinstance(lattice, Lattice):
        #   emsg = "expected instance of Lattice"
        #    raise TypeError(emsg)
        else:
            self.lattice = lattice


        self._primitive_unitcell = primitive_unitcell
        import time
        self.date = time.ctime()
    def __init__(self,
                 atoms=[],
                 lattice=None,
                 description=None,
                 filename=None,
                 useOpenBabel=False):
        """define group of atoms in a specified lattice.

        atoms    -- list of Atom instances to be included in this Molecule.
                    When atoms argument is an existing Molecule instance,
                    the new Molecule is its copy.
        lattice  -- instance of Lattice defining coordinate systems.
        description -- string description of the structure
        filename -- optional, name of a file to load the structure from.
                    Overrides atoms argument when specified.

        Molecule(mol)     create a copy of Molecule instance.

        Because Molecule is inherited from a list it can use list expansions,
        for example:
            oxygen_atoms = [ for a in stru if a.symbol == "O" ]
        """
        self._labels = {}
        self._labels_cached = False
        if isinstance(atoms, Molecule):
            mol = atoms
            # create a shallow copy of all source attributes
            self.__dict__.update(mol.__dict__)
            # make a deep copy of source lattice
            self.lattice = Lattice(mol.lattice)

        self.description = description
        # check if data should be loaded from file
        if filename is not None:
            if useOpenBabel:
                base, ext = os.path.splitext(filename)
#                self.cinfonyMol = obabel.readfile(ext[1:],filename)
#                for atom in self.cinfonyMol:
#                    self.addNewAtom(atom)
            else:
                self.read(filename)
        # otherwise assign list of atoms to self
        else:
            self[:] = atoms
        # override from lattice argument
        if lattice is None:
            if not self.lattice: self.lattice = Lattice()
        #elif not isinstance(lattice, Lattice):
        #   emsg = "expected instance of Lattice"
        #    raise TypeError(emsg)
        else:
            self.lattice = lattice
        import time
        self.date = time.ctime()
    def __init__(self, atoms=[], lattice=None, description=None, filename=None,
                 useOpenBabel=False):
        """define group of atoms in a specified lattice.

        atoms    -- list of Atom instances to be included in this Molecule.
                    When atoms argument is an existing Molecule instance,
                    the new Molecule is its copy.
        lattice  -- instance of Lattice defining coordinate systems.
        description -- string description of the structure
        filename -- optional, name of a file to load the structure from.
                    Overrides atoms argument when specified.

        Molecule(mol)     create a copy of Molecule instance.

        Because Molecule is inherited from a list it can use list expansions,
        for example:
            oxygen_atoms = [ for a in stru if a.symbol == "O" ]
        """
        self._labels = {}
        self._labels_cached = False
        if isinstance(atoms, Molecule):
            mol = atoms
            # create a shallow copy of all source attributes
            self.__dict__.update(mol.__dict__)
            # make a deep copy of source lattice
            self.lattice = Lattice(mol.lattice)

        self.description = description
        # check if data should be loaded from file
        if filename is not None:
            if useOpenBabel:
                base,ext=os.path.splitext(filename)
#                self.cinfonyMol = obabel.readfile(ext[1:],filename)
#                for atom in self.cinfonyMol:
#                    self.addNewAtom(atom)
            else:
                self.read(filename)
        # otherwise assign list of atoms to self
        else:
            self[:] = atoms 
        # override from lattice argument
        if lattice is None:
            if not self.lattice: self.lattice = Lattice()
        #elif not isinstance(lattice, Lattice):
        #   emsg = "expected instance of Lattice"
        #    raise TypeError(emsg)
        else:
            self.lattice = lattice
        import time
        self.date = time.ctime()
Example #8
0
    def analyse(file, graph_directory, export_directory):
        print('-' * 25)
        print('Analysis of \'' + file.stem + '\'')

        print(file)

        engine = Engine(graph_directory)

        context = engine.import_context_from_file(file)
        #         context_extended = engine.transform_to_extended_context(context)
        latice_context = Lattice(engine, context)
        latice_context.generate_graph(graph_directory)
        #         context.display()
        #         context.export_txt_for_conex(export_directory)
        #         latice_context = Lattice(engine, context_extended)
        #         latice_context.generate_graph(graph_directory, add_name = '_ext', extended = True)

        #         context.display()
        #         context.export_txt_for_conex(export_directory)

        median_context = engine.transform_to_median_context(context)
        lattice_median_context = Lattice(engine, median_context)
        lattice_median_context.generate_graph(graph_directory,
                                              differences=context.J)

        print('-' * 25)
Example #9
0
    def set_open_position(self, value):
        refresh_nb = False
        if self._open != value:
            refresh_nb = True

        self._open = tuple(value)
        if refresh_nb:
            self.neighbours_open_position = Lattice.get_neighbours_open(tuple(value))
Example #10
0
    def create_lattice(self):
        info = dict()
        info = json.load(open(str(self.id) + self.sub_id + '/' + 'info', 'r'))

        lattice = Lattice()
        lattice.density = 1
        i = 0
        while True:
            if os.path.exists(self.id + self.sub_id + '/Particles/' + str(i)):

                print(str(i))

                particles = Particles.load(project_id=self.id,
                                           sub_id=self.sub_id,
                                           simulation_number=i,
                                           implementation=True)

                lattice.update(particles=particles)

                lattice.save(project_id=self.id,
                             sub_id=self.sub_id,
                             simulation_number=i,
                             implementation=True)

                i += 1

            else:
                break
Example #11
0
    def prune_step_1_always_keep_alternative(self):
        """
        Return
            always_keep(dict)
            alternatives(dict)
        """
        current_piece = self.SentencePiece.get_pieces()
        # pieceをkeyとしてdictで管理
        always_keep = dict()
        alternatives = defaultdict(list)

        # First segments the current sentencepieces to kwon how each sentencepiece is resegmented if this sentencepiece is  removed from vocabulary.
        for key, score in current_piece.items():
            L = Lattice()
            L.set_sentence(key)
            L.populate_nodes(current_piece, self.Trie)
            nbests = L.NBest(2, ret_piece=True)

            if len(nbests) == 1:  # only one way to resegment it
                always_keep[key] = True

            elif len(nbests[0]) >= 2:
                always_keep[key] = False

            elif len(nbests[0]) == 1:
                always_keep[key] = True
                alternatives[key] = nbests[1]

        #print("alt=>",alternatives)
        return always_keep, alternatives
Example #12
0
def process_each_prune(tup):
    """
    poolで呼ばれる関数。
    classのなかにかくと、classごとcopyされてeach processに渡される。
    それを防ぐために、外に書く

    1文ずつの処理。(sent,piece,trie)よりも、まとめた方が早い(sent_list, piece,trie)
    """
    (items, piece, trie) = tup

    vsum = 0
    freq = defaultdict(int)
    inverted = defaultdict(int)

    L = Lattice()
    for item in items:
        if item is None:
            continue

        (s, score) = item
        vsum += score
        L.set_sentence(s)
        L.populate_nodes(piece, trie)

        for word in L.Viterbi(ret_piece=True):
            freq[word] += score
            inverted[word] += score
    return (vsum, freq, inverted)
Example #13
0
 def get_data(self, simulation_number=int()):
     data = np.zeros((int(self.y_max-self.y_min), int(self.x_max-self.x_min)))
     cells = Lattice.load(project_id=self.project_id, simulation_number=simulation_number, cells_only=True)
     for cell in cells.values():
         if cell.get_concentration() > self.critical_c:
             if cell.position(1).x_axis > self.x_min and cell.position(1).x_axis < self.x_max:
                 if cell.position(1).y_axis > self.y_min and cell.position(1).y_axis < self.y_max:
                     data[int((cell.index.y_axis-self.y_min)), int((cell.index.x_axis-self.x_min))] = cell.counter
     return data
Example #14
0
    def set_position(self, value):
        refresh_nb = False
        self.next_direction = None

        if self._position != value:
            refresh_nb = True
        self._position = tuple(value)
        if refresh_nb:
            self.neighbours_position = Lattice.get_neighbours(tuple(value))
def avg_pc(runs):
    """
    Given specified number of runs will calculate an average pc value on 50x50 lattice
    """
    pc = []

    for i in range(runs):
        lat10 = Lattice(50)

        while not common_cluster(lat10):
            pos1 = rand_pos(len(lat10.get_lattice()))
            search_neighbours(lat10, pos1)
            if lat10.filled():
                print("No spanning cluster found")
                break

        pc.append(lat10.perc_value())

    return sum(pc) / len(pc)
Example #16
0
def make_stuff_for_part_1():
    ''' Find M vs. T '''
    #===============================================================================
    # Adjustable parameters for the problem 
    J = 1.5
    n = 50 #TODO: make this array-able... in B) we need to compare results for different n.
    n_steps = 20000
    kT_min = 1.0
    kT_max = 6.0
    kT_step = 0.1
    #===============================================================================
    kT_array = np.arange( kT_min, kT_max, kT_step )
    lattice = Lattice( J, n, n_steps, kT_array )
    lattice.run_metropolous_algorithm()
    
    fp = filepath_for_now( local_data_directory )
    print "Save to "
    print fp
    pickle.dump( lattice, open( fp + '.p' , "wb" ) )
Example #17
0
    def save_lattice(self, particles=None, simulation_number=int()):

        lattice = Lattice()
        lattice.update(particles=particles)
        lattice.save(project_id=self.id, simulation_number=simulation_number)
        print('Aktualny stav koncentracie ulozeny. Cislo iteracie = ' +
              str(simulation_number))
Example #18
0
def teststuff():
    for dim in [2, 3, 6]:
        N = 30
        L = 1
        box_depth = 3
        lat = Lattice(N, L, nr_dims=dim)
        lat.setup_boxes(box_depth)

        assert lat.nr_boxes == len(
            lat.Box_list
        ), f"Number of boxes doesn't correspond to length of Box_list, dim={dim}."
        assert len(
            lat.Box_list
        ) == box_depth**dim, f"Number of boxes doesn't corresponds to length of Box_list, dim={dim}"
        for i in range(box_depth**dim):
            box = lat.Box_list[i]
            if (box.corner_coord == np.ones(dim) * (box_depth - 1) // 2).all():
                assert box.a_local == 1, f"Central box doesn't have spacing 1, dim={dim}"
            else:
                assert box.a_local == 2, f"Non-central box doesn't have spacing 2, dim={dim}"
        nr_points = np.sum((N // (box_depth * lat.a_list))**dim, dtype=int)
        assert lat.nr_points == nr_points, f"Number of points {nr_points}, doesn't correspond to reported number of points, {lat.nr_points}, dim={dim}."
Example #19
0
 def encode_one_sent(self, sent):
     #TODO encode_poolがうまくいくなら決して良い
     """
     Arguments:
         sent(str): sentence piece vocを使って分割する文
     Returns:
         tokenize_sent(str): space split tokenize sentence
     """
     L = Lattice()
     L.set_sentence(sent)
     L.populate_nodes(self.SentencePiece.get_pieces(), self.Trie)
     tokenize_sent = " ".join(L.Viterbi(ret_piece=True))
     assert "".join(tokenize_sent.split(" ")) == sent
     return tokenize_sent
def process_each(tup):
    (items,piece,trie) = tup

    L = Lattice()

    ret=[]
    for item in items:
        if item is None:
            continue

        L.set_sentence(item)
        L.populate_nodes(piece, trie)
        ret.append(L.Viterbi(ret_piece=True))

    return ret
Example #21
0
def test_Stencils():
    from Lattice import Lattice
    N = 30
    L = 1
    nr_dims = 2
    box_depth = 3
    lat = Lattice(N, L, nr_dims)
    lat.setup_boxes(box_depth)
    stencils = Stencils(lat)
    for idx in range(lat.nr_points):
        s = stencils.get_stencil(idx)

    for idx in range(lat.nr_points):
        if not lat.IsCloseToEdgeWithHigherSpacing(idx, 1, nr_dims):
            nr_points = len(lat.get_nearby_points(idx, 1))
        else:
            nr_points = len(lat.get_nearby_points(idx, 2))
        if len(s) != nr_points:
            print(len(s), "\n", nr_points, s)
Example #22
0
def process_each_encode(tup):
    """
    tup: tuple(sentence_list, piece, trie)
    
    return: tokenized_sentence_list
    """
    (items, piece, trie) = tup

    ret = []
    L = Lattice()
    for sent in items:
        if sent is None:
            continue
        L.set_sentence(sent)
        L.populate_nodes(piece, trie)
        tokenize_sent = " ".join(L.Viterbi(ret_piece=True))
        ret.append(tokenize_sent)
        assert "".join(tokenize_sent.split(" ")) == sent
    return ret
Example #23
0
def process_each_estep(tup):

    expected = defaultdict(int)
    objective = 0
    num_tokens = 0

    (items, pieces, trie) = tup
    L = Lattice()
    for item in items:
        if item is None:
            continue
        (key, freq) = item
        L.set_sentence(key)
        L.populate_nodes(pieces, trie)
        Z, ret_expected = L.populate_marginal(freq)

        for key, val in ret_expected.items():
            expected[key] += val

        N = len(L.Viterbi())
        num_tokens += N
        objective -= Z
    return (expected, objective, num_tokens)
Example #24
0
    def save_lattice(self,
                     project_id=str(),
                     particles=None,
                     simulation_number=int()):
        info = dict()
        info = json.load(open(project_id, 'r'))

        space = Space(project_id=project_id)
        space.lattice = Lattice()

        if particles:
            lattice = Lattice()
            lattice.update(particles=particles)
            lattice.save(project_id=project_id,
                         simulation_number=simulation_number)

        else:
            i = 0
            while True:
                if os.path.exists('Dataset/Particles/' + project_id + '/' +
                                  str(i)):

                    print(str(i))

                    space.particles = Particles.load(
                        project_id=info['project_id'], simulation_number=i)

                    space.lattice.update(particles=space.particles)

                    space.lattice.save(project_id=info['project_id'],
                                       simulation_number=i)

                    i += 1

                else:
                    break
Example #25
0
#!/usr/bin/python
#coding=utf-8

"""godin.py: 主入口调用脚本
@author: Lizzie
@license: ...
@contact: [email protected]
@version: 0.2
"""

from FormalContext import *
from Lattice import Lattice
import time

if __name__ == '__main__':

    # load随机形式背景
    #fc = load_FC()
    fc = read_FC_file()
    
    b1 = [0.0, 0.3, 0.5, 0.7, 0.9]
    b2 = [0.0, 0.2, 0.4, 0.6, 0.8]
    
    myLattice = Lattice(fc, 0.5, 0.4)
    before = time.time()
    for obj in range(fc.object_num):
        myLattice.addOneObject([obj], fc.oa_value[obj])
    print myLattice
Example #26
0
    def inspect_lattice(self, project_id=str(), critical_concentration=None):

        info = dict()
        info = json.load(open(project_id, 'r'))

        lattice = Lattice()
        lattice.critical_concentration = int(1e5) * critical_concentration

        i = 0
        while True:
            if os.path.exists('Dataset/Lattices/' + project_id + '/' + str(i)):
                print(str(i))

                # loading state
                lattice.cells = Lattice.load(cells_only=True,
                                             project_id=project_id,
                                             simulation_number=i)

                # inspecting loaded state
                lattice.update_critical()

                lattice.sort_critical()
                lattice.update_maximal_distances(dimension=info['dimension'])

                i += 1

            else:
                break

        json.dump(
            lattice.maximal_distances,
            open(
                'Dataset/Maximal_distances/' + info['project_id'] + '/' +
                str(critical_concentration), 'w'))
Example #27
0
import numpy as np
import matplotlib.pyplot as plt
from Lattice import Lattice



if __name__ == "__main__":
    nr_dims = 2
    N = 33
    L = 1
    box_depth = 3

    lat = Lattice(N, L, nr_dims=nr_dims)
    lat.setup_boxes(box_depth)
    hash_list = np.zeros(lat.nr_points, dtype=int)
    idx_list = np.zeros(400, dtype=int)

    # for idx0 in range(lat.nr_points):
    #     hash = lat.get_stencil(idx0)
    #     hash_list[idx0] = hash

    #     idx_list[hash] = idx0


    # plt.hist(idx_list)
    # plt.show()

    for idx in range(lat.nr_points):
        coord = lat.coords[idx]
        plt.scatter(coord[0], coord[1], c="navy")
        for i in range(box_depth+1):
Example #28
0
#!/usr/bin/python
#coding=utf-8
"""godin.py: 主入口调用脚本
@author: Lizzie
@license: ...
@contact: [email protected]
@version: 0.2
"""

from FormalContext import *
from Lattice import Lattice

if __name__ == '__main__':
    # 从文件中读入
    #fc = read_FC_file()

    #fc = FormalContext()
    # 随机生成形式背景
    #fc.randomize(10, 10, 0.3)

    fc = load_FC()

    myLattice = Lattice(fc, 0, 0)
    myLattice.All()
    print myLattice
Example #29
0
#!/usr/bin/python
#coding=utf-8
"""godin.py: 主入口调用脚本
@author: Lizzie
@license: ...
@contact: [email protected]
@version: 0.2
"""

from FormalContext import *
from Lattice import Lattice

if __name__ == '__main__':

    fc1 = FormalContext()
    # 随机生成形式背景
    fc1.randomize(20, 10, 0.3)

    # 从文件中读入
    #fc1 = read_FC_file()

    myLattice = Lattice(fc1.object_list, fc1.attribute_list, 0.5, 0.4)
    for obj in range(fc1.object_num):
        myLattice.addOneObject([obj], fc1.oa_value[obj])
    print myLattice
Example #30
0
@version: 0.2
"""

from FormalContext import *
from Lattice import Lattice

if __name__ == '__main__':

    fc = FormalContext()
    # 随机生成形式背景
    fc.randomize(1000, 20, 0.2)

    # 从文件中读入
    fc1 = read_FC_file()

    myLattice = Lattice(fc.object_list, fc.attribute_list)
    for obj in range(fc.object_num):
        myLattice.addOneObject([obj], fc.oa_value[obj])
    #print myLattice
    #str = myLattice.generate_dot_file()
    #print str
    #try:
    #    to_file = file('/home/shengyan/workspace/godin/new/dot/show', 'wa')
    #    to_file.write('BR-----------\n%s\n\n' % BR)
    #    to_file.write('Lattice-----------\n%s\n\n' % myLattice)
    #    dot_file = file('/home/shengyan/workspace/godin/new/dot/show_godin.dot', 'wa')
    #    dot_file.write('graph G {\n%s}' % str)
    #except IOError, e:
    #    print e
    #finally:
    #    dot_file.close()
class Molecule(list):
    """Molecule --> group of atoms with bonds

    Molecule class is inherited from Python list.  It contains
    a list of Atom instances.  Molecule overloads setitem and setslice
    methods so that the lattice attribute of atoms get set to lattice.

    Data members:
        description   -- molecule description
        lattice -- coordinate system (instance of Lattice)
    """
    def __init__(self, atoms=[], lattice=None, description=None, filename=None):
        """define group of atoms in a specified lattice.

        atoms    -- list of Atom instances to be included in this Molecule.
                    When atoms argument is an existing Molecule instance,
                    the new Molecule is its copy.
        lattice  -- instance of Lattice defining coordinate systems.
        description -- string description of the structure
        filename -- optional, name of a file to load the structure from.
                    Overrides atoms argument when specified.

        Molecule(mol)     create a copy of Molecule instance.

        Because Molecule is inherited from a list it can use list expansions,
        for example:
            oxygen_atoms = [ for a in stru if a.symbol == "O" ]
        """
        self._labels = {}
        self._labels_cached = False
        if isinstance(atoms, Molecule):
            mol = atoms
            # create a shallow copy of all source attributes
            self.__dict__.update(mol.__dict__)
            # make a deep copy of source lattice
            self.lattice = Lattice(mol.lattice)

        self.description = description
        # check if data should be loaded from file
        if filename is not None:
            self.read(filename)
        # otherwise assign list of atoms to self
        else:
            self[:] = atoms 
        # override from lattice argument
        if lattice is None:
            if not self.lattice:    self.lattice = Lattice()
        #elif not isinstance(lattice, Lattice):
        #   emsg = "expected instance of Lattice"
        #    raise TypeError(emsg)
        else:
            self.lattice = lattice
        import time
        self.date = time.ctime()
#    def __str__(self):
#        """simple string representation"""
#        s_lattice = "lattice=%s" % self.lattice
#        s_atoms = '\n'.join([str(a) for a in self])
#        return s_lattice + '\n' + s_atoms

    def getChemicalFormula(self):
        atoms = self
        counts = {}
        for atom in atoms:
            e = atom.symbol
            if e in counts: counts[e]+=1
            else: counts[e]=1
            continue
        elems = counts.keys()
        elems.sort()
        chemFormRaw = ''.join( '%s_%s ' % (e, counts[e]) for e in elems )
        return chemFormRaw.strip()
    
    def getSpecies(self):
        speciesList = []
        for atom in self:
            if atom.symbol in speciesList:
                pass
            else:
                speciesList.append(atom.symbol)
        return speciesList
  
    def addNewAtom(self, *args, **kwargs):
        """Add new Atom instance to the end of this Structure.

        All arguments are forwarded to Atom constructor.

        No return value.
        """
        kwargs['lattice'] = self.lattice
        a = Atom(*args, **kwargs)
        list.append(self, a)
        self._uncache('labels')
        return

    def getLastAtom(self):
        """Return Reference to the last Atom in this structure.
        """
        last_atom = self[-1]
        return last_atom

    def getAtom(self, id):
        """Reference to internal Atom specified by the identifier.

        id  -- zero based index or a string label formatted as
               "%(element)s%(order)i", for example "Na1", "Cl1"

        Return Atom instance.
        Raise ValueError for invalid id.

        See also getLabels().
        """
        try:
            if type(id) is int:
                rv = self[id]
            else:
                if not self._labels_cached or id not in self._labels:
                    self._update_labels()
                rv = self._labels[id]
        except (IndexError, KeyError):
            emsg = "Invalid atom identifier %r." % id
            raise ValueError(emsg)
        return rv

    def getLabels(self):
        """List of unique string labels for all atoms in this structure.

        Return a list.
        """
        elnum = {}
        labels = []
        for a in self:
            elnum[a.symbol] = elnum.get(a.symbol, 0) + 1
            alabel = a.symbol + str(elnum[a.symbol])
            labels.append(alabel)
        return labels
    
    def getPosition(self, siteId):
        """Returns the (fractional) position of a site."""
        return self._siteIds[siteId].getPosition()

    def setPositions(self, positions):
        """Sets the (fractional) positions of the sites in the unit cell."""
        assert(len(positions) == self.getNumSites())
        for isite in range(self.getNumSites()):
            self._sites[isite].setPosition(positions[isite])
              
    def generateDescription(self):
        if self._description==None:
            self._description = self.getChemicalFormula()#+' in '+str(self.lattice)
        return self._description
    def setDescription(self, desc):
        self._description = desc
    description = property(generateDescription, setDescription, "structure description")
    
################################################    
# property methods
################################################
#Notes:
# for now these are done in the style of diffraction
# eventually will be done in Jiao's style with metaclasses

    # fractional xyz
    def _get_xyz(self):
        return [atom.xyz.tolist()  for atom in self[:]]
    def _set_xyz(self, xyzList):
        for atom,xyz in zip(self, xyzList):
            atom.xyz = xyz
    xyz = property(_get_xyz, _set_xyz, doc =
        """fractional coordinates of all atoms""" )  

    # xyz_cartn
    def _get_xyz_cartn(self):
        return [atom.xyz_cartn.tolist() for atom in self[:]]
    def _set_xyz_cartn(self, xyzList):
        for atom,xyz_cartn in zip(self, xyzList):
            atom.xyz_cartn = xyz_cartn
    xyz_cartn = property(_get_xyz_cartn, _set_xyz_cartn, doc =
        """absolute Cartesian coordinates of all atoms""" )   
    
    # symbols
    def _get_symbols(self):
        return [atom.symbol for atom in self[:]]
    def _set_symbols(self, symbolList):
        for atom,symbol in zip(self, symbolList):
            atom.symbol = symbol
    symbols = property(_get_symbols, _set_symbols, doc =
        """symbols of all atoms""" )  
    
    # forces
    def _get_forces(self):
        return [atom.force for atom in self]
    def _set_forces(self, forceList):
        for atom,force in zip(self, forceList):
            atom.force = force
    forces = property(_get_forces, _set_forces, doc =
        """forces on all atoms""" )   
    
    # charges
    def _get_charges(self):
        return [atom.charge for atom in self]
    def _set_charges(self, chargeList):
        for atom,charge in zip(self, chargeList):
            atom.charge = charge
    charges = property(_get_charges, _set_charges, doc =
        """charges on all atoms in electron units""" )   
    
################################################################################################    
# geometry and symmetry methods--these should be farmed out to Geometry class which does all this--see vimm
################################################################################################ 

    def distance(self, id0, id1):
        """Distance between 2 atoms, no periodic boundary conditions.

        id0 -- zero based index of the first atom or a string label
               such as "Na1"
        id1 -- zero based index or string label of the second atom.

        Return float.
        Raise ValueError for invalid arguments.
        """
        a0 = self.getAtom(id0)
        a1 = self.getAtom(id1)
        return self.lattice.dist(a0.xyz, a1.xyz)

    def angle(self, a0, a1, a2):
        """angle at atom a1 in degrees"""
        u10 = a0.xyz - a1.xyz
        u12 = a2.xyz - a1.xyz
        return self.lattice.angle(u10, u12)
  
    def computeDistances(self, maxdist=30, latticeRange=[2,2,2]):
        """ unitcell.computeDistances(self, [nx,ny,nz]):
        builds up a Big multiple dictionary, namely
        self.distances[atom1][atom2][(DX,DY,DZ)]
        (DX,DY,DZ) are integer numbers specifying the cell containing atom2,
        relatively to atom1.
        DX,DY,DZ run from -nx to nx, -ny to ny, -nz to nz, respectively."""
        distances = {}
        idlist = self.getLabels()
        #idlist = self.getIds()
        for iA in range(0, len(idlist)):
            idA = idlist[iA]
            distances[idA] = {}
            for iB in range(0, len(idlist)):
                idB = idlist[iB]
                distances[idA][idB]={}
                for tx in range(-latticeRange[0],latticeRange[0]+1):
                    for ty in range(-latticeRange[1],latticeRange[1]+1):
                        for tz in range(-latticeRange[2],latticeRange[2]+1):
                            posA = self.getCartesianPosition(idA)
                            posB = self.getCartesianPosition(idB) + numpy.dot([tx,ty,tz], self._lattice)
                            dist = numpy.sqrt(numpy.sum( (posB-posA) * (posB-posA) ))
                            if(dist<maxdist):
                                distances[idA][idB][(tx,ty,tz)] = dist
        self._distances = distances
        return distances

###########################
# IO
###########################
    def read(self, filename, format='auto'):
        """Load structure from a file, any original data may become lost.

        filename -- file to be loaded
        format   -- all structure formats are defined in Parsers submodule,
                    when format == 'auto' all Parsers are tried one by one

        Return instance of data Parser used to process file.  This
        can be inspected for information related to particular format.
        """
        from Parsers import getParser
        p = getParser(format)
        new_structure = p.parseFile(filename)
        # reinitialize data after successful parsing
        # avoid calling __init__ from a derived class
        Molecule.__init__(self)
        if new_structure is not None:
            self.__dict__.update(new_structure.__dict__)
            self[:] = new_structure
        if not self.description:
            self.generateDescription()
#            import os.path
#            tailname = os.path.basename(filename)
#            tailbase = os.path.splitext(tailname)[0]
#            self.description = tailbase
        return p

    def readStr(self, s, format='auto'):
        """Load structure from a string, any original data become lost.

        s        -- string with structure definition
        format   -- all structure formats are defined in Parsers submodule,
                    when format == 'auto' all Parsers are tried one by one

        Return instance of data Parser used to process input string.  This
        can be inspected for information related to particular format.
        """
        from Parsers import getParser
        p = getParser(format)
        new_structure = p.parse(s)
        # reinitialize data after successful parsing
        # avoid calling __init__ from a derived class
        Molecule.__init__(self)
        if new_structure is not None:
            self.__dict__.update(new_structure.__dict__)
            self[:] = new_structure
        return p

    def write(self, filename, format):
        """Save molecule to file in the specified format

        No return value.

        Note: available structure formats can be obtained by:
            from Parsers import formats
        """
        from Parsers import getParser
        p = getParser(format)
        p.filename = filename
        s = p.tostring(self)
        f = open(filename, 'wb')
        f.write(s)
        f.close()
        return

    def writeStr(self, format, **kwds):
        """return string representation of the structure in specified format

        Note: available structure formats can be obtained by:
            from Parsers import formats
        """
        from Parsers import getParser
        p = getParser(format)
        s = p.tostring(self,**kwds)
        return s

    ##############################################################################
    # overloaded list methods
    ##############################################################################

    def append(self, a, copy=True):
        """Append atom to a structure and update its lattice attribute.

        a    -- instance of Atom
        copy -- flag for appending a copy of a.
                When False, append a and update a.owner.

        No return value.
        """
        self._uncache('labels')
        adup = copy and Atom(a) or a
        adup.lattice = self.lattice
        list.append(self, adup)
        return

    def insert(self, idx, a, copy=True):
        """Insert atom a before position idx in this Structure.

        idx  -- position in atom list
        a    -- instance of Atom
        copy -- flag for inserting a copy of a.
                When False, append a and update a.lattice.

        No return value.
        """
        self._uncache('labels')
        adup = copy and Atom(a) or a
        adup.lattice = self.lattice
        list.insert(self, idx, adup)
        return

    def extend(self, atoms, copy=True):
        """Extend Structure by appending copies from a list of atoms.

        atoms -- list of Atom instances
        copy  -- flag for extending with copies of Atom instances.
                 When False extend with atoms and update their lattice
                 attributes.

        No return value.
        """
        self._uncache('labels')
        if copy:    adups = [Atom(a) for a in atoms]
        else:       adups = atoms
        for a in adups: a.lattice = self.lattice
        list.extend(self, adups)
        return

    def __setitem__(self, idx, a, copy=True):
        """Set idx-th atom to a.

        idx  -- index of atom in this Structure
        a    -- instance of Atom
        copy -- flag for setting to a copy of a.
                When False, set to a and update a.lattice.

        No return value.
        """
        self._uncache('labels')
        adup = copy and Atom(a) or a
        adup.lattice = self.lattice
        list.__setitem__(self, idx, adup)
        return

    def __setslice__(self, lo, hi, atoms, copy=False):
        """Set Structure slice from lo to hi-1 to the sequence of atoms.

        lo    -- low index for the slice
        hi    -- high index of the slice
        atoms -- sequence of Atom instances
        copy  -- flag for using copies of Atom instances.  When False, set
                 to existing instances and update their lattice attributes.

        No return value.
        """
        self._uncache('labels')
        if copy:    
            adups = [Atom(a) for a in atoms]
        else:       
            adups = atoms
        for a in adups: a.lattice = self.lattice
        list.__setslice__(self, lo, hi, adups)

    ####################################################################
    # property handlers
    ####################################################################

    # lattice
    def _get_lattice(self):
        if not hasattr(self, '_lattice'):
            self._lattice = Lattice()
        return self._lattice
    def _set_lattice(self, value):
        for a in self:  a.lattice = value
        self._lattice = value
        return
    lattice = property(_get_lattice, _set_lattice, doc =
        "Coordinate system for this Structure.")

    ####################################################################
    # protected methods
    ####################################################################

    def _update_labels(self):
        """Update the _labels dictionary of unique string labels of atoms.

        No return value.
        """
        kv = zip(self.getLabels(), self[:])
        self._labels = dict(kv)
        self._labels_cached = True

    def _uncache(self, *args):
        """Reset cached flag for a list of internal attributes.

        *args -- list of strings, currently supported are "labels"

        No return value.
        Raise AttributeError for any invalid args.
        """
        for a in args:
            attrname = "_" + a + "_cached"
            setattr(self, attrname, False)
Example #32
0
    def visualise(self,
                  heatmap=False,
                  max_distance=False,
                  critical_concentration=float(),
                  simulation_number=None):

        if heatmap:
            x_max = 60
            x_min = -60
            y_max = 60
            y_min = -60

            y_size = int((y_max - y_min)) + 1
            x_size = int((x_max - x_min)) + 1
            data = np.zeros((y_size, x_size))
            plot_data = []
            for i in range(10, 700, 50):
                lattice = Lattice.load(project_id=self.id,
                                       sub_id=self.sub_id,
                                       simulation_number=i,
                                       implementation=True)

                for cell in lattice.cells.values():
                    if cell.get_concentration() > critical_concentration:
                        if cell.position(1).x_axis > x_min and cell.position(
                                1).x_axis < x_max:
                            if cell.position(
                                    1).y_axis > y_min and cell.position(
                                        1).y_axis < y_max:
                                data[int((cell.index.y_axis - y_min)),
                                     int((cell.index.x_axis -
                                          x_min))] = cell.counter

                graph_x_axis = list(
                    range(int(x_min * lattice.density),
                          int(x_max * lattice.density)))
                graph_y_axis = list(
                    range(int(y_min * lattice.density),
                          int(y_max * lattice.density)))
                trace = go.Heatmap(z=data, x=graph_x_axis, y=graph_y_axis)
                plot_data.append(trace)

            fig = tools.make_subplots(rows=4, cols=4)
            for i in range(len(plot_data)):
                print(plot_data[i]['z'])
                # fig.append_trace(plot_data[i], i//4+1, i%4+1)
            # plotly.offline.plot(fig, filename='H' + str(simulation_number) + '.html',
            #                     image_filename='2D-h' + str(simulation_number) ,
            #                     image_width=800, image_height=800, image='png', auto_open=True)
            # Visualiser.concentration_heatmap(lattice=lattice, simulation_number=simulation_number, critical_concentration=critical_concentration)

        if max_distance:
            maximal_distances = json.load(
                open(
                    str(self.id) + self.sub_id + 'Maximal_distances/' +
                    str(critical_concentration) + 'n2', 'r'))
            print(maximal_distances)
            trace = go.Scatter(
                x=np.arange(len(maximal_distances)),
                y=maximal_distances,
                mode='markers',
            )
            data = [trace]
            layout = go.Layout(
                title='',
                xaxis=dict(title='Počet iteračných krokov',
                           titlefont=dict(family='Courier New, monospace',
                                          size=14,
                                          color='#7f7f7f')),
                yaxis=dict(title='Polomer oblasti s kritickou koncentráciou',
                           titlefont=dict(family='Courier New, monospace',
                                          size=14,
                                          color='#7f7f7f')))
            fig = go.Figure(data=data, layout=layout)
            plotly.offline.plot(fig,
                                filename='impl2-2D-1e5-R(n)' +
                                str(critical_concentration) + 'n2' + '.html')
Example #33
0
class Structure(list):
    """Structure --> group of atoms

    Structure class is inherited from Python list.  It contains
    a list of Atom instances.  Structure overloads setitem and setslice
    methods so that the lattice attribute of atoms get set to lattice.

    Data members:
        description   -- structure description
        lattice -- coordinate system (instance of Lattice)
    """
    def __init__(self,
                 atoms=[],
                 lattice=None,
                 sgid=1,
                 description=None,
                 filename=None,
                 primitive_unitcell=None):
        """define group of atoms in a specified lattice.

        atoms    -- list of Atom instances to be included in this Structure.
                    When atoms argument is an existing Structure instance,
                    the new Structure is its copy.
        lattice  -- instance of Lattice defining coordinate systems, property.
        sgid     -- space group symbol, either short_name or pdb_name,
                    whatever it means in mmlib.  Can be also an integer.
        description -- string description of the structure
        filename -- optional, name of a file to load the structure from.
                    Overrides atoms argument when specified.

        Structure(stru)     create a copy of Structure instance stru.

        Because Structure is inherited from a list it can use list expansions,
        for example:
            oxygen_atoms = [ for a in stru if a.symbol == "O" ]
            oxygen_stru = Structure(oxygen_atoms, lattice=stru.lattice)
        """

        self._labels = {}
        self._labels_cached = False
        if isinstance(atoms, Structure):
            stru = atoms
            # create a shallow copy of all source attributes
            self.__dict__.update(stru.__dict__)
            # make a deep copy of source lattice
            self.lattice = Lattice(stru.lattice)

        self.description = description
        self.sg = sgid
        # check if data should be loaded from file
        if filename is not None:
            self.read(filename)
        # otherwise assign list of atoms to self
        else:
            self[:] = atoms

        # override from lattice argument
        if lattice is None:
            if not self.lattice: self.lattice = Lattice()
        #elif not isinstance(lattice, Lattice):
        #   emsg = "expected instance of Lattice"
        #    raise TypeError(emsg)
        else:
            self.lattice = lattice

        self._primitive_unitcell = primitive_unitcell
        import time
        self.date = time.ctime()

    def __str__(self):
        """simple string representation"""
        s_lattice = "lattice=%s" % self.lattice
        s_atoms = '\n'.join([str(a) for a in self])
        return s_lattice + '\n' + s_atoms

    def getChemicalFormula(self):
        atoms = self
        counts = {}
        for atom in atoms:
            e = atom.symbol
            if e in counts: counts[e] += 1
            else: counts[e] = 1
            continue
        elems = counts.keys()
        elems.sort()
        chemFormRaw = ''.join('%s_%s ' % (e, counts[e]) for e in elems)
        return chemFormRaw.strip()

    def getSpecies(self):
        speciesList = []
        for atom in self:
            if atom.symbol in speciesList:
                pass
            else:
                speciesList.append(atom.symbol)
        return speciesList

    # these properties are actually independent of space group and so should
    # be moved to lattice perhaps
    def _getCrystalSystem(self):
        return self.sg.crystal_system

    crystal_system = property(_getCrystalSystem)

    def _getCentering(self):
        return self.sg.pdb_name[0]

    centering = property(_getCentering)

    _centerings = {
        'P': 'primitive',
        'C': 'single face centered',
        'A': 'single face centered',
        'H': 'primitive',
        'R': 'primitive',
        'I': 'body centered',
        'F': 'face centered',
    }

    def _getCenteringDescription(self):
        return self._centerings[self.centering]

    centering_description = property(_getCenteringDescription)

    def _getBravaisType(self):
        centeringAndSystem2bravais = {
            ('P', 'CUBIC'): 'simple cubic',
            ('F', 'CUBIC'): 'face centered cubic',
            ('I', 'CUBIC'): 'body centered cubic',
            ('P', 'HEXAGONAL'): 'simple hexagonal',
            ('P', 'TRIGONAL'): 'simple trigonal',
            ('P', 'TETRAGONAL'): 'simple tetragonal',
            ('R', 'TETRAGONAL'): 'simple tetragonal',
            ('I', 'TETRAGONAL'): 'body centered tetragonal',
            ('P', 'ORTHORHOMBIC'): 'simple orthorhombic',
            ('C', 'ORTHORHOMBIC'): 'base centered orthorhombic',
            ('A', 'ORTHORHOMBIC'): 'base centered orthorhombic',
            ('F', 'ORTHORHOMBIC'): 'face centered orthorhombic',
            ('I', 'ORTHORHOMBIC'): 'body centered orthorhombic',
            ('P', 'ORTHORHOMBIC'): 'simple monoclinic',
            ('P', 'MONOCLINIC'): 'base centered monoclinic',
            ('P', 'TRICLINIC'): 'triclinic'
        }
        return centeringAndSystem2bravais[(self.sg.short_name[0],
                                           self.sg.crystal_system)]

    bravais_type = property(_getBravaisType)

    def _getStrukturberichtDesignation(self):
        finder = self._getStrukturberichtDesignationFinder()
        return finder.find(self)

    StrukturberichtDesignation = property(_getStrukturberichtDesignation)

    def _getStrukturberichtDesignationFinder(self):
        k = '_StrukturberichtDesignationFinder'
        if hasattr(self, k): return getattr(self, k)
        from StrukturberichtDesignationFinder import StrukturberichtDesignationFinder
        r = StrukturberichtDesignationFinder()
        setattr(self, k, r)
        return r

    def _get_primitive_unitcell(self):
        t = self._primitive_unitcell
        if t is None:
            #t = self._primitive_unitcell = self._lattice.getPrimitiveLattice(self.sg)
            t = self._primitive_unitcell = self._create_primitive_unitcell()
        return t

    def _set_primitive_unitcell(self, p):
        self._primitive_unitcell = p
        return p

    primitive_unitcell = property(_get_primitive_unitcell,
                                  _set_primitive_unitcell)

    def _create_primitive_unitcell(self):
        # the ctor
        from UnitCell import UnitCell
        base = self._lattice.getPrimitiveLattice(self.sg)
        base = numpy.array(base)

        puc = UnitCell(base=base)
        for atom in self:
            if puc.hasAtom(atom): continue
            puc.addAtom(atom)
            continue
        return puc

        # check symmetry
        sg = self.sg
        verdict, atompos, symop = self.symConsistent()
        if not verdict:
            raise RuntimeError, \
                  "inconsistent structure: atom position: %s, sym operation %s" % (
                atompos, symop)

        #
        if sg.number == 225:
            # face centered--below is only for cubic...need to generalize
            a = self.lattice.a
            base = numpy.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]]) * 0.5 * a

        elif sg.number == 229:
            # body centered--below is only for cubic...need to generalize
            a = self.lattice.a
            base = numpy.array([[1, 0, 0], [0, 1, 0], [0.5, 0.5, 0.5]]) * a

        elif sg.short_name[0] == 'P':
            # primitive
            base = self.lattice

        else:
            # not implemented
            return

    def addNewAtom(self, *args, **kwargs):
        """Add new Atom instance to the end of this Structure.

        All arguments are forwarded to Atom constructor.
        """
        kwargs['lattice'] = self.lattice
        a = Atom(*args, **kwargs)
        list.append(self, a)
        self._uncache('labels')

    def getLastAtom(self):
        """Return Reference to the last Atom in this structure.
        """
        last_atom = self[-1]
        return last_atom

    def getAtom(self, id):
        """Reference to internal Atom specified by the identifier.

        id  -- zero based index or a string label formatted as
               "%(element)s%(order)i", for example "Na1", "Cl1"

        Return Atom instance.
        Raise ValueError for invalid id.

        See also getLabels().
        """
        try:
            if type(id) is int:
                rv = self[id]
            else:
                if not self._labels_cached or id not in self._labels:
                    self._update_labels()
                rv = self._labels[id]
        except (IndexError, KeyError):
            emsg = "Invalid atom identifier %r." % id
            raise ValueError(emsg)
        return rv

    def getLabels(self):
        """List of unique string labels for all atoms in this structure.

        Return a list.
        """
        elnum = {}
        labels = []
        for a in self:
            elnum[a.symbol] = elnum.get(a.symbol, 0) + 1
            alabel = a.symbol + str(elnum[a.symbol])
            labels.append(alabel)
        return labels

    #untested--from UnitCell
    def bringFractionalPositionIntoCell(self, fracpos):
        """Brings a fractional position (x,y,z) 'into' the unit cell,
        i.e.: (x,y,z)->(x',y',z') such that x,y,z in [0,1( """
        pos = numpy.array(fracpos)
        assert (len(pos) == 3)
        for i in range(3):
            if pos[i] < 0:
                while pos[i] < 0:
                    pos[i] += 1
            if pos[i] >= 1:
                while pos[i] >= 1:
                    pos[i] -= 1
        return pos

    #untested--from UnitCell
    def cartesianPositionInLattice(self, siteId, latticeVector):
        """Returns the Cartesian position vector from the origin
        ( fractional coordinates [0,0,0] in unit cell [0,0,0]),
        for a Site corresponding to 'siteId',
        in the unit cell corresponding to latticeVector
        (triplets of coordinates in terms of cellvectors), 
        defining which unit cell in the lattice.
        """
        try:
            posincell = self.getCartesianPosition(siteId)
        except KeyError:
            raise KeyError, 'Invalid site Id'
        pos = numpy.array(posincell) + numpy.dot(latticeVector, self._lattice)
        return pos

    def getPosition(self, siteId):
        """Returns the (fractional) position of a site."""
        return self._siteIds[siteId].getPosition()

    def setPositions(self, positions):
        """Sets the (fractional) positions of the sites in the unit cell."""
        assert (len(positions) == self.getNumSites())
        for isite in range(self.getNumSites()):
            self._sites[isite].setPosition(positions[isite])

    def getCartesianPosition(self, siteId):
        """Returns the cartesian position of a site."""
        return self.fractionalToCartesian(self._siteIds[siteId].getPosition())

    def fractionalToCartesian(self, fracpos):
        """Converts a coordinate from fractional to cartesian."""
        return (fracpos * self._lattice).sum(0)  # should be double-checked

    def cartesianToFractional(self, cartpos):
        """Converts a coordinate from cartesian to fractional."""
        return (cartpos * numpy.linalg.inv(self._lattice)).sum(
            0)  # should be double-checked

    def generateDescription(self):
        if self._description == None:
            self._description = self.getChemicalFormula(
            )  #+' in '+str(self.lattice)
        return self._description

    def setDescription(self, desc):
        self._description = desc

    description = property(generateDescription, setDescription,
                           "structure description")

    ################################################
    # property methods
    ################################################
    #Notes:
    # for now these are done in the style of diffraction
    # eventually will be done in Jiao's style with metaclasses

    # fractional xyz
    def _get_xyz(self):
        return [atom.xyz.tolist() for atom in self[:]]

    def _set_xyz(self, xyzList):
        for atom, xyz in zip(self, xyzList):
            atom.xyz = xyz

    xyz = property(_get_xyz,
                   _set_xyz,
                   doc="""fractional coordinates of all atoms""")

    # xyz_cartn
    def _get_xyz_cartn(self):
        return [atom.xyz_cartn.tolist() for atom in self[:]]

    def _set_xyz_cartn(self, xyzList):
        for atom, xyz_cartn in zip(self, xyzList):
            atom.xyz_cartn = xyz_cartn

    xyz_cartn = property(_get_xyz_cartn,
                         _set_xyz_cartn,
                         doc="""absolute Cartesian coordinates of all atoms""")

    # symbols
    def _get_symbols(self):
        return [atom.symbol for atom in self[:]]

    def _set_symbols(self, symbolList):
        for atom, symbol in zip(self, symbolList):
            atom.symbol = symbol

    symbols = property(_get_symbols,
                       _set_symbols,
                       doc="""symbols of all atoms""")

    # forces
    def _get_forces(self):
        return [atom.force for atom in self]

    def _set_forces(self, forceList):
        for atom, force in zip(self, forceList):
            atom.force = force

    forces = property(_get_forces, _set_forces, doc="""forces on all atoms""")

    # charges
    def _get_charges(self):
        return [atom.charge for atom in self]

    def _set_charges(self, chargeList):
        for atom, charge in zip(self, chargeList):
            atom.charge = charge

    charges = property(_get_charges,
                       _set_charges,
                       doc="""charges on all atoms in electron units""")

    ################################################################################################
    # geometry and symmetry methods--these should be farmed out to Geometry class which does all this--see vimm
    ################################################################################################

    def distance(self, id0, id1):
        """Distance between 2 atoms, no periodic boundary conditions.

        id0 -- zero based index of the first atom or a string label
               such as "Na1"
        id1 -- zero based index or string label of the second atom.

        Return float.
        Raise ValueError for invalid arguments.
        """
        a0 = self.getAtom(id0)
        a1 = self.getAtom(id1)
        return self.lattice.dist(a0.xyz, a1.xyz)

    def angle(self, a0, a1, a2):
        """angle at atom a1 in degrees"""
        u10 = a0.xyz - a1.xyz
        u12 = a2.xyz - a1.xyz
        return self.lattice.angle(u10, u12)

    def symConsistent(self, decimal=7):
        from numpy.testing import assert_array_almost_equal
        verdict = True
        nonCompliantAtomPosition = None
        nonCompliantSymOp = None

        def arrayInList(trialArray, arrayList):
            matchesQ = False
            for certainArray in arrayList:
                if (numpy.round(trialArray - certainArray,
                                decimal) == 0).all():
                    matchesQ = True
            return matchesQ

        sg = self.sg
        # as long as the structure is given a lattice, each atom.xyz should be in fractional coords
        atomPositions = [atom.xyz for atom in self[:]]
        for atomPosition in atomPositions:
            for symop in sg.symop_list:
                rawPosition = numpy.dot(symop.R, atomPosition) + symop.t
                fracPos, intPos = numpy.modf(numpy.round(rawPosition, decimal))
                newPosition = numpy.mod(fracPos, 1)
                if not arrayInList(newPosition, atomPositions):
                    verdict = False
                    nonCompliantAtomPosition = atomPosition
                    nonCompliantSymOp = symop
                    break
        return verdict, nonCompliantAtomPosition, nonCompliantSymOp

    def placeInLattice(self, new_lattice):
        """place structure into new_lattice coordinate system

        sets lattice to new_lattice and recalculate fractional coordinates
        of all atoms so their absolute positions remain the same

        return self
        """
        Tx = numpy.dot(self.lattice.base, new_lattice.recbase)
        Tu = numpy.dot(self.lattice.normbase, new_lattice.recnormbase)
        for a in self:
            a.xyz = list(numpy.dot(a.xyz, Tx))
        self.lattice = new_lattice
        return self

    def computeDistances(self, maxdist=30, latticeRange=[2, 2, 2]):
        """ unitcell.computeDistances(self, [nx,ny,nz]):
        builds up a Big multiple dictionary, namely
        self.distances[atom1][atom2][(DX,DY,DZ)]
        (DX,DY,DZ) are integer numbers specifying the cell containing atom2,
        relatively to atom1.
        DX,DY,DZ run from -nx to nx, -ny to ny, -nz to nz, respectively."""
        distances = {}
        idlist = self.getLabels()
        #idlist = self.getIds()
        for iA in range(0, len(idlist)):
            idA = idlist[iA]
            distances[idA] = {}
            for iB in range(0, len(idlist)):
                idB = idlist[iB]
                distances[idA][idB] = {}
                for tx in range(-latticeRange[0], latticeRange[0] + 1):
                    for ty in range(-latticeRange[1], latticeRange[1] + 1):
                        for tz in range(-latticeRange[2], latticeRange[2] + 1):
                            posA = self.getCartesianPosition(idA)
                            posB = self.getCartesianPosition(idB) + numpy.dot(
                                [tx, ty, tz], self._lattice)
                            dist = numpy.sqrt(
                                numpy.sum((posB - posA) * (posB - posA)))
                            if (dist < maxdist):
                                distances[idA][idB][(tx, ty, tz)] = dist
        self._distances = distances
        return distances

##     def findTetrahedra(self, list4ids, latticeVectors=[(0,0,0),(0,0,0),(0,0,0),(0,0,0)]):
##         """Searches the tetrahedra that equivalent by symmetry to the reference tetrahedron
##         defined by the list4ids (4 Ids) and the cells indices where vertices lie."""
##         # from OpenPhonon:
##         # OP_cella. FindTetragons(self, Latoms, CellsCoo=[(0,0,0),(0,0,0),(0,0,0),(0,0,0)])
##         # This is the key routine to find good candidates to symmetry group.
##         # Latoms is a list of the kind [  (Aa,kA) ,(Bb,kB)....]
##         # ( i.e. couples formed by atom-name and position in the position list.
##         # Latoms must be formed of four  atoms defining a non-degenerate tetraedron.
##         # A check is permormed on the non-degeneracy.
##         # The funtions finds all the possible equivalent tetraedrons (which have the same
##         # set of distances, and the same atom kinds)
##         # The function return the list of all these tetraedrons

##         if type(list4ids) is not type([]):
##             raise ValueError, 'list4ids should be a list of 4 site Ids.'
##         if len(list4ids) != len(latticeVectors):
##             raise ValueError, 'There should be as many site Ids as lattice vectors.'
##         if len(list4ids) != 4:
##             raise ValueError, 'Need 4 sites to define a tetrahedron.'

##         tetraVertices = [self.cartesianPositionInLattice(id,lattvec)
##                          for (id,lattvec) in zip(list4ids,latticeVectors)]
##         # compute vectors for edges of tetrahedron from first point:
##         edgeVectors = tetraVertices[1:4] - tetraVertices[0]

##         # check for non-degeneracy:
##         det = la.det(edgeVectors)
##         if(abs(det) < 1e-6):
##             raise ValueError, 'determinant smaller than 1e-6: degenerate reference tetrahedron.'

###########################
# IO
###########################

    def read(self, filename, format='auto'):
        """Load structure from a file, any original data may become lost.

        filename -- file to be loaded
        format   -- all structure formats are defined in Parsers submodule,
                    when format == 'auto' all Parsers are tried one by one

        Return instance of data Parser used to process file.  This
        can be inspected for information related to particular format.
        """
        from Parsers import getParser
        p = getParser(format)
        new_structure = p.parseFile(filename)
        # reinitialize data after successful parsing
        # avoid calling __init__ from a derived class
        Structure.__init__(self)
        if new_structure is not None:
            self.__dict__.update(new_structure.__dict__)
            self[:] = new_structure
        if not self.description:
            self.generateDescription()
#            import os.path
#            tailname = os.path.basename(filename)
#            tailbase = os.path.splitext(tailname)[0]
#            self.description = tailbase
        return p

    def readStr(self, s, format='auto'):
        """Load structure from a string, any original data become lost.

        s        -- string with structure definition
        format   -- all structure formats are defined in Parsers submodule,
                    when format == 'auto' all Parsers are tried one by one

        Return instance of data Parser used to process input string.  This
        can be inspected for information related to particular format.
        """
        from Parsers import getParser
        p = getParser(format)
        new_structure = p.parse(s)
        # reinitialize data after successful parsing
        # avoid calling __init__ from a derived class
        Structure.__init__(self)
        if new_structure is not None:
            self.__dict__.update(new_structure.__dict__)
            self[:] = new_structure
        return p

    def write(self, filename, format, **kwds):
        """Save structure to file in the specified format

        No return value.

        Note: available structure formats can be obtained by:
            from Parsers import formats
        """
        from Parsers import getParser
        p = getParser(format)
        p.filename = filename
        s = p.tostring(self, **kwds)
        f = open(filename, 'wb')
        f.write(s)
        f.close()
        return

    def writeStr(self, format, **kwds):
        """return string representation of the structure in specified format

        Note: available structure formats can be obtained by:
            from Parsers import formats
        """
        from Parsers import getParser
        p = getParser(format)
        s = p.tostring(self, **kwds)
        return s

    ##############################################################################
    # overloaded list methods
    ##############################################################################

    def append(self, a, copy=True):
        """Append atom to a structure and update its lattice attribute.

        a    -- instance of Atom
        copy -- flag for appending a copy of a.
                When False, append a and update a.owner.

        No return value.
        """
        self._uncache('labels')
        adup = copy and Atom(a) or a
        adup.lattice = self.lattice
        list.append(self, adup)
        return

    def insert(self, idx, a, copy=True):
        """Insert atom a before position idx in this Structure.

        idx  -- position in atom list
        a    -- instance of Atom
        copy -- flag for inserting a copy of a.
                When False, append a and update a.lattice.

        No return value.
        """
        self._uncache('labels')
        adup = copy and Atom(a) or a
        adup.lattice = self.lattice
        list.insert(self, idx, adup)
        return

    def extend(self, atoms, copy=True):
        """Extend Structure by appending copies from a list of atoms.

        atoms -- list of Atom instances
        copy  -- flag for extending with copies of Atom instances.
                 When False extend with atoms and update their lattice
                 attributes.

        No return value.
        """
        self._uncache('labels')
        if copy: adups = [Atom(a) for a in atoms]
        else: adups = atoms
        for a in adups:
            a.lattice = self.lattice
        list.extend(self, adups)
        return

    def __setitem__(self, idx, a, copy=True):
        """Set idx-th atom to a.

        idx  -- index of atom in this Structure
        a    -- instance of Atom
        copy -- flag for setting to a copy of a.
                When False, set to a and update a.lattice.

        No return value.
        """
        self._uncache('labels')
        adup = copy and Atom(a) or a
        adup.lattice = self.lattice
        list.__setitem__(self, idx, adup)
        return

    def __setslice__(self, lo, hi, atoms, copy=False):
        """Set Structure slice from lo to hi-1 to the sequence of atoms.

        lo    -- low index for the slice
        hi    -- high index of the slice
        atoms -- sequence of Atom instances
        copy  -- flag for using copies of Atom instances.  When False, set
                 to existing instances and update their lattice attributes.

        No return value.
        """
        self._uncache('labels')
        if copy:
            adups = [Atom(a) for a in atoms]
        else:
            adups = atoms
        for a in adups:
            a.lattice = self.lattice
        list.__setslice__(self, lo, hi, adups)

    ####################################################################
    # property handlers
    ####################################################################

    # lattice

    def _get_lattice(self):
        if not hasattr(self, '_lattice'):
            self._lattice = Lattice()
        return self._lattice

    def _set_lattice(self, value):
        for a in self:
            a.lattice = value
        self._lattice = value
        return

    lattice = property(_get_lattice,
                       _set_lattice,
                       doc="Coordinate system for this Structure.")

    # space group

    def _get_spaceGroup(self):
        if not self._sg:
            from matter.SpaceGroups import GetSpaceGroup
            self._sg = GetSpaceGroup(self._sgid)
        return self._sg

    def _set_spaceGroup(self, item):
        from matter.SpaceGroups import SpaceGroup
        if isinstance(item, SpaceGroup):
            self._sg = item
            self._sgid = item.number
        else:
            from matter.SpaceGroups import GetSpaceGroup
            self._sg = GetSpaceGroup(item)
            self._sgid = item

    sg = property(_get_spaceGroup,
                  _set_spaceGroup,
                  doc="""Space group for this structure.  This can be set 
        by instantiating with a new spacegroup class or with a space group id.
        One can also use the explicit setter.""")

    ####################################################################
    # additional setter
    ####################################################################

    def setSg(self, sgid):
        self.sg = sgid
        return

    ####################################################################
    # protected methods
    ####################################################################

    def _update_labels(self):
        """Update the _labels dictionary of unique string labels of atoms.

        No return value.
        """
        kv = zip(self.getLabels(), self[:])
        self._labels = dict(kv)
        self._labels_cached = True
        return

    def _uncache(self, *args):
        """Reset cached flag for a list of internal attributes.

        *args -- list of strings, currently supported are "labels"

        No return value.
        Raise AttributeError for any invalid args.
        """
        for a in args:
            attrname = "_" + a + "_cached"
            setattr(self, attrname, False)
        return
Example #34
0
class Structure(list):
    """Structure --> group of atoms

    Structure class is inherited from Python list.  It contains
    a list of Atom instances.  Structure overloads setitem and setslice
    methods so that the lattice attribute of atoms get set to lattice.

    Data members:
        description   -- structure description
        lattice -- coordinate system (instance of Lattice)
    """
    

    def __init__(self, atoms=[], lattice=None, sgid=1, description=None, filename=None,
                 primitive_unitcell=None
                 ):
        """define group of atoms in a specified lattice.

        atoms    -- list of Atom instances to be included in this Structure.
                    When atoms argument is an existing Structure instance,
                    the new Structure is its copy.
        lattice  -- instance of Lattice defining coordinate systems, property.
        sgid     -- space group symbol, either short_name or pdb_name,
                    whatever it means in mmlib.  Can be also an integer.
        description -- string description of the structure
        filename -- optional, name of a file to load the structure from.
                    Overrides atoms argument when specified.

        Structure(stru)     create a copy of Structure instance stru.

        Because Structure is inherited from a list it can use list expansions,
        for example:
            oxygen_atoms = [ for a in stru if a.symbol == "O" ]
            oxygen_stru = Structure(oxygen_atoms, lattice=stru.lattice)
        """

        self._labels = {}
        self._labels_cached = False
        if isinstance(atoms, Structure):
            stru = atoms
            # create a shallow copy of all source attributes
            self.__dict__.update(stru.__dict__)
            # make a deep copy of source lattice
            self.lattice = Lattice(stru.lattice)

        self.description = description
        self.sg = sgid
        # check if data should be loaded from file
        if filename is not None:
            self.read(filename)
        # otherwise assign list of atoms to self
        else:
            self[:] = atoms
            
        # override from lattice argument
        if lattice is None:
            if not self.lattice:    self.lattice = Lattice()
        #elif not isinstance(lattice, Lattice):
        #   emsg = "expected instance of Lattice"
        #    raise TypeError(emsg)
        else:
            self.lattice = lattice


        self._primitive_unitcell = primitive_unitcell
        import time
        self.date = time.ctime()


    def __str__(self):
        """simple string representation"""
        s_lattice = "lattice=%s" % self.lattice
        s_atoms = '\n'.join([str(a) for a in self])
        return s_lattice + '\n' + s_atoms


    def getChemicalFormula(self):
        atoms = self
        counts = {}
        for atom in atoms:
            e = atom.symbol
            if e in counts: counts[e]+=1
            else: counts[e]=1
            continue
        elems = counts.keys()
        elems.sort()
        chemFormRaw = ''.join( '%s_%s ' % (e, counts[e]) for e in elems )
        return chemFormRaw.strip()
    
    def getSpecies(self):
        speciesList = []
        for atom in self:
            if atom.symbol in speciesList:
                pass
            else:
                speciesList.append(atom.symbol)
        return speciesList

    # these properties are actually independent of space group and so should
    # be moved to lattice perhaps
    def _getCrystalSystem(self):
        return self.sg.crystal_system
    crystal_system = property(_getCrystalSystem)


    def _getCentering(self):
        return self.sg.pdb_name[0]
    centering = property(_getCentering)

    
    _centerings = {
        'P': 'primitive',
        'C': 'single face centered',
        'A': 'single face centered',
        'H': 'primitive',
        'R': 'primitive',
        'I': 'body centered',
        'F': 'face centered',
        }
    def _getCenteringDescription(self):
        return self._centerings[self.centering]
    centering_description = property(_getCenteringDescription)
    
    def _getBravaisType(self):
        centeringAndSystem2bravais = {
        ('P', 'CUBIC'):'simple cubic',
        ('F', 'CUBIC'):'face centered cubic',
        ('I', 'CUBIC'):'body centered cubic', 
        ('P', 'HEXAGONAL'):'simple hexagonal',
        ('P', 'TRIGONAL'):'simple trigonal',
        ('P','TETRAGONAL'):'simple tetragonal',
        ('R','TETRAGONAL'):'simple tetragonal',
        ('I','TETRAGONAL'):'body centered tetragonal',
        ('P','ORTHORHOMBIC'):'simple orthorhombic',
        ('C','ORTHORHOMBIC'):'base centered orthorhombic',
        ('A','ORTHORHOMBIC'):'base centered orthorhombic',
        ('F','ORTHORHOMBIC'):'face centered orthorhombic',
        ('I','ORTHORHOMBIC'):'body centered orthorhombic',
        ('P','ORTHORHOMBIC'):'simple monoclinic',
        ('P','MONOCLINIC'):'base centered monoclinic',
        ('P','TRICLINIC'):'triclinic'                  
        }
        return centeringAndSystem2bravais[(self.sg.short_name[0], self.sg.crystal_system)]
    bravais_type = property(_getBravaisType)


    def _getStrukturberichtDesignation(self):
        finder = self._getStrukturberichtDesignationFinder()
        return finder.find(self)
    StrukturberichtDesignation = property(_getStrukturberichtDesignation)
        

    def _getStrukturberichtDesignationFinder(self):
        k = '_StrukturberichtDesignationFinder'
        if hasattr(self, k): return getattr(self, k)
        from StrukturberichtDesignationFinder import StrukturberichtDesignationFinder
        r = StrukturberichtDesignationFinder()
        setattr(self, k, r)
        return r
    

    def _get_primitive_unitcell(self):
        t = self._primitive_unitcell
        if t is None:
            #t = self._primitive_unitcell = self._lattice.getPrimitiveLattice(self.sg)
            t = self._primitive_unitcell = self._create_primitive_unitcell()
        return t
    def _set_primitive_unitcell(self, p):
        self._primitive_unitcell = p
        return p
    primitive_unitcell = property(_get_primitive_unitcell, _set_primitive_unitcell)


    def _create_primitive_unitcell(self):
        # the ctor
        from UnitCell import UnitCell
        base = self._lattice.getPrimitiveLattice(self.sg)
        base = numpy.array(base)
        
        puc = UnitCell(base=base)
        for atom in self:
            if puc.hasAtom(atom): continue
            puc.addAtom(atom)
            continue                
        return puc
        
        # check symmetry
        sg = self.sg
        verdict, atompos, symop = self.symConsistent()
        if not verdict:
            raise RuntimeError, \
                  "inconsistent structure: atom position: %s, sym operation %s" % (
                atompos, symop)

        #
        if sg.number == 225:
            # face centered--below is only for cubic...need to generalize
            a = self.lattice.a
            base = numpy.array([[0,1,1], [1,0,1], [1,1,0]])*0.5*a
            
        elif sg.number == 229:
            # body centered--below is only for cubic...need to generalize
            a = self.lattice.a
            base = numpy.array([[1,0,0], [0,1,0], [0.5,0.5,0.5]])*a
            
            
        elif sg.short_name[0] == 'P':
            # primitive
            base = self.lattice

        else:
            # not implemented
            return
        
        
    
    def addNewAtom(self, *args, **kwargs):
        """Add new Atom instance to the end of this Structure.

        All arguments are forwarded to Atom constructor.
        """
        kwargs['lattice'] = self.lattice
        a = Atom(*args, **kwargs)
        list.append(self, a)
        self._uncache('labels')

    def getLastAtom(self):
        """Return Reference to the last Atom in this structure.
        """
        last_atom = self[-1]
        return last_atom

    def getAtom(self, id):
        """Reference to internal Atom specified by the identifier.

        id  -- zero based index or a string label formatted as
               "%(element)s%(order)i", for example "Na1", "Cl1"

        Return Atom instance.
        Raise ValueError for invalid id.

        See also getLabels().
        """
        try:
            if type(id) is int:
                rv = self[id]
            else:
                if not self._labels_cached or id not in self._labels:
                    self._update_labels()
                rv = self._labels[id]
        except (IndexError, KeyError):
            emsg = "Invalid atom identifier %r." % id
            raise ValueError(emsg)
        return rv


    def getLabels(self):
        """List of unique string labels for all atoms in this structure.

        Return a list.
        """
        elnum = {}
        labels = []
        for a in self:
            elnum[a.symbol] = elnum.get(a.symbol, 0) + 1
            alabel = a.symbol + str(elnum[a.symbol])
            labels.append(alabel)
        return labels
        
    #untested--from UnitCell
    def bringFractionalPositionIntoCell(self, fracpos):
        """Brings a fractional position (x,y,z) 'into' the unit cell,
        i.e.: (x,y,z)->(x',y',z') such that x,y,z in [0,1( """
        pos = numpy.array(fracpos)
        assert (len(pos) == 3)
        for i in range(3):
            if pos[i]<0:
                while pos[i]<0:
                    pos[i] += 1
            if pos[i]>=1:
                while pos[i]>=1:
                    pos[i] -= 1
        return pos

    #untested--from UnitCell
    def cartesianPositionInLattice(self, siteId, latticeVector):
        """Returns the Cartesian position vector from the origin
        ( fractional coordinates [0,0,0] in unit cell [0,0,0]),
        for a Site corresponding to 'siteId',
        in the unit cell corresponding to latticeVector
        (triplets of coordinates in terms of cellvectors), 
        defining which unit cell in the lattice.
        """
        try:
            posincell = self.getCartesianPosition(siteId)
        except KeyError: raise KeyError, 'Invalid site Id'
        pos = numpy.array(posincell) + numpy.dot(latticeVector, self._lattice)
        return pos
    
    def getPosition(self, siteId):
        """Returns the (fractional) position of a site."""
        return self._siteIds[siteId].getPosition()

    def setPositions(self, positions):
        """Sets the (fractional) positions of the sites in the unit cell."""
        assert(len(positions) == self.getNumSites())
        for isite in range(self.getNumSites()):
            self._sites[isite].setPosition(positions[isite])

    def getCartesianPosition(self, siteId):
        """Returns the cartesian position of a site."""
        return self.fractionalToCartesian(self._siteIds[siteId].getPosition())

    def fractionalToCartesian(self, fracpos):
        """Converts a coordinate from fractional to cartesian.""" 
        return (fracpos * self._lattice).sum(0)  # should be double-checked

    def cartesianToFractional(self, cartpos):
        """Converts a coordinate from cartesian to fractional."""
        return (cartpos * numpy.linalg.inv(self._lattice)).sum(0)  # should be double-checked
    
    def generateDescription(self):
        if self._description==None:
            self._description = self.getChemicalFormula()#+' in '+str(self.lattice)
        return self._description
    def setDescription(self, desc):
        self._description = desc
    description = property(generateDescription, setDescription, "structure description")
    
################################################    
# property methods
################################################
#Notes:
# for now these are done in the style of diffraction
# eventually will be done in Jiao's style with metaclasses

    # fractional xyz
    def _get_xyz(self):
        return [atom.xyz.tolist()  for atom in self[:]]
    def _set_xyz(self, xyzList):
        for atom,xyz in zip(self, xyzList):
            atom.xyz = xyz
    xyz = property(_get_xyz, _set_xyz, doc =
        """fractional coordinates of all atoms""" )  

    # xyz_cartn
    def _get_xyz_cartn(self):
        return [atom.xyz_cartn.tolist() for atom in self[:]]
    def _set_xyz_cartn(self, xyzList):
        for atom,xyz_cartn in zip(self, xyzList):
            atom.xyz_cartn = xyz_cartn
    xyz_cartn = property(_get_xyz_cartn, _set_xyz_cartn, doc =
        """absolute Cartesian coordinates of all atoms""" )   
    
    # symbols
    def _get_symbols(self):
        return [atom.symbol for atom in self[:]]
    def _set_symbols(self, symbolList):
        for atom,symbol in zip(self, symbolList):
            atom.symbol = symbol
    symbols = property(_get_symbols, _set_symbols, doc =
        """symbols of all atoms""" )  
    
    # forces
    def _get_forces(self):
        return [atom.force for atom in self]
    def _set_forces(self, forceList):
        for atom,force in zip(self, forceList):
            atom.force = force
    forces = property(_get_forces, _set_forces, doc =
        """forces on all atoms""" )   
    
    # charges
    def _get_charges(self):
        return [atom.charge for atom in self]
    def _set_charges(self, chargeList):
        for atom,charge in zip(self, chargeList):
            atom.charge = charge
    charges = property(_get_charges, _set_charges, doc =
        """charges on all atoms in electron units""" )   
    
################################################################################################    
# geometry and symmetry methods--these should be farmed out to Geometry class which does all this--see vimm
################################################################################################ 

    def distance(self, id0, id1):
        """Distance between 2 atoms, no periodic boundary conditions.

        id0 -- zero based index of the first atom or a string label
               such as "Na1"
        id1 -- zero based index or string label of the second atom.

        Return float.
        Raise ValueError for invalid arguments.
        """
        a0 = self.getAtom(id0)
        a1 = self.getAtom(id1)
        return self.lattice.dist(a0.xyz, a1.xyz)


    def angle(self, a0, a1, a2):
        """angle at atom a1 in degrees"""
        u10 = a0.xyz - a1.xyz
        u12 = a2.xyz - a1.xyz
        return self.lattice.angle(u10, u12)


    def symConsistent(self, decimal=7):
        from numpy.testing import assert_array_almost_equal
        verdict = True
        nonCompliantAtomPosition = None
        nonCompliantSymOp = None
        def arrayInList(trialArray,arrayList):
            matchesQ=False
            for certainArray in arrayList:
                if (numpy.round(trialArray-certainArray, decimal)==0).all():
                    matchesQ = True
            return matchesQ
        sg = self.sg
        # as long as the structure is given a lattice, each atom.xyz should be in fractional coords
        atomPositions = [atom.xyz for atom in self[:]]
        for atomPosition in atomPositions:
            for symop in sg.symop_list:
                rawPosition = numpy.dot(symop.R, atomPosition) + symop.t
                fracPos, intPos = numpy.modf(numpy.round(rawPosition, decimal))
                newPosition = numpy.mod(fracPos,1)
                if not arrayInList(newPosition, atomPositions):
                    verdict = False
                    nonCompliantAtomPosition = atomPosition
                    nonCompliantSymOp = symop
                    break
        return verdict, nonCompliantAtomPosition, nonCompliantSymOp
    
    def placeInLattice(self, new_lattice):
        """place structure into new_lattice coordinate system

        sets lattice to new_lattice and recalculate fractional coordinates
        of all atoms so their absolute positions remain the same

        return self
        """
        Tx = numpy.dot(self.lattice.base, new_lattice.recbase)
        Tu = numpy.dot(self.lattice.normbase, new_lattice.recnormbase)
        for a in self:
            a.xyz = list(numpy.dot(a.xyz, Tx))
        self.lattice = new_lattice
        return self
    
    def computeDistances(self, maxdist=30, latticeRange=[2,2,2]):
        """ unitcell.computeDistances(self, [nx,ny,nz]):
        builds up a Big multiple dictionary, namely
        self.distances[atom1][atom2][(DX,DY,DZ)]
        (DX,DY,DZ) are integer numbers specifying the cell containing atom2,
        relatively to atom1.
        DX,DY,DZ run from -nx to nx, -ny to ny, -nz to nz, respectively."""
        distances = {}
        idlist = self.getLabels()
        #idlist = self.getIds()
        for iA in range(0, len(idlist)):
            idA = idlist[iA]
            distances[idA] = {}
            for iB in range(0, len(idlist)):
                idB = idlist[iB]
                distances[idA][idB]={}
                for tx in range(-latticeRange[0],latticeRange[0]+1):
                    for ty in range(-latticeRange[1],latticeRange[1]+1):
                        for tz in range(-latticeRange[2],latticeRange[2]+1):
                            posA = self.getCartesianPosition(idA)
                            posB = self.getCartesianPosition(idB) + numpy.dot([tx,ty,tz], self._lattice)
                            dist = numpy.sqrt(numpy.sum( (posB-posA) * (posB-posA) ))
                            if(dist<maxdist):
                                distances[idA][idB][(tx,ty,tz)] = dist
        self._distances = distances
        return distances

##     def findTetrahedra(self, list4ids, latticeVectors=[(0,0,0),(0,0,0),(0,0,0),(0,0,0)]):
##         """Searches the tetrahedra that equivalent by symmetry to the reference tetrahedron
##         defined by the list4ids (4 Ids) and the cells indices where vertices lie."""        
##         # from OpenPhonon:
##         # OP_cella. FindTetragons(self, Latoms, CellsCoo=[(0,0,0),(0,0,0),(0,0,0),(0,0,0)])
##         # This is the key routine to find good candidates to symmetry group.
##         # Latoms is a list of the kind [  (Aa,kA) ,(Bb,kB)....] 
##         # ( i.e. couples formed by atom-name and position in the position list.
##         # Latoms must be formed of four  atoms defining a non-degenerate tetraedron.
##         # A check is permormed on the non-degeneracy.
##         # The funtions finds all the possible equivalent tetraedrons (which have the same
##         # set of distances, and the same atom kinds)
##         # The function return the list of all these tetraedrons
        
##         if type(list4ids) is not type([]):
##             raise ValueError, 'list4ids should be a list of 4 site Ids.'
##         if len(list4ids) != len(latticeVectors):
##             raise ValueError, 'There should be as many site Ids as lattice vectors.'
##         if len(list4ids) != 4:
##             raise ValueError, 'Need 4 sites to define a tetrahedron.'
        
##         tetraVertices = [self.cartesianPositionInLattice(id,lattvec)
##                          for (id,lattvec) in zip(list4ids,latticeVectors)]
##         # compute vectors for edges of tetrahedron from first point:
##         edgeVectors = tetraVertices[1:4] - tetraVertices[0]

##         # check for non-degeneracy:
##         det = la.det(edgeVectors)
##         if(abs(det) < 1e-6):
##             raise ValueError, 'determinant smaller than 1e-6: degenerate reference tetrahedron.'

###########################
# IO
###########################
    def read(self, filename, format='auto'):
        """Load structure from a file, any original data may become lost.

        filename -- file to be loaded
        format   -- all structure formats are defined in Parsers submodule,
                    when format == 'auto' all Parsers are tried one by one

        Return instance of data Parser used to process file.  This
        can be inspected for information related to particular format.
        """
        from Parsers import getParser
        p = getParser(format)
        new_structure = p.parseFile(filename)
        # reinitialize data after successful parsing
        # avoid calling __init__ from a derived class
        Structure.__init__(self)
        if new_structure is not None:
            self.__dict__.update(new_structure.__dict__)
            self[:] = new_structure
        if not self.description:
            self.generateDescription()
#            import os.path
#            tailname = os.path.basename(filename)
#            tailbase = os.path.splitext(tailname)[0]
#            self.description = tailbase
        return p

    def readStr(self, s, format='auto'):
        """Load structure from a string, any original data become lost.

        s        -- string with structure definition
        format   -- all structure formats are defined in Parsers submodule,
                    when format == 'auto' all Parsers are tried one by one

        Return instance of data Parser used to process input string.  This
        can be inspected for information related to particular format.
        """
        from Parsers import getParser
        p = getParser(format)
        new_structure = p.parse(s)
        # reinitialize data after successful parsing
        # avoid calling __init__ from a derived class
        Structure.__init__(self)
        if new_structure is not None:
            self.__dict__.update(new_structure.__dict__)
            self[:] = new_structure
        return p

    def write(self, filename, format, **kwds):
        """Save structure to file in the specified format

        No return value.

        Note: available structure formats can be obtained by:
            from Parsers import formats
        """
        from Parsers import getParser
        p = getParser(format)
        p.filename = filename
        s = p.tostring(self, **kwds)
        f = open(filename, 'wb')
        f.write(s)
        f.close()
        return

    def writeStr(self, format, **kwds):
        """return string representation of the structure in specified format

        Note: available structure formats can be obtained by:
            from Parsers import formats
        """
        from Parsers import getParser
        p = getParser(format)
        s = p.tostring(self, **kwds)
        return s

    ##############################################################################
    # overloaded list methods
    ##############################################################################

    def append(self, a, copy=True):
        """Append atom to a structure and update its lattice attribute.

        a    -- instance of Atom
        copy -- flag for appending a copy of a.
                When False, append a and update a.owner.

        No return value.
        """
        self._uncache('labels')
        adup = copy and Atom(a) or a
        adup.lattice = self.lattice
        list.append(self, adup)
        return

    def insert(self, idx, a, copy=True):
        """Insert atom a before position idx in this Structure.

        idx  -- position in atom list
        a    -- instance of Atom
        copy -- flag for inserting a copy of a.
                When False, append a and update a.lattice.

        No return value.
        """
        self._uncache('labels')
        adup = copy and Atom(a) or a
        adup.lattice = self.lattice
        list.insert(self, idx, adup)
        return

    def extend(self, atoms, copy=True):
        """Extend Structure by appending copies from a list of atoms.

        atoms -- list of Atom instances
        copy  -- flag for extending with copies of Atom instances.
                 When False extend with atoms and update their lattice
                 attributes.

        No return value.
        """
        self._uncache('labels')
        if copy:    adups = [Atom(a) for a in atoms]
        else:       adups = atoms
        for a in adups: a.lattice = self.lattice
        list.extend(self, adups)
        return

    def __setitem__(self, idx, a, copy=True):
        """Set idx-th atom to a.

        idx  -- index of atom in this Structure
        a    -- instance of Atom
        copy -- flag for setting to a copy of a.
                When False, set to a and update a.lattice.

        No return value.
        """
        self._uncache('labels')
        adup = copy and Atom(a) or a
        adup.lattice = self.lattice
        list.__setitem__(self, idx, adup)
        return

    def __setslice__(self, lo, hi, atoms, copy=False):
        """Set Structure slice from lo to hi-1 to the sequence of atoms.

        lo    -- low index for the slice
        hi    -- high index of the slice
        atoms -- sequence of Atom instances
        copy  -- flag for using copies of Atom instances.  When False, set
                 to existing instances and update their lattice attributes.

        No return value.
        """
        self._uncache('labels')
        if copy:    
            adups = [Atom(a) for a in atoms]
        else:       
            adups = atoms
        for a in adups: a.lattice = self.lattice
        list.__setslice__(self, lo, hi, adups)

    ####################################################################
    # property handlers
    ####################################################################

    # lattice

    def _get_lattice(self):
        if not hasattr(self, '_lattice'):
            self._lattice = Lattice()
        return self._lattice
    def _set_lattice(self, value):
        for a in self:  a.lattice = value
        self._lattice = value
        return
    lattice = property(_get_lattice, _set_lattice, doc =
        "Coordinate system for this Structure.")
    
    # space group

    def _get_spaceGroup(self):
        if not self._sg:
            from .SpaceGroups import GetSpaceGroup
            self._sg = GetSpaceGroup(self._sgid)
        return self._sg

    def _set_spaceGroup(self, item):
        from .SpaceGroups import SpaceGroup
        if isinstance(item, SpaceGroup):
            self._sg = item
            self._sgid = item.number
        else:
            from .SpaceGroups import GetSpaceGroup
            self._sg = GetSpaceGroup(item)
            self._sgid = item

    sg = property(_get_spaceGroup, _set_spaceGroup, doc =
        """Space group for this structure.  This can be set 
        by instantiating with a new spacegroup class or with a space group id.
        One can also use the explicit setter.""")
    
    ####################################################################
    # additional setter
    ####################################################################

    def setSg(self, sgid):
        self.sg = sgid
        return

    ####################################################################
    # protected methods
    ####################################################################

    def _update_labels(self):
        """Update the _labels dictionary of unique string labels of atoms.

        No return value.
        """
        kv = zip(self.getLabels(), self[:])
        self._labels = dict(kv)
        self._labels_cached = True
        return


    def _uncache(self, *args):
        """Reset cached flag for a list of internal attributes.

        *args -- list of strings, currently supported are "labels"

        No return value.
        Raise AttributeError for any invalid args.
        """
        for a in args:
            attrname = "_" + a + "_cached"
            setattr(self, attrname, False)
        return
Example #35
0
 def _get_lattice(self):
     if not hasattr(self, '_lattice'):
         self._lattice = Lattice()
     return self._lattice
class ChemicalEntity(list):
    """ChemicalEntity -- superclass of Structure and Molecule

    Molecule class is inherited from Python list.  It contains
    a list of Atom instances.  Molecule overloads setitem and setslice
    methods so that the lattice attribute of atoms get set to lattice.

    Data members:
        description   -- molecule description
        lattice -- coordinate system (instance of Lattice)
    """
    def __init__(self,
                 atoms=[],
                 lattice=None,
                 description=None,
                 filename=None):
        """define group of atoms in a specified lattice.

        atoms    -- list of Atom instances to be included in this Molecule.
                    When atoms argument is an existing Molecule instance,
                    the new Molecule is its copy.
        lattice  -- instance of Lattice defining coordinate systems.
        description -- string description of the structure
        filename -- optional, name of a file to load the structure from.
                    Overrides atoms argument when specified.

        Molecule(mol)     create a copy of Molecule instance.

        Because Molecule is inherited from a list it can use list expansions,
        for example:
            oxygen_atoms = [ for a in stru if a.symbol == "O" ]
        """
        self._labels = {}
        self._labels_cached = False
        if isinstance(atoms, Molecule):
            mol = atoms
            # create a shallow copy of all source attributes
            self.__dict__.update(mol.__dict__)
            # make a deep copy of source lattice
            self.lattice = Lattice(mol.lattice)

        self.description = description
        # check if data should be loaded from file
        if filename is not None:
            self.read(filename)
        # otherwise assign list of atoms to self
        else:
            self[:] = atoms
        # override from lattice argument
        if lattice is None:
            if not self.lattice: self.lattice = Lattice()
        #elif not isinstance(lattice, Lattice):
        #   emsg = "expected instance of Lattice"
        #    raise TypeError(emsg)
        else:
            self.lattice = lattice
        import time
        self.date = time.ctime()
#    def __str__(self):
#        """simple string representation"""
#        s_lattice = "lattice=%s" % self.lattice
#        s_atoms = '\n'.join([str(a) for a in self])
#        return s_lattice + '\n' + s_atoms

    def getChemicalFormula(self):
        atoms = self
        counts = {}
        for atom in atoms:
            e = atom.symbol
            if e in counts: counts[e] += 1
            else: counts[e] = 1
            continue
        elems = counts.keys()
        elems.sort()
        chemFormRaw = ''.join('%s_%s ' % (e, counts[e]) for e in elems)
        return chemFormRaw.strip()

    def getSpecies(self):
        speciesList = []
        for atom in self:
            if atom.symbol in speciesList:
                pass
            else:
                speciesList.append(atom.symbol)
        return speciesList

    def addNewAtom(self, *args, **kwargs):
        """Add new Atom instance to the end of this Structure.

        All arguments are forwarded to Atom constructor.

        No return value.
        """
        kwargs['lattice'] = self.lattice
        a = Atom(*args, **kwargs)
        list.append(self, a)
        self._uncache('labels')
        return

    def getLastAtom(self):
        """Return Reference to the last Atom in this structure.
        """
        last_atom = self[-1]
        return last_atom

    def getAtom(self, id):
        """Reference to internal Atom specified by the identifier.

        id  -- zero based index or a string label formatted as
               "%(element)s%(order)i", for example "Na1", "Cl1"

        Return Atom instance.
        Raise ValueError for invalid id.

        See also getLabels().
        """
        try:
            if type(id) is int:
                rv = self[id]
            else:
                if not self._labels_cached or id not in self._labels:
                    self._update_labels()
                rv = self._labels[id]
        except (IndexError, KeyError):
            emsg = "Invalid atom identifier %r." % id
            raise ValueError(emsg)
        return rv

    def getLabels(self):
        """List of unique string labels for all atoms in this structure.

        Return a list.
        """
        elnum = {}
        labels = []
        for a in self:
            elnum[a.symbol] = elnum.get(a.symbol, 0) + 1
            alabel = a.symbol + str(elnum[a.symbol])
            labels.append(alabel)
        return labels

    def getPosition(self, siteId):
        """Returns the (fractional) position of a site."""
        return self._siteIds[siteId].getPosition()

    def setPositions(self, positions):
        """Sets the (fractional) positions of the sites in the unit cell."""
        assert (len(positions) == self.getNumSites())
        for isite in range(self.getNumSites()):
            self._sites[isite].setPosition(positions[isite])

    def generateDescription(self):
        if self._description == None:
            self._description = self.getChemicalFormula(
            )  #+' in '+str(self.lattice)
        return self._description

    def setDescription(self, desc):
        self._description = desc

    description = property(generateDescription, setDescription,
                           "structure description")

    ################################################
    # property methods
    ################################################
    #Notes:
    # for now these are done in the style of diffraction
    # eventually will be done in Jiao's style with metaclasses

    # fractional xyz
    def _get_xyz(self):
        return [atom.xyz.tolist() for atom in self[:]]

    def _set_xyz(self, xyzList):
        for atom, xyz in zip(self, xyzList):
            atom.xyz = xyz

    xyz = property(_get_xyz,
                   _set_xyz,
                   doc="""fractional coordinates of all atoms""")

    # xyz_cartn
    def _get_xyz_cartn(self):
        return [atom.xyz_cartn.tolist() for atom in self[:]]

    def _set_xyz_cartn(self, xyzList):
        for atom, xyz_cartn in zip(self, xyzList):
            atom.xyz_cartn = xyz_cartn

    xyz_cartn = property(_get_xyz_cartn,
                         _set_xyz_cartn,
                         doc="""absolute Cartesian coordinates of all atoms""")

    # symbols
    def _get_symbols(self):
        return [atom.symbol for atom in self[:]]

    def _set_symbols(self, symbolList):
        for atom, symbol in zip(self, symbolList):
            atom.symbol = symbol

    symbols = property(_get_symbols,
                       _set_symbols,
                       doc="""symbols of all atoms""")

    # forces
    def _get_forces(self):
        return [atom.force for atom in self]

    def _set_forces(self, forceList):
        for atom, force in zip(self, forceList):
            atom.force = force

    forces = property(_get_forces, _set_forces, doc="""forces on all atoms""")

    # charges
    def _get_charges(self):
        return [atom.charge for atom in self]

    def _set_charges(self, chargeList):
        for atom, charge in zip(self, chargeList):
            atom.charge = charge

    charges = property(_get_charges,
                       _set_charges,
                       doc="""charges on all atoms in electron units""")

    ################################################################################################
    # geometry and symmetry methods--these should be farmed out to Geometry class which does all this--see vimm
    ################################################################################################

    def distance(self, id0, id1):
        """Distance between 2 atoms, no periodic boundary conditions.

        id0 -- zero based index of the first atom or a string label
               such as "Na1"
        id1 -- zero based index or string label of the second atom.

        Return float.
        Raise ValueError for invalid arguments.
        """
        a0 = self.getAtom(id0)
        a1 = self.getAtom(id1)
        return self.lattice.dist(a0.xyz, a1.xyz)

    def angle(self, a0, a1, a2):
        """angle at atom a1 in degrees"""
        u10 = a0.xyz - a1.xyz
        u12 = a2.xyz - a1.xyz
        return self.lattice.angle(u10, u12)

    def computeDistances(self, maxdist=30, latticeRange=[2, 2, 2]):
        """ unitcell.computeDistances(self, [nx,ny,nz]):
        builds up a Big multiple dictionary, namely
        self.distances[atom1][atom2][(DX,DY,DZ)]
        (DX,DY,DZ) are integer numbers specifying the cell containing atom2,
        relatively to atom1.
        DX,DY,DZ run from -nx to nx, -ny to ny, -nz to nz, respectively."""
        distances = {}
        idlist = self.getLabels()
        #idlist = self.getIds()
        for iA in range(0, len(idlist)):
            idA = idlist[iA]
            distances[idA] = {}
            for iB in range(0, len(idlist)):
                idB = idlist[iB]
                distances[idA][idB] = {}
                for tx in range(-latticeRange[0], latticeRange[0] + 1):
                    for ty in range(-latticeRange[1], latticeRange[1] + 1):
                        for tz in range(-latticeRange[2], latticeRange[2] + 1):
                            posA = self.getCartesianPosition(idA)
                            posB = self.getCartesianPosition(idB) + numpy.dot(
                                [tx, ty, tz], self._lattice)
                            dist = numpy.sqrt(
                                numpy.sum((posB - posA) * (posB - posA)))
                            if (dist < maxdist):
                                distances[idA][idB][(tx, ty, tz)] = dist
        self._distances = distances
        return distances

###########################
# IO
###########################

    def read(self, filename, format='auto'):
        """Load structure from a file, any original data may become lost.

        filename -- file to be loaded
        format   -- all structure formats are defined in Parsers submodule,
                    when format == 'auto' all Parsers are tried one by one

        Return instance of data Parser used to process file.  This
        can be inspected for information related to particular format.
        """
        from Parsers import getParser
        p = getParser(format)
        new_structure = p.parseFile(filename)
        # reinitialize data after successful parsing
        # avoid calling __init__ from a derived class
        Molecule.__init__(self)
        if new_structure is not None:
            self.__dict__.update(new_structure.__dict__)
            self[:] = new_structure
        if not self.description:
            self.generateDescription()


#            import os.path
#            tailname = os.path.basename(filename)
#            tailbase = os.path.splitext(tailname)[0]
#            self.description = tailbase
        return p

    def readStr(self, s, format='auto'):
        """Load structure from a string, any original data become lost.

        s        -- string with structure definition
        format   -- all structure formats are defined in Parsers submodule,
                    when format == 'auto' all Parsers are tried one by one

        Return instance of data Parser used to process input string.  This
        can be inspected for information related to particular format.
        """
        from Parsers import getParser
        p = getParser(format)
        new_structure = p.parse(s)
        # reinitialize data after successful parsing
        # avoid calling __init__ from a derived class
        Molecule.__init__(self)
        if new_structure is not None:
            self.__dict__.update(new_structure.__dict__)
            self[:] = new_structure
        return p

    def write(self, filename, format):
        """Save molecule to file in the specified format

        No return value.

        Note: available structure formats can be obtained by:
            from Parsers import formats
        """
        from Parsers import getParser
        p = getParser(format)
        p.filename = filename
        s = p.tostring(self)
        f = open(filename, 'wb')
        f.write(s)
        f.close()
        return

    def writeStr(self, format):
        """return string representation of the structure in specified format

        Note: available structure formats can be obtained by:
            from Parsers import formats
        """
        from Parsers import getParser
        p = getParser(format)
        s = p.tostring(self)
        return s

    ##############################################################################
    # overloaded list methods
    ##############################################################################

    def append(self, a, copy=True):
        """Append atom to a structure and update its lattice attribute.

        a    -- instance of Atom
        copy -- flag for appending a copy of a.
                When False, append a and update a.owner.

        No return value.
        """
        self._uncache('labels')
        adup = copy and Atom(a) or a
        adup.lattice = self.lattice
        list.append(self, adup)
        return

    def insert(self, idx, a, copy=True):
        """Insert atom a before position idx in this Structure.

        idx  -- position in atom list
        a    -- instance of Atom
        copy -- flag for inserting a copy of a.
                When False, append a and update a.lattice.

        No return value.
        """
        self._uncache('labels')
        adup = copy and Atom(a) or a
        adup.lattice = self.lattice
        list.insert(self, idx, adup)
        return

    def extend(self, atoms, copy=True):
        """Extend Structure by appending copies from a list of atoms.

        atoms -- list of Atom instances
        copy  -- flag for extending with copies of Atom instances.
                 When False extend with atoms and update their lattice
                 attributes.

        No return value.
        """
        self._uncache('labels')
        if copy: adups = [Atom(a) for a in atoms]
        else: adups = atoms
        for a in adups:
            a.lattice = self.lattice
        list.extend(self, adups)
        return

    def __setitem__(self, idx, a, copy=True):
        """Set idx-th atom to a.

        idx  -- index of atom in this Structure
        a    -- instance of Atom
        copy -- flag for setting to a copy of a.
                When False, set to a and update a.lattice.

        No return value.
        """
        self._uncache('labels')
        adup = copy and Atom(a) or a
        adup.lattice = self.lattice
        list.__setitem__(self, idx, adup)
        return

    def __setslice__(self, lo, hi, atoms, copy=False):
        """Set Structure slice from lo to hi-1 to the sequence of atoms.

        lo    -- low index for the slice
        hi    -- high index of the slice
        atoms -- sequence of Atom instances
        copy  -- flag for using copies of Atom instances.  When False, set
                 to existing instances and update their lattice attributes.

        No return value.
        """
        self._uncache('labels')
        if copy:
            adups = [Atom(a) for a in atoms]
        else:
            adups = atoms
        for a in adups:
            a.lattice = self.lattice
        list.__setslice__(self, lo, hi, adups)

    ####################################################################
    # property handlers
    ####################################################################

    # lattice
    def _get_lattice(self):
        if not hasattr(self, '_lattice'):
            self._lattice = Lattice()
        return self._lattice

    def _set_lattice(self, value):
        for a in self:
            a.lattice = value
        self._lattice = value
        return

    lattice = property(_get_lattice,
                       _set_lattice,
                       doc="Coordinate system for this Structure.")

    ####################################################################
    # protected methods
    ####################################################################

    def _update_labels(self):
        """Update the _labels dictionary of unique string labels of atoms.

        No return value.
        """
        kv = zip(self.getLabels(), self[:])
        self._labels = dict(kv)
        self._labels_cached = True

    def _uncache(self, *args):
        """Reset cached flag for a list of internal attributes.

        *args -- list of strings, currently supported are "labels"

        No return value.
        Raise AttributeError for any invalid args.
        """
        for a in args:
            attrname = "_" + a + "_cached"
            setattr(self, attrname, False)
Example #37
0
    AOI = np.radians(args.AOI)
    phi = np.radians(args.Azi)
    # incident polarization of the light, [1,0,0] means light is polarized in x, [0,1,0] mean light is polarized in y
    if args.pol == 'p':
        E0_vec = np.array([1, 0, 0], dtype=complex)
    elif args.pol == 's':
        E0_vec = np.array([0, 1, 0], dtype=complex)
    # inciddent k vector [0,0,1] means light is travelling in +z axis
    k_vec = np.array(
        [np.sin(AOI) * np.cos(phi),
         np.sin(AOI) * np.sin(phi),
         np.cos(AOI)])
    # Dielectric function of surrounding medium
    eps_surround = args.N_m**2
    # Create lattice object
    Lat = Lattice(args.nx, args.ny, args.lc, args.a, args.b, args.c)
    N, pos, r_eff = getattr(Lat, args.Lat)()  # Call a class method by a string
    Lat.Grid_Viz()  # Visualize the grid

    # Create empy containers
    A = np.zeros([3 * N, 3 * N],
                 dtype='complex')  # A matrix of 3N x 3N filled with zeros
    p = np.zeros(
        3 * N, dtype='complex'
    )  # A vector that stores polarization Px, Py, Pz of the each particles, we will use this for initial guess for solver
    E0 = np.tile(
        E0_vec, N
    )  # A vector that has the Ex, Ey, Ez for each particles, we make this by tiling the E0_vec vector
    E_inc = np.zeros(
        3 * N, dtype='complex'
    )  # A vector storing the Incident Electric field , Einc_x, Einc_y, Einc_z for each particle
Example #38
0
from FormalContext import *
from Lattice import Lattice
import time

if __name__ == '__main__':

    # load随机形式背景
    fc = load_FC()
    fp = open(
        'result_%s_%s_%s' % (fc.object_num, fc.attribute_num, fc.oa_rate), 'w')

    b1 = [0.0, 0.3, 0.5, 0.7, 0.9]
    b2 = [0.0, 0.2, 0.4, 0.6, 0.8]

    # b1, b2 变化
    for b11 in b1:
        for b22 in b2:
            try:
                myLattice = Lattice(fc, b11, b22)
                before = time.time()
                for obj in range(fc.object_num):
                    myLattice.addOneObject([obj], fc.oa_value[obj])
                fp.write('b1=%s, b2=%s --> conceptnum is %s\n time: %s\n' %
                         (b11, b22, len(
                             myLattice.conceptSet), time.time() - before))
            except Exception, e:
                fp.write('\n\nException : %s\n\n' % e)
            finally:
                fp.flush()
    print 'end  b1, b2 变化'
Example #39
0
    def run_simulation(self):

        self.simulation_idx = 1
        print('Simulation start')

        n_simulations = len(self.hatch_times) * len(
            self.nutritional_values) * len(self.n_rats_range) * len(
                self.n_birds_range)

        for hatch_time in self.hatch_times:
            for nutritional_value in self.nutritional_values:
                for nrats in self.n_rats_range:
                    for nbirds in self.n_birds_range:
                        start = time.process_time()
                        sim = Lattice(self.size,
                                      nrats,
                                      nbirds,
                                      self.n_sim_steps,
                                      hatch_time,
                                      self.nest_placement_delay,
                                      self.rat_energy,
                                      nutritional_value,
                                      plot_environment=False,
                                      plot_populations=False)
                        sim.start()
                        bird_pop, rat_pop, nest_pop, time_record = sim.join()
                        max_bird_pop = max(bird_pop)
                        max_rat_pop = max(rat_pop)
                        min_bird_pop = min(bird_pop)
                        min_rat_pop = min(rat_pop)
                        fig, ax = plt.subplots()
                        plt.plot(time_record,
                                 bird_pop,
                                 color='blue',
                                 label='Bird population')
                        plt.plot(time_record,
                                 nest_pop,
                                 color='green',
                                 label='Nest population')
                        plt.plot(time_record,
                                 rat_pop,
                                 color='red',
                                 label='Rat population')
                        handles, labels = ax.get_legend_handles_labels()
                        plt.legend(handles, labels)
                        ax.set_xlabel('Time steps')
                        ax.set_ylabel('Populations')
                        ax.set_title(
                            'initial bird population: {}, initial rat population: {}\n'
                            'hatch time: {}, nest nutritional value: {}'.
                            format(nbirds, nrats, hatch_time,
                                   nutritional_value))
                        fname = 'nbirds_{}_nrats_{}_nutrition_{}_hatchtime_{}'.format(
                            nbirds, nrats, nutritional_value, hatch_time)
                        self.save_data(fig,
                                       fname,
                                       bird_pop=bird_pop,
                                       rat_pop=rat_pop,
                                       nest_pop=nest_pop,
                                       time=time)
                        plt.close(fig)

                        print('simulation ' + str(self.simulation_idx) + '/' +
                              str(n_simulations))
                        self.simulation_idx += 1
                        stop = time.process_time()
                        print(
                            'time taken to generate 1 plot: {}'.format(stop -
                                                                       start))