# Trouble making topographical EEG interpolation

**URL:** https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733
**Category:** Visualization
**Tags:** interpolations, makie, gmt
**Created:** [March 8, 2020, 10:39pm UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733 "2020-03-08T22:39:04Z")
**Posts on this page:** 19
**Page:** 1

<div class="post-metadata">

### Author: ![ElectronicTeaCup](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/electronicteacup/32/12647_2.png) [@ElectronicTeaCup](https://discourse.julialang.org/u/ElectronicTeaCup)
#### Post date: [March 8, 2020, 10:39pm UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/1 "2020-03-08T22:39:04Z")

</div>

Hi everyone. I’m trying to make an EEG topographical plot, something like this:

![image](https://global.discourse-cdn.com/julialang/original/3X/8/6/86d511b7d277f0d46f7df8cf800be3ad41ab0d3d.png)

The steps, in general are (without the aesthetics and circular appearance):

1. Turn polar coordinates to Cartesian coordinates
2. Interpolate data onto coordinates
3. …?

So far I’ve tried to keep it pretty simple, but still can’t manage. I was trying to adapt some MATLAB [code](http://mikexcohen.com/book/AnalyzingNeuralTimeSeriesData_MatlabCode.zip) but just couldn’t manage to implement the steps. Can you see something that I’m missing?

```julia
using MAT, Plots, Random, Measures
using FFTW, DSP
using ScatteredInterpolation
using Statistics
using StatsBase

plotly()

# I/O for the EEG mat file, using MAT package
EEG = matread("sampleEEGdata.mat")
EEG = EEG["EEG"]

function pol2cart(th,r,z=1)
    x = r.*cos.(th)
    y = r.*sin.(th)
    return (x, y, z)
end

# Introduction to Topographical Plots

timepoint2plot = 100 # in ms
trial2plot = Int(sample(1:EEG["trials"]))
color_limit = 20

# Convert time point from ms to index and get relevant EEG data
_, timepointidx = findmin(dropdims(abs.(EEG["times"].-timepoint2plot), dims=1))
timepoint_trial_data = EEG["data"][:,timepointidx, trial2plot][:,1]

# First step is to get X and Y coordinates of electrodes
# These must be converted to polar coordinates
th = (π/180) .*EEG["chanlocs"]["theta"][1,:]
radi = EEG["chanlocs"]["radius"][1,:]
electrode_locs_X, electrode_locs_Y = pol2cart(th, radi)

# Interpolate to get nice surface
interpolation_level = 100 # you can try changing this number, but 100 is probably good
interpX = range(
    minimum(electrode_locs_X),
    maximum(electrode_locs_X),
    length=interpolation_level
)
interpY = range(
    minimum(electrode_locs_Y),
    maximum(electrode_locs_Y),
    length=interpolation_level
)

# testing ScatteredInterpolation.jl
points = [electrode_locs_X' ; electrode_locs_Y']
samples = timepoint_trial_data
n = 100
x = interpX
y = interpY
X = repeat(x, n)[:]
Y = repeat(y', n)[:]
gridPoints = [X Y]'

itp = interpolate(Multiquadratic(), points, samples)
interpolated = evaluate(itp, gridPoints)
gridded = reshape(interpolated, n, n)
p2 = contour(x, y, gridded)

```

The matlab code was:

```matlab
% First step is to get X and Y coordinates of electrodes
% These must be converted to polar coordinates
th=pi/180*[EEG.chanlocs.theta];
[electrode_locs_X,electrode_locs_Y] = pol2cart(th,[EEG.chanlocs.radius]);

% interpolate to get nice surface
interpolation_level = 100; % you can try changing this number, but 100 is probably good
interpX = linspace(min(electrode_locs_X),max(electrode_locs_X),interpolation_level);
interpY = linspace(min(electrode_locs_Y),max(electrode_locs_Y),interpolation_level);

% meshgrid is a function that creates 2D grid locations based on 1D inputs
[gridX,gridY] = meshgrid(interpX,interpY);

% now interpolate the data on a 2D grid
interpolated_EEG_data = griddata(electrode_locs_Y,electrode_locs_X,double(squeeze(EEG.data(:,timepointidx,trial2plot))),gridX,gridY);
contourf(interpY,interpX,interpolated_EEG_data,100,'linecolor','none');

```

I get the following: (Julia plot on the left, MATLAB on the right)

 ![image](https://global.discourse-cdn.com/julialang/original/3X/0/a/0a5fcedb9cc638334565789b56050a25a8f037a8.png)

Does anyone have any better approaches on getting the final product?

---

<div class="post-metadata">

### Author: ![asinghvi17](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/asinghvi17/32/8272_2.png) [@asinghvi17](https://discourse.julialang.org/u/asinghvi17)
#### Post date: [June 5, 2020, 9:58am UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/2 "2020-06-05T09:58:41Z")

</div>

You might have some luck with GR.jl’s `tricont` or `trisurf` functions.

---

<div class="post-metadata">

### Author: ![johnh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnh/32/3615_2.png) [@johnh](https://discourse.julialang.org/u/johnh)
#### Post date: [June 5, 2020, 10:02am UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/3 "2020-06-05T10:02:22Z")

</div>

Out of interest I bought one of these ECG sensors [https://www.amazon.co.uk/gp/product/B08216YR9H/ref=ppx\_yo\_dt\_b\_search\_asin\_title?ie=UTF8&psc=1](https://www.amazon.co.uk/gp/product/B08216YR9H/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1)

It should work with a Raspberry Pi.  
May I ask what the polar plot represents?

---

<div class="post-metadata">

### Author: ![ElectronicTeaCup](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/electronicteacup/32/12647_2.png) [@ElectronicTeaCup](https://discourse.julialang.org/u/ElectronicTeaCup)
#### Post date: [June 5, 2020, 12:46pm UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/4 "2020-06-05T12:46:05Z")

</div>

> [@asinghvi17](#):
>
> `trisurf`

Thanks for the suggestion! Getting this with `tricont`

![image](https://global.discourse-cdn.com/julialang/original/3X/d/8/d8e562aa1ebc0e28177bee15fa926292667ab20d.png)

Any ideas how I can fill this?

---

<div class="post-metadata">

### Author: ![ElectronicTeaCup](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/electronicteacup/32/12647_2.png) [@ElectronicTeaCup](https://discourse.julialang.org/u/ElectronicTeaCup)
#### Post date: [June 5, 2020, 12:49pm UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/5 "2020-06-05T12:49:46Z")

</div>

The plot represents electrical brain activity (Electroencephalography, EEG) on the surface of a human subject during a experimental task. ECG (the sensor you have) in a similar vein, is for detecting electrical signals read out from the heart and is used clinically by medical doctors.

---

<div class="post-metadata">

### Author: ![johnh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnh/32/3615_2.png) [@johnh](https://discourse.julialang.org/u/johnh)
#### Post date: [June 5, 2020, 12:50pm UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/6 "2020-06-05T12:50:36Z")

</div>

@ElectronicTeaCup My bad. Entirely. I used to work in a medical physics department and I hang my head in shame.  
Please tell us more about your interesting work. What is the task the subjects are asked to do?

---

<div class="post-metadata">

### Author: ![ElectronicTeaCup](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/electronicteacup/32/12647_2.png) [@ElectronicTeaCup](https://discourse.julialang.org/u/ElectronicTeaCup)
#### Post date: [June 5, 2020, 1:27pm UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/7 "2020-06-05T13:27:13Z")

</div>

Hehe, no issues. This particular data is public, which I’m using for text-book based course on time-frequency analyses so I’m not super sure what the experiment was. I’m hoping to apply the same time-frequency methods to MEG recordings that I will be taking during a simple task which involves passively listening to tones. The idea is to get a general idea of how sounds can form a temporally intact memory trace in the auditory cortex using modelling approaches and empirical data.

---

<div class="post-metadata">

### Author: ![likanzhan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/likanzhan/32/26354_2.png) [@likanzhan](https://discourse.julialang.org/u/likanzhan)
#### Post date: [January 6, 2022, 1:17pm UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/8 "2022-01-06T13:17:28Z")

</div>

Do we have an update on this topic?

---

<div class="post-metadata">

### Author: ![ElectronicTeaCup](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/electronicteacup/32/12647_2.png) [@ElectronicTeaCup](https://discourse.julialang.org/u/ElectronicTeaCup)
#### Post date: [January 13, 2022, 1:24pm UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/9 "2022-01-13T13:24:46Z")

</div>

@likanzhan Sorry about the late reply, but there was some more discussion in this [thread](https://github.com/JuliaNeuroscience/NeuroPlots.jl/issues/1#issuecomment-932606876), with some functioning [code](https://github.com/unfoldtoolbox/UnfoldMakie.jl/blob/topoplot/src/topoplot.jl) to make something like this:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/c/4/c4e46d14474797c0bc6b664da4a22b4e6818f33f.jpeg)

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [January 14, 2022, 8:13am UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/10 "2022-01-14T08:13:21Z")

</div>

FWIW, if the human scalp can be approximated by an ellipsoid, then you can try GMT’s `greenspline` interpolation which uses a generalized Green’s function for spherical surface splines in tension. See one [example here](https://docs.generic-mapping-tools.org/latest/gallery/ex29.html#example-29) and the [technical reference here](https://academic.oup.com/gji/article/174/1/21/2126658).

---

<div class="post-metadata">

### Author: ![Zach\_Christensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zach_christensen/32/7220_2.png) [@Zach\_Christensen](https://discourse.julialang.org/u/Zach_Christensen)
#### Post date: [January 14, 2022, 11:59am UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/11 "2022-01-14T11:59:32Z")

</div>

usually it’s treated as an ellipsoid, although it’s becoming a bit more common to create a unique 3d mesh representing each persons head structure.

---

<div class="post-metadata">

### Author: ![likanzhan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/likanzhan/32/26354_2.png) [@likanzhan](https://discourse.julialang.org/u/likanzhan)
#### Post date: [January 16, 2022, 9:24am UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/12 "2022-01-16T09:24:26Z")

</div>

Thanks. Based on others’ suggestions and the [plot\_topography](https://www.mathworks.com/matlabcentral/fileexchange/72729-topographic-eeg-meg-plot) function written in Matlab, I think triangulate methods are better. Here are what I have achieved via the [triangulate](https://www.generic-mapping-tools.org/GMT.jl/dev/#GMT.triangulate) function in `GMT`. The code I used to do the plotting is [here](https://github.com/likanzhan/PlotTopography.jl/blob/main/src/PlotTopography.jl).

- Julia rewritten version

 ![Julia](https://global.discourse-cdn.com/julialang/original/3X/2/1/21b31292dd641ef4391eb4eda807144278300f9a.png)

- Original Matlab version

 ![MatLab](https://global.discourse-cdn.com/julialang/original/3X/c/3/c3388e8277028bce59f9f111a754427e6e72de27.jpeg)

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [January 16, 2022, 12:22pm UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/13 "2022-01-16T12:22:43Z")

</div>

> [@ElectronicTeaCup](#):
>
> I get the following: (Julia plot on the left, MATLAB on the right)
> 
> ![image](https://global.discourse-cdn.com/julialang/original/3X/0/a/0a5fcedb9cc638334565789b56050a25a8f037a8.png)
> 
> Does anyone have any better approaches on getting the final product?

Using GMT and the tip from @joa-quim [here](https://discourse.julialang.org/t/contour-plot-for-non-rectangular-domain/57381/5), you can produce a contour plot like this (_OP’s script has random sampling, so input is different_):

 ![GMT_contours_in_a_circle](https://global.discourse-cdn.com/julialang/original/3X/d/f/df1340bc231269cbf91d72ac3ebb54f5eb5f08f4.png)

```julia
# GMT GRIDDING (Smith and Wessel [1990] Splines in tension):
using GMT
data = [electrode_locs_X electrode_locs_Y timepoint_trial_data]
x = y = LinRange(-0.65, 0.65, 100)
G = GMT.surface(data, R=(extrema(x)..., extrema(y)...), inc=(step(x), step(y)), T=0.1)

# GMT PLOTTING
circ0 = reduce(vcat, 0.65*[[cos(θ) sin(θ)] for θ in 0:0.1:2π]) # circle
GMT.contourf(G, clip=circ0, fmt=:png, show=true)

```

**NB:**  
_the spline interpolation method used acts along “flat” x-y support coordinates, but as mentioned it is also possible to use spherical surface splines acting along an ellipsoid_

---

<div class="post-metadata">

### Author: ![Zach\_Christensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zach_christensen/32/7220_2.png) [@Zach\_Christensen](https://discourse.julialang.org/u/Zach_Christensen)
#### Post date: [January 16, 2022, 6:04pm UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/14 "2022-01-16T18:04:37Z")

</div>

If someone puts together a proposal in a PR I’d be happy to review it for NeuroPlots.

---

<div class="post-metadata">

### Author: ![likanzhan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/likanzhan/32/26354_2.png) [@likanzhan](https://discourse.julialang.org/u/likanzhan)
#### Post date: [January 17, 2022, 1:26am UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/15 "2022-01-17T01:26:40Z")

</div>

@Zach_Christensen Do you think it is potentially useful to others if I push the function I wrote to NeuroPlots?

---

<div class="post-metadata">

### Author: ![behinger](https://avatars.discourse-cdn.com/v4/letter/b/7ba0ec/32.png) [@behinger](https://discourse.julialang.org/u/behinger)
#### Post date: [January 17, 2022, 7:58pm UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/16 "2022-01-17T19:58:09Z")

</div>

could you elaborate why you prefer triangulation methods for topoplots?

Cheers, Bene

---

<div class="post-metadata">

### Author: ![likanzhan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/likanzhan/32/26354_2.png) [@likanzhan](https://discourse.julialang.org/u/likanzhan)
#### Post date: [January 18, 2022, 1:53am UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/17 "2022-01-18T01:53:34Z")

</div>

@behinger There are some discussion concerning their difference [here](https://docs.generic-mapping-tools.org/latest/gallery/ex16.html#example-16). As we can see from the four examples, there exist some tiny difference between them. My intuition is that it is more reasonable to suppose the hotpot is in the center of the surface, rather than at the edge of the surface. But I’m no expert on either EEG or GMT, please correct me if I’m wrong. Furthermore, we can easily implement different methods, as the case [griddata](https://www.mathworks.com/help/matlab/ref/griddata.html?s_tid=srchtitle_griddata_1) in Matlab, for the users to select.

Sincerely,  
Likan

---

<div class="post-metadata">

### Author: ![Zach\_Christensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zach_christensen/32/7220_2.png) [@Zach\_Christensen](https://discourse.julialang.org/u/Zach_Christensen)
#### Post date: [January 20, 2022, 2:24pm UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/18 "2022-01-20T14:24:47Z")

</div>

Let’s start by getting something working. This is long overdue. Then we can work on how to facilitate different interpolation methods.

---

<div class="post-metadata">

### Author: ![behinger](https://avatars.discourse-cdn.com/v4/letter/b/7ba0ec/32.png) [@behinger](https://discourse.julialang.org/u/behinger)
#### Post date: [July 5, 2022, 5:55am UTC](https://discourse.julialang.org/t/trouble-making-topographical-eeg-interpolation/35733/19 "2022-07-05T05:55:46Z")

</div>

There is a new package TopoPlots.jl that should resolve this issue. If you have ideas to improve, we are happy to hear them!

> **[GitHub - MakieOrg/TopoPlots.jl: Makie topo plot recipes, for neuro-science,...](https://github.com/MakieOrg/TopoPlots.jl)**
>
> Makie topo plot recipes, for neuro-science, geo plots and anyone needing surface plots from unstructured data - GitHub - MakieOrg/TopoPlots.jl: Makie topo plot recipes, for neuro-science, geo plots...

![grafik](https://global.discourse-cdn.com/julialang/original/3X/b/2/b2673166789768751d3447b0b70a4e058570efc8.jpeg)

 ![grafik](https://global.discourse-cdn.com/julialang/original/3X/1/f/1f5552d844e22879a0f46b70a7724cfac3328968.jpeg)
