Category: IronPython

Learning IronPython for Spotfire


Ever since I learned what IronPython was and what it could do in Spotfire, I’ve had a “goal” to learn IronPython. I put the word goal in air quotes because learning IronPython isn’t a goal. Or at least, it’s not a very good one because it’s not measurable.  How do I know when I’ve accomplished it? And that’s not to say I haven’t learned any IronPython over the years.  Clearly, I have.  I write about it a lot, but I aspire for deep knowledge.  

The struggle was knowing how to compartmentalize learning IronPython. How could I break it down into something measurable? Finally, in October I commited to 100 hours of IronPython.  Now, that’s measurable.  The amount of time is somewhat arbitrarily.  However, I expected that if I spent 100 hours on IronPython, I would know significantly more than when I started and be able to explain it other people.
So, did that happen? OF COURSE! Heck, I’m only 16 hours in, and I understand so much more now than I did 16 hours ago. Now, you might be saying — Wait, you set the goal in October, and you’re only 16 hours in? Yes. That is correct. I do have a day job and this awesome blog and HOLIDAYS. Stuff happens, but life (and my career) is a long game, so no giving up.
That is my somewhat long-winded explanation to this post. I know all users struggle with applying IronPython in Spotfire, and I want to make that easier on you. Since it’s a bit of an unknown path for me, I can’t break this down into a series like I have other topics. You’ll just see Learning IronPython posts now and again.
This post in particular is going to cover the following…
  1. An explanation of why learning IronPython is so hard
  2. My initial learning goals
  3. My learning methods
  4. Some syntax and structure via a code example
Please feel free to comment if you see places where I am going awry, but be nice.

Why is learning IronPython so hard?

When learning a new coding language, many users look for books or online tutorials. If you google “learn IronPython”, the results are surprisingly sparse. The first result is to a set of documentation, and the second is Quora. Anytime Quora is in your top results, you are in trouble.  The fourth reference is in the UK….you see where this is going.
If you search Amazon for books on IronPython, you get the results shown below.  After 3 or 4 books, the results shift to books about Python. None of the results look suitable for beginners.  Strike two.
At some point, you have to ask, what is IronPython? will tell you…
IronPython is an open-source implementation of the Python programming language which is tightly integrated with the .NET
That might lead you to think that you need to learn Python, and that would be helpful, but Wiki will tell you…..
IronPython is written entirely in C#, although some of its code is automatically generated by a code generator written in Python.Wikipedia
  The hamster wheel is now starting to turn, and perhaps you remembered that Spotfire extensions are also written in C#, and you have seen a reference to C# in the TIBCO API documentation, as shown here.
Wait….you mean I should actually be learning C#??? Yup.  Now, things get a lot easier. 

Learning Goals

Now, it may seem like a bit of backtracking, but I want to explain what I set out to learn. If you’ve read the blog for any length of time, you know I’ve posted IronPython code snippets before. How can I do that but not really know IronPython? Easy…I learn by looking at code online, breaking it down bit by bit, and learning by doing (i.e modern learning). However, without a solid understanding of the underlying architecture, that method is limited. Thus, my primary goals for the first 10 hours were…
  1. Find better resources
  2. Get an understanding of IronPython structure
  3. Get an understanding of the Spotfire API
  4. Apply that understanding in Spotfire code examples
It turns out, that took 16 hours, not 10. I had to put in 16 hours of learning before I felt confident enough to write this post.

Learning Methods

I started my learning process by evaluating what I knew and didn’t know. Right before I kicked off this journey, I learned about The Spotfire IronPython Quick Reference.  This is an amazing website for learning IronPython for Spotfire. I started this code snippet from the Quick Reference to make a basic assessment.
As a result, here are a few questions that came up.  
  1. Why is there no reference to the namespace? Most IronPython that I’ve seen before always starts with the “import something” command.
  2. IronPython is an object-oriented programming language. How do I differentiate between developer named objects and syntax that was part of the code structure?
  3. I know references to the API should be capitalized. If that’s true why are “page” and “visual” in page.Visuals and visual.Title lowercase?
  4. I can see that “Pages” is a property in the Document class. “Visuals” and “Title” are properties in the Page class. “Title” is also a property in the Visual class. Thus, why does the code only call the Document class with “Document.Pages”? There is no reference to the Page class or the Visual class. (This question might be difficult if you aren’t familiar with traversing the Spotfire API).
So, let’s answer those questions.

Syntax & Structure

Why is there no reference to the namespace? Most of the classes in the Spotfire.Dxp.Application namespace load by default, so you don’t have to import. There are some exceptions like DocumentSaveSettings and DocumentOpenSettings. Thank you TIBCO support for that answer.
How do I differentiate between developer named objects and code structure? Simple. You test it. In the code snippet provided, you might wonder if “page” in “for page in Document.Pages:” is part of the code structure or an object. Replace “page” with any other word. If the code runs, it was a named object. If it fails, it’s part of the code structure.  It’s also lower case, so that is a hint.  All references to the API are in uppercase. 
Why are “page” and “visual” in “page.Visuals” and “visual.Title” not capitalized? They are objects, not references to the API. They could be any word.
I can see that “Pages” is a property in the Document class. “Visuals” and “Title” are properties in the Page class. “Title” is also a property in the Visual class. Thus, why does the code only call the Document class with “Document.Pages”?  To follow along with the answer to this, go to the Spotfire API reference. Open the Spotfire.Dxp.Application namespace (first namespace in the API). Click on the Document Class. The intro to the Document Class says this:
A document opened in a running instance of TIBCO Spotfire is referred to as an Analysis Document. The document not only contains a series of metadata information (see DocumentMetadata), but it also contains references to the data itself (see DataManager), and to various other components being part of the document, such as pages, filterings, bookmarks, etc. As soon as data has been opened in TIBCO Spotfire, an instance of this class can be accessed through the Document property of the AnalysisApplication. This is regardless of whether the data was opened through the user interface or programmatically. TIBCO Support
There’s a lot going on in that statement.  To explain it, go to the Spotfire.Dxp.Application namespace and click on the line below it that says AnalysisApplication Class.
You can see that Document is, in fact, a property of the namespace, as indicated in the description.  If you click on Document, it jumps to the Document class.  How does that answer the original question?  We’ll get there.  I just wanted to start with an explanation from the API and show you how navigating it works.  Our original question asked about the Document class, which is where you should be in the API reference if you are following along. So….
Pages is a property of the Document class. The code “for page in Document.Pages:” will get the pages of the document. More specifically, it is getting a collection of pages.  If you click on the Pages property in the Document class, it will take you to the screen show below.  There, you’ll note that the Type = PageCollection. The pages of the document are part of a PageCollection.  Now, click on PageCollection.
Now you jump down to the PageCollection class, which is below the Page Class and essentially because you are in the PageCollection Class you also have access to the properties of the Page class.  Title and Visuals are both properties of the Page class (as noted a while ago in the post).   The code only calls the Document class because you can access Title and Visuals by navigating the hierarchy as we just did.
As someone new to understanding the structure, I find this a bit confusing.  Because the API reference is organized like a tree, I expect to navigate it in a certain way, and that is clearly not how it should be navigated.  Hopefully, this will make more sense in another 10 hours or so.


Once I started searching for C# references, I found several very good tutorials worth sharing. To keep everything straight, I started saving tutorials and links by C# structure/syntax so I could have them handy and not have to search each time.  I’ve made the list available for you in this post. I will maintain this as I move thru learning. Please feel free to comment with other links, and I’ll add them.

Spotfire Version

All content created with Spotfire 7.12.

Guest Spotfire blogger residing in Whitefish, MT.  Working for SM Energy’s Advanced Analytics and Emerging Technology team!

How to Add Lines to a Probit Plot with IronPython

A few weeks ago, I wrote a post detailing how to create a multiple variable probit plot.  This post improved upon an older post on creating a single variable probit plot.  Part of those instructions included adding several “supplemental” lines via Lines and Curves like P10, P90, and the Median.  This is actually the most time-consuming part of the process.  Each line must be added one by one.

Today, while reviewing my instructions, I realized I had to do better. I know this can be done with IronPython! A quick Google search pulled up this TIBCO community post that I was able to use as a guide. I modified that script to work for my probit plot use case. Now, I have a piece of code that will add all of those lines and is easily modifiable and scalable.

The Code

Here is what the code looks like in my DXP.  I made the following modifications from TIBCO’s original:

  1. Changed BarChart to ScatterPlot to suit my visualization
  2. Modified the expressions from an average to the Percentile, P10, P90, and Median.
  3. Added code for vertical lines.

Code for Copy & Paste

from Spotfire.Dxp.Application.Visuals import *

scatterPlot = sp.As[ScatterPlot]()

#Add Horizontal Straight Line
horizontalLine1 = scatterPlot.FittingModels.AddHorizontalLine(‘P90([Y])’)
horizontalLine2 = scatterPlot.FittingModels.AddHorizontalLine(‘P10([Y])’)
horizontalLine3 = scatterPlot.FittingModels.AddHorizontalLine(‘Median([Y])’)
horizontalLine4 = scatterPlot.FittingModels.AddHorizontalLine(‘Percentile([Y],20)’)
horizontalLine5 = scatterPlot.FittingModels.AddHorizontalLine(‘Percentile([Y],30)’)
horizontalLine6 = scatterPlot.FittingModels.AddHorizontalLine(‘Percentile([Y],40)’)
horizontalLine7 = scatterPlot.FittingModels.AddHorizontalLine(‘Percentile([Y],60)’)
horizontalLine8 = scatterPlot.FittingModels.AddHorizontalLine(‘Percentile([Y],70)’)
horizontalLine9 = scatterPlot.FittingModels.AddHorizontalLine(‘Percentile([Y],80)’)

#Add Vertical Straight Line
verticalLine1 = scatterPlot.FittingModels.AddVerticalLine(’10’)
verticalLine2 = scatterPlot.FittingModels.AddVerticalLine(‘100’)
verticalLine3 = scatterPlot.FittingModels.AddVerticalLine(‘1000’)

Detailed Steps

  1. Add a Text Area to the page, right-click, select Edit HTML.
  2. Click the Add Action Control button.
  3. Name the button.
  4. Click the Script button.
  5. Click the New button.
  6. Name the script.
  7. Copy and paste code.  Modify to suit.
  8. Add a parameter called “sp” and connect it to your visualization.
  9. Run script to test. Click OK to close on script window.
  10. Modify the HTML as shown to hide the button.  You don’t want to click it again.


  1. Once you run the script, it does not need to be run again.  When you clicked Run Script the first time, 13 lines were created.  Clicking again will create another 13 lines.  I made this mistake when testing.  Then, I had to delete a ton of lines one by one! (Please upvote my Idea to allow users to delete more than one line at a time).
  2. The script creates the lines, but you still have to edit them one by one.  This might also be possible with IronPython, but I haven’t dug that far yet.
  3. If you copy and paste from my code snippet above, you’ll need to replace the quotes.  Spotfire won’t recognize them correctly from copy and paste.

This should make setting up probit plots just a little bit faster.  You can also modify this code any time you want to add multiple lines to a different visualization or another probit plot.

Spotfire Version

Content created with Spotfire 7.12.

Guest Spotfire blogger residing in Whitefish, MT.  Working for SM Energy’s Advanced Analytics and Emerging Technology team!

IronPython to Turn Panels On & Off

  • Are you building projects for users who aren’t familiar with Spotfire’s concept of panels?
  • Would you like to be able to turn panels on and off with the click of a button?
  • Do you want to learn a little bit more about IronPython?

Read More

Guest Spotfire blogger residing in Whitefish, MT.  Working for SM Energy’s Advanced Analytics and Emerging Technology team!

IronPython to Sort the Bars of a Combination Chart

  • Are you running an older version of Spotfire (7.9 or lower)?
  • Would you like to be able to sort the bars of a combination chart in the same way that you can sort the bars in a bar chart?
  • Would you like a little bit more control over the appearance of combination charts?
  • Are you working on IronPython skills?

Read More

Guest Spotfire blogger residing in Whitefish, MT.  Working for SM Energy’s Advanced Analytics and Emerging Technology team!

IronPython to reset all tags

For a recent project, we wanted the user of a Spotfire template to be able to reset all the tags, including both built-in tags and tags the user may have added, with a single click.

One solution is to use an IronPython script to reset each tag collection in the template, keeping in mind that, if we hard-code the names of the tags to reset, we won’t be able to handle cases where users have added custom tags. In order to reset tags that may be added later on, we can use Spotfire’s IronPython API to identify and reset tag columns on the fly.

Here is what the code looks like in Spotfire:

And in more copy/paste-friendly format:

from Spotfire.Dxp.Data import *
from System import Array

for table in Document.Data.Tables:
    for column in table.Columns:
        if str(column.Properties.ColumnType) == “Tags”:
            tagCollectionName = column.Properties.Name
            tagColumn = column.As[TagsColumn]()
            tagNames = Array[str](tagColumn.TagValues)

Notes on the code:

This script loops over all the tables in the Spotfire analysis and checks the type of each column. When we locate a tags column, we extract the name of the tag collection, as well as any associated tags, drop the column from the data table, and create the tags collection anew. We can use this approach to reset all tags with one command because, by default, all datapoints are untagged when a “new” tag collection is created. The script will reset all tags in the analysis, including custom tags added by the user, and it will simply exit quietly if there are no tags. There are no input/output parameters for this script, but we could use input parameters to apply the same tag-resetting logic to a specific subset of the data.

Spotfire Version

Content created with Spotfire 7.12

Data Science Intern at and  Applied Physics PhD candidate at Rice University

Exporting Spotfire to PDF with Action Control Button

Recent Spotfire versions include the ability to export visualizations, pages, or the entire analysis into a PDF from the File menu or even with an Action Control button.  Finally!  Version 7.12 includes extremely user friendly customization options while previous versions require some IronPython code:  we will address both here.

The 7.12 version gives the user an interface for customization that we could previously only access via IronPython.  Spotfire has delivered what many users for years have clamored for, so check it out after the break…

Read More

Jason is a Junior Data Scientist at with a Master’s degree in Predictive Analytics and Data Science from Northwestern University. He has experience with a multitude of machine learning techniques such as Random Forest, Neural Nets, and Hidden Markov Models. With a previous Master’s in Creative Writing, Jason is a fervent believer in the Oxford comma.