{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "`firefly/ntbks/reader_tutorial.ipynb`" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2\n", "from IPython.display import YouTubeVideo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A recording of this jupyter notebook in action is available at:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "image/jpeg": "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by+s/dUv2rPptvL6z93T/ag9b6Fl+q2+dhf3lDQYRBa2JnIZ69q8k9Nt5fWfu6f7U9Nt5fWfu6f7UHrbaDAA0NaABAEZIaTTMtbfOwvwuvJPTbeX1n7un+1PTbeX1n7un+1B630LbHC2wgWFhp2KTWAAAAAAQOQXkXptvL6z93T/AGp6bby+s/d0/wBqD1voGQBgbAyECB2LHQMv1G3zsLryX023l9Z+7p/tT023l9Z+7p/tQeteTs9Rv2R78B3I6i2D1W3F7DhkvJfTbeX1n7un+1YPw13l9Z+7p/tQergQIFgsryb0z3j9Y+7p/tT0z3j9Y+7p/tQesovJvTPeP1j7un+1PTPeP1j7un+1B6yi8m9M94/WPu6f7U9M94/WPu6f7UHrKLyb0z3j9Y+7p/tT0z3j9Y+7p/tQesovJvTPeP1j7un+1PTPeP1j7un+1B6yi8m9M94/WPu6f7U9M94/WPu6f7UHrKLyb0z3j9Y+7p/tT0z3j9Y+7p/tQcFERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREBERAREQEREH/2Q==\n", "text/html": [ "\n", " <iframe\n", " width=\"400\"\n", " height=\"300\"\n", " src=\"https://www.youtube.com/embed/lYPGa6DibOk\"\n", " frameborder=\"0\"\n", " allowfullscreen\n", " \n", " ></iframe>\n", " " ], "text/plain": [ "<IPython.lib.display.YouTubeVideo at 0x10411aca0>" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "YouTubeVideo(\"lYPGa6DibOk\")" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "don't have phil's colormaps\n" ] } ], "source": [ "import sys\n", "import os\n", "import numpy as np\n", "## ignore this line, you do not need to add this if Firefly is pip installed into your PYTHONPATH\n", "sys.path.insert(0,\"/Users/agurvich/research/repos/firefly/src/\")\n", "from firefly.data_reader import Reader,ArrayReader,ParticleGroup" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Tutorial notebook: Using the `Reader` class\n", "One of the main purposes of Firefly is to enable users to interactively explore their *own* data (or else interactively explore someone else's respective own data). While it is possible to format one's data manually using a text editor we have provided a python API for producing the `.json` files that are necessary to run an iteration of firefly.\n", "\n", "The central piece of that API is the `firefly.data_reader.Reader` class, which acts to collect the different parts of the API together to produce consistently formatted and linked `.json` files that the Firefly webapp can interpret. The `Reader` class is <a href=\"https://alexbgurvi.ch/Firefly/docs/build/html/data_reader/reader.html\">documented here</a> but here we only provide a brief example of how to use the API. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Creating a Reader instance\n", "To begin, we'll start by initializing a `Reader` object. Users are encouraged to familiarize themselves with the different keyword arguments through the documentation linked above. \n", "\n", "Perhaps the most important keyword argument is the `JSONdir`, which tells your `Reader` object where it should collect the different `.json` files it will produce. The `.json` files have to be readable from the `firefly/static/data` directory of the iteration of Firefly that's trying to open the data. The `Reader` class will automatically create a shortcut to the directory if you don't choose a path that lives in `firefly/static/data`. If you enter a relative path it will assume you mean relative to your `${HOME}` directory. If no `JSONdir` is provided then it will default to `${HOME}/<JSONprefix>` (which itself defaults to `Data` if nothing is passed). " ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "## initialize a Reader object, cwd will be firefly/ntbks\n", "JSONdir = os.path.abspath(os.path.join(os.getcwd(),'..','static','data','tutorial'))\n", "my_reader = Reader(JSONdir=JSONdir)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "## let's create some sample data, a grid of points in a 3d cube\n", "my_coords = np.linspace(-10,10,20)\n", "xs,ys,zs = np.meshgrid(my_coords,my_coords,my_coords)\n", "xs,ys,zs = xs.flatten(),ys.flatten(),zs.flatten()\n", "coords = np.array([xs,ys,zs]).T\n", "\n", "## we'll pick some random field values to demonstrate filtering/colormapping\n", "fields = np.random.random(size=xs.size)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Store the coordinates in a ParticleGroup\n", "Particle data is validated and organized in `firefly.data_reader.ParticleGroup` objects. In general users should not sub-class the `ParticleGroup` class but if you're an enterprising user with a specific use case I'm a tutorial not a cop! For details about how the `ParticleGroup` class works, check the <a href=\"https://alexbgurvi.ch/Firefly/docs/build/html/data_reader/particle_group.html\">particle group documentation</a>.\n", "\n", "For our purposes, we'll take advantage of the fact that any keyword arguments passed here go directly to the `particleGroup.settings_default` dictionary which controls which elements appear in the particle panes in the UI, see the <a href=\"https://alexbgurvi.ch/Firefly/docs/build/html/data_reader/settings.html\">settings documentation</a> or see `settings_tutorial.ipynb` for an example.\n", "\n", "**Note:**\n", "Sometimes data is too large to load directly into Firefly, we encourage users who are trying a new dataset for the first time to use the `decimation_factor` keyword argument to reduce the dataset size by the factor specified (the implementation is just a `shuffle(coords)[::decimation_factor]`). " ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Make sure each field_array (1) has a field_filter_flag (0), assuming True.\n", "Make sure each field_array (1) has a field_colormap_flag (0), assuming True.\n", "Make sure each field_array (1) has a field_radius_flag (0), assuming False.\n", "Make sure each field_array (1) has a field_filter_flag (0), assuming True.\n", "Make sure each field_array (1) has a field_colormap_flag (0), assuming True.\n", "Make sure each field_array (1) has a field_radius_flag (0), assuming False.\n" ] } ], "source": [ "## create a particle group that contains our test coordinates\n", "my_particleGroup = ParticleGroup(\n", " 'partname',\n", " coords,\n", " sizeMult=5, ## increase the size of the particles to make the particles a bit easier to see since there's so few of them\n", " color = [0,0,1,1], ## make them blue, colors should be RGBA list,\n", " field_arrays=[fields], ## track the dummy field to demonstrate how to pass field data\n", " field_names=['testfield']) ## name the dummy field\n", "\n", "## sometimes data is too large to load directly into Firefly\n", "my_decimated_particleGroup = ParticleGroup(\n", " 'decimated',\n", " coords,\n", " sizeMult=5, ## increase the size of the particles to make the particles a bit easier to see since there's so few of them\n", " color = [0,0,1,1], ## make them blue, colors should be RGBA list,\n", " field_arrays=[fields], ## track the dummy field to demonstrate how to pass field data\n", " field_names=['testfield'], ## name the dummy field\n", " decimation_factor=10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All that's left is to connect the `ParticleGroup` object to the `Reader` object using the `.addParticleGroup` method. " ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Reader with 2 particle groups\n", "[partname - 8000/8000 particles - 1 tracked fields\n", " decimated - 800/8000 particles - 1 tracked fields]\n" ] } ], "source": [ "## instructs my_reader to keep track of my_particleGroup\n", "my_reader.addParticleGroup(my_particleGroup)\n", "my_reader.addParticleGroup(my_decimated_particleGroup)\n", "print(my_reader)\n", "print(my_reader.particleGroups)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that the decimation factor is represented by the fraction 800/8000 in the second particle group \"decimated\". " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Outputting to `.ffly`\n", "At this point we're ready to output our data to `.ffly` format in order to load in with Firefly. The `Reader` object will automatically dump all of the necessary files associated with each of the `ParticleGroup` objects and `Settings` objects we've attached to it as described in the <a href=\"https://alexbgurvi.ch/Firefly/docs/build/html/data_reader/reader.html\">reader documentation</a>." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Outputting: partname - 8000/8000 particles - 1 tracked fields\n", "Outputting: decimated - 800/8000 particles - 1 tracked fields\n" ] }, { "data": { "text/plain": [ "''" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "## have the reader dump all its data to the different JSON files\n", "my_reader.writeToDisk(loud=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that `.writeToDisk` returned an empty string, this is because the `.ffly` and configuration `.json` files were written to disk. Another option is instead to produce a single `.json` formatted string with all the data that would've been written to disk. This is useful for transmitting data through Flask, which is the [subject of another tutorial](http://www.alexbgurvi.ch/Firefly/docs/build/html/data_reader/flask_tutorial.html)." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Outputting: partname - 8000/8000 particles - 1 tracked fields\n", "Outputting: decimated - 800/8000 particles - 1 tracked fields\n", "big_JSON has 451720 characters\n" ] } ], "source": [ "## have the reader dump all its data to a single big string\n", "big_JSON = my_reader.writeToDisk(loud=True,write_to_disk=False,extension='.json')\n", "\n", "print(\"big_JSON has %d characters\"%len(big_JSON))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Using an `ArrayReader` sub-class\n", "\n", "The procedure outlined above is a common use case, and so we've provided a sub-class to `firefly.data_reader.Reader`, `firefly.data_reader.ArrayReader` which wraps the `ParticleGroup` and `.addParticleGroup` so the user can get a `Reader` containing their data with a single initialization. It will automatically name particle groups and fields unless they are specified directly (see <a href=\"https://alexbgurvi.ch/Firefly/docs/build/html/data_reader/reader.html\">reader documentation</a>)." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Make sure each field_array (1) has a field_filter_flag (0), assuming True.\n", "Make sure each field_array (1) has a field_colormap_flag (0), assuming True.\n", "Make sure each field_array (1) has a field_radius_flag (0), assuming False.\n", "Outputting: PGroup_0 - 8000/8000 particles - 1 tracked fields\n" ] } ], "source": [ "my_arrayReader = ArrayReader(\n", " coords,\n", " fields=fields,\n", " JSONdir=JSONdir,\n", " write_to_disk=True)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.7" } }, "nbformat": 4, "nbformat_minor": 4 }