def load_jmol_conf(self, file_name, number_of_chains=1): """ Load chain configuration from JMOL file @string file_name: Name of jmol file @dict map_dict: dict with Monomer class @int number_of_chains: number of chains in jmol file """ f = open(file_name, "r+") data = f.readlines() header = int(data[0]) coordinate_data = map(lambda x: x.split(" "), data[2:]) chains = [] for chain_idx in range(number_of_chains): chain_seq = [] slice_coordinate = coordinate_data[chain_idx * header:] self.chain_list[chain_idx].positions_list = [] for c_idx in range(len(slice_coordinate)): c = slice_coordinate[c_idx] crr = tuple(map(lambda x: float(x)/settings.JMOL_SCALE, tuple(c[1:]))) print "Load", crr self.chain_list[chain_idx].chain[c_idx]._open = crr self.chain_list[chain_idx].chain[c_idx].position = Lattice.convert_to_periodic_coordinate(crr) self.chain_list[chain_idx].positions_list.append(self.chain_list[chain_idx].chain[c_idx]._position) self.chain_list[chain_idx] = self.rebuild_direction(self.chain_list[chain_idx])
def begin_rotate(self, monomer_idx = None): """ rotate with begin """ random_direction = randrange(0, Lattice.z) #new_position = Lattice.get_coordinate(self.chain[1]._position, random_direction) new_position = self.chain[1].neighbours_position[random_direction] if self.box.is_occupied(new_position) or new_position in self.positions_list: #logging.info("Reject rotate; position: (%d, %d, %d) is occupied" % (new_position)) return False new_monomer = self.chain[0] old_position = self.chain[0]._position old_open_position = self.chain[0]._open old_next_direction = self.chain[0].next_direction old_energy = self.total_energy self.chain[0].position = new_position self.chain[0]._open = Lattice.get_open_coordinate(self.chain[1]._open, random_direction) self.chain[0].next_direction = Lattice.TURN_DIRECTION[random_direction] self.positions_list[0] = new_position perform_move = True new_energy = None if self.box.athermal_state == False: new_energy = self.box.calculate_chain_energy(self) dE = new_energy - old_energy if self.box.accept(dE, None): perform_move = True else: perform_move = False if perform_move: if not new_energy: new_energy = self.box.calculate_chain_energy(self) self.total_energy = new_energy else: new_monomer.position = old_position new_monomer._open = old_open_position new_monomer.next_direction = old_next_direction self.chain[0] = new_monomer self.positions_list[0] = old_position # restore old energy self.total_energy = old_energy return perform_move
def create_valid_lists(list): point_monomer = {} monomer_list = [] position_set = set() for line in list: type = line[0] ll = np.array(line[1:]) * scale position = tuple(ll) m = DummyMonomer(position, type, Lattice.get_neighbours(tuple(position))) point_monomer[position] = m monomer_list.append(m) position_set.add(position) return point_monomer, monomer_list, position_set
def get_direction(self, monomer_b, monomer_a): """ Return direction between two monomers, use to avoid some moves End point: b Start point: a """ if not isinstance(monomer_a, Monomer): monomer_a = self[monomer_a] if not isinstance(monomer_b, Monomer): monomer_b = self[monomer_b] vector = np.array(monomer_b._open) - np.array(monomer_a._open) try: direction = Lattice.get_direction(tuple(vector)) except Exception, e: #logging.debug("get_direction for (%d, %d, %d) - (%d, %d, %d): (%d, %d, %d)" % (monomer_b._open, monomer_a._open, vector)) raise e
def process(file, step=None, output_file=None): if isinstance(file, str): f = open(file) else: f = file try: line = f.readlines() nr = int(line[0].replace("\n", "")) except: print line sys.exit(1) data = np.loadtxt(file, dtype=str, skiprows=1) # data = f.readlines()[1:] point_monomer = {} monomer_list = [] position_set = set() if parser.scale == -1 and "." in data[0]: print "Atom position are float, please set -scale parameter to rescale them!" sys.exit(1) for line in data: # tmp = line.replace("\n","").split(" ") type = line[0] ll = map(float, line[1:]) x = int(ll[0] * scale) y = int(ll[1] * scale) z = int(ll[2] * scale) position = (x, y, z) m = DummyMonomer(position, type, Lattice.get_neighbours(tuple(position))) point_monomer[position] = m monomer_list.append(m) position_set.add(position) return point_monomer, monomer_list, position_set
def pull_move(self, monomer_idx = None): """ Pull move, N. Lesh, M. Mitzemacher, S. Whitesides """ ## flags valid_configuration = False if settings.DEBUG: self.valid_chain() #if monomer_idx is None: monomer_idx = randrange(0, self._total_length - 1) ## two special cases at the begin/end case = 3 old_energy = self.total_energy is_occupied = self.box.is_occupied is_neighbour = self.box.lattice.is_neighbour ## trials with optimization last_affected_idx = 0 # case # 0 - left # 1 - right # 3 - inside # 0 - right # 1 - left #mod_pos = 0 if monomer_idx == 0: ## left dir_1 = randrange(0, Lattice.z) dir_2 = randrange(0, Lattice.z) pos_1 = self.chain[0].neighbours_position[dir_1] pos_2 = self.box.lattice.get_coordinate(pos_1, dir_2) if is_occupied(pos_1) or is_occupied(pos_2): return False #if not is_neighbour(pos_1, pos_2): # return False m1 = self.chain[0] m2 = self.chain[1] open_pos_1 = self.box.lattice.get_open_coordinate(m1._open, dir_1) open_pos_2 = self.box.lattice.get_open_coordinate(open_pos_1, dir_2) old_position_list = self.positions_list[:] #old_monomer_position = [ m._position for m in self.chain ] old_monomer_position = old_position_list old_monomer_open_position = [ m._open for m in self.chain ] old_monomer_next_direction = [ m.next_direction for m in self.chain ] m1.position = pos_2 m1._open = open_pos_2 m2.position = pos_1 m2._open = open_pos_1 ## old energy #self[0] = m1 m1.chain = self self.chain[0] = m1 self.positions_list[0] = m1._position #self[1] = m2 m2.chain = self self.chain[1] = m2 self.positions_list[1] = m2._position #mod_pos = 2 for idx in xrange(2, self._total_length): i_monomer = self.chain[idx] p_monomer = self.chain[idx - 1] diff = np.array(i_monomer._open) - np.array(p_monomer._open) diff = diff.dot(diff) if diff == 2: p_monomer.next_direction = p_monomer.neighbours_position.index(i_monomer._position) break #mod_pos += 1 i_monomer.position = old_monomer_position[idx - 2] i_monomer._open = old_monomer_open_position[idx - 2] i_monomer.next_direction = old_monomer_next_direction[idx - 2] #self[idx] = i_monomer i_monomer.chain = self self.chain[idx] = i_monomer self.positions_list[idx] = i_monomer._position last_affected_idx = idx self.chain[0].next_direction = self.chain[0].neighbours_position.index(self.chain[1]._position) self.chain[1].next_direction = self.chain[1].neighbours_position.index(self.chain[2]._position) case = 0 if settings.DEBUG: self.valid_chain() elif monomer_idx == self._total_length - 1: ## right dir_1 = randrange(0, Lattice.z) dir_2 = randrange(0, Lattice.z) pos_1 = self.chain[-1].neighbours_position[dir_1] pos_2 = self.box.lattice.get_coordinate(pos_1, dir_2) if is_occupied(pos_1) or is_occupied(pos_2): return False open_pos_1 = self.box.lattice.get_open_coordinate(self.chain[-1]._open, dir_1) open_pos_2 = self.box.lattice.get_open_coordinate(open_pos_1, dir_2) old_position_list = self.positions_list[:] #old_monomer_position = [ m._position for m in self.chain ] old_monomer_position = old_position_list old_monomer_open_position = [ m._open for m in self.chain ] old_monomer_next_direction = [ m.next_direction for m in self.chain ] m1 = self.chain[-1] m2 = self.chain[-2] m1.position = pos_2 m1._open = open_pos_2 m2.position = pos_1 m2._open = open_pos_1 #mod_pos = 2 for idx in xrange(self._total_length - 2, -1, -1): i_monomer = self.chain[idx] n_monomer = self.chain[idx+1] diff = np.array(i_monomer._open) - np.array(n_monomer._open) diff = diff.dot(diff) if diff == 2: i_monomer.next_direction = i_monomer.neighbours_position.index(n_monomer._position) break #mod_pos += 1 i_monomer.position = old_monomer_position[idx + 2] i_monomer._open = old_monomer_open_position[idx + 2] i_monomer.next_direction = old_monomer_next_direction[idx + 2] #self[idx] = i_monomer i_monomer.chain = self self.chain[idx] = i_monomer self.positions_list[idx] = i_monomer._position last_affected_idx = idx case = 1 self.chain[-2].next_direction = self.chain[-2].neighbours_position.index(self.chain[-1]._position) self.chain[-1].next_direction = 0 if settings.DEBUG: self.valid_chain() if case == 3: prev_monomer = self.chain[monomer_idx - 1] monomer = self.chain[monomer_idx] next_monomer = self.chain[monomer_idx + 1] random_neighbour_prev = randrange(0, Lattice.z) #if self.box.is_occupied(prev_monomer.neighbours_position[random_neighbour_prev]): # return False #L can be adjenct to i-1 or i+1, randomly choose sub_case = randrange(0, 2) ## 0 - right, 1 - left if sub_case == 0: L_position = next_monomer.neighbours_position[random_neighbour_prev] L_open_position = Lattice.get_open_coordinate(next_monomer._open, random_neighbour_prev) Lnext_direction = self.box.lattice.get_neighbours(L_position).index(next_monomer._position) elif sub_case == 1: L_position = prev_monomer.neighbours_position[random_neighbour_prev] L_open_position = Lattice.get_open_coordinate(prev_monomer._open, random_neighbour_prev) Lprev_direction = self.box.lattice.get_neighbours(L_position).index(prev_monomer._position) C_position = monomer.neighbours_position[random_neighbour_prev] C_open_position = Lattice.get_open_coordinate(monomer._open, random_neighbour_prev) diff = np.array(L_position) - np.array(C_position) diff = diff.dot(diff) if diff != 2: return False if is_occupied(L_position): return False if is_occupied(C_position): if (sub_case == 0 and C_position != prev_monomer._position) or (sub_case == 1 and C_position != next_monomer._position): return False # old_energy #old_energy = self.box.calculate_chain_energy(self) # direction L->C C_nb = self.box.lattice.get_neighbours(C_position) CL_direction = C_nb.index(L_position) LC_direction = self.box.lattice.TURN_DIRECTION[CL_direction] # save old position list old_position_list = self.positions_list[:] #old_monomer_position = [ m._position for m in self.chain ] old_monomer_position = old_position_list old_monomer_open_position = [ m._open for m in self.chain ] old_monomer_next_direction = [ m.next_direction for m in self.chain ] if (sub_case == 0 and prev_monomer._position == C_position) or \ (sub_case == 1 and next_monomer._position == C_position): valid_configuration = True monomer.position = L_position monomer._open = L_open_position if sub_case == 0: monomer.next_direction = Lnext_direction elif sub_case == 1: monomer.next_direction = LC_direction #self[monomer_idx] = monomer monomer.chain = self self.chain[monomer_idx] = monomer self.positions_list[monomer_idx] = monomer._position if sub_case == 0: prev_monomer.position = C_position prev_monomer._open = C_open_position prev_monomer.next_direction = CL_direction #self[monomer_idx - 1] = prev_monomer prev_monomer.chain = self self.chain[monomer_idx - 1] = prev_monomer self.positions_list[monomer_idx - 1] = prev_monomer._position elif sub_case == 1: if not valid_configuration: next_monomer.position = C_position next_monomer._open = C_open_position next_monomer.next_direction = self.box.lattice.TURN_DIRECTION[random_neighbour_prev] #self[monomer_idx + 1] = next_monomer next_monomer.chain = self self.chain[monomer_idx + 1] = next_monomer self.positions_list[monomer_idx + 1] = next_monomer._position prev_monomer.next_direction = random_neighbour_prev #self[monomer_idx - 1] = prev_monomer prev_monomer.chain = self self.chain[monomer_idx - 1] = prev_monomer self.positions_list[monomer_idx - 1] = prev_monomer._position #mod_pos = 2 if not valid_configuration: if sub_case == 0: ## right for j in xrange(monomer_idx - 2, -1, -1): j_monomer = self.chain[j] i_monomer = self.chain[j+1] diff = np.array(j_monomer._open) - np.array(i_monomer._open) diff = diff.dot(diff) if diff == 2: j_monomer.next_direction = j_monomer.neighbours_position.index(i_monomer._position) break #mod_pos += 1 j_monomer.position = old_monomer_position[j+2] j_monomer._open = old_monomer_open_position[j+2] j_monomer.next_direction = j_monomer.neighbours_position.index(i_monomer._position) #self[j] = j_monomer j_monomer.chain = self self.chain[j] = j_monomer self.positions_list[j] = j_monomer._position elif sub_case == 1: for j in xrange(monomer_idx + 2, self._total_length): j_monomer = self.chain[j] i_monomer = self.chain[j-1] diff = np.array(j_monomer._open) - np.array(i_monomer._open) diff = diff.dot(diff) if diff == 2: i_monomer.next_direction = i_monomer.neighbours_position.index(j_monomer._position) break #mod_pos += 1 j_monomer.position = old_monomer_position[j-2] j_monomer._open = old_monomer_open_position[j-2] i_monomer.next_direction = i_monomer.neighbours_position.index(j_monomer._position) #self[j] = j_monomer j_monomer.chain = self self.chain[j] = j_monomer self.positions_list[j] = j_monomer._position if settings.DEBUG: self.valid_chain() ## end move procedure # old_energy, emergency case new_energy = self.box.calculate_chain_energy(self) dE = new_energy - old_energy accept_move = False if dE <= 0.0 or self.box.athermal_state: accept_move = True else: accept_move = self.box.accept(dE, None) if accept_move is True: self.total_energy = new_energy #self.positions_list = [ m._position for m in self.chain ] self.box.global_energy_update([self.idx]) #f = open("mod_pos_%d" % self._total_length, "w+") #f.write("%d\n" % mod_pos) #f.close() #self.valid_chain() else: ## revert if case == 3: if sub_case == 0: monomer_list = xrange(0, monomer_idx+2) elif sub_case == 1: monomer_list = xrange(monomer_idx-1, self._total_length) elif case == 0: monomer_list = xrange(0, self._total_length) elif case == 1: ## monomer_list = xrange(0, self._total_length) #monomer_list = changed_monomer_idx for idx in monomer_list: m = self.chain[idx] old_pos = old_monomer_position[idx] old_dir = old_monomer_next_direction[idx] if m._position != old_pos or m.next_direction != old_dir: m.position = old_monomer_position[idx] m._open = old_monomer_open_position[idx] m.next_direction = old_monomer_next_direction[idx] #self[idx] = m m.chain = self self.chain[idx] = m self.positions_list[idx] = m._position #self.positions_list = old_position_list[:] self.total_energy = old_energy #self.valid_chain() return accept_move
def _snake(self, move_type): """ Snake move """ #direction_to_choice = range(0, Lattice.z) if settings.DEBUG: self.valid_chain() if move_type == 0: monomer = self.chain[0] elif move_type == 1: monomer = self.chain[-1] #random new position random_direction = randrange(0, Lattice.z) new_position = monomer.neighbours_position[random_direction] open_position = Lattice.get_open_coordinate(monomer._open, random_direction) if self.box.is_occupied(new_position) or new_position in self.positions_list: return False # copy old_position_list = self.positions_list[:] old_open_position_list = [ x._open for x in self.chain ] old_next_direction_list = [ x.next_direction for x in self.chain ] old_energy = self.total_energy self.positions_list = [] """ Update position of monomers in chain (copy) """ if move_type == 0: # left self.positions_list = [new_position] for idx in range(1, self._total_length): self.chain[idx].position = old_position_list[idx - 1] self.chain[idx]._open = old_open_position_list[idx - 1] self.chain[idx].next_direction = old_next_direction_list[idx - 1] self.positions_list += old_position_list[0: self._total_length - 1] self.chain[0].position = new_position self.chain[0]._open = open_position self.chain[0].next_direction = self.box.lattice.TURN_DIRECTION[random_direction] elif move_type == 1: # right for idx in range(0, self._total_length - 1): self.chain[idx].position = old_position_list[idx + 1] self.chain[idx]._open = old_open_position_list[idx + 1] self.chain[idx].next_direction = old_next_direction_list[idx + 1] self.chain[-1].position = new_position self.chain[-1]._open = open_position self.chain[-2].next_direction = random_direction self.positions_list = old_position_list[1:] + [new_position] new_energy = self.box.calculate_chain_energy(self) dE = new_energy - old_energy if dE <= 0.0 or self.box.athermal_state: if settings.DEBUG: self.valid_chain() self.total_energy = new_energy return True elif self.box.accept(dE, None): if settings.DEBUG: self.valid_chain() self.total_energy = new_energy return True else: for idx in xrange(self._total_length): self.chain[idx].position = old_position_list[idx] self.chain[idx]._open = old_open_position_list[idx] self.chain[idx].next_direction = old_next_direction_list[idx] self.positions_list = old_position_list[:] self.total_energy = old_energy if settings.DEBUG: self.valid_chain() return False
if number_of_positions == 0: return False new_position = list(common_neighbours_positions)[randrange(0, number_of_positions)] if not new_position or len(new_position) != 3: if __debug__: logging.debug("New_position %s:" % str(new_position)) return False try: direction = prev_monomer.neighbours_position.index(new_position) except Exception, e: if __debug__: logging.error("Reject segment, error in direction, (%d, %d, %d)" % (new_position)) return False open_position = Lattice.get_open_coordinate(prev_monomer._open, direction) if self.box.is_occupied(new_position): #logging.debug("Reject segment; Position: (%d, %d, %d) is occupied" % (new_position)) return False # make copy of old monomer old_position = rotate_monomer._position old_open_position = rotate_monomer._open old_prev_next_direction = self.chain[monomer_idx - 1].next_direction old_next_direction = rotate_monomer.next_direction old_energy = self.total_energy self.chain[monomer_idx].position = new_position self.chain[monomer_idx]._open = open_position
def random_strategy(self, chain): """ Put chain in random mode """ random_point = tuple(map(lambda x: x/2, self.box_size)) while self.is_occupied(random_point) or not Lattice.is_valid_coordinate(random_point): random_point = tuple([ random.randrange(0, self.box_size[x]) for x in range(3) ]) if __debug__: logging.info("Chain start point: %d, %d, %d" % random_point) f_monomer = chain.chain[0] f_monomer.position = random_point f_monomer._open = random_point chain[0] = f_monomer for idx in range(1, chain._total_length): prev_monomer = chain.chain[idx - 1] monomer = chain.chain[idx] not_found = True direction_list = range(0, Lattice.z) direction_list_idx = Lattice.z while not_found: try: direction_idx = random.randrange(0, direction_list_idx) except: return False direction = direction_list[direction_idx] pos = Lattice.get_coordinate(prev_monomer._position, direction) open_pos = Lattice.get_open_coordinate(prev_monomer._open, direction) if pos in chain.positions_list or \ (self.number_of_chains > 1 and self.is_occupied(pos)): not_found = True direction_list.remove(direction) direction_list_idx -= 1 else: not_found = False monomer.position = pos monomer.open_position = open_pos #monomer.next_direction = None prev_monomer.next_monomer = monomer prev_monomer.next_direction = direction chain[idx] = monomer chain.chain[idx-1] = prev_monomer ## rebuild directions for idx in range(1, chain._total_length): p = chain.chain[idx - 1] m = chain.chain[idx] d = p.neighbours_position.index(m._position) p.next_direction = d chain.chain[idx - 1].next_direction = d chain.chain[-1].next_direction = 0 if __debug__: logging.info('Chain inside box, length=%d' % chain.length) return chain
def greedy_strategy(self, chain): """ Put chain in the box based on a greedy strategy """ random_point = tuple(map(lambda x: x/2, self.box_size)) while self.is_occupied(random_point) or not Lattice.is_valid_coordinate(random_point): random_point = tuple([ random.randrange(0, self.box_size[x]) for x in range(3) ]) f_monomer0 = chain.chain[0] f_monomer0.position = random_point f_monomer0._open = random_point chain[0] = f_monomer0 next_direction = random.randrange(0, Lattice.z) f_monomer1 = chain.chain[1] f_monomer1.position = Lattice.get_coordinate(random_point, next_direction) f_monomer1._open = Lattice.get_open_coordinate(random_point, next_direction) chain[1] = f_monomer1 chain[0].next_direction = next_direction pos_list = [f_monomer0._position, f_monomer1._position] direction_list = range(0, Lattice.z) for idx in range(2, chain._total_length): prev_monomer = chain.chain[idx - 1] monomer = chain.chain[idx] min_energy = self.calculate_chain_energy(chain) min_pos = None min_open_pos = None min_dir = 0 np.random.shuffle(direction_list) last_valid_pos = None last_valid_open_pos = None for dir in direction_list: pos = Lattice.get_coordinate(prev_monomer._position, dir) open_pos = Lattice.get_open_coordinate(prev_monomer._open, dir) if pos in chain.positions_list or \ (self.number_of_chains > 1 and self.is_occupied(pos)) or \ pos in pos_list: pass else: last_valid_pos = pos last_valid_open_pos = open_pos monomer.position = pos monomer._open = open_pos chain[idx] = monomer m_e = self.calculate_chain_energy(chain, slice=[0, idx+1]) if min_energy > m_e: min_energy = m_e min_pos = pos min_open_pos = open_pos min_dir = dir monomer.position = min_pos if min_pos else last_valid_pos monomer._open = min_open_pos if min_open_pos else last_valid_open_pos chain[idx] = monomer prev_monomer.next_direction = min_dir chain[idx - 1] = prev_monomer ## rebuild directions for idx in range(1, chain._total_length): p = chain.chain[idx - 1] m = chain.chain[idx] d = p.neighbours_position.index(m._position) p.next_direction = d chain.chain[idx - 1].next_direction = d if __debug__: logging.info("Greedy strategy, chain with min energy: %f" % \ self.calculate_chain_energy(chain)) return chain