In-View Python Scripting Console in Plexus Connect

    This documentation aims to provide users with a clear understanding of the Python scripting Console capabilities within Plexus Connect, illustrating how they can leverage this new tool to enhance data management and analysis processes. Practical examples are included.

    Introduction

    Plexus Connect offers many functionalities to facilitate daily workflows, though they may be unknown to regular users. Some of these features might initially appear too complex and discourage users from using them at all. A good example of such feature is Python scripting, a powerful tool for data manipulation and analysis. Recognizing that previous requirements for setting up Python scripting could be a barrier, we've streamlined the process with the introduction of an integrated Python scripting console.

    This built-in console eliminates the preliminary setup complexities, making Python scripting straightforward and directly accessible alongside your dataset. It's designed to simplify the scripting process, making it accessible even to users with minimal Python knowledge. Here’s a brief overview of what can be achieved with Python scripting built-in console in Plexus Connect:

    • Custom Visualizations: Create customized charts and graphs using libraries like Matplotlib and Plotly, enabling enhanced data presentation.

    • Automation: Automate repetitive tasks, such as data search, data exports and periodic analyses, to improve efficiency and accuracy.

    • Custom Tools: Develop your own functions and tools that expand Plexus Connect’s capabilities, tailored to your specific needs.

    • Data Cleaning: Utilize scripts to automate the cleaning process, including removing duplicates, filtering data, and managing missing values, ensuring your datasets remain pristine.

    • Collaboration: Facilitate script sharing among team members to foster collaboration and standardize methodologies for handling data.

    images/download/attachments/252021/python-console.png

    Requirements and Setup

    • Python scripting console is available directly in the UI only in Plexus Connect version 23.16.0 or higher.

    • Python version 3.7 or higher installed on your computer. Python installation is described for example here in our documentation. This installation is necessary to run any python script on your computer.

    • Connect API containing Plexus Connect Python library, downloadable on our website. Connect API installation is described here in our documentation. This installation integrates Python into Plexus Connect and enables to run scripts directly in Plexus Connect. Connect API package also contains folder with exemplary scripts, which can be modified or used as templates.

    Examples of Usage

    Once the requirements are satisfied, the Python scripting console is ready to use. To access the console, navigate to Python Script tab in the upper right corner of any open view (see the screenshot above).

    Example 1: Sample Script

    Upon opening the console, you'll find a preloaded sample script. This script is there to show you what a basic Python script looks like. It includes three important methods you can use in Plexus Connect: OnLoad, OnClick, and OnSelectionChange. Each method triggers a different event. For example, in our initial script, every method causes a specific message to pop up (look at lines 15 to 19, 21 to 25, and 27 to 35 in the script). To get the script working, just hit Save and refresh your view.

    In general, methods define what will happen when certain action is taken.

    • OnLoad method is activated when new data is loaded. In the sample script, message "Python scripting enabled!.." appears.

    • OnClick method is activated upon clicking on some object in the View. In the sample script, message "Button button1 clicked for view <View ID>"

    • OnSelectionChange method is activated upon browsing thru your data set. In the sample script, message "You've selected <CdID number>"

    Example 2: Adding Static Graphical Object to a View

    To further extend python versatility, so-called libraries often have to be installed. In this example, we will install pillow library that adds image processing capabilities and supports all typical image formats (jpg, jpeg, png, svg, etc.).

    To install pillow library, open command line (Terminal on Mac) and write pip3 install pillow. The installation takes few second.

    The following script allows to display an image in either jpeg or png format located on your computer. In order to display the image, add Canvas Widget to your form view (preferably, there should be only one canvas widget). Then, copy paste the script to the in-view python console and replace "someAbsolutePathToJpgImage" in jpeg or "someAbsolutePathToJpgImage" in png section of the script with absolute path pointing to your image. Hit save and reload the view. The Canvas widget should be occupied by the image.

    from connect_api import ConnectScript
    import base64
    import os
    import io
    from PIL import Image
    import sys
    
    def animate_text(text, index, helper):
      colors = ['red', 'blue', 'green']
      svg = '<?xml version="1.0" encoding="utf-8"?>' \
      f'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="100%" height="200"  style="background: {colors[index]}">' \
        f'<text x="20" y="100" fill="purple" >{text}' \
        '</text>' \
      '</svg>'
      return helper.getImageDataUrl('svg+xml', svg.encode('utf-8'))
    
    # finds some JPEG image on the filesystem and returns data URL of it
    def givemejpg(self, helper):
      img = Image.open("someAbsolutePathToJpgImage", "r")
      img_byte_arr = io.BytesIO()
      img.save(img_byte_arr, format='JPEG', subsampling=0, quality=100)
      return helper.getImageDataUrl('jpeg', img_byte_arr.getbuffer().tobytes())
    
    # finds some PNG image on the filesystem and returns data URL of it
    def givemepng(self, helper):
      img = Image.open("someAbsolutePathToPngImage", "r")
      img_byte_arr = io.BytesIO()
      img.save(img_byte_arr, format='PNG', subsampling=0, quality=100)
      return helper.getImageDataUrl('png', img_byte_arr.getbuffer().tobytes())
    
    # class to be used by Connect, defining handlers according to connect_api documentation
    class MyScript(ConnectScript):
      def onLoad(self):
        self.response.showMessage("Python scripting enabled! ..")
        self.response.setFormButtons([
          { "id": "button1", "text": "pytest"}
        ])
        pass
    
      def onClick(self, payload):
        id = payload["id"]
        serverSchemaId = payload["serverSchemaId"]
        self.response.showMessage(f"Button {id} clicked for view {serverSchemaId} ..")
        pass
    
      # on each selection change and initial load of view, onSelectionChange handler is called by Connect,
      # passing also IDs od each canvas widget in the form
      def onSelectionChange(self, payload):
        for index, canvasId in enumerate(payload["canvasWidgetIds"]):
            # here for each canvas widget it will generate example image, png or jpeg and sends it as a response
            self.response.showInCanvas(canvasId, givemepng(self, self.helper) if index == 0 else givemejpg(self, self.helper))
        pass
    
    # initializes the handlers
    MyScript().execute()
    images/download/attachments/252021/python-console-2.png

    Example 3: Adding Dynamic Graphical Object to a View

    The following script creates chart from current dataset. If the dataset is changed (filtering data, etc.) the chart is updated accordingly. OnDataLoad method used in this script updates the chart every time new data is displayed.

    Both x and y variables (fields) are specified in the script. In order to display the chart, add Canvas Widget to your form view (preferably, there should be only one canvas widget). Then, copy paste the script to the in-view python console, hit save and reload the view. The Canvas widget should be occupied by the chart.

    from connect_api import ConnectScript
    import base64
    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    import seaborn as sns
    import io
    
    class MyScript(ConnectScript):
        def onLoad(self):
            pass
    
        def onDataLoad(self, payload):
            allData = self.currentSession.getData([
                "CdId",
                "Acceptors",
                "Donors"])
            # Create a DataFrame from the data
            cdId = [inner_list[0] for inner_list in allData]
            acceptors = [inner_list[1] for inner_list in allData]
            donors = [inner_list[2] for inner_list in allData]
            df = pd.DataFrame({'CdId': cdId, 'Acceptors': acceptors, 'Donors': donors})
    
            # Convert the columns to numeric types
            df['CdId'] = pd.to_numeric(df['CdId'])
            df['Acceptors'] = pd.to_numeric(df['Acceptors'])
            df['Donors'] = pd.to_numeric(df['Donors'])
    
            # Sort the DataFrame by 'CdId'
            df = df.sort_values('CdId')
    
            # Create the scatter plot using seaborn
            sns.scatterplot(x='CdId', y='Acceptors', data=df, color='blue', label='Acceptors')
            sns.scatterplot(x='CdId', y='Donors', data=df, color='red', label='Donors')
    
            # Interpolate the curves
            x_min = df['CdId'].min()
            x_max = df['CdId'].max()
            x_range = np.linspace(x_min, x_max, len(df['Donors']))  # Match the number of data points in the y array
    
            interpolated_acceptors = np.interp(x_range, df['CdId'], df['Acceptors'])
            interpolated_donors = np.interp(x_range, df['CdId'], df['Donors'])
    
            # Plot the interpolated curves
            plt.plot(x_range, interpolated_acceptors, color='blue', linestyle='dashed', label='Interpolated Acceptors')
            plt.plot(x_range, interpolated_donors, color='red', linestyle='dashed', label='Interpolated Donors')
    
            # Set labels and legend
            plt.xlabel('CdId')
            plt.ylabel('Count')
            plt.legend(loc='upper right')
            buf = io.BytesIO()
            plt.savefig(buf, format='png', dpi=300)
            bytes = buf.getvalue()
            for index, canvasId in enumerate(payload["canvasWidgetIds"]):
                self.response.showInCanvas(canvasId, self.helper.getImageDataUrl('image/png', bytes))
            pass
    
    MyScript().execute()
    
    images/download/attachments/252021/python-scripting-console-3.png

    {info} Should you require a solution precisely tailored to your specific needs, the Instant JChem support team is ready to assist. Contact us via Chemaxon Freshdesk for custom-designed scripts.