User talk:Inductiveload/Archive 1/MuPAD

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search

More about MuPad plots[edit]

Hey, thanks for the comment. I did already notice those images, but come to think of it, I actually think I can manage a lighting similar to that of Mathematica (normal lighting, not the rainbow colours one, a bit like your 3D Klein bottle done with Mathematica) using a colour function. I'll try to get that ready this evening. About your density plot at http://en.wikipedia.org/wiki/Image:Exponential_Function_%28Real_Part%29_Density.png, I suppose that render took you an horrendous while, how much ? I figured out doing density plots isn't the way to go, as it generally really takes too long, so I came up with an alternative :

z := x + I*y:
F := z -> 1/z:
f := plot::Function3d(Re(E^z),
x = -6..4, y = -5..5, Mesh=[20,20], Submesh=[1,1], AdaptiveMesh=0, 
FillColor=[0.6, 0.8, 1, 1], FillColor2=[0, 0, 0.3, 1]):
plot(f,
plot::AmbientLight(1), OrthogonalProjection = TRUE, plot::Camera([0, 0, 10], [0, 0, -10],PI/6),
plot::Transform3d([0, 0, 0], [1, 0, 0, 0, 1, 0, 0, 0, 1], 
             plot::modify(f, ZContours = [Automatic,15],
                             LineWidth = 0.3,
                             LineColorType = Dichromatic,
                             LineColor = RGB::White.[0.2],
                             LineColor2 = RGB::White.[0.2],
                             XLinesVisible = FALSE,
                             YLinesVisible = FALSE,
                             Filled = FALSE)),
       plot::Transform3d([0, 0, -5], [1, 0, 0, 0, 1, 0, 0, 0, 0], 
             plot::modify(f, ZContours = [Automatic,15],                              LineWidth = 0.5,
                             LineColorType = Dichromatic,
                             LineColor = [0.6, 0.8, 1, 0.4],
                             LineColor2 = [0, 0, 0.3, 0.4],
                             XLinesVisible = FALSE,
                             YLinesVisible = FALSE,
                             Filled = FALSE)),                            
GridVisible = TRUE, SubgridVisible = TRUE, GridLineWidth = 0.2, SubgridLineWidth = 0.1, 
GridInFront = FALSE, GridLineColor = RGB::SlateGreyDark.[0.2], SubgridLineColor = RGB::SlateGreyDark.[0.1],
TicksNumber = Normal, TicksBetween = 4, TicksLabelFont=["Cambria",10,RGB::CornflowerBlue], AxesTitleFont=["Calibri",12,RGB::SlateGreyDark],
ViewingBox = [-6..4, -5..5, -5..5],
Height=150, Width=150, Scaling=Constrained,
AxesTitles = ["x", "y", "z"])

Now, a few things here : the orthogonal projection allows getting a density plot by looking from above, the camera is specified to always have the view from above (the angle parameter doesn't change anything with orthogonal projection) and the diffuse light prevents the specular reflections. I just gave you the code as I'm using it for the moment, with quite peculiar colors and arguments at the end (like the fonts for the legend), but anyway, I think I got it quite good looking. Just comment out the line

plot::AmbientLight(1), OrthogonalProjection = TRUE, plot::Camera([0, 0, 10], [0, 0, -10],PI/6),

to get a normal render. Then another thing about this type of plots, I'd still like to know how to get renders similar to this http://mathworld.wolfram.com/images/eps-gif/ParabolicCylinderDContours_851.gif. When I tried with the density plot, firstly it took an horrendous amount of time to get any render, but I couldn't get nice transitions between colours : I tried many ways to bypass that, like doing a geometric mean with three plots with slightly different transitions (thus blurring out the transitions a bit, they were much too sharp and aliased with a simple "floor" argument). So If you know how to get that going with a colour function I'd be quite happy, but not with density plots as they really are too slow. Furthermore, I don't find any disadvantages to using 3D plots seen from above instead of doing density plots... Oh and also, if this is of any interest to you, I've got a quite nice visualisation scheme going on for conformal plots :

m := 11:
M := 5:
f := z -> (0.5*E^(I*PI/3)*(conjugate(z)-1)+1):
hsv1 := z -> RGB::fromHSV([(arg(z))*180/PI, 0.5+max(abs(Re(z)),abs(Im(z)))/(2*M), 0.25 + max(abs(Re(z)),abs(Im(z)))/(4/3*M), 0.6]):
hsv2 := z -> RGB::fromHSV([(arg(z))*180/PI, 0.5+max(abs(Re(z)),abs(Im(z)))/(2*M), 0.25 + max(abs(Re(z)),abs(Im(z)))/(4/3*M), 1]):
p := arctan(Im(z)/Re(z)):
q := abs(z)/(M*sqrt(2)):
plot(plot::Conformal(z, z=-M*(1+I)..M*(1+I), Mesh=[m,m],LineColorType=Functional, 
LineColorFunction=(hsv1)),
plot::Conformal(f(z), z=-M*(1+I)..M*(1+I), Mesh=[m,m], LineColorType=Functional, AdaptiveMesh=2, Submesh=[3,3],
LineColorFunction=(hsv2)), Axes=Boxed, GridVisible = TRUE, SubgridVisible = TRUE,GridLineWidth = 0.1, SubgridLineWidth = 0.1,
 GridInFront = FALSE, GridLineColor = RGB::SlateGreyDark.[0.15], SubgridLineColor = RGB::SlateGreyDark.[0.1], ViewingBox = [-5..5, -5..5])

Oh and, wow, I really like your Klein bottle construction images ! Congratulations. Anyway, thanks for being so helpful. --Xedi

As you already said on my talk page, Mathematica lighting consists of three lights : A red light at (1,0,1), a green light at (1,1,1) and blue light at (0,1,1). As there are no shadows or of the sort, it can't be that hard to :

  • Take away the specular reflections by putting ambientlight
  • Make a colour function that simulates this colour

Any ideas ? Would it be as complicated as having to get a normal vector for the surface to get the corresponding colour ? If so, how would non-orientable surfaces be coloured ? Just to get something like this http://commons.wikimedia.org/w/index.php?title=Image:KleinBottle-Figure8-01.png as it really looks nice.

--Xedi

Still more[edit]

Your lighting attempt is quite good, but there are of course many limitations, obviously the pesky speculars are one. I just modified your plot to see if there was any occlusion - thankfully there isn't.

dist  := 20:
intent:= 1:

                 
sphere := plot::Sphere(0.5, [0.6,0.6,0.6]) :
sphere2 := plot::Sphere(0.25, [0,0,0]) :
l1 := plot::PointLight([dist,0,dist], 
                          intent,
                          LightColor = RGB::Red):
                          
l2 := plot::PointLight([0,dist,dist], 
                          intent,
                          LightColor = RGB::Blue):
                          
l3 := plot::PointLight([dist,dist,dist], 
                          intent,
                          LightColor = RGB::Green):
                          
ambientlight := plot::AmbientLight(0.0):

plot(sphere,
     sphere2,
     l1, l2, l3,
     Axes = Frame,
     FillColor = RGB::White, 
     FillColorType = Flat, 
     Lighting = Explicit):

Shame about the speculars though. It or having an ambient light without speculars (and having to compensate with a colour function which is annoying), or having directed lights but speculars...

One of the reasons I didn't really like density plots was the aliasing - and the lack of effect of the antialiasing option. Render time seemed quite awful to me, but I see you're getting very decent ones - I'll have to try that again then. The problem of missing chunks can be sorted by giving a greater range (as you probably know anyway) but it's true that won't work for singularities, and that sure is an advantage of density plots compared to the orthogonal plots. But even on the Mathworld site, the "density" plots disappear for big values just as the normal ones do (as can be seen on the parabolic cylinder functions article).

For the curves on the density plot, and the grid, you could do like this :

plot(plot::Density(cos(PI*x*y), x = -2..2, y = -2..2), plot::Curve2d([cos(t),sin(t)], t = -PI..PI), GridVisible=TRUE)

But that would mean you would have to put lots of plot::Curve2D to get the z contours (and yes, the one that's here isn't relevant). For the grid, just use the regular expressions (the help will be of more use than I would, just change like GridLineWidth or GridLineColor for different grids) Another way to get the z contours would be transforming a 3D function and projecting it onto the 2D plane, but I get a "dimension mismatch" error as MuPad obviously can mix what comes from 3D plots (a 3D function transformed to be 2D) and 2D plots (here, density plots). I thought they got it working in the help with this example

c := plot::Cone(1, [-sin(a), 0, -cos(a)], [sin(a), 0, cos(a)], 
                a = 0..2*PI):
s := plot::Surface([x, y, 0], x = -1..1, y = -1..1):
S1 := plot::Scene3d(c, s):
S2 := plot::Scene3d(c, ViewingBoxZRange = -0.01 .. 0.01):
plot(S1, S2, Layout = Horizontal)

But actually this shows the limitation : the second plot is in fact 3D, and so can't contain a Density plot... Maybe if we could find a way to get a density plot in a 3D scene, that could be made to work, as sadly a transformation of a 3D function onto a plane can't be embedded in a 2D scene...

About the conformal, are you getting an error with x+I*y=-5-5*I..5+5*I ? Just do

delete z:

, hopefully that will sort it, obviously because z was defined as x + I*y in another plot and the conformal plotter doesn't like this. If that still doesn't work, try doing it in a new notebook.

Here another example (maybe a bit nicer)

m := 11:
M := 1:
f := z -> (1/z):
hsv1 := z -> RGB::fromHSV([(arg(z))*180/PI, 0.5+max(abs(Re(z)),abs(Im(z)))/(2*M), 0.25 + max(abs(Re(z)),abs(Im(z)))/(4/3*M), 0.6]):
hsv2 := z -> RGB::fromHSV([(arg(z))*180/PI, 0.5+max(abs(Re(z)),abs(Im(z)))/(2*M), 0.25 + max(abs(Re(z)),abs(Im(z)))/(4/3*M), 1]):
p := arctan(Im(z)/Re(z)):
q := abs(z)/(M*sqrt(2)):
plot(plot::Conformal(z, z=-M*(1+I)..M*(1+I), Mesh=[m,m],LineColorType=Functional, 
LineColorFunction=(hsv1)),
plot::Conformal(f(z), z=-M*(1+I)..M*(1+I), Mesh=[m,m], LineColorType=Functional, AdaptiveMesh=2, Submesh=[3,3],
LineColorFunction=(hsv2)), Axes=Boxed, GridVisible = TRUE, SubgridVisible = TRUE,GridLineWidth = 0.1, SubgridLineWidth = 0.1,
 GridInFront = FALSE, GridLineColor = RGB::SlateGreyDark.[0.15], SubgridLineColor = RGB::SlateGreyDark.[0.1], ViewingBox = [-2.5..2.5, -2.5..2.5])

The code is actually quite simple, it's just a bit obscured by the many variables I introduced... I'm sure you can understand how the colouring system works : hue corresponds to argument of the number, and then saturation and lightness depend on max(abs(Re(z)),abs(Im(z))) (I realize I could just of written max(Re(z),Im(z)), but well). Edit : In fact, it's abs(Im),abs(Re) obviously because saturation and lightness have to be positive.

For other things to do, well, I can't be of much help, but did you consider http://en.wikipedia.org/wiki/Fundamental_polygon ? Especially, there are some images to do with respect to the real projective plane (related are http://en.wikipedia.org/wiki/Boy%27s_surface, http://en.wikipedia.org/wiki/Roman_surface and http://en.wikipedia.org/wiki/Cross-cap).

To comment things out, it's easy, just write // and it comments out the full line after it.

Thanks again ! --Xedi

Colours ![edit]

Oh and another thing, another reason I don't really like density plots is that, at least those I've seen, it isn't linear. You have noted that in your Image:Exponential Function (Real Part at Infinity).png, but it just doesn't seem totally smooth (especially visible at the cyan and yellow borders I believe). How could that be fixed ?

--Xedi


I've looked a bit about colour models, and haven't managed finding anything relevant that would attenuate that indesirable effet of pseudo borders. Obviously the Hue model is the main cause of this Image:HSV-RGB-comparison.svg, have you got any idea of remediation ? Like using other curves than the ones depicted in that image to get a less steep gradient. I don't really know anything about colour perception, so wouldn't really be well placed to make a symmetrical model that would correct that problem. Anyway.

--Xedi

Hey, so I started trying using other curves than straight lines. Sadly, I went on trying with logarithms and it didn't come out too well (the borders are somewhat attenuated but not enough) : see this animation http://img353.imageshack.us/img353/1322/hsvcoloursdo2.gif . But yes, your idea with sines seems much better-I'll try that, maybe now if I have time, otherwise tomorrow.

--Xedi

Actually, it was quite a lot faster with sin, so I got an image up : http://img452.imageshack.us/img452/9523/hsvcolours2ux2.png . It definitely looks better than the preceding one and than the basic image. (This is with sin(PI*x/120), I'm sure good results can be achieved with sqrt(sin(PI*x/120)), but I ran into problems (XML error something, couldn't get it sorted)). Anyway, hopefully we'll find something - quite odd that nothing seems to exist to sort this problem...

--Xedi

Well, I sorted out the XML error by adding an abs(), seems quite odd as I did take care that the results were real, and they were, but the abs() sorted it out, so well. So I got a sqrt(sin(PI*x/120)) image : http://img178.imageshack.us/img178/3406/hsvcolours3jv3.png . Now it seems it's going to far the other way - the too step gradients are now in the pure colors (red blue green) rather than cyan magenta yellow. A bit a fine tuning could maybe do the trick. Oh, and for LAB colours, actually, I don't have an idea. I had a look at the wikipedia article but that wasn't of much help. Hope I'm not annoying you too much with all this !

--Xedi

I'll just leave you the full code so you can try it out - it's a bit cumbersome because I had to use a few tricks to bypass somethings...

a := 1:
r := plot::Function2d(piecewise([x<60,1],[x>60 and x<120, sin(PI*x/120)^a],[x>120 and x<240, 0],[x>240 and x<300, sin(PI*x/120)^a],[x>300 , 1]), LineColor=RGB::Red, LineWidth=0.7,x=0..360):
g := plot::Function2d(piecewise([x<60,sin(PI*x/120)^a],[x>60 and x<180, 1],[x>180 and x<240, (-sin(PI*x/120))^a],[x>240, 0]), LineColor=RGB::Green, LineWidth=0.7,x=0..360):
b := plot::Function2d(piecewise([x<120,0],[x>120 and x<180, (-sin(PI*x/120))^a],[x>180 and x<300, 1],[x>300, sin(PI*x/120)^a]), LineColor=RGB::Blue, LineWidth=0.7,x=0..360):
c1 := ((x) -> [1,abs(sin(PI*x/120)^a),0]):
c2 := ((x) -> [abs(sin(PI*x/120)^a), 1,0]):
c3 := ((x) -> [0,1,abs((-sin(PI*x/120))^a)]):
c4 := ((x) -> [0,abs((-sin(PI*x/120))^a),1]):
c5 := ((x) -> [abs(sin(PI*x/120)^a),0,1]):
c6 := ((x) -> [1, 0,abs(sin(PI*x/120)^a)]):
T1 := plot::Function2d(cos(30*PI*x)/2+2, LineColorFunction=c1, LineWidth=1,x=0..60):
T2 := plot::Function2d(cos(30*PI*x)/2+2, LineColorFunction=c2, LineWidth=1,x=60..120):
T3 := plot::Function2d(cos(30*PI*x)/2+2, LineColorFunction=c3, LineWidth=1,x=120..180):
T4 := plot::Function2d(cos(30*PI*x)/2+2, LineColorFunction=c4, LineWidth=1,x=180..240):
T5 := plot::Function2d(cos(30*PI*x)/2+2, LineColorFunction=c5, LineWidth=1,x=240..300):
T6 := plot::Function2d(cos(30*PI*x)/2+2, LineColorFunction=c6, LineWidth=1,x=300..360):
plot(r(x), g(x), b(x),
T1,T2,T3,T4,T5,T6,
ViewingBox = [0..360, 0..3])

Just to explain quickly : the value of a gives you the result with (sin(PI*x/120))^a. And the cos(30*PI*x)/2+2 thing is a bypass, it simulates a rectangle onscreen with the rapid oscillations - because I couldn't give a colorfunction to a normal rectangle... so I cheated. All the rest should be pretty explicit, but do ask if you would like more information.

And about the conformal plots, I would recommend you look at the mathworld page : http://mathworld.wolfram.com/ConformalMapping.html. Basically, all it is is looking at the image of the initial grid by a transformation, I added the colours to be able to see from where and to where a point is mapped. I find it also gives good insight to complex analysis, and in special of the behaviour of functions near poles. But I'm by no means an expert. Thanks for your time, I'll have a rest.

--Xedi

Wow, thank you very much for the code you provided - it's great ! There are just one thing I don't really understand : what's the arctan for, exactly ? And why did you put that factor of 1.2 ? (Well, you did comment it was to prevent it from cycling and merging, but actually wouldn't it be better (at least in some cases) with colours cycling ?). Actually I don't really understand your arctan - could you, for example, post a similar image than those you already made with the code ? That'll surely get me going. Other than that, I did a few graphs with z instead of arctan z, I think it comes out quite nicely (but with a low resolution for the moment !). Actually, why not try another function than arctan ? Even if it's true arctan is quite nice, as it's like x near 0 but still allows very big values by having a limit value.

About what value of a would be best, I did a little animation http://img359.imageshack.us/img359/3391/hsvcolours4iy2.gif

r := plot::Function2d(piecewise([x<60,1],[x>60 and x<120, sin(PI*x/120)^a],[x>120 and x<240, 0],[x>240 and x<300, sin(PI*x/120)^a],[x>300 , 1]), LineColor=RGB::Red, LineWidth=0.7,x=0..360,a=0.3..2.3):
g := plot::Function2d(piecewise([x<60,sin(PI*x/120)^a],[x>60 and x<180, 1],[x>180 and x<240, (-sin(PI*x/120))^a],[x>240, 0]), LineColor=RGB::Green, LineWidth=0.7,x=0..360,a=0.3..2.3):
b := plot::Function2d(piecewise([x<120,0],[x>120 and x<180, (-sin(PI*x/120))^a],[x>180 and x<300, 1],[x>300, sin(PI*x/120)^a]), LineColor=RGB::Blue, LineWidth=0.7,x=0..360,a=0.3..2.3):
c1 := ((x,b,a) -> [1,abs(sin(PI*x/120)^a),0]):
c2 := ((x,b,a) -> [abs(sin(PI*x/120)^a), 1,0]):
c3 := ((x,b,a) -> [0,1,abs((-sin(PI*x/120))^a)]):
c4 := ((x,b,a) -> [0,abs((-sin(PI*x/120))^a),1]):
c5 := ((x,b,a) -> [abs(sin(PI*x/120)^a),0,1]):
c6 := ((x,b,a) -> [1, 0,abs(sin(PI*x/120)^a)]):
T1 := plot::Function2d(sin(PI*x)/2+2, LineColorFunction=c1, LineWidth=0.5,x=0..60,a=0.3..2.3):
T2 := plot::Function2d(sin(PI*x)/2+2, LineColorFunction=c2, LineWidth=0.5,x=60..120,a=0.3..2.3):
T3 := plot::Function2d(sin(PI*x)/2+2, LineColorFunction=c3, LineWidth=0.5,x=120..180,a=0.3..2.3):
T4 := plot::Function2d(sin(PI*x)/2+2, LineColorFunction=c4, LineWidth=0.5,x=180..240,a=0.3..2.3):
T5 := plot::Function2d(sin(PI*x)/2+2, LineColorFunction=c5, LineWidth=0.5,x=240..300,a=0.3..2.3):
T6 := plot::Function2d(sin(PI*x)/2+2, LineColorFunction=c6, LineWidth=0.5,x=300..360,a=0.3..2.3):
plot(r(x), g(x), b(x),
T1,T2,T3,T4,T5,T6,
ViewingBox = [0..360, 0..3])

(The (x,b,a) bit is a bit of a bug I think, the animation doesn't do anything if I just put in (x,a)...)

I have got a CRT screen, and the best value does seem to be in the range 1-1.2 as you said, I'm sure 1 is fine and it's hard to tell the difference between 1 and 1.1 anyway. I personally quite like around 1.1, maybe a bit less. But all this shows a little problem with the colour plots - they are imprecise. But well, as long as the give the behaviour of the function correctly, it's fine (and the cyan magenta yellow stripes were definitely annoying, it's much better now). Thank you very much. --Xedi

Also, I was thinking, maybe it would be a good idea to put up a function that would be black near zero and white at singularities, with the regular colours in between. Sadly, that may mean having to redo the whole code... What do you think ? Could changing the arctan function to something else allow this ? It would be really easily done with HSL (Hue Saturation Lightness) : L would be 0 near 0, 1 near singularities and 0.5 everywhere else (something like arctan(x)/PI+arctan(x-20)/(2*PI)+0.25 maybe (yes, love those arctan too)). Anyway, it's still great as it is ! Cheers. --Xedi

I was looking around on commons (just looking at some math images) and encountered Image:Surface-plot.png, any ideas how to do that ? Especially with a 3D plot from above it seems easier... Any ideas how the program actually does these images ? (Here it's MathCAD, has Mathematica got anything relevant ?) Thanks --Xedi

Hmm, how can these renders take so long ? You said a 1600*1600 density plot takes you about five minutes, I started a 1000*1000 density plot one hour and a half ago and it still isn't finished... There must be something wrong... Oh well ! Edit : Well it just finished now, 1h40 after starting it ! --Xedi

Density plots[edit]

So, finally, here's what I got http://img45.imageshack.us/img45/5484/gammatestcolourstn0.png with this code


  f := abs(gamma(x+I*y)):

  ylimit := 3:
  xlimit := 5:
  mesh := 1000:     //resolution of density plot
   
a:=1:              //change this to adjust the colour band drop-of rate
fmin := 0:        //minimum value of colour function (i.e the one with arctan in it)
fmax :=  5:        //maximum value of colour function
range:=5:  //for brevity
  
colour := proc(c)
 begin
    if   c <  fmin then
       return ([1, abs(sin((c-fmin)*(PI/2)/(range/6))^a), 0])  //this term may not be needed, but it means we can deal with slightly under-limit values
    elif c <= fmin + 1*range/6  then 
       return ([1, abs(sin((c-fmin)*(PI/2)/(range/6))^a), 0])
    elif c <= fmin + 2*range/6 then
       return ([abs(sin((c-fmin)*(PI/2)/(range/6))^a), 1, 0])
    elif c <= fmin + 3*range/6 then
       return ([0, 1, abs(-sin((c-fmin)*(PI/2)/(range/6))^a)]) 
    elif c <= fmin + 4*range/6 then
       return ([0, abs(-sin((c-fmin)*(PI/2)/(range/6))^a), 1])  
    elif c <= fmin + 5*range/6 then
       return ([abs(sin((c-fmin)*(PI/2)/(range/6))^a), 0, 1])
    elif c <= fmin + 6*range/6 then
       return ([1, 0, abs(sin((c-fmin)*(PI/2)/(range/6))^a)])
    else 
       return ([1, 0,abs(sin((c-fmin)*(PI/2)/(range/6))^a)])
  end_if
end_proc:

  colfunc := (x,y,z) -> colour(z): //the factor of 1.2 prevents the spectrum from wrapping around and merging.

  
  cplot := plot::Density(f, 
                         x = -xlimit..xlimit, 
                         y = -ylimit..ylimit, 
                         AntiAliased = TRUE,
                         Mesh = [mesh, mesh],
                         AxesTitleFont = ["Courier New", Bold, 14],
                         TicksLabelFont = ["Arial", 10],
                         FillColorFunction = colfunc,
                         YTicksDistance = 0.5,
                         XTicksDistance = 0.5):
  
  plot(cplot,
       Axes = Frame,
       Width = 8.5*unit::inch, 
       Height = 7*unit::inch):

So I have a few questions : how come the colours cycle at all ? (as I just put in colfunc := (x,y,z) -> colour(z) ) And then, how come it cycles red/magenta ? Now I suppose I could of had a normal cycle with something like (z- range*floor(z/range)) instead of just z. I'll try that (but low LOW resolution). Edit : Tried it, it works fine for cycling colours. Last thing, the colours aren't really like I would like (but I like red for 0) : you easily see the evolution between red and yellow, but then it seems to get stuck on yellow... Maybe that's the opposite effect and we should increase a a bit more, or maybe it's something else. Edit : Changing a didn't change anything. Any ideas why ? If the render on your computer of this image isn't too long, could you try to get something looking nicer ? I'm also quite undecided about the cycling colors-maybe it is better to not have them cycling-must depend on functions (when the difference between min and max is too big, cycling might be better). Oh well, hope we can get all this sorted !

Thanks so much.

--Xedi

Firstly, yes that image is quite like the parabolic cylinder functions I found on MathWorld - I don't know, I felt like mentioning that again.

Anyway, I understood what you meant by cycle - obviously without that the really small numbers and the really big ones would have the same colour and that would be quite confusing. For the fact that the colours are getting stuck, I don't really think it's because of the lack of different colours (by the way, I was talking about my graph (http://img45.imageshack.us/img45/5484/gammatestcolourstn0.png and the new one http://img356.imageshack.us/img356/8725/gammatestcolours2lqcr2.png), not yours, as obviously yes for yours your justification is quite adequate.) I don't really know what to think : between red and yellow it's fine, between yellow and green it's fine, but it gets stuck at yellow red and green. No, actually, I know why : look at http://img443.imageshack.us/img443/6093/greencentredspectrumhl8.png (even with your screen) : the red yellow green cyan blue magenta all seem to be quite extended in space and the transitions are "quicker" : I'll try and change a, but when I tried to change a on the graphics, I didn't see any diffence (I did change it from 1 to 2 !). I'm just afraid my sin function isn't good enough whatever value of a it is : if a is small, cyan yellow and magenta are too spreaded, if a is big, red green blue are too spreaded, but if a is in betwenn ALL are too spreaded (but by a lot less). Maybe I'll try with circles just now, but I haven't really got much time on my hands. Edit : I tried circles, it's just bad. http://img444.imageshack.us/img444/7184/hsvcolourscirclessp6.png)

About your black and white for small and large singularities, I don't really understand, why not make them all the same colour ? How do you differentiation a "small" singularity from a large one ? I like the black for zero and white for singularities (or the other way round), it does show the important relationship between both. But then the colour functions would get nightmare-ish !

Oh well, we'll work it out.

--Xedi

What do you think we should do ? I think the colours being a bit stuck on my graphs comes from the fact we haven't managed a good-enough way to get a smooth and linear hue variation. Have you got any ideas ? Maybe we should just stick with the sin ones... Your choice.

--Xedi

I know this takes you a long time, but could you try a render of Image:Exponential Function (AbsReal Part at Infinity) Density.png (for example) with this new system (it would be perfect if the colours corresponded) to be able to see by how much the magenta cyan yellow bits become more smoothly distributed. If you have time, also, could you do that with two different values of a ? (quite different ones so that the differences become apparent, like, even to you with your LCD). Doesn't have to be high quality, of course. I'll try one and post it when it's done (surely tomorrow). Thanks for your time.

--Xedi

I really like your black and white and coloured function - just one thing I hope to see, is like on Image:Exponential Function (AbsReal Part at Infinity) Density.png to see how the transitions are. When those are sorted out, everything will be just fine. Cheers. (Going to sleep now - 1:50am here down in the French Pyrenees. Thanks for everything !)

--Xedi

Comparisons[edit]

I'm sure you already compared them, but look at old vs new. The comparison between these two images gives, I think, all the qualities and defaults of both methods : in the first one, there seems to be jumps around cyan magenta and yellow (with those values standing out where the function seems to increase/decrease faster), and in the second one, these jumps disappear, but there is something else, as I already said, instead of being (for example) as much between yellow and red than being just red, it seems the colour function stays longer in the six principal colours then changes quickly from one to another (but still much more smoothly than before) : instead of being red red red-yellow red-yellow yellow yellow it seems to be red red red red-yellow yellow yellow yellow. As I said that seems to be something to do with our method of interpolation using sines, it's much better than straight lines, but still not perfect. I can't really think of a better way than those sin (and changing the value of a isn't really beneficial - it's already optimal as it is, I think). Any ideas ?

Otherwise, yes, the arctan way-of-life is quite great for showing small variations near zero, but I also like the cycling colours way of doing it for some graphs (like for example my abs(gamma)) function. But I do agree it seems quite irrelevant for most of your images, that come out really nicely with the arctan (and surely less nicely with cycling colours).

Finally, this image gave me a great idea for all those parabolic-cylinder type colourings-I'll surely be back with a nicely working image within an hour or so.

Oh, and DON'T belive MuPad's counter for the seconds a render takes - for my 1h40 long render, at the end it said 1800s (that's 30min), but sometimes the counter is even worse (it's in the bottom right of the screen, and sometimes I wait 10seconds for it to go up by 1 second !).

I'll be back--Xedi (17:15 here, so that'll be 16:15 for you)


I'm back. I'm very happy with how this is turning out : contours as at Mathworld ! A few things about this :

  • The jagged colour borders are just the consequence of a low resolution (well actually, it's a high resolution, submesh=10, but well).
  • This image shows really well what I mean with the fact that our new colourfunction stays on the six main colours and then changes quickly between them : for example, on th e top left plot (or bottom right) the colours go (from high to low) : Red to Orange to Yellow to Yellow to Yellow to Yellow-Green to Green to Green. I think that's the only thing I dislike with our colourfunction.

Anyway, here's the code (well, basically, it's the same as yours with two lines changed !)

q := sin(PI*x)*sin(PI*y):

  conts := 21:
  xlimit := 1:
  ylimit := 1:
  submeshlevel := 10:

a:=1:
zmin := -1:
zmax := 1:
range:=zmax-zmin:
plotmin := -1:
plotmax := 1:
projectionlevel:=plotmin:
colour := proc(c)
 begin
    if   c <= zmin then
       return ([1, abs(sin((c-zmin)*(PI/2)/(range/6))^a), 0])
    elif c <= zmin + 1*range/6  then 
       return ([1, abs(sin((c-zmin)*(PI/2)/(range/6))^a), 0])
    elif c <= zmin + 2*range/6 then
       return ([abs(sin((c-zmin)*(PI/2)/(range/6))^a), 1, 0])
    elif c <= zmin + 3*range/6 then
       return ([0, 1, abs(-sin((c-zmin)*(PI/2)/(range/6))^a)]) //([abs(-sin((c-zmin)*(PI/2)/(range/6))^a),0,1])
    elif c <= zmin + 4*range/6 then
       return ([0, abs(-sin((c-zmin)*(PI/2)/(range/6))^a), 1])   //([0, abs(-sin((c-zmin)*(PI/2)/(range/6))^a), 1])
    elif c <= zmin + 5*range/6 then
       return ([abs(sin((c-zmin)*(PI/2)/(range/6))^a), 0, 1])
    elif c <= zmin + 6*range/6 then
       return ([1, 0, abs(sin((c-zmin)*(PI/2)/(range/6))^a)])
    else 
       return ([1, 0,abs(sin((c-zmin)*(PI/2)/(range/6))^a)])
  end_if
end_proc:

colfunc := (x,y,z) -> colour(floor((conts-1)/2*z)/((conts-1)/2)):

funcplot := plot::Function3d(q(x,y),
                             x = -xlimit..xlimit,
                             y = -ylimit..ylimit,
                             Mesh = [21, 21],
                             Submesh = [submeshlevel,submeshlevel],
                             LineColor = RGB::Black.[0.4],
                             LineWidth = 0.15,
                             FillColorFunction = colfunc,
                             AxesTitleFont = ["Courier New", Bold, 14],
                             ViewingBoxZRange = -1..1,
                             YTicksNumber = None,
                             YTicksAt = [-3*PI/2 = "-3 PI/2", -PI = "-PI", -PI/2 = "-PI/2", -2*PI = "-2 PI",
                                         0 = "0", 
                                         PI/2 = "PI/2", PI = "PI",  3*PI/2 = "3 PI/2", 2*PI = "2 PI"]
                            ):

contours := plot::modify(funcplot,
                         ZContours = [Automatic, conts],
                         LineWidth = 0.4,
                         LineColor = RGB::Gray20.[0.9],
                         XLinesVisible = FALSE,
                         YLinesVisible = FALSE,
                         Filled = FALSE
                        ):
                                                     
                             
ploteverything := plot::Canvas(funcplot, contours,
                               Width = 8.5*unit::inch, 
                               Height = 7*unit::inch,
                               plot::AmbientLight(1), OrthogonalProjection = TRUE, plot::Camera([0, 0, 4*plotmax], [0, 0, (plotmin+plotmax)/2],PI/6)
                              ): 
                       
plot(ploteverything);

It works quite nicely also, with a submesh of 10 it took me only about 3minutes (MuPad says 165sec).

So, now my first preoccupation is to find how to make it so colour changes are more regular - but I don't promise I'll be able to come up with anything !

Thanks a lot anyway, finally managed to make those Mathworld like contours.

Cheers --Xedi

I wanted to compare a bit more between our colourfunction and the basic HSV one, here's what I got : With our colours With the basic HSV colours So, ok, the difference isn't that big, but well.

Here goes the code for the second one :

q := sin(PI*x)*sin(PI*y):

  conts := 21:
  xlimit := 1:
  ylimit := 1:
  submeshlevel := 10:

a:=1:
zmin := -1:
zmax := 1:
range:=zmax-zmin:
plotmin := -1:
plotmax := 1:
projectionlevel:=plotmin:
colour := x -> RGB::fromHSV([3*180/PI*x+180,1,1]):
colfunc := (x,y,z) -> colour(floor((conts-1)/2*z)/((conts-1)/2)):

funcplot := plot::Function3d(q(x,y),
                             x = -xlimit..xlimit,
                             y = -ylimit..ylimit,
                             Mesh = [21, 21],
                             Submesh = [submeshlevel,submeshlevel],
                             LineColor = RGB::Black.[0.4],
                             LineWidth = 0.15,
                             FillColorFunction = colfunc,
                             AxesTitleFont = ["Courier New", Bold, 14],
                             ViewingBoxZRange = -1..1,
                             YTicksNumber = None,
                             YTicksAt = [-3*PI/2 = "-3 PI/2", -PI = "-PI", -PI/2 = "-PI/2", -2*PI = "-2 PI",
                                         0 = "0", 
                                         PI/2 = "PI/2", PI = "PI",  3*PI/2 = "3 PI/2", 2*PI = "2 PI"]
                            ):

contours := plot::modify(funcplot,
                         ZContours = [Automatic, conts],
                         LineWidth = 0.4,
                         LineColor = RGB::Gray20.[0.9],
                         XLinesVisible = FALSE,
                         YLinesVisible = FALSE,
                         Filled = FALSE
                        ):
                                                     
                             
ploteverything := plot::Canvas(funcplot, contours,
                               Width = 8.5*unit::inch, 
                               Height = 7*unit::inch,
                               plot::AmbientLight(1), OrthogonalProjection = TRUE, plot::Camera([0, 0, 4*plotmax], [0, 0, (plotmin+plotmax)/2],PI/6)
                              ): 
                       
plot(ploteverything);

So there.

Do you like it ?

--Xedi

So, I've just seen your image, personnaly I think it's very nice but for this type of functions I prefer my cyclic color ones (I feel with the arctan it's all a bit fuzzy to see how big the difference in values is, as with your method all the points on the real line to the right of 5 will look magenta-even the point at (20000,0) : it doesn't really convey the fact that the Gamma function rises very steeply - more than the exponential function. But then of course on your plots the non cyclic is much better ! (Mine for comparison (low res) if you can't find the link : here) But then come to think of it, you can't really get a colouring scheme that would be perfect, for example for yours you have to say that it's arctan so people can see that even if it's magenta at x = 5 and magenta at x=3000 there's a really big difference, and for mine I would have to explain how the colours cycle so that no one thinks the function starts to wildly oscillate. Both ways are nice, but I prefer the cyclic colours for the Gamma plot, and the arctan colours for all your "at infinity" plots.

Thanks. --Xedi

Summary[edit]

Density Plots[edit]

From 2D[edit]

  f := abs(gamma(x+I*y)):

  ylimit := 3:
  xlimit := 5:
  mesh := 1000:     //resolution of density plot
   
a:=1:              //change this to adjust the colour band drop-of rate
fmin := 0:        //minimum value of colour function (i.e the one with arctan in it)
fmax :=  5:        //maximum value of colour function
range:=5:  //for brevity
  
colour := proc(c)
 begin
    if   c <  fmin then
       return ([1, abs(sin((c-fmin)*(PI/2)/(range/6))^a), 0])  //this term may not be needed, but it means we can deal with slightly under-limit values
    elif c <= fmin + 1*range/6  then 
       return ([1, abs(sin((c-fmin)*(PI/2)/(range/6))^a), 0])
    elif c <= fmin + 2*range/6 then
       return ([abs(sin((c-fmin)*(PI/2)/(range/6))^a), 1, 0])
    elif c <= fmin + 3*range/6 then
       return ([0, 1, abs(-sin((c-fmin)*(PI/2)/(range/6))^a)]) 
    elif c <= fmin + 4*range/6 then
       return ([0, abs(-sin((c-fmin)*(PI/2)/(range/6))^a), 1])  
    elif c <= fmin + 5*range/6 then
       return ([abs(sin((c-fmin)*(PI/2)/(range/6))^a), 0, 1])
    elif c <= fmin + 6*range/6 then
       return ([1, 0, abs(sin((c-fmin)*(PI/2)/(range/6))^a)])
    else 
       return ([1, 0,abs(sin((c-fmin)*(PI/2)/(range/6))^a)])
  end_if
end_proc:

  colfunc := (x,y,z) -> colour(z): //put arctan(z/2)*(5.0001/6)/(0.5*PI) instead of z : your method, better for small changes around 0
  
  cplot := plot::Density(f, 
                         x = -xlimit..xlimit, 
                         y = -ylimit..ylimit, 
                         AntiAliased = TRUE,
                         Mesh = [mesh, mesh],
                         AxesTitleFont = ["Courier New", Bold, 14],
                         TicksLabelFont = ["Arial", 10],
                         FillColorFunction = colfunc,
                         YTicksDistance = 0.5,
                         XTicksDistance = 0.5):
  
  plot(cplot,
       Axes = Frame,
       Width = 8.5*unit::inch, 
       Height = 7*unit::inch):

From 3D[edit]

q := sin(PI*x)*sin(PI*y):

  conts := 21:
  xlimit := 1:
  ylimit := 1:
  submeshlevel := 10:

a:=1:
zmin := -1:
zmax := 1:
range:=zmax-zmin:
plotmin := -1:
plotmax := 1:
projectionlevel:=plotmin:
colour := x -> RGB::fromHSV([3*180/PI*x+180,1,1]): //Put our colour scheme for an other type of colours
colfunc := (x,y,z) -> colour(floor((conts-1)/2*z)/((conts-1)/2)): //Put z instead of floor((conts-1)/2*z)/((conts-1)/2) for continuous.

funcplot := plot::Function3d(q(x,y),
                             x = -xlimit..xlimit,
                             y = -ylimit..ylimit,
                             Mesh = [21, 21],
                             Submesh = [submeshlevel,submeshlevel],
                             LineColor = RGB::Black.[0.4],
                             LineWidth = 0.15,
                             FillColorFunction = colfunc,
                             AxesTitleFont = ["Courier New", Bold, 14],
                             ViewingBoxZRange = -1..1,
                             YTicksNumber = None,
                             YTicksAt = [-3*PI/2 = "-3 PI/2", -PI = "-PI", -PI/2 = "-PI/2", -2*PI = "-2 PI",
                                         0 = "0", 
                                         PI/2 = "PI/2", PI = "PI",  3*PI/2 = "3 PI/2", 2*PI = "2 PI"]
                            ):

contours := plot::modify(funcplot,
                         ZContours = [Automatic, conts],
                         LineWidth = 0.4,
                         LineColor = RGB::Gray20.[0.9],
                         XLinesVisible = FALSE,
                         YLinesVisible = FALSE,
                         Filled = FALSE
                        ):
                                                     
                             
ploteverything := plot::Canvas(funcplot, contours,
                               Width = 8.5*unit::inch, 
                               Height = 7*unit::inch,
                               plot::AmbientLight(1), OrthogonalProjection = TRUE, plot::Camera([0, 0, 4*plotmax], [0, 0, (plotmin+plotmax)/2],PI/6)
                              ): 
                       
plot(ploteverything);

Conformal Plots[edit]

m := 11:
M := 1:
f := z -> (1/z):
hsv1 := z -> RGB::fromHSV([(arg(z))*180/PI, 0.5+max(abs(Re(z)),abs(Im(z)))/(2*M), 0.25 + max(abs(Re(z)),abs(Im(z)))/(4/3*M), 0.6]):
hsv2 := z -> RGB::fromHSV([(arg(z))*180/PI, 0.5+max(abs(Re(z)),abs(Im(z)))/(2*M), 0.25 + max(abs(Re(z)),abs(Im(z)))/(4/3*M), 1]):
p := arctan(Im(z)/Re(z)):
q := abs(z)/(M*sqrt(2)):
plot(plot::Conformal(z, z=-M*(1+I)..M*(1+I), Mesh=[m,m],LineColorType=Functional, 
LineColorFunction=(hsv1)),
plot::Conformal(f(z), z=-M*(1+I)..M*(1+I), Mesh=[m,m], LineColorType=Functional, AdaptiveMesh=2, Submesh=[3,3],
LineColorFunction=(hsv2)), Axes=Boxed, GridVisible = TRUE, SubgridVisible = TRUE,GridLineWidth = 0.1, SubgridLineWidth = 0.1,
 GridInFront = FALSE, GridLineColor = RGB::SlateGreyDark.[0.15], SubgridLineColor = RGB::SlateGreyDark.[0.1], ViewingBox = [-2.5..2.5, -2.5..2.5])

3D plots[edit]

f := plot::Function3d(8*sin(x-cos(y))+(x^2+x*y),
                     Mesh=[30,30], Submesh=[0,0]):
plot(f,plot::Transform3d([0, 0, 0], [1, 0, 0, 0, 1, 0, 0, 0, 1], 
             plot::modify(f, ZContours = [Automatic,15],
                             LineWidth = 0.3,
                             LineColorType = Dichromatic,
                             LineColor = RGB::White.[0.2],
                             LineColor2 = RGB::White.[0.2],
                             XLinesVisible = FALSE,
                             YLinesVisible = FALSE,
                             Filled = FALSE)),
       plot::Transform3d([0, 0, -9], [1, 0, 0, 0, 1, 0, 0, 0, 0], 
             plot::modify(f, ZContours = [Automatic,15],
                             LineWidth = 0.5,
                             LineColorType = Dichromatic,
                             LineColor = RGB::Red.[0.9],
                             LineColor2 = RGB::CornflowerBlue.[0.9],
                             XLinesVisible = FALSE,
                             YLinesVisible = FALSE,
                             Filled = FALSE)),
GridVisible = TRUE, SubgridVisible = TRUE, GridLineWidth = 0.2, SubgridLineWidth = 0.1, 
GridInFront = FALSE, GridLineColor = RGB::SlateGreyDark.[0.2], SubgridLineColor = RGB::SlateGreyDark.[0.1],
TicksBetween = 1, TicksLabelFont=["Cambria",10,RGB::CornflowerBlue], AxesTitleFont=["Calibri",12,RGB::SlateGreyDark],
Height=150, Width=200,
AxesTitles = ["x", "y", "z"])

I think that does it. Maybe just adjusting the proc colour function. --Xedi