Jump to content

Execution of IronPython script after visualization update.


Funny Cat
Go to solution Solved by Andrew Berridge,

Recommended Posts

Hi,

I'm using an IronPython script to update zoom slider positions in two charts after document property change. The document property is set by a data function.

On change of a marking, the visualizations were updated and afterwards the IronPython script was executed.

This worked great until I had to restart Spotfire.

Now, it seems that when I change the marking, first the script is executed setting the zoom sliders and afterwards the visualizations are updated, resetting the zoom sliders to the default range.

That's not the intended behaviour. I'd like to refresh the visualization before executing the script.

Thanks in advance for helping!

Link to comment
Share on other sites

I am not sure why this is happening. When you say "when I change marking", what do you mean? Do you mean, change the marking settings, or when marking rows? How does that trigger anything? Are the marked rows an input to the data function?

Perhaps you can explain the whole flow?

Updating a visualisation should not reset the zoom slider positions, unless you are calling AutoConfigure() on the visualisations, or are unintentionally resetting the zoom slider positions?

If you can't figure this out through the natural flow of operations, you may wish to consider executing some code asynchronously after a delay. Here is a very simple example of how to execute some code on the ApplicationThread:

from Spotfire.Dxp.Framework.ApplicationModel import *
 
def test():
	print "hello"
 
applicationThread = Application.GetService[ApplicationThread]().Invoke(
	test
)

You can also execute asynchronously, with a delay. Something like this:

from Spotfire.Dxp.Framework.ApplicationModel import *
 
def test():
	sleep(5000)
	# Do something else
 
applicationThread = Application.GetService[ApplicationThread]().InvokeAsynchronously(
	test
)

Note that we can't see any output in this example (hence why I have removed the print statement). I believe this is because the asynchronous method has no ability to write back to the output window, so I would initially develop the script to run synchronously.

Thanks,

Andrew

Link to comment
Share on other sites

Hi Andrew,

ok, I'm trying to make it more detailed.

I'm using TIBCO Spotfire Analyst 12.0.0 LTS / Build version 12.0.0.223

I've got a source dataset containing x/y coordinates and many columns with different electrical parameter values.

In a second dataset there are spec limits for the single parameters.

What I'm trying to achieve is a dashboard containing

  • a cross table showing statistical values for each parameter
  • a histogram (limitted to the marked parameter of the cross table)
  • a boxplot (also limitted to the marked parameter)
  • a heatmap (also limitted to the marked parameter)

I'd like to have electrical parameters and the respective spec limits in a single table, therefore I'm making a dataset unpivotting the source dataset, so that I get a single "Parameter" and "Value" column. Afterwards, I'm joining the spec limits from the second table.

This is important because I want to calculate additional columns, indicating, whether a row is pass/fail or an outlier, etc.

The cross table is containing the list of parameters on the vertical axis and several statistical values (mean, median, stdev, cpk, ... spec limits) in the cell values.

As stated above, I wan't to limit the data of the histogram, box plot and heatmap to the selected parameter. So I just created a details visualization for them.

The histogram and the box plot should also show the spec limits as vertical and horizontal lines respectively. So I added those lines from the dataset.

Since the data sometimes has large outliers, the data of interest (e.g. spec range +/-10%) on histogram and boxplots would be barely visible, so I want to set the zoom sliders to the a sensible range. (Of course I could also filter the outliers, but I want to keep them in the charts just in case someone wants to look at the data. So setting of the zoom sliders is preferred.)

Also I want 500 histogram bins within the spec range, so I need to calculate the number of total bins. (I didn't succeed using on the following expression on the x-axis: AutoBinNumeric([Value],Integer(500 * (Max([Value]) - Min([Value])) / (Median([uSL]) - Median([LSL])))) , but it works when I use AutoBinNumeric([Value],Integer(${Bins})) , so I just use a document property for the number of bins.)

To set the zoom sliders, I created 4 document properties

  • LSL
  • USL
  • Bins
  • SelectedParameter

Those I set via data functions using an R-script

output <- mean(input)

and

output <- input

, limitting the data to the marking.

For LSL and USL the inputs are just the LSL and USL columns. For the Bins property I use above formula. Outputs are the respective document properties.

For SelectedParameter I use the expression First(["dataset"].[Parameter]) in a custom expression as input and the document property as output.

So when I select another row in the cross table (that's what I meant with "change the marking"), those properties are all updated.

Additionally, on change of the SelectedParameter property I run a script SetZoomRange to set the range of the zoom sliders.

from Spotfire.Dxp.Application.Visuals import VisualContentfrom Spotfire.Dxp.Application.Visuals import AxisRangefrom Spotfire.Dxp.Data import DataPropertyClass vc = vis.As[VisualContent]() # this is the histogramvc2 = vis2.As[VisualContent]() # this is the boxplot min = Document.Properties["LSL"]-(Document.Properties["USL"]-Document.Properties["LSL"])*0.1max = Document.Properties["USL"]+(Document.Properties["USL"]-Document.Properties["LSL"])*0.1 vc.XAxis.ZoomRange = AxisRange(min,max)vc2.YAxis.ZoomRange = AxisRange(min,max)

When I run the script manually, the zoom slider positions are exactly as they should be.

However, when the script is triggered by the changed selection in the cross table, leading to a change of the document property SelectedParameter, something is odd.

(Previously I mentioned, zoom sliders are reset. Sorry this is not true.)

I can't figure out how the zoom sliders are set. Sometimes it seems the zoom sliders are set to the intended value of the previously selected parameters. Sometimes, the upper or the lower slider is correct.

Also when I switch the selection between two parameters, I do not always get the same slider positions.

I think it depends on how fast I switch between the two parameters.

And, the zoom of the histogram and the boxplot are different in case I set the number of histogram bins to the document property ${Bins} If I'm setting the number of histogram bins to a fixed value, the zoom of the histogram and the boxplot are equal.

Link to comment
Share on other sites

I tried the two suggested methods.

The asynchronous method seems to not execute the function "test" at all. Not only that there's nothing in the output window, as you had stated already, also the zoom sliders are not moving.

The synchronous method works when I run the script manually.

When it's run automatically after the document property change, it's not working.

I figured out, that I'm getting a working result in case I add the script to all 4 document properties.

With a delay time of some seconds I can nicely see the changes in the chart:

  1. Chart is updating
  2. Upper Slider is updating position
  3. Lower Slider is updating position
  4. Number of histogram bins are updating

Seems to me that a data function is executed updating the document property.

Afterwards the script is executed attributed to the document property.

Once the script is finished the next data function is executed updating another document property

and so on...

Executing the script 4 times is not a very nice solution though, since the charts are jumping for half a second.

Is there a better way to resolve this issue?

Link to comment
Share on other sites

  • Solution

Gosh ok. I really appreciate the detailed response! Ah I think I may have just happened upon a solution for you...

Can you return everything as one output parameter, setting a single document property, then just execute the IronPython when it changes? A very simple way to do this would be to set the parameter to a semicolon delimited list - something like this:

LSLValue;USLValue;Bins;SelectedParameter

0.1;0.4;500;SomeParameter

Then you can "split" the value of the document property in the IronPython code, and update everything in one shot.

allValues = str(document.Properties["myOutput"]).split(";")

lslValue = allValues[0]

uslValue = allValues[1]

etc....

The above is pseudocode from memory, so don't rely on my syntax being correct!

Andrew

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...