I want to create a line at the top of a figure that will move like a progress bar that completely fills up. My idea is to make it so that it's a function of time. I have a code for a Whack-A-Mole game and I have it set up so that instead of having a limited amount of time to "Whack" the moles, each whack gets progressively faster. I want some sort of a progress bar that crosses the screen at the same rate (indicating that when the bar has crossed the screen there is no more time left to whack the mole). I haven't seen anything that does this. Would appreciate any help.
MATLAB: Creating a moving line to depict progress
barfigurefunctionMATLABmoving lineprogresstime
Related Solutions
If you have a modern Matlab version >= 2016b, use the auto expanding instead of an explicit repmat:
% Ipc = repmat(I(:,jt2),[1,npmax(jz)-1]);
Ipc = I(:,jt2);... CnE(:,1:npmax(jz)-1,jl)) .* Ipc * dt / hb
I guess, that dt and hb are scalars (please do not let the readers guess!). Then remember, that Matlab evaluate the code from left to right:
Y = X * dt / hb
is equivalent to:
Temp = X * dt;Y = Temp / hb;
These are 2 matrix operations. But you can combine the scalar operations:
Y = X * (dt / hb)
This is 1 matrix operation and a cheap scalar division.
As Matt J has explained already, operating on subarrays as in |dCnE(:,2:npmax(jz)) is expensive. Better crop the data, such that you can omit the ugly indexing.
I cannot run it by my own, because you did not provide the input values, but compare it optically:
Ipc=repmat(I(:,jt2),[1,npmax(jz)-1]);dCnE(:,2:npmax(jz))=(sigma0*CnZ(:,2:npmax(jz),jl)-sigma*CnE(:,2:npmax(jz),jl)+ ... vs2*sigma*CnE(:,1:npmax(jz)-1,jl)).*Ipc*dt/hb+CnB(:,2:npmax(jz),jl)*(1-exp(-dt/tau2))... +vs2*(beta0*CnZ(:,1:npmax(jz)-1,jl).*(Ipc.^2))*dt/(2*hb)-CnE(:,2:npmax(jz),jl)/tau1*dt;
or:
c1 = 1 - exp(-dt / tau2); % Calculate constants outside the loops!
Ipc = I(:,jt2);dCnE = (sigma0 * CnZ(:, :, jl) - sigma * CnE(:, :, jl) + ... vs2 * sigma * CnE(:, :, jl)) .* (Ipc * (dt / hb)) + ... CnB(:,:,jl) * c1 + ... (vs2 * beta0 * dt / (2*hb)) * CnZ(:, :, jl) .* (Ipc .^ 2) - ... CnE(:, :, jl) / (tau1 * dt);
This can be simplified a little bit for the CnE term:
dCnE = (sigma0 * CnZ(:, :, jl) + ... CnE(:, :, jl)) .* (Ipc * ((vs2 * sigma - sigma) * dt / hb)) + ... CnB(:,:,jl) * c1 + ... (vs2 * beta0 * dt / (2*hb)) * CnZ(:, :, jl) .* (Ipc .^ 2) - ... CnE(:, :, jl) / (tau1 * dt);
Methods:
- Combine the scalar operations to reduce the number of matrix operations.
- Move constants out of the loop.
- Crop the data outside the loops instead of applying an a:b indexing in each iteration.
- Use auto-expanding instead of inflating by repmat. bsxfun is sometimes faster or slower than auto-expanding - try it.
- Avoid repeated calculations. In your case e.g. Ipc(:,1)*dt/hb is computed several times. Using this avoids this:
C1 = I(:, jt2) * (dt/hb);
The latter includes another idea: You inflate I(:,jt2) at first by Ipc = repmat(...), and waste time with cropping out a subvector Ipc(:,1) later on. Better create the subvector once only: Ipc = I(:,jt2).
Finally: Replace
non0=Cn0(:,jl); non0(non0<0)=0; Cn0(:,jl)=non0;
by:
Cn0 = max(Cn0, 0);
and move it outside the loops, because you do not use the cleaned values inside the loop.
The problem of you code was cp(i.*j,:). i*j is not a growing index. In the 1st iteration 1*1 is fine. For i=1 it works for the complete loop over j. But in the next iteration for i=2, j=1 you overwrite the value written by i=1, j=2. Better:
nx = numel(cpx);ny = numel(cpy);cp = zeros(nx * ny, 2); % Pre-allocation!!!
for i = 1:nx for j = 1:ny cp((i-1) * ny + j,:) = [cpx(i) cpy(j)]; endend
But this can be written without loops:
cp = [repelem(cpx(:), numel(cpy), 1), repmat(cpy(:), numel(cpx), 1)];
Best Answer