17

I'm occasionally in a situation where I have to use Mathematica on the terminal. I'd like to visualize the solutions I get from NDSolve, but when I use Plot, Mathematica just shows -Graphics- instead of trying to plot anything. I decided to write my own function for this:

AsciiPlot[functionsl_, {t_, tmin_, tmax_}] := Module[
{buffer, pts, width, height, ymin, ymax, s, functions, function, 
allpts},
width = 77; height = 24;
buffer = Table[" ", {height}, {width}];
If[Head[functionsl] === List, functions = functionsl, 
functions = {functionsl}];(*ensure functions is a list even if of length 1*)
allpts = Table[{x, (functions[[j]]) /. t -> x} // N, {j, 
 Length[functions]}, {x, tmin, tmax, (tmax - tmin)/width}];

(*Min and max of all y's across all functions to plot*)
ymin = Min[allpts[[1 ;;, 1 ;;, 2]]];
ymax = Max[allpts[[1 ;;, 1 ;;, 2]]];
s = (ymax - ymin)/(tmax - tmin);

For[i = 1, i <= Length[functions], i++,
function = functions[[i]];
pts = allpts[[i]];

(*I think it is bad form to declare a function inside a module, but it needs the variables and it is a pain to pass them all as arguments*)
set[point_, letter_] := ( 
  buffer[[height - point[[2]] + 1, point[[1]]]] = letter;);
PickLetter[slope_] := 
 Piecewise[{{"-", -.65 s < slope < .65 s}, {"/", .65 s <= slope < 
     3.5 s}, {"|", 
    3.5 s <= slope},  {"\\", -3.5 s < slope <= -.65 s}, {"|", 
    slope <= -3.5 s}}, "*"];
ScalePoint[p_] := 
 Round[{(p[[1]] - tmin)*(width - 1)/(tmax - tmin) + 
    1, (p[[2]] - ymin)*(height - 1)/(ymax - ymin) + 1}];

Map[set[ScalePoint[#], 
   PickLetter[D[function, t] /. t -> #[[1]]]] &, pts, 1];](*end for each function*)
Map[Print[StringJoin[#]] &, buffer, 1];]

How can I extend this to plot axes as well? My strategy (forcing even one function to be a list) for plotting multiple functions to mimick the native Plot[]'s behavior seems pretty unintuitive. Is there a better way?

Also, I would have preferred a function that could work on a Raster object, which would allow me also to use things like ParametricPlot and even the 3D plots with no extra effort. I couldn't think of a way to get around needing the derivative short of trying to fit curves to the rasterized image and plotting those. Any tips?

0xFE
  • 1,038
  • 7
  • 19

1 Answers1

25

If you're stuck with the terminal, but have access to X11 and Java, then I suggest using JavaGraphics`, which allows you to display plots, but continue to work in the terminal. This was also answered here, but I learnt it from from Jens.

If you really want an ASCII plot, I suggest using the Terminal` package that gives you an ASCII plot:

<< Terminal`
Plot[Sinc[x], {x, 0, 20}, PlotRange -> All]

enter image description here

It also works in the front end (although, I don't know why anyone would use it in the FE):

enter image description here

rm -rf
  • 88,781
  • 21
  • 293
  • 472
  • Wow! I had no idea this existed. Unfortunately, I get Can't open display ":0.0" when I try it. I am connecting to a linux machine that is at runlevel 3 (no X11 or any graphical interface) using ssh. – 0xFE Nov 01 '12 at 03:19
  • @user141603 JavaGraphics won't work without X11, but if even Terminal (which doesn't require JavaGraphics) doesn't work for you, then I don't know... please try using only Terminal in a fresh kernel – rm -rf Nov 01 '12 at 03:24
  • I am running CentOS 6.3. I reboot, login at the "localhost login:" prompt, run "math", type "<<Terminal`" and get that error... Very odd. – 0xFE Nov 02 '12 at 03:34
  • @user141603 It doesn't work for me either... on runlevel 3 Mathematica even produces a segfault. – sebhofer Nov 02 '12 at 09:39
  • @sebhofer I've never gotten a segfault. Are you using CentOS? – 0xFE Nov 06 '12 at 02:12
  • @user141603 No, I'm on Linux Mint Debian. – sebhofer Nov 06 '12 at 08:39
  • As cool as this is, I can't get it to work in Mathematica 10.0.3 – Michael Stern Oct 25 '15 at 00:10
  • Currently (version 11), on the open cloud online, this prints something like 255<>255<>255<>255... instead. – user202729 Dec 06 '18 at 13:31