예제 #1
0
    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
예제 #2
0
 async def upload_shapes(self, shape_list):
     for shape in shape_list:
         Logs.message(shape.index)
     response = await nanome.api.shapes.Shape.upload_multiple(shape_list)
     self.shapes.extend(response)
     for shape in shape_list:
         Logs.message(shape.index)
     return shape_list
예제 #3
0
 def connect(self, host, port):
     try:
         self._connection.connect((host, port))
         self._connection.setblocking(False)
         Logs.message("Connected to server", host, port)
     except (ssl.SSLError, socket.error) as e:
         self._socket = None
         self._context = None
         self._connection = None
         Logs.error("Cannot connect to plugin server at", host, port, e)
         return False
     return True
예제 #4
0
 async def on_run(self):
     default_url = os.environ.get('DEFAULT_URL')
     if default_url:
         jupyter_token = os.environ.get('JUPYTER_TOKEN')
         url = f'{default_url}?token={jupyter_token}'
         Logs.message(f'Opening {url}')
         self.open_url(url)
     Logs.message("Polling for requests")
     self.set_plugin_list_button(PluginListButtonType.run,
                                 text='Live',
                                 usable=False)
     await self.poll_redis_for_requests(self.redis_channel)
예제 #5
0
        def loading_bar_callback(button):
            Logs.message("button pressed: " + button.text.value.idle)
            button.text.value.selected = "Button Pressed!"
            button.selected = not button.selected

            self.loadingBar.percentage += .1
            self.loadingBar.title = "TITLE"
            self.loadingBar.description = "DESCRIPTION " + str(
                self.loadingBar.percentage)

            self.update_content(button)
            self.update_content(self.loadingBar)
예제 #6
0
 def message_callback(self, fn_definition, response_channel, response=None):
     """When response data received from NTS, serialize and publish to response channel."""
     output_schema = fn_definition.output
     serialized_response = {}
     if output_schema:
         if isinstance(output_schema, Schema):
             serialized_response = output_schema.dump(response)
         elif isinstance(output_schema, fields.Field):
             # Field that does not need to be deserialized
             serialized_response = output_schema.serialize(response)
     json_response = json.dumps(serialized_response)
     Logs.message(f'Publishing Response to {response_channel}')
     self.rds.publish(response_channel, json_response)
예제 #7
0
    async def start(self):
        # Create Redis channel name to send to frontend to publish to
        redis_channel = os.environ.get('REDIS_CHANNEL')
        self.redis_channel = redis_channel if redis_channel else str(
            uuid.uuid4())
        Logs.message(
            f"Starting {self.__class__.__name__} on Redis Channel {self.redis_channel}"
        )
        self.streams = []
        self.shapes = []

        self.rds = redis.Redis(host=REDIS_HOST,
                               port=REDIS_PORT,
                               password=REDIS_PASSWORD,
                               decode_responses=True)
예제 #8
0
def interactive_mode():
    Logs.message("Setup utility for Nanome Plugins global configuration")
    for i in range(len(config_items)):
        c = config_items[i]
        Logs.message("==============================")
        Logs.message(c['name'] + " (" + c['description'] + ")")
        Logs.message("Current Value:", config.fetch(c['key']))
        str = input("New Value (leave empty if unchanged): ")
        str = str.strip()
        if str == '':
            continue
        value = parse_value(str, c['parse_method'])
        config.set(c['key'], value)
예제 #9
0
def _setup_file():
    s = "/"

    home = os.getenv('APPDATA')
    if (home == None):
        home = os.getenv('HOME')
    directory = home + s + ".nanome_lib"
    config = directory + s + "config.txt"

    if (not os.path.isdir(directory)):
        try:
            os.mkdir(directory)
        except:
            return False
    if (not os.path.isfile(config)):
        try:
            Logs.message("Creating config file with path " + config)
            _setup_clean_config(config)
        except:
            return False
    return config
예제 #10
0
    def process_message(self, message):
        """Deserialize message and forward request to NTS."""
        try:
            data = json.loads(message.get('data'))
        except json.JSONDecodeError:
            error_message = 'JSON Decode Failure'
            self.send_notification(NotificationTypes.error, error_message)

        Logs.message(f"Received Request: {data.get('function')}")
        fn_name = data['function']
        serialized_args = data['args']
        serialized_kwargs = data['kwargs']
        fn_definition = api_function_definitions[fn_name]
        fn_args = []
        fn_kwargs = {}

        # Deserialize args and kwargs into python classes
        for ser_arg, schema_or_field in zip(serialized_args,
                                            fn_definition.params):
            if isinstance(schema_or_field, Schema):
                arg = schema_or_field.load(ser_arg)
            elif isinstance(schema_or_field, fields.Field):
                # Field that does not need to be deserialized
                arg = schema_or_field.deserialize(ser_arg)
            fn_args.append(arg)
        response_channel = data['response_channel']
        function_to_call = getattr(self, fn_name)
        # Set up callback function
        argspec = inspect.getargspec(function_to_call)
        callback_fn = None
        if 'callback' in argspec.args:
            callback_fn = functools.partial(self.message_callback,
                                            fn_definition, response_channel)
            fn_args.append(callback_fn)
        # Call API function
        function_to_call(*fn_args, **fn_kwargs)
        # For non-callback fucntions, ensure message sent back
        if not callback_fn:
            self.message_callback(fn_definition, response_channel)
예제 #11
0
 def on_run(self):
     Logs.message("Run UI Plugin")
     menu = self.rebuild_menu()
     self.update_menu(menu)
예제 #12
0
    async def start_process(self, workspace, ff, steps, steepest):
        if sum(1 for _ in workspace.complexes) == 0:
            Logs.message('No structures to minimize')
            return
        input_file = tempfile.NamedTemporaryFile(delete=False,
                                                 suffix='.sdf',
                                                 dir=self.temp_dir.name)
        constraints_file = tempfile.NamedTemporaryFile(delete=False,
                                                       suffix='.txt',
                                                       dir=self.temp_dir.name)
        output_file = tempfile.NamedTemporaryFile(delete=False,
                                                  suffix='.pdb',
                                                  dir=self.temp_dir.name)
        self.__output_lines = []
        self.__updates_done = {}
        self.__packet_id = 0

        (saved_atoms, indices) = self.__save__atoms(input_file.name, workspace)
        Logs.debug("Wrote input file:", input_file.name)
        self.__save__constraints(constraints_file.name, saved_atoms)
        Logs.debug("Wrote constraints file:", constraints_file.name)
        self.__stream, error = await self.__plugin.create_writing_stream(
            indices, StreamType.position)

        if error == StreamCreationError.AtomNotFound:
            # User deleted atom in time between start_process() and create_writing_stream().
            # so lets update the workspace and try again
            Logs.warning(
                f"User deleted atoms while setting up process, retrying")
            updated_workspace = await self.__plugin.request_workspace()
            await self.start_process(updated_workspace, ff, steps, steepest)
            return

        elif error != StreamCreationError.NoError:
            Logs.error(f"Error while creating stream: {error}")
            return

        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
        self.calculation_start_time = time.time()
        log_data = {
            'exe_path': exe_path,
            'force_field': ff,
            'steps': steps,
            'steepest': steepest
        }
        Logs.message("Starting Minimization Process", extra=log_data)
        p.start()

        self.__process = p
        self.__process_running = True
        self.is_running = True
예제 #13
0
def display_help():
    Logs.message("The following arguments are available for Nanome Plugins global configuration")
    for i in range(len(config_items)):
        c = config_items[i]
        Logs.message(c['arg_key'], c['name'], '-', c['description'])
    Logs.message("\nOr run without arguments for interactive mode")
예제 #14
0
 def start(self):
     Logs.message("Start UI Plugin")
     self.create_callbacks()
예제 #15
0
 def hover_callback(button, hovered):
     Logs.message("button hover: " + button.text.value.idle, hovered)
예제 #16
0
 def select_button_callback(button):
     button.selected = not button.selected
     Logs.message("Prefab button pressed: " + button.text.value.idle +
                  " " + str(button._content_id))
     self.update_content(button)
예제 #17
0
def text_submitted_callback(textInput):
    Logs.message("text input submitted: " + str(textInput.input_text))
예제 #18
0
    def create_tab1(self):
        self.menu_index = 1
        self.previous_menu = None

        content = nanome.ui.LayoutNode()
        ln_contentBase = nanome.ui.LayoutNode()
        ln_label = nanome.ui.LayoutNode()
        ln_button = nanome.ui.LayoutNode()
        ln_slider = nanome.ui.LayoutNode()
        ln_textInput = nanome.ui.LayoutNode()
        ln_list = nanome.ui.LayoutNode()

        content.forward_dist = .02
        content.layer = 1

        ln_label.padding_type = nanome.ui.LayoutNode.PaddingTypes.ratio
        ln_label.padding = (0.01, 0.01, 0.01, 0.01)
        ln_label.forward_dist = .001

        label = nanome.ui.Label()
        label.text_value = "Press the button..."
        label.text_color = nanome.util.Color.White()

        Logs.message("Added Label")

        ln_button.padding_type = nanome.ui.LayoutNode.PaddingTypes.ratio
        ln_button.padding = (0.01, 0.01, 0.01, 0.01)
        ln_button.forward_dist = .001

        #super styled button
        button = nanome.ui.Button()
        button.name = "OpenSubMenu"
        b_t = button.text
        b_t.active = True
        b_t.value.set_all("Spawn menu")
        b_t.auto_size = False
        b_t.size = .6
        b_t.underlined = True
        b_t.ellipsis = True
        b_t.color.idle = nanome.util.Color.Red()
        b_t.color.highlighted = nanome.util.Color.Blue()
        b_t.bold.set_all(False)
        b_t.padding_left = .5
        b_t.vertical_align = nanome.util.enums.VertAlignOptions.Middle
        b_t.horizontal_align = nanome.util.enums.HorizAlignOptions.Left
        b_m = button.mesh
        b_m.active = True
        b_m.color.idle = nanome.util.Color.Blue()
        b_m.color.highlighted = nanome.util.Color.Red()
        b_o = button.outline
        b_o.active = True
        b_o.color.idle = nanome.util.Color.Red()
        b_o.color.highlighted = nanome.util.Color.Blue()
        b_t = button.tooltip
        b_t.title = "spawn a submenu"
        b_t.content = "it is useless"
        b_t.positioning_target = nanome.util.enums.ToolTipPositioning.center
        button.register_pressed_callback(self.spawn_menu_callback)
        button.register_hover_callback(self.hover_callback)

        Logs.message("Added button")

        ln_slider.padding_type = nanome.ui.LayoutNode.PaddingTypes.ratio
        ln_slider.padding = (0.01, 0.01, 0.01, 0.01)
        ln_slider.forward_dist = .001

        slider = nanome.ui.Slider()
        slider.register_changed_callback(slider_changed_callback)
        slider.register_released_callback(slider_released_callback)

        Logs.message("Added slider")

        ln_textInput.padding_type = nanome.ui.LayoutNode.PaddingTypes.ratio
        ln_textInput.padding = (0.01, 0.01, 0.01, 0.01)
        ln_textInput.forward_dist = .001

        textInput = nanome.ui.TextInput()
        textInput.max_length = 30
        textInput.register_changed_callback(text_changed_callback)
        textInput.register_submitted_callback(text_submitted_callback)

        Logs.message("Added text input")

        ln_list.sizing_type = nanome.ui.LayoutNode.SizingTypes.ratio
        ln_list.sizing_value = 0.5
        ln_list.padding_type = nanome.ui.LayoutNode.PaddingTypes.ratio
        ln_list.padding = (0.01, 0.01, 0.01, 0.01)
        ln_list.forward_dist = .03

        prefab = nanome.ui.LayoutNode()
        prefab.layout_orientation = nanome.ui.LayoutNode.LayoutTypes.vertical
        child1 = nanome.ui.LayoutNode()
        child1.sizing_type = nanome.ui.LayoutNode.SizingTypes.ratio
        child1.sizing_value = .3
        child1.name = "label"
        child1.forward_dist = .01
        child2 = nanome.ui.LayoutNode()
        child2.name = "button"
        child2.forward_dist = .01
        prefab.add_child(child1)
        prefab.add_child(child2)
        prefabLabel = nanome.ui.Label()
        prefabLabel.text_value = "Molecule Label"
        prefabButton = nanome.ui.Button()
        prefabButton.text.active = True
        prefabButton.text.value.set_all("Molecule Button")
        prefabButton.register_pressed_callback(self.select_button_callback)
        child1.set_content(prefabLabel)
        child2.set_content(prefabButton)

        list_content = []
        for i in range(0, 10):
            clone = prefab.clone()
            list_content.append(clone)

        list = nanome.ui.UIList()
        list.display_columns = 1
        list.display_rows = 1
        list.total_columns = 1
        list.items = list_content

        Logs.message("Added list")

        content.add_child(ln_contentBase)
        ln_contentBase.add_child(ln_label)
        ln_contentBase.add_child(ln_button)
        ln_contentBase.add_child(ln_slider)
        ln_contentBase.add_child(ln_textInput)
        ln_contentBase.add_child(ln_list)
        ln_label.set_content(label)
        ln_button.set_content(button)
        ln_slider.set_content(slider)
        ln_textInput.set_content(textInput)
        ln_list.set_content(list)
        return content
예제 #19
0
def slider_released_callback(slider):
    Logs.message("slider released: " + str(slider.current_value))
예제 #20
0
def text_changed_callback(textInput):
    Logs.message("text input changed: " + str(textInput.input_text))
예제 #21
0
 def received(self, presenter_info):
     Logs.message("Presenter:", presenter_info.account_id,
                  presenter_info.account_name, presenter_info.account_email)
예제 #22
0
 def print_callback(self):
     Logs.message("hbonds complete")
예제 #23
0
def menu_opened_callback(menu):
    Logs.message("Menu opened: " + menu.title + " " + str(menu.enabled))
예제 #24
0
def dropdown_callback(dropdown, item):
    Logs.message("dropdown item selected: " + str(item.name))
예제 #25
0
 def spawn_menu_callback(button):
     Logs.message("button pressed: " + button.text.value.idle)
     self.update_content(button)
     self.spawn_sub_menu()
예제 #26
0
def slider_changed_callback(slider):
    Logs.message("slider changed: " + str(slider.current_value))
예제 #27
0
 def start(self):
     Logs.message(
         "Connected to a new session!")  # Displays a message in the console
예제 #28
0
    def create_tab2(self):
        content = nanome.ui.LayoutNode()
        ln_contentBase = nanome.ui.LayoutNode()
        ln_label = nanome.ui.LayoutNode()
        ln_button = nanome.ui.LayoutNode()
        ln_slider = nanome.ui.LayoutNode()
        ln_textInput = nanome.ui.LayoutNode()

        content.forward_dist = .02
        content.layer = 1

        ln_label.padding_type = nanome.ui.LayoutNode.PaddingTypes.ratio
        ln_label.padding = (0.01, 0.01, 0.01, 0.01)
        ln_label.forward_dist = .001

        label = nanome.ui.Label()
        label.text_value = "Press the button..."
        label.text_color = nanome.util.Color.White()

        Logs.message("Added Label")

        ln_button.padding_type = nanome.ui.LayoutNode.PaddingTypes.ratio
        ln_button.padding = (0.01, 0.01, 0.01, 0.01)
        ln_button.forward_dist = .001

        button = nanome.ui.Button()
        button.text.active = True
        button.text.vertical_align = nanome.util.enums.VertAlignOptions.Middle
        button.text.horizontal_align = nanome.util.enums.HorizAlignOptions.Middle
        button.register_pressed_callback(self.loading_bar_callback)
        button.register_hover_callback(self.hover_callback)

        Logs.message("Added button")

        ln_slider.padding_type = nanome.ui.LayoutNode.PaddingTypes.ratio
        ln_slider.padding = (0.01, 0.01, 0.01, 0.01)
        ln_slider.forward_dist = .001

        slider = nanome.ui.Slider()
        slider.register_changed_callback(slider_changed_callback)
        slider.register_released_callback(slider_released_callback)

        Logs.message("Added slider")

        ln_textInput.padding_type = nanome.ui.LayoutNode.PaddingTypes.ratio
        ln_textInput.padding = (0.01, 0.01, 0.01, 0.01)
        ln_textInput.forward_dist = .001

        textInput = nanome.ui.TextInput()
        textInput.max_length = 30
        textInput.register_changed_callback(text_changed_callback)
        textInput.register_submitted_callback(text_submitted_callback)

        Logs.message("Added text input")

        prefab = nanome.ui.LayoutNode()
        prefab.layout_orientation = nanome.ui.LayoutNode.LayoutTypes.vertical
        child1 = nanome.ui.LayoutNode()
        child1.sizing_type = nanome.ui.LayoutNode.SizingTypes.ratio
        child1.sizing_value = .3
        child1.name = "label"
        child1.forward_dist = .01
        child2 = nanome.ui.LayoutNode()
        child2.name = "button"
        child2.forward_dist = .01
        prefab.add_child(child1)
        prefab.add_child(child2)
        prefabLabel = nanome.ui.Label()
        prefabLabel.text_value = "Molecule Label"
        prefabButton = nanome.ui.Button()
        prefabButton.text.active = True
        prefabButton.text.value.set_all("Molecule Button")
        prefabButton.register_pressed_callback(self.select_button_callback)
        child1.set_content(prefabLabel)
        child2.set_content(prefabButton)

        ln_loading_bar = nanome.ui.LayoutNode(name="LoadingBar")
        ln_loading_bar.forward_dist = .03
        self.loadingBar = ln_loading_bar.add_new_loading_bar()

        content.add_child(ln_contentBase)
        ln_contentBase.add_child(ln_label)
        ln_contentBase.add_child(ln_button)
        ln_contentBase.add_child(ln_slider)
        ln_contentBase.add_child(ln_textInput)
        ln_contentBase.add_child(ln_loading_bar)
        ln_label.set_content(label)
        ln_button.set_content(button)
        ln_slider.set_content(slider)
        ln_textInput.set_content(textInput)
        return content
예제 #29
0
 def round_2(self, complexes):
     Logs.message("round2")
     complexes[0].name = "c1"
     complexes[1].name = "c2"
     complexes[2].name = "c3"
     self.add_to_workspace(complexes)