def get_range(prompt, min_value=None, max_value=None, value_type=float): """ Get a range (np.array) of values. Optionally constrain the range between min_value and max_value, or force a value_type for the first and last numbers. """ disp(prompt) first = get_number("First number: ", min_value, max_value, value_type) last = get_number("Last number: ", min_value, max_value, value_type) if first == last: return [first] values = get_number("Number of values: ", 1, None, int) return np.linspace(first, last, values).tolist()
def get_number(prompt, min_value=None, max_value=None, value_type=float): """ Get numeric input. Optionally have a min_value and max_value for the number, or force the number to be value_type = int. """ if value_type not in (float, int): raise ValueError( "Numeric type must be float or int, not {}.".format(value_type)) do = True while do: try: answer = value_type(get(prompt)) except ValueError: pass else: if min_value is not None and answer < min_value: disp("Value must be greater than or equal to {}.".format( min_value)) elif max_value is not None and answer > max_value: disp("Value must be less than or equal to {}.".format( max_value)) else: do = False return answer
def get_file(prompt, directory, new_file=False, fetch_pdb=False): """ Get a filename that exists within a given directory. new_file: if True, file must be a valid but non-existant path. fetch_pdb: if True, if the file does not exist but is a valid PDB id, then download the PDB to directory. """ # The directory must exist. if not os.path.isdir(directory): raise OSError("Directory does not exist: {}".format(directory)) if new_file: # In this mode, a new file must be specified. do = True while do: base_file = get(prompt) # name of the new file full_file = os.path.join(directory, base_file) # full path to the new file if os.path.exists(full_file): # A new file may not overwrite an existing file. disp("Cannot create file, path already exists: {}".format( full_file)) else: # Ensure the name of the file is a valid path. if standards.is_path_component(base_file): file_directory = os.path.dirname(full_file) # Ensure the directory in which the file will be written exists. if os.path.isdir(file_directory): # If so, then the file path is valid: return it. do = False else: disp( "Cannot create file, directory does not exist: {}". format(file_directory)) else: disp( "Only the following characters are permitted in path components: {}" .format(standards.AllowedPathCharacters)) return full_file else: # In this mode, an existing file must be specified. do = True while do: name = get(prompt) # name of the file if name in os.listdir(directory): # If the file exists, then nothing more must be done: return the file path. do = False elif fetch_pdb: try: # If the file does not exist but fetch_pdb is True, then try to download the PDB. PDBList().retrieve_pdb_file(name, pdir=directory, file_format="pdb") # PDBs are downloaded in this file name format. temp_name = os.path.join(directory, "pdb{}.ent".format(name)) # Rename the file to PDBID.pdb name += ".pdb" os.rename(temp_name, os.path.join(directory, name)) # If that worked, return the path to the PDB file. do = False except: disp("Could not fetch PDB '{}'".format(name)) else: disp("File does not exist '{}'".format(name)) # Return the path to the file. return os.path.join(directory, name)
def select_from_list(prompt, list_, min_number=None, max_number=None, names=None): """ Select between min_number and max_number of items from a list. If names is given, list element names are replaced with names. """ n = len(list_) if isinstance(list_, dict): # If the list is given as a dict: if names is None: # If names is not given, use the keys as names and the values as the items in the list. names = map(str, list_.keys()) list_ = list_.values() else: # Otherwise, discard the values and use the keys. list_ = list_.keys() if names is None: # If names is not specified, then convert the list items to strings and use them as names. names = map(str, list_) else: # Ensure that the number of names matches the number of items in the list. if len(names) != n: raise ValueError("Length of names must equal length of list.") # Strip off whitespace from the names. names = map(string.strip, names) # The minimum number selected cannot be negative. if min_number is None: min_number = 0 else: min_number = max(int(min_number), 0) # The maximum number selected cannot exceed the total number of items. if max_number is None: max_number = n else: max_number = min(int(max_number), n) # The minimum number cannot exceed the maximum number. if min_number > max_number: raise IOError( "Minimum selction {} cannot be greater than maximum selection {}.". format(min_number, max_number)) # If the minumum number equals the number of items, all items must be selected. if min_number == n: disp("Automatically selecting all {n} items from length-{n} list: {l}". format(n=n, l=", ".join(names))) # Return a copy of the list so that things that depend on the lists input and returned being a different objects won't fail. return list(list_) # Initialize to no items selected. items = None # Make a statement of which options are available. permitted = "Options include the following:\n{}".format( disp_list(names, get_string=True)) # Has that statment been displayed yet? permitted_displayed = False # Repeat until a selection has been made. while items is None: # Ask the user to specify items. selection_string = get(prompt) if selection_string.strip() == "": # If the input is blank, say what options are available. disp(permitted) permitted_displayed = True else: # Otherwise, try to parse the input. selection_keys = split_selection_string(selection_string) try: indexes = [ index for key in selection_keys for index in get_selected_indexes(names, key) ] except ValueError: # If parsing fails, then stop parsing and get another input from the user. select_items = False else: # If parsing succeeded, then proceed to the selection step. select_items = True if select_items: # Select the items. selected_items = [list_[index] for index in indexes] # Ensure the number selected meets specifications. if len(selected_items) >= min_number and len( selected_items) <= max_number: # If so, then finalize the selection by setting items = selected_items, which terminates the loop. items = selected_items else: disp("You must select from {} to {} items.".format( min_number, max_number)) else: # Alert that something went wrong with parsing. disp('There was a problem selecting the following items: "{}"'. format(selection_string)) if not permitted_displayed: # If an error occurs and the options have not been displayed yet, then display them. disp(permitted) permitted_displayed = True return items
python check_status [prefix] If prefix is given, then only experiments that begin with the prefix will be listed. """ import cPickle as pkl import os import sys import console import standards console.clear() console.disp("{:<39} {:<39}".format("EXPERIMENT", "STATUS")) console.disp("-" * 80) for experiment in os.listdir(standards.ExperimentsDirectory): if len(sys.argv) > 1: if not any([x in experiment for x in sys.argv[1:]]): continue directory = os.path.join(standards.ExperimentsDirectory, experiment) errors = os.path.join(directory, "errors.txt") pickle = os.path.join(directory, ".temp", "{}.pickle".format(experiment)) summary = os.path.join(directory, "Summary.txt") results = os.path.join(directory, "Results.csv") if os.path.isfile(errors): status = "ERROR: see errors.txt" else: if all([os.path.isfile(x) for x in [summary, results]]): status = "Completed"
def get_structure(self, file_name=None): """ Load a structure from a file. """ # The file doesn't need to be the filename associated with the molecule. # Molecules can be used to load structures from any PDB or MMCIF file. if file_name is None: file_name = self.file structure = get_parser(file_name).get_structure(self.name, file_name) # OptMAVEn currently can only handle structures with one model. models = Selection.unfold_entities(structure, "M") if len(models) != 1: raise NotImplementedError( "Optmaven cannot currently handle structures with {} models.". format(len(models))) # Optionally, exclude heteroatoms from the structure. Only do this the first time this molecule loads a structure. if self.exclude_hetero in [ standards.HetAtmAsk, standards.HetAtmExclude ] and self.excluded_residue_ids is None: self.excluded_residue_ids = dict() # Loop through the chains. for chain in Selection.unfold_entities(models[0], "C"): # Identify any heteroatoms. hetero_residues = [ residue for residue in chain if residue.get_id()[0] != " " ] hetero_residue_ids = [ residue.get_id() for residue in hetero_residues ] if len(hetero_residue_ids) > 0: # If there are heteroatoms: if self.exclude_hetero == standards.HetAtmAsk: # If the user can decide whether or not to exclude them, then ask. disp("Excluding hetero-residues from chain {}.".format( chain.get_id())) self.excluded_residue_ids[chain.get_id()] = set( user_input.select_from_list( "Please select hetero-residues to exclude from {}: " .format(self.name), hetero_residue_ids, names=map(residue_code, hetero_residues))) elif self.exclude_hetero == standards.HetAtmExclude: # Otherwise, exclude heteroatoms automatically. self.excluded_residue_ids[ chain.get_id()] = hetero_residue_ids else: raise ValueError( "Bad value for heteroatom exclusion: {}".format( self.exclude_hetero)) elif self.exclude_hetero not in standards.HetAtmOptions: raise ValueError("Bad value for heteroatom exclusion: {}".format( self.exclude_hetero)) if self.excluded_residue_ids is not None: # The previous step just identified residues to exclude. # This step actually removes them from the structure. for chain in Selection.unfold_entities(models[0], "C"): exclude = self.excluded_residue_ids.get(chain.get_id()) if exclude is not None: for res_id in exclude: try: chain.detach_child(res_id) except KeyError: pass return structure