# Indirect Pen Tag Path

**URL:** <https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643>\
**Category:** Ignition\
**Tags:** ignition81, vision\
**Created:** [October 18, 2023, 1:42pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643 "2023-10-18T13:42:03Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [October 18, 2023, 1:42pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/1 "2023-10-18T13:42:03Z")

</div>

I have an easy chart with pens configured to use a MySQL database. However, this project will also be deployed on an Edge panel and use the Edge Historian for trending at the local panel.

What I've run into is that I cannot rename the Edge Historian history provider, so I need to be able to dynamically change the tag path based on where the project is deployed.

My first thought is a cell update binding on the _[tag]_ pens dataset, but performance with that is yet to be seen. My next thought was an indirect tag path in the data section of the pen configuration. Wondering if that's possible at all (guessing not) and what sort of performance I can expect with the cell update bindings as the pen sets get larger.

---

<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:** [October 18, 2023, 2:47pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/2 "2023-10-18T14:47:43Z")

</div>

You cannot use the `pens` dataset with EasyChart at all on Edge, as DB pens require a DB. You need to configure the `tagPens` dataset for charting from the historian.

You may be able to script the population of the two datasets based on the environment.

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [October 18, 2023, 2:49pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/3 "2023-10-18T14:49:51Z")

</div>

Yes, I am using the tag pens dataset

---

<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:** [October 18, 2023, 2:50pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/4 "2023-10-18T14:50:58Z")

</div>

Then just script the content of `.tagPens` based on the environment.

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [October 18, 2023, 2:57pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/5 "2023-10-18T14:57:02Z")

</div>

It's a pretty large dataset to script... not sure if I want to start down that route (yet).

Wondering if you have any opinions on the cell update bindings.

---

<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:** [October 18, 2023, 3:00pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/6 "2023-10-18T15:00:43Z")

</div>

Not a fan of cell update bindings.

Consider making custom dataset properties for the two environments and storing the correct content in each. Then bind to `.tagPens` an expression of the form:

```auto
if({some.edge.boolean}, {path.to.edge.pens}, {path.to.nonEdge.pens})

```

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [October 18, 2023, 3:03pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/7 "2023-10-18T15:03:34Z")

</div>

I see. Just "big" datasets that exist on the page and the only expression is figuring out which to use. Seems like alot of work when the only thing that changes is the data source (i.e. `[MySQL/ignition-desktop-av4v6h5:area_01]` \> `[Edge Historian/area_01]`) for each tag pen. I guess the second dataset could be scripted and use a loop/replace. Now I wish easy charts could have custom properties...

---

<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:** [October 18, 2023, 3:22pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/8 "2023-10-18T15:22:25Z")

</div>

Just put the custom props on the container in which the EasyChart sits.

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [October 18, 2023, 3:23pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/9 "2023-10-18T15:23:23Z")

</div>

Ya, I just like to put component-specific custom props on the component themselves if possible.

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [October 18, 2023, 4:44pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/10 "2023-10-18T16:44:28Z")

</div>

So I've got the two custom dataset properties made. One I populated just using a temporary binding to the existing tag pens dataset on the easy chart. Now, I'm trying to use an update script on that dataset to modify the `TAG_PATH` column for each row and just not sure how to do that second part.

I know datasets are immutable so I have to somehow use the existing dataset to create a new one and then write that to the prop, just unfamiliar with that process.

---

<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:** [October 18, 2023, 4:46pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/11 "2023-10-18T16:46:51Z")

</div>

Don't script it. Copy the dataset to the clipboard in the dataset editor popup. Fix up in your favorite text editor. Paste into the other dataset.

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [October 18, 2023, 4:47pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/12 "2023-10-18T16:47:42Z")

</div>

I'm going to be doing this quite a bit and would like it to update automatically if pens area added in the future.

---

<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:** [October 18, 2023, 4:50pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/13 "2023-10-18T16:50:10Z")

</div>

You can't, using the `if()` expression binding (nor a cell update binding, fwiw). That would make a circular reference and crash/freeze your client.

You may need to script the entire thing.

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [October 18, 2023, 4:57pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/14 "2023-10-18T16:57:33Z")

</div>

Where's the circular reference? That binding I was talking about was just to get the rows and columns from the existing easy chart without doing it manually. The binding no longer exists. This custom dataset would end up being the driving data source for the tag pens.

The `if()` just decides which dataset to use; the primary dataset or the 'derived' dataset. I just want to script the creation of the derived dataset so it updates if the primary dataset is changed.

---

<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:** [October 18, 2023, 5:01pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/15 "2023-10-18T17:01:51Z")

</div>

Ah, ok. Then your update script would loop through the source dataset, using a string replace operation to produce a new list of rows, then assemble with `system.dataset.toDataSet()`.

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [October 18, 2023, 5:37pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/16 "2023-10-18T17:37:45Z")

</div>

Getting a `toDataSet(): 1st arg can't be coerced to org.python.core.PySequence ` error when I try and convert the lists to a dataset. I used data.getColumnNames()

```auto
[NAME, TAG_PATH, AGGREGATION_MODE, AXIS, SUBPLOT, ENABLED, COLOR, DASH_PATTERN, RENDER_STYLE, LINE_WEIGHT, SHAPE, FILL_SHAPE, LABELS, GROUP_NAME, DIGITAL, OVERRIDE_AUTOCOLOR, HIDDEN, USER_SELECTABLE, SORT_ORDER, USER_REMOVABLE]

```

Fixed by adding `[]` around the headers, but now it says row 0 has a different number of columns, which it doesn't... it's literally made from the same dataset...

```auto
penData_master = system.dataset.toPyDataSet(event.source.master)

headers = event.source.master.getColumnNames()
penData_edge = []

TAG_PATH_index = event.source.master.getColumnIndex('TAG_PATH')

#print headers
#print len(headers)
for row in penData_master:
	new_row = list(row)
	
	new_row[TAG_PATH_index] = row['TAG_PATH'].replace('[MySQL/ignition-desktop-av4v6h5:area_01]',event.source.parent.hist_root_path)
	
	penData_edge.append(new_row)
	
	#print new_row
	#print len(new_row)

newData = system.dataset.toDataSet([headers], penData_edge)

```

len() prints show header and rows are all 20 elements in length. Probably because of the `[headers]`. But without the wrapping `[]` I'm back where I started.

Things just keep getting weirder... so I transposed the headers to a list of lists and no longer get any errors, but now each header is a list...

```auto
newData = system.dataset.toDataSet([[str(col)] for col in headers], penData_edge)

```

Original dataset headers:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/d/8/d87f1453a88d5117b486ed626634affd9ecce85f.png)  
New dataset headers:  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/0/b/0bf8523eee690584e8202b3c338597cf00357f53.png)

very confused

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [October 18, 2023, 6:05pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/17 "2023-10-18T18:05:27Z")

</div>

Finally got it.

So, `event.source.master.getColumnNames()` returns strings in that `u'STRING'` format, which `system.dataset.toDataSet(headers, data)` does not like in the headers list.

```auto
penData_master = system.dataset.toPyDataSet(event.source.master)

headers = event.source.master.getColumnNames()
headers = [str(col) for col in headers]
penData_edge = []

TAG_PATH_index = event.source.master.getColumnIndex('TAG_PATH')

#print headers
#print len(headers)
for row in penData_master:
	new_row = list(row)
	
	new_row[TAG_PATH_index] = row['TAG_PATH'].replace('[MySQL/ignition-desktop-av4v6h5:area_01]',event.source.parent.hist_root_path)
	
	penData_edge.append(new_row)
	
	#print new_row
	#print len(new_row)

event.source.edge = system.dataset.toDataSet(headers, penData_edge)

```

---

<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:** [October 18, 2023, 6:08pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/18 "2023-10-18T18:08:41Z")

</div>

> [@amarks](#):
>
> does not like in the headers

It is not the unicode, but that it is a java list, not a python list. You can just use:

```auto
headers = list(event.source.master.getColumnNames())

```

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [October 18, 2023, 6:12pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/19 "2023-10-18T18:12:17Z")

</div>

Thanks

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [November 3, 2023, 3:40pm UTC](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643/20 "2023-11-03T15:40:58Z")

</div>

So my motivation for this was because I couldn't find a way to rename the Edge Historian. This is working just fine, but I've now found that I can rename the Edge Historian.

Now the question is... do I undo it all or just leave it because it works... 😑

I'm thinking I'll probably just leave it because the path would still have to change either way.

[Next page](https://forum.inductiveautomation.com/t/indirect-pen-tag-path/80643.md?page=2)
