Source code for pimms.data_structures

## ...........................................................................
## 
## PIMMS (Polymer Interactions in Multicomponent Mixtures)
## Alex Holehouse, Pappu Lab, Holehouse Lab
## Copyright 2015 - 2026
## ...........................................................................



##
## Not used yet, but might be a good model for organization going forward
##

import os
from pimms.latticeExceptions import UnfinishedCodeException, KeyFileException
from pimms import pimmslogger

[docs] class AnalysisSettings: """ Lightweight container for on-the-fly analysis configuration. Holds settings used by the analysis machinery during a simulation, currently just the cluster-size threshold. """ def __init__(self, cluster_threshold): """ Initialize the analysis settings container. Parameters ---------- cluster_threshold : int Threshold cluster size used by clustering analysis routines. """ self.cluster_threshold = cluster_threshold
[docs] class FreezeFile: """ Reader/container for a simulation freeze file. Parses a freeze file (see :meth:`__init__` for the file format) and exposes the set of frozen chain IDs (and, in future, bead IDs) so that the simulation can hold those chains fixed during sampling. """ # ........................................................................... # def __init__(self, filename): """ Class for reading and storing information from a freeze file. This is a file which can be used to specify which chains or beads are to be frozen in the simulation. Expected freeze file structure ------------------------------ The freeze file is plain text with one directive per line. Supported directives: - `C <chain_id> <chain_id> ...` Freeze one or more chain IDs. Multiple `C` lines are allowed. Notes: - Empty lines are ignored. - Lines beginning with `#` are ignored. - Inline comments are allowed after `#`. - Duplicate chain IDs are allowed in the file and are deduplicated internally. Current limitation: - `B ...` bead-level directives are recognized but not implemented and will raise `UnfinishedCodeException`. Example: # Freeze two groups of chains C 0 1 2 C 10 11 # Inline comments are also supported C 42 # freeze chain 42 Parameters ---------- filename : str The name of the file to be read """ # check that the file exists if not os.path.isfile(filename): raise KeyFileException(f'Unable to find FREEZE FILE. Passed filename is: {filename}. Please verify the file actually exists') # initialize the chains and beads lists chains = [] beads = [] # open the file and read the contents with open(filename, 'r') as f: content = f.readlines() # cycle through each line for idx, line in enumerate(content): # strip the line of whitespace sline = line.strip() # skip empty lines if len(sline) == 0: continue # skip comment lines if sline[0] == '#': continue # discard comments at the end of the line as well, if they exist sline = sline.split('#')[0].strip() # if this line is reporting on chains (C) if sline[0] == 'C': try: local_chains = [int(i) for i in sline[1:].split()] except: raise ValueError(f'Error parsing chains in freeze file on line {idx}: {line}') chains.extend(local_chains) # if this line is reporting on beads [NOT YET IMPLEMENTED] if sline[0] == 'B': try: local_beads = [int(i) for i in sline[1:].split(' ')] except: raise ValueError(f'Error parsing beads in freeze file on line {idx}: {line}') beads.extend(local_beads) raise UnfinishedCodeException('Beads not yet implemented for freezeing') # remove duplicates self._chains = list(set(chains)) self._beads = list(set(beads)) self._filename = filename # ........................................................................... # @property def chains(self): """ list of int : The deduplicated chain IDs to be frozen. """ return self._chains # ........................................................................... # @property def beads(self): """ list of int : The deduplicated bead IDs to be frozen (bead-level freezing is not yet implemented, so this is typically empty). """ return self._beads # ........................................................................... # @property def filename(self): """ str : The path of the freeze file that was read. """ return self._filename # ........................................................................... #
[docs] def validate_freeze_file(self, latticeObject): """ Function to validate that the chains and beads specified in the freeze file are actually present in the lattice object. Parameters ---------- latticeObject : Lattice The lattice object to be validated against Returns ------- None No return variable, but an exception is raised if the freeze file is not valid """ # for each chain specified in the freeze file for chainID in self.chains: # if the chain is not present in the lattice object, raise an exception if chainID not in latticeObject.chains: raise KeyFileException(f"\n\nFreeze file {self.filename} specifies chain {chainID} which is present in the lattice object. Lattice object chains are {list(latticeObject.chains.keys())} while freeze file chains are {self.chains}.")
# ........................................................................... #
[docs] def log_freeze_file(self): """ Write a summary of the freeze file to the simulation log. Logs the freeze file path, the number of frozen chains, and the list of frozen chain IDs as STATUS entries. Returns ------- None No return value; entries are appended to the simulation log. """ pimmslogger.log_status(f"Freeze file : {self.filename}", timestamp=False) pimmslogger.log_status(f"Number of frozen chains : {len(self.chains)}", timestamp=False) pimmslogger.log_status(f"Frozen chainIDs : {str(self.chains)}", timestamp=False)
# ........................................................................... # def __str__(self): """ Return a human-readable summary of the frozen chains and beads. Returns ------- str Multi-line string listing the frozen chain and bead IDs. """ s = 'Freeze file:\n' s = s + 'Chains: %s\n'%self.chains s = s + 'Beads: %s\n'%self.beads return s # ........................................................................... # def __repr__(self): """ Return the same summary string as :meth:`__str__`. Returns ------- str Multi-line string listing the frozen chain and bead IDs. """ return self.__str__()