Actions

Actions are one of the latest features incorporated. They provide simple but powerful tools to create code snippets that can be easily shared and executed in the browser.

Actions are ideal for applications that require real time interaction. Moreover, they are no executed in the SDK, which provides a high level of freedom when it comes to sharing, using and creating them.


Defining an Action

In the simplest way possible, an action is defined as a function with the reserved name action and the client as a parameter.

def action(shimoku_client: Client):
    #code [...]
    shimoku_client.run()

Then, on your main Python file, it is necessary to add the following code to create the action instance.

indicator_action_id = shimoku_client.actions.create_action(
    name="Your action name",
    code=open("MyAction.py", "r").read(),
    overwrite=True,
)

Snackbars

Actions provide a snackbar based method of communication on the frontend. It is useful to express different stages in the process and even handling errors. These snackbars can portray information, success or an error.

def action(shimoku_client: Client):

    global_front_end_connection.snackbar_info(
        "Starting action"
    )
    #code [...]
    
    if variable1 is None: #let variable be any important value
        global_front_end_connection.snackbar_error("Variable1 must have a value!")
        return
    
    global_front_end_connection.snackbar_info("Plotting the results")
    #plotting code [...]
    
    shimoku_client.run()
    global_front_end_connection.snackbar_success(
        "End of action"
    )

Implementation Example

In this example, a visual representation of the relation between zeta an omega in an 'Damping Harmonic Oscillator' is showcased using an action.

import numpy as np
from numpy import array, pi
import pandas as pd

#shimoku necessary libraries
from shimoku import Client
from shimoku.actions_execution.front_connection import global_front_end_connection

# physics calculations

Nt = 1000
t = np.linspace(0.0, 10.0, Nt)
dt = t[1] - t[0]  # Time step


def ode(X: array, zeta: float = 0.05, omega0: float = 2.0 * pi) -> array:
    x, dotx = X
    ddotx = -2 * zeta * omega0 * dotx - omega0**2 * x
    return array([dotx, ddotx])


def rk4_step(X: array, zeta: float, omega0: float, loc_dt: array) -> array:
    k1 = ode(X, zeta, omega0)
    k2 = ode(X + 0.5 * k1 * loc_dt, zeta, omega0)
    k3 = ode(X + 0.5 * k2 * loc_dt, zeta, omega0)
    k4 = ode(X + k3 * loc_dt, zeta, omega0)
    return X + (k1 + 2 * k2 + 2 * k3 + k4) * loc_dt / 6


def update(zeta: float = 0.05, omega0: float = 2.0 * pi):
    X = np.array([1.0, 0.0])
    values = [X[0]]
    for _ in range(1, Nt):
        X = rk4_step(X, zeta, omega0, dt)
        values.append(X[0])
    return values


# defining the action

def action(shimoku_client: Client):
    global_front_end_connection.snackbar_info(
        "Beginning action of Damping Harmonic Oscillator"
    )
    shimoku_client.set_menu_path("Actions", "Damping Harmonic Oscillator")

    input_form_values = shimoku_client.plt.get_input_forms()[0]["data"]
    zeta = float(input_form_values["zeta"])
    omega0 = float(input_form_values["omega0"])
    if zeta < 0:
        global_front_end_connection.snackbar_error("Zeta can not be negative")
        return
    if omega0 < 0:
        global_front_end_connection.snackbar_error("Omega can not be negative")
        return
    

    y = update(zeta=zeta, omega0=omega0)
    df = pd.DataFrame(t, columns=["Time"])
    df["Value"] = y

    global_front_end_connection.snackbar_info("Plotting the results")
    shimoku_client.plt.line(
        data=df, order=2, x="Time", y="Value", rows_size=2, cols_size=12
    )

    shimoku_client.run()
    global_front_end_connection.snackbar_success(
        "End of action of Damping Harmonic Oscillator"
    )

Handling Errors

It is usual having errors when using a new tool. For that reason it has been created a series of common errors to help you understand the nomenclature and structure of an action, while also troubleshoot your code in case of error. If your specific error can not be found down below, visit our mockable tests guide on GitHub here for more detailed and technical guidance.


Actions must always have the client parameter, annotated and in this specific format: shimoku_client: Client

Furthermore, an action can not be defined in a class.

#CORRECT WAY
def action(shimoku_client: Client):  
    pass
    

#INCORRECT WAYS
#ERROR1
def action(): # always add the client parameter
    pass

#ERROR2
def action(shimoku_client): # always annotate the clietn variable
    pass
    
#ERROR3   
def action(shimoku_client: int): # the client variable must be of type Client
    pass
    
#ERROR4
def action(shimo: Client):  # the client variable must be named shimoku_client
    pass
    
#ERROR5
def action(shimoku_client: Client, value1):  # cannot use arbitrary variables as params
    pass
    
#ERROR6
class UsesClient:
    def action(self, shimoku_client: Client):  # cannot declare the action in a class
        pass

There has to exist an action and it can not be redefined in the same file.

#ERROR7
def action(shimoku_client: Client):  
    pass

def action(shimoku_client: Client):  
    pass

#ERROR8
    #no action declared

In terms of libraries, always import the client using the following specific format: from shimoku import Client. Furthermore, the asyncio library and its functionalities can not be imported.

#CORRECT WAY
from shimoku import Client

def action(shimoku_client: Client):
    pass

#ERROR9
from shimoku import Client
import asyncio

#ERROR10
from shimoku import Client
from asyncio import sleep

#ERROR11
from shimoku import Client as whatever

It is crucial to maintain the integrity of Client. Here are some errors that do not respect that integrity.

#ERROR12
def action(shimoku_client: Client):
    use_s(other_param=shimoku_client)  #cannot use other params for the client variable
    
#ERROR13
def use_s(shimoku_client: Client):
    return shimoku_client  #cannot return the client

#ERROR14
shimoku_client = 6 #cannot reassign the client variable
def action(shimoku_client: Client):
    pass
    
#ERROR15
variable = Client() #cannot create another client
def action(shimoku_client: Client):
    pass

#ERROR16
from shimoku import Client as shimo  # cannot rename the client

def action(shimoku_client: shimo):
    pass

Last updated