# Best way to do heavy math operations in Ignition?

**URL:** <https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412>\
**Category:** General Discussion\
**Tags:** ignition79, scripting\
**Created:** [September 20, 2017, 4:32pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412 "2017-09-20T16:32:35Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![albetro.15](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/albetro.15/32/3922_2.png) [@albetro.15](https://forum.inductiveautomation.com/u/albetro.15)\
**Post date:** [September 20, 2017, 4:32pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/1 "2017-09-20T16:32:36Z")

</div>

I know Jython is very powerful for scripting, but i was wondering if there’s any module (java or python) compatible in ignition that compares to the capabilites that numpy could have.

Best,

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [September 20, 2017, 4:53pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/2 "2017-09-20T16:53:22Z")

</div>

Consider building upon the [JScience](http://jscience.org/) collection of libraries. All under a permissive license, suitable for redistribution within an Ignition module.

---

<div class="post-metadata">

**Author:** ![KathyApplebaum](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kathyapplebaum/32/7261_2.png) [@KathyApplebaum](https://forum.inductiveautomation.com/u/KathyApplebaum)\
**Post date:** [September 21, 2017, 8:26pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/3 "2017-09-21T20:26:19Z")

</div>

Oh, nice find! 👍

Also, depending on your needs, [Apache Math](http://commons.apache.org/proper/commons-math/apidocs/index.html) is worth looking at.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [September 21, 2017, 8:49pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/4 "2017-09-21T20:49:13Z")

</div>

I didn’t really find JScience myself. I learned about it when contributing to the now-defunct CompPad add-on for OpenOffice/LibreOffice.

---

<div class="post-metadata">

**Author:** ![Brian](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@Brian](https://forum.inductiveautomation.com/u/Brian)\
**Post date:** [February 16, 2018, 8:27pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/5 "2018-02-16T20:27:05Z")

</div>

I came across this thread when looking for options on how to add some statistical math functions to ignition. I followed the Apache Math link, and it looks like there’s everything I could want there. However, I’m not sure how to go about adding the functionality to ignition.

Is this something that you need to make a module with? If so, how do you do that? I’m a bit surprised that someone hasn’t created a Math module, or ignition hasn’t added the functions to the core software, given the frequency with which questions regarding numpy are asked. Of course, I’m guessing my perception is a bit skewed after searching the forums for a while on this topic.

For what it’s worth, at the moment, I’m interested in mode, median, standard deviation, kurtosis, and skewness. I suppose it’s possible I’d be looking for more down the road sometime, but those would get me started.

---

<div class="post-metadata">

**Author:** ![KathyApplebaum](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kathyapplebaum/32/7261_2.png) [@KathyApplebaum](https://forum.inductiveautomation.com/u/KathyApplebaum)\
**Post date:** [February 20, 2018, 3:53pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/6 "2018-02-20T15:53:50Z")

</div>

If you’re willing to have gateway only access, you don’t need a module, but a module will absolutely be the easiest way to get access to Apache Math.

Honestly, the things you’re looking for are really easy to calculate in your own script module without Apache Math, especially if you add some functions to calculate the nth central moment (which, with your standard deviation calc, will give you kurtosis and skewness). And, of course, mean and std dev are already available in the expression language.

But adding those kind of math functions is a great idea, and you should suggest it at [ideas.inductiveautomation.com](http://ideas.inductiveautomation.com). This is a great kind of project for me to give to new developers. 🙂

---

<div class="post-metadata">

**Author:** ![Brian](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@Brian](https://forum.inductiveautomation.com/u/Brian)\
**Post date:** [February 20, 2018, 6:19pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/7 "2018-02-20T18:19:05Z")

</div>

Yeah, I will probably try to code my own functions that I’m looking for. I’m just a little surprised that those kind of functions aren’t available already. I suppose data analysis like that might be a little outside the realm of traditional SCADA systems, but Ignition is so good at working with databases and scripting, it just makes sense to do it internally.

I added the idea. [Here’s the link](http://ideas.inductiveautomation.com/forums/255378-ignition-features-and-ideas/suggestions/33391129-add-additional-math-functions) in case anyone else reading this wants to upvote.

Thanks!

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [February 20, 2018, 6:24pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/8 "2018-02-20T18:24:56Z")

</div>

I'd be hurt that no one mentioned this... if it wasn't for my huge ego... 😉

> [@Math Extensions for Ignition](http://forum.inductiveautomation.com/t/math-extensions-for-ignition/3106):
>
> EDIT 2017-07-13: Things have changed enough that this first post is getting revamped. EDIT 2019-08-08: Re-uploaded due to broken link Some useful math functions just aren’t available through scripting. This is an attempt to rectify some of it. Functions: sum mean rectangular-to-polar conversions polar-to-rectangular conversions simple linear regressions polynomial regression greatest-common-denominator least common multiple standard deviation (population and sample) decimal to BCD decimal t…

---

<div class="post-metadata">

**Author:** ![Brian](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@Brian](https://forum.inductiveautomation.com/u/Brian)\
**Post date:** [February 20, 2018, 6:31pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/9 "2018-02-20T18:31:56Z")

</div>

I actually saw that post when I was looking around! However, it’s missing several of the functions I was looking for. And, worse, when I tried uploading my project to my 7.9.6 gateway, it complained that [global] was already existing on the gateway and let me rename it. I did, but it appeared to be an empty project. I couldn’t find any scripting assets in the project. I didn’t pursue it further as it didnt’ appear to have everything I needed anyway.

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [February 20, 2018, 6:43pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/10 "2018-02-20T18:43:30Z")

</div>

Import it by right-clicking on ‘Global’ at the top of the tree and select ‘Import’. Afterward, you should see it in the shared script library.

That being said, I’m always open to new functionality. I had originally hoped that it would be a collaborative effort, but so far it’s been a team of one. Heh.  
 ![](https://us1.discourse-cdn.com/inductiveautomation/original/2X/f/faa62213b8d756f8418277618feb0a310d56960a.png)

---

<div class="post-metadata">

**Author:** ![Brian](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@Brian](https://forum.inductiveautomation.com/u/Brian)\
**Post date:** [February 20, 2018, 6:49pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/11 "2018-02-20T18:49:39Z")

</div>

Ohhhhh, that’s how you import that! I’ll have to give it a try!

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [February 20, 2018, 6:52pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/12 "2018-02-20T18:52:00Z")

</div>

No worries, Brian!

Like I said I don’t mind working on new functionality. I just need to know what functionality to work on. 😃

---

<div class="post-metadata">

**Author:** ![Brian](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@Brian](https://forum.inductiveautomation.com/u/Brian)\
**Post date:** [February 20, 2018, 9:25pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/13 "2018-02-20T21:25:27Z")

</div>

Below is a mode function I modified from an example I found on the web. I added it to your math script and it seems to be working. Give it a try and see what you think. I’m sure there’s other ways to be doing mode calculations (I’m no mathematician), but I think this will serve my purposes.

Probably the more proper thing to do instead of simple rounding for real values would be to calculate intervals to assign the data points to and then calculate a mode from that.

```auto
# Function to return all modes, this function takes into account multimodal distributions.
# Optional digits argument will round numbers to the specified decimal places.
# The rounding function is incompatible with string types.
# Function returns all modes as list or an empty list if such value doesn't exist.
def mode(l,digits=None):
    if len(l) > 1: #
        #Creates dictionary of values in l and their count
        d = {}
        for value in l:
            if digits != None:
            	value = round(value,digits)
            if value not in d:
                d[value] = 1
            else:
                d[value] += 1

        if len(d) == 1:
            return [value]
        else:
            # Finds most common value
            i = 0
            for value in d:
                if i < d[value]:
                    i = d[value]

            # All values with greatest number of occurrences can be a mode if:
            # other values with less number of occurrences exist
            modes = []
            counter = 0
            for value in d:
                if d[value] == i:
                    mode = (value, i)
                    modes.append(mode)
                    counter += mode[1] # Create the counter that sums the number of most common occurrences

            # Example [1, 2, 2, 3, 3]
            # 2 appears twice, 3 appears twice, [2, 3] are a mode
            # because sum of counter for them: 2+2 != 5
            if counter != len(l):
                return [mode[0] for mode in modes]
            else:
                return []
    else:
        return []

```

---

<div class="post-metadata">

**Author:** ![Brian](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@Brian](https://forum.inductiveautomation.com/u/Brian)\
**Post date:** [February 20, 2018, 10:13pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/14 "2018-02-20T22:13:41Z")

</div>

Some example results from the function.

```auto
>>> print shared.math.mode([1])
[]
>>> print shared.math.mode([1, 1])
[1]
>>> print shared.math.mode([1, 1, 2, 2])
[]
>>> print shared.math.mode([1, 2, 3, 4, 5])
[]
>>> print shared.math.mode([1, 1, 2, 2, 3, 3, 4])
[1, 2, 3]
>>> print shared.math.mode([1, 2, 3, 4, 4])
[4]
>>> print shared.math.mode(['string', 'string', 1])
['string']
>>> print shared.math.mode(['string', 'string', 1, 1, 1])
[1]
>>> print shared.math.mode([0.57099998,0.571367845,0.571367845,0.571657243,0.571657243],3)
[0.571]

```

---

<div class="post-metadata">

**Author:** ![KathyApplebaum](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kathyapplebaum/32/7261_2.png) [@KathyApplebaum](https://forum.inductiveautomation.com/u/KathyApplebaum)\
**Post date:** [February 20, 2018, 10:25pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/15 "2018-02-20T22:25:56Z")

</div>

I’m a bit confused on your output…

`>>> print shared.math.mode([1, 1, 2, 2])`  
`[]`  
gives an empty return set, but

````auto
[1, 2, 3]```
does not? It doesn't seem consistent.
````

---

<div class="post-metadata">

**Author:** ![Brian](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@Brian](https://forum.inductiveautomation.com/u/Brian)\
**Post date:** [February 20, 2018, 10:31pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/16 "2018-02-20T22:31:01Z")

</div>

I was a little confused about that myself. There’s a comment in the code:

```auto
# All values with greatest number of occurrences can be a mode if:
# other values with less number of occurrences exist

```

I haven’t done research on how modes should be handled with uniform distributions (like I said, not a mathematician). I just assumed that it was some edge case the programmer was handling. It’s one of the reasons I posted it to be picked apart 😉

Edit: [Interesting reference](http://mathforum.org/library/drmath/view/52793.html) I found

---

<div class="post-metadata">

**Author:** ![KathyApplebaum](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kathyapplebaum/32/7261_2.png) [@KathyApplebaum](https://forum.inductiveautomation.com/u/KathyApplebaum)\
**Post date:** [February 20, 2018, 11:54pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/17 "2018-02-20T23:54:06Z")

</div>

Definitely agree with the “no consensus part”. LOL

Brings up a good thought for someone spec’ing a module (which may end up being me)… probably the best user experience is to allow an optional param to specify how this situation is handled. Because no matter how you handle it, someone will complain. 😆

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [February 21, 2018, 1:02pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/18 "2018-02-21T13:02:54Z")

</div>

Here’s what I came up with. include optional parameter to allow all modes vs. no mode for even distributions.

```auto
def mode(listIn, all_modes = 0):
  bins = list(set(listIn))
  counts = [listIn.count(x) for x in set(listIn)]
  maxCounts = max(counts)
  indices = [i for i, x in enumerate(counts) if x == maxCounts]

  dataOut = []
  if all_modes == 0:
    if len(set(counts)) != 1:
      for i in indices:
        dataOut.append(bins[i])
  else:
    for i in indices:
      dataOut.append(bins[i])
  
  return dataOut

```

---

<div class="post-metadata">

**Author:** ![JordanCClark](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/jordancclark/32/83362_2.png) [@JordanCClark](https://forum.inductiveautomation.com/u/JordanCClark)\
**Post date:** [February 21, 2018, 11:07pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/19 "2018-02-21T23:07:19Z")

</div>

For what it’s worth, I’m modifying a statistics package that you may be interested in. More details coming. 🙂

---

<div class="post-metadata">

**Author:** ![Brian](https://avatars.discourse-cdn.com/v4/letter/b/97f17d/32.png) [@Brian](https://forum.inductiveautomation.com/u/Brian)\
**Post date:** [February 21, 2018, 11:31pm UTC](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412/20 "2018-02-21T23:31:18Z")

</div>

Awesome! I haven’t had any time to play with this stuff today. Other duties and stuff…

If I could make a request, please include in the mode function, an optional parameter for either rounding or binning floats. The mean and median functions will work fine with floats in their raw form, but there’s a decent chance that an analog signal recorded to a float will have enough unique values over a short period to have all of the values be unique. Including the rounding/binning actions in the mode function should keep from having to loop through the data twice.

[Next page](https://forum.inductiveautomation.com/t/best-way-to-do-heavy-math-operations-in-ignition/15412.md?page=2)
