Samir Khan

1956 Reputation

20 Badges

16 years, 160 days

My role is to help customers better exploit our tools. I’ve worked in selling, supporting and marketing maths and simulation software for all my professional career.

I’m fascinated by the full breadth and range of application of Maple. From financial mathematics and engineering to probability and calculus, I’m always impressed by what our users do with our tools.

However much I strenuously deny it, I’m a geek at heart. My first encounter with Maple was as an undergraduate when I used it to symbolically solve the differential equations that described the heat transfer in a series of stirred tanks. My colleagues brute-forced the problem with a numerical solution in Fortran (but they got the marks because that was the point of the course). I’ve since dramatized the process in a worksheet, and never fail to bore people with the story behind it.

I was born, raised and spent my formative years in England’s second city, Birmingham. I graduated with a degree in Chemical Engineering from The University of Nottingham, and after completing a PhD in Fluid Dynamics at Herriot-Watt University in Edinburgh, I started working for Adept Scientific – Maplesoft’s partner in the UK.

MaplePrimes Activity


These are Posts that have been published by Samir Khan

Last year, I read a fascinating paper that presented evidence of an exoplanet, inferred through the “wobble” (or radial velocity) of the star it orbits, HD 3651. A periodogram of the radial velocity revealed the orbital period of the exoplanet – about 62.2 days.

I found the experimental data and attempted to reproduce the periodogram. However, the data was irregularly sampled, as is most astronomical data. This meant I couldn’t use the standard Fourier-based tools from the signal processing package.

I started hunting for the techniques used in the spectral analysis of irregularly sampled data, and found that the Lomb Scargle approach was often used for astronomical data. I threw together some simple prototype code and successfully reproduced the periodogram in the paper.

 

After some (not so) gentle prodding, Erik Postma’s team wrote their own, far faster and far more robust, implementation.

This new functionality makes its debut in Maple 2019 (and the final worksheet is here.)

From a simple germ of an idea, to a finished, robust, fully documented product that we can put in front of our users – that, for me, is incredibly satisfying.

That’s a minor story about a niche I’m interested in, but these stories are repeated time and time again.  Ideas spring from users and from those that work at Maplesoft. They’re filtered to a manageable set that we can work on. Some projects reach completion in under a year, while other, more ambitious, projects take longer.

The result is software developed by passionate people invested in their work, and used by passionate people in universities, industry and at home.

We always pack a lot into each release. Maple 2019 contains improvements for the most commonly used Maple functions that nearly everyone uses – such as solve, simplify and int – as well features that target specific groups (such as those that share my interest in signal processing!)

I’d like to to highlight a few new of the new features that I find particularly impressive, or have just caught my eye because they’re cool.

Of course, this is only a small selection of the shiny new stuff – everything is described in detail on the Maplesoft website.

Edgardo, research fellow at Maplesoft, recently sent me a recent independent comparison of Maple’s PDE solver versus those in Mathematica (in case you’re not aware, he’s the senior developer for that function). He was excited – this test suite demonstrated that Maple was far ahead of its closest competitor, both in the number of PDEs solved, and the time taken to return those solutions.

He’s spent another release cycle working on pdsolve – it’s now more powerful than before. Here’s a PDE that Maple now successfully solves.

Maplesoft tracks visits to our online help pages - simplify is well-inside the top-ten most visited pages. It’s one of those core functions that nearly everyone uses.

For this release, R&D has made many improvements to simplify. For example, Maple 2019 better simplifies expressions that contain powers, exponentials and trig functions.

Everyone who touches Maple uses the same programming language. You could be an engineer that’s batch processing some data, or a mathematical researcher prototyping a new algorithm – everyone codes in the same language.

Maple now supports C-style increment, decrement, and assignment operators, giving you more concise code.

We’ve made a number of improvements to the interface, including a redesigned start page. My favorite is the display of large data structures (or rtables).

You now see the header (that is, the top-left) of the data structure.

For an audio file, you see useful information about its contents.

I enjoy creating new and different types of visualizations using Maple's sandbox of flexible plots and plotting primitives.

Here’s a new feature that I’ll use regularly: given a name (and optionally a modifier), polygonbyname draws a variety of shapes.

In other breaking news, I now know what a Reuleaux hexagon looks like.

Since I can’t resist talking about another signal processing feature, FindPeakPoints locates the local peaks or valleys of a 1D data set. Several options let you filter out spurious peaks or valleys

I’ve used this new function to find the fundamental frequencies and harmonics of a violin note from its periodogram.

Speaking of passionate developers who are devoted to their work, Edgardo has written a new e-book that teaches you how to use tensor computations using Physics. You get this e-book when you install Maple 2019.

The new LeastTrimmedSquares command fits data to an equation while not being signficantly influenced by outliers.

In this example, we:

  • Artifically generate a noisy data set with a few outliers, but with the underlying trend Y =5 X + 50
  • Fit straight lines using CurveFitting:-LeastSquares and Statistics:-LeastTrimmedSquares

LeastTrimmedSquares function correctly predicts the underlying trend.

We try to make every release faster and more efficient. We sometimes target key changes in the core infrastructure that benefit all users (such as the parallel garbage collector in Maple 17). Other times, we focus on specific functions.

For this release, I’m particularly impressed by this improved benchmark for factor, in which we’re factoring a sparse multivariate polynomial.

On my laptop, Maple 2018 takes 4.2 seconds to compute and consumes 0.92 GiB of memory.

Maple 2019 takes a mere 0.27 seconds, and only needs 45 MiB of memory!

I’m a visualization nut, and I always get a vicarious thrill when I see a shiny new plot, or a well-presented application.

I was immediately drawn to this new Maple 2019 app – it illustrates the transition between day and night on a world map. You can even change the projection used to generate the map. Shiny!

 

So that’s my pick of the top new features in Maple 2019. Everyone here at Maplesoft would love to hear your comments!

You might recall this image being shared on social media some time ago.

Source: http://cvcl.mit.edu/hybrid_gallery/monroe_einstein.html

Look closely and you see Albert Einstein. However, if you move further away (or make the image smaller), you see Marilyn Monroe.

To create the image, the high spatial frequency data from an image of Albert Einstein was added to the low spatial frequency data from an image of Marilyn Monroe. This approach was pioneered by Oliva et al. (2006) and is influenced by the multiscale processing of human vision.

  • When we view objects near us, we see fine detail (that is, higher spatial frequencies dominate).

  • However, when we view objects at a distance, the broad outline has greater influence (that is, lower spatial frequencies dominate).

I thought I'd try to create a similar image in Maple (get the complete application here).

Here's an overview of the approach (as outlined in Oliva et al., 2006). I used different source images of Einstein and Monroe.

Let's start by loading some packages and defining a few procedures.

restart:
with(ImageTools):
with(SignalProcessing):

fft_shift := proc(M)
   local nRows, nCols, quad_1, quad_2, quad_3, quad_4, cRows, cCols;
   nRows, nCols := LinearAlgebra:-Dimensions(M):
   cRows, cCols := ceil(nRows/2), ceil(nCols/2):
   quad_1 := M[1..cRows,      1..cCols]:
   quad_2 := M[1..cRows,      cCols + 1..-1]:  
   quad_3 := M[cRows + 1..-1, cCols + 1..-1]:
   quad_4 := M[cRows + 1..-1, 1..cCols]:
   return <<quad_3, quad_2 |quad_4, quad_1>>:
end proc:

PowerSpectrum2D := proc(M)
   return sqrt~(abs~(M))
end proc:

gaussian_filter := (a, b, sigma) -> Matrix(2 * a, 2 * b, (i, j) -> evalf(exp(-((i - a)^2 + (j - b)^2) / (2 * sigma^2))), datatype = float[8]):

fft_shift() swaps quadrants of a 2D Fourier transform around so that the zero frequency components are in the center.

PowerSpectrum2D() returns the spectra of a 2D Fourier transform

gaussian_filter() will be used to apply a high or low-pass filter in the frequency domain (a and b are the number of rows and columns in the 2D Fourier transform, and sigma is the cut-off frequency.

Now let's import and display the original Einstein and Monroe images (both are the same size).

einstein_img := Read("einstein.png")[..,..,1]:
Embed(einstein_img)

marilyn_img  := Read("monroe.png")[..,..,1]:
Embed(monroe_img)

Let's convert both images to the spatial frequency domain (not many people know that SignalProcessing:-FFT can calculate the Fourier transform of matrices).

einstein_fourier := fft_shift(FFT(einstein_img)):
monroe_fourier   := fft_shift(FFT(monroe_img)):

Visualizing the power spectra of the unfiltered and filtered images isn't necessary, but helps illustrate what we're doing in the frequency domain.

First the spectra of the Einstein image. Lower frequency data is near the center, while higher frequency data is further away from the center.

Embed(Create(PowerSpectrum2D(einstein_fourier)))

Now the spectra of the Monroe image.

Embed(Create(PowerSpectrum2D(monroe_fourier)))

Now we need to filter the frequency content of both images.

First, define the cutoff frequencies for the high and low pass Gaussian filters.

sigma_einstein := 25:
sigma_monroe   := 10:

In the frequency domain, apply a high pass filter to the Einstein image, and a low pass filter to the Monroe image.

nRows, nCols := LinearAlgebra:-Dimension(einstein_img):

einstein_fourier_high_pass := einstein_fourier *~ (1 -~ gaussian_filter(nRows/2, nCols/2, sigma_einstein)):
monroe_fourier_low_pass    := monroe_fourier   *~ gaussian_filter(nRows/2, nCols/2, sigma_monroe):

Here's the spectra of the Einstein and Monroe images after the filtering (compare these to the pre-filtered spectra above).

Embed(Create(PowerSpectrum2D(einstein_fourier_high_pass)))

Embed(Create(PowerSpectrum2D(monroe_fourier_low_pass)))

Before combining both images in the Fourier domain, let's look the individual filtered images.

einstein_high_pass_img := Re~(InverseFFT(fft_shift(einstein_fourier_high_pass))):
monroe_low_pass_img    := Re~(InverseFFT(fft_shift(monroe_fourier_low_pass))):

We're left with sharp detail in the Einstein image.

Embed(FitIntensity(Create(einstein_high_pass_img)))

But the Monroe image is blurry, with only lower spatial frequency data.

Embed(FitIntensity(Create(monroe_low_pass_img)))

For the final image, we're simply going to add the Fourier transforms of both filtered images, and invert to the spatial domain.

hybrid_image := Create(Re~(InverseFFT(fft_shift(monroe_fourier_low_pass + einstein_fourier_high_pass)))):
Embed(hybrid_image)

So that's our final image, and has a similar property to the hybrid image at the top of this post.

  • Move close to the computer monitor and you see Albert Einstein.
  • Move to the other side of the room, and Marilyn Monroe swims into vision (if you're myopic, just take off your glasses and don't move back as much).

To simulate this, here, I've successively reduced the size of the hybrid image

And just because I can, here's a hybrid image of a cat and a dog, generated by the same worksheet.

To demonstrate Maple 2018’s new Python connectivity, we wanted to integrate a large Python library. The result is the DeepLearning package - this offers an interface to a subset of the Tensorflow framework for machine learning.

I thought I’d share an application that demonstrates how the DeepLearning package can be used to recognize the numbers in images of handwritten digits.

The application employs a very small subset of the MNIST database of handwritten digits. Here’s a sample image for the digit 0.

This image can be represented as a matrix of pixel intensities.        

The application generates weights for each digit by training a two-layer neural network using multinomial logistic regression. When visualized, the weights for each digit might look like this.

Let’s say that we’re comparing an image of a handwritten digit to the weights for the digit 0. If a pixel with a high intensity lands in

  • an intensely red area, the evidence is high that the number in the image is 0
  • an intensely blue area, the evidence is low that the number in the image is 0

While this explanation is technically simplistic, the application offers more detail.

Get the application here

As a momentary diversion, I threw together a package that downloads map images into Maple using the Google Static Maps API.

If you have Maple 2017, you can install the package using the MapleCloud Package Manager or by executing PackageTools:-Install("5769608062566400").

This worksheet has several examples, but I thought I'd share a few below .

Here's the Maplesoft office

 

Let's view a roadmap of Waterloo, Ontario.

 

The package features over 80 styles for roadmaps. These are examples of two styles (the second is inspired by the art of Piet Mondrian and the De Stijl movement)

 

You can also find the longitude and latitude of a location (courtesy of Google's Geocoding API). Maple returns a nested list if it finds multiple locations.

 

The geocoding feature can also be used to add points to Maple 2017's built-in world maps.

 

Let me know what you think!

Yahoo Finance recently discontinued their (largely undocumented) historical stock quote API.

Previously, you simply send a HTTP:-Get request like this…

HTTP:-Get(“http://ichart.yahoo.com/table.csv?s=AAPL&a=00&b=1&c=2016&d=00&e=1&f=2017&g=d&ignore=.csv")

…and get historical OHLCV (open, high, low, close, trading volume) data in your worksheet (in this case for AAPL between 1 January 2016 and 1 January 2017).

This no longer works! Yahoo shut the door on this easy-to-use and widely disseminated API.

You can still download historical stock quotes from Yahoo Finance into Maple, but the process is now somewhat more involved. My complete code in this worksheet but I'll step through the process below.

If you visit the updated Yahoo Finance website and download historical data for a ticker, you see a URL like this in the status bar of your browser

https://query1.finance.yahoo.com/v7/finance/download/AAPL?period1=1497727945&period2=1500319945&interval=1d&events=history&crumb=C9luNcNjVkK

Let's examine how ths URL is constructed.

  • period1 and period2 are Unix time stamps for your start and end date
  • interval is the data retrieval interval (this can be either 1d, 1w or 1m)
  • crumb is an alphanumeric code that’s periodically regenerated every time you download new historical data from from the Yahoo Finance website using your browser. Moreover, crumb is paired with a cookie that’s stored by your browser.

Here’s how to extract and supply the cookie-crumb pair to Yahoo Finance so you can still use Maple to retrieve historical stock quotes

Send a dummy request to get a cookie-crumb pair

res:=HTTP:-Get("https://finance.yahoo.com/lookup?s=bananas"):

Grab the crumb from the response

i:=StringTools:-Search("CrumbStore\":{\"crumb\":\"",res[2]):
crumbValue := res[2][i+22..i+32]
                  crumbValue := "btW01FWTBn3"

Store the cookie from the response

cookieHeader:=res[3]["Set-Cookie"]
    cookieHeader := "B=702eqhdcmq7cl&b=3&s=0t; expires=Mon,17-Jul-2018 20:27:01 GMT; path=/; domain=.yahoo.com

Construct the URL

  • Your desired start and end dates have to be defined as Unix time stamps. Converting a human readable date (like 1st January 2017) to a Unix timestamp is simple, so I won't cover it here.
  • The previously retrieved crumb has to be added to the URL.
ticker:="AAPL":
p1 := 1497709183:
p2 := 1500301183:
url:=cat("https://query1.finance.yahoo.com/v7/finance/download/",ticker,"?period1=",p1,"&period2=",p2,"&interval=1d&events=history&crumb=", crumbValue):

Send the request to Yahoo Finance, including the cookie in the header

data:=HTTP:-Get(url,headers = ["Cookie" = cookieHeader])

Your historical data is now returned

The historical data is now easily parsed into a matrix.

Please note that any use of Yahoo Finance has to be consistent with their terms of service.

2 3 4 5 6 7 8 Last Page 4 of 12