Message Boards Message Boards

GROUPS:

Plot functions of Quantities with Units?

Posted 2 years ago
4301 Views
|
6 Replies
|
6 Total Likes
|

Hi, I'm trying to plot a function which takes quantities as inputs, but the resulting plot is either empty or completely wrong. Here is code that quickly shows the issue I'm having:

a = Quantity[0, "AngularDegrees"];
b = Quantity[90, "AngularDegrees"];
Plot[Sin[x], {x, a, b}]

I realize that if I instead do:

Plot[Sin[Quantity[x,"AngularDegrees"]],{x,0,90}]

that it works fine, so the issue seems to be in the range function (what is the list {x,xmin,xmax} called?). The problem is that I have functions which take multiple values, each with units, and where the ranges are all defined using constants or other functions, so I'd prefer to not write wrappers to rip off the units in order to make the range, and then put them back in when I call the function. This seems like a bug to me. Am I missing something? Is there some general work-around for this? Some way of making a range using Quantities?

Thanks in advance for any help that you can offer.

6 Replies

Hi Eric!

I ran your code in Mathematica 12.0 and it seems to work just fine, what version of the Wolfram Language are you running your code on? Here is the output of your code.

Here, as you can see, I'm using the version 12.0.0.

And, the Table[] function works with Quantity[].

One simple and a less technical workaround that I recommend you is to just update Mathematica. If you are not working on a huge scale project, I believe you won't have difficulties with code incompatibility. If you can't update to the newest version, please, describe the errors with screenshots.

Looking forward to helping you to figure out this problem.

Pedro Cabral.

Thanks for the quick response. The first plot is wrong, it should look exactly like the second one. I see the same output that you do.

Hey Eric!

Ah! I see! The first doesn't obey that logic, because it understands that the x-axis range is from 0° to 90°, and not for plotting the points for the range between a and b.

A simple solution for that is plotting using ListLinePlot[] with Range[] and the two quantity ranges.

You can wrap that into a function, and use it as an alias.

But for using Plot[] with an already existing range, that's impracticable...

Hope I could clarify the situation! Please don't hesitate to enter in contact with me!

Pedro Cabral

Thanks for another quick response. I wasn't familiar with the ListLinePlot function so it is good that I can use that to work around this bug.

I don't understand your comment about Plot "understanding" that the x-range is from 0 to 90 degrees. It isn't plotting it that way -- whether I choose to use:

Plot[Sin[x],{x,Quantity[0,"AngularDegrees"],Quantity[360,"AngularDegrees"]}]

or

Plot[Sin[Quantity[x,"AngularDegrees"]],{x,0,360}]

they should clearly yield the same result and they don't.

Here is another example which simply doesn't plot at all (even though you can evaluate the function, e.g. using your ListLinePlot, and it works)

f[x_] := x/Quantity[1, "Inches"];
l0 = Quantity[0, "Feet"];
l1 = Quantity[1, "Feet"];
Plot[f[x], {x, l0, l1}]

So I'm pretty sure that Mathematica has a bug that it doesn't understand Quantities (treat them properly) in the notation {x,xstart,xend} in the Plot function. Though, again, if I'm missing something important here please let me know.

I was finally able to find the answer on StackExchange: https://mathematica.stackexchange.com/questions/27680/units-plotting-and-empty-plots.
It is a bug with Plot (Hold holds more than it should). They suggest wrapping the function with Evaluate to solve the problem, but that doesn't work in the cases above, I'm not sure why.

I thought I'd follow up with my solution to this bug in case anyone else is interested. It is based on a really excellent StackExchange response to a similar question here: https://mathematica.stackexchange.com/questions/8865/pass-function-or-formula-as-function-parameter

Here is the code that I wrote based on that. Please note that I've only been using Mathematica a few days so it is entirely possible/likely that I've made some stupid mistakes. But it seems to work:

QPlot[fn_, intvl_, options___] := 
  Module[{func, externalSymbol, localVar, minQ, maxQ, unit}, 
   externalSymbol = Unevaluated[intvl] /. {x_, y__} :> HoldPattern[x];
   {minQ, maxQ} = Rest[intvl];
   unit = QuantityUnit[minQ];
   func = 
    Unevaluated[fn] /. 
     externalSymbol :> Unevaluated[Quantity[localVar, unit]];
   Plot[func, {localVar, QuantityMagnitude[minQ, unit], 
     QuantityMagnitude[maxQ, unit]}, options]];

In short, the idea is to strip the units off of the range limits and then put them back in before calling the function.

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract