npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gov.nasa.jpl.honeycomb/telemetry-animator

v0.0.6

Published

Classes for iterating, animating, and scrubbing over time series data.

Downloads

3

Readme

Telemetry Animator

Animators that take a set of data frames and tracks playback.

Frames are expected in the following form and sorted by time. Time is not required to be in a specific format.

[
    {
        time: <number>,
        state: <object>
    },
    ...
]

!> The KeyframeAnimator and LiveAnimator classes use the object-cache package to cache keyframes so it is assumed that all array data is consistently typed.

Use

Using an Animator

import { TelemetryAnimator } from '@gov.nasa.jpl.honeycomb/telemetry-animator';

// ...

const animator = new TelemetryAnimator(frames);
animator.onChange = state => {
    console.log('New State: ', state);
}

let lastTime = window.performance.now();
const loop = () => {
    const delta = window.performance.now() - lastTime;
    lastTime = window.performance.now();

    animator.step(delta);

    requestAnimationFrame(loop);
}

Adding Custom Telemetry Rollup

import { CustomTelemetryAnimator } from '@gov.nasa.jpl.honeycomb/telemetry-animator';

const mergeMap = {

    data: ( from, to ) => {

        if ( ! Array.isArray( to ) ) {

            to = [];

        }
        to.push( from );

    }

};

const frames = [
    { time: 1, state: { data: 1 } },
    { time: 2, state: { data: 2 } },
];
const animator = new CustomTelemetryAnimator( frames, { mergeMap } );
animator.setTime( 3 );

console.log( animator.state );
// { data: [ 1, 2 ] }

Data from a Websocket

import { TelemetryAnimator } from '@gov.nasa.jpl.honeycomb/telemetry-animator';
const animator = new TelemetryAnimator();

// Disable seekability so we always display the latest
// websocket data and we won't keep old data around.
animator.seekable = false;
ws.on('data', e => {

    animator.addFrames([{
        time: window.performance.now(),
        state: e.state,
    }]);

});

animator.addEventListener('change', () => {
    animator.setTime(window.performance.now());
});

Seekable data from a Websocket

TODO

Preprocessing Data From File Paths in State

import { TelemetryAnimator, LookAheadAnimatorMixin } from '@gov.nasa.jpl.honeycomb/telemetry-animator';

const LookAheadAnimator = LookAheadAnimatorMixin(TelemetryAnimator);
const animator = new LookAheadAnimator();

const cache = {};
animator.preloadData = function( state ) {

    if ( 'filePath' in state ) {

        const path = state.filePath;

        if ( ! ( path in cache ) ) {

            const controller = new AbortController();
            const info = {};
            info.controller = controller;
            info.references = 0;
            info.promise = fetch( path, { signal: controller.signal } )
                .then( res => res.buffer() )
                .then( buffer => ( info.buffer = buffer ) );
            cache[path] = info;

        }

        info.references ++;
        return info.promise;

    } else {

        return null;

    }

};

animator.unloadData = function( state ) {

    if ( 'filePath' in state ) {

        const path = state.filePath;
        const info = cache[ path ];
        info.references --;
        if ( info.references === 0 ) {

            info.controller.abort();
            delete cache[ path ];

        }

    }

}

animator.preprocessState = function( state ) {

    if ( 'filePath' in state ) {

        const path = state.filePath;
        const info = cache[ path ];
        if ( info.buffer ) {

            state.loadedData = buffer;
            return true;

        }

    }

    return false;

}

Buffering Large Files from HTTP

import { TelemetryAnimator, BuferedAnimatorMixin } from '@gov.nasa.jpl.honeycomb/telemetry-animator';

const BufferedAnimator = BuferedAnimatorMixin(TelemetryAnimator);
const animator = new BufferedAnimator();
animator.getFrames = function( time, duration ) {

    return fetch( `./data/server/?time=${ time }&duration=${ duration }` )
        .then( res => res.json() )
        .then( json => json.frames );

};

Buffering Large Files from Disk

import { TelemetryAnimator, BuferedAnimatorMixin } from '@gov.nasa.jpl.honeycomb/telemetry-animator';

const BufferedAnimator = BuferedAnimatorMixin(TelemetryAnimator);
const animator = new BufferedAnimator();
animator.getFrames = async function( time, duration ) {

    let frames;

    // ... read frame data at times from disk into frames variables in an async manner ...

    return frames;

};

Preprocessing a file to use Keyframes

import { TelemetryAnimator, KeyframeAnimatorMixin, BufferedAnimatorMixin } from '@gov.nasa.jpl.honeycomb/telemetry-animator';

const AnimatorClass = KeyframeAnimatorMixin(BuferedAnimatorMixin(TelemetryAnimator));
const animator = new AnimatorClass();

// ... set up buffered animator functions ...

await animator.generateKeyframes();

Live Data With File Cache

TODO

API

Functions

BufferedAnimatorMixin

BufferedAnimatorMixin( base : class ) : void

Mixin function that produces a new class that inherits from base and mixes in BufferedAnimator. Base class is expected to derive from TelemetryAnimator.

LookAheadAnimatorMixin

LookAheadAnimatorMixin( base : class ) : void

Mixin function that produces a new class that inherits from base and mixes in LookAheadAnimator. Base class is expected to derive from TelemetryAnimator.

KeyframeAnimatorMixin

KeyframeAnimatorMixin( base : class ) : void

Mixin function that produces a new class that inherits from base and mixes in KeyframeAnimator. Base class is expected to derive from TelemetryAnimator.

Frame

time

time : Number

The time in milliseconds that this frame is associated with.

state

state : Object

An object that represents a set of data for this time.

TelemetryAnimator

Class that manages and can step through a set of frames over time.

extends EventDispatcher

Events

added-frames

Fired when new frames are added to the animator.

change

Fired when the rolled up state has changed.

reset

Fired when the animator has been reset.

dispose

Fired when the animator has been disposed.

ready

ready : Boolean

Returns whether or not frames are available to be animated.

startTime

startTime : Number

The beginning time for the frames.

endTime

endTime : Number

The end time for the frames.

seekable

seekable : Boolean = true

Whether or not this animator can be rewound. Set this to false if using a websocket and frames are being streamed in using .addFrames. If false old data behind the playhead will be discarded.

!> Note that if the playhead is not kept at the latest frame using .setTime then frames could be accumulated using addFrames and overrun available memory.

nonSeekableBuffer

nonSeekableBuffer : Number = 0

The duration of frames to retain when seekable === false.

liveData

liveData : Boolean = false

A field indicating that the data provided by the animator is coming in live, such as through a websocket. This doesn't change the behavior of the class and is just an informative flag.

continuous

continuous : Boolean = false

If true indicates that data can be interpolated and if the time is set to before the start time of the frames the initial frame data is assumed to be set before frame 0.

interpolate

interpolate : Boolean = true

If true then the values in returned state are interpolated when the current time lands in between frames.

traverseArrays

traverseArrays : Boolean = false

By default arrays in states are copied when being merging states rather than merging objects within the array. Setting this field to true enables copying and deep merging objects within the array.

stale

stale : Boolean = false

If true indicates that the current data is out of date and waiting on something to be up to date. This flag can be set by derivative animators that dynamically fetch data from the server or preprocess data and may not be ready immediately especially when jumping ahead.

frames

frames : Array<Frame> = null

The array of frames the animator will iterate over.

time

time : Number = 0

The current time the animator has iterated up to and that state is set to.

state

state : Object

The last state stepped to. If interpolation = true then this will included interpolation.

constructor

constructor( frames : Array<Frames> = null ) : void

setTime

setTime( time : Number ) : Promise

Set the time to track the animator up to. Frames will be iterated over to the given time and merged using the mergeState function. If the given time is between frames and interpolate is true, then the interpolateState function will be used to interpolate the data.

The resultant state will be set on state and the current time on time.

findFrameAtTime

findFrameAtTime( time : Number, nextFrame : Boolean = false ) : Frame

Performs a binary search to find the frame at the given time. Returns the frame (which should not be modified) that occurs on or right before the given time. If nextTime is true then the frame after the given time is returned.

getNextSignificantTime

getNextSignificantTime(  ) : Number

Returns the time of the next frame after the current time that the animator is at.

getPrevSignificantTime

getPrevSignificantTime(  ) : Number

Returns the time of the previous frame before the current time that the animator is at.

reset

reset(  ) : Promise

Resets the animation to time 0. This is called every time the time is reversed in order to re-roll up all frames to the new time. Returns a promise when the animator has finished resetting in case setting the time requires asynchronous loading.

forEachFrame

forEachFrame( cb : ( frame : Frame ) => void, options : Object = null ) : Promise

Iterates over and calls cb for every frame in the data set. By default every frame is iterated over and merged. If the callback returns "true" then the iteration ends early. The set of options available options are:

{
     // If true then an unmerged frame state will be provided
     raw = false : boolean,

     // The time bounds over which to iterate. Defaults to all frames
     startTime : number,
     endTime : number
}

Returns a promise that resolves when all frames have been iterated over in the case that frames need to be loaded and processed asynchronously.

seekBack

seekBack( cb : ( frame : Frame ) => void, fromTime : Number | null = null ) : void

Look back through all available frames that are currently loaded. Stops when "true" is returned from the callback or all data is iterated over. Raw, unmerged frame state data is passed into the callback

optimize

optimize(  ) : void

Merges any frames that describe the same point in time to minimize the amount of frames stored and iterated over.

sort

sort(  ) : void

Sorts the frames by the time field.

addFrames

addFrames( newFrames : Array<Frame> ) : void

Appends the given frames to the list of loaded frames. It is assumed that these frames are already sorted and come after the set of already loaded frames.

dispose

dispose(  ) : void

Marks the animator as disposed so any async tasks can cancel and not resolve.

interpolateState

interpolateState( currState : Object, nextState : Object, ratio : Number, target : Object ) : void

The function that is called to interpolate a state object. The interpolated values are expected to be placed on the target object. currState and nextState are to not be modified. The target object (or a replacement for it) is expected to be returned.

Intended to be overriden by derivative classes. By default only shallow fields are interpolated.

mergeState

mergeState( from : Object, to : Object ) : void

The function that is called to merge states when iterating over frames. The fields from from are expected to be copied or moved onto to.

Intended to be overriden by derivative classes. By default only shallow fields are moved onto to.

JoinedTelemetryAnimator

Animator made up of multiple animators and produces a state composed of all frame data in the child canimators.

extends TelemetryAnimator, EventDispatcher

ready

ready : Boolean

seekable

seekable : Boolean

liveData

liveData : Boolean

interpolate

interpolate : Boolean

stale

stale : Boolean

endTime

endTime : Number

startTime

startTime : Number

generatingKeyframes

generatingKeyframes : Boolean

generatedKeyframesUpTo

generatedKeyframesUpTo : Number

animators

animators : Object<String, TelemetryAniamtor>

state

state : Object

time

time : Number

constructor

constructor( animators : Object<String, TelemetryAniamtor> = {} ) : void

addAnimator

addAnimator( animator : TelemetryAnimator, id : String ) : void

Add an animator with the given name.

removeAnimator

removeAnimator( name : String ) : void

Removes the animator with the given name.

NestedTelemetryAnimator

Telemetry Animator that can handle interpolating nested objects

extends TelemetryAnimator

args

args : ...null

BufferedAnimator

Mixin class used for dynamically reading frames from disk or fetching them in chunks via a custom getFrames implementation. Use if the full set of frame data cannot be loaded at once.

chunkSize

chunkSize : Number = 1

The size of a "chunk" of frames or the amount of frames to load at once relative to the datas time scale

buffer

buffer : Number = 5

The buffer amount relative to the datas time scale before and after the current time to load.

constructor

constructor( options : Object = {} ) : void

Frames array is not taken because it is read as needed.

CustomTelemetryAnimator

Provides means for creating an animator with custom merge and interpolate functions for different sub objects.

extends NestedTelemetryAnimator

constructor

constructor( frames : Array<Frame>, options : Object = {} ) : void

Options object can take a value for interpolateMap and #CustomTelemetryAnimator#mergeMap.

LiveAnimator

A wrapper animator that helps facilitate live data playback and caching of frames for scrubbing.

extends TelemetryAnimator, EventDispatcher

endTime

endTime : Boolean

startTime

startTime : Boolean

stale

stale : Boolean

state

state : Object

interpolate

interpolate : Boolean

traverseArrays

traverseArrays : Boolean

connected

connected : Boolean

connectionHost

connectionHost : String

connectionChangeTime

connectionChangeTime : Date | null

constructor

constructor(
	streamingAnimator : TelemetryAnimator, 
	bufferedKeyframeAnimator : BufferedKeyframeAnimator
) : void

Takes an animator that is filled with the latest streaming data and another that spools and reads data to and from disk for scrolling back in time.

LookAheadAnimator

Mixin class used for premptively loading data for upcoming (and previous) frames within some threshold. Used when frame data contains references to external data that must be loaded ahead of time. When frames leave the provided window any loaded data is unloaded and pending loads are cancelled.

lookAhead

lookAhead : Number = 1000

The amount of time in milliseconds to look ahead to prep loaded data.

lookBack

lookBack : Number = 100

The amount of time in milliseconds to look back to prep loaded data.

KeyframeAnimator

Mixin class used for generating keyframes up front using an ObjectCache and reading those keyframes as the time is scrubbed to avoid having to iterate over all prior frames. Used for cases when all telemetry data must be progressively read from disk on demand because it's too much to read into memory.

keyframeStride

keyframeStride : Number = 5

The time relative to the datas time scale between generated keyframes.

generatingKeyframes

generatingKeyframes : Boolean

Whether or not keyframes are actively being generated.

generatedKeyframesUpTo

generatedKeyframesUpTo : Number

The time in milliseconds that keyframes have been generated up to.