Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.
Showing results for
Search instead for
Did you mean:
Do you have an idea for LabVIEW NXG?
Use the in-product feedback feature to tell us what we’re doing well and what we can improve. NI R&D monitors feedback submissions and evaluates them for upcoming LabVIEW NXG releases. Tell us what you think!
The goal of this idea is to make it easy for the LabVIEW ecosystem to create reusable libraries for LabVIEW that would be type independent. Let's think for a second dictionaries, also called as key-value stores. Dictionaries are data structures that allow storing and retrieving values with a specific key. To create a generic reusable strongly typed dictionary is currently impossible with the LabVIEW type system. One can create a dictionary that is type specific but then it's not reusable. Or one can create a reusable dictionary but then it's not strongly typed. Type Parameters and Parametrized Generic Types as explained in this idea would allow creating strongly typed dictionaries that are widely reusable across applications. Specifically type parameters and parametrized generic types would allow LabVIEW ecosystem to develop highly reusable strongly typed components to solve various common programming problems. This would allow National Instruments to put more focus on the core of the language as the LabVIEW ecosystem could solve much wider range of problems that preivously have required National Instruments to contribute.
Add a new control type Type Parameter to LabVIEW that augments the current Control, Type Def and Strict Type Def control types. The Type Parameter type would act like a regular Type Def control with one special and important distinction. You could wire anything to an input terminal expecting a specific Type Parameter type and the downstream type would adapt at compile time to the type wired to the type parameter input.
In a single VI type parameter could be used in multiple places but all instances of the type parameter would adapt to the same type.
When a VI that uses Type Parameters in the front panel is used on a block diagram, the template VI is replaced by the compiler by a type specific instance that has adapted the type parameters to the type wired to the Type Parameter input. Notice below how in our VI the control and the indicator were of type Type Parameter with a default type of DBL and the instance got adapted to type U32 that was wired to the input.
The same type parameter could be used on multiple inputs of a VI.
And all of the type parameters would adapt to the same type when the VI is being used.
Note that in the above example we chose the element of the array to be a specific type specified by a type parameter. However the arrays themselves could as well have been specified by a type parameter.
So far we have focused on VI boundary where type parameters adapt the whole VI to specific type or types if multiple different type parameters are being used in the connector pane of the VI. Type parameters can also be used in composite types (e.g. arrays, clusters, classes) and the downstream composite types would adapt to what is wired to the type parameter input.
Note that x and y as instances of the same type parameter have to be of the same or compatible type.
Type parameters can also be used in class private data to create parameterized custom types. This is where type parameters become extremely powerful. Let's assume that we have a class 3D Vector.lvclass that has three instances of a "Data Element.ctl" Type Parameters. The default type of the Data Element is set to be DBL. The cluster private data has three instances of the Data Element, one for each of X, Y and Z.
Now we could create a Create 3D Vector method VI for this class that allows us to construct type parametrized instance of the class type.
Now calling this Create 3D Vector.vi with string as the inputs for type parametrized inputs X, Y and Z will create an instance of class 3D Vector with compile time type 3D Vector[String].
And this is where we now start seeing the superpowers of type parameters and parametrized types as well as generic type parameterized VIs that go along with them. Now we have a capability of creating custom VIs and custom types that both can adapt to different parameter types at usage time.
Let's get back to the question of dictionaries. We could easily construct a dictionary that allows the key type to be parametrized with one parameter and the value type to be parametrized with another parameter. For example we could use the dictionary with I32s as keys and Strings as values. Or we could use it with Strings as keys and File Paths as values. Constructor for such custom type would be trivial to create.
Once we have constructed the dictionary we would naturally like to use it. We could now use method VIs of the Dictionary class to add and fetch elements from the dictionary. As an example Get Element By Key would look something like this in it's simplest form.
Note that Dictionary In is type parametrized with two different type parameters Key Type and Value Type. In the class library there is a Type Parameter control Key Type.ctl and Value Type.ctl. Now type parameter Key Type.ctl is used both inside the private data of the class and on the fron panel as the Key input, the type of these two must be the same. The same is true for the Value Type element of private data and the Value indicator that both derive from Value Type.ctl type parameter. The has function is any function that can convert any LabVIEW types to some strings that we can use as keys for the variant attribute node. We are using variant attributes as the store implementation is this basic example.
Calling the Dictionary with integer as the type parameter and string as the value would look something like this.
As you can see the 0 and empty string will define propagate as type parameter types for Key Type and Value Type in the dictionary wire. Now Add Element.vi would have to adapt to these elections for Key Type and Value Type the moment the Dictionary wire is connected. The Key input immediately change to type INT32 and the Value input to type String. Similar would be true if the wires would be connected in reverse order. Connecting University of Texas string to the Value input of Add Element and connecting number 1 of type INT32 to the Key input of the Add Element would immediately adapt the Dictionary in and Dictionary out inputs to be of type Dictionary[Key Type = INT32, Value Type = String]. A type error would occur if Dictionary in would be of different type.
Type Parametrized Generic Types are an extremely powerful concept to incldue in a language and this idea describes a feasible way to implement them in a visual dataflow model of LabVIEW. This is and has been for maybe ten years my absolute #1 feature I have wanted to see in LabVIEW. I think the time is right for me to officially make this request. Ideally Type Parameters can be bounded but that's a topic for a whole other idea post.
Languages like 'R', 'Python', and MatLab (yes I use the old name) have these. They are useful.
One of the key ideas in LabVIEW is that the user needs minimal interventions to code a useful result. As more information is encoded in a data type there is more opportunity to make "hands free" code that "just works". I think these two data types can do that.
Primary data type in R
It is Array-like, but NOT an array
each column contains one measurement (row) on one variable
It acts like a list of vectors, but the vectors have the same number of rows, and indexing allows a return of all or subset from all columns
column types are heterogenous - they can be different
column types can be set. A column of 0 vs. 1 can be set as factors/binomial values or as continuous.
There are functions that data analysis folks do every day that are informed by variable type, so the function operating on the inputs doesn't need type specified because it is interior to the table. This means you can say "plot(mydata)" and if your data is set up well, the graph parameters are already specified and useful.
This is from Hadley Wickham, a very famous person in 'R'. He does great work, and his name has high brand value in data-analysis.
Uses the "data.table" package
is able to be screaming-fast (think roller-coaster) especially when used with the "split-apply-combine" approach to data analysis, and SQL-like operations.
is built for handling huge data (100GB tables) quickly and efficiently.
In many applications the same operation is not possible due to memory constraint or viable due to processor overhead can execute adequately (aka wonderfully) by using this data type on the same hardware.
The In Range and Coerce function is frequently used to determine whether a value is within range of an upper limit and lower limit values.
But when it is out of range, you often also want to know whether the value is out of range too high, or out of range too low. It is easy enough to add a comparison function alongside and compare the original value to the upper limit. It's another primitive and 2 more wire branches. But since comparison is one of the primary purposes of the In Range and Coerce function, why shouldn't it be built into it?
The use case that made me think of this that as come up in my code a few times over the years is with any kind of thermostat type of control, particularly one that would have hysteresis built into it. If a temperature is within range (True), then you would often do nothing. If it is lower than the lower limit, you'd want to turn on a heater. If it is higher than the upper limit, than you'd turn off the heater. (Or the opposite if you are dealing with a chiller.)
Request: Add an additional output to In Range and Coerce that tells whether the out of range condition is higher than the upper limit, or lower than the lower limit.
(That does leave the question as to what should the value of this extra output be when the input value is within range. Perhaps, the output should not be a boolean, but a numeric value of 1, 0, and -1, perhaps an enum.)
NI updater kindly informed me that LabVIEW 2014 SP1 was released (even though I uninstalled it shortly after I tried it last year) and out of curiosity, I took a look at the known issues list.
I learned a few interesting things I did not know about, and also that some problems had been reported as long ago as version 7.1.1. This type of stuff looks like bugs that won't be fixed, ever.
For instance, CAR #48016 states that there is a type casting bug in the Formula Node. It was reported in version 8 and the suggested workaround it to use a MathScript Node instead of a Formula Node (where is the "Replace Formula Node by a MathScript Node" contextual menu item?).
Problem: the MathScript RT Module is required. Even in my Professional Development System, this is not included by default. Does this really count as a workaround?
I read: we don't have the resources to fix that bug, or we don't want to break code that expected that bug.
In any case, this bug with most likely never be fixed.
The bottom line is, we can waste a lot of time as users, rediscovering bugs that have been known for a while and will probably never be fixed. As a user, I would really appreciate a courteous warning from NI that there are known traps and have a complete description handily available with the help file related to the affected function.
My suggestion: add a list of known issues (with link to their description) for all objects, properties, functions. VIs, etc, in the corresponding entry in the Help File.
I suggest that it should be allowed to mix booleans with numeric operations, in which case the boolean would be "coerced" (for lack of a better word) to 0,1, where FALSE=0 and TRUE=1. This would dramatically simplify certain code fragments without loss in clarity. For example to count the number of TRUEs on a boolean array, we could simply use an "add array elements".
(A possible extension would be to also allow mixing of error wires and numerics in the same way, in which case the error would coerce to 0,1 (0=No Error, 1=Error))
Here's how it could look like (left). Equivalent legacy code is shown on the right. Counting the number of TRUEs in a boolean array is an often needed function and this idea would eliminate two primitives. This is only a very small sampling of the possible applications.
Idea Summary: When a boolean (or possibly error wire) is wired to a function that accepts numerics, it should be automatically coerced to 0 or 1 of the dominant datatype connected to the other inputs. If there is no other input, e.g. in the case of "add array elements", it should be coreced to I32.
TensorFlow has APIs available in several languages both for constructing and executing a TensorFlow graph. The Python API is at present the most complete and the easiest to use, but the C++ API may offer some performance advantages in graph execution, and supports deployment to small devices such as Android.
Idea Summary: I would love to see LabVIEW among the "perhaps others".
(Disclaimer: I know very little in that particular field of research)
Currently, you can place a probe on a wire while developing, which is an indicator of the data on a wire. I want the ability to CONTROL the data on the wire, with a data forcing mechanism.
The implementation would be very simple... right click on a wire, and in the context menu the option "Force" would be right under "Probe." It would pop up a window of the forcing control, and while the VI is running and forcing is set to "Enable", the programmer can control the values that pass on the wire. If the force window were set to "Disable", the data in the wire would be completely controlled by the VI's logic.
I think the implementation by NI could be trivially simple. If you only allow a forcing control to be added during edit mode (not while the VI is running), the force could be added as an inline VI (as denoted by the green rectangle on the wire). The code inside the inline VI would be as follows, and the front panel would be "Data Force (1)" as shown above.
Of course, if you could add a force to a wire during runtime like probes, props NI. But I would be PERFECTLY happy if you could only add these force controls in edit mode prior to running.
One level further (and this would be AMAZING, NI, AMAZING): enable and disable certain parts of the cluster that you would like to force and allow the other elements to be controlled by the VI logic. I made the example above because it would be very natural to ONLY force Sensor1 and Sensor2, and letting the output run it's course from your forced input.
It is time to put a dent in the floating point "problems" encountered by many in LV. Due to the (not so?) well-known limitations of floating point representations, comparisons can often lead to surprising results. I propose a new configuration for the comparison functions when floats are involved, call it "Compare Floats" or otherwise. When selected, I suggest that Equals? becomes "Almost Equal?" and the icon changes to the approximately equal sign. EqualToZero could be AlmostEqualToZero, again with appropriate icon changes. GreaterThanorAlmostEqual, etc.
I do not think these need to be new functions on the palette, just a configuration option (Comparison Mode). They should expose a couple of terminals for options so we can control what close means (# of sig figs, # digits, absolute difference, etc.) with reasonable defaults so most cases we do not have to worry about it. We get all of the ease and polymorphism that comes with the built-in functions.
There are many ways to do this, I won't be so bold as to specify which way to go. I am confident that any reasonable method would be a vast improvement over the current method which is hope that you are never bitten by Equals?.
I would like to have the ability to set the compare aggregates mode for comparisons involving containers (arrays certainly, clusters would be a nice bonus) and a scalar value. This includes the comparisons to 0 functions as well.
LabVIEW has a somewhat hidden feature built into the variant attributes functionality that easily allows the implementation of high performance associative arrays. As discussed elsewhere, it is implemented as a red-black tree.
I wonder if this functionality could be exposed with a more intuitive set of tools that does not require dummy variants and somewhat obscure VIs hidden deeply in the variant palette (who would ever look there!).
Also, the key is currently restricted to strings (Of course we can flatten anything to strings to make a "name" for a more generalized use of all this).
I imagine a set of associative array tools:
Create associative array (key datatype, element datatype)
insert key/element pair (replace if key exists)
lookup key (index key) to get element
read all keys
delete all keys/elements
dump associative array to disk
restore associative array from disk
destroy associative array
... (I probably forgot a few more)
I am currently writing such a tool set as a high performance cache to avoid duplicate expensive calculations during fitting (Key: flattened input parameters, element: calculated array).
However, I cannot easily write it in a truly generalized way, just as a version targeted for my specific datatype. I've done some casual testing and the variant attribute implementation is crazy fast for lookup and insertion. Somebody at NI really did a fantastic job and it would be great to get more exposure for it.
Example performance: (Key size: 1200bytes, element size 4096: bytes, 10000 elements)
insert: ~60 microseconds
random lookup: ~12 microseconds
(compare with a random lookup using linear search (search array): 10ms average. 1000x slower!)
After applying my own subjective intellisense (see also ), I noticed that "replace array subset" is almost invariably followed by a calculation of the "index past replacement". Most of the time this index is kept in a shift register for efficient in-place algorithm implementations (see example at the bottom of the picture copied from here).
I suggest new additional output terminals for "replace array subset". The new output should be aligned with the corresponding index input and outputs the "index past replacement" value. This would eliminate the need for external calculation of this typically needed value and would also eliminate the need for "wire tunneling" as in the example in the bottom right. (sure we can wire around as in the top right examples, but this is one of the cases where I always hide the wire to keep things aligned with the shift register).
If course the idea needs to be extended for multidimensional arrays. I am sure if can be all made consistent and intuitive. There should be no performance impact, because the compiler can remove the extra code if the new output is not wired.
Several String functions have an "offset past ..." output (e.g. "search and replace string", "match pattern", etc.) and I suggest to re-use the same glyph on the icon.
Here is how it could look like (left) after implementing the idea. equivalent legacy code is shown on the right.
Idea Summary: "Replace array subset" should have new outputs, one for each index input, that provides the "index past replacement" position.
There are a plethora of timestamp formats used by various operating systems and applications. The 1588 internet time protocol itself lists several. Windows is different from various flavors of Linux, and Excel is very different from about all of them. Then there are the details of daylight savings time, leap years, etc. LabVIEW contains all the tools to convert from one of these formats to another, but getting it right can be difficult. I propose a simple primitive to do this conversion. It would need to be polymorphic to handle the different data types that timestamps can take. This should only handle numeric data types, such as the numeric Excel timestamp (a double) or a Linux timestamp (an integer). Text-based timestamps are already handled fairly well. Inputs would be timestamp, input format type, output format type, and error. Outputs would be resultant format and error.
I would love an update to the signal processing VI's contained in NI_MAPro.lvlib to support waveforms with a SGL Y-value representation. The library is locked and most VI's call dll's that are not able to be modified anyways (by me that is, I am not all that strong in traditional text based languages). It would be nice to also support SGL waveforms within the .llb's contained in vi.lib/measure; although these are mostly unlocked and able to be modified.
Working with a cRIO, the FPGA to host DMA channels encourage the use of SGL data type so I went with it and kept it as SGL throughout my application. For some functions I turn my SGL array into a waveform with SGL Y-value representation. I was disappointed to learn that most of the signal processing waveform tools contained in NI_MAPro.lvlib do not support the SGL Y-values.
The predessesor application was done on the usb cDAQ line that i was using DBL representation Y-values. I want to re-use a lot of code and was hoping the waveform signal processing VI's would accept SGL Y-values. For now I am stuck converting my data type for the sole purpose of re-using code; at 50kHz on 36 channels this can become a performance issue.
The Timing palatte is looking bad with all thes gaps. A simple fix would be to fill these holes with useful functions. I'm proposing 3 and attaching 2 from my re-use code. (I may re-create the third later)
Time to XL.vi (Attached): and its inverse, XL to Time.vi
12:00:00.0 AM Jan 0, 1900 is a pretty common epoch (Base Date) for external programs and converting from LabVIEW epoch shows up several times a year on the forums. and Time to excel has a few solutions to threads under its belt. Moreover for analisys against external data from other enviornments you are often using Access, Excel, Lotus... All share the same epoch (and Leap year bug) in their date/time formats. These vi.s have been pretty useful to me although the names may change to avoid (tm) infringements
Time to Time of Day.vi (Attached) has also been in my arsenal and proves both valuable and get on a few threads per year on the forum.