Crazy busy travel schedule. Comparing three metrics for consumer behaviour during respective national holidays.
For the data.world and makeover monday folks, a ‘snippet’ is a png picture of your code, that contains the code, and can be dropped in the program environment (IDE) and puts the code into your current program. Kind of a cut and paste of code.
I was inspired by the original graphics, https://www.statista.com/chart/3246/how-chinese-new-year-compares-with-thanksgiving/
so I was looking for a control that might have a round look to it. My first thought was to used meter controls , and so I stuck with that approach.
I replaced the pointer and center pivot with images to match the holidays. It retrospect, I should have looked to see if the meter display could be stretched into more of a complete circle rather than just a limited arc.
Because of the numbers involved, I choose to display two of the meters in logarithmic scale. I’m not sure if the average person reading an article would comfortable visualize the scales involved this way. However, the dial seemed very limited in its ability to display a nice, wide range of values, so in two cases, te display of one of the meters appeared to be zero.
In addition, I added a switch, to scale the values by the number of 1 million peoples in the samples, a sort of per capita of 1 million people. I didn’t see a large change in what was displayed, indicating that in both absolute dollars and in per capita, the relative differences between the two countries was the same. This was all based on how the graphs looked, so maybe quantitative measures could have told that story, but talk about scope creep.
I didn’t think about the actual differences in sheer values, and how these would affect the meter control’s display. So part of the lesson is to cleanse and evaluate the data prior to designing the display. However, the spirit of these lessons that I am using is to jump in head first, rather than treat the effort as a paid gig.
This affected me because the way the meters were displaying the data, the low values looking like zeroes, I spent some cycles troubleshooting the code.
I even went through the effort of programatically scaling the meters with high and low values. Turns out the low values still displayed in a way to look close to zero even though they were large numbers, but small numbers compared to the max. Thus the Logarithm ended up being a programmer’s choice, but maybe not a best “viewers choice”
This ended up being a simple read, analyze, and display. I used an event structure that only looks for the switch change. So, possibly overkill, but I think I am going to keep this approach, rather than polling, even on simple displays. I also made a snippet for the simple “empty” event structure.
I left the programmatic updates of the meter min/max values sitting like an bump on a log in the code. In retrospect, I would have evaluated the data challenges, and created the min/max values in the data read step, and passed them on in cluster to be used in the programmatic update of the meters.
Time to run on to next week and catch up. Meters are fun, but I need to explore updating the display to stretch further. With time I would have updated the switch to have a different visual element than a switch push button.
LabView shows it’s quirk in importing a field in quotes that has commas in it. It doesn’t recognize the quotes, and treats each commas as part of a CSV. Maybe there is an openG file loader that sees these like SQL does.
This week I got stuck on business travel for five days, so I got a late start on the Data.World data set. I cut off on Tuesday, giving myself two extra days.
I wanted to use a knob and a XY graph. The data set is challenging because there are five “dimensions”, or metrics, per country, and five years of data.
My thought was to have a knob to display the year of choice, in order of largest composite score. Then have a second knob to set the order of the largest value of a selected indicator score, including the composite score. I ran out of time on the second knob. Details on how this would be implemented is below.
I set the knob to show the year instead of a standard number. This is all native functionality.
The data is in text and numbers. I started out by focusing on the numeric values, not realizing that I would have to account of keeping track of the country name.
In addition, I have to calculate the composite score, and store it by country and year too.
I ended up using clusters to hold the data that I wanted to display or manipulate. This is much easier than running parallel arrays, for numeric values and for text values.
For the Data.World crowd, Clusters are like containers, they can hold all sorts of data types, text, numerics, arrays and more.
There is a file I/O function. In it I also perform some small calculations to provide meta data later on. As an Aside, I think I will start creating more meta data functionality blocks. I noticed this is becoming more and more needed as I progress through these exercises.
After I/O the data is manipulated to create the composite score, and then to sort by that value, for each year. To do this you also have to keep track of what number goes with what country, this is where clusters come in handy.
The next step is to prepare the graph. For this data set, I had to create a plot for each indicator of each county, for each year. So, having the value of each indicator is not enough, I had to create the points that are the stacking of the individual indicators on top of each other, in size.
Once the graph and data are ready I set up a loop so that when the knob changes, the graph is updated with the data from the respective year. I calculated the yearly data sets, and stored them in an array by year. This way we are calculating the data organization once, only having to display it thereafter.
The second knob I didn’t get to would have been selecting the indicator value, including the composite score, and having the graph order the data by that value. Currently it only sorts by composite score. To do this, it would have been the same exercise, that is, create all those plots, and then store them. I would have used a 3D array, where the pages were years, and the rows would have been the indicators.
The article & Code
I hope you enjoy the code. There was some hard coded elements due to time restrictions. I’m looking forward to starting to customize the native UI elements. Time permitting I should start to get these worked into the weekly routine.
10 Downing Street energy usage, the new data set for Makeover Monday. For this week I decided to use a waveform graph.
For the Data.World crowd, a waveform graph in LabVIEW will take and display a data type called a waveform. This data type, a container of sorts, contains a starting date/time, the time interval between points, and an array of data points.
Although I have usually used the waveform for scientific data, it seems like a good fit for data set that is based on a calendar.
The graph comes standard with it’s organic graph controls. Mainly types of zooms. I wanted to add in the ability to translate or zoom using the mouse.
When the mouse pointer is hovering over either of the values of the graph axis the mouse can then control the graph view by the use of the wheel. Scrolling the mouse will move the data to the right or left, translated. If the right mouse button is held and the scroll wheel is moved, the graph will zoom in or zoom out at that point.
I noticed the data is provided missing the first energy value, and also sorted alpha numerically in the half hour column a second level sort after the calendar day sort , so that in any day, the half hours are not in order. They go .5, 1, 1.5, 10, 10.5, 11 ….. 2, 2.5, 20, 20.5 , …… So they have to be sorted. I decided to just fill in the one missing energy, rather than go through all the hoops of data validation, where I would discover missing data an most likely put in an interpolated value or discardit as bad data.
There is a lot of effort required to know where the mouse is in relation to the graph axis values. All of this is made more interesting based on where the graph is in relation to the origin of the front panel.
My effort to implement the zoom feature of the mouse involved determining the two distances from the mouse to the ends of the axis location, i.e. the top and bottom of the vertical (y) and the left and right fo the horizontal (x). I got it mostly correct, but I seemed to have missed a subtlety. The graphs also translate a bit while they zoom. It is much more evident in the x-axis, the calendar date/time. I think it is more evident as this value is stored as the number of seconds since 1900.
I’ll have to come back at some point a figure it out.
This weeks UI was a single element. I focused on the mouse zoom and translation. I probably should have spent more time with pen and paper to really map it out, mental note to self. But .. having gone with the more relaxed approach, I ended up using more troubleshooting efforts, tracking values in the code using probes.
I wanted to make the x-axis, the time, to be more like the original chart from data.world. It was my plan to make the zooming go from one year, to zoom to one quarter, to zoom to one month, and then to one week. So it would not be an analog zoom, like the Y-axis, but more of a discrete steps zoom.
Minimum wage, my second Data.World entry. I completely ran out of time on this week.
My first several data sets I am going to continue with the theme of using the native LabVIEW FP controls.
This week a slider and a tree are making an appearance. I set the slider to use actual numbers as the scales.
For those from Data.World a few LabVIEW pointers. Talking about the wires, is a reference to the code. LabVIEW is a visual data language, and the data flows along wires. The code looks like a circuit, to a certain extent, so thus the name wires for the data flow. The “pallet” refers to a small pop up window that shows all the functions that can be used in LabVIEW. So if you want to use a function that adds two numbers, the add function is on the pallet.
Click on the slider, to select a year, and the data for that year will display in the tree. Very simple.
I should have put the headers into the Tree so a person would know what the heck they are looking at. Well, I’m holding myself to a one week cut off. Also, I needed to put some cleaner looks on the slider and the Tree, they are really almost straight off the pallet.
Main Process and Development
I got caught up in the process of massaging the data. I developed an idea to use a three dimensional array, where each page was all the data for one state.
In this way, I could easily go to each page and pick out the year data.
The main loop uses a case structure to act on the change of the slider. When there is a change, the year selected is used to search each page.
For the code, I decided to force the code to have to look up all the sizes and ranges, and set the slider values. This way, if next year (week, etc…) we get a different data set, the slider will set itself to the range of years in the data, the number of stated, the number of columns, etc…. as much as possible.
I had to cut myself short, so the Tree Bins I hard coded from the article.
I can see how these data sets give a person a lot of choices on how to code, how much to focus on the wires and how much on the display. For this one I took to much of my limited time on the code, as opposed to the display.
For example, I decided to make two large arrays of the file data, one as text, the other as numeric data types, this way I didn’t have to continuously update the data type for display and use later on. However, since I stopped developing functionality, I ended up not using the numeric data type for calculations … I had been thinking about coding colors for states above or below the national average, or to also make a display of each states rate of change of their minimum wage data.
I did use the numeric data to bin the states, by comparing the state values against the bin values, for sorting the states into bins in the tree.
Source Forge: 1-14-2019 minimum wage folder –> https://sourceforge.net/projects/data-world-labview/files/1-14-2019%20Minimum%20Wage/
I could put in another week on this, but gonna keep as is to stick with a one week timeline. First view of the slider and the tree. Spent a lot of time messing around with formatting the data. I wanted to preallocate all the arrays, even though this data set is small, I want to keep with the approach that I would use for large data sets, that is to reduce memory allocations and data copies.
Freedom of the press. My first run at the Data.World data set. I decided to use multicolumn tables, combo boxes, and XY Graphs. For the UI, I am sticking with the organic front panel controls, but colored to a very plain white look.
For those from Data.World a few LabVIEW pointers. A VI is a like a subroutine or a function. The Front Panel (FP) is what you see, and the Block Diagram is where the code is written.
My intent is to get up to speed at quickly making updates to standard User Interface elements. My first few projects will likely be me refreshing on some of the finer points of the UI elements, so there will be a lot of standard “looks” for a while.
The main UI functionality will be to display a selected plot in one graph. I also wanted to be able to stack multiple plots, so I use a second graph to “stack” multiple plots for comparison. However, I use a switch to activate the addition of plots to the “stacking graph”. Finally I want to be able to remove plots from the “stacking graph”.
I wanted the user to be able to use the drop down feature of the combo boxes to select plots to show or add, and to select plots to remove from the stacked graph.
The three actions are 1) displaying or adding graphs from the full list combo box. 2) Removing plots using the ‘remove’ combo box. And 3) using the switch to turn on or off the the functionality for adding plots to the stacked graph.
The Multicolumn tables require deliberate clearing, they can’t be simply reset with an “init all to default” command. I also set the active cell to the 0,0 point.
Generally each of the controls has to be set clear, and a lot of it can be done using the VI level ‘re-init to default values’ function. However, the combo box and the multicolumn list box are set to clear using their property nodes.
Graph inits are always intensive, having to clear the plot data and the plot names. In more complex plots, you might also set colors, line size, cursors, etc… So for this I made a subVI for all the actions needed. For this UI it was only plot names.
I created a subVI to read in the data, and then to arrange it into the format I felt would be the easiest to use for placing the data into the UI elements.
I decided to use a polling loop to look at changes in the combo boxes. These two changes would indicate that a new plot is to be displayed/added or that a plot is to be removed from the stacked plot.
During the update, if a new plot is selected, the switch is also checked to see if the country should also be added to the stacked plot. If the “county to remove” combo box is changed, then that country is removed : the plot, plot name, and the county name from the combo box.
The User Interface
Data world is all about displaying data. For this project I am displaying data using native controls. I was running short on time, so they are not as dynamic as the could be. To make them resizable, panels could have been used on the front panel.
The list boxes contain all the entries for each county year and year data.
I would probably change the graph background color too. A mental reminder to focus more on the UI than the code. Ha Ha, but I honestly ran out of time, I am making a point of cutting myself off by the end of the week.
I decided to do this all without a specification document. I paid the price, as I started with a simple polling loop, and then I wanted to add the functionality of plotting multiple countries, and realized that after I finished the VI, It was easier to make a second VI, more thought through, with the full functionality I wanted planned from the start, so that is why there is a “second try” VI file.
As this is more for my personal interests, I am using a ‘head first dive’ approach to planning. I find it to be a good gut check, and a way to get more lessons learned.
So far, the major functional sections each week will likely be: clear UI elements, read file data, format data to fit the functional and display plan, and then main processing implementation.
Also, for the first several I plan to force myself into using many different UI elements for the practice, and then make the UI look as intuitive as possible for the chosen elements.
I hope you all enjoy. More details to follow. I can see adding in data output functionalities. If I can get an intuitive functionality, and display the data as desired, it would be great to add the output, either files, reports, or both, that are based on how the user chooses to display, and what subset of the data they choose.