Choose Language Hide Translation Bar

Developing a Unit Conversion Add-In Using JMP 18 Python Integration

The units of physical quantities are extremely important to scientists and engineers. They communicate a lot but, unfortunately, can lead to huge and costly mistakes. An add-in has been developed to help manage units within JMP and reduce these errors. This add-in uses the new JMP 18 Python integration to easily do what would have been difficult to achieve in JMP 17. This presentation shows the capabilities of this add-in, as well as how it was developed, including Python use, source control, testing, documentation, and build systems.

 

 

Hi, my name is Evan McCorkle. I'm a developer with JMP, and I'm here today to talk about an add-in that I developed using the JMP 18 new Python integration. This add-in is for physical unit conversion, and I'm going to go over why I developed this add-in, as well as how I developed this add-in, the techniques that I use in developing it, and some of the details about the JMP 18 Python integration used there as well.

My training and my early career were as an engineer. In that training and in that early career, I had to deal a lot with different unit systems and different kinds of units, mostly US customary units and metric units. I'm sure many of you have to do this as well, and I'm sure many of you know that there have been many high-profile, costly mistakes due to unit conversion problems. For that reason, I always tried to use a tool to help me check my unit conversions.

Oftentimes, I use a Python library called Pint to do that. I was looking at the new JMP 18 Python integration, and I wanted to see, could we put that in with JMP's existing capability of annotating columns with their units? If you go to a column, you can put a unit on that column, and can we use that to do unit conversions and validate the units and all that thing?

That was the impetus behind developing this add-in. So the add-in capabilities, when you bring in a table, it can detect parenthetical units on columns and auto-assign the unit property and validate those units. It can let you look at a glance at your whole table and units for the whole table, make bulk changes to units, make sure that the system understands the units and the abbreviations that are being used, as well as determine the units for simple formula columns.

Then the main powerhouse of the add-in is converting columns between units. Converting from inches to millimeters, for instance. You can either do this in place or as a new column. When you convert the data, it will also convert over the column properties as well, like your reference lines your access settings, your spec limits, etcetera.

In addition to these capabilities, there's a browsable database of all the supported units and the ways that you can compose the units, as well as a JSL API. If you're interested in any of this, you can see the QR code on the screen here, or you can go to the community and look for the unit conversion add-in.

That's all I'm going to talk about the features of the add-in. Now I'm going to talk about how the add-in was developed. For source control for the add-in, I used Git and an internal GitLab instance. For building and deploying the add-in, I use the custom solution of a build add-in JSL file and a manifest JSL file, which I'll go into more detail in a minute. For testing, I use the JSL Hamcrest framework, so you can find that on GitHub. I am a co-developer of that framework. We use that framework internally within JMP to test JMP itself, and I use it to test this add-in as well.

For documentation, mostly Markdown files that are then converted to HTML using Pandoc and put into the add-in and then shown in the add-in using the JMP built-in web browser. Everything's implemented via JSL and Python with the pint library in Python. Then other tools, JMP, VS Code, Git, Pandoc, and Google Material Icons were used in this.

The structure of the add-in at the top level looks like this. You've got to build folder, docs, source, tests, and then the read me mark down files. So the tests are separate off on their own. The build has the build add-in and the manifest file and the artifacts' subfolder, which is where the HTML goes and where the JMP add-in itself will go when it is built. Docs are mostly screenshots and things like that. Then the source folder has several subfolders, icons, menu. So the menu has these action JSL files in it that are very, very simple. They're just used by the JMPcust file as a jumping off point, as well as source source, which is the bulk of the code. Then we have the def JMPcust and the adding load JSL file.

For the Manifest file, this is basically a listing of all the files from this structure over here on the left, that is going to end up in the JMP add-in archive that will then be installed. The build add-in JSL script basically does the Pandoc step to convert Markdown to HTML, reads the Manifest, and uses the JSL Zip Archive API to collect all the files and put them into a JMP add-in file in the build artifacts directory.

Anytime I wanted to add a new feature, I'll go put an icon in source icons. I go I got a short little stub code in source menu, and then the bulk of the code would go in source. I take all three of those files, add them to the manifest, edit the JMP add-in Cust file to refer to that little Stub in source menu. Then I could build the add-in and start developing on that feature and then add test to the suite in the test files.

The sub in source menu would just do some basic validation, like look for a current data table or something like that. Then it would include the main source file and then invoke the GUI. The reason for this separation is so we could easily include this main source file in the test and then test that feature without invoking GUI. It's just a nice division between the source menu, which is what's invoked interactively when you click on the menu, and the test files, and they both run through source-source.

Now, finally, since a big part of this add-in is using the new JMP 18 Python integration, I wanted to go in detail about how that works. That basically consists of three parts. First in the add-in load file. Whenever the add-in is loaded, we go try to install the Python packages. So pint is one of them. Install that, make sure it's installed. Then I have a com_jmp_unitconversion.py file that is installed with the add-in. I go ahead, and I'll import that as this fully qualified name here.

Basically, everything that's in that Python file is just a bunch of function definitions, and they all use the pint library. But there's no real work. It's just the function definitions. Then in the core JSL code, I wrap those Python calls using that fully qualified name and the Python integration inside of a JSL function. Then in the rest of the add-in, I can just use the JSL functions over here on the right. Are units convertible, feet to kilometers? Yes. Feet to milliliters? No. It's just using regular JSL functions, but internally, those are going into the Python code using the Python integration. Everything is set up on the add-in load, and all of my Python code is nice and contained inside of this one package, so I'm not polluting the whole Python namespace.

That is how I used the new in JMP 18 Python integration to develop this physical unit conversion add-in. Thank you.