MATLAB Mobile allows you to collect information from your device sensors and perform cool experiments with the acquired data. For this post, I would like to welcome Luiz Zaniolo, our development... read more >>

]]>MATLAB Mobile allows you to collect information from your device sensors and perform cool experiments with the acquired data. For this post, I would like to welcome Luiz Zaniolo, our development manager to talk about one such experiment.

While I wrote this blog post, all credit for the experiment must go to my son, Giancarlo, a Carnegie Mellon University student (and adventure sports enthusiast) who wanted to perform some tests with his BMX bicycle.

His objective: determine how much time the bike spent in the air in a jump.

His means: he used an interesting technique to attach his cell phone to the bike and turned on the accelerometer in MATLAB Mobile, started logging data, and proceed to ride the bicycle and jump over a small ramp.

The log file was automatically uploaded to MATLAB Drive after the data collection ended.

Quick primer for those who are not aware: MATLAB Mobile can acquire data from your device sensors. You can analyze the data directly in MATLAB Mobile, MATLAB Online or on a MATLAB session on your desktop. You can even log sensor data when you are offline.

To start analyzing the data, my son logged in to MATLAB Online on his laptop, loaded the .mat file and plotted the acceleration results in the X, Y, and Z axes.

load jumpKink.mat

xAcceleration = Acceleration.X;

yAcceleration = Acceleration.Y;

zAcceleration = Acceleration.Z;

rawTimestamp = Acceleration.Timestamp;

timestamp = rawTimestamp - rawTimestamp(1);

allAxis = [xAcceleration, yAcceleration, zAcceleration];

figure; plot(timestamp, allAxis)

title('X, Y, and Z acceleration values')

xlabel('Time')

ylabel('Acceleration (m/s^2)')

legend('X', 'Y', 'Z')

Since the measurement axis on a smartphone is defined as shown in the picture below, the most appropriate axis to measure gravity acceleration is Y.

Plotting the acceleration on the Y axes gives us more clarity on the 3 different states: stopped, riding, and jumping.

figure; plot(timestamp, yAcceleration)

title('Y acceleration values')

xlabel('Time')

ylabel('Acceleration (m/s^2)')

legend('Y')

By differentiating the acceleration file, he was able to identify the jerk (rate of change of acceleration), which should be small when the bike is either stopped or in the air.

difYAcceleration = diff(yAcceleration);

timestampdif = timestamp;

timestampdif(end)=[]; % remove last element to match with difYAcceleration array

figure; plot(timestampdif, difYAcceleration)

title('Differential of Y')

xlabel('Time')

ylabel('Jerk (m/s^3)')

legend('Y')

He then applied his algorithm to detect when the bicycle was in the air. The algorithm implements a low-pass filter in the differential signal by averaging the time measurement with 2 neighbors on each side and outputs an array of the current state in time.

% mode 0: stopped

% mode 1: riding

% mode 2: in air

modeArray = zeros(length(yAcceleration), 1);

filteredDifArray = zeros(length(difYAcceleration), 1);

modeArray(1) = 0;

airCounter = 0;

threshold = 16;

for i = 3 : (length(difYAcceleration) - 2)

sumOfPoints = abs(difYAcceleration(i-2)) + abs(difYAcceleration(i-1)) + ...

abs(difYAcceleration(i)) + abs(difYAcceleration(i+1)) + abs(difYAcceleration(i+2));

filteredDifArray(i) = sumOfPoints / 5;

% if it passes the threshold (moving on bumpy enough ground)

if sumOfPoints > threshold

% if in "air" for less than 0.25 secs before jump lands, read over all "air"s with 1s

if airCounter < 25

for j = i : -1 : (i - airCounter)

modeArray(j) = 1;

end

end

modeArray(i) = 1;

airCounter = 0;

elseif sumOfPoints < threshold

% if it doesnt pass the threshold (either still or in air)

if modeArray(i - 1) == 0 || length(yAcceleration) - i < 300

%if its stopped it stays stopped

modeArray(i) = 0;

%if its still for too long it counts it as stopped, reads over all "air"s with 0s

elseif airCounter >= 300

for j = i: -1: (i - airCounter)

modeArray(j) = 0;

end

else

modeArray(i) = 2;

end

airCounter = airCounter + 1;

end

end

Finally, plotting the mode array on top of the Y acceleration shows the detections of different modes: stopped, riding, and jumping.

modeArray = modeArray .* 20; % amplify to show better in graph scale

figure; plot(timestamp, yAcceleration)

hold on

plot(timestamp, modeArray, 'r')

hold off

title('Jump Detection Algorithm')

xlabel('Time')

ylabel('Acceleration (m/s^2)')

legend('Y', 'modeArray')

And since he had the mode array, he counted how many samples were reported as "in air" to display the total air time of 0.44 seconds.

numOfAirSamples = sum (modeArray == 40);

airTime = numOfAirSamples * 0.01 % the acquisition rate was 100 samples per second

Even though this is a simple example of signal processing, my son described it as something that he enjoyed doing. The intermediate plots helped him understand better what needed to be done to accomplish his task. Although if he's planning to execute more reckless jumps to improve his air time, his father needs to have a talk with him.

Have you used your phone to collect sensor data for experiments like this? If you did, we would love to learn more. Please share them with us by adding a comment below.

]]>MATLAB is good at math, of course, but it can also let you have some fun with words. Go to the Gaming > Word Games category of the File Exchange and you can find a variety of different word... read more >>

]]>MATLAB is good at math, of course, but it can also let you have some fun with words. Go to the Gaming > Word Games category of the File Exchange and you can find a variety of different word games.

I like laddergrams, and since I couldn't find any on the File Exchange, I thought I'd have some fun and write about them here. Laddergrams (also called Word Ladders) are a word game invented by Lewis Carroll in which you change one word into another by means of intermediate words that differ by exactly one character. He introduced the puzzle with this word pair: HEAD to TAIL.

So the challenge is this: how can you transform HEAD to TAIL one letter at a time? Here is his answer from 1879.

Can we write some MATLAB code that will find a solution to this problem?

This problem gives us a chance to play with the graph object in MATLAB. As is frequently the case, once you set up the problem correctly, it's a breeze to calculate laddergrams for any pair of words. We'll start by reading a list of English words into a string.

url = "https://raw.githubusercontent.com/first20hours/google-10000-english/master/google-10000-english.txt";

wordList = string(webread(url));

words = wordList.splitlines;

Extract all the words that are exactly 4 letters long.

keep = words.matches(lettersPattern(4));

words = words(keep);

numWords = length(words)

Let's alphabetize the list.

words = sort(words);

We want to build a graph that contains all these four-letter words. Each node is a word, and each edge connects two words that can be "bridged" in one laddergram step. Let's build the adjacency matrix.

Two words are connected by an edge if they differ by one and only one letter location. So HEAD and HEAL are connected. HEAD and HEED are connected. But HEAD and HERE are not, since you need to change two letters to get from one to the next.

adj = zeros(numWords);

for i = 1:numWords

for j = i:numWords

% Three letters must be exact matches

if sum(char(words(i))==char(words(j)))==3

% The matrix is symmetric (the graph is undirected), so we

% touch two locations in the adjacency matrix.

adj(i,j) = 1;

adj(j,i) = 1;

end

end

end

spy(adj)

The adjacency matrix has some fascinating structure! By marking the break between first letters, we can see what's going on a little better. We'll use the diff command to see where the first letter of each word changes.

ix = find(diff(char(words.extract(1)))~=0);

for i = 1:length(ix)

xline(ix(i))

yline(ix(i))

end

title("Word Connectivity Adjacency Plot")

Around index 800, you can see a very narrow strip that corresponds to Q. Only three 4-letter words in this dictionary start with Q: QUAD, QUIT, and QUIZ

Let's throw the alphabet on the plot's Y axis to make this more clear.

alphabet = ('a':'z')';

set(gca,YTick=ix, ...

YTickLabel=cellstr(alphabet))

Make the graph object.

g = graph(adj,words);

Calculate the distances between all the words. This is where the magic happens. This one command is incredible: effectively distances is solving every single potential word ladder. That's the beauty of tapping into the excellent libraries that are just waiting to be used in MATLAB. Any code I would come up with to solve this problem would take a long time to write and longer to run. Instead, BOOM! It's all done.

d = distances(g);

Some word pairs are relatively inaccessible, so they show up as infinitely far apart.

[word1ix,word2ix] = find(d==Inf);

Here are two words you will never be able to connect via laddergram, at least with this dictionary.

i = 10;

words([word1ix(i) word2ix(i)])

Or, as they say in Maine: You can't get there from here.

Let's zero out all those infinite edges so they don't confuse the rest of our calculations.

d(d==Inf) = 0;

And now a histogram to look at the numbers.

maxLadderLen = max(d(:))

histogram(d(:),1:maxLadderLen)

xlabel("Length of the Laddergram")

ylabel("Number of Word Pairs")

Six is the most common number of intermediate steps.

What are the longest possible word ladders?

[word1ix,word2ix] = find(d==max(d(:)));

length(word1ix)

i = 9;

p = shortestpath(g,word1ix(i),word2ix(i));

for j = 1:length(p)

fprintf("%s\n",words(p(j)))

end

There is a multi-way tie for longest laddergram (20 steps), but this champion word pair goes from TOWN to DRUM. As always, everything depends on the dictionary. A different dictionary can give vastly different results.

Finally, we can solve the problem that Lewis Carroll posed back in 1879.

p = shortestpath(g,"head","tail")'

Our words are different, but even with MATLAB on our side, we can't do better than Carroll did almost 150 years ago. But in the bargain, we've solved every single laddergram that can be represented in this dictionary.

numLaddergrams = nnz(d)/2

All 405,591 of them! I just love graph algorithms.

]]>Seasonal greetings of the Greater Solstice Metropolitan Area! As I write this, the solstitial sun sets on the shortest day of my northern hemispheric year. Winter is here. So naturally, my mind... read more >>

]]>Seasonal greetings of the Greater Solstice Metropolitan Area! As I write this, the solstitial sun sets on the shortest day of my northern hemispheric year. Winter is here. So naturally, my mind turns to cookies.

The inspiration for this winter daydream comes from some code written by Eric Ludlam. Eric, in addition to being in charge of the MATLAB graphics team, is an inveterate tinkerer. He loves making fun graphics code. You may remember some of his pumpkin-inspired creations that I described in this space last year. Or you may recall his many entries from the latest Mini Hack (and the one before that).

He's back, this time with code for seasonal cookies and snowflakes. If you want to look at his code, you can find it in his Digital Art with MATLAB repo. In fact, let's go look at it now.

We can start by cloning our own copy in MATLAB. You can do this directly from the Current Folder Browser. Select "Manage Files..." from the Source Control context menu.

Enter the Repository Path (https://github.com/zappo2/digital-art-with-matlab), and the files come right down.

Eric made some cookie code using blobby implicit surfaces as described by Jim Blinn. We can use Eric's template as a cookie-cutter (heh) to stamp out other designs. Shown below is the code from gingerbreadperson.m, only I've substituted my own design at the top: a candy cane.

% Create a gingerbread person cookie

K = [ ...

' xxx '

' xxxxx '

' xxx xxx '

' xxx xxx '

'xxx xxx '

'xxx xxx '

'xxx xxx '

' xxx '

' xxx '

' xxx '

' xxx '

' xxx '

' xxx '];

% Convert K into array of blob centers

[y,x]=find(~isspace(K));

% Scale and offset centers into 3D cookie space

C=[x*5,y*5]+5; C(:,3)=10;

% Compute a volume using a short implementation of Blinn's blobs

nx=size(K,2)*5+10; ny=size(K,1)*5+10; nz=20; % Size of volume

[y,x,z]=ndgrid(1:ny,1:nx,1:nz);

vol=zeros(ny,nx,nz);

for i=1:size(C,1)

vol=vol+exp(-.05*((C(i,1)-x).^2 + (C(i,2)-y).^2 + (C(i,3)-z).^2));

end

% Compute isosurface from the blobs

S=isosurface(vol,.3);

% Draw the isosurface using patch

newplot

patch(S,'FaceColor','#a56c3c','EdgeColor','none'); % cookie

axis equal ij off

lighting gouraud

camlight

material([.6 .9 .3 ])

It's not the most shapely candy cane, but it will do. Let's add some icing.

newplot

patch(S,'FaceColor','interp','EdgeColor','none','FaceVertexCData',S.vertices(:,3));

colormap(validatecolor({ '#a56c3c' '#f09090' }, 'multiple'));

clim([10 20]);

axis equal ij off

lighting gouraud

camlight

material([.6 .9 .3 ])

% Create a gingerbread blob

K = double(rand(10,10)>0.5);

K(K==1) = char(' ');

K(K==0) = char('*');

K = char(K);

% Convert K into array of blob centers

[y,x]=find(~isspace(K));

% Scale and offset centers into 3D cookie space

C=[x*5,y*5]+5; C(:,3)=10;

% Compute a volume using a short implementation of Blinn's blobs

nx=size(K,2)*5+10; ny=size(K,1)*5+10; nz=20; % Size of volume

[y,x,z]=ndgrid(1:ny,1:nx,1:nz);

vol=zeros(ny,nx,nz);

for i=1:size(C,1)

vol=vol+exp(-.05*((C(i,1)-x).^2 + (C(i,2)-y).^2 + (C(i,3)-z).^2));

end

% Compute isosurface from the blobs

newplot

S=isosurface(vol,.3);

patch(S,'FaceColor','interp','EdgeColor','none','FaceVertexCData',S.vertices(:,3));

colormap(validatecolor({ '#a56c3c' '#8090f0' }, 'multiple'));

clim([10 20]);

axis equal ij off

lighting gouraud

camlight

material([.6 .9 .3 ])

I like my random cookies, and I'm now inclined to try some in the kitchen.

I'll close with Eric's snowflake code. It's in a different folder in the same repo. Here's the default.

snowflake

axis off

But, just as with the cookies (and as with real-life snowflakes), we can opt for a random flake.

steps = randi(10,1,randi(8)+2)

snowflake(steps)

axis off

As the days get shorter and drearier here in New England, I get hungry for sunlight. This makes me somewhat obsessed with when the sun sets. But unlike our ancient ancestors, I don't need to worry... read more >>

]]>As the days get shorter and drearier here in New England, I get hungry for sunlight. This makes me somewhat obsessed with when the sun sets. But unlike our ancient ancestors, I don't need to worry that the sun will never return. I have something they didn't have: MATLAB. To cope with the shortening days, I can calculate exactly when the days will start getting longer. And for me, the days will start getting longer on December 10th.

You're probably aware that the shortest day is December 21st. But the earliest sunset is on December 10th (at my latitude). And since I never wake up before dawn, then the day as I experience it is already getting longer by December 11th. It's a subtle point, but it helps carry me through the twilight of the waning year (I've written about this phenomenon before).

Using Francois Beauducel's "Sunrise" contribution on the File Exchange, I can easily make a plot of the sunset time where I live (north latitude 42 degrees).

% Where: Natick, Massachusetts.

lat = 42.3;

lon = -71.4;

% When: this year.

% List all the days of the year

d = datetime(2022,1,1:365);

% SUNRISE uses the DATENUM format

[~,sset_datenum] = sunrise(lat,lon,0,[],datenum(d));

sset = datetime(sset_datenum,ConvertFrom="datenum");

t = hour(sset) + minute(sset)/60 + second(sset)/3600;

plot(d,t,LineWidth=3)

grid on

box on

ylim([15 20])

ylabel("Time of Sunset")

[~,ix] = min(t);

line(sset(ix),t(ix), ...

Marker="o", ...

MarkerSize=15, ...

LineWidth=2, ...

Color="red")

text(sset(ix),t(ix), ...

sprintf("Earliest Sunset \n%s ",sset(ix)), ...

Color="red", ...

VerticalAlignment="bottom", ...

HorizontalAlignment="right")

setTimeYTick(gca)

Note that all times are Standard Time. We're not worrying about any Daylight Saving Time nonsense. I like to call the day with the earliest sunset Crepusculus (after crepusculum, the Latin word for dusk). It's an important milestone, so it deserves a name!

Let's take that same data and use it to animate the sunset time using the face of a clock. Here we're visualizing the hour hand at the time of sunset. You can see a little asymmetry here. The days get shorter more quickly than they get longer.

For this animation, I used a File Exchange contribution of my own called Animator.

Now let's plot the span from latest to earliest sunset for several north latitudes.

clf

hold on

latList = 0:10:50;

crepusculusTimes = zeros(size(latList));

crepusculusDates = NaT(size(latList));

colorMap = flipud(parula(10));

for n = 1:length(latList)

d = datetime(2022,1,1:365);

lat = latList(n);

lon = -71;

[~,sset] = sunrise_dt(lat,lon,d);

t = hour(sset)+minute(sset)/60+second(sset)/3600;

[~,ixEarliest] = min(t);

[~,ixLatest] = max(t);

sset = sset(ixLatest:ixEarliest);

crepusculusTimes(n) = t(ixEarliest);

crepusculusDates(n) = d(ixEarliest);

plot(d,t,LineWidth=3,Color=colorMap(n,:))

grid on

hold on

box on

end

legend(string(latList + " deg"),Location="southeast")

title("Sunset Times at Various North Latitudes")

ylabel("Time of Sunset")

setTimeYTick(gca)

hold off

As expected, day length varies considerably as you get farther away from the equator.

legend off

set(findobj(gcf,"Type","line"),LineWidth=1)

h = line(crepusculusDates,crepusculusTimes,LineWidth=2,Color="red",Marker="o");

legend(h,"Crepusculus",Location="southeast")

title("Date of the Earliest Sunset Varies with Latitude")

Crepusculus depends on your latitude! The earliest sunset skews earlier in the year as you get closer to the equator.

Once again, let's display some of this information on the face of a clock. This time, instead of an animation, we'll do a static clock face where the color of the hour hand depends on the month of the year.

d = datetime(2022,6,1:214);

lat = 42.3;

lon = -71.4;

[~,sset] = sunrise_dt(lat,lon,d);

t = hour(sset)+minute(sset)/60+second(sset)/3600;

[~,ixEarliest] = min(t);

[~,ixLatest] = max(t);

d = d(ixLatest:ixEarliest);

t = t(ixLatest:ixEarliest);

sset = sset(ixLatest:ixEarliest);

clf

drawClockFace

gammaHr = pi/2 - 2*pi*mod(t,12)/12;

% colorMap = prism(7);

colorMap = get(gca,"ColorOrder");

colorIxList = [1 1 1 1 1 1 2 3 4 5 6 7];

monthList = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];

monthList = monthList(unique(month(d)));

h = zeros(12,1);

nMonths = length(unique(month(d)));

r = 0.8;

for i = 1:length(gammaHr)

colorIx = colorIxList(month(d(i)));

% colorIx = colorIxList(i);

color = colorMap(colorIx,:);

h(colorIx) = line([0 r*cos(gammaHr(i))],[0 r*sin(gammaHr(i))], ...

Color=color, ...

LineWidth=2);

end

r = 1.1;

x = r*cos(gammaHr(1));

y = r*sin(gammaHr(1));

line([0 x],[0 y],Color=0.5*[1 1 1])

sset.Format = "dd-MMM HH:mm";

text(x,y,sprintf("Latest Sunset \n%s ", string(sset(1))), ...

Color=0.5*[1 1 1], ...

VerticalAlignment="top", ...

HorizontalAlignment = "right")

x = r*cos(gammaHr(end));

y = r*sin(gammaHr(end));

line([0 x],[0 y],Color=0.5*[1 1 1])

sset.Format = "dd-MMM HH:mm";

text(x,y,sprintf(" Earliest Sunset \n %s ", string(sset(end))), ...

Color=0.5*[1 1 1], ...

VerticalAlignment="top", ...

HorizontalAlignment = "left")

axis equal

axis off

monthList = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];

monthList = monthList(unique(month(d)));

h(h==0) = [];

legend(h,monthList, ...

Location="NortheastOutside")

This graph shows roughly half the year, from the latest sunset in June to the earliest sunset in December.

Finally, here's an animation of the sunset visualization shown above as it changes with latitude. Once again, we see that equatorial days don't vary much in length.

Which would you rather have: the steady day length of the tropics, or gloriously long days of summer at the expense of short winter days?

function setTimeYTick(ax)

h = hours(get(ax,"YTick"))-hours(12);

h.Format = "hh:mm";

hStr = replace(string(h), textBoundary+"0", "") + " pm";

set(gca,YTickLabels=hStr, ...

YDir="reverse")

end

Any cricketers out there? If you like cricket and coding in MATLAB (and who doesn't?), then allow me to direct your attention to an entirely cricket-themed Cody problem group created by quizmaster... read more >>

]]>The Cody First XI – MATLAB Problems for Cricket Fans

As a fan of the New Zealand Black Caps, Matt has been keenly following the T20 World Cup going on in Australia. Unfortunately for Matt, the Black Caps were eliminated by Pakistan in the semifinals. I'm not much of a cricketer myself, but here's another result that caught my eye.

I will note that, if your name is Ned, you can't help but cheer for Netherlands during international sporting events.

But what does this have to do with Cody? Matt was inspired by the World Cup to make this latest sports-themed problem group. He was even kind enough to put me in a problem description here.

It's a nifty problem dealing with MATLAB tables. The title is a mouthful, but the function you write to solve it is whosyourbunny. *Who's your bunny?* Like I said, cricket is not my first language, so I had to look it up. A bunny is a batter who is consistently dismissed by a particular bowler. The problem description portrays me as a skilled bowler, so naturally I had to solve it right away. This let me be the first solver, bringing me, after all these years, my first Leader badge. Huzzah! (My answer has since been surpassed...)

I want to thank Matt and Ben Placek and Renee Bach for all the work they did creating problems for the recent tenth anniversary contest. You can find dozens of new and fascinating problems in these groups. The contest may be over, but these problems are still ready for you answers.

Week 1: Matrices and Arrays

Week 2: Plotting and Visualization

Week 3: Programming Constructs

... and everyone's favorite: Week 4: Are You Smarter Than a MathWorker?

But of course, if cricket is your sport, then you know where to go!

]]>Today, once again, I am delighted to introduce guest blogger Dave Bulkin. You may remember that Dave blogged in this space last year about our first Mini Hack (Mini Hack Contest Analysis). Dave is a... read more >>

]]>Today, once again, I am delighted to introduce guest blogger Dave Bulkin. You may remember that Dave blogged in this space last year about our first Mini Hack (Mini Hack Contest Analysis). Dave is a developer on the MATLAB Graphics and Charting Team. In the post below, Dave not only examines the code behind the leading entries, but he also introduces you to some new visualization techniques.

For reference, follow this link to the Mini Hack Gallery.

by Dave Bulkin

Thanks to the Mini Hack organizers and all the contributors for another great set of beautiful and inspiring visualizations! And thanks to Ned for letting me return to his blog to share some analyses about the content.

Last year’s analysis showed that the axis function was unquestionably the most popular function, the only one used in the majority of submissions. This was unsurprising: axis is a four-character “Swiss army knife” of functionality. The axis function remained on top in 2022, and still was used in most entries, but the chart below shows that trig functions made their way up in the ranks this year.

To make this chart I used one of our standalone visualizations: parallelplot. Parallel coordinates plots are often used with more than two variables but can be handy for a quick visualization of how things change in two different conditions. I used a trick to label the values: parallelplotprovides a grouping variable which is intended to visualize how groups of lines change across multiple coordinates, but I used one group for each function to serve as a label. My code to call parallelplotlooked something like this (I also tweaked the Colorproperty a bit to get distinct colors for the last 5 functions:

parallelplot(tbl, ...

CoordinateVariables = ["prob21" "prob22"], ...

GroupVariable = 'Function', ...

CoordinateTickLabels = ["2021" "2022"], ...

LineWidth = 2, ...

DataNormalization = "none");

When I looked at the Mini Hack data last year I tried to drill into all the ways that contest entries used axis, this year I thought it would be interesting to look at how the various colormaps were used. Here, I didn’t rely on static analysis to pick out function calls because colormaps can be used as a function (clr = lines(4);) or as a string (colormap('hot')), so instead I just searched the entries for all occurrences of all of our colormaps. The contains function makes short work of this kind of task. I started with a bar plot of the data but it was a little bland, so I decided to try to make a chart where each bar’s face showed the colormap:

One approach to making these bars would be to use patch, setting linearly spaced vertices along the edges of the bars and using the FaceVertexCData property to specify the color for each vertex. However, bars are rectangles, and it’s quite easy to make colorful rectangles with the image command, so I took that approach. My code looked something like this:

spacemult = 1.3; % used for adding space between the bars

for i = 1:numel(cmaps)

x = [0 mu(i)];

y = [i i] * spacemult;

n = ...; % n was normally 255, but a lower value for prism, flag, and lines

c = reshape(feval(cmaps(i), n), 1, n, 3);

offset = diff(x)/n; % An offset because image takes center coordinates

image(x + [offset -offset]/2, y, c);

rectangle('Position',[0 y(1)-.5 x(2) 1])

end

And here’s a version of the plot that looks at the change in colormap popularity across years. hsv, turbo, bone and cool were less popular, while copper, colorcube, lines and prism were more popular:

It’s all well and good to talk about which functions (and colormaps) were used the most, but if you want to have a successful Mini Hack entry, you probably want to know which functions led to the most votes. To investigate I computed the average number of votes for entries that contained each function. Because some functions were used sparsely, I limited this analysis to functions that were used in at least 20 entries, and to simplify the presentation I included both years in my analysis and didn’t try to compare. This was by no means a perfect analysis, I found that popular submissions (and their remixes) tended to dominate the scores. But if you’re looking to win in Mini Hack, you might consider making an image with some gamma random numbers, a two-dimensional inverse Fourier transform, and a pink colormap…

One of the coolest features of this year’s Mini Hack, was the ability to depend on File Exchange submissions. For my final analysis I wanted to use a File Exchange chart that uses the MATLAB ChartContainer base class. ChartContainer provides a framework for developing standalone visualizations like parallelplot above – these visualizations aren’t like traditional MATLAB graphics that can be combined in an axes, but instead are charts designed for a special purpose that works independently from other charts. You can read more about standalone visualizations in the “More About” section at the bottom of the parallelplot documentation page.

The MATLAB Charting Team has published a few example charts on File Exchange (you can find these by searching for the chartcontainer tag). One of our examples produces Euler diagrams. These charts have been controversial internally – in part because many folks call them Venn diagrams which are slightly different. However, the deeper challenge with this visualization is that proportional circular Euler diagrams with more than two categories don’t necessarily have a solution, so error (potentially qualitative error) tends to be present in these charts. Thus, we’ve puzzled about whether we should include this kind of visualization in a product where the math…works. Nonetheless we had an ambitious intern last year who implemented an algorithm published in IEEE Transactions on Visualization and Computer Graphics, and it makes for a neat chart that highlights the co-occurrence of function use in Mini Hack entries. The diagram below shows how light is often used in entries with surf, but not with scatter, and colormap is used with surf and scatter, but not so much with plot.

]]>Here in New England, autumn is in full swing. The maple leaves are shifting into their best yellows and reds. On MATLAB Central, it's contest season. We currently have not one, but two contests... read more >>

]]>

*Here's a snapshot from my stroll around the MathWorks Natick campus*

Our second MATLAB Mini Hack has been running for a week now. You may remember the first Mini Hack: you got 280 characters worth of MATLAB code to make any picture you like. It was truly remarkable to see what people could do with so little code. The second Mini Hack has the same 280 character constraint, but there's a big loophole: you can also include a call to any File Exchange entry that you like.

One of my favorite File Exchange contributions is Phase Plots of Complex Functions by Elias Wegert. I even wrote a post about it here back in 2020. Elias makes it super easy to do lovely colorful plots of complex functions. I used his code to make this entry in the Mini Hack contest.

If that looks like fun to you, you can take my code and remix it.

Now my entry is your entry. Using it as a starting point, you can change the z-domain, the complex function, or the visualization style. With Elias helping you, it's actually hard NOT to make a beautiful plot. Try it! I dare you.

Here's another example of someone using a File Exchange item in their entry. In this case, it's Lateef Adewale Kareem calling his own PythagorasTree entry. Very nice!

And switching gears here, I also want to mention our ongoing Cody contest. Cody is ten years old (he's growing up so fast!), so of course we want to celebrate that milestone with a big 10th Anniversary Contest. For this contest, the goal is to have the longest streak of solving at least one problem every day for the duration of the contest. You can solve any of the problems in Cody, but for this contest, we've created some brand new problems. This week's new puzzles have the theme of Matrices and Arrays. Can you, for example, make this arrow matrix for an arbitrarily large square matrix? Give it a try!

Happy birthday Cody!

]]>If I give you something but you never get the news, did I really give it to you? This happens all the time with MATLAB features. We hear from someone who says, "Why doesn't MATLAB have a way to do... read more >>

]]>This happens all the time with MATLAB features. We hear from someone who says, "Why doesn't MATLAB have a way to do X?" and we say something like "That feature has been shipping for two years." Sometimes this makes people happy, and sometimes it makes them very grumpy. Either way, they had to suffer through a period where they needed X and didn't have it. And that's unfortunate.

What's the solution? You can read the release notes. This page is pretty handy for showing you what's new between any two releases. MATLAB R022b just came out, and it has 112 notes associated with it. That's a lot to sift through, so you can be forgiven for not wanting to read the release notes for every version. But you might get lucky and have something like the dictionary feature catch your eye on the Release Notes page.

Community is one of the best ways to keep up with what's new and useful. My favorite way to discover new stuff is to have a well-informed friend who fills you in from time to time. We don't all have such a friend, so blogs are also good for discovery. Let Mike Croucher be your clever friend who tells you about, for example, the dictionary feature in his MATLAB blog.

An introduction to dictionaries (associative arrays) in MATLAB » The MATLAB Blog.

You'll often find discussion of new features on the blogs during "release season." For MathWorks, release season is early March (R20XXa) and early September (R20XXb).

But really, you don't always care about what's new. You care about what's new to you, even though it might be very old. This happens because you don't care about a feature until the moment you need it, and at that moment you're too busy building something. This is the teachable moment where, ideally, your friend the MATLAB expert happens to walk by and say, "Oh wow, you should totally use datetime for that."

In that spirit, I'm *not* going to tell you about new features today. I'm going to tell you about some older three-star features. What do I mean by three stars? The Michelin Guide gives stars to restaurants with this explanation.

**Michelin Stars**

1 star : A very good restaurant in its category.

2 stars : Excellent cooking, worth a detour.

3 stars : Exceptional cuisine, worth a special journey.

**Ned's Stars**

1 star. Worth knowing about. "Hmmm. Might be useful someday."

2 stars. Worth writing some code to play around with it. "That's cool!"

3 stars. Worth re-writing a lot of old code to simplify it. "Wow. Wish I had this last year."

Here are three features from recent years that were such big improvements to MATLAB that I went back and rewrote old code. It made me so happy to clean it up.

**datetime**. If you've spent ages bouncing around between datenum, datestr, and datevec, it's time to meet datetime. You'll be so much happier.**tables and timetables**. Tables are old news by now, but if you haven't started using them in your code, you're really missing out. Particularly if you deal with time series data; timetables are a delight. You can bring your tables in directly from data files with the Import Data UI. Get rid of all those fiddly sscanfs and textscans.**arguments**. Some functions just sound funny. On this basis, I always liked nargin and nargout. They remind me of Tweedledum and Tweedledee, standing guard at the entrance of a function. But they're a pain to work with, and they lead to ugly code. Use the arguments command and everyone will be better off.

Sometimes old news, when it's new to you, is the best news. What function changed your code, once you finally got around to properly learning it? And remember, since you're the kind of person who reads things on MATLAB Central, *you are somebody else's clever MATLAB friend*. What three-star function should you be telling your friends about?

Listen in as Yuki Kamatani interviews a man who built his own MRI! Hi, I'm Yuki Kamatani, an application engineer in our Osaka office. My specialty is in systems engineering and Model-Based Design... read more >>

]]>Hi, I'm Yuki Kamatani, an application engineer in our Osaka office. My specialty is in systems engineering and Model-Based Design related products in power electronics applications.

Today, I would like to introduce @yashiro_ld-san. He is running his "hobby" project to build a home-made MRI. Yashiro-san gave a presentation titled "Desktop MRI - HOME MADE MRI with MATLAB" at our community event at MATLAB Expo (Lightning Talks). The recording (in Japanese) is available on YouTube. You can also check the detail of his project on his blog page in English: Home Made MRI.

Yashiro-san and I have been "Geek Friends" on Twitter for a while now. I am delighted to have had the opportunity to interview him.

Lightning Talks are a part of MATLAB EXPO Japan where we invite users to present short sessions on exciting and fun projects with MATLAB. The presentations are full of unexpected ways of using MATLAB. We are organizing this event to foster interaction between passionate and motivated folks. (Note: You can learn more about these Lightning Talks in a previous blog post.)

It is fantastic that we live in an age where it is even possible to make MRIs at home, and I wonder what will happen in the next era. When I first saw his tweet, I was so shocked that my eyeballs popped out of my head. It makes me happy to think that we, as tool vendors, play a part in this evolution.

Q. Thank you for taking time out of your busy schedule to do this interview! I'm @ykamataniMWJ! I have known you as a geek friend on Twitter. So, I'm so DOKI☆DOKI that I get to interview you this way. (Note: DOKI☆DOKI is a Japanese onomatopoeia used when one is very excited!)

First of all, could you briefly introduce yourself and your MATLAB experience?

My name is Yashiro (@yashiro_ld), a geek who inhabits Twitter. I'm usually doing some weird(?) electronic work. I have been using MATLAB since I was in college, for about 5-6 years now.

Q. Wow! You have been using MATLAB for quite a long time. How did you start using MATLAB at the university? Was it because you were using it in class?

A. I think it all started when I used MATLAB to simulate motor control in a university lab.

Q. I see! So what is your favorite Toolbox that you have been using for a long time?

A. Optimization Toolbox, because I like to optimize.

Q. I totally agree! I have already bought the books you kindly recommended to me.

Q. I know you have been asked this question countless times... but I will venture to ask it. What made you decide to build your own MRI this time?

A. I thought it would be fun and interesting to make an MRI.

*Through various adjustments, the image resolution and signal-to-noise ratio have improved dramatically. Currently, it is limited to 2D imaging. We will continue to improve it so that 3D scanning can be performed.*

Q. I think it is the coolest thing that you came to this challenge with the motivation of "fun and interesting to make an MRI." Do you have any episode or story that made you think that manufacturing is fun in this way?

A. I like to see phenomena that we cannot usually see... such as rainbows, clouds of unusual shapes, and lightning. I love creating situations where my product allows us to see things we usually wouldn't be able to see! I think my earliest pleasant memory of making things was making paper airplanes and flying them into the sky as a child.

Q. I see! You often go out to take pictures of the waves, don't you? These photos seems to be strongly related to your motivation. On a different note, what motivated you to participate in the MATLAB EXPO Lightning Talk?

A. I saw about MATLAB EXPO and Lighting Talk on Twitter and thought it looked fun, and I was invited by @michio_MWJ and @griffin921.

Q. You used MATLAB to design gradient coils in your presentation. Where did you find MATLAB's features helpful in this process?

A. In all seriousness, the ability to save 2D graphs as BMPs was beneficial. I was able to spit out the gradient coil pattern information as an image in BMP format and import it into my printed circuit board design software extremely smoothly.

I wrote the electromagnetic field calculation code by myself in MATLAB and confirmed the linearity.

Q. You have received replies from all over the world to your Twitter posts about the process of creating your work, haven't you?

Yes, that's right. I was very impressed by the various insights and advice given by the researchers on the causes of problems when the NMR signal had not yet been seen. I enjoyed feeling their willingness to solve problems so strongly.

Q. I would be very proud of the results obtained in MATLAB that helped people worldwide understand your work's excellence. I see that you made full use of the various functions of MATLAB this time; do you have any tips for learning MATLAB?

A. First, I would like to look at the official documentation.

Q. If there is anything you would like to see in MATLAB in the future, please let me know!

A. Further performance improvement, nothing else to say.

Q. I'll do my best to listen to your feedback and incorporate it into the product in terms of calculation speed and functionality enhancements! Thank you for your time today!

Thank you, Yashiro-san, for taking time out of your busy schedule to answer our interview. Please keep in touch with us on Twitter!

This blog post began its life as a Live Script in MATLAB. I could have started typing into WordPress, but then I wouldn't have been able to do this. Stand back... m =... read more >>

]]>This blog post began its life as a Live Script in MATLAB. I could have started typing into WordPress, but then I wouldn't have been able to do this.

Stand back...

m = linspace(-3*pi,3*pi,400);

[x,y] = meshgrid(m);

s = sin(x).*sin(y).*log(abs(x)).*log(abs(y));

imagesc(s)

colormap(colorcube)

axis equal off

Yowza!

That's a lot of popcorn for not very much code. What on earth is going on here? Much of the drama comes from the wildly varying colormap. Let's look at this surface from the side.

surf(x,y,s)

shading flat

colorbar

Let's strip away the color to get a better picture. What is the underlying shape?

surf(x,y,s)

colormap([0.5 0.75 0.4])

axis off; shading flat; material dull

set(gca, DataAspectRatio=[1 1 1.5])

light(Position=[10 1 10])

view([-20 30])

We can decompose it still further to see that there's a sort of egg carton texture being multiplied by a four-petal folded shape. We are conveniently glossing over some infinities along the axes.

s1 = sin(x).*sin(y);

s2 = log(abs(x)).*log(abs(y));

cla

surface(x,y,s1)

surface(x,y,s2/5+7)

axis off; shading flat; material dull

set(gca, DataAspectRatio=[1 1 0.75])

light(Position=[10 1 10])

view([-20 20])

It's fun dissecting this image in a Live Script. But that's not what I'm here to talk about today. What I want to talk about is this: I'm typing this in the MATLAB Editor and you're reading it in WordPress. How did that happen?

I'm sure you can imagine various tedious ways to move a Live Script onto a blogging platform. It would involve lots of copying and pasting bits of text and screenshotting individual images. But what if I told you it was super easy and only took a few seconds?

Okay, let me less hypothetical: I AM telling you it was super easy and only took a few seconds. And you can do it too, with the help of the new, free WordPress Publishing Tool available right now on the File Exchange and GitHub. And since I like MATLAB scripts and blogging, this makes me very happy. The tool was created by MathWorks developer Cheng Chen, and I've been using early versions of it for a while. One example is the post in which I announced the Mini Hack contest. Given all the MATLAB calculations in there, it would have been difficult to create any other way. But this way it's a breeze.

The easiest way to get started with the Publishing Tool is to go to the Add-Ons Explorer in MATLAB. Search for "WordPress" and add the file. Once you've got everything installed (there's a plugin on the WordPress side and an app on the MATLAB side), run the MATLAB app. After you've provided some details about your blog, just press the big "Publish" button and you're on your way.

I would provide a link to the resulting article, but you're reading it right now!

Today's starting image, by the way, was adapted from Sumihiro's Symmetry entry in the Mini-Hack contest that we ran last fall. That entry was inspirational, getting remixed for a record total of 32 times! Not to mention the fact that I am further remixing it right here. Thanks Sumihiro!

And if you create your own blog post using this tool, please include a link to it in the comments below!

]]>