Manim:why is my graph plotted in half the animation time? - manim

I have this simple script, where I would like the ValueTracker (displayed as a number on the right) to evolve at the same speed with the graph. Instead the graph plotting finishes in 5 seconds. Do you know why and how to fix it?
from manim import *
class TrackerExample(Scene):
def sin(self,x):
f = 1 / 50
return np.sin(x * 2 * math.pi * f) / 2 + 0.5
def construct(self):
axes= Axes(x_range=[0, 749, 100],
y_range=[0, 4, 2],
axis_config={"include_numbers": True, "font_size": 24},
x_axis_config={},
x_length=4,
y_length=3
).move_to(LEFT * 2)
self.play(Write(axes, lag_ratio=0.01, run_time=1))
tracker = ValueTracker(0)
sin_graph = axes.plot(lambda x: self.sin(x), color=BLUE)
numbers = DecimalNumber(0).move_to(2*RIGHT)
numbers.add_updater(lambda m: m.set_value(int(tracker.get_value())))
self.add(numbers)
self.play(tracker.animate.set_value(749), Write(sin_graph), run_time=10,
rate_func=linear)
example = TrackerExample()
example.construct()
I am using the community version of manim, 0.16.0.post0

This is due to your choice of Animation: Write draws, in the first 50% of the animation run time, the stroke of the mobject and then fills it in the remaining 50% of the run time. Replace Write with Create, and it will look as expected.
And by the way, if you want to render your scene directly from the script, use the render method, not construct:
example = TrackerExample()
example.render()

Related

Drawing a Matrix

Im trying to generate a random map using a matrix but I dont really know how. Here is the
function for the matrix. wMap and hMap are the width and height, and mapSprites is a table containing some ground sprites. Also how can I draw the matrix? Im sorry if this is too much of a question, but Im really in need for some help
function buildMap(wMap, hMap)
for i = 1, wMap do
mt[i] = {}
for j = 1, hMap do
mt[i][j] = math.random(mapSprites)
end
end
end
Generating a random map in any programming language will utilize two core concepts: The language's random function and nested for loops, two for the case of a map/matrix/2d array.
The first problem, is you may or may not have mt initialized outside the function. This function assumes the variable exists outside of the function and each time the function is called it will overwrite mt (or initialize it for the first function call) with random values.
The second problem, the width, wMap, and height, hMap, of the map are in the wrong order, as maps/matrices/2d arrays first iterate over the height (y dimension) and then the width (x dimension).
The last problem, mapSpripes also has to be declared outside the function (which is not clear with your code snippet), which will be the highest possible value the random function can generate. You can read more about math.random here: http://lua-users.org/wiki/MathLibraryTutorial
Consider this function I wrote that makes those adjustments as well as has some additional variables for the minimum and maximum random value. Of course, you can remove these to have it fit your intended purposes.
function buildMap(wMap, hMap)
local minRand = 10
local maxRand = 20
for y = 1, hMap do
matrix[y] = {}
for x = 1, wMap do
matrix[y][x] = math.random(minRand, maxRand)
end
end
end
I suggest you use this function as inspiration for your future iteratins. You can make minRand and maxRand parameters or make matrix a returned value rather than manipulating an already declared matrix value outside of the function.
Best of luck!
EDIT:
Regarding your second question. Look back at the section I wrote about nested for loops. This will be crucial to "drawing" your map. I believe you have the building blocks to resolve this issue yourself as there isn't enough context provided about what "drawing" looks like. Here is a fundamentally similiar function, based on my previous function, on printing the map:
function printMap(matrix)
for i = 1, #matrix do
for j = 1, #matrix[i] do
io.write(matrix[i][j] .. " ")
end
io.write("\n")
end
end
For choosing random sprite, I recommend you to create a table of sprites and then save index of sprite in matrix. Then you can draw it in same loop, but now, you will iterate over matrix and draw sprite based on sprite index saved in matrix in position given by matrix position (x and y in loop) times size of sprite.
local sprites, mt = {}, {}
local spriteWidth, spriteHeight = 16, 16 -- Width and height of sprites
function buildMap(wMap, hMap)
mt = {}
for i = 1, wMap do
mt[i] = {}
for j = 1, hMap do
mt[i][j] = math.random(#sprites) -- We choose random sprite index (#sprites is length of sprites table)
end
end
end
function love.load()
sprites = {
love.graphics.newImage('sprite1.png'),
love.graphics.newImage('sprite2.png'),
-- ...
}
buildMap()
end
function love.draw()
for y, row in ipairs(mt) do
for x, spriteIndex in ipairs(row) do
-- x - 1, because we want to start at 0, 0, but lua table indexing starts at 1
love.graphics.draw(sprites[spriteIndex], (x - 1) * spriteWidth, (y - 1) * spriteHeight)
end
end
end

Unclear progress bar logic

My progress bar:
https://imgur.com/M6S3xkA
The problem:
How you can see, this is not a regular progress bar, the logic is unclear for me.
Let's say - when you have ~30 points (from 1000), you should have 50% in progress bar,
but how to count this magic number?
In normal case with 30 points (from 1000) you should have around <5%.
I will happy for any clues!
You should calculate the progress based on PARTS, which you split. In your case, you split range to 5 parts.
Step 1: Find which part the current point are in. (if point is 30, it is over 2 parts - (0..3) and (3..20))
Step 2: Find which percentage of the point in current part (if point is 30, current part is (20..50) -> percentage = (30 - 20) / (50 - 20) = 0.333
Step 3: Combine them and divide the parts number.
Sample code:
PARTS = [(0..3), (3..20), (20..50), (50..200), (200..1000)]
PARTS_NUMBER = PARTS.size # 5
def calculate_percentage point
part_index = PARTS.find_index {|x| x.include?(point)}
part = PARTS[part_index]
remain = (point - part.first) * 1.0 / (part.last - part.first)
(part_index + remain) / PARTS_NUMBER
end
calculate_percentage(30) # => 0.4666666666666667
Hope it helps :D

Need help in using turtle module

So I'm writing a program using the turtle module. I have 2 questions:
I have 4 turtles. How can I make their names show up on the screen while drawing?
After I finish drawing, how can I exit one screen and open another within the same program?
I have 4 turtles. How can I make their names show up on the screen
while drawing?
Sure, here's a crude example:
from random import choice
from turtle import Turtle, Screen
NAMES = ['Donnie', 'Raph', 'Mickey', 'Leo']
SPEEDS = ["slowest", "slow", "normal", "fast", "fastest"]
FONT = ("Arial", 12, "normal")
MAGNIFICATION = 5
STAMP_SIZE = 20
MAXIMUM_SPEED = 10
LINE_OFFSET = 50
screen = Screen()
WINDOW_WIDTH = screen.window_width()
START, FINISH = LINE_OFFSET - WINDOW_WIDTH//2, WINDOW_WIDTH//2 - (LINE_OFFSET + MAXIMUM_SPEED)
turtles = {name: Turtle(shape='turtle') for name in NAMES}
for offset, turtle in enumerate(turtles.values(), start=-len(NAMES)//2):
turtle.turtlesize(MAGNIFICATION)
turtle.color("black", "white")
turtle.penup()
turtle.goto(START, offset * MAGNIFICATION * STAMP_SIZE)
turtle.speed(choice(SPEEDS))
turtle.write("", font=FONT) # dummy write for 1st undo
winner = False
while not winner:
for name, turtle in turtles.items():
turtle.undo() # unwrite name
turtle.forward(turtle.speed() + 1)
turtle.write(name, font=FONT) # rewrite name
if turtle.xcor() >= FINISH:
winner = True
break
screen.exitonclick()
To do better with respect to text centering and eliminating flicker, we would need one or more extra invisible turtles to just handle the text. However, when the turtles turn, the text won't turn with them, it'll always be horizontal.

Scaling of Gaussian Equation

I'm using Gaussian equation for a particular photo effect in an iOS application.
I use:
double sigmaX = ...; //some value here
for(int i=0;i<height;i++)
{
double F = 0;
double step = -(pos)*width/20;
/*height,width,pos - all predefined, no problem there*/
for(int j=0;j<4*width;j+=4)
{
F = (double) ((1/1)*exp(-sigmaX*(pow((step++)/1, 2.0)))) ;
//do some operation here...
}
}
and the value of F is used to determine a particular intensity which is used up elsewhere.
So far so good.... F is the typical bell curve as expected.
But, the question is, I want to scale the standard deviation of this curve as per user input.
For example, in the following image, I'd like to shift the curve from the green to the red line (blue maybe an intermediate), hopefully in linear steps:
Now, given the standard notation of:
and comparing it with the way I implemented it in my code, I got the idea to vary 1/sqrt(sigmaX) to alter the scale/SD. I tried incrementing 1/sqrt(sigmaX) in linear steps (to get linear increment) or by x^n to get power of n increment in SD, but none of that worked.
I am a bit stuck with the concept.
Can you please let me know how to scale the Standard Deviation by a predefined ratio, i.e I may want it 1.34 or 3.78 times the oirginal SD and it will scale up the the +3sigma to -3sigma span accordingly.
Your calculation here:
F = (double) ((1/1)*exp(-sigmaX*(pow((step++)/1, 2.0)))) ;
Is not reflecting the Gaussian formula you showed. It should be something like this:
double dSigma = 1.0;
static const double dRootTwoPi = sqrt(2.0 * M_PI);
F = (1.0 / (dSigma * dRootTwoPi)) * exp(-0.5 * pow(step++ / dSigma, 2.0));
Then you can vary dSigma from 1.0 to 3.0 (or whatever) to get the effect you want.
Thanks Roger Rowland, for the help... I finally got this to work:
Changed the gaussian function to:
sigmaX*=scaling;
F = (double) ((scaling / (sigmaX))*exp(-0.0005*(powf((step++/sigmaX), 2.0)))) ;
Indeed, what I had done before wasn't exactly Gaussian. This works fine and scales fine, based on the scaling parameter.
Thanks again.

open flash chart rails x-axis issue

I am using open flash chart 2 (the plugin) in my rails application. Everything is looking smooth except for the range on my x axis. I am creating a line to represent cell phone plan cost over a specific amount of usage and I'm generate 8 values, 1-5 are below the allowed usage while 6-8 are demonstrations of the cost for usage over the limit.
The problem I'm encountering is how to set the range of the X axis in ruby on rails to something specific to the data. Right now the values being displayed are the indexes of the array that I'm giving. When I try to hand a hash to the values the chart doesn't even load at all.
So basically I need help getting a way to set the data for my line properly so that it displays correctly, right now it is treating every value as if it represents the x value of the index of the array.
Here is a screen shot which may be a better description than what I am saying: http://i163.photobucket.com/albums/t286/Xeno56/Screenshot.png Note that those values are correct just the range on the x-axis is incorrect, it should be something like 100, 200, 300, 400, 500, 600, 700
Code:
y = YAxis.new
y.set_range(0,100, 20)
x_legend = XLegend.new("Usage")
x_legend.set_style('{font-size: 20px; color: #778877}')
y_legend = YLegend.new("Cost")
y_legend.set_style('{font-size: 20px; color: #770077}')
chart =OpenFlashChart.new
chart.set_x_legend(x_legend)
chart.set_y_legend(y_legend)
chart.y_axis = y
line = Line.new
line.text = plan.name
line.width = 2
line.color = '#006633'
line.dot_size = 2
line.values = generate_data(plan)
chart.add_element(line)
def generate_data(plan)
values = []
#generate below threshold numbers
5.times do |x|
usage = plan.usage / 5 * x
cost = plan.cost
values << cost
end
#generate above threshold numbers
3.times do |x|
usage = plan.usage + ((plan.usage / 5) * x)
cost = plan.cost + (usage * plan.overage)
values << cost
end
return values
end
Also the other problem I'm having is I can't just add a few points as any values I give are taken as x being the elements position in the array and y being the value, whereas I need to be able to specify the x and y values for each point so I don't have to buffer my array with a bunch of null values
You have to create an XAxis Object to set the labels:
x = XAxis.new
x.labels = [100, 200, 300, 400, 500, 600, 700].collect(&:to_s)
chart.x_axis = x
From my experience there are many ways to do things with Open Flash Chart 2. mikezter example above is almost correct; however, this is how I set the XAxis labels.
x = XAxis.new
x.set_labels([100, 200, 300, 400, etc]).collect(&:to_s)
chart.x_axis = x
Note the only difference between my example and mikezter's is I use:
x.set_labels([array values etc])
instead of
x.labels = [array values etc]
I ended up ditching open flash chart 2 and going with Flotr

Resources