Skip to content

Commit

Permalink
Merge pull request #81 from wschroed/Doc-updates
Browse files Browse the repository at this point in the history
Documentation updates
  • Loading branch information
jourdain committed Jun 24, 2022
2 parents 41c4d62 + 6959dc8 commit 44d44fc
Show file tree
Hide file tree
Showing 14 changed files with 140 additions and 158 deletions.
40 changes: 19 additions & 21 deletions docs/content/docs/cheatsheet.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Cheatsheet

The working application below manage to capture the fundamentals of __trame__ in less than 45 lines.
In that sense, it could be seen as a cheatsheet on how to use __trame__ as it is mostly self explanatory.
The working application below captures the fundamentals of __trame__ in less than 45 lines. Consider this as a cheatsheet on how to use __trame__ as it is mostly self explanatory.

```python
from trame.app import get_server # Entry point to trame
Expand Down Expand Up @@ -52,33 +51,33 @@ with SinglePageLayout(server) as layout:
server.start()
```

## Result
## Results


<p style="text-align:center;display: flex;align-items: center;">
<img src="/trame/images/trame-cheatsheet-app.jpg" alt="Application" style="width: 45%; height: 45%">
<img src="/trame/images/trame-cheatsheet-output.jpg" alt="Output" style="width: 45%; height: 45%">
</p>

## Things to understand
## Explanatory Details

### State

Read variable from shared state
Read a variable from shared state:

```python
value = state.var_name
value = state["var_name"]
```

Write variable to the shared state
Write a variable to shared state:

```python
state.var_name = value
state["var_name"] = value
```

Write several variables at once in the shared state
Write several variables at once to the shared state:

```python
state.update({
Expand All @@ -87,7 +86,7 @@ state.update({
})
```

Bind a method/function to a state variable change
Bind a method/function to a state variable change:

```python
@state.change("var_name")
Expand All @@ -101,23 +100,22 @@ def change_detected(**kwargs):
print(f"Either var_name or var_name_1 is modified")
```

Initialise a variable from the UI definition with an initial value.
Use a tuple to define the value of a given attribute where the first entry is a string with the variable name and the second entry is its initial value.
Specify an initial value for a UI variable. Use a tuple to define the value of a given attribute, where the first entry is a string with the variable name and the second entry is its initial value.

```python
vuetify.VTextField(v_model=("var_name", "initial value"))
vuetify.VSlider(v_model=("resolution", 6), min=1)
```

Provide a JavaScript expression as attribute. We still provide a tuple but with no initial value.
Provide a JavaScript expression as an attribute value. We still provide a tuple but with no initial value.

```python
vuetify.VTextField(value=("'Hello' + var_name", ))
```

### Method binding

Method can be passed to events attribute of your UI elements. By default, the function will be called with no arguments.
Methods can be passed to the events attribute of your UI elements. By default, the function will be called with no arguments.

If you want to control its arguments you can use a tuple where the second entry represents the __args__ and the third represents the __kwargs__. If you only want to provide args without kwargs, just provide a tuple with 2 entries. __$event__ is a reserved name to represent the event object.

Expand All @@ -129,7 +127,7 @@ vuetify.VBtn("Click me", click=(ctrl.do_something, "[index, $event]", "{ a: 12 }

### Controller

The controller from trame is just a dynamic container for methods or functions that can be get or set in either order.
The trame controller is just a dynamic container for methods or functions that can be set or get in either order.

```python
vuetify.VBtn("Click me", click=ctrl.do_something)
Expand All @@ -142,11 +140,11 @@ ctrl.do_something = fn

## Life Cycle

* on_server_ready : All protocols initialized and available for client to connect
* on_client_connected : Connection established to server
* on_client_exited : Linked to browser "beforeunload" event
* on_server_exited : Trame is exiting its event loop
* on_server_reload : If callback registered it is use for reloading server side modules
* on_server_ready : All protocols initialized and available for the client to connect.
* on_client_connected : Connection established to server.
* on_client_exited : Linked to browser "beforeunload" event.
* on_server_exited : Trame is exiting its event loop.
* on_server_reload : If callback registered it is used to reload server side modules.

```python

Expand All @@ -156,8 +154,8 @@ ctrl.on_server_ready.add(lambda **_: print("Staring Factory - Launcher barrier")
ctrl.on_client_exited = lambda **_: print("Someone is gone...")
```

## Conclusion
## Conclusion and Next Steps

The remaining part to learn is all the components available for displaying other 3D graphics, charts, maps and more. But right now you've learn the fundamentals on how trame works which should let you build your application simply. For more details, please refer to the [tutorial](https://kitware.github.io/trame/docs/tutorial.html) or [API](https://trame.readthedocs.io/en/latest/index.html).
At this point the fundamentals of trame have been presented. To build fully-fledged applications, the next steps are to learn the various components available for displaying 3D graphics, charts, maps and more. For more details, please refer to the [tutorial](https://kitware.github.io/trame/docs/tutorial.html) or [API](https://trame.readthedocs.io/en/latest/index.html).

Trame is a powerful framework for building any kind of application in plain Python. From prototypes to professional applications, trame offers an innovative approach for “write once and run anywhere” by allowing your app to migrate from your desktop to a cloud service.
Trame is a powerful Pyton-based integration framework for creating visual analytics applications. From prototypes to professional applications, trame offers an innovative approach to “write once and run anywhere” through applications that run from a desktop to a cloud service using a standard web browser.
46 changes: 17 additions & 29 deletions docs/content/docs/getting_started.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
# How to use trame

trame aims to streamline creation of graphical interfaces for interactive data manipulation and visualization with a very compact and simple API.
This document tries to capture the core API and concepts behind trame so you can use it when you get started but also as a reference once you get more familiar with trame.
Trame aims to streamline the creation of visual analytics applications, with support for interactive data manipulation and visualization, through a very compact and simple API. This document describes the core API and concepts behind trame; the document is both a start up guide, but also a quick reference for those more familiar with trame.

## Core concept
## Core concepts

trame allow you to easily share variables between the UI components and your Python application.
But on top of that shared state, functions and methods can be triggered from either side.
For example, you can link a Python function to be called when a button in the UI is clicked.
This document will focus on how you can leverage those two functionalities inside your application using trame.
Trame allows you to easily share variables between UI components and a Python application. The resulting shared state can be modified by functions and methods invoked from the UI or application. For example, a Python function can be called when a button in the UI is clicked; or the UI can be updated in response to programmatic changes to the state. This document focuses on how you can leverage these capabilities inside your application using trame.

## Shared state

trame mainly focuses on the Python side, therefore the variables that we aim to use across our application will be defined from Python.
The following sections will illustate the various way you can affect the shared state.
Trame mainly focuses on the Python side, therefore the variables that we aim to use across our application will be defined from Python. The following sections illustate the various ways the shared state can be modified.

### UI element with a dynamic variable

The example below uses Vuetify to create a slider where the value controlled by that slider is available in our shared state behind the name `slider_value` that we initialize with the value `8`. So variables in our shared state can be defined and initialized right were we want to use them when defining our UI elements. In this example, the slider will be able to modify that value but also will reflect its content if that value changes on the server side.
The example below uses Vuetify to create a slider where the value is controlled by the slider. The variable `slider_value` is initialized with the value `8`. So variables in the shared state can be defined and initialized right were we want to use them when defining our UI elements. In this example, the slider will be able to modify that value but also will reflect its content if that value changes on the server side.

```python
from trame.widgets import vuetify
Expand All @@ -30,10 +25,9 @@ slider = vuetify.VSlider(
)
```

### Listening to change
### Listening to changes

Let's pretend we want to monitor the value of `slider_value` within our Python application and execute a method when that variable gets updated.
The code below illustate how we can annotate a function so it can be called when a value of our shared state is modified.
Imagine that we want to monitor the value of `slider_value` within our Python application and execute a method when that variable is updated. The code below illustate how we can annotate a function so it can be called when a value of the shared state is modified.

```python
from trame.app import get_server
Expand All @@ -46,12 +40,11 @@ def slider_value_change(slider_value, **kwargs):
print(f"Slider is changing slider_value to {slider_value}")
```

So far, we only have the client modifying that variable. But if a function on the server were to change that variable, that function will also be called as we simply react to the fact that the variable has been updated by someone.
So far, we only have the client modifying that variable. But if a function on the server were to change that variable, the function would also be called as we simply react to the fact that the variable has been updated by someone.

### Changing the value from Python

Within our Python application it is possible that we would like to read and even write in the shared state so the UI can reflect your changes.
The code below provides a function that will read the current value and update its content.
Within a Python trame application, it is possible to update the UI in response to read and even write operations to and from the shared state. The code below provides a function that will read the current value and update its content.

```python
from trame.app import get_server
Expand All @@ -67,7 +60,7 @@ def random_update():

### Forcing state exchange

Sometimes, the variable inside your shared state is an actual object with nested structure. While the state on the Python side always keeps the same reference to that object, you are manually editing its content and you want to flush its content so the client can see your changes. In that use case we have a `dirty()` method that can be called with the list of variable names that should be pushed. This is also useful in some async contexts to control when pieces of the state should be pushed to the other side. The code below provides a usage example.
Sometimes, the variable inside your shared state is an actual object with a nested structure. While the state on the Python side always maintains a reference to that object, when manually editing it's important to flush its contents so that the client reflects changes. In this situation, the `dirty()` method can be called with the list of variable names that should be pushed. This is also useful in some async contexts to control when pieces of the state should be synchronized between client and server. The code below provides a typical example.

```python
import asyncio
Expand All @@ -82,7 +75,7 @@ async def update_time():

## Method calls

When building a client/server application you will need to be able to trigger methods on both side and trame has some easy ways to do that.
When building a client/server application you will need to be able to trigger methods on both sides and trame has some easy ways to do that.

### Bind method to a button click

Expand All @@ -109,10 +102,9 @@ def random_update():
ctrl.rnd_update = random_update
```

### Calling JS methods
### Calling JavaScript methods

Some components in your layout may have APIs that you can use and call from the Python side.
The code below provides an example of such use case:
Some components in an application may have APIs that you be used and invoked from the Python side. The code below provides an example of such a use case:

```python
from trame.app import get_server
Expand All @@ -131,9 +123,7 @@ def reset_camera():

## Layout management

Layouts are meant to define the core UI elements of an application. Think of FullScreen vs Toolbar, Drawer, Footer and so on.
Layouts let you drop pieces of your UI into pre-defined locations.
The layout gathers the way your application will look. It could be defined once or be redifined at runtime.
Layouts are meant to define the core UI elements of an application. Think of FullScreen vs Toolbar, Drawer, Footer and so on. Layouts let you drop pieces of your UI into pre-defined locations. The layout organizes the way an application is structured. It could be defined once, or be redifined at runtime.

When creating a layout, you have the opportunity to define the Tab title along with a path to a favicon and a method to call at startup.

Expand Down Expand Up @@ -165,8 +155,7 @@ vuetify.VSlider(

## Command line arguments

Since a trame application is a real application, as opposed to a service that aims to serve many concurrent users, you may want to provide some information to your application when you start it like which ML model you want to load or the file/directory that you would like to explore or process.
This can be achieved by adding CLI parameters using [ArgParse](https://docs.python.org/3/library/argparse.html), like in the following example.
Since trame is used to create applications, as compared to web services that aim to serve many concurrent users, it may be important to provide information to an application on start up. For example, which ML model to load, or the file/directory that you would like to explore or process. This can be achieved by adding CLI parameters using [ArgParse](https://docs.python.org/3/library/argparse.html), like in the following example.

```python
from trame.app import get_server
Expand All @@ -178,10 +167,9 @@ args = server.cli.parse_args()
print(args.data)
```

## Starting the application
## Starting an application

trame server provides a `start()` method which will actually start your application.
Usually we put the following section in your main script.
The server provides a `start()` method which actually starts a trame application. Typically the following section is placed in the main script:

```python
if __name__ == "__main__":
Expand Down
Loading

0 comments on commit 44d44fc

Please sign in to comment.