Testing the Thermodynamic Functions for Saturated Water As A Function of Pressure–Except…

I started working through the graphs of the various thermodynamic functions vs. pressure and recognized that the standard format wasn’t showing all of the detail contained in the fits across the different ranges of input pressure. If the plotable width of the graph is about 350 pixels over a range of 1800 psi on a linear scale that would mean that every pixel represents a range of over 5 psi. As you can see from the function below the lower two ranges cover less than that and as a result would not even show up on a standard plot.

Expanding the plot to around 2000 pixels still doesn’t show all the details in a meaningful way. (The graph below is scrollable sideways.)

Generating plots over smaller and smaller ranges of pressure shows that each range of the function is smooth.

A way of getting these details to display is to do the plot on a logarithmic scale. I’ve done some of the work toward making that happen but that work will continue next week. I realize that I neglected to add this feature to the master list I created earlier this week, even though I was thinking about it. I’ve solved the basic parts of the problem but have to integrate the solution into the overall flow of code. As always, that may require breaking things apart into different functions. We’ll see how it goes.

Posted in Tools and methods | Tagged , | Leave a comment

Testing the Thermodynamic Functions for Saturated Water As A Function of Temperature

Here are plots of the standard thermodynamic values for saturated water, all as a function of temperature. Tomorrow I’ll plot them all out as a function of pressure.

I extended the range of each function below 32 degrees Fahrenheit to address conditions that occurred in a model I build earlier in my career. For those lower temperatures the water is not saturated but exists either in a subcooled state in the liquid phase of the superheated state in the vapor phase. Many of these function exhibit a discontinuity at 32 degrees. I apparently used data from a different set of tables which I’ll try to identify going forward, particularly as I work through the process of recreating the curve fits I did and correcting those that seem obviously in error. I’ll be working through that process next week.

I also believe that I’ve figured out why the plotted lines are so thick and why they often include small bulges that make the plot look like it’s chattering up and down unexpectedly. The effect appears to be caused by drawing lines with the lineCap mode set to “square,” which adds nearly a full pixel to either end of each plotted line segment. Since the curves are drawn at one-pixel intervals along the x-axis any pixel changes along the y-axis should result in extra thick lines or lone pixels above or below the plotted line. Tomorrow I will try producing the graphs with the lineCap mode set to “butt.”

There are clearly a few segments that look awry on these graphs, and they are usually at the lower end of the temperature scale, above 32 and less than 100 degrees. Re-fitting the curves will require me to implement a few of the features on my to-do list for the graph project, as well as demonstrating how the curve function were created in the first place.

Finally, here is an example of one of the thermodynamic functions. It is composed of individual curve fits across a limited range or temperatures, and the value for a global variable called graphCycle is set to an index based on which of the fits are used. That index is used to select the color in which that section of the function’s output curve is to be drawn. If the input value is out of the range covered by the function the value for graphCycle is set to a different constant indicating that the input value is lower or higher than the active range. In those cases no line segments are added to the graph.

Posted in Tools and methods | Tagged , | Leave a comment

Context for the Graph Project

A friend asked me what my recent series of posts is trying to communicate, so here is a brief rundown.

When not writing here about my previous experience or reactions to things I’ve seen or read, the goal is to work on a series of projects that accomplish the following ends:

  • Practice newly-acquired skills. Of late I’ve been concentrating on JavaScript and the HTML5 Canvas object, but I’ve also gotten more of a feel for web development in general, different modes of user interaction, and browser dependencies. I’ll be adding more jQuery elements going forward, and of course a wider range of tools, techniques, and languages over time. I’m currently working through yet another Java course and have courses in things like Python and Ruby in the queue as well.
  • Illustrate work I’ve done previously. The 3D pouring demo was a reconstruction of a code I write in Borland Delphi in the mid-90s for a control product for industrial furnaces that melt metals using high-powered induction. The graph demo touches on capabilities I’ve built into various real-time, simulation, and test harness codes I’ve written in the past.

  • Illustrate my passion for developing tools in a modular, iterative fashion that address a variety of possible requirements. Most of the development process I describe is just me thinking out loud as I’m working through problems of one sort or another. I’m not doing any of these projects with the same formality I would in a professional setting, especially up front. That said, I do stop and consciously reexamine things from time to time (e.g., as I did yesterday).
  • Give me problems that are tractable but interesting. I’ve done a lot of the low-level, nitty-gritty technical work involved in writing simulations, tools and other software from scratch, but I enjoy producing dynamic, visually interesting interface elements as well. I intend to work through some simulation tools going forward, but I need to create a few of the more basic widgets first.
  • Yield finished components that will be usable by a wider community with minimal overhead.
  • Provide a context for describing work and analyses I’ve performed in other areas. The graph project grew out of a desire to illustrate some of the work I’ve done with thermodynamics, numeric and technical computing, curve fitting, tool-building, and so on. Those discussions are all in the service of building a basic simulation capability to illustrate my deeper experience and understanding of that field.
  • Provide a goal that causes me to work through whatever problems I may encounter. This forces me to learn new things to solve problems.
  • Give me an opportunity to report on interesting things I find. I’ve learned a lot about the HTML5 canvas object that I comment on as I go, but eventually I will summarize all of my findings in a way that may be useful for others, including things that I haven’t seen anyone else write about where it is easily found. I’ve also identified a few exercises to work through that will illustrate some subtle details for me and possibly others. I also want to bee able to share links to descriptions and tutorials others have created that are so good that there is little or no need to try to improve upon them. The more people that can leverage the good work of others the better.
  • Elicit comments and feedback from anyone who happens to stumble upon my activities here. If you think it’s interesting or if you think it’s pointless I’d like to know.
  • Give me a hard and fast schedule that keeps me engaged on a consistent basis.

When I started this process I was able to generate a list of about 130 subjects I could write on, and so far I’ve probably addressed half of those. That exercise was useful for getting me into a consistent process that I hoped would make the ideas flow and force me into contact with new things on a regular basis. I have found a rhythm that works for me for the time being, and doubtless these communications will improve as time goes on.

This process reminds me of a very brief Reader’s Digest story I encountered when I was young, that for some reason has always stuck with me. Like the little girl in the story, finding new things to describe now has ceased to be a problem.

Posted in Software | Tagged , | Leave a comment

JavaScript Graph Object, Part 12

Today I think I’m just going to list all of the TO DO items for the project while taking a moment to see if anything in the basic structure of the existing code might be reworked. Rather than continuously banging through these items, the list of which is rather extensive, I am likely to use the project for the reasons that inspired me to start it in the first place, and then work items off the list as the need appears.

For the next day or two I’ll be testing out all of the thermodynamic functions of saturated water (liquid and vapor) I created many years ago. Then I’ll work on describing the creation of the functions from the steam tables using the curve fit program I wrote (also a long time ago). Those activities will definitely require extension of the graph object, and I will ultimately be able to finish creating the online steam table page I started a few weeks ago.

  • Make functionality of axes more independent and modular.
    • Add switches to suppress or allow drawing of axis labels.
    • Add switches to suppress or allow drawing of axis tick values.
    • Add switches to suppress or allow drawing of axis itself.
    • Add switches to suppress or allow drawing of axis opposite boundary line.
    • Add ability to draw axes on either side of the graph (left or right and top or bottom).
    • Add ability to draw multiple axes and have different plots use appropriate scale. (Y-axis at least but possibly x-axis as well.)
    • Break up plot mechanism to provide pixel locations as a function of value and value as a function of pixel locations for each axis independently.
    • Add staggered drawing of x-axis tick value labels when they get too long.
    • Add ability to draw major ticks between labels. This would presumably eliminate drawing of minor ticks.
    • Ensure final tick on any axis does not get drawn one pixel out of place (current mechanism sometimes draws final tick one pixel beyond the end of an axis due to cumulative rounding error).
    • Add ability of graph to set its own y-axis range based on the function or data to be plotted (if it has identifiable extents). The basic parameters are in place for this but are not currently being leveraged. (Add a getRangeHiLo function.)
    • Allow major ticks to fall at arbitrary locations so they don’t always have to fall at the first and last pixel of each axis.
    • Save bounds of each axis and element as part of being able to capture click events.
    • Add ability to draw labels at arbitrary locations in graph area (labels and tick values would stay at outer edge of graph area?).
    • Add ability to draw plots as x-as-a-function-of-y. This effectively rotates plots 90 degrees clockwise for the ability to scroll vertically and plot things the way economists sometimes do.
  • Make location specifications for all elements more generic.
    • Outer boundaries are currently defined as the edges of the canvas, but should be able to be set arbitrarily, so a graph could be placed anywhere.
    • More elements could be placed as needed (plot/symbol legends, additional axes, etc.)
    • Allow more elements to be arbitrarily placed (graph title, legend, etc.).
  • Add more plot mechanisms (that leverage already modular plotting mechanism).
    • Plot from table entries rather than from continuous functions.
    • Plot from continuous functions that don’t include cyclic color information.
    • Add lines, scatters, bars, box-and-whisker plots (and outliers), stock plots, plots where symbol size and color provide additional meaning, etc.
    • Add horizontal and vertical range lines (to illustrate ranges, things like run plots as used in quality analysis, warning limits on scrolling graphs, and asymptotes).
    • Add ability to handle parametric function plots that aren’t simply y-as-a-function-of-x.
    • Add plot/symbol legends.
  • Add animation, scrolling, real-time, and data features.
    • Add ability to have scrolling graph update interactively as new data is added (real-time scrolling).
    • Plot series data as non-scrolling animation.
    • Have graph object modify or extend animation features as new data are received through a receiver function.
    • Have graph object be able to record data received through a receiver function. Include time stamps with data.
    • Have object be able to recall and review recorded data and meta-data.
    • Allow user to select with data stream or streams are to be reviewed and displayed.
    • Make recall/review functions work across files split by time period or other method.
  • Make graph objects movable and able to be interactively displayed, hidden, and dismissed.
    • Graphically within a single canvas. Would need to save information it covers while moving or displaying.
    • Entire canvas object within a DOM page.
  • Add user interactivity, especially as ability to select elements by mouse click and use menus and dialogs to effect modifications. Especially may need to allow selection of plot elements in graphing area.
    • Add UI support for interactive modification of graph element parameters. Probably use tabbed dialogs. Could be in separate window, expanded or slideout region, or popup.
    • Place more limits on values that can be assigned to various parameters (e.g., angle of rotation of tick value labels only between -90 and +90 degrees).
    • Include a flag to indicate when any element is modified that may require re-spacing other element or otherwise redrawing the graph. This may not be needed because that logic can be handled in various places.
    • Add ability to scroll across larger data set (at least horizontally) under user control.
    • Add ability to zoom in or out on x-axis scale.
    • Add ability to zoom in or out on y-axis scale.
    • Add ability to modify values by dragging plotted elements?
  • Incorporate general enhancements.
    • Add support for additional fonts and font sizes over 30px.
    • Handle labels with multiple lines.
    • Add arbitrary text comments and pointers.
    • Add ability to include user-defined symbols or images (e.g., Steve Martin’s rubber chicken graph).
    • Add transparency and ability to draw over (arbitrary/user-supplied) background image.
    • Save graph description as a list of parameterized elements by x- and y-coordinates and other properties to they can be redrawn after arbitrary rotations in two or three dimensions. Requires transform between plot space and display space and separate means of storage for both.
    • Provide ability to print graphs.
    • Provide ability to save graphs as images.
    • Provide ability to save (and read) graph as XML specification.
    • Make occasional passes through code to improve efficiency and clarity.
Posted in Software | Tagged , , | Leave a comment

Turning the Graph Function Into an Object in JavaScript, Part 11

Today I continued to dive into smaller and smaller details of how the tick value labels get placed when they are rotated. When it seemed like I was done I set the graph up to continually modify the angle of the labels on each axis, along with the font size of the graph label, all at different speeds. What I saw was that the anchor positioning of the text for the tick value labels flicked around more than I thought it should. One thing that confused me was that I was trying to judge single-pixel alignment of text elements that varied in shape on either end, depending on the beginning or ending numeral.

I therefore decided to temporarily pad the label text with a capital letter “M” on each end. That told me that my initial design intent was correct and that I probably didn’t need most of the adjustment factors I was adding in.

I also added a small reference rectangle at the origin point for each text element (in green, upper left pixel is actual anchor, colors to not always reset correctly if drawing context is rotated). That turned out to be really interesting because I could clearly see that a certain amount of the location “chatter” I was seeing was due to the displacements accumulated as the HTML canvas object draws each character in the string supplied to the fillText function. These errors aren’t large, but when you’re trying to nudge things down to the last pixel they do become noticeable, especially over the course of drawing a longer series of characters. I therefore decided that things are good enough as they are for the time being. If things aren’t continuously moving you’d be unlikely to notice most of the issues.

The continuous cycling of the graph’s elements shows how the spacing is determined from each outside edge of the canvas in towards the drawing area. This isn’t the kind of thing you’d normally do with a graphing widget, but it seemed to illustrate things well for this purpose.

Posted in Software | Tagged , , | Leave a comment

Turning the Graph Function Into an Object in JavaScript, Part 10

Today the X-axis tick value labels can be rotated, though I may need to rethink what the angles actually mean. Also, a bit of spacing has been added to let the presentation breathe and some gentler colors were chosen for the gridlines in the graph area.

Posted in Software | Tagged , , | Leave a comment

Turning the Graph Function Into an Object in JavaScript, Part 9

Today I reorganized things so that the location of the graph axes are calculated automatically. The first image just shows the typical arrangement of items in their normal sizes.

The graph and axis labels are larger in this image.

In this image the graph and axis labels are back to their original size but the axis value labels are larger. In this case in particular you can see that the top value on the y-axis requires more clearance than the top graph label so there is extra space below the top graph label. If the y-axis text were tilted the other way there could be extra clearance at the bottom of the graph if the lowest value text was sufficiently long.

Next up is to reflect all functionality from the y-axis to the x-axis and make a few other tweaks. Then I can start adding different plotting functions and the ability to display axes on either side of the graph and also add additional vertical axes.

Posted in Software | Tagged , , | Leave a comment

Turning the Graph Function Into an Object in JavaScript, Part 8

The screenshots below show the graph object with different amounts of text rotation on the y-axis labels and the buffer spaces (shown as green bars) that indicate how the spacing of elements is to be determined from the outside edge in towards the graph area itself. All that remains to do now is actually implement the part where the location of the axes is calculated automatically (with errors if the size of the entire canvas is too small) from each edge and to reflect the code for the y-axis to apply also to the x-axis.

I had been working on all of this for a little while when I realized I was making the selection of the rotation point for the axis text way too complicated. That was followed by some very relaxing pruning and simplification. I think I got the solution fairly well generalized, but the slight offsets around text objects mean that getting things tuned just the way you want is a bit of a black art, though perhaps there is a slightly different way to approach the problem that I haven’t thought of yet.

I’ve also added the ability to draw major and minor grid lines on the graphing area and separated that functionality from the drawing of the tick marks, which can now be drawn inside the axis, outside the axis, inside and outside the axis, or not at all. The colors and fonts (at least the font sizes) can be set independently for all elements.

One interesting thing I noticed was that when rotating the y-axis label 90 degrees and then drawing the buffer bars on either side of it, is that there is actually a one-pixel shift in the text. Either the first half or second half of the text was higher (or farther left or right) by one pixel halfway through. I tried different angles of rotation but couldn’t find one that would not produce this artifact (at least in Firefox). I tried more and more subtle tweaks to the numbers and ended up with a rotation angle of Math.PI * 0.499999453 (give or take a 9) that seemed to be the critical point. I searched for a while (top 30 or so Google results) to see if anyone else has noticed this but haven’t found any mentions. I understand how such an artifact can creep into the canvas functionality but the perfectionist in me can’t help but be moderately annoyed. If anyone else has seen this, especially if they know what to do about it, please leave a comment here.

Posted in Software | Tagged , , | Leave a comment

Turning the Graph Function Into an Object in JavaScript, Part 7

Today I implemented the ability to rotate the tick labels on the graph axes. There are a few little tweaks left to implement and describe, but the figures below show how the various offsets work to position each label relative to the end of its associated tick mark. I added a small square to each label, the upper left pixel of which indicates the base location given to the textFill command to place the right-justified text. Finally, I added some text labels to show the relevant parameters as they are calculated and used. I’ll describe some of the more subtle details next time.

Notice how in the bottom example, with -45 degrees of rotation, the top of the y-axis label text reaches higher than the graph label text. When the code is written to locate the axes automatically, the calculation will take things like that into account.

Posted in Software | Tagged , , | Leave a comment

Turning the Graph Function Into an Object in JavaScript, Part 6

Here is a diagram of all the measurements needed to place items in the graphing area. Given the width and height of the canvas element in pixels you can see how every element is placed building in from the outer edges on all sides. The graph object in its current form requires the user to specify the location and extent of each axis, but when everything is done those locations will be calculated automatically.

  • leftOuterBuffer: pixels between outer left edge and elements
  • rightOuterBuffer: pixels between outer right edge and elements
  • topOuterBuffer: pixels between outer top edge and elements
  • bottomOuterBuffer: pixels between outer bottom edge and elements
  • graphLabelHeight: pixel height of graph label not including descenders, including row above and below
  • graphLabelDrop: pixel height of graph label descenders
  • graphLabelBuffer: pixels between graph label and graph area
  • xaxisLabelWidth: pixel width of the x-axis label, used for line wrapping (space between lines given by xaxisSecondLineOffset)
  • xaxisLabelHeight: pixel height of x-axis label not including descenders, including row above and below
  • xaxisLabelDrop: pixel height of x-axis label descenders
  • xaxisTickValueBuffer: pixels between x-axis label and tick value text
  • xaxisHeightPixels: pixel height of longest x-axis label
  • xaxisWidthPixels: pixel width of longest x-axis label
  • xaxisTickOffsetDown: vertical pixels between end of x-axis major tick and origin of tick label text block
  • xaxisTickOffsetLeft: horizontal pixels between end of x-axis major tick and origin of tick label text block
  • xmajorTickLength: pixel length of x-axis major tick lines
  • xminorTickLength: pixel length of x-axis minor tick lines
  • xaxisLeftPixels: overflow pixels to the left of the leftmost tick on the x-axis
  • xaxisRightPixels: overflow pixels to the right of the leftmost tick on the x-axis
  • yaxisLabelWidth: pixel width of the y-axis label, used for line wrapping (space between lines given by yaxisSecondLineOffset)
  • yaxisLabelHeight: pixel height of y-axis label not including descenders, including row above and below
  • yaxisLabelDrop: pixel height of y-axis label descenders
  • yaxisTickValueBuffer: pixels between y-axis label and tick value text
  • yaxisHeightPixels: pixel height of longest y-axis label
  • yaxisWidthPixels: pixel width of longest y-axis label
  • yaxisTickOffsetDown: vertical pixels between end of y-axis major tick and origin of tick label text block
  • yaxisTickOffsetLeft: horizontal pixels between end of y-axis major tick and origin of tick label text block
  • ymajorTickLength: pixel length of y-axis major tick lines
  • yminorTickLength: pixel length of y-axis minor tick lines
  • yaxisTopPixels: overflow pixels above the topmost tick on the y-axis
  • yaxisRightPixels: overflow pixels below the lowermost tick on the y-axis

Writing everything out like this shows that some of the names could be made more consistent, which item is going on the to-do list. Tomorrow I’ll go into more details about how the tick labels are placed relative to the tick marks, particularly when they are rotated.

Posted in Software | Tagged , , | Leave a comment