Sean‘s pick this week is xlswritefig by Michelle Hirsch. One of my colleagues approached me earlier this week and asked me to help her with an Excel report that I’d created a few months... read more >>

]]>Sean‘s pick this week is `xlswritefig` by Michelle Hirsch.

One of my colleagues approached me earlier this week and asked me to help her with an Excel report that I’d created a few

months back. When I first created this report, I just did it manually thinking it was a one time thing. But, she wanted

to create the same report many times.

My first question was: Does it have to be Excel or could I create Word or PowerPoint reports instead? I didn’t know her end

goal for the reports so figured it would be easier to automate reporting for those formats with MATLAB Report Generator. However, Excel was a requirement.

There were some data from a table and a few figures that needed to be written and fortunately no other formatting, e.g.

conditional formatting. The table was easy; a simple call to `writetable` sufficed.

But how to export a figure? I didn’t want to deal with the Excel API myself, so I went to the File Exchange and searched

for “figure to Excel”. There were a few results, but Michelle’s `xlswritefig` seemed to have the most options and it worked on first try!

Here’s some random data for next 24 hours.

nexthour = dateshift(datetime('now'), 'end', 'hour'); Time = (nexthour:hours(1):(datetime('now')+hours(24))).'; Data = cumsum(rand(size(Time)) - 0.2);

Plot the data. **Note** that the convenience functions `xticks` and `xtickangle` along with many others are new in R2016b!

plot(Time, Data) xticks(Time(1:3:end)) xtickangle(-45) xlabel('Next 24 Hours') ylabel('Randomness') title('A Plot')

Write to Excel.

writetable(table(Time, Data), 'Results.xlsx', 'WriteVariableNames', true) xlswritefig(gcf, 'Results.xlsx', 'Sheet1', 'D2')

Does creating formatted reports from MATLAB interest you? If so, what would you like to do?

Give it a try and let us know what you think here or leave a comment for Michelle.

Published with MATLAB® R2016b

]]>Brett's Pick this week is blackjack, by Cleve Moler.Last night, while preparing for a seminar on machine learning I found myself with a lot of time to wait while a training algorithm ran. I was trying to create a classifier to differentiate images from 101 different categories, and things were... read more >>

]]>Brett's Pick this week is `blackjack`, by Cleve Moler.

Last night, while preparing for a seminar on machine learning I found myself with a lot of time to wait while a training algorithm ran. I was trying to create a classifier to differentiate images from 101 different categories, and things were taking a very long time.

A bit bored, I started browsing the File Exchange, and I came across a blackjack implementation by MathWorks's chief mathematician, chairman, and cofounder Cleve Moler. Intrigued, I downloaded it and spent the next hour happily playing cards while my computer churned away in the background.

The first thing I noticed when I ran Cleve's code was that, while it ran without errors, my Command Window was filled with red warnings that indicated that the 'symbol' font is no longer supported--as noted by user Bill R in 2015. (Cleve first submitted the file back in 2004.) The cards were readable, and they were properly colored, but the representations of the suits were awry. And though suits are irrelevant, the warning was annoying. Instead of suppressing the warning, I thought I'd take a quick stab at fixing it.

It took me a few seconds to find the offending line in Cleve's code:

text(x,y+.025,char(166+s),'fontname','symbol','fontsize',fs,'color',redblack)

...and to replace it with a simple indexing call to work around the issue:

charInd = [67,68,72,83]; text(x,y+0.025,char(charInd(s)),'fontsize',fs,'color',redblack)

In short order, I was playing again, this time with no warnings. (The replacement of the symbols with letters didn't bother me at all, and certainly didn't affect the game.)

Cleve's commentary in the file is also interesting; he provides some background information on the game, and a rudimentary approach to maximizing your likelihood of winning. (Or rather, to minimize your loss--without "counting strategies," the game is always slightly skewed in favor of the dealer, no matter how well you play--assuming you're not counting cards. And counting cards just doesn't work when a random number generator is dealing from a "continuous shuffling machine"!)

Armed with Cleve's strategy ("You stand on any total over 11 when the dealer is showing a six or less. Split aces and split 8's. Do not split anything else. Double down with 11, or with 10 if the dealer is showing a six or less."), I played 35 hands...and ended up $20 in the hole! If only there had been someone bringing me free drinks while I played, the experience would have been complete!

As it turns out, Cleve has blogged about blackjack before. The article makes for an interesting read--highly recommended. Among other things, I learned that, with a "basic strategy, the house advantage is only about one half of one percent of the original bet." (The article provides some more depth on strategy, and has some nice references.)

To test that "1/2-percent" idea, I turned to Cleve's companion code, `blackjacksim`, which provides a cummulative sum of *n* simulated runs of well-played blackjack hands. But instead of just simulating a million serial hands (which I did):

s = blackjacksim(1e6); s(end)= -32025

(meaning that even if I played well, after a million hands I would be $32,000 in the hole!)...

I also simulated a million single hands, and looked at the distribution of 1-hand results (and the expected value of a single hand):

sv = zeros(1e6,1); for ii = 1:1e6 sv(ii) = blackjacksim(1); end mean(sv)

ans = -0.01606

(Pretty close to -1.5%!)

histogram(sv,9)

Thanks, Cleve. That was fun!

As always, I welcome your thoughts and comments.

Get
the MATLAB code

Published with MATLAB® R2016b

Sean's pick this week is Data Acquisition Tool by Isaac Noh. Data Acquisition Hardware Have you ever wanted to bring data directly from hardware into MATLAB or control... read more >>

]]>Sean's pick this week is Data Acquisition Tool by Isaac Noh.

Have you ever wanted to bring data directly from hardware into MATLAB or control something via a data acquisition board?

Working with data acquisition hardware was my very first project in MATLAB back in the winter of 2008. I had a miniature load frame, transparent to x-rays, for applying a load to a concrete cylinder. There were three sensor inputs: two displacements, and force, and one output: a voltage to a piezoelectric actuator that applied a force. Here's a figure from my thesis:

I built a user interface in GUIDE to allow me to apply the load while recording and plotting the signals. To complicate matters, the session based interface for the Data Acquisition Toolbox didn't exist yet, so I was also doing everything with timers on my own.

I can only imagine how much easier it would've been with this app. I no longer have access to the load frame, so instead here's an example getting data from an ADALM1000, a low cost data acquisition device.

Let's control it with the app. First, I'll just get connected and pull some data from the attached RC circuit. Note I previously had to install the hardware support package for this board.

Seems to work, great!

Now I want to output some data to it. There are two channels, the first will be a sine wave and the second a cosine wave. The board can take 0-5V so add 1 to the waves keep them positive.

```
t = linspace(0,8*pi,100000)';
x = [sin(t) cos(t)]+1; %
```

In order to get them into the output, we simply pick the variable:

And then run the session:

From here, the data can be exported or equivalent code can be generated from the file menu to automate this acquisition session.

My only point of feedback is that error messages are not all exposed via dialogs. For example, the first time I selected
*x* with the range -1:1, it errored at the command line with a useful message that I didn't see because the app was maximized.

Going back to my use case in college, I was trying to control load, with displacement so that the loading rate would be roughly linear. To do this, I ran a bunch of experiments and fit an equation to the load v. displacement curve for many cylinders. At the time, I knew nothing about Simulink or how it could help me. If challenged with the same task today, I would likely use the data acquisition blocks in Simulink R2016b to control the actuator. This would allow me to then use the PID block and its tuning capabilities to accomplish what I was doing much more quickly.

For nostalgia's sake, I put together a quick a model of the system.

Do you work with data acquisition hardware? Give it a try and let us know what you think here or leave a comment for Isaac.

Get
the MATLAB code

Published with MATLAB® R2016b

Jiro's pick this week is Music Visualizer by NathanM.

A fun, cool entry for this week. It's like I can * feel* the music!

This application post-processes the audio data, so the first time you select a music file, it takes a while to process. However, it stores the processed information in a MAT file so that it can be loaded the second time. Nathan uses `audioplayer` to play the music and the Timer functionality of `audioplayer` to synchronize the visual with the music.

For people analyzing audio data and developing audio processing algorithms, you may be interested in taking a look at the Audio System Toolbox. It provides various "algorithms and tools for the design, simulation, and desktop prototyping of audio processing systems," including streaming analysis of signals.

**Comments**

Give this a try and let us know what you think here or leave a comment for Nathan.

Get
the MATLAB code

Published with MATLAB® R2016b

Will's pick this week is Sunrise Sunset by Meysam Mahooti. Ever wonder when the sun is going to set for an event you're planning in the future? Ever wonder when the moon is going to appear above the horizon in the year 2037? Well if so, this is the exchange contribution... read more >>

]]>Ever wonder when the sun is going to set for an event you're planning in the future? Ever wonder when the moon is going to appear above the horizon in the year 2037? Well if so, this is the exchange contribution for you. Meysam predicts the altitude of the sun and moon for a particular point on the Earth's surface. Given a user-supplied date, the code identifies the time of day for sunrise, sunset, dawn, dusk, moon rise and moon set. Here is my the output for yesterday in my home of Columbia, Maryland.

How accurate is the algorithm? It must be pretty good because I found the answer to only be off by a minute for sunrise and sunset when I compared to a weather website. But how will it fare for a future prediction? That depends on the quality of the estimate of the sun and moon's position. The subroutines, SunPos.m and MoonPos.m include perturbation effects of other gravitational bodies, which would be essential for the estimates to remain accurate over a wide range of dates. I had the code estimate times six months from now; sunrise was the same time as the weather site, and sunrise was off by 3 minutes. Not too bad.

A couple things would make this contribution even stronger. First, I would make the main file a function rather than a script so that users can supply different arguments more easily. Second, I'd add more documentation to SunPos and MoonPos so that we could have better insight into the calculations. But still a great contribution...fun and easy to operate.

Let us know what you think here or leave a comment for Meysam.

]]>

Greg's pick this week is Unit Testing C Code using MATLAB and MATLAB Coder by Bill Chou. In general I try to pick entries developed by those outside MathWorks, but... read more >>

]]>Greg's pick this week is Unit Testing C Code using MATLAB and MATLAB Coder by Bill Chou.

In general I try to pick entries developed by those outside MathWorks, but Bill has provided a nice demonstration that combines two topics I'm passionate about: formalize testing and code generation.

Using unit testing in conjunction with MATLAB Coder enables three capabilities:

I recommend taking a look at Bill's videos that go along with this entry.

Fundamentally, a unit test determines if a single feature of software produces expected results under specific conditions. The theory is, by keeping the tests "small" and specific, it is easier to develop and maintain the software and tests.

The primary benefit of having tests is it helps determine if a design meets its requirements. This could apply to the initial design of the software, or when you decide to make changes to the software.

There are all sorts of additional philosophies and techniques that can apply unit testing such as Behavior Driven Development (BDD). I won't get into that here, sufficed to say that how you use unit tests will inform how you write them.

More specifically, there is a unit testing framework available in MATLAB. It is based on the xUnit framework. For those of you who might be stuck on older versions of MATLAB, it's worth checking out this File Exchange entry.

The thing I like about using this the Unit Test framework in MATLAB is it provides a consistent means of defining tests, as well as a number of tools and functions to automate test execution. It also provides a number of levels of sophistication, so if you're not into writing classes and methods to exercise your code, you can use simple scripts or functions instead.

For more about using this framework, I suggest checking out Andy's blog here.

It seems unnecessary and possibly just using a tool because you can.

Well use the right tool for the job. If you want your tests to leverage other MATLAB features that aren't readily available in the language you're using (plotting, filtering, data management), then it may very well make sense to develop your test suite in MATLAB.

In the videos I linked above, Bill does a nice job of going through how to apply the unit tests to the C-code testing process. However, there is an additional benefit for C-code generation from MATLAB that Bill doesn't address directly in the videos for this example.

If you look at the second step of the MATLAB Coder app called "Define Input Types" you will notice that `run_unit_tests` appears in the dialog to "Automatically define input types".

By executing the code found in this dialog, MATLAB Coder can determine what datatype is being used on the inputs to the function for which you are generating code, and apply the appropriate constraints.

In this case you will see that the `addOne` function has an input variable `x` which is a scalar ( 1 x 1) of type `double`.

An example of how to use this feature can be viewed at minute 2:30 of the video here.

Type definition of the inputs is required because C-code is a statically typed language, while MATLAB is a dynamically typed language. (Check out this discussion for more detail about how these type systems differ)

When the unit tests fail, you actually have to look at the test result summary to determine if there was a failure.

To make it more prominent when there is a failure, I recommend throwing an error or assertion if there are any test failures.
I changed `run_unit_tests.m` to the following:

results = runtests( pwd ); if any([results.Failed]) error('Unit test failure'); end

That way, it becomes very obvious that there is an issue to be addressed.

Let us know here.

Get
the MATLAB code

Published with MATLAB® 9.0

Jiro's pick this week is "Command-line peak fitter for time-series signals" by Tom O'Haver.Continuing with the celebration of MATLAB Central's 15th birthday and previous week's blog post by Sean, I'd like to focus on all of the great interactions people have had through the File Exchange entries. Although, you may... read more >>

]]>Jiro's pick this week is "Command-line peak fitter for time-series signals" by Tom O'Haver.

Continuing with the celebration of MATLAB Central's 15th birthday and previous week's blog post by Sean, I'd like to focus on all of the great interactions people have had through the File Exchange entries. Although, you may not think of the File Exchange as the next big social network, people have collaborated and exchanged conversations through the comments and rating sections of the entries. When I see a File Exchange entry with a lot of comments, I tend to think that the file is getting a lot of interest from other users. If I also see a lot of responses from the author of the file, that means that the author is actively involved with improving and helping people use the file. If there are a lot of updates to the entry, that also means that the author is actively maintaining the file.

So, I wanted to see which files had the most interactions amongst the author and the users. *Disclaimer: Not all of the metrics used here are purely quantitative. I've introduced some qualitative fudge factors.*

**The Data**

I gathered my data the brute-force way, of course using MATLAB. I went through all possible File Exchange IDs and scraped each webpage for comments and updates.

```
load FEX
```

Here's what the first few entries look like.

FEX(1:5,:)

ans = Name FEXID Author Comments Updates _________________________ _____ ____________________ ___________ ___________ 'central_diff.m' 12 'Robert Canfield' [3x4 table] [5x3 table] 'interpsinc.m' 13 'Michael Minardi' [1x4 table] [1x3 table] 'Polybase' 15 'Giampiero Campa' [8x4 table] [7x3 table] 'Toolbox BOD Version 2.8' 16 'Gert-Helge Geitner' [1x4 table] [7x3 table] 'connectnames.m' 17 'Douglas Harriman' [1x4 table] [0x3 table]

Here are the comments from the first entry (central_diff.m, which was Picked a couple of weeks ago).

FEX.Comments{1}

ans = Date Name Comment Rating __________ ___________________ _____________________________________________________________________ ______ 2004-09-16 'godlove njie teku' ' ' 4 2006-08-09 'Shyang-Wen Tseng' '<p>This is a very good and usefull add-on function. Thank you.</p>' 4 2007-08-06 'Alvaro Valcarce' '<p>I think that line 98 should be (notice the "=" sign)</p>…' 4

And the updates for that entry.

FEX.Updates{1}

ans = Date Version Description __________ _______ __________________________________________________________________________ NaT '' '<p>update description</p>' NaT '' '<p>description</p>' NaT '' '<p>updating description</p>' 2001-08-21 '' '<p>updating</p>' 2015-10-01 '2.0' '<p>Second-order accurate forward and backward difference formulae are u…'

**The Metric**

To help me find the entries with the most "interactions", I first calculated the number of comments and updates from the data.

FEX.NumComments = cellfun(@height, FEX.Comments); FEX.NumUpdates = cellfun(@height, FEX.Updates);

Next, I also wanted to know of all the comments for each entry, how many were by the author of the entry.

```
FEX.NumAuthorComments = cellfun(@(a,c) nnz(strcmp(a,c.Name)), ...
FEX.Author, FEX.Comments);
FEX.NumUserComments = FEX.NumComments - FEX.NumAuthorComments;
```

**Most Comments**

Let's see which entry had the most comments.

FEX = sortrows(FEX,'NumComments','descend'); barh(FEX.NumComments(10:-1:1)) title('Number of Comments') % Truncate the file names to the first 20 characters (for labeling) fexNames = cellfun(@(x) x(1:min(20,length(x))),FEX.Name(10:-1:1),'UniformOutput',false); % Axes properties ax = gca; ax.YLim = [0 11]; ax.YTickLabel = fexNames; ax.TickLabelInterpreter = 'none'; ax.YTickLabelRotation = 30;

Not surprisingly, `export_fig`.

**Most Updates**

How about most number of updates?

FEX = sortrows(FEX,'NumUpdates','descend'); barh(FEX.NumUpdates(10:-1:1)) title('Number of Updates') % Truncate the file names to the first 20 characters (for labeling) fexNames = cellfun(@(x) x(1:min(20,length(x))),FEX.Name(10:-1:1),'UniformOutput',false); % Axes properties ax = gca; ax.YLim = [0 11]; ax.YTickLabel = fexNames; ax.TickLabelInterpreter = 'none'; ax.YTickLabelRotation = 30;

"DICOM to NIfTI converter" just beats `export_fig`.

**Highest percentage of comments by the original author**

One way to see how much the original author was involved with the user comments is to look at the percentage of author comments. (Yes, an author can be heavily involved without actually responding to comments on the File Exchange. He/she can choose to respond via email or simply update files.) To account for bias towards low number of comments, I have included an arbitrary qualification cutoff of 20 comments.

FEX.AuthorCommentRatio = FEX.NumAuthorComments ./ FEX.NumComments; % Fix 0/0 (-> NaN) to 0 FEX.AuthorCommentRatio(isnan(FEX.AuthorCommentRatio)) = 0; % Only look at entries with 20 or more comments FEX = FEX(FEX.NumComments >= 20,:); FEX = sortrows(FEX,'AuthorCommentRatio','descend'); FEX(1:5,{'Name','Author','NumComments','NumAuthorComments','NumUpdates'})

ans = Name Author NumComments NumAuthorComments NumUpdates ___________________________________ _________________________ ___________ _________________ __________ 'ipf(arg1,arg2,arg3,arg4)' 'Tom O'Haver' 23 14 39 'nth_element' 'Peter Li' 26 14 7 'Tree Controls for User Interfaces' 'Robyn Jackey' 29 15 6 'Wavelet Based Image Segmentation' 'Ashutosh Kumar Upadhyay' 23 11 16 'iPeak' 'Tom O'Haver' 36 17 30

Great job folks!

Let me add another arbitrary qualification cutoff of 10 minimum updates.

FEX = FEX(FEX.NumUpdates >= 10,:); FEX(1:5,{'Name','Author','NumComments','NumAuthorComments','NumUpdates'})

ans = Name Author NumComments NumAuthorComments NumUpdates __________________________________________________ _________________________ ___________ _________________ __________ 'ipf(arg1,arg2,arg3,arg4)' 'Tom O'Haver' 23 14 39 'Wavelet Based Image Segmentation' 'Ashutosh Kumar Upadhyay' 23 11 16 'iPeak' 'Tom O'Haver' 36 17 30 'Command-line peak fitter for time-series signals' 'Tom O'Haver' 120 54 41 'Fast Bilateral Filter' 'Kunal Chaudhury' 20 9 14

Wow, Tom is up there 3 times!! I'm a little intrigued by the 4th one, which has 120 comments with 41 updates. Let's take a closer look at the timings of those comments and updates.

% Process the 4th entry % Break up the comments into user comments and author comments authorCommentID = strcmp(FEX.Author{4},FEX.Comments{4}.Name); userComments = FEX.Comments{4}(~authorCommentID,:); authorComments = FEX.Comments{4}(authorCommentID,:); % Create plot h1 = scatter(datenum(userComments.Date),ones(1,height(userComments)),... 'MarkerFaceColor','b','MarkerEdgeColor','none','MarkerFaceAlpha',0.25); hold on h2 = scatter(datenum(authorComments.Date),1.5*ones(1,height(authorComments)),... 'MarkerFaceColor','r','MarkerEdgeColor','none','MarkerFaceAlpha',0.25); h3 = plot([FEX.Updates{4}.Date FEX.Updates{4}.Date]',... repmat([0;0.5],1,height(FEX.Updates{4})),'Color',[.3 .7 .3],... 'DatetimeTickFormat','uuuu'); hold off % Axis properties ax = gca; ax.YLim = [0 2]; ax.YTick = [1 1.5]; ax.YTickLabel = {'Users','Author'}; ax.YTickLabelRotation = 60; ax.YGrid = 'on'; title({FEX.Name{plotID},FEX.Author{plotID}}) ylabel('Comments') xlabel('Date') legend([h1;h2;h3(1)],'User Comments','Author Comments','Updates')

We can see that there is a nice balance of comments from users and Tom. The updates seem to be coming in at a nice regular interval, with updates happening recently. This is a sign that Tom has been heavily involved with interacting with users and keeping the file up-to-date.

Thank you, Tom, for being a great citizen of MATLAB Central and the File Exchange! You are what makes this community thrive.

**Comments**

Give this a try and let us know what you think here or leave a comment for Tom.

Get
the MATLAB code

Published with MATLAB® R2016a

Sean's going to take this week to celebrate the top files and authors of the File Exchange. As you may know by now, MATLAB Central is celebrating its 15th birthday.... read more >>

]]>Sean's going to take this week to celebrate the top files and authors of the File Exchange.

As you may know by now, MATLAB Central is celebrating its 15th birthday. Let's start by making it a File Exchange based birthday cake!

HappyBirthday({'MATLAB' 'Central'}, 15)

I figured an interesting thing to look at would be the top files of all time and the distribution downloads based on the total number of downloads for each file.

T = readtable('fx_downloads.xlsx'); T = sortrows(T,'total_downloads','descend');

And the 15 most downloaded files are:

barh(T.total_downloads(1:15)); ax = gca; ax.YTickLabel = T.title(1:15); ax.YDir = 'reverse'; ax.XAxis.Exponent = 0; ax.YAxis.TickLabelInterpreter = 'none'; xlabel('Total Downloads') title('Top 15 Files')

It's not a surprise to me at all to see `export_fig` at the top. We'll dig into it a bit more later. There are also three Arduino support packages up there. This isn't too
surprising either given the popularity of Arduinos in recent years.

What about the distribution in number of downloads of all of the files? Let's look at a histogram of the number of files binned by number of downloads. Note, the log scale.

histogram(T.total_downloads, [logspace(0,5,30) inf]) set(gca, 'XScale', 'log') xlabel('Total Downloads') ylabel('Number of Files') title('Download Distribution')

So which authors have the most files and downloads?

Sum the total number of downloads grouping by author.

Author = varfun(@sum,T,'GroupingVariables','Creators_name','InputVariables','total_downloads'); summary(Author)

Variables: Creators_name: 10468x1 cell string GroupCount: 10468x1 double Values: min 1 median 1 max 189 sum_total_downloads: 10468x1 double Values: min 1 median 1154 max 6.9059e+05

So it looks like there are 10468 unique authors. Most people submit only one file and one person has submitted 189 files. Who's that?

disp(Author(Author.GroupCount == 189,:))

Creators_name GroupCount sum_total_downloads ________________________ __________ ___________________ 'Antonio Trujillo-Ortiz' 189 3.7709e+05

What does the distribution of submitted files per author look like?

histogram(Author.GroupCount) set(gca,'XScale','log') axis tight xlabel('Number of Files') ylabel('Number of Authors') title('Number of Files per Author')

What about the most downloaded author?

Author = sortrows(Author,'sum_total_downloads','descend'); barh(Author.sum_total_downloads(1:15)); ax = gca; ax.YTickLabel = Author.Creators_name(1:15); ax.YDir = 'reverse'; ax.XAxis.Exponent = 0; ax.YAxis.TickLabelInterpreter = 'none'; xlabel('Total Downloads') title('Top 15 Authors')

So what about `export_fig`? It used to belong to Oliver Woodford, the original author. In August 2015, Yair Altman took over maintenance and ownership
of it. It's only fair that we give Oliver credit for the years he owned it.

I have another file that has export_fig's history. Read it in convert the date to datetime for logical indexing and plotting. The original format was 'yyyyMmm', e.g. 2016M07 for July, 2016.

HistoryExportFig = readtable('monthly-export_fig_Downloads.xlsx'); HistoryExportFig.MonthName_Download = datetime(HistoryExportFig.MonthName_Download,'InputFormat','yyyy''M''MM'); summary(HistoryExportFig)

Variables: MonthName_Download: 88x1 datetime Description: Original column heading: 'Month Name - Download' Values: min 01-Apr-2009 median 16-Nov-2012 max 01-Jul-2016 SourceFileId: 88x1 double Description: Original column heading: 'Source File Id' Values: min 23629 median 23629 max 23629 FileDownloadCount: 88x1 double Description: Original column heading: 'File Download Count' Values: min 555 median 2163.5 max 4082

How has `export_fig` been used with time?

plot(HistoryExportFig.MonthName_Download, HistoryExportFig.FileDownloadCount) Aug15 = datetime(2015,8,0); hold on h = plot([Aug15 Aug15],ylim); legend(h,'Yair Takes Over','location','northwest') xlabel('Time') ylabel('Monthly Downloads') title('Monthly Export Fig Downloads')

So it looks like `export_fig` use is in decline. But don't worry, I don't think it's Yair's fault! MATLAB R2014b included a new graphics system in MATLAB.
With this printing has become much improved which has removed usecases where `export_fig` really helped; for example, with antialiasing. As users migrate to newer releases, I'd expect to see this trend continue.

So what happens if we give Oliver credit for the `export_fig` downloads leading up to August, 2015?

% Sum the file downloads before ownership transferred beforeAug15 = HistoryExportFig.MonthName_Download < datetime(2015,8,18); export_fig_Oliver = sum(HistoryExportFig.FileDownloadCount(beforeAug15)); % Add it to Oliver's count idxOliver = find(strcmp(Author.Creators_name,'Oliver Woodford')); Author.sum_total_downloads(idxOliver) = Author.sum_total_downloads(idxOliver)+export_fig_Oliver; % Re-sort Author = sortrows(Author,'sum_total_downloads','descend');

Is it enough to bring Oliver into the top 15?

idxOliver = find(strcmp(Author.Creators_name,'Oliver Woodford')); disp(['Oliver''s ranking: ' num2str(idxOliver)])

Oliver's ranking: 23

Not quite, but it brings him from 129th down to 23rd!

What has been your "Top File" ever? Is there any other way you'd like me to slice this data? Let us know here!

Get
the MATLAB code

Published with MATLAB® R2016a

Jiro's pick this week is Teaching Calculus with MATLAB by the TCM Team.I really like these apps that the folks from TU Darmstadt and University of Stuttgart created for teaching various calculus concepts. Many concepts taught in calculus can can be better understood if the students can visualize them. Back... read more >>

]]>Jiro's pick this week is Teaching Calculus with MATLAB by the TCM Team.

I really like these apps that the folks from TU Darmstadt and University of Stuttgart created for teaching various calculus concepts. Many concepts taught in calculus can can be better understood if the students can visualize them. Back when I was in college, I remember learning the Newton's Method on paper, drawing tangent lines iteratively to find a root of a function. Just the fact I could draw (visualize) the process made it easier to understand.

It would be even better if I could repeat this learning experience for an arbitrary function. Using interactive apps like the ones the TCM Team made improves the experience greatly.

Here are a couple of other examples, polynomial interpolation and steepest descent.

In addition to the pure usefulness of these apps in teaching situations, here are my other reasons I like this submission.

- Well-written MATLAB code. All of the apps are written in a consistent manner, making use of nested functions to share two common structures across the app, one for maintaining the data specific to the concept and another for the user interface. Well-written code means maintainable code.
- Similar UI for all apps. Because all apps look similar with similar set of buttons and parameters, it's easy for you to use any of the other apps once you learn to use one.
- Because of points 1 and 2, the team can easily create other apps for other concepts, which they intend to do in the future.

**Comments**

Give this a try and let us know what you think here or leave a comment for the TCM Team.

Get
the MATLAB code

Published with MATLAB® R2016a

In honor of MATLAB Central's 15th anniversary this week, Sean's picks this week are the two "oldest" files on the File Exchange. Contents ... read more >>

]]>In honor of MATLAB Central's 15th anniversary this week, Sean's picks this week are the two "oldest" files on the File Exchange.

Every File Exchange entry has an id that you can reference it with. These ids continue to increase as new files arrive on the File Exchange with the 58671st arriving just now.

Thus is seems that the "first" file on the File Exchange might be the one with the lowest id. I did a quick binary search typing in URLs with low ids and discovered that 12 was the lowest index on the File Exchange. At one point, there was a file at 11, but it has since been deleted.

So what is file 12? It's central_diff by Robert Canfield. This file was originally submitted on October 27th, 2000 and actually most recently updated, last year or 15 years later, to make it more accurate!

This file computes the derivative of a vector using a second order central difference. Here's a quick example:

x = linspace(-2*pi,2*pi,1000); f = sin(x); dfdx = central_diff(f,x); plot(x,y,x,dfdx) axis tight xlabel('x') legend({'$f(x)$', '$\frac{dF}{dx}$'}, 'Interpreter', 'latex')

But is it really the oldest?

There are different ways to sort results on the File Exchange and one is by *"Date Submitted (Oldest - Newest)"*.

Looking at the oldest one, it's routh by Edmundo Rivera-Santos. This file has an index of 58 but was submitted on January 30, 1997!

It seems this is truly the oldest file. And it still runs almost two decades later in R2016a!

**NOTE** There is no BSD license so use at your own risk.

syms a b c EPS ra=routh([1 a b c],EPS)

ra = [ 1, b] [ a, c] [ -(c - a*b)/a, 0] [ c, 0]

It's also great that both of these files happen to have the characteristics of a pick of the week. They have good: help, error checking, comments and examples which I'm sure have been used hundreds or thousands of times over the years.

So why does routh precede central_diff in age but not index? I reached out to Ned to find out.

Before there was a File Exchange, there was an FTP site where files could be shared. Ned provided this antique screen shot of that FTP site; the files were in the "contrib" folder:

When the File Exchange was created, the FTP files were not immediately migrated. Thus the first files posted to the File Exchange got lower ids.

Give them a try and let us know what you think here or leave a congratulatory comment for the authors of routh or central_diff.

Get
the MATLAB code

Published with MATLAB® R2016a