firefly/ntbks/flask_tutorial.ipynb
[1]:
%load_ext autoreload
%autoreload 2
from IPython.display import IFrame,YouTubeVideo
A recording of this jupyter notebook in action is available at:
[2]:
YouTubeVideo("OD598z7pqB0")
[2]:
[3]:
import numpy as np
import os
import requests
import sys
## ignore these lines, you do not need to add this if Firefly is pip installed into your PYTHONPATH
sys.path.insert(0, '/Users/ageller/VISUALIZATIONS/Firefly')
sys.path.insert(0,'/Users/agurvich/research/repos/firefly/src')
from firefly.data_reader import ArrayReader
from firefly.server import spawnFireflyServer,quitAllFireflyServers
Tutorial notebook: Sending data to a local Firefly server through Flask
A drawback of using .json
files on disk to pass data between the Python frontend and the Firefly webapp is that these .json
files can 1. take up a lot of unnecessary disk space 2. take a long time to read from disk
To address these problems, we use Flask to host a webserver and parse data directly from Python at a data upload endpoint. This procedure is detailed in the server documentation. From the user’s perspective, all they need to do is POST their data to a specific port on their local machine and they will be able to explore their own data without ever having to write a file to disk.
Start the Firefly server as a background process
In this tutorial we’ll demonstrate how to update the data being shown in a live instance of Firefly running on a local webserver through Flask. Before attempting this tutorial read through the server documentation which explains how to specify the listening port and different methods of hosting a Flask Firefly server (here we use the firefly.server.spawnFireflyServer
function which starts a background process).
[4]:
process = spawnFireflyServer(5500)
Waiting up to 10 seconds for background Firefly server to start....done! Your server is available at - http://localhost:5500
Show Firefly in an IFrame
IPython allows one to embed webpages into a notebook using an IFrame, we’ll take advantage of that to embed Firefly here (you can also visit the localhost:5500 url in your browser if you’d prefer).
[5]:
url = "http://localhost:5500"
IFrame(url, width=1000, height=500)
[5]:
Create some example data and put it into a firefly.data_reader.Reader
object
See the reader documentation or the reader_tutorial.ipynb
example notebook.
[6]:
## let's create some sample data, a grid of points in a 3d cube
my_coords = np.linspace(-10,10,20)
xs,ys,zs = np.meshgrid(my_coords,my_coords,my_coords)
xs,ys,zs = xs.flatten(),ys.flatten(),zs.flatten()
coords = np.array([xs,ys,zs]).T
## we'll pick some random field values to demonstrate filtering/colormapping
fields = np.random.random(size=xs.size)
We’ll use an ArrayReader
here, check out the reader_tutorial.ipynb
example notebook if this is new for you!
[7]:
my_arrayReader = ArrayReader(
coords,
fields=fields,
write_to_disk=False)
datadir is None, defaulting to /Users/agurvich/research/repos/firefly/src/firefly/static/data/Data
Make sure each field_array (1) has a field_filter_flag (0), assuming True.
Make sure each field_array (1) has a field_colormap_flag (0), assuming True.
Make sure each field_array (1) has a field_radius_flag (0), assuming False.
PGroup_0 - 8000/8000 particles - 1 tracked fields
Send this data to the Flask app
The data will be sent to the Firefly server via a POST request, we can do this in python using the requests
module. One the POST has been made scroll back up to the window above and see the new data (if you don’t see new data, it’s possible that you’ve overwritten the default startup.json
that shipped with Firefly by following some of the other tutorials. That’s okay! See the multiple datasets documentation or the multiple_datasets.ipynb
example notebook to learn more about the
startup.json
file.
[8]:
## make a POST request to port 5500, supplying the JSON produced by setting
## write_jsons_to_disk=False and calling .dumpToJSON"
port = 5500
print('sending to Firefly', sys.getsizeof(my_arrayReader.JSON))
requests.post(f'http://localhost:{port:d}/data_input',json=my_arrayReader.JSON)
sending to Firefly 49
[8]:
<Response [200]>
We’ve also wrapped this code in the .sendDataViaFlask
method.
[9]:
## make a POST request
my_arrayReader.sendDataViaFlask(5500)
PGroup_0 - 8000/8000 particles - 1 tracked fields
Posting data on port 5500...data posted!
Quitting the Firefly server process when you’re done
Because the Firefly server was started in the background, the process will persist even when you’re done with it. You should make sure to quit it using the firefly.server.quitAllFireflyServers
function. If you supply a process id (which is returned by the spawnFireflyServer
function) then it will only quit that one process. However, processes are a bit defensive and sometimes we’ve found they survive the attempt on their life and then hide under a different PID. In which case, it’s
always safest to just quit all the servers indiscriminately. Generally the two are interchangeable unless you’re hosting multiple local servers of Firefly on different ports. This is pretty uncommon/advanced in which case you hopefully know what you’re doing.
The firefly.server.quitAllFireflyServers
function will print all of the output the Firefly server
[10]:
return_code = quitAllFireflyServers()
Server output:
--------------
kill: 35444: No such process
[ ]: