11-26-2021 05:03 AM
Hello,
I am new to LabVIEW and have some programming experience in Python.
In Python, I have learned about generators, which are functions that effectively return a list of elements, however the elements are computed and returned one-at-a-time. The use of generators is known as lazy programming (because values are never computed before you need them), which I find extremely useful.
I would like to implement this behavior in Labview. For example, I already have a VI that continuously acquires camera images. I want to obtain these images one-at-a-time and analyze them in real-time. This means that first building an array of all camera images is not a solution for me. I also don't want to merge my VI's together because I want my code to remain modular and readable.
Is there any way to achieve this in LabVIEW?
Thanks,
Kasper
Solved! Go to Solution.
11-26-2021 05:27 AM
11-26-2021 05:42 AM
"I want to obtain these images one-at-a-time and analyze them in real-time"
I would probably use channel wires. No need for extra wires in a producer/consumer using a queue. It's all built-in. Start here.
11-26-2021 05:55 AM
Thank you so much, a stream channel seems what i am looking for. Could you explain how I can make this for two separate VIs? The link you showed has everything in one vi
11-26-2021 06:08 AM
Isn't that called Lazy Evaluation?
Anyway, you can separate the producer and consumer(s) with either (user) events or queues.
This will start to resemble a producer\consumer pattern.
11-26-2021 06:13 AM
@KasperWUR wrote:
Thank you so much, a stream channel seems what i am looking for. Could you explain how I can make this for two separate VIs? The link you showed has everything in one vi
Select the code you want in a sub VI, and then select Edit>Create SubVI.
This will show the way, but usually we do this manually. The automatically generated VIs usually need tweaking.
11-26-2021 06:39 AM - edited 11-26-2021 06:40 AM
11-26-2021 09:41 AM
According to Kasper's Post, a Python Generator is not like a Producer/Consumer Design Pattern, but is even simpler to construct with LabVIEW. Kasper's description of a Generator agrees with what I just learned by doing a Web search for Python Generator. [I must confess I don't see why this is so "exciting" -- it is trivial, in LabVIEW].
[I just realized, when starting to write this paragraph, I was about to use the term "produce", so just for fun, I'm going to use the terms "Producer" and "Consumer", but those who know the Producer/Consumer Design pattern will see that what I am describing works backwards, the Consumer causing the Producer to do work ...]
You have a VI that want to process (or "Consume") some data. When it is ready to do so, it calls another routine to "Produce" the next set of data for it to Consume. Suppose I want to, say, graph a Factorial sequence (0! = 1, 1! = 1, 2! = 2, 3! = 6, ... n! = (n-1)! * n ...). You write Produce as a subVI consisting of a While Loop with True wired to the Stop condition (so it runs exactly once). Inside you put a Case Statement with "First Call?" wired to the Conditional terminal. Create two outputs for this sub-VI -- call the first "N" (and make it an Integer type) and call the other "Factorial N" (and make it a U64 to get the most "digits before it overflows"). Also add two Shift Registers to the While Loop.
In the True Case (First Call), return 0 to N using one Shift Register, and 1 to Factorial N using the other. In the False case (all subsequent calls), bring wires from the two Shift Registers into the False Case, increment the wire going to the N output and connect it to the N output Shift Register. Take the wire coming from the Factorial N Shift Register (which is, therefore, (n-1)!) and multiply it by the now-incremented N (making (n-1)! * N) and wire it to the Factorial N output Shift Register.
All done. This VI will be a Factorial Generator. The first time you call it, it will give you 0 (for n) and 1 (for Factorial N). Subsequent calls will generate subsequent Factorials.
Note -- Kasper is new to LabVIEW, so I'm choosing to not show a Block Diagram, but (I hope) to show "how to think through a Problem in the LabVIEW way and find a Good Solution". The only "non-beginner" thing here is the "First Call?" function. This can be found by opening the Synchronization Palette on the Block Diagram. It is True the first time it is called, and False thereafter.
Bob Schor
11-29-2021 03:23 AM
Thanks to everyone who replied, especially to Bob for his elaborate answer. Bobs answer best resembles what a Python generator does, and the producer/consumer pattern seems best practice for my application of acquiring and processing camera images.
I tried Bob's example and added a snippet below:
(Factorial generator, true case contains just constants 0 and 1 (not shown).)
(Main loop retrieves the next factorial upon a button press, ready to be used for further analysis)
Thanks a lot for teaching me this design pattern, I will be sure to use it in the future.
Kasper
11-29-2021 04:24 PM
Thank you for translating my "words" into LabVIEW code that created a "Factorial Generator" for you.
Here's a "free" improvement for you to consider, one that can also teach you something about the LabVIEW Event Structure.
From the standpoint of the User Interface, there are two Buttons (OK and Stop) that "do things", and two Indicators (N and N!) that show the results of "what is done".
Most of the time, nothing of interest is being done. Think about the following situations:
There's a very interesting Structure in LabVIEW called the Event Structure (on the Block Diagram "Structure" Palette). This is almost always placed inside a While Loop and the combination called an "Event Loop". A very important (and very common) use for an Event Loop is to "Do something (once) when a Control on the Front Panel is changed by the User".
Do you know about Event Loops? If not, there are tutorial (see first page of this Forum, or do a Web search for "LabVIEW Event Structure".
Your code can be re-written using a single Event Loop with two Event Cases -- a Value-Changed Event for OK, and a Value-Changed Event for Stop.
Some things to notice with this "re-formulated" routine:
Bob Schor