Git Product home page Git Product logo

streamjoy's Introduction

๐ŸŒˆ StreamJoy ๐Ÿ˜Š


build codecov PyPI version

Downloads GitHub stars


๐Ÿ”ฅ Enjoy animating!

Streamjoy turns your images into animations using sensible defaults for fun, hassle-free creation.

It cuts down the boilerplate and time to work on animations, and it's simple to start with just a few lines of code.

Install it with just pip to start, blazingly fast!

pip install streamjoy

Or, try out a basic web app version here:

https://huggingface.co/spaces/ahuang11/streamjoy

๐Ÿ› ๏ธ Built-in features

  • ๐ŸŒ Animate from URLs, files, and datasets
  • ๐ŸŽจ Render images with default or custom renderers
  • ๐ŸŽฌ Provide context with a short intro splash
  • โธ Add pauses at the beginning, end, or between frames
  • โšก Execute read, render, and write in parallel
  • ๐Ÿ”— Connect multiple animations together

๐Ÿš€ Quick start

๐Ÿค Absolute basics

Stream from a list of images--local files work too!

from streamjoy import stream

if __name__ == "__main__":
    URL_FMT = "https://www.goes.noaa.gov/dimg/jma/fd/vis/{i}.gif"
    resources = [URL_FMT.format(i=i) for i in range(1, 11)]
    stream(resources, uri="goes.gif")  # .gif, .mp4, and .html supported

๐Ÿ’… Polish up

Specify a few more keywords to:

  1. add an intro title and subtitle
  2. adjust the pauses
  3. optimize the GIF thru pygifsicle
from streamjoy import stream

if __name__ == "__main__":
    URL_FMT = "https://www.goes.noaa.gov/dimg/jma/fd/vis/{i}.gif"
    resources = [URL_FMT.format(i=i) for i in range(1, 11)]
    himawari_stream = stream(
        resources,
        uri="goes_custom.gif",
        intro_title="Himawari Visible",
        intro_subtitle="10 Hours Loop",
        intro_pause=1,
        ending_pause=1,
        optimize=True,
    )

๐Ÿ‘€ Preview inputs

If you'd like to preview the repr before writing, drop uri.

Output:

<AnyStream>
---
Output:
  max_frames: 50
  fps: 10
  display: True
  scratch_dir: streamjoy_scratch
  in_memory: False
---
Intro:
  intro_title: Himawari Visible
  intro_subtitle: 10 Hours Loop
  intro_watermark: made with streamjoy
  intro_pause: 1
  intro_background: black
---
Client:
  batch_size: 10
  processes: True
  threads_per_worker: None
---
Resources: (10 frames to stream)
  https://www.goes.noaa.gov/dimg/jma/fd/vis/1.gif
  ...
  https://www.goes.noaa.gov/dimg/jma/fd/vis/10.gif
---

Then, when ready, call the write method to save the animation!

himawari_stream.write()

๐Ÿ–‡๏ธ Connect streams

Connect multiple streams together to provide further context.

from streamjoy import stream, connect

URL_FMTS = {
    "visible": "https://www.goes.noaa.gov/dimg/jma/fd/vis/{i}.gif",
    "infrared": "https://www.goes.noaa.gov/dimg/jma/fd/rbtop/{i}.gif",
}

if __name__ == "__main__":
    visible_stream = stream(
        [URL_FMTS["visible"].format(i=i) for i in range(1, 11)],
        intro_title="Himawari Visible",
        intro_subtitle="10 Hours Loop",
    )
    infrared_stream = stream(
        [URL_FMTS["infrared"].format(i=i) for i in range(1, 11)],
        intro_title="Himawari Infrared",
        intro_subtitle="10 Hours Loop",
    )
    connect([visible_stream, infrared_stream], uri="goes_connected.gif")

๐Ÿ“ท Render datasets

You can also render images directly from datasets, either through a custom renderer or a built-in one, and they'll also run in parallel!

The following example requires xarray, cartopy, matplotlib, and netcdf4.

pip install xarray cartopy matplotlib netcdf4
import numpy as np
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
from streamjoy import stream, wrap_matplotlib

@wrap_matplotlib()
def plot(da, central_longitude, **plot_kwargs):
    time = da["time"].dt.strftime("%b %d %Y").values.item()
    projection = ccrs.Orthographic(central_longitude=central_longitude)
    subplot_kw = dict(projection=projection, facecolor="gray")
    fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=subplot_kw)
    im = da.plot(ax=ax, transform=ccrs.PlateCarree(), add_colorbar=False, **plot_kwargs)
    ax.set_title(f"Sea Surface Temperature Anomaly\n{time}", loc="left", transform=ax.transAxes)
    ax.set_title("Source: NOAA OISST v2.1", loc="right", size=5, y=-0.01)
    ax.set_title("", loc="center")  # suppress default title
    plt.colorbar(im, ax=ax, label="ยฐC", shrink=0.8)
    return fig

if __name__ == "__main__":
    url = (
      "https://www.ncei.noaa.gov/data/sea-surface-temperature-"
      "optimum-interpolation/v2.1/access/avhrr/201008/"
    )
    pattern = "oisst-avhrr-v02r01.*.nc"
    stream(
        url,
        uri="oisst.gif",
        pattern=pattern,  # GifStream.from_url kwargs
        max_files=30,
        renderer=plot,  # renderer related kwargs
        renderer_iterables=[np.linspace(-140, -150, 30)],  # iterables; central longitude per frame (30 frames)
        renderer_kwargs=dict(cmap="RdBu_r", vmin=-5, vmax=5),  # renderer kwargs
        # cmap="RdBu_r", # renderer_kwargs can also be propagated for convenience
        # vmin=-5,
        # vmax=5,
    )

Check out all the supported formats here or best practices here. (Or maybe you're interested in the design--here)


โค๏ธ Made with considerable passion.

๐ŸŒŸ Appreciate the project? Consider giving a star!

streamjoy's People

Contributors

ahuang11 avatar zhihua-zheng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

streamjoy's Issues

Max frames not respected

Something is not being propagated properly between:
df.streamjoy(max_frames=max_frames)
vs
stream(max_frames=max_frames)
vs
GifStream().write(max_frames=max_frames)
vs
GifStream(max_frames=max_frames).write()

Example when using Dask Gateway cluster (remote workers)

Is your feature request related to a problem? Please describe.

I'm not sure how to write the image files to scratch when using a remote dask cluster (e.g. a Dask Gateway cluster, where the workers are running on kubernetes and don't see the local filesystem)
https://nbviewer.org/gist/rsignell/9cd38657ca9ad20e55799bf41cb80de6

Is there a way to use streamjoy already with this type of Dask cluster?
If not, what would be the best way?
Can the scratch images be stored in memory or on object storage?

import stream __init__() unexpected argument 'check_exists'

Wanted to start using streamjoy after looking at your NMME forecast example to produce something similar. Started of with your minimum working project:

Initial hurdle after pip installing steamjoy

# Traceback / Example
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[2], line 1
----> 1 from streamjoy import stream

File ~/miniconda3/envs/cda/lib/python3.11/site-packages/streamjoy/__init__.py:4
      1 import logging
      3 from ._utils import update_logger
----> 4 from .core import connect, stream
      5 from .models import ImageText, Paused
      6 from .renderers import (
      7     default_holoviews_renderer,
      8     default_pandas_renderer,
      9     default_xarray_renderer,
     10 )

File ~/miniconda3/envs/cda/lib/python3.11/site-packages/streamjoy/core.py:7
      4 from pathlib import Path
      5 from typing import Any, Callable, Literal
----> 7 from . import streams
      8 from .serializers import serialize_appropriately
      9 from .settings import extension_handlers

File ~/miniconda3/envs/cda/lib/python3.11/site-packages/streamjoy/streams.py:64
     60     except ImportError:
     61         pn = None
---> 64 class MediaStream(param.Parameterized):
     65     """
     66     An abstract class for creating media streams from various resources.
     67     Do not use this class directly; use either GifStream or Mp4Stream.
     68 
     69     Expand Source code to see all the parameters and descriptions.
     70     """
     72     resources = param.List(
     73         default=None,
     74         doc="The resources to render.",
     75     )

File ~/miniconda3/envs/cda/lib/python3.11/site-packages/streamjoy/streams.py:177, in MediaStream()
    166 threads_per_worker = param.Integer(
    167     default=None,
    168     bounds=(1, None),
    169     doc="The number of threads to use per worker.",
    170 )
    172 show_progress = param.Boolean(
    173     default=True,
    174     doc="Whether to show the progress bar when rendering.",
    175 )
--> 177 scratch_dir = param.Path(
    178     doc="The directory to use for temporary files.", check_exists=False
    179 )
    181 in_memory = param.Boolean(
    182     doc="Whether to store intermediate results in memory.",
    183 )
    185 fsspec_fs = param.Parameter(
    186     doc="The fsspec filesystem to use for reading and writing.",
    187 )

File ~/miniconda3/envs/cda/lib/python3.11/site-packages/param/__init__.py:1779, in Path.__init__(self, default, search_paths, **params)
   1776     search_paths = []
   1778 self.search_paths = search_paths
-> 1779 super(Path,self).__init__(default,**params)

TypeError: Parameter.__init__() got an unexpected keyword argument 'check_exists'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.