Dynamic Row/Column table creation?

Hello I see you are the most engaging person here
I wan to create tags in table using the row names and columns names for instance.
For instance, if I have columns as C1 , C2, C3 and rows as R1, R2 R3,

Then I want to create a dynamic tag such that with one click all the table entries are tagged for instance R1C1 tag should look something like this

MotorA/R1.Name/process parameters/C1.Name. I want to make my tags dynamic to use my column values and update the tag for next column automatically by writing tag as MotorA/R1.Name/process paramters/C2.name

You need to start a new topic for this rather than necroposting.

2 Likes

Done.

Please describe your desired behavior in more detail. Also, is this Perspective or Vision? Please tag the topic accordingly.

Examples of how you want it to look would help.

Thanks. I'm not cool enough to do that yet. :stuck_out_tongue:

My money is on a script that populates the table. Use 2 lists, one with the header names, one with the row "names". Use nested for loops to build one list of all the tags to be read for the entire table, then one call to system.tag.readBlocking() and create a dataset from the results.

Something like (using the path you provided)

columns = ['C1', 'C2', 'C3']
rows = ['R1','R2','R3']

tagPaths = []

for row in rows:
	for column in columns:
		tagPaths.append('MotorA/'+str(row)+'.Name/process parameters/'+str(column)+'.Name')
		
		
#tagQValues = system.tag.readBlocking(tagPaths)[tag]
#tagValues = [tagQValues[tag].Value for tag in tagQvalues]
tagValues = [qval.value for qval in system.tag.readBlocking(tagPaths)]

numColumns = len(columns)
numTags = len(tagValues)

data = [tagValues[i:i + numColumns] for i in range(0, numTags), numColumns)]

dataset = system.dataset.toDataSet(columns,data)

**not tested or checked for syntax at all. can't remember if Qvalues value prop is capitalized or not and I might have the syntax for unpacking them all at once off.

I don't understand this and I can't figure out how it would ever work.
I suggest reworking it to something simpler:

tagValues = [qval.value for qval in system.tag.readBlocking(tagPaths)]

edit: here's how I'd do it (can't run it so there might be some fixing to do):

from itertools import product

columns = ['c1', 'c2', 'c3']
rows = ['r1', 'r2', 'r3']

paths = ["foo/{}/bar/{}".format(r, c) for r, c in product(columns, rows)]
values = [qval.value for qval in system.tag.readBlocking(paths)]
ds = system.dataset.toDataSet(
	columns,
	lib.utils.chunks(values, chunk_size=len(columns))
)

Now you obviously don't have the same lib.utils.chunks as I have, but I suggest librarying this kind of function. There's a number of different implementations on the internet.
To remove that dependency, let's inline the one @amarks provided (with one change and one fix), because it works very well in this case:

from itertools import product

columns = ['c1', 'c2', 'c3']
rows = ['r1', 'r2', 'r3']

paths = ["foo/{}/bar/{}".format(r, c) for r, c in product(columns, rows)]
values = [qval.value for qval in system.tag.readBlocking(paths)]
chunk_size = len(columns)
ds = system.dataset.toDataSet(
	columns,
	[values[i:i+chunk_size] for i in xrange(0, len(values), chunk_size)]
)
1 Like

Ya, like I said I wasn't sure on the syntax on that. I've done it before, but it's not something I have committed to memory yet.

As for the rest of the code, I'd argue that my version is a bit easier to read.

Which part ?
The only thing I really changed is the use of xrange instead of range and product instead of nested loops.
If you're thinking of the call to toDataSet, it's only cosmetic, so it's up to personal preference.
I agree that it's a bit "heavier" on the eye, but it also has the benefit of putting things exactly where they're used, which - to me - makes it easier to parse.

Path creation string is not as direct as using string concatenation as I did.
Creation of the dataset is not as direct.

I've simplified mine using list comprehension, as you did to highlight those differences.

columns = ['C1', 'C2', 'C3']
rows = ['R1','R2','R3']

tagPaths = ['MotorA/' + str(row) + '.Name/process parameters/' + str(column) + '.Name' for row in rows for column in columns]
		
tagValues = [qval.value for qval in system.tag.readBlocking(tagPaths)]

numColumns = len(columns)
numTags = len(tagValues)

data = [tagValues[i:i + numColumns] for i in range(0, numTags), numColumns)]

dataset = system.dataset.toDataSet(columns,data)

I know it's a matter of personal preference but... are you saying you find this:

['MotorA/' + str(row) + '.Name/process parameters/' + str(column) + '.Name' for row in rows for column in columns]

easier to read than this:

["MotorA/{}.Name/process parameters/{}.Name".format(r, c) for r, c in product(columns, rows)]

?

Is it the formatting method, or the product ?
I'm not sure what you mean by "direct".

Yes, of course it's just personal preference. For me, it's using {}.format(r,c) I'm not familiar with that method. String concatenation with the + operator just feels more natural.

I really don't like those + and str() in the middle of my strings, that's why I use format... even though concatenation is a bit more efficient in most cases.

1 Like