# Indirection on components?

**URL:** <https://forum.inductiveautomation.com/t/indirection-on-components/77453>\
**Category:** Ignition\
**Tags:** ignition81, perspective\
**Created:** [August 4, 2023, 3:39pm UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453 "2023-08-04T15:39:17Z")\
**Posts on this page:** 12\
**Page:** 2

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [August 4, 2023, 9:23pm UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453/21 "2023-08-04T21:23:08Z")

</div>

Close. I would recommend that you keep the two functions in a Script Library.

Really you should define another function in a script library that holds all of the actual code in a script library., but you don't have to.

If you choose to just define them in this script then, all of the imports should be on the first line, I just did it in each function for clarity (and so the functions by themselves can be used without modification).

So it should look like this:

```auto
def runAction(self, event):
	from itertools import repeat,izip_longest as zipl
	from itertools.chain import from_iterable as chainIt
	
	def chunks(it,size):
		return zipl(*[iter(it)] * size)
	def rangeGroup(it,start,n):
		for i,j in zip(chainIt(repeat(k,len(it)) for k in xrange(start,n)),chainIt(repeat(it,n))):
			yield (i,j)

    quad = ['A','B','C','D']
    path = '[default]Twisters/TW{}/Operator Assignments/Quad_{} {}'
    tags = ['J Shift Operator Name','J Shift Operator BadgeNum']
    
    paths = [path.format(i,n,tag) for i,n in rangeGroup(quad,0,66) for tag in tags]
    
    tagValues = [qv.value for qv in system.tag.readBlocking(paths)]
    
    #I incremented the end value here rather than in the loop.
    tw_ranges = [(1,13),(13,25),(25,41),(41,57),(57,66)]
    
    for cc_index,(tw_start,tw_end) in enumerate(tw_ranges):
        for tw_num,quad in rangeGroup(quad,tw_start,tw_end):
           cont = 'CoordinateContainer_{}'.format(cc_index)
           tw = 'TW{}'.format(tw_num)
           nameQuad = 'Quad_{}_OpName'.format(quad)
           numQuad = 'Quad_{}_OpNum'.format(quad)
    
           for opName,opNum in chunks(tagValues,2):
               self.parent.getChild(cont).getChild(tw).props.params[nameQuad] = opName
               self.parent.getChile(cont).getChild(tw).props.params[numQuad] = opNum

```

Honestly though, it should really look like this:

```auto
def runAction(self,event):
    shared.someScriptLibrary.someScriptFile.populateComponents(self)

```

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [August 4, 2023, 9:23pm UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453/22 "2023-08-04T21:23:25Z")

</div>

1. Put `chunks` and `rangeGroup` in a project library script, with the import at the top of the file.
2. call them from your `runAction` script.
3. the indentation in your script is way off.

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [August 4, 2023, 9:27pm UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453/23 "2023-08-04T21:27:31Z")

</div>

In my project those functions are part of my script utils library, and the imports are all at the top of the file.

But with the imports that way, as smelly as it is, the functions will work as is no matter where they're pasted.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [August 4, 2023, 10:05pm UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453/24 "2023-08-04T22:05:05Z")

</div>

> [@lrose](#):
>
> ```auto
> def rangeGroup(it,start,n):
> for i,j in zip(chainIt(repeat(k,len(quad)) for k in xrange(start,n)),chainIt(repeat(quad,n))):
> yield (i,j)
> 
> ```

I'm guessing `quad` should be `it` ?

I don't think you need `yield` here. Returning a `zip` object should be just as good I believe.  
I think `zip` produced a list in Cpython 2, but I don't think it's the case with Jython.  
And if it does produce a list, it's going to produce it anyway in your function, whether you yield its results or not.

I think `product` is better for this use case:

```python
def group_range(start, n, it):
    return product(range(start, n), it)

```

much simpler, and returns an iterator. Frankly it even makes having a function for it almost useless.

edit:  
`itertools` has an `izip` that returns an iterator. I'm not sure exactly what is the `class 'zip'` that zip returns in jython...

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [August 4, 2023, 10:13pm UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453/25 "2023-08-04T22:13:13Z")

</div>

Yes you're correct, I missed those.

Honestly, didn't know about `product` until you used.

---

<div class="post-metadata">

**Author:** ![WillMT10](https://avatars.discourse-cdn.com/v4/letter/w/7feea3/32.png) [@WillMT10](https://forum.inductiveautomation.com/u/WillMT10)\
**Post date:** [August 5, 2023, 3:29pm UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453/26 "2023-08-05T15:29:12Z")

</div>

I have to say, I'm surprised at how fun this problem is from a code optimization standpoint. Below is my take. Definitely learned some new things!

```auto
from itertools import product

def get_iterator(op_strings):
	quads = ['A','B','C','D']
	return product(range(1,66), quads, op_strings)

path = '[default]Twisters/TW{}/Operator Assignments/Quad_{} J Shift Operator {}'
paths = [path.format(*p) for p in get_iterator(['Name','BadgeNum'])]
tag_qvals = system.tag.readBlocking(paths)

cc_idx, tw_breaks = 0, [12,24,40,56,65]
for i,p in enumerate(get_iterator(['Name','Num'])):
	cc_idx += int(p[0] > tw_breaks[cc_idx])
	cc_str = 'CoordinateContainer_{}'.format(cc_idx)
	tw_str = 'TW{}'.format(p[0])
	pm_str = 'Quad_{}_Op{}'.format(p[1],p[2])
	self.parent.getChild(cc_str).getChild(tw_str).props.params[pm_str] = tag_qvals[i].value

```

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [August 5, 2023, 6:40pm UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453/27 "2023-08-05T18:40:43Z")

</div>

> [@WillMT10](#):
>
> I'm surprised at how fun this problem is

I was actually thinking about opening a thread to propose little challenges like this. I'm still figuring out how that would work, but it could be a fun way of learning new things.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [August 6, 2023, 8:22am UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453/28 "2023-08-06T08:22:27Z")

</div>

> [@WillMT10](#):
>
> ```auto
> def get_iterator(op_strings):
> quads = ['A','B','C','D']
> return product(range(1,66), quads, op_strings)
> 
> ```

Here's a neat little thing (though in this particular case I'd just use a direct call to `product`):

```python
from functools import partial

prod = partial(product, "ABCD", xrange(1, 66))

```

When you want to wrap a function to give it predefined arguments, `partial` is a handy thing.

---

<div class="post-metadata">

**Author:** ![mjohnson0238](https://avatars.discourse-cdn.com/v4/letter/m/4bbf92/32.png) [@mjohnson0238](https://forum.inductiveautomation.com/u/mjohnson0238)\
**Post date:** [August 6, 2023, 12:20pm UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453/29 "2023-08-06T12:20:23Z")

</div>

I wouldike to thank everyone who has helped me with this! You guys have been really great!

---

<div class="post-metadata">

**Author:** ![mjohnson0238](https://avatars.discourse-cdn.com/v4/letter/m/4bbf92/32.png) [@mjohnson0238](https://forum.inductiveautomation.com/u/mjohnson0238)\
**Post date:** [August 6, 2023, 1:37pm UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453/30 "2023-08-06T13:37:31Z")

</div>

One last question for the group:

Is there a length limit to how many lines the jython code can be?

For future reference.

---

<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:** [August 6, 2023, 1:45pm UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453/31 "2023-08-06T13:45:19Z")

</div>

Not a length limit, but a compiled (to jython bytecode) size limit. 64k, IIRC.

---

<div class="post-metadata">

**Author:** ![mjohnson0238](https://avatars.discourse-cdn.com/v4/letter/m/4bbf92/32.png) [@mjohnson0238](https://forum.inductiveautomation.com/u/mjohnson0238)\
**Post date:** [August 6, 2023, 1:47pm UTC](https://forum.inductiveautomation.com/t/indirection-on-components/77453/32 "2023-08-06T13:47:58Z")

</div>

Thanks again, I wish I could buy everyone here a round for the help!

[Previous page](https://forum.inductiveautomation.com/t/indirection-on-components/77453.md?page=1)
