Thursday, February 5, 2015

Announcing My Retirement as the World's Fastest LabVIEW Programmer

After winning the title of the World's Fastest LabVIEW Programmer at NI Week 2008 through 2014, and being challenged at additional venues along the way (I'm looking at you, Copenhagen!), I have decided to retire from the competition and allow someone new to claim the title at NI Week 2015. It feels right to go out on top with an undefeated record.

I've really enjoyed defending the title all these years, particularly because of how much it has allowed me to advance the use of Quick Drop to increase LabVIEW developer efficiency. I'm confident that whoever wins the NI Week 2015 competition will be a Quick Drop user.

Thanks to all of my opponents over the years for being such good sports, and good luck to whoever ends up competing for the title this year.

Wednesday, October 8, 2014

Three Use Cases for LabVIEW Bookmarks

When LabVIEW 2013 released, I was really excited about LabVIEW Bookmarks. I've been using them for a year now, and I feel they are one of the most productivity-enhancing features in the whole product.

What are bookmarks? Any word preceded by a "#" symbol within a free label, object label, wire label, or subdiagram label on the block diagram. So they're super-easy to create (you just type!), and also very easy to manage with the View > Bookmark Manager window. And my favorite (often-overlooked) aspect of the Bookmark Manager is that it will parse all of the VIs in your project for bookmarks, even VIs that are not in memory! In my opinion, that's the primary benefit that the Bookmark Manager provides over the standard Find window.

After using bookmarks regularly over the past year, I have discovered three distinct use cases where they come in handy:

To-Dos - This one is probably pretty obvious, but whenever there is a section of code that you know you'll need to revisit, stick a #todo bookmark there and use the Bookmark Manager to come back to it later.

Benchmarking - When I'm investigating a large app for performance improvements, I'll often make tweaks in several places to try to speed things up...turning on inlining, setting reentrancy, parallelizing For Loops, etc. I leave bookmarks (#inlined, #reentrant, etc.) where I make these changes to make it easy to come back to them later if necessary.

Code Review - I have a colleague with whom I've been doing frequent code reviews, and he's a Bookmark Believer too. It is so nice to arrive at his desk for a code review, and to see the Bookmark Manager already open on his screen, with #review bookmarks ready to go through, outlining all the changes he made.

So if you have LabVIEW 2013 or later, you should really start using this great feature! One final note...if you are using the Bookmark Manager to navigate through code that ships with LabVIEW, you might want to add these INI tokens to your LabVIEW INI file:

BookmarkManager.ShowVILIB=TRUE (LabVIEW 2013 and later)
BookmarkManager.ShowRESOURCE=TRUE (LabVIEW 2014 and later)

Without these INI tokens, the Bookmark Manager will not show bookmarks in VIs that live in the [LabVIEW 20xx]\vi.lib or [LabVIEW 20xx]\resource folders. Obviously I need these tokens for my work in LabVIEW R&D, but I can think of use cases where other LabVIEW developers might need to navigate bookmarks in shipping LabVIEW VIs as well.

Thursday, August 14, 2014

SubVI Panels as Modal Dialogs - A How-To Guide

It's fairly common in LabVIEW applications to display the front panel of a subVI in order to retrieve inputs from the user, or to just display information. Unfortunately, there are several "gotchas" associated with this seemingly simple use-case. Follow these steps to ensure your modal subVI panel functions properly.
  1. Handle the opening and closing of the subVI panel programmatically. You may be tempted to use the SubVI Node Setup right-click option on the subVI to easily display the subVI panel when it executes:

    The biggest problem with using this option is that your subVI is not allowed to run any initialization code before displaying its panel. If your subVI needs to move/disable/hide controls and indicators, you have no control over when it is "safe" to display the subVI panel when using this option. So instead, use the FP.Open method to display the subVI panel once you have initialized it, and use the FP.Close method to close it once the user dismisses the subVI dialog:

  2. Configure the VI Properties of the subVI properly. You'll want the Window Appearance in VI Properties to be set to "Custom", with custom settings like this:

    Note that the menu bar, title bar, and scrollbars have all been hidden. Also note that the Show Abort Button option is disabled...this is so a user can't abort your entire application by pressing Ctrl-. while your subVI dialog is active. The Window Behavior is set as Modal, and note that the Show front panel when called option is disabled, to avoid the same issues described in point #1 above.
  3. Call your modal dialog subVI dynamically. Whenever you run a VI, all of its statically-called subVIs (i.e. normal subVIs sitting on its diagram) are reserved for running. This means that none of the subVIs are in edit mode, since they may be executed by the top-level VI at some point. An unfortunate side effect of this behavior is that any reserved subVI that also has a modal window appearance will be immediately displayed if its front panel is already open. And since it is a modal window, you cannot dismiss it (since it's not running, it's just reserved for running). The best way to avoid this problem (other than always making sure your modal subVI panels are closed before running) is to call the modal dialog subVI dynamically:

    By changing the subVI to Load and retain on first call, it will no longer be reserved for running when you run the top-level VI, and as a result, will not ever hang your app if you accidentally leave it open before running.
Follow these steps for dialog subVIs (show/hide the panel programmatically, configure properties correctly, and call dynamically) to make sure your LabVIEW applications with user-visible subVI panels are robust and easy to develop and debug.

Saturday, November 3, 2012

Getting Started with Custom Quick Drop Keyboard Shortcuts

Back when I first introduced Quick Drop Keyboard Shortcuts (QDKS) in LabVIEW 2009, I wrote this blog post that discussed how to write your own shortcuts. That information is still valid (for LabVIEW 2009, anyway), but it's a bit dated, and doesn't quite discuss all the details and functionality available today. Plus, I've been asked several times recently about how to "get started" writing custom QDKS. So this blog post will be a a refresher, along with up-to-date information about what's currently available in LabVIEW 2012 that pertains to QDKS.

There is a plugin template that ships with LabVIEW that you can use to get started writing your shortcut:

[LabVIEW 2012]\resource\dialog\QuickDrop\QuickDrop Plugin

Yes, I know it should be a .vit file, and it will be in LabVIEW 2013...but for now, you have to save your own copy somewhere. Anyway, this VI is full of commentary describing how you go about adding the necessary scripting code for your plugin. The template already includes the bookend code necessary to set up an Undo transaction for whatever operation your plugin performs.

File Locations
You can place your plugin VI in one of the following two locations to make it available as a QDKS:

[LabVIEW 20xx]\resource\dialog\QuickDrop\plugins
[LabVIEW Data]\Quick Drop Plugins

If you put your plugin in the LabVIEW 20xx folder, it will only be available in that version of LabVIEW. If you put it in the LabVIEW Data folder, it will be available in any LabVIEW version (2010 and later), as long as you saved it in the earliest LabVIEW version you want to support.

Getting Started
Not sure how to get started actually writing the scripting code for your plugin? The shipping plugins are all fully documented, so you can browse their code for reference:

[LabVIEW 2012]\resource\dialog\QuickDrop\plugins

The Wire All Terminals and VI Server Rename plugins are password-protected because they use private scripting functionality, but the other plugins are available for your perusal. If you need any help writing your plugin, the Quick Drop Enthusiasts group on the NI Community has lots of experience writing shortcuts, and there are dozens of community shortcuts that you can use for reference as well.

Sharing your Shortcut
Once your plugin is ready for prime time, share it with the world! Post it to the Quick Drop Enthusiasts community, and include a link to it on the List of Community Quick Drop Keyboard Shortcuts page.

Friday, August 24, 2012

What's the Deal with Coercion Dots?

Let's talk about those little red dots on your diagram:

They used to be gray, but we changed the default color of coercion dots to red in LabVIEW 8.2, presumably to make them easier to see (and so their appearance wouldn't be confused with the Show Buffer Allocations feature).  Note that you can change the color of coercion dots in Tools > Options > Environment > Colors > Coercion Dots, but most people keep them red.

So what is a coercion dot, anyway?  It is LabVIEW's way of telling you that you have mismatched data types wired together, but they're close enough that your VI will still compile.  Contrast the image above with this one:

In the first image, you have two (different) numeric types wired to the Add function. Since both types are numeric, the Add will work, after it coerces one of the inputs (the I32) to match the other (the DBL).  In the second image, you're trying to add a numeric and a path.  Those types are coercion can be performed, so you get a broken wire.

The purpose of the coercion dot is to inform you, the programmer, when LabVIEW is performing a conversion behind the scenes.  You could explicitly perform this conversion yourself, thereby removing the coercion dot entirely:

Scalar Numeric Coercions
So how does LabVIEW decide which type will be coerced?  In the case of DBL vs. I32, it's rather straightforward...the I32 will be coerced, because coercing the DBL would lose fractional data.  Depending on which value is coerced, 1.7 (DBL) + 3 (I32) would either equal 4.7 (DBL) or 5 (I32)...I think we all agree that 4.7 is the better answer. :)

So for coercions like I32 -> DBL, you don't really need to worry about the coercion dot.  You could add the To Double Precision Float conversion function (these are often called conversion "bullets") to your diagram like the previous screenshot, but it's just going to do exactly what the coercion dot is already doing.
But what about trickier numeric coercions?  Check out this diagram:

I have indicated the data types of the constants in their labels.  In this diagram, the I16 has been coerced to a U16 value.  But since the result of this operation is a negative number, the U16 rolls under, and this diagram generates a value of '65531', even though you probably wanted it to generate '-5'.  So this would be a case where an explicit conversion on your part (specifically, of the U16 to an I16) would have been preferable.  When dealing with integer data types in particular, you'll always want to keep an eye out for places where roll unders or roll overs might occur.

One nifty feature to mention here is the Adapt to Source right-click menu option on numeric indicator terminals:

If you do convert the U16 input to an I16, and you have Adapt to Source enabled on the indicator, then its data type will automatically change to an I16 once the types match.

Array Coercions
A lot of the paranoia surrounding coercion dots is the concern that they "affect memory usage".  In practice, this often turns out not to be true.  Check out this diagram:

Now, the "coercion dots are bad!" crowd would tell you that, in order to avoid additional memory usage because of the different data types, you need to do something about that coercion dot, particularly if this loop is running a whole bunch of times (since the arrays might be very large).  Well, it turns out that, no matter how I try to "optimize" this diagram to remove the coercion dot (a few things I tried included using a conversion bullet on the iteration count, a conversion bullet on the I32 array, and maintaining my own DBL iteration count in a shift register), all other approaches used more memory during execution than the simple coercion dot approach illustrated here.  So before you go trying to get rid of every coercion dot on your diagrams because you're afraid they affect performance and memory, I'd recommend actually using the Profile Performance and Memory Window to see if any of the alternative approaches really are better.

Typedef Coercions
Another thing to look out for is coercion on typedef terminals. In these cases, the data types contained in the wire might be the same, but if one end of the wire is typedefed, and the other is not, you'll get a coercion dot.  In general, you're going to want to make sure this does not happen, and the easiest way to do so is to ensure that the source and the sink of the wire are both linked to the same typedef.  If you do not do this, and you see a coercion dot on a typedef terminal, then you may have problems when you change the data type of the typedef...the typedefed terminal will change, but the other terminal will not.  In the case of types like clusters and enums, you'll get a broken wire when the typedef changes. If you have many non-typedefs wired to typedefs throughout your VIs, these broken wires can become tedious to correct.  The easiest way to avoid these kinds of problems is to make sure the terminals wired together are linked to the same typedef.  For more information about typedefs, check out this Eyes on VIs post.

Variant Coercion
Another time when you'll frequently see coercion dots is when you're dealing with variant data types.  Since a variant can contain any LabVIEW data type, you'll often see APIs where you will wire a specific type into a variant terminal, and you'll see a coercion dot.  Again, this is perfectly fine, and it's usually a waste of diagram space to use the To Variant function to eliminate the coercion dot.  The only time I can recall using To Variant was when I had a case structure generating a variety of types in different cases, all of which went to the same (variant) output tunnel.  In this case, I had to use To Variant to avoid assigning a specific, non-variant type to the tunnel:

Identifying Coerced Types
If you want some more details about the specific types that are causing a coercion dot, there's a great new feature in LabVIEW 2012 that will display (in the Context Help window) the wired type, and the expected type, of a coerced terminal:

There are some other interesting scenarios involving coercion dots, like Dynamic Data, LabVIEW class wires, strict VI Server reference types, and more.  But for now, I'm hoping this blog post gives a good introduction to some more general issues regarding coercion dots.  I have described several scenarios that you need to watch out for...but these tend to be corner cases.  Usually, LabVIEW is doing the right thing behind the scenes when it has to coerce data types, and you won't need to worry much about memory usage, performance, etc., as long as you pay attention to the types you're using in the first place.

Friday, May 11, 2012

Spell Checking in LabVIEW

Did you know that LabVIEW has a spell checker?  Well, sort of.  It's the 'Spell Check' test of the VI Analyzer Toolkit.  The VI Analyzer Toolkit is a LabVIEW toolkit that you can either purchase separately, or is included as part of the NI Developer Suite.

The Spell Check test will check the spelling of words it finds in your VI against three different dictionaries:  (1) standard English words, (2) engineering and scientific technical terms, and (3) custom words added by the user.  The following configuration options can be used to customize which parts of your VI are checked, and what kind of words are checked (the screenshot shows the default selected options for the test):

But enough of the sales pitch (we've got other people around here for that) are some of the reasons our current spell checking solution is less than ideal:
  • Lack of integration - If you want to spell check your code, currently you have to run a separate tool (VI Analyzer) in order to see the results of the misspellings, as opposed to the standard way of just getting a red wavy underline of misspelled words as you type.  Also, to add a word to the custom dictionary, you have to do that through the VI Analyzer as well, as opposed to simply being able to right-click a word and add it to the custom dictionary.  Although I suppose it wouldn't be too tough to write a Quick Drop Keyboard Shortcut or a JKIRCF plugin to enable a UI gesture to do this as you sift through your VI Analyzer results.
  • English only - The VI Analyzer Toolkit is not localized, so we only provide English dictionaries.
  • Maintenance difficulty - Ok, this one is kind of selfish, but it's up to me, as the VI Analyzer Toolkit owner, to keep track of LabVIEW features that add different text fields to a VI so I can add the scripting code to the Spell Check test to get the text out of those fields.  In fact, I discovered recently a feature that was added two releases ago that I have yet to add Spell Check support for... :\
Despite these deficiencies, I've spoken to multiple developers who use the Spell Check test regularly because it's the best tool they have for identifying and fixing spelling mistakes in their VIs.  So with this blog post, I have a few questions to ask:
  1. Do you use the VI Analyzer Spell Check test?  If so, how has the experience been?
  2. Do you think it's a feature that would be worth significant investment for LabVIEW R&D to integrate better into the LabVIEW editor?
  3. Are there any words you've found flagged by the Spell Check test that you think should be added to our standard dictionary or our technical dictionary?
Even if you've never used the Spell Check test, or even thought about spell checking in LabVIEW before, your feedback is welcome!

Thursday, February 9, 2012

Captions: More than You Ever Wanted to Know

Every once in a while, the subject of control/indicator captions comes up around here, and every time, confusion arises.  So here we go...everything I know about captions.

The Basics
Enabling a caption on a control or indicator is straightforward enough:

If you select this option, your control doesn't appear to change if you leave the caption as its default value:

But trust me, it has.  We have hidden the label of the control.  You are now viewing its caption (in the same location as the label).  If you give the caption a different value than the label, you will see both in the Context Help window:

Any control with its caption showing (assuming the caption is different than the label) will display the caption at the top, and the label in brackets underneath.  When hovering over the terminal of a subVI, you'll see the caption of the control/indicator in the tip strip instead of the label.

Use Cases
Now why would you ever want to show the caption in the first place?  I know of two possible reasons:
  1. Long caption, short label - If you want your control/indicator to have a long, meaningful description on the panel, but you don't want that long string getting in the way on the diagram, you could show its caption. Personally, I eschew this approach...instead of using a caption, I would opt for a free label on the panel positioned appropriately near the control with appropriately-justified text.
  2. Localization - This is the primary reason we use captions in LabVIEW R&D.  When we localize LabVIEW into other languages, we don't want to change the labels of controls and indicators...that could potentially break code that programmatically refers to controls and indicators by name.  So instead, we show localized captions (and hide the labels) for the controls and indicators in all user-facing VIs that ship with LabVIEW.

Deleting a Caption
In older LabVIEW versions, there was no easy way to delete the caption of a control/indicator.  Thankfully, in LabVIEW 8.2 and later, it is very easy.  All you need to do is select the caption with your selection tool and press the 'Delete' key on your keyboard.  Note that this is not the same as highlighting the text in the caption and pressing the 'Delete' key...if you do that, the control will still have a caption, but it will be an empty string.

Working with Captions Programmatically
This is where it gets a little tricky.  By default, controls and indicators do not have captions.  Let's say you try to read the Caption.Text property of a control like this:

Believe it or not, one of three different things can happen with this code:
  1. If the control already has a caption, you'll get the caption text.
  2. If the control doesn't already have a caption, and the VI that owns the control is in edit mode, then a caption will be created for you, with the same string as the label, and you'll get that text.
  3. If the control doesn't already have a caption, and the VI that owns the control is in run mode, then you'll get error 1320, which tells you that you can't read properties of control parts that haven't been created yet when the VI is in run mode.
Because of all this craziness, there is another helpful VI Server property that you can use:

The "HasCaption" property will tell you if a control even has a caption to begin with, before you start trying to do other caption-related stuff.

One other nifty tip for dealing with captions programmatically...if you want to delete a caption programmatically, this is the way to do it:

So there you have it...way more information than you ever wanted to know about a LabVIEW feature that you probably weren't even using in the first place. :P  But in the event that someone ever does need this information, here's hoping this blog post eventually bubbles up to the top of a "LabVIEW captions" google search.  ;)