08-24-2023 09:45 AM
Hi, I want to build a logging subVI which accepts two clusters, each with 0 to n elements of an arbitrary type (hence no array). Basically, the clusters are gonna be settings and measurement data, e. g. someone wants to log a timestamp, an x and y coordinate (uint) as well as a preset voltage (dbl) (where was the data acquisition location and what was the control voltage?), and a pressure (dbl), temperature (dbl) and an over-temperature (bool) value (what was actually measured?). However, the same program should also work without modification if someone just wants to log a timestamp and a current (dbl) for example. So it has to support empty clusters and any arbitrary size of cluster as input. Does this work or is there another way, perhaps without clusters?
Thanks in advance.
08-24-2023 09:50 AM
Either make a polymorphic VI with one version for each, or make the input a Variant and check and convert inside the VI to the right cluster type.
08-24-2023 10:02 AM
Thanks for the response. My problem is that the person who uses this program just wants to drag this logging subVI into every single one of their measurement programs, wire up all applicable values to it and expects a log file to come out. Again, this has to work irrespective of the input data types. How would I convert a bunch of different values of various data types to a variant without the user having to do it themselves?
08-24-2023 10:18 AM
I'd recommend using the JSONText library. It has functions that will accept an arbitrary input and will turn it into JSON-formatted text, which you can then stick into a log file. That has a secondary benefit of also being later readable by other automated things since it will include the types and any names you assign.
The format might not be as simple as you'd like it to be, but it's consistent and will easily be readable by just about anything else. The downside is it won't be super easily plottable in Excel. If you wanted to make it just a comma-separated-value file, you could make sure to remove all of the item names, then do some string processing to remove brackets and curly braces:
08-24-2023 10:24 AM
You can create Malleable VIs
08-24-2023 10:39 AM
You should probably do this as an array of Doubles. It sounds inefficient but the whole point of a cluster is that they're statically sized. VIMs can cause a myriad of development time issues (most of the time they work, until they don't and then they're a huge PITA). And writing contents of a VIM that can handle arbitrary cluster contents and data types is definitely in the realm of very complex VIM which is more likely to have issues.
Another option is to have a logger class that you can add elements of any data type to, it builds up the row of data doing conversions from various types, and then you can trigger writing the whole line at once.
There are also some libraries already available for reading/writing from variants, which you can convert any cluster to, but they rely on run-time type inspection and have various amounts of performance impact depending on the library and which may or may not be an issue. If you don't want something like JSON or other available formats you can at least reference them and see how they do the type inspection to roll your own for your log format.
In LabVIEW, trying to simplify an API like this for users can be a recipe for pain.
08-24-2023 10:54 AM
I once did something very similar where the task was to parse the data out as CSV file with automatically generated headers.
I solved it by reading the cluster in as a variant and then used the variant data parsing to get the data and headers out.
If your use case is simple and restricted, it might be quite fast to solve it this way. If you want to keep it flexible for different (and nested) clusters, it becomes a super fun exercise, but might take a bit longer.
08-24-2023 11:10 AM
Yeah, it's supposed to be very dynamic and flexible. In Python I'd just do it as an array and do a for element in array loop or work with variable-length function arguments like def log(*args) but so far I haven't found anything that would work this way in LabVIEW.
08-24-2023 11:34 AM
Is there a way to bundle the cluster data in a variant data type, have that as an input for the subVI, and then unbundle the variant so I have the original cluster again? Or at least refnums to all elements of the original cluster?
08-24-2023 12:30 PM - edited 08-24-2023 12:31 PM
Okay, I solved it through a Python node now. I just have my timestamp from LabVIEW, the two clusters (which can be any size, they just get converted to tuples in Python) and the file path of the logging VI. When I run it, I just write all those to a log file using the csv module in Python and that's that. Thanks for all your help, everyone! I truly appreciate it.
In case anyone is curious what my Python code looks like:
import csv
def log(time, independent, dependent, path):
log_data = []
log_data.append(str(time))
[log_data.append(element) for element in independent]
[log_data.append(element) for element in dependent]
with open(path + "/testfile.csv", "a") as f:
x = csv.writer(f)
x.writerow(log_data)