def set_scores(self, molecule): """Clean and Parse score information for provided molecule.""" molecule.min_atom_score = float('inf') molecule.max_atom_score = float('-inf') num_rgx = r'(-?[\d.]+(?:e[+-]\d+)?)' pattern = re.compile( '<{},{},{}> {} {} {} {} {}'.format(*([num_rgx] * 8)), re.U) for associated in molecule.associateds: # make the labels pretty :) associated['Minimized Affinity'] = associated.pop( '> <minimizedAffinity>') associated['Atomic Interaction Terms'] = associated.pop( '> <atomic_interaction_terms>') pose_score = associated['Minimized Affinity'] for residue in molecule.residues: residue.label_text = pose_score + " kcal/mol" # TODO: Re-enable this when core-bug with frame labels is fixed. # https://nanome.slack.com/archives/CBDV1975K/p1641410333253500 residue.labeled = False interaction_terms = associated['Atomic Interaction Terms'] interaction_values = re.findall(pattern, interaction_terms) for i, atom in enumerate(molecule.atoms): if i < len(interaction_values) - 1: Logs.debug("interaction values for atom " + str(i) + ": " + str(interaction_values[i])) atom.score = float(interaction_values[i][5]) molecule.min_atom_score = min(atom.score, molecule.min_atom_score) molecule.max_atom_score = max(atom.score, molecule.max_atom_score)
def load_molecule(self, name, callback=None): complex_name = '.'.join(name.split(".")[:-1]) extension = name.split(".")[-1] file_path = os.path.join(self.current_dir, name) if extension == "pdb": complex = Complex.io.from_pdb(path=file_path) complex.name = complex_name self.add_bonds([complex], partial(self.bonds_ready, callback=callback)) elif extension == "sdf": complex = Complex.io.from_sdf(path=file_path) complex.name = complex_name self.bonds_ready([complex], callback) elif extension == "cif": complex = Complex.io.from_mmcif(path=file_path) complex.name = complex_name self.add_bonds([complex], partial(self.bonds_ready, callback=callback)) elif extension in ["ppt", "pptx", "odp", "pdf"]: self.display_ppt(file_path, callback) elif extension in ["png", "jpg"]: self.display_image(file_path, callback) else: Logs.warning("Unknown file extension for file", name) return
def on_run(self): self.set_to_refresh() self.open_matryx_menu() self.defer(self.populate_all_tournaments, 60) # self.print_node(self._menu_matryx.root) Logs.debug('requesting directory...') self.request_directory('/', self.on_directory_received)
def on_stream_creation(stream, error): if error != StreamCreationError.NoError: Logs.error("Error while creating stream") return self.__stream = stream self.__data_queue = deque() cwd_path = self.__nanobabel_dir exe = 'nanobabel.exe' if IS_WIN else 'nanobabel' exe_path = os.path.join(cwd_path, exe) args = [ 'minimize', '-h', '-l', '20', '-n', str(steps), '-ff', ff, '-i', input_file.name, '-cx', constraints_file.name, '-o', output_file.name ] if IS_WIN: args += ['-dd', 'data'] if steepest: args.append('-sd') Logs.debug(args) p = Process(exe_path, args, True) p.on_error = self.__on_process_error p.on_output = self.__on_process_output p.on_done = self.__on_process_done p.start() self.__process = p self.__process_running = True self._is_running = True
def update_score(self, value=None): Logs.debug("update score called: ", value) if value is None: self.rmsd_score_label.text_value = "--" else: self.rmsd_score_label.text_value = str("%.3g" % value) self._plugin.update_content(self.rmsd_score_label)
def load_request(self, button=None): if not self.request: self.plugin.send_notification(nanome.util.enums.NotificationTypes.message, "Please select a request") return self.save_fields_to_vars() self.set_load_enabled(False) results = {} for i, step in enumerate(self.request['steps']): resource = self.settings.get_resource(step['resource']) import_type = resource['import type'] metadata = step['metadata_source'] data = resource['data'].replace("\'", "\"") # override data if necessary data_override_field_name = f"{self.request['name']} {step['name']} data" if step['override_data']: data = self.fields[data_override_field_name] contexts = [self.fields, results, self.settings.variables] response = self.get_response(resource, contexts, data) var_uid, var_value = self.settings.get_output_variable(resource, 0) if not response: self.plugin.send_notification(nanome.util.enums.NotificationTypes.error, f"Step {i} failed. Aborting {self.request['name']}") self.set_load_enabled(True) return results[f'step{i+1}'] = json.dumps(var_value) or response.text Logs.debug(f'setting step{i+1} to {var_value} ({self.settings.variables[var_uid][0]})') if import_type: import_name = self.contextualize(variable=resource['import name'], contexts=contexts) self.import_to_nanome(import_name, import_type, var_value or response.text, metadata) self.set_load_enabled(True)
def load_accounts(self): if not self.__class__.enable_accounts: return try: with open(AUTH_PATH, 'r') as f: self.accounts = [] for line in f.readlines(): account = line.rstrip().split(' ') if len(account) != 3: Logs.warning('Invalid account entry: \n' + line) continue self.accounts.append(account) except: # create default accounts file if none exists self.accounts = [['admin', 'admin', '1']] changed = False for account in self.accounts: if not md5re.match(account[1]): # password isn't hashed, hash it account[1] = md5(account[1].encode()).hexdigest() changed = True if changed: self.save_accounts()
def __update_secondary_structure(self, complex): molecules = complex._molecules if len(molecules) != len(self.__current_complex_result): Logs.debug("[DSSP] Complex", complex._name, ": Molecule count", len(molecules), "doesn't match DSSP count", len(self.__current_complex_result)) return for i in range(len(self.__current_complex_result)): secondary = self.__current_complex_result[i] molecule = molecules[i] residues = dict() for chain in molecule._chains: residues[chain._name] = dict() for residue in chain._residues: residues[chain._name][residue._serial] = residue for dssp_info in secondary: try: chain = residues[dssp_info[0]] residue = chain[dssp_info[1]] structure_type = dssp_info[2] if structure_type == " ": residue._secondary_structure = _Residue.SecondaryStructure.Coil elif structure_type == "E": residue._secondary_structure = _Residue.SecondaryStructure.Sheet elif structure_type == "H": residue._secondary_structure = _Residue.SecondaryStructure.Helix except: Logs.debug("[DSSP] Key not found:", dssp_info[0], dssp_info[1], traceback.format_exc())
def menu(self): if not self.__set_first: self.__set_first = True Logs.warning( "The default menu (self.menu) is now deprecated and will be removed in a future version. Please use the ui.Menu() constructor to create the menu." ) return self.__menu
def decontextualize(self, json, contexts=[], left_wrapper="{{", right_wrapper="}}", k_or_v=False): def replace(json, old, new, k_or_v=False): newd = {} for k, v in json.items(): if k_or_v: if v == old: newd[k] = new else: newd[k] = v if isinstance(v, dict): v = replace(v, old, new, k_or_v) if not k_or_v: if k == old: newd[new] = v else: newd[k] = v return newd if not contexts: contexts = [self.variable_values] for context in contexts: for var_value, var_names in context.items(): Logs.debug(f'replacing {var_value} with {var_names[0]}') json = replace(json, var_value, left_wrapper + var_names[0] + right_wrapper, k_or_v) return json
def start(self): self.make_tracking_atoms() self.make_menu() import time time.sleep(5) Logs.debug("requesting complexes") self.request_complex_list(self.connect_complexes)
def _display_selected(workspace): paths_names = self.write_selection(workspace) self._paths_selected = len(paths_names) self.set_display(len(paths_names) != 0) self._list.items = [] for path_name in paths_names: self._workpaths[path_name[0]] = True Logs.debug('filename:', path_name[1]) clone = self._prefab_entry.clone() clone.find_node( 'Label').get_content().text_value = path_name[1] icon_ln = clone.find_node('Selected Icon') icon_ln.add_new_image(self._icon_path) icon_ln.selected = True icon_ln.path = path_name[0] clone.get_content().register_pressed_callback( partial(self.toggle_selected, icon_ln)) self._list.items.append(clone) if self._is_component: self._ln_cancel.enabled = False self._plugin.refresh_menu() else: self._ln_cancel.enabled = True self._plugin.open_menu(self._menu)
def write_json(helper, content): if (content is None): return None elif (isinstance(content, _Button)): type_name = "Button" _button_json.write_json(helper, content) elif (isinstance(content, _Mesh)): type_name = "Mesh" _mesh_json.write_json(helper, content) elif (isinstance(content, _Slider)): type_name = "Slider" _slider_json.write_json(helper, content) elif (isinstance(content, _TextInput)): type_name = "TextInput" _text_input_json.write_json(helper, content) elif (isinstance(content, _Label)): type_name = "Label" _label_json.write_json(helper, content) elif (isinstance(content, _UIList)): type_name = "List" _ui_list_json.write_json(helper, content) elif (isinstance(content, _Image)): type_name = "Image" _image_json.write_json(helper, content) elif (isinstance(content, _LoadingBar)): type_name = "LoadingBar" _loading_bar_json.write_json(helper, content) else: Logs.error("unknown content type: " + str(type(content))) return None helper.write("type_name", type_name)
def init_hashes(): hashes = dict() i = -1 for command in _Commands: i += 1 hash = hash_command(command.name) if hash in hashes: Logs.error("Command hash collision detected:", command.name, "and", hashes[hash]) continue hashes[hash] = command.name _Hashes.CommandHashes[i] = hash hashes.clear() i = -1 for command in _Messages: i += 1 hash = hash_command(command.name) if hash in hashes: Logs.error("Message hash collision detected:", command.name, "and", hashes[hash]) continue hashes[hash] = command.name _Hashes.MessageHashes[i] = hash
async def _run_docking(self): receptor = self._selected_receptor ligands = self._selected_ligands site = None if self._selected_site: site = self._selected_site if not receptor or not ligands: if self._selected_site is None: Logs.warning( "Trying to run docking without having one receptor, one site and at least one ligand selected" ) return self.loading_bar.percentage = 0 self.enable_loading_bar() self.make_plugin_usable(False) try: await self._plugin.run_docking(self._selected_receptor, ligands, site, self.get_params()) except Exception as e: message = f'{type(e).__name__}: {next(iter(e.args), "Error Occurred. Please Check Logs.")}' Logs.error(message) self._plugin.send_notification(NotificationTypes.error, message) self.make_plugin_usable(True) self.enable_loading_bar(False)
def __start_process(self): entry = self.__pending.popleft() entry.send(_ProcessManager.process_data_type_starting, []) request = entry.request args = [request.executable_path] + request.args has_text = entry.output_text def enqueue_output(out, err, queue_out, queue_err, text): if text: sentinel = '' else: sentinel = b'' for line in iter(err.readline, sentinel): queue_err.put(line) err.close() for line in iter(out.readline, sentinel): queue_out.put(line) out.close() try: entry.process = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1, cwd=request.cwd_path, universal_newlines=has_text, close_fds=POSIX) Logs.debug("Process started:", request.executable_path, "for session", entry.session._session_id) except: Logs.error("Couldn't execute process", request.executable_path, "Please check if executable is present and has permissions:\n", traceback.format_exc()) entry.send(_ProcessManager.process_data_type_done, [-1]) return entry.stdout_queue = Queue() entry.stderr_queue = Queue() thread = Thread(target=enqueue_output, args=(entry.process.stdout, entry.process.stderr, entry.stdout_queue, entry.stderr_queue, has_text)) thread.daemon = True thread.start() self.__running.append(entry)
def do_DELETE(self): try: parsed_url = urlparse(self.path) path = parsed_url.path path = urllib.parse.unquote(path) except: Logs.warning("Error trying to parse request:\n", traceback.format_exc()) self._send_json_error(200, "Parsing problem") return if not path.startswith('/files'): self._send_json_error(403, "Forbidden") return path = path[7:] if not path: self._send_json_error(403, "Forbidden") return path = os.path.join(FILES_DIR, path) try: if os.path.isfile(path): os.remove(path) else: shutil.rmtree(path) except: self._send_json_error(200, "Cannot find file to delete") return self._send_json_success()
def _rpc_request(self, function_name, args=None, kwargs=None): """Publish an RPC request to redis, and await response. :rtype: data returned by PluginInstance function called by RPC. """ args = args or [] kwargs = kwargs or {} fn_definition = api_function_definitions[function_name] serialized_args = [] serialized_kwargs = {} for arg_obj, arg_definition in zip(args, fn_definition.params): if isinstance(arg_definition, schemas.Schema): ser_arg = arg_definition.dump(arg_obj) elif isinstance(arg_definition, fields.Field): # Create object with arg value as attribute, so we can validate. temp_obj = type('TempObj', (object, ), {'val': arg_obj}) ser_arg = arg_definition.serialize('val', temp_obj) serialized_args.append(ser_arg) # Set random channel name for response response_channel = str(uuid.uuid4()) message = json.dumps({ 'function': function_name, 'args': serialized_args, 'kwargs': serialized_kwargs, 'response_channel': response_channel }) Logs.message( f"Sending {function_name} Request to Redis Channel {self.channel}") # Subscribe to response channel before publishing message pubsub = self.redis.pubsub(ignore_subscribe_messages=True) pubsub.subscribe(response_channel) self.redis.publish(self.channel, message) timeout = 10 start_time = time.time() while True: message = pubsub.get_message() if time.time() >= start_time + timeout: raise TimeoutError( f"Timeout waiting for response from RPC {function_name}") if not message: continue if message.get('type') == 'message': response_channel = next(iter( pubsub.channels.keys())).decode('utf-8') Logs.message( f"Response received on channel {response_channel}") message_data_str = message['data'].decode('utf-8') response_data = json.loads(message_data_str) pubsub.unsubscribe() output_schema = fn_definition.output if output_schema: deserialized_response = output_schema.load(response_data) else: deserialized_response = None return deserialized_response
def start_simulation(self): Logs.debug("Start Simulation") self.__start = timer() self.running = True self.__stream = None self.__menu.change_state(True) self.request_complexes(self._selected_complexes, self.on_complexes_received)
def parse_value(str, parser): if parser == None: return str try: return parser(str) except: Logs.error("Wrong value:", str, "\nExpected:", parser) sys.exit(1)
def deserialize(self, version, context): ui_type = _UIBaseSerializer.ContentType(context.read_uint()) try: serializer = _UIBaseSerializer.registered_serializers[ui_type] except: Logs.error("Trying to deserialize unknown UI type:", ui_type) return return context.read_using_serializer(serializer)
def get_exception(self, default_error, pattern=".*?([\w ]*Error:[\w ]*)"): exc = traceback.format_exc() Logs.debug(exc) exc_lines = re.findall(pattern, exc, re.MULTILINE) if not len(exc_lines) or len(exc_lines[0]) < 15: return default_error else: return exc_lines[0]
def main(): if not NANOBABEL: Logs.error('Error: nanobabel not found, please set NANOBABEL env var') sys.exit(1) plugin = nanome.Plugin("Minimization", "Run minimization on selected structures. See Advanced Parameters for forcefield, number of steps, and steepest descent", "Minimization", True) plugin.set_plugin_class(Minimization) plugin.run()
def upload_files(self, paths): files = [] for path in paths: files.append(('files', open(path, 'rb'))) response = requests.post(self._url + '/upload/files', files=files) ipfs_hash = response.json()['data']['hash'] Logs.debug('ipfs hash', ipfs_hash) return ipfs_hash
def on_complexes_received(self, complexes): Logs.debug("Requested complexes") for complex in complexes: if (complex is None): Logs.debug("None received") else: complex.locked = True self.label_all(complex) self.update_structures_deep([complex])
def run_test_group(test, options = TestOptions()): Logs.debug("runnning test group", test.__name__) counter = TestCounter() test.run(counter) Logs.debug("tests passed: ", str(counter.passed)+"/"+str(counter.total)) if (counter.passed < counter.total): return False else: return True