Animating Your Visualizations


Spotfire includes very robust and dynamic visualization capabilities. In addition to offering many different visualization types,  the ability to visualize multiple dimensions, the ability to offer detail visualizations, etc... Spotfire can also animate the data available in visualizations.

By using the SDK, Spotfire can spawn  a thread off the main application thread, allowing periodic updates to the analysis document.  To show how this is done, we will create a custom tool, which will loop through a filter's values, updating the document after each step through.

Assume we have the following data loaded in TIBCO Spotfire Professional

 


We may want to display a Bubble Chart with ‘Group’ on the X-Axis, ‘Sales’ on the Y-Axis, and have the markers sized by ‘Market share %’.

 


 
In order to view how these Groups changed over time, we could trellis by ‘Quarter’, or we  could have the consumer step through  the ‘Quarter’ filter one at a time manually.


Using a Custom Tool, we can automate the step through of the filter.  Below is the code that goes inside our tool to make this word:

      protected override void ExecuteCore(Page context)
        {
            AnalysisApplication application = context.Context.GetService<AnalysisApplication>();
            RefreshDocumentWorker refreshDocumentWorker = new RefreshDocumentWorker(application);
            refreshDocumentWorker.Start();
        }


        private class RefreshDocumentWorker
        {
            private readonly AnalysisApplication application;
            private readonly ApplicationThread applicationThread;
            private bool shallQuit;
            private string filterVal;
            private ItemFilter itemFilter;
            private IList filterValList;


            public RefreshDocumentWorker(AnalysisApplication application)
            {
                this.shallQuit = false;
                this.application = application;
                this.filterVal = "";

                FilterPanel myPanel = application.Document.ActivePageReference.FilterPanel;
                Filter myFilter = myPanel.FilteringSchemeReference.DefaultFilterCollection["Quarter"];
                myFilter.TypeId = FilterTypeIdentifiers.ItemFilter;
                this.itemFilter = myFilter.As<ItemFilter>();

                this.filterValList = this.itemFilter.Values;

                // Fetch the application thread. It is available as an analysis service. 
                this.applicationThread = application.GetService<ApplicationThread>();
            }

 

            public void Start()
            {
                // Ask the application thread to spawn a new thread that executes the RefreshDataLoop. 
                this.applicationThread.ExecuteOnWorkerThread("Document Refresh Thread", RefreshDocumentLoop);
            }

            private bool ShallQuit
            {
                get
                {
                    lock (this)
                    {
                        return this.shallQuit;
                    }
                }
                set
                {
                    lock (this)
                    {
                        this.shallQuit = value;
                    }
                }
            }

            // This method is executed on the worker thread. 
            private void RefreshDocumentLoop()
            {
                foreach (string val in this.filterValList)
                { 
                    // Sleep for 2 seconds. 
                    Thread.Sleep(TimeSpan.FromSeconds(2));

                    // Update the filterVal property
                    this.filterVal = val;

                    this.applicationThread.Invoke(RefreshDocument);
                }
            }


            //This method is executed on the application thread. 
            private void RefreshDocument()
            {
                Document document = this.application.Document;

                if (document == null)
                {
                    this.ShallQuit = true;
                    return;
                }

                ProgressService progressService = application.GetService<ProgressService>();
                progressService.ExecuteWithProgress(
                    "Automatic document refresh",
                    "Refreshing the document to apply the current filter",
                    delegate
                    {
                        this.itemFilter.Value = this.filterVal;
                    });
            }
        }
 


To see a demo of this tool in action, view the URL below: http://spotfire.tibco.com/community/downloads/AnimateFilters.htm


The tool shown in this video is hard coded to step through the ‘Quarter’ filter at 2 second intervals, but for a more production ready tool, these values should be configured through a dialog as the tool launches.


In next week’s tip, we will see how to make this solution work inside the Spotfire Web Player.

If you are interested in learning how to complete a tool like this yourself, consider taking our Developer Bootcamp. If you would like to have Spotfire build this tool or a similar tool for you, please contact Professional Services.