I want to modify the MATLAB app I recently made to scrape web pages, so that it can handle the case where there is more... read more >>
]]>Sean's pick this week is MATLAB Project File by Dmitry Ratner and the new Projects functionality... read more >>
]]>Sean's pick this week is MATLAB Project File by Dmitry Ratner and the new Projects functionality in base MATLAB added to R2019a. This was previously Simulink Projects but Simulink is no longer required.
Have you ever wanted to work on a project and when starting for the day, or had a new team member start on the project, have everything configured for you? Well now you can leave behind those addpath(genpath(pwd)) and those instructions like "run this script before starting" or the effort to manually choose which files export when sharing with someone else!
Dmitry's File Exchange submission provides a means for configuring the path, shortcuts, and a startup script and works in older versions of MATLAB. Projects in base MATLAB also do this but go much further by allowing export capabilities, shut down files, upgrade advisors, categories for different files, graphical dependency and product analysis, integration with source control and more.
Here I will describe how to create a project from an existing set of files and configure it. I will use the "Pick of the Week" Folder where I keep all of the blog entries and utilities to publish them.
First, create a new project. I usually do this by going from an existing folder to a project (even if the existing folder is under source control).
Give it a descriptive name and then set it up. Set up will ask you which folders to add to the path.
You can then specify anything to run when starting or shutting down the project. I don't need that here.
Next you can create custom labels or use the existing ones to label files in the project. A filter can then be applied to show just those files.
If you'd like to see dependencies in the project, you can right click on a file to view it's dependencies as a graph, or the files impacted by it if you want to change it. This will also point out project dependencies and potential missing files required for your code to run.
You can run checks against the project, upgrade it at once (more important for Simulink workflows), and manage source control all from within the project toolstrips, and have custom tasks or shortcuts.
Additionally, you can replace anywhere that needs to find the location of a file using mfilename('fullpath') with the RootFolder property of currentProject.
prj = currentProject
prj = Project with properties: Name: "potw" SourceControlIntegration: "Git" RepositoryLocation: "http://insidelabs-git.mathworks.com/sdewolsk/potw.git" SourceControlMessages: [1×3 string] ReadOnly: 0 TopLevel: 1 Dependencies: [1×1 digraph] Categories: [1×1 matlab.project.Category] Files: [1×4604 matlab.project.ProjectFile] Shortcuts: [1×0 matlab.project.Shortcut] ProjectPath: [1×19 matlab.project.PathFolder] ProjectReferences: [1×0 matlab.project.ProjectReference] StartupFiles: [1×0 string] ShutdownFiles: [1×0 string] Description: "" RootFolder: "C:\Documents\MATLAB\potw" ProjectStartupFolder: "C:\Documents\MATLAB\potw\MatlabProject" SimulinkCacheFolder: "" SimulinkCodeGenFolder: ""
I hope you're as excited about Projects in MATLAB as I am. I've been using them since the prerelease became available to us and it has made my day to day project work much easier.
Give it MATLAB projects a try and let us know what you think here or leave a comment for Dmitry.
Get
the MATLAB code
Published with MATLAB® R2019a
Why are manhole covers round? It is so they won't fall through the hole they are intended to cover. They have the same... read more >>
]]>Why are manhole covers round? It is so they won't fall through the hole they are intended to cover. They have the same diameter regardless of where it is measured. If the hole has a slightly smaller diameter, it is not possible to orient the cover so that it will fall through. A square or rectangular cover can be turned slightly and it will easily fit through the hole.
The circle is not the only planar curve that has this constant width property. The Reuleaux Triangle is the next best-known curve of constant width. I want to describe an interactive MATLAB® program that generates generalizations of the Reuleaux Triangle.
Image Credit: Wikipedia
Franz Reuleaux (1829-1905) was a German mechanical engineer, a professor at the Eidgenössische Technische Hochschule Zürich, then a lecturer at the Berlin Royal Technical Academy and ultimately President of the Academy. In addition to his triangle and many other mechanical creations, he is known for the theory of kinematic pairs.
Here is the Reuleaux triangle in action in an animated gif showing one full rotation. The sides of the "triangle" are circular arcs; each is one-sixth of a circle centered at the opposite vertex.
The triangle is rotating, but not about the origin at its center. These plots were made with the MATLAB command
axis tight square
so the bounding box is a square with the length of a side equal to the diameter of the curve. The x and y labels show this diameter. The fact that the diameter does not change as the figure rotates is the defining property of constant width.
These animations vary two parameters, n and delta. In the next two figures there are n blue dots at the vertices of a regular polygonal. There are n large arcs; each is one n-th of a circle centered at the opposite blue dot. They join the n small arcs, each is one n-th of a circle of radius delta centered at the nearby blue dot. The resulting curve is smooth, except when delta is zero.
The diameter is always the distance from one large circular arc to the opposite small circular arc, no matter how the curve is rotated.
Here n is kept constant at three and delta varies.
Here delta is kept constant at 0.05 and n varies over odd integers.
The blue dots do not have to form a regular polygon. Here they form a 3-4-5 triangle.
I will add an interactive app, constant_width, to Cleve's Laboratory. You can choose regular or irregular spacing, vary n and delta, and rotate the resulting curves at any speed.
I was intrigued by a paper by Stanley Rabinowitz. He describes how curves of constant width can be generated by so-called "support functions." An example is
$$ p(\theta) = a \cos^2{(\frac{k\theta}{2})} + b $$
Parametric equations for the curve are
$$ x = p(\theta) \cos{\theta} - p'(\theta) \sin{\theta} $$
$$ y = p(\theta) \sin{\theta} + p'(\theta) \cos{\theta} $$
Not all choices of the parameters produce convex curves, but $a = 2$, $b = 40$, and $k = 7$ produce a satisfactory heptagonal figure. A constant step size $h = \pi/(12 k)$ yields
Rabinowitz goes on to create a curve of constant width that is actually a polynomial of degree eight in the two variables $x$ and $y$.
Several countries mint coins shaped by curves of constant width. They are difficult to counterfeit and work perfectly well in vending machines. Here are a few.
Image credit: cp4space
Wankel engines, which incorporate a Reuleaux triangle, were invented in the early 1950s by Felix Wankel, a German engineer.
Image credit: gizmodo
Get
the MATLAB code
Published with MATLAB® R2018b
In my April 2 post, I introduced multiresolution pyramids, and I explained my dissatisfaction with the function impyramid, which (sadly) I designed. (Aside: I had... read more >>
]]>In my April 2 post, I introduced multiresolution pyramids, and I explained my dissatisfaction with the function impyramid, which (sadly) I designed. (Aside: I had that post ready to go on April 1, but I decided that maybe I should wait a day to publish it.) I followed that up on April 9 with an alternative computation method and interface for computing such a pyramid.
Today, I'll introduce a variation called the Laplacian pyramid. While the ordinary multiresolution pyramid contains a bunch of images that have been successively lowpass filtered and downsampled, the Laplacian pyramid contains a bunch of images that have essentially been bandpass filtered and downsampled. Burt and Adelson described the Laplacian pyramid as a data structure useful for image compression in "The Laplacian Pyramid as a Compact Image Code," IEEE Transactions on Communications, vol. COM-31, no. 4, April 1983, pp. 532-540.
The i-th image in the Laplacian pyramid is computed by taking the (i+1)-st image in the multiresolution pyramid, expanding it by a factor of 2, and subtracting the result from the i-th multiresolution pyramid image. The only thing to be particulary careful about is to handle the case where the level i image is not exactly twice the size of the level (i+1) image. If you compute the multiresolution pyramid the way I did last time, that can only happen between the first two levels.
Let's try it on the image I used last time.
A = imread('https://blogs.mathworks.com/steve/files/IMG_9968.jpg');
imshow(A)
First, we need to compute the multiresolution pyramid using the function I presented previously.
mrp = multiresolutionPyramid(im2double(A));
Now we follow the computational recipe that I described in words above.
lapp = cell(size(mrp)); num_levels = numel(mrp); lapp{num_levels} = mrp{num_levels}; for k = 1:(num_levels - 1) A = mrp{k}; B = imresize(mrp{k+1},2,'lanczos3'); [M,N,~] = size(A); lapp{k} = A - B(1:M,1:N,:); end lapp{end} = mrp{end};
Another function, showLaplacianPyramid (also at the end of this script), visualizes the pyramid.
showLaplacianPyramid(lapp)
Given a Laplacian pyramid, we can reconstruct the original image by reversing the recipe above.
num_levels = numel(lapp); B = lapp{end}; for k = (num_levels - 1) : -1 : 1 B = imresize(B,2,'lanczos3'); Lk = lapp{k}; [M,N,~] = size(Lk); B = B(1:M,1:N,:) + Lk; end imshow(B)
See the function reconstructFromLaplacianPyramid below.
In the Burt and Adelson paper, a key idea was to quantize the level images in the Laplacian pyramid so that they could be stored using fewer bits per pixel (on average). To simulate the effect, I'll round each pixel in the Laplacian level images (except the last one) to the nearest 0.1 (in a normalized range) and reconstruct from that.
for k = 1:(numel(lapp) - 1) lapp_quantized{k} = round(lapp{k},1); end lapp_quantized{numel(lapp)} = lapp{end}; B_coded = reconstructFromLaplacianPyramid(lapp_quantized); imshow(B_coded)
You can see the distortions resulting from this crude quantization method, but the overall image is surprisingly recognizable and even detailed considering how much information we tossed away.
Next time, I plan to discuss the application that I was originally interested when I started writing this series on multiresolution pyramids: image blending.
function lapp = laplacianPyramid(mrp) % Steve Eddins % MathWorks lapp = cell(size(mrp)); num_levels = numel(mrp); lapp{num_levels} = mrp{num_levels}; for k = 1:(num_levels - 1) A = mrp{k}; B = imresize(mrp{k+1},2,'lanczos3'); [M,N,~] = size(A); lapp{k} = A - B(1:M,1:N,:); end lapp{end} = mrp{end}; end function showLaplacianPyramid(p) % Steve Eddins % MathWorks M = size(p{1},1); N = size(p{1},2); stretch_factor = 3; for k = 1:numel(p) Mk = size(p{k},1); Nk = size(p{k},2); Mpad1 = ceil((M - Mk)/2); Mpad2 = M - Mk - Mpad1; Npad1 = ceil((N - Nk)/2); Npad2 = N - Nk - Npad1; if (k < numel(p)) pad_value = -0.1/stretch_factor; else pad_value = 0.4; end A = p{k}; A = padarray(A,[Mpad1 Npad1],pad_value,'pre'); A = padarray(A,[Mpad2 Npad2],pad_value,'post'); p{k} = A; end for k = 1:(numel(p)-1) p{k} = (stretch_factor*p{k} + 0.5); end imshow(imtile(p,'GridSize',[NaN 2],... 'BorderSize',20,'BackgroundColor',[0.3 0.3 0.3])) end function out = reconstructFromLaplacianPyramid(lapp) % Steve Eddins % MathWorks num_levels = numel(lapp); out = lapp{end}; for k = (num_levels - 1) : -1 : 1 out = imresize(out,2,'lanczos3'); g = lapp{k}; [M,N,~] = size(g); out = out(1:M,1:N,:) + g; end end
Get
the MATLAB code
Published with MATLAB® R2019a
Today, I want to cover the current state of support of Functional Mock-up Units (FMU) in Simulink. Background From the FMI standard website, FMI is: Functional Mock-up Interface... read more >>
]]>Background
From the FMI standard website, FMI is:
Functional Mock-up Interface (FMI) is a tool independent standard to support both model exchange and co-simulation of dynamic models using a combination of xml-files and compiled C-code.
This standard has been gaining popularity over the past few years, and we added support in Simulink to import and export FMUs.
Disclaimer: The FMI standard is one of many options available for co-simulation between Simulink and other tools. As with most standards, it comes with a set of constraints. If your requirements do not fit within those constraints and you want more flexibility, I recommend writing an S-Function as I described in this post: Communicating with an External Application for Co-Simulation. With an S-Function, you have full control over the co-simulation interface.
FMU Import
In R2017b, the FMU block was introduced. This block supports FMI standards 1.0 and 2.0, in both Co-Simulation mode (where the FMU contains its own local solver) and Model Exchange mode (where the FMU states are integrated by the Simulink solver).
I recommend looking at the FMU Importing section of the documentation to get started with that.
FMU Import Enhancements
In R2018a, we added two significant enhancements to the FMU block. The first one is numerical compensation.
Co-Simulation FMUs typically represent continuous phenomena, but their interface must be discrete and this can introduce numerical inaccuracies. To reduce those inaccuracies, numerical compensation can help. When a port has numerical compensation enabled, you will see the following icon next to it:
The second enhancement to the FMU block is that it can now run on different cores. As you can imagine, this can result in significant performance improvements if componentized properly.
One thing to note is that those two features also work with hand-written C-Mex S-Functions. If you want to write a co-simulation interface for a third-party tool without going through the FMU standard, keep that in mind!
Export a Model as a Tool-Coupling FMU
In R2018b, we added support in the other direction. It is now possible to export a model as a Tool-Coupling FMU and include it in other tools.
To begin, your Simulink model must be in a Simulink Project. In the Share menu, you will notice a new FMU entry:
Note that the Simulink Project should be configured to load and put on the path everything that the model needs. This is typically done through project startup tasks.
Using the Exported Tool-Coupling FMU
To use the FMU, you need a dedicated MATLAB session. For that, you have two options.
The first option is to manually start MATLAB and execute shareMATLABForFMUCoSim. When the other tool utilizing the FMU will begin executing, you should see the Simulink project and model open and start.
The second option is to start a dedicated MATLAB session from the operating system to run in the background. On Windows OS, you can execute a batch file from a DOS prompt to start as many dedicated MATLAB session as needed. See the documentation for the location and syntax of this batch file.
Debugging Tip
Before importing an FMU in Simulink, I recommend running it through the FMU Compliance Checker, to ensure that the FMU is valid.
If you have problems utilizing an FMU exported from Simulink in another tool, I recommend trying to import it first in a seperate MATLAB session using the FMU Import block. In the block, enable debugging to get as much information as possible:
If you select to send the debug log to "Display" as in the image above, the info will show up in the Simulink Diagnostic Viewer.
Now it's your turn
Are you using the FMU technology to co-simulate with different tools? Let us know which ones in the comment below.
]]>I have been a little bit slow in announcing some of the coolest new features/products in the most recent release, R2019a. Why should you even... read more >>
]]>I have been a little bit slow in announcing some of the coolest new features/products in the most recent release, R2019a. Why should you even care? What does Stateflow do? It allows you show the logic behind the work you are doing. You may say "I can already do that in MATLAB with if/else statements, switch/case statements, etc. And you can. But as you add extra conditions, the nesting of code and at least my ability to fully comprehend it can create a lot of mental overhead and burden. With state charts, you can encapsulate extra condition behavior without quite some much clutter, and yet high clarity.
You can get a quick idea from this picture, showing how to design the system of a lamp with the option to have the light blinking at different rates.
Guy beat me to the punch announcing Stateflow charts for MATLAB. Rather than replicate his wonderful post, I do want to encourage you to read about it. I also encourage you to watch a small video which, I hope, will give you some ideas.
One of the main MATLAB applications we see state charts helping with include the logic that controls Apps. I am quite sure there are others? Do have see a place in your workflow that a state chart can help with? Let me know here.
Get
the MATLAB code
Published with MATLAB® R2019a
Jiro's Pick this week is MATLAB Grader Test Generator by Robin T. Bye.MATLAB Grader is a web service product available for our academic customers. It's... read more >>
]]>Jiro's Pick this week is MATLAB Grader Test Generator by Robin T. Bye.
MATLAB Grader is a web service product available for our academic customers. It's an auto-grading system for MATLAB problems. Professors can author MATLAB problems and invite students to their courses, and students can take the course through a web browser, with immediate feedback to their answers. One of the key aspects to creating a problem in MATLAB Grader is the assessments. Assessments check whether the answers submitted by the student are correct. One of the easiest ways to do that is to check whether a particular varible equals the provided solution.
Robin's submission provides a creative way of generating assessment code. You provide the solution and learner template files, and the app automatically creates assessment code for all the appropriate variables.
I chose this entry as a Pick this week, because
However, I do want to highlight a feature in MATLAB Grader that makes variable assessment quite simple. There is a "Variable Equals Reference Solution" option where all you need to do is enter the name of the variable, and the assessment will automatically check whether the variable equals the solution. It could be a simple alternative to the code version of the assessments.
Comments
Give it a try and let us know what you think here or leave a comment for Robin.
Get
the MATLAB code
Published with MATLAB® R2018b
Connell D'Souza is back guest-blogging and tells us about object detection in MATLAB. -- A few weeks ago, I visited Florida Atlantic University’s Team Owltonomous, who compete... read more >>
]]>s = toStruct(detector); save('detectorCodegen.mat','-struct','s','Classifier','ModelName',... 'NumWeakLearners','ObjectTrainingSize','TrainingOptions')Next load the MAT-file inside the function using the coder.load function as shown below and call the constructor. You will want to declare it as persistent, so it is stored in memory and does not need to be constructed at every call to the function. Once you have modified your code you can follow the MATLAB Coder app workflow to obtain C/C++ code. Not familiar with the MATLAB Coder app? Check out this tutorial series on code generation.
function [boxes,scores ] = ACFDetector(img)
%#codegen
persistent s detector
if isempty(detector)
s = coder.load('detectorCodegen.mat');
detector = acfObjectDetector(s.Classifier,s.TrainingOptions);
end
[boxes, scores] = detect(detector,img);)
To conclude, I would encourage you to download the code and try it out. See how a few lines of MATLAB code can help you develop robust object detectors as well as convert it into C/C++ .]]>Last time, I talked about the function impyramid and how I have been dissatisfied with it. (Confession: I designed it.) Today I want to present... read more >>
]]>Last time, I talked about the function impyramid and how I have been dissatisfied with it. (Confession: I designed it.) Today I want to present an alternative approach to creating a multiresolution pyramid.
Here are some of my wishes:
To start off, then, how many levels should we compute by default? Another way to ask that question is: how small do we want to let the last level get? Should we avoid letting the images get smaller than a certain size, such as 32x32? Or should we compute the levels all the way down to a scalar?
I don't know what is best. To answer the question, I would want to experiment with practical applications of multiresolution pyramids to find a heuristic rule that works well. For now, I'll go with a lower size limit of 32x32. Let's tinker with some code based on that rule.
A = imread('https://blogs.mathworks.com/steve/files/IMG_9968.jpg');
imshow(A)
M = size(A,1); N = size(A,2); [M N]
ans = 1360 1904
lower_limit = 32;
Each level of the pyramid reduces the size by a factor of two, so the log2 function seems relevant.
log2([M N])
ans = 10.4094 10.8948
ans - log2(lower_limit)
ans = 5.4094 5.8948
If we don't divide by 2 more than the above number of times, then the smallest image size in the pyramid will be no smaller than lower_limit. Clearly, the number of size reduction steps has to be an integer.
num_levels = min(floor(log2([M N]) - log2(lower_limit)))
num_levels = 5
To handle degenerate cases smoothly, as well as to make visualizations easier, I want to include the original image as the first level in the pyramid, so ...
num_levels = num_levels + 1
num_levels = 6
Next, let's consider how to avoid odd image size dimensions when reducing each pyramid level. Our example image is 1360x1904, and if you just divide those numbers by 2 five times, you end up with [42.5 59.5]. Let's take the point of view that we want the smallest image in the pyramid to have an integer number of rows and columns. And then let's figure out how much to pad the original image so that we don't end up with any fractional rows and columns anywhere.
smallest_size = [M N] / 2^(num_levels - 1)
smallest_size = 42.5000 59.5000
smallest_size = ceil(smallest_size)
smallest_size = 43 60
padded_size = smallest_size * 2^(num_levels - 1)
padded_size = 1376 1920
I can imagine different ways to pad the original image, each of which has pros and cons. I'm inclined to do something simple, like pad to the right and bottom of the image by replicating the border pixels.
A_padded = padarray(A,padded_size - [M N],'replicate','post');
Now I need to pick a method for shrinking images by a factor of two to form each level. I propose to use imresize with the Lanczos3 interpolating kernel. (The lanczos3 function is at the bottom of this script.
figure fplot(@lanczos3,[-4 4],'LineWidth',1.5) title('Lanczos3 interpolating kernel')
You can see that this is similar to a sinc function but nonzero only in the interval $|x| \leq 3$. The kernel has reasonably good sharpness and antialiasing behavior.
Now we're ready to shrink the original image (as padded) several times to form the multiresolution pyramid.
pyramid = cell(1,num_levels); pyramid{1} = A_padded; for k = 2:num_levels pyramid{k} = imresize(pyramid{k-1},0.5,'lanczos3'); end
One final fix-up step: let's use the original (unpadded) image as level 1. One advantage of doing that is that we don't have to keep track of the original image size as a separate piece of data.
pyramid{1} = A;
The function multiresolutionPyramid, included at the bottom of this post, includes the logic and computations that I have described above. I have included another function, visualizePyramid, for visualizing the pyramid.
pyramid = multiresolutionPyramid(A); visualizePyramid(pyramid)
Next time, I expect to talk about Laplacian pyramids.
function f = lanczos3(x) % See Graphics Gems, Andrew S. Glasser (ed), Morgan Kaufman, 1990, % pp. 157-158. f = (sin(pi*x) .* sin(pi*x/3) + eps) ./ ((pi^2 * x.^2 / 3) + eps); f = f .* (abs(x) < 3); end function mrp = multiresolutionPyramid(A,num_levels) %multiresolutionPyramid(A,numlevels) % mrp = multiresolutionPyramid(A,numlevels) returns a multiresolution % pyramd from the input image, A. The output, mrp, is a 1-by-numlevels % cell array. The first element of mrp, mrp{1}, is the input image. % % If numlevels is not specified, then it is automatically computed to % keep the smallest level in the pyramid at least 32-by-32. % Steve Eddins % MathWorks A = im2double(A); M = size(A,1); N = size(A,2); if nargin < 2 lower_limit = 32; num_levels = min(floor(log2([M N]) - log2(lower_limit))) + 1; else num_levels = min(num_levels, min(floor(log2([M N]))) + 2); end mrp = cell(1,num_levels); smallest_size = [M N] / 2^(num_levels - 1); smallest_size = ceil(smallest_size); padded_size = smallest_size * 2^(num_levels - 1); Ap = padarray(A,padded_size - [M N],'replicate','post'); mrp{1} = Ap; for k = 2:num_levels mrp{k} = imresize(mrp{k-1},0.5,'lanczos3'); end mrp{1} = A; end function tiles_out = visualizePyramid(p) % Steve Eddins % MathWorks M = size(p{1},1); N = size(p{1},2); for k = 1:numel(p) Mk = size(p{k},1); Nk = size(p{k},2); Mpad1 = ceil((M - Mk)/2); Mpad2 = M - Mk - Mpad1; Npad1 = ceil((N - Nk)/2); Npad2 = N - Nk - Npad1; A = p{k}; A = padarray(A,[Mpad1 Npad1],0.5,'pre'); A = padarray(A,[Mpad2 Npad2],0.5,'post'); p{k} = A; end tiles = imtile(p,'GridSize',[NaN 2],'BorderSize',20,'BackgroundColor',[0.3 0.3 0.3]); imshow(tiles) if nargout > 0 tiles_out = tiles; end end
Get
the MATLAB code
Published with MATLAB® R2019a
Anna works in the Interdimensional Transport Group at Yoyodyne Propulsion Systems. Her team of ten engineers is using a lot of MATLAB these days, and... read more >>
]]>playerTable = readtable("names.csv")
Now call the leaderboard function.
makeLeaderboard("leaderboard.html",playerTable.ID)The result looks like this. Anna attached this code to a nightly scheduled task on her PC. Now, every day when she arrives at work, she can quickly scan for changes in the lead.
scoreTable = gatherScoreData("scores.csv",playerTable.ID)
Using this historical data, Rebecca could plot the scores over time.
[scoreMatrix,t,playerNames] = makeScoreMatrix(scoreTable,playerTable); plot(t,scoreMatrix,"LineWidth",2) legend(playerNames,"Location","northeastoutside") grid onFinally, for a fun sort of horse-race plot, she made an abstract rank plot that showed changes in position over time. You can really see Debra sweeping up the ranks from last place into the middle of the pack.
makeRankPlot(scoreMatrix,t,playerNames)
t2 = datetime(2019,3,15)
t2 = datetime 15-Mar-2019
currentLeaderTable = leaderTableAtTime(playerTable,scoreTable,t2)
This functionality let Anna fix something that had been bugging her. Some people, like Grace and Alex, had been playing Cody for a long time. It somehow didn't seem fair for other people, new to Cody, to have to compete with them on the same absolute scale. So they created a monthly competition in which everyone was ranked by how many points they had scored in the preceding month.
nDays = 30; t1 = t2 - days(nDays)
t1 = datetime 13-Feb-2019 00:00:00
dMinus30Table = leaderTableAtTime(playerTable,scoreTable,t1)
currentTable = leaderTableAtTime(playerTable,scoreTable,t2); Rank = zeros(height(playerTable),1); RankChange = zeros(size(Rank)); ScoreChange = zeros(size(Rank)); BadgeChange = zeros(size(Rank)); for i = 1:height(currentTable) Rank(i) = i; ixOld = find(dMinus30Table.Id==currentTable.Id(i)); if isempty(ixOld) RankChange(i) = NaN; ScoreChange(i) = currentTable.Score(i); BadgeChange(i) = currentTable.Badges(i); else RankChange(i) = ixOld - Rank(i); ScoreChange(i) = currentTable.Score(i) - dMinus30Table.Score(ixOld); BadgeChange(i) = currentTable.Badges(i) - dMinus30Table.Badges(ixOld); end end % Augment the current table with four new columns. currentTable = [currentTable table(Rank,RankChange,ScoreChange,BadgeChange)]; % Sort by the ScoreChange column. currentTableSorted = sortrows(currentTable,'ScoreChange','descend'); currentTableSorted(:,[1 3 7])
Now it's clear that, although Grace still has the highest score, Julia achieved the most in the last month. You can bet this came up the next time the two of them chatted next to the coffee machine.
In MATLAB R2019a, it is now possible to create standalone Stateflow charts that can be executed in MATLAB. Let's see how this work! Getting Started First, an... read more >>
]]>Getting Started
First, an important concept: A standalone Stateflow chart is a MATLAB class. The difference is that you edit it using the Stateflow graphical language instead of MATLAB code.
To get started, use the Stateflow Chart entry under the New button in the MATLAB toolstrip:
The simplest example I can think of is the following, where I increase the value of a local variable "x" every time the chart executes.
I can execute this chart by first creating a chart object obj and initializing the value of x to zero. Then I can call the chart step method as many times I want and observe how the value of x increases.
You can also add Event Inputs to charts, and they result in methods for the MATLAB class. In the following chart, I defined a RESET event and use it to reset the value of local variable x:
Designing MATLAB Apps logic in Stateflow
One of the things I like the most about standalone Stateflow Charts is that they team up very well with MATLAB Apps created using the App Designer.
Let's extend our previous example a little bit. In App Designer, I created this simple App:
My goal is that when I click the Enable button, the value displayed on TicksCount gauge will begin to increase by Increments and keep increasing every Delay. If I click the Reset button, TicksCount goes back to zero.
How does this work?
To connect the app with the Stateflow chart, they both need to know about the other one. On the app side, you can create a private property storing a handle to the chart. On the Stateflow side, you need to create a local variable that will contain a handle to the app. That way each of them will be able to call the other.
In App Designer, the code will look like the following. The startupFcn initializes the Stateflow chart named appLogicChart and passes it the handle to the app. The chart object is then stored in the app property theChart.
With that done, the buttons in the app can call events in the chart.
At the same time, the chart can access the various properties of the app through its handle. Thanks to the Stateflow animation, it becomes very convenient to debug the logic in your app:
One important thing to point out in the above chart is the usage of the after keyword. Under the hood, the chart sets up MATLAB timer to implement the temporal logic. In my opinion, this makes it the simplest way to use timers in MATLAB.
Now it's your turn
If you are interested in this new feature, I recommend going through the Execution in MATLAB section of the Stateflow documentation.
We are curious to hear how you are going to leverage standalone Stateflow charts... Let us know in the comments below!
Personally, I may never write a MATLAB class in the MATLAB Editor ever again!
]]>Greg's pick this week is slQuery by Robert Rasche. ... read more >>
]]>Greg's pick this week is slQuery by Robert Rasche.
Robert has created an impressive mechanism for finding and operating on elements of Simulink models from MATLAB scripts and functions.
The part I feel he understates in his description of the entry is the ability to find blocks based on what the blocks are connected to, not just properties of the blocks themselves.
Once you get a handle on the query syntax, it's pretty trivial to create complex queries of Simulink model blocks.
If you want to access blocks in a Simulink model, the standard APIs do enable you to locate blocks based on the properties of those blocks.
The standard API most users know about is the
If you want to search for a block based on property values, the standard API and
Find All Atomic Subsystems with Whitespace in the Name:
asbhl20_VehicleSystemsModel; blocks = slQuery('SubSystem[Name~=\w+\s+\w+, TreatAsAtomicUnit=on]'); % Replace whitespace in block names with underscore "_" names = regexprep(strtrim(blocks.Name), '\s+', '_')'; names(1:7)
ans = 7×1 cell array {'Air_Data_Computer' } {'Log_LL1_Actuator_Position_Sensors'} {'Log_LL2_Actuator_Position_Sensors'} {'Log_LU1_Actuator_Position_Sensors'} {'Log_LU2_Actuator_Position_Sensors'} {'Log_Hydraulic_System_1_Sensors' } {'Log_Hydraulic_System_2_Sensors' }
blocks = find_system(get_param(bdroot, 'Handle'), 'RegExp', 'on', ... 'BlockType', 'SubSystem', 'TreatAsAtomicUnit', 'on', ... 'Name', '\w+\s+\w+'); % Replace whitespace in block names with underscore "_" names = regexprep(strtrim(get(blocks, 'Name')), '\s+', '_'); names(1:7)
ans = 7×1 cell array {'Air_Data_Computer' } {'Log_LL1_Actuator_Position_Sensors'} {'Log_LL2_Actuator_Position_Sensors'} {'Log_LU1_Actuator_Position_Sensors'} {'Log_LU2_Actuator_Position_Sensors'} {'Log_Hydraulic_System_1_Sensors' } {'Log_Hydraulic_System_2_Sensors' }
The standard API uses the addition of functional arguements to build a query, while
The slQuery function offers a way to search for blocks based on their connections to other elements in the Simulink model. This pretty much blows my mind!
In my 20 years of using Simulink, I could have definitely used features like this on several occasions.
This is something that the standard API functions
Find Inports directly connected to a Gain block
asbhl20; r = slQuery('Inport -> Gain'); cell2table([r(1).Parent.Name; r(1).Name; r(2).Name], ... 'RowNames', {'Parent', 'Inport', 'Gain'})
ans=3×4 table Var1 Var2 Var3 Var4 __________________________ ______ ______ _________________ Parent 'Low Altitude↵Intensity' 'Hqgw' 'Hrgw' 'cascvt' Inport 'Windspeed ↵at 20ft (6m)' 'V' 'V' 'In1' Gain 'sigma_wg ' 'pi/4' 'pi/3' 'Unit Conversion'
Note that this searches currently open Simulink model by default.
Find Feedback Loops
There are more sophisticated connection searches available, including the ability to look for feedback loops.
vdp;
r = slQuery('#vdp / Integrator >> $1') ;
r.Name
ans = 2×2 cell array {'vdp'} {'vdp'} {'x1' } {'x2' }
This syntax looks for a block that is connected to itself.
Firstly, I thought this was a really creative way to attack the problems Robert was facing. He leverages the extensibility of the MATLAB Language to great effect.
In addition, this File Exchange entry is documented, and provides a number of test cases; two elements that make it easier to understand how to use the
Let us know here.
]]>Welcome again to R2019a! There’s a new release of MATLAB out right now. Last post, we covered a bunch of new 19a examples, and today's... read more >>
]]>There's a function in the Image Processing Toolbox that I'm not especially fond of: impyramid.I shouldn't tell you who designed this function, but I'll give... read more >>
]]>There's a function in the Image Processing Toolbox that I'm not especially fond of: impyramid.
I shouldn't tell you who designed this function, but I'll give you a hint: his initials are "Steve Eddins."
Years ago, we had occasional user requests for creating multiresolution image pyramids, such as Gaussian pyramids and Laplacian pyramids. I thought these requests would be easy to satisfy by impyramid, but I was wrong. I was reminded of the problems by some code written by one our Pilot engineers, Steve Kuznicki. Steve made a nice of use impyramid to implement a multiresolution image blending method, but weaknesses in the design of impyramid made some of the code awkward. Today I want to discuss those weaknesses. In a follow-up post later, I'll demonstrate some possible improvements.
I'll start by explaining multiresolution pyramids. Below an example of one. This form is sometimes called a lowpass pyramid.
The original image is shown in the upper left. The image is lowpass filtered and then subsampled by a factor of 2 in each direction to form the image in the upper right. That process is repeated several times, reaching the tiny version of the original image at the lower right.
So, I think "multiresolution pyramid" and "lowpass pyramid" are both sensible terms, but why is this frequently called a "Gaussian pyramid"? The answer comes from an implementation technique described in Burt, "Fast Filter Transforms for Image Processing," Computer Graphics and Image Processing, vol. 16, pp. 20-51, 1981. Burt described a procedure for forming a multiresolution pyramid by filtering at each step with the kernel $h_1(x)$ in Fig. 2 from the paper:
The coefficients of $h_1(x)$ are $1/4 - a/2$, 0.25, and $a$, with typical values for $a$ around 0.4.
As you successively apply this filter at each stage of a multiresolution pyramid, the overall effect becomes similar to filtering with a continuous Gaussian-shaped kernel, and this is where the name Gaussian pyramid comes from.
At the time this paper was written, computers were vastly slower than they are now, especially with floating-point computation. The floating-point convolution of a 512x512 image (considered large then, and considered quite small now) with a filter of modest size could take minutes.
That explains part of the significance of Burt's implementation method. Not only is the filter applied at each pyramid stage very small, but when $a = 0.375$, all the filter coefficients are exact binary fractions and so can be implemented by direct processor bit-shift instructions on the integer pixel values. That allowed for reasonably fast implementations on the computers of that time.
When I try to put impyramid to good use, or when I have seen other people try to use it, the following problems stand out to me:
Extra credit: Do you know what building is in the image above? If so, leave a note in the comments.
Get
the MATLAB code
Published with MATLAB® R2019a
Sedona Arizona is a perfect site for the first MathWorks excursion into lifestyle products.ContentsSedona, ArizonaMATLAB StoreBiorhythmsEnergy VorticesSchuerman MountainSedona, ArizonaAccording to Wikipedia Sedona is a city ...... read more >>
]]>Sedona Arizona is a perfect site for the first MathWorks excursion into lifestyle products.
According to Wikipedia
Sedona is a city ... in the northern Verde Valley region of the U.S. state of Arizona. As of the 2010 census, its population was 10,031. Sedona's main attraction is its array of red sandstone formations. The formations appear to glow in brilliant orange and red when illuminated by the rising or setting sun. The red rocks form a popular backdrop for many activities, ranging from spiritual pursuits to the hundreds of hiking and mountain biking trails.
Sedona is the site of the first MathWorks venture into retail marketing. Similar to the successful Apple outlets, this store features products made with MATLAB that can enhance a visitor's Sedona spiritual experience.
One popular item, intended to attract visitors to the store, is biorhythms. For only $1.99, a customer who reveals their birthday can have a printout of a personal biorhythm. As a special attraction, on a customer's birthday the biorhythm is free.
Here is an example, the biorhythm of someone whose 30th birthday is April 1, 2019. People with this birthday will have an exceptionally fortuitous 10-day period. Two and three days prior to the birthday their physical and emotional capabilities will be at their peak. Their intellectual capability will be at its 33-day maximum a week after the birthday.
biorhythm
For many visitors to the Sedona MATLAB store, the highlight will be their personal energy vortices. For $29.99, a customer who supplies their complete horological background, including the dominant zoological sign at the moment of birth, can obtain a topographic map of the Sedona area with regions of maximum personal spiritual energy highlighted. The service includes the exact longitude and latitude of these personal vortices for use in GPS devices.
Here are examples of energy vortices for certain people.
Another example is a vortex easily reached from the Schuerman Mountain trail.
The view from the Schuerman vortex.
photo credit: Mark Chisholm
Get
the MATLAB code
Published with MATLAB® R2018b
I'm pleased to announce the introduction of a new product today, the Performance Review Toolbox. It's so new, there isn't even a web page or... read more >>
]]>I'm pleased to announce the introduction of a new product today, the Performance Review Toolbox. It's so new, there isn't even a web page or marketing material for it.
Do you need to write an annual self-review? We do at MathWorks. Needless to say, if you been doing a similar job for the past few years, it can be challenging to figure out what's new to say. MATLAB can help you, using Text Analytics Toolbox, along with machine and deep learning from Statistics and Machine Learning Toolbox and Deep Learning Toolbox. Simply have available the proper document directories from your work in the previous year, as well as relevant threads in email and internal 'groups', source code control and bug/enhancement reporting systems, etc. With the Performance Review Toolbox, you can use MATLAB to mine all the sources for good information, do affinity analysis to see what the big themes have been. After generating the outline for your document, you then can modify it to your liking. With the new outline in hand, you then use MATLAB to generate a draft of your self-review.
Another part of the review process is providing peer review comments. In a similar way to writing your review, the Performance Review Toolbox can assist you by again searching the proper sources for interactions you've had in the past year working with the individual for whom you need to write a peer quote. Using sentiment analysis tools, you similarly generate an outline with the top plusses and areas for improvement. After modifying as necessary, generate the quote!
If you are a manager, I am sorry. Version 1 of the Performance Review Toolbox does not generate reviews automatically for your use for your employees. It's a much requested feature.
Early reviews of this new product are promising.
If so, please first note the post's date, then let us know here.
Get
the MATLAB code
Published with MATLAB® R2019a
Sean's pick this week is Connectionist Temporal Classification Layer by SergeyLA. ... read more >>
]]>Sean's pick this week is Connectionist Temporal Classification Layer by SergeyLA.
Last year, we introduced the ability to write your own custom deep learning layers and integrate them with trainNetwork in the Deep Learning Toolbox. Our internal deep learning discussion group was very excited last week when this was discovered on our File Exchange.
Simply create the layer and then append it to the end of the layer array making up your deep network.
ctclayer = ctcClassificationLayer("Blog Classifier", ["POTW" "Art of MATLAB" "MATLAB Community"])
ctclayer = ctcClassificationLayer with properties: Categories: ["POTW" "Art of MATLAB" "MATLAB Community"] cacheSub: [] Name: 'Blog Classifier' Classes: 'auto' Description: 'Connectionist Temporal Classification Layer' Type: ''
Give it a try and let us know what you think here or leave a comment for SergeyLA.
Get
the MATLAB code
Published with MATLAB® R2019a
I want to turn the MATLAB App I developed recently into a web app so it is accessible from a browser. It can then be... read more >>
]]>Hi Everyone! Welcome to R2019a. A new version of MATLAB is available now! I'd like to walk through a few of the new deep learning... read more >>
]]>3-D Brain Tumor Segmentation Using Deep Learning | Image-to-Image Regression* | Train a YOLO v2 Object Detector | Classify Video using Deep Learning | |||
Voice Activity Detection in Noise Using Deep Learning | Cocktail Party Source Separation Using Deep Learning Networks | Acoustic Scene Recognition Using Late Fusion | ||
Train a reinforcement learning agent to solve a grid world problem. | Train a controller to balance an inverted pendulum in MATLAB using reinforcement learning This has been described to me as "Reinforcement Learning 101", so if you're interested in this topic, start here. | Train a robot to walk in a straight-line using Simulink and reinforcement learning | ||
Waveform segmentation using Deep Learning | Modulation Classification | Texture Classification with Wavelet Scattering | ||
Radar Target Classification using Machine and Deep Learning | Radar Waveform Classification Using Deep Learning | |
While we are talking about buckets, it makes sense for me to introduce you to another type of bucket. This one contains objects and allows... read more >>
]]>It is 2019 and in this age of the cloud, there are many object storage systems available to users. In this post, I will focus on the services offered by one such storage system offered by Amazon. The Amazon S3™ (Simple Storage Service) uses the same scalable storage infrastructure that Amazon uses to run its platform.
MATLAB and Simulink developers can already use these services with our shipping R2018b/19a product as documented by leveraging the datastore function that allows easy read/write access of data stored in on S3 (among other forms of remote data).
Specialized forms of this datastore function allow users to work directly with images (ImageDatastore), files (FileDatastore), spreadsheets (SpreadsheetDatastore) or tabular text (TabularTextDatastore). Typically, once a user has configured MATLAB with the access key ID, secret access key and region, the datastore will provide users an abstraction to the data pointed at by the internationalized resource identifier (IRI).
Abstraction is nice, but developers require finer control of what their code does with data for a good reason. They require to declare and attach permissions, control the encryption of the data, define who can and cannot access the data and exert their rights to create, read, update and delete (CRUD) content. Many of these actions are required to satisfy a variety of business, legal and technical requirements far beyond that of mere analysis. Additionally, developers can extend the tooling and use it to debug their data access workflows.
At this point, with no further ado, permit me to introduce you to an open source *prototype* MATLAB client released on github.com to allow MATLAB developers to use Amazon S3. The easiest way to get started is to clone this repository and all required dependencies using:
git clone --recursive https://github.com/mathworks-ref-arch/mathworks-aws-support.git
The repository contains MATLAB code that leverages the AWS SDK for Java. This package uses certain third-party content which is licensed under separate license agreements. See the pom.xml file for third-party software downloaded at build time.
Build the underlying Java artifactsYou can build the underlying Java SDK using Maven and the process is straightforward:
$ cd matlab-aws-s3/Software/Java/
$ mvn clean package
On a successful build, a JAR archive is packaged and is made available to MATLAB by running the startup.m file
>> cd matlab-aws-s3/Software/MATLAB
>> startup
Authenticate against the S3 service
You can do this in a number of ways including the use of the Amazon CLI (which you can call directly from MATLAB), token service (STS for time-limited or multi-factor based authentication), environment variables, etc. For the purposes of demonstration, and to keep it simple I will use a static file on the MATLAB path, with credentials from the Amazon Identity and Access Management (IAM) service:
{
"aws_access_key_id": "REDACTED",
"secret_access_key" : "REDACTED",
"region" : "us-west-1"
}
Create a bucket
To create a bucket, you can use the API interface:
% Create the client
s3 = aws.s3.Client()
s3.initialize();
% Create a bucket, note AWS provides naming guidelines
bucketName = 'com-example-mybucket';
s3.createBucket(bucketName);
List existing buckets
You can list all existing buckets:
% Get a list of the buckets
bucketList = s3.listBuckets();
bucketList =
CreationDate Name Owner OwnerId
______________________________ __________________________ _______________ _____________
'Thu Mar 02 02:13:19 GMT 2018' 'com-example-mybucket' 'aws_test_dept' '[REDACTED]'
'Thu Jun 08 18:46:37 BST 2018' 'com-example-my-test-bucket' 'aws_test_dept' '[REDACTED]'
I did warn you that this post was about bucket lists!
Storing dataStoring data from MATLAB into cloud based buckets on Amazon S3 becomes simple.
% Upload a file
% Create some random data
x = rand(100,100);
% Save the data to a file
uploadfile = [tempname,'.mat'];
save(uploadfile, 'x');
% Put the .MAT file into an S3 object called 'myobjectkey' in the bucket
s3.putObject(bucketName, uploadfile, 'myobjectkey');
Fetching data
Similarly, you can pull objects down into MATLAB from S3 buckets as follows.
% Download a file
s3.getObject(bucketName,'myobjectkey','download.mat');
Clean up
You get the idea. The MATLAB interface allows you to exert control of how data is persisted on cloud object storage on Amazon S3. You data can be similarly deleted and the bucket can be cleaned up.
s3.deleteBucket(bucketName);
Control, control, control the access
With the interface, you can now exert finer control on everything from who gets to access the data and what rights they have to read/write.
% Create a canned ACL object in this case AuthenticatedRead and apply it
% CAUTION granting permissions to AuthenticatedUsers will apply the permission
% anyone with an AWS account and so this bucket will become readable to the wider Internet
myCannedACL = aws.s3.CannedAccessControlList('AuthenticatedRead');
s3.setBucketAcl(myBucket,myCannedACL);
Implications
In closing, interfaces such as the one discussed in this post, make it easy for you, the developer to leverage the promise of practically unlimited cloud-based storage to supercharge your workflows within your existing and familiar MATLAB and Simulink tools. And most importantly, none of this prevents you from using the high-level interfaces in the same code, where it is more appropriate, giving you a wider choice of approaches.
So, do you use cloud object storage? As always, we value your thoughts, feedback and comments.
]]>