MRI Technology with Dr. Martijn Froeling

A live-streamed demonstration and discussion with Dr. Martijn Froeling about quantitative MRI (QMRI) methods, his open-source Mathematica/Wolfram-language toolbox (QMRI Tool), and workflows for imaging, modeling, noise reduction, registration, and visualization. Froeling explains MRI physics (diffusion, T2, Dixon water–fat imaging, phase), data sizes, sources of error, experiment design (diffusion gradient shells), and his engineering approach to building, documenting, and optimizing a large analysis toolbox used for muscle and neuromuscular research.
Chapters
Sam. Hello, everyone. Thank you for joining us today. We are fortunate enough to have made Martin Fronling with us today. I hope I pronounced that close to correctly. Who is an expert on MRI technology and a longtime user of Wolfram Technology. I'm Noah Chartoff and joined today of course, as always, by John McNally.
Hello. We are very happy to have you here. So one of the questions that I of course had is if we could get a quick orientation for the benefit of the audience and of course for us, of what are the nuts and bolts of the fields that you are an expert in and what are the things that you use technology to do to help with all this great medical technology that as people living today we have access to?
Yeah, thanks for having me on this nice live stream. So, so I work with MRI scanners. Basically very big magnets. We put people in and then we make image of the human body. And an MRI system itself can generate a lot of different types of images. So you can do the anatomical images but also more quantitative measurements. So depending on the settings of the scanner. And I specifically look at muscles in the context of neuromuscular disease and sports related injury. So I had a quick slide to actually quickly introduce you to what actually mean when I say quantitative imaging. So the toolbox that I use in mathematics kind of develop is called Cumari tools and not MRI tools. So the Q stands for quantitative and that's quite important.
Did I hear you say that you developed this tool yourself?
Yeah, from scratch.
Very cool.
Started during my masters in 2009 and since then I've been keeping track of all the code I've written and been adding it to it. And it's grown a little bit since then. You can sort of see an MRI scanner as a camera that takes pictures of the body and we talk about qualitative imaging. We just take a snapshot with your camera and we can see things on it. And that's quite interesting. But of course we can also use the MRI as a quantitative precision measurement device. So it's more than that if you're looking at a night sky through a normal telescope or to something that actually measures wavelengths. So you can actually infer a lot of quantitative measures from the human body. And it's depending on the settings and the filters we use, of course. So when we talk about quantitative imaging, a lot of things that are important to us are precision, repeatability, what kind of measurement errors we can do. So there's a lot of like modeling going on beyond the image acquisition. And that's Where I use Mathematica for. So basically when I got the data from the MRI machine, we have to analyze it, we have to do derive quantitative values from it. Like I said, we're trying to look at muscle microstructure. When muscles are healthy, they look like the left top image over here. Then of course all kinds of diseases can happen where the cells change, the tissue changes. But with mri, we're not at this length scale. This is in the order of micrometers. Of course with MRI we have a resolution in the order of millimeters. We're really looking at macroscopic pictures of the human body and we're trying to infer microstructural properties from that. And there we use modeling a lot. So of course with modeling you have equations and parameters typically derived from physics. So the entire MRI process is really well described by physics. So we get our data and signal and we can do the forward and inverse problems modeling. And of course it's all based on assumptions and all the other things. And there we want to look at for example, muscle tissue. And when you get diseased, fat will infiltrate the muscle. And then there's different techniques that I mostly use called Dixon based imaging where we can say something about the water fat content of an imaging location, something called T2, which is one of the main contrast mechanisms in Mr. Where we can actually say something about inflammation and something's called diffusion weighted imaging, where we can actually say something about the microscopic motion of water within tissue. The things how I use MRI and for this analysis of this modeling, the Mathematica toolbox comes into play.
So when you say microscopic motion of water, I, I assume that you're referring to more than, more microscopic than water going through veins or, or arteries, that, that we're looking at it closer than that, like diffusion again across cell walls or what are we talking about?
Yes. Yeah. So, so our body is mostly water and mri, all atoms with a spin can actually be visible. But water is the strongest one because we have it in abundance. So therefore we mostly could water and water in cells, outside cells, within every tissue. So we're really looking at the water signal and then if it moves in veins or in arteries, it flows. So we can actually measure motion. With mri we talk about diffusion, we're really looking at the microscopic motion. So that's indeed within cells, within membranes, interaction with brains. We can also use all kind, look at all kind of other properties. For example, the oxygenation in blood gives blood slightly different magnetic properties. And that's what, what typically is called FMRI functional magnetic resonance imaging, where you can look at brain activation, for example.
Right. Where, where oxygen is going into parts of the brain where it'll be useful.
Yeah. So and if the oxygenation of the blood changes, the, the preparing properties of the blood will change and that we can actually measure. So these kinds of properties, physics properties, underly most of the MRI measurements we do. And so we typically don't really take one picture, but we take an entire range of pictures and then we apply models to that and then MRI data. Of course, when you take a picture of the body, the information you measure is actually placed in world coordinates. So we have like the body anatomically correct. So it can actually also infer something macroscopic from how is a muscle build up, how out related. So those are the things we do. Yeah, as for that. So to do the analysis we get images from the scanner. Well, I mean not really images, but data from the scanner. So it's really MRI measures radio frequencies, so RF waves and that we convert via field transform to images or data sets. And there's data sets we analyze using Mathematica.
Brief question. So out of curiosity, order of magnitude, how large is this data set that you would get from a typical MRI scan that someone would go and be a part of?
Really depends. So when you typically look at anatomical imaging, really depends on the resolution. Of course. Take for example you take a head at 20 x 20 cm. Typical resolutions would be 1 x 1 x 1 millimeter. So we're always looking at a volume and not at a really cross sectional photograph, but really we measure volumes. So then the data set would be say 128. 120. 128 voxels and that would be around 30 to 40 MB. But when we do quantitative measurements, it can go up to 5,600mb per data set. And if we take the raw data into account, it can be gigabytes. So that amount of data can vary quite a lot. It also depends what kind of models we're using. Some models need a lot of data, some models only a few data samples. So that really depends on that.
Okay, interesting. And so you have also you mentioned that you've written tools for dealing with this data and turning this data into analysis. So it looks like you have a demonstration here. So I'm very much looking forward to seeing this because this is the first time that I have seen this.
And we should mention at this point, as is often the case in these livestreams, that if we go through any of this code too quickly for you to follow, just know that the notebooks that we use in this demonstration are going to be included via link in the video's description shortly after we're done broadcasting. So if there's anything you wanted to see in more detail, code wise, you will get a chance.
So you can see my screen clearly, right?
Oh yes.
Yeah. So this notebook is actually part of my demonstration for the toolbox. So the toolbox is aimed for expert users in the field. So my code typically doesn't really take care much about error catching or stuff like that. So I assume that the people are using it, know what they're doing. So it's called QMRI Tool. So here, just to show people what actually we are doing, I have this demo data extraction function that actually will extract in the location where you installed the packlet in the resources, it will extract a folder with demo data and this demo data I will use in the toolbox. If you download the toolbox, then actually you will get this demo data as well.
Great.
So just quickly show what's in there. So within the toolbox we also have some functions that actually shows me what's in the toolbox itself. So sometimes I forget what's actually in there and I have to keep track of like is everything incorrectly. So we can actually print the functions on screen that are actually in the toolbox. So this is a list of all the functions that contain in the toolbox. I think currently it's 450 different functions exposed to the front end and of course they also come with options. So here I actually can see if everything's named correctly. And also sometimes what's the name of the function again I can go through it. I think that also what's important is actually to have good documentation when you write code.
Oh good. Because I was looking a lot of these functions and thinking I bet I could guess what they do. But I would love to see it in detail.
So I've been using mostly Eclipse with Wolf from Workbench in the past. So now I'm switching more towards Visual Studio code. Since most of the research for most of the functions that are used to generate documentation can be run from Automatica itself. You don't need the Workbench toolbox anymore to generate it. So I have this guide page that starts off with the main toolbox and it shows all the sub toolboxes that are in there. So for example, tools that are related to this diction imaging, Waterfet Imaging. Here you will get the different functions that are in there. You can click through it and nowadays it's also very nice. It can also compile this to HTML. So everything is available on websites as well. So I also have an online version of this. So basically this is all documented so people can click through all the different things. And I hope, of course not everything is there. I think there's now 850 documentation pages within the toolbox. So the data management of that is getting a bit difficult. But luckily the tools are getting better to do this also for users and not only for internal development. And then one tool I also use a lot is something I've written. It's called memory usage. Actually when I open this I get an extra palette that actually says what kind of big data sets are in my memory. Like I said, some of the data sets actually get quite big and if you do computations on them, sometimes your memory will overflow and then everything gets screeched to a halt. So you actually can see what kind of data sets are currently loaded that are above 1 MB, 10 MBs, 100 MBs, and I can also clear them from here. So if it would clear data, I would say clear and then this is gone.
As a related question, so as part of your professional workflow are the sort of. When you're doing these analyses, is it sometimes useful to connect to computers which are sort of faster and more memory than the typical thing that you might have just sitting on a desk? Or is the scale of this problem okay?
So sometimes we do, but I tend to try to make everything as efficient as possible so that it will run on my own laptop. I can actually do all the computations on my laptop. So it's not a. Well, it's quite a heavy laptop, but not that that big. So it's nice that. So if you design stuff that actually have to run on service, then people have to have like get Matmatica installed and all those kinds of things. And that's sort of like higher requirement for the software. So everything actually runs on my laptop, which is just I think 32 gigabytes of RAM and an I Core 7. So I tend to try to optimize things that actually they will run on a simple system.
That's definitely great for people who are wanting to sort of explore areas that, you know, maybe they're either looking to get into or just sort of curious about. So that. That's awes awesome that everything is designed to work.
Of course if you need to go to bigger systems, always a possibility. So what one of these data sets looks like. So this is some Loading now a data set of some legs. So let me just quickly show. So one of the most important things in data processing I think is always looking at data, knowing what you have, knowing what you measured. So data visualization is a really important part of data analysis I think maybe even the most important one. So of course mathematics, a lot of built in functions like especially been added over the last few years with the default image hat, but also some other like good plotting functions and there's a lot of options you can give to it to make it look pretty. So I built this graphical user interface built on manipulate where you can actually slide through these data sets.
I should ask immediately because just want to be sure of people using this. All of these medical images are anonymized, right?
Yeah. Okay. They're all anonymized. So the ones that I share are anonymized. So these are two lower legs. So you see here the tibia bone just show. So this is the tibia bone, so your shin bone basically. And then we have the calf muscles here. So this is a typical data set from the fusion weighted imaging that I look at. And of course we really want to look at data in other orientations. And you might also notice that the resolution of this data in this specific case is 1.5 by 1.5 by 6 millimeters. So the transverse images where you do a sort of a cross section of the leg has a high in plane resolution. But if you actually look at the sextile and coronal views, then actually the z direction is different than the in plane resolution. So actually these, these pixels here are actually in a ratio 1.5 by 6. So that's already one of the things you have to tweak when you display medical images. You have to take into account like real world measures. So take away this, this voxel definition. So this is actually the definition here. So that's actually just saying, well, sigma three by three actually in this specific case and if I would now look at this data on this direction and actually it's, it's not correct, it's not anatomically correct anymore. So that's of course one of the things I have to take care of. So therefore we develop this viewer and also of course when you make nice color colored images, you can do all kinds of crazy things with it. And this is just in the background, it just uses array plot to quickly do all this. But yeah, it's convenient to have this to actually look at it. So you can add a legend bar, you can type something, plot titles each Time if you, you don't have to do the code generation over and over. And of course there's also some export stuff. So I can export it like multiple files as animated GIFs or any image format.
Just out of curiosity, what do the numbers corresponding to the colors in this case?
Just arbitrary units because it's just a grayscale image. So I can show you quantitative data a little bit later on that actually shows these numbers actually have meaning. So this is basically raw data so that we get from the scanner. So it's arbitrary scaled. Typically it comes from dicom, which is in a medical imaging standard. So medical device export the data as dicom. Mathematica has default DICOM import export functionality to also get all the metadata that's in there. So then these values are arbitrarily scaled. Typically it's 12 bit or 16 bit integers. And then once we do computation out of it, so these models can for example give water fat fractions in percent. So then all of a sudden these numbers do have value. So then we go from like qualitative data to quantitative data. And that's, that's after we did apply all the models and get really. Then these values will actually. And then therefore color bars. So typically I use grayscale if I look at qualitative data and color bars if I look at quantitative data.
So right now all it's measuring is brightness of image.
Yeah, yeah, yeah. And then let me see if I can get to a different data set. So if we would do. Look at this full data set. So this was one volume of this data set and now I'm looking at all volumes. So we actually do multiple directions of this data. Direction is the wrong word. So we, this is diffusion weighted data, which is actually the sensitivity of the machine is set to diffusion. So basically when we have motion of water molecules, this causes signal attenuation. So we lose signal due to the motion of water. And the amount of signal we lose is actually proportional to the actual underlying diffusion constant. And the fusion constant basically means the amount of random walk particles will do. So that's really on the molecular scale. And when you freeze water, it doesn't move. When you heat it up, it moves violently. So the fusion constant goes up with temperature. But also if, if the fusion is just free and free water, if you drop a drop of ink in there, it will diffuse throughout the entire volume. But if you put something in straws, for example, you have these barriers where water cannot pass through. And then we can actually say something about the directionality of the Diffusion in the tissue. So there's to actually infer that we need multiple measurements with different diffusion weighing strengths, but also different diffusion weighing directions. And with directions, I mean that if we apply the fusion weighing in for example along a muscle fiber or perpendicular to it, we have different contrasts. So this is the same data, but now you can see that it's actually not a 3D data set anymore, but it has slices in one. So that's still going through the data set. But I have an extra dimension to my data. So this is actually the different measurements we do. And you see that the contrast actually changes throughout the measurements. And this is actually different diffusion weighing strengths in different directions. Let me just zoom in a bit on these high diffusion weight images. So you can still see the muscle structure, but you can see the contrast changing with different muscles. That's the information we use in these models. So we sort of get a 3D representation of what the diffusion is actually doing. So if you would look at what the measurements actually is, that's going to be plot. No gradient plot, I think gradient law, yes. Of the. So actually we apply the diffusion weighing in these different directions. So it's like evenly distributed in half a sphere and then with different strength. So the outer shell is the biggest diffusion weighing strength. And then we have varying the number of directions going inward. And we do this on half a sphere. Typically because diffusion is symmetric, we can't really infer direction, positive or negative. So we don't need to do the measurements in the negative direction. And actually so if we want to optimize these experiments actually also build something. It's also really nice to see gradients. No, it's going to be generates gener. So this is actually a tool that we built to actually generate or design these experiments. So let's say I'm going to do a multi shell experiment, what we call it multiple if you want strength. So I can give in the values here and actually can generate these, these things. So this is based on static propulsion of particles on a sphere. And then we have a different shells that are all equally spaced in half a sphere and they also don't overlap. So they always have like unique directional information. Of course you can also tweak this a bit. So they don't really optimize a single shell, but everything is optimized. But each single shell is not really optimized. So yes, that's done. So this is something we typically don't want. Or we can go the all the way the other direction where each shell on its Own is completely optimized, but there's no crosstalk between. So this is all. So this demonstration is basically built for teaching purposes, but also to do experimental design. And of course there's different ways of visualizing this. You can also fold it out on grid. So actually you fold out the sphere. So if you do also with map of the world. Right. So you have a sphere and you can map it out in a Cartesian grid.
You mentioned two things I'm curious about. One is that when you're talking about optimization, what are some different things that you might be looking for that different strategies would be optimal for? So for example, different things that you're trying to spot while doing imaging.
Yeah, so if we talk about for example, diffusion imaging specifically, then we can design experiments that's optimized to do quantitative analysis of the diffusion properties. For example, look at what's the mean diffusion inside a tissue. So let's say if a healthy cell has a membrane, if, if you get disease, the membrane falls apart, so the fusion get more free. And it's a tropic aspect to this diffusion signal. So it's not equal in all directions. Like I said, along the muscle fiber we can have high diffusion and perpendicular to its low. So look at the ratio of the diffusion, so called fractional anestropy. So we have an anisotropic part of the signal. So we can also quantify that and that's what we call F8. And in that case, so you can also imagine that if cells start to get smaller, then there's more restriction perpendicular to it. So these kinds of things we typically look at. We also can do something called fiber tractography, where we actually can generate a 3D representation of muscle architecture. I'll show you an example later on of that.
Looking forward to it.
You can design these experiments to be sensitive, different aspects.
All of this sounds extremely precise. You mentioned error measurements and figuring that out. I guess I was wondering what are sources of errors when you've got a machine that can detect fusion of water across the cell membrane? Like what, what is the.
Too many. So one of the main things. So we typically talk about two kinds of errors. So one is physiological. So people move regrettably.
Sure, sure.
So you have motion, so macroscopic motion, but also pulsation. For example, your heart pumps blood to cells to vessels. So there's those pulsate. But also we're dealing with a quite sensitive measurement equipment. So also there's. There's thermal or electronic noise in the measurement. So you can imagine that if we try to get to too high of a resolution, there's enough signal in these imaging location. So it's the same with like taking a picture in a well lit environment or in a at night. So we get thermal noise and physiological noise. So those are the two main things that we look at and those the origins of the thermal noise can be loads of things. So we also, before we start doing, applying the model, we have to do a lot of signal processing, pre processing typically we call. So we try to enhance our data. I have something here that would be maybe nice to show. Let me just see if I load this.
I was just going to say for the audience here, while you're loading this up, this is showing one way that you can take this noisy initial data and then clean it up. Is that a fair summary?
Yeah, yeah. So this is. So I thought I had a MX file loaded, but it can't find it. So I'll rerun it. So this is basically an algorithm that can actually get rid of noise in data. So we're quite used to this with when we look at for example like if you look at the old CSI shows like enhance this, this blurry image or you get these, which is all.
Nonsense usually when they're.
There is a fundamental. So you can do that. So there's now images that can upscale resolution of pictures without you even seeing it. So when you look at technology on your camera that actually takes pictures at night, these images look crisp and they only look 10 years ago. It would be a noisy, noisy thing.
Right. And when there was a noisy image, there would be pretty much nothing you could do about it.
But yeah, so there are techniques actually and because we take, we're not taking the same image over and over, but we take the image so the anatomy stays the same and we have sort of changing signal over time and there needs to be some structure to it. So in this specific case I'm actually using something based on principal component analysis to actually decompose the signal and recompose the signal and then hopefully only keep the signal part and get rid of the noise part. So now it's actually running real time. So for this I use. So the nice thing about.
But.
But for me using Mathematica is that especially when first trying stuff, you can do really rapid prototyping because almost everything has a Mathematica function nowadays which is already there and typically it does the job. But because it can handle so many different variants of the data, it's typically not the most optimized. So the core Algorithm will be optimized. So there's a lot of tricks to actually get to this core algorithm in a lot of cases to actually make things quick. But when you start prototyping, you don't really have to think about it. It's only when you know what you're doing and everything works, you actually want to do something fast. So let's see.
Cool. So it's good for exploration because you never know what direction you're going to need to go in.
Yeah.
So a tool that does only one thing might be missing, something you're going to need.
Yeah. So when I started programming for science. Yeah like I think 2008, 2009, really doing it on a large scale. I think Mathematica 5 was out back then and you had MATLAB and Python was around a bit and then C of course. But then Python was not as advanced as was now. Also mathematical. It's not. But when I started using it for the first time, it's like this can do a lot of things that I don't have to think about. That's what I liked about it. Sort of things grew out of hand a bit and now I'm kind of stuck to it because if I have to recode everything this in a different language, I will be. I need a very long sabbatical to do this.
Makes sense. So you've. You've built something so huge.
Yeah.
And so.
And luckily nowadays it's really easy to, to. To link Python to different programming languages and so with also. And vice versa, different Wolfram language that runs on command line. So I think the integration of different programming languages become so much better over the years. It's actually also not that important what kind of language you're. You're. You're using the only so think. So open Science is now really a hot thing. So my code is open source but Mathematica has paid license so that's sort of like hindering some people and say, oh, Python's completely free. Sure. But nowadays it doesn't have to be. So when you run the Wolfram language kernel, you can also run it from jupyter notebooks. You don't need the Mathematica front end and it's still free. So I think that that actually is nice development to get it more accessible. So actually the example.
Yeah, sorry, go ahead.
All right, so I think the example is now done. So this, these two data sets actually look quite similar, but this one, right, has denoised so we can actually scroll through it and let's look at A low in signal intensity where the noise is a bit more visible.
For the audience. The, the noisy version is on the left and the Denoise is on the right.
Yeah. So let's look at the difference of the two. So it's also some overlay things I have here. So the difference of these two data sets, so there's actually immediately subtracted so we can actually scroll to different volumes and you see that the thing that's removed is actually noise or actually the difference between the two data sets looks like white noise, which is good because.
That'S basically what it is.
Yeah, it should be if everything goes right.
I see. So if you were seeing a structure that looks like muscles or something, you.
Would say, oh, I'm removing signal and not noise. Yeah, yeah. So as you can. So I've built in some others. It's more a hobby project. You can also do some, some fancy checkboard visualizations for example. It's more of like. It doesn't really have a big use case, but it was fun to, to explore, do some overlay where you can just go from left to right. So I've got all these. It actually helps with making images for publications and sometimes you need pretty images for your publication and it's nice to have something that makes you generate a lot of images really quickly without having to code everything. Basically all these things plug into the options of array plots and then it's automatically propagated.
So one thing I'm curious about when you're mentioning doing principal component analysis is that like, I don't know when it was first added to the language, but now I know that there are sort of high level functions for people who want to do principal component analysis. When you first started building this, was, was that added yet? Or is that something that you implemented more low level functions at the time?
And then let me ask for people who might not be familiar, such as me, what defines principal components analysis?
Well, you can represent any vector into sort of, or set of vectors into sort of a basis space. You can do same as dimensional reduction. You actually try to project your, your data space onto a lower dimensional representation of that.
Huh.
And so typically, so you have the typical eigensystem decomposition where you have eigenvalues, eigenvectors, principal component independent components, all different ways of actually splitting the signal into its basis vectors and the weights of these vectors. Now you can say, well, these are the main components actually build the signal and the other ones actually are so low in amplitude that I can actually remove them and then we make the signal from that and actually for this I think I just use the default. Well we can actually look at it. I have no clue what kind of function I'm actually so when I do development I say well I use Eclipse. So this is I know in denoising tools and it's called PCA denoising.
So and it's quite hard to read a lot of these details.
I think I can zoom in. What's a good question? Can I zoom in here? Window appearance soon? Sure. I have no clue. Let me just open in Mathematica.
Yeah if you're an audience member wondering what goes into building a large tool set like this, you're getting a great view of what this looks like and we'll have some more detailed questions and if you as an audience member have any questions about tips and tricks for building a large set of integrated tools that complete some high level functionality like doing qmri, you know, do put in questions into the chat.
We have an interesting question from the audience about errors connected to that. But I want to wrap this up here before we touch on that.
Now it should be opening hopefully in. So it's all from language files but so for. For like when you use GitHub for code sharing and that's kind of things then actually the. Why isn't this opening? Let me do it differently. Just do it the old fashioned way. Denoise tools. There we go. So this is actually the same file but then run it in the Wolfram language front end and then it always gives this weird message where I have no clue how to fix it but it always doesn't. So we have to go to. So I work quite structured in these kinds of things. So. So these things you can see in Mathematica I don't really see here. Well you see them being inserted here but they don't really have value. But for here it's quite nice. So functions always have users notes all structured and then we go to the correct1. So PCA Denoise and then somewhere here there should be calling to the principal components it in somewhere.
This is also you're seeing live the advantage of having high level functions for things because you know you can do this part once and then the high level functions sort of take care of that.
Yeah, let's see. No, I've optimized this with low level functions. It's not doing the principal component and I'm not doing this. So it's actually.
Yeah, I was curious.
Yeah so I'm actually doing so but yeah this is Sort of how I build up my toolboxes in general. So everything is highly organized. All the functions have usage code and I try to also be quite structured with adding syntax information to everything so I can actually have user input so the user actually gets feedback like are you using the correct number of arguments? Those kinds of things. So that's sort of the.
That's a wonderful thing. I, I love how much that is built into our built in functions. So I'm so glad that it's a tool that when people are making their own functions, their own tools, they'll be able.
Yeah, it's going a long way over the years. I think that, that it's getting more user friendly. A lot of things I learned the hard way of just trying and seeing some small examples here and there on the forum and stuff like that. So it has evolved over the years. I think that especially loading of the toolbox and getting all the context right because I've now many, many different. So if you zoom in a bit here. So these are all the different things that work together and each of these scripts has to be aware of the context of the others to actually work because there will be functions in here that are called here and here and.
Makes sense, makes sense.
Was a nice learning curve over the years. So this is of course the main loader that actually loads everything but it's actually, it's not just calling get toolbox but it's also removing all context from all the function names that are actually in the toolbox. So it destroys all previous made definitions that might interfere with my toolbox.
Oh, that makes sense.
Yeah, Reruns everything. It loads the documentation. It actually has also some feedback if you want to load it. You actually see when I'm debugging or things are actually going wrong, I can actually do something that's like this. So I verbose loading. So you can actually define verbose true and then it will load. Giving you a lot of feedback of what's actually happening.
Oh cool.
You mentioned teaching earlier and so when you're showing this functionality, I don't know if you want to bring up that point now or if you want to save it until after you've shown some more of the functionality that's in this toolbox. But the angle of teaching is something that I think is really important and a lot of people who are considering going into various fields, people who might be interested in medical imaging and saying oh wow, this, this is amazing technology. I want to use this. The teaching aspects I think are going to be Particularly relevant for them. So I just wanted to put a pin in that part of the conversation that whenever you feel appropriate to sort of talk about, you know, using tools like teaching.
Yeah, I think this will actually when a lot of the images and concepts I show in presentations while teaching are actually generated by Mathematica. But I typically tell students you program in every environment that you like because once, you know, coding in a language, it's quite easy to learn coding in a different language. It's more about the logic behind coding than actually using what kind of language.
We like to say grammar.
It's easy sometimes.
Yeah.
So but in the end if they do projects with me. Yeah, they have to use this.
Oh yeah.
Just be for these kinds of like demonstration notebooks actually you can highlight or show what's going on with coding with simple examples I think is quite important. So this notebook is also made specifically for that. So it shows low level functionality just as documentation does in the Wolfram language to actually show and highlight what's possible. But if you want to do something new or special with it, of course you have to think for yourself. So in that case I use this a lot to show them like I'm doing with you guys now to show demonstration of what the capabilities are. And because with education visualization is also really important. So you need like sometimes to visualize processes and I think also that has come a long way in generating movies animations with manipulate it's quite easy to show stuff happening. So for example, I think one of the things, things that is very specific to this Dixon technique is I think optimize Dixon Echo this one. Yeah, it's quite critical to show but actually here we need to optimize two parameters and it does different things with. With the signal and how it goes. So this can actually be quite helpful to. To show what's going on. So these kinds of things I've also built over the years actually one for one help me optimize my experiments but also to show actually what's going on. So you can. And then of course these, these are things typically that hobby projects that go out of hand. So I build something simple and then because it's fun to build, I go crazy with it. Yeah. So these kinds of things. Yeah, they help a lot in that sense. So yeah, this is one of the applications and maybe what's nice also show is quickly zoom out a bit overview. So this was mostly so I'll show some something else about the fusion later on but some other things that I do a lot is of course, simulations to actually show the accuracy of the models. So that's also something built into this.
That's fantastic as a feature.
Yeah. So the modeling, because the symbolic nature of Automatica, it's quite easy to build forward and inverse model. So basically you write the same code once or write code once and then are you poured into Find Fit or you pour it into a table and you generate the signal with it. So that's sort of nice. I think it's also nice to show. So this is something also quite unique to Amar. So Amar, I've been showing magnitude images, as we call them, so grayscale images, but actually the Mr. Signal is a complex number, so we measure complex value data. So the data we get out of it has magnitude and phase. So the face also holds information and face typically scale between minus PI and plus PI and that actually can get wrapped. So if you have a wrong settings, you get these phase wraps. And this is some things that I really like to do is like see what kind of algorithms are out there to do this efficiently. I. I recently found that there's a research function that does phase unwrapping in a 1DK. So if I would try to unwrap all these phase reps and this noisy data using a research function. So this is a research function that does it and then we can visualize what actually is happening. Let's see. Yeah, so you can see this is the things I showed before and there are. This is the ground truth that it should look like. And then here you see the results. So in 1D does it great, but in 2D and 3D, even for medical data, it becomes a quite more challenging thing. So there's a lot of literature out there, really fundamental algorithmic things to do with these kinds of data sets. And for a lot of Mr. Applications, phase mapping is quite important. So we built some functions actually do a better job in this. So actually you can get back to this really nice visualization. This is something I do use in teaching a lot. So when the nice thing is that you can just show the images in the notebook. So this is something that we use a lot. Let me just quickly. I don't know why WhatsApp is not muted.
Talking about what it should be versus what it is. There was a question a little bit ago in the chat from someone and of course I understand this could have a lot of different answers based on very specific circumstances, but it said, is there a probabilistic chance of identifying false positive positives in these scans?
And then A follow up question might be sort of what tools do you use as a professional to sort of test for that and to try to not have that happen.
Yeah, so I'm doing preclinical research so really showing or developing new techniques that might work in the future. And of course when you do clinical translation, false positives and false negatives, I think even worse. So yeah, you're not diagnosed with it. That's, that's worse than being like positively identified with a disease in hindsight. Sorry, we were wrong.
Sure.
Yeah, yeah, that's, that's, that's a hot topic. But that's more statistics thing. So we try to understand what's the variability of the measurement we do. So what's the predictive value of it? And if we want to prove for example that a patient group A is different than patient group B, we need to prove that statistically first. So we do large group experiments, so tens, even hundreds of patients to show actually that there's the ability to distinguish people from healthy or diseased. And then to actually make it relevant for a single patient you need sort of cut off value. So like above this threshold value, if your cholesterol is above this value, you're high risk of those kinds of things. But that's more like epidemiology statistics. So we typically. So my research mainly focused on developing the machine itself, the code that runs on the machine and the analysis methods that come with it. So if we design a new measurement technique, we want to sort of give people the indication this might be possible and do some clinical validation of course, myself as well. And then hopefully the next step is working with doctors in the hospital to actually translate it to patients in the clinic. But that takes decades.
Sometimes that makes sense. So you can talk about how accurate or how prone to inaccuracy the measurement is. But in terms of whether or not that is especially likely to create a false positive, probably the best measure of that would be try and see where you find it or don't and count how many of those were false.
Yeah, yeah. So that, that's so. So I work in academic hospital, but on the engineering side and we work in large multilisal team, so we have different skill sets. We have mathematicians, physicists, engineers, doctors, all working together. So of course when we start moving things toward patients or testing things on patients, we need also doctors to work with us. And so it's very different if you set up a pilot study or something study to say how prove that something really works. That's the, the scale of that, so if I test something, I test on five subjects, maybe 10 to show proof of principle. But if you move to larger studies, so some, some of these bigger studies can include thousands, maybe tens of thousands of patients worldwide. So those are multi year studies. So I just started a new study myself and I'm just looking at, at healthy people to actually understand what defines the variability in muscles when we measure with these techniques. Just is it age, gender, is it the amount of exercise you do, A bodybuilder or long distance runner? They're different. You can see it. And we have, our measurements actually show these differences. So we can see that neuromuscular patient is different than a healthy one. We don't need these techniques for that. So we, but we do need techniques to evaluate medication, for example. So if we want to start giving patients medication, is this medication working? It's expensive. You don't want to wait for five years to see if things get worse or not. You want to see very small changes in the early stage. And therefore we're developing more of these techniques. So that, that's sort of what I'm doing now. So for example, now I'm, I'm starting study with 250 subjects but that before I even finish with data acquisition, I'm two years in and then I have to still analyze it. So that, that's sort of a slow process. So therefore. Yeah, it's. But I think it's, it's in most scientific fields, right. So you have breakthrough moments like everything's working but then the news picks up on it. But they never say well it's 40 years in the making or something like that. So that's right. So I think that's, that's sort of. There was a nice thing about science actually that small incremental steps and understanding.
Yeah. We have another audience question related to statistics if we want to briefly go into that. So the question was what do you use for doing circular statistics in your data analysis? Is there particular functions that you find useful or do you have any tips for doing that?
So for like generating and simulating data, I used built in functions from Mathematica. So there's a huge large number of statistical distributions available for statistical analysis typically. So there is some Nova toolboxes and some basic T test stuff going on. But the more advanced stuff. So there are. So you can build your own linear regression model in Mathematica, but there are software tools better equipped for that. So R as a programming language has purposely been built for statistics and it's also doing R is very good at what it does and you can interface R with Mathematica or vice versa. There's dedicated statistical software packages written like spss. So when. When you use statistics you typically have this Excel sheet and you just want to crunch the numbers and then mathematically for me is slightly too cumbersome. I just want to click some function options and do that thing do everything. So it would be all possible Mathematica. But so mostly I use R and SPSS for that.
As a follow up question. So you like to use lots of different tool sets for doing what you do. So I know it's possible that one can run R code from within Mathematica session. Is this what you do or do you typically sort of run one thing, have it produce a result and then feed the result to another language or what's your flow for that? Usually.
Application. Okay, it really depends. So sometimes I use the inline stuff, but mostly so data analysis and then preparing the data for analysis. It's like sort of an endpoint where you could now have my Excel sheet or now if my export from Automatica to whatever format I want and I start doing the last parts this analysis and then for plotting. So I. It's typically more convenient to split it up. There are some tools that I. I've pre compiled as executables and I run from automatic language and then basically from. In mathematical language I run on command line certain commands to call tools for example to do image registration. I think that's also an example here. So when I say image registration I mean that's that the other sort of noise is of course civic motion. Just find good example of that go up. So yeah, here. So this is something that image registration is basically aligning two images that they match. I think there's like this function image stitch that can do like these nice spherical things and whatnot. So that principle is the same for a lot of medical data. If you want to get rid of motion you perform registration and the functionality Mathematica is nice, but it's not good enough for the applications we do. So for example, if I've. So I loaded the same data set again, but now I've taken one leg out of it. And this is the original and this one I changed the orientation off. This would be a large movement and I want to realign these two volumes.
Am I right in understanding this is a vertical orientation?
Yeah. So this is sort of. This is the transfer. So the cross sectional area. If I go through it, you can actually see that I scaled stretch Skewed. I really warped the data set to a different orientation. This is something that we want to do. So for this example I call an external executable. So there's a huge scientific team that's been optimizing registration algorithms for all kinds of medical purposes. So I would be like. Would be a ways not to use all that knowledge. Right. So that's. We have a nice executable that actually does that. So I call that with this register data function. So let me zoom in again. So this register data function and actually that, that, that can actually we'll call this executable. It will export some stuff to attempt directory and it will run the executable point of September if you run it there. And once everything's done, I load everything in again and then hopefully this data set will be now aligned. So now you can see this, these two are aligned. So I can see how good the alignment is using. Oh, this is the wrong one. I have to use this one. No, this was. Which way is it?
Data s. Data s. There it is.
Yeah.
So now these two are hopefully almost aligned. So you see some. That's on the edges, but they're pretty well aligned. Of course when that was cut off and actually we can see how well it did. So we can actually also show. So these were the rotation, translation, scale and skew parameters I impose on the data. And this is what I get out of the algorithm. So here I really use external toolboxes that are highly optimized to a specific thing, but being called PNM automatica environment. So I don't have to switch to a different environment to the registration. And I go back, which allows me actually to script quite complicated pipelines without leaving atka. So when we do data. So I. It's been evolving over the years. So by now I have this one script that I can run on my data sets that I acquire. So I go to the scanner, acquire some data, put it on a specific folder in the server, I turn on my notebook as I run scripts and then I wait for a few hours and everything's processed. And that's all done from atomat. Yeah, but then, yeah, that's really high level of optimization. And of course then you still have to check everything, if everything went correctly, crash and those kinds of things. Because I think especially with fitting data to every image point. So when I say we do like forward modeling, I do this for each image point in the data set. So when you have like 100 by 100 by 100 data points, that's to maybe sometimes a million evaluations for one data set. So it's not just fitting one function with Find Fit running that same function 1 million times. So there the chance of you getting numerical errors or unexpected things happening is quite high. And especially then when you run over hundreds of data sets, you will always get this one exception that will crush the entire system and you have no clue why. And then you have to to find the specific voxeling where it happens and they have this rounding error that happens when you do optimization and then yeah, everything goes to. But that's sort of the. So yeah.
Oh, sorry.
No, go ahead, go ahead.
Hearing about how much more complicated this has gotten over years because you've been adding features to is great to hear because I love how much the Wolfram language is backwards compatible that when something works it should continue. It made me think though has have changes to MRI technology made you need to go back and change any of your tools to. To fit the new sort of.
Oh, definitely, definitely. So science is evolving constantly. So I remember when I did my first data set, I was looking at forearm muscles. The acquisition time of the data set was around 20 million 20 minutes. And now I do the same data acquisition in three minutes. So the scanner has become better. We have new acceleration techniques on the scanner itself. We don't have to acquire the full data set. We can acquire compressed versions of the data and then uncompress it later on to get the full images again. On that side a lot of things have changed. So we can get more data in the same amount of time if you want to turn it around. So if you still have the same amount of time, you can actually get more data. But also the models we use to process and analyze the data. So for example, the noise removal. I think I'm not the sixth iteration of that technique. So I've used different versions over the years. So I still have the old functions that get the things I did in the past. But yeah, if you see somebody publishing a new article with like a new method, you need yeah. Either find how to implement it to find their code and use that or implement it yourself. So that, yeah, that's constantly evolving. But so for my toolbox I never guarantee backward compatibility because I think from a. From a business point of view it's very smart to do it. But from a research point of view it's too much of a hassle. The same with like error catching and stuff like that. I can spend a lot of time doing that, but just. Yeah, that's not my My main aim.
Your goal is that it works now techniques and technology that you have and.
The moment it goes to clinic or to applications or to, to vendors to imply to incorporate in their MRI machines, they're not going to use Mathematic for that. That's going to be highly optimized code written in C or whatever. So yeah, so the translation step for me is not that important.
Gotcha.
The moment new version of Mathematic comes out, I typically run this entire demonstration notebook to see if the main functionality is maintained, which sometimes is, sometimes isn't. Everybody makes mistakes, sometimes it's my mistake. Sometimes some things are thought to be backwards compatible or not, but yeah, then typically it's solved in a new version. If you just make a nice post in the forum, for example, and like, hey, something unexpected is happening, is it me misunderstanding the new functionality or is it you guys messing something up? They're typically quite honest in saying, ah, we might have missed something which is quite logical and then most of the times actually finished quite, quite quickly.
Makes sense. Makes sense. I mean I, I know that we can compile our code so that it runs in a similar C style efficient sort of way where the computer is figuring out what is doing what, but it makes sense. It's, it's a good thing that people who are working in other coding languages will have a use for everything you're discovering here, even if they don't speak the language you're using.
Yeah, I think that's. And nowadays like coding, like when you know how to do something, it's easy, right? It's always in hindsight everything's easy. So once you know the algorithm then it's easy to optimize it. Right? So code optimization and writing optimal algorithms is a complete field of science on its own. So I don't really want to touch that. So I really like it that there's like highly optimized versions of most of the functions in Mathematica and also don't have to like download certain packages to actually edit information to most of the time. So of course some people have written amazing packages that do stuff that, that Mathematica doesn't have. And now with the function repository and the packlet repository, these things get more visible because in the past it would be sort of non, non findable. It's like you have, you have like nice Python repositories online and stuff like that and where people can share the code. And now there's this infrastructure coming that also mathematically users have this platform to share stuff which is actually quite nice. And you can actually see that there's a lot of interesting stuff happening there. So, yeah, that's, I think, good for development. And then I did test some of my notebooks from like 10 years ago, and they still run most of the time. That's cool.
I have a variety of questions, but I also want to be conscious of your time and make sure that you get a chance to show off any other functionality that you think is really. You're really excited for people to know about that's there. And so I'll.
No, I didn't go away with a question.
One of the questions that I have actually is that when you're creating functionality like this, that has a lot of graphic user interfaces. So do you, generally speaking, what's your design process there? Do you have a particular interface in mind from the beginning that you're like, oh, this would be really nice if I could code this up? And so the picture of the finished process is sort of existing in your mind first? Or is this something that you. You build over iterations when you're prototyping things? Or how. Maybe a little bit of both. How does that usually go for you?
Mostly iterations, typically I'm starting with like, I want to plot a certain function, so I type in the function and I make a plot out of it. And it's like, what's the dependency of this parameter? And I put a small manipulator around it and then just one slider for this one parameter to get some more intuitive feeling about it.
Then.
It gets out of hand. In general, I try to not write too much graphical user interfaces because they're quite hard work to make work. So sure. So the simple cases are quite easy. So with. With the simple manipulate and a few things. So the one I showed with the. So the. This one. So this is the GUI version of this. This is basically just saying, I want 12 just go, this is how I use it. And all that fancy visualization is nice for demonstration purposes, but it becomes slow. So, yeah, it's actually quite a lot of work. And I actually tried to make this GUI work, for example, in Cloud, but it's like you need so many dependent functions and visualization stuff and it's all. So I do like building them because it's like, it's nice to have something visual and tangible, but most of the main core things don't have guis in there because it's a skill on its own. And also when people can press buttons, they start to press all the buttons.
Right, yes, yes.
The order in which you press buttons becomes important and you have to do error catching and then you have to be the monkey. Yes, right. If you push everything in simultaneously, Mathematica should not crash. So yeah, I like building them, but for true function, it's more demonstration and visualization purposes than really daily use. If I can script encode it, I will script encode it. And if I press a button, life's too short to press buttons, I typically say.
Exactly.
I wanted to ask. Oh, oh, sorry John, did you have a follow up there?
Yeah, it was going to be about the larger scale designing pipelines. So if you had a question that's about this topic, maybe we could do this one and then talk about the sort of designing the pipelines that you were talking about before.
My question is on another topic. So.
Okay, so yeah, so my follow up question then is that so you know, the visualization is nice for teaching, for sort of understanding what's going on. But as you say, life's too short to do this when you're, when you're dealing with huge, huge data sets. So what would your tips and tricks be for designing a pipeline? Like you're talking about where you have this data nowadays, it can be compressed, but originally it wasn't even when it was coming off the device, if I was hearing correctly. And then you want to do these analysis steps and then you want to have sort of an analyzed product that is being sent off to someone that then they can use to make professional decisions about. So how do you, what, what tips would you have? How do you think about that process? What do you use to do that when you're thinking about designing these pipelines?
Yeah, so it's, it's the first step. What a lot of people in my opinion do wrong is this. They start, they have not really a clear picture in our head and you start coding and then it becomes this like beast of code that nobody really understands the logic anymore.
They don't have a plan.
You have to have a plan, a really thought out plan and then cut it up in small pieces. So which are the steps? I have to go from A to B and then make. So like what I'm showing here. So when I, for example with the fusion data import Denoise register, then do model fitting. So the tensor fitting that we use here, so that's actually one of the steps here is fitting the tensor itself, then doing quantitative analysis with tensor and then maybe even do muscle segmentation and analysis. So all these steps are like chunks and together they form this big beast of a script that cannot do everything. But let's say I just wanted to have a slightly different denoising method. I can just swap out one function and really have a clear picture in your mind which steps you have to go through. And if it feels becomes too big or too chunky, then cut it up in smaller projects, which can actually also easier debug so you can test these things in isolation.
So this is the computational thinking that we were kind of talking about earlier. And so when you're thinking about something like this, if I'm hearing you think about it at a high level and then as you were saying before, you worry about some of the optimization details of is it as fast as it can possibly be for doing this 10 trillion times?
Right.
That's a different question.
Yeah, so typically when I have like a new function that I want to try out, I just build it, make it work. Sometimes it's useful and I keep using it. And then it starts to crash once in a while. Like why is this, in this specific exception going to crash? And then I'll solve the issue. Yeah, I'm using it over and over and all of a sudden I use it in every pipeline. It's like now I'm waiting two minutes for this computation. Each time I have to do it a few hundred times. Now it might be an interesting point to say, well, can I make it twice as fast? And then all of a sudden I, I'll save hours. But. But if I spent hours making something 10 faster, it's not worth the time because computers do things on their own perfectly fine. And I'll just wait over the weekend. But if I have to, like, let's say I want to process these 100 data sets I just acquired and it takes four hours per data sets, I'm looking at days. And then if I can make something twice as fast, it's only a day. So then all of a sudden it becomes useful to actually do code optimization a bit so that typically my code goes up to a lot of iterations. So something useful. Am I going to use it a lot? Some of these codes are written five, ten years ago. Once in a while I need it. There's no reason to optimize it. So this, this large scale, I don't think you can start something like with. So you have to have the envision. Yeah, but, but everything's built piece by piece. So if you want to try to do everything at once, it will never work. You have to make it manageable. Small chunks where's the gain you can get instead of trying to do it. So you can easily get stuck in optimizing a function for days because it's fun to get this puzzle working and then you've lost a week of work and then you gain 10% of speed and it's like, was it really worth it? So sometimes you have to also be sort of realistic in that sense.
Yeah. We had another audience comment about being interested to learn more about this tool for MRI analysis. And yes, we will have links to the presentation notebooks available after the stream is live on the replay. You'll definitely. Excuse me, you'll definitely be able to see that. And so I wanted to take the opportunity when we had that comment. What are the sorts of things that come up a lot in QMRI are functionality that's within this tool set that you've built.
So basically all these applications are basically loading data, processing data, generating pictures and quantitative. That's the main pipeline. So most of the functionality is all related to one of these steps. So. And then of course there's a lot of like things, basic things that I need. So most of it's like designed around that. But there's some like basic functionality they've added to the language that's are really needed to these large scale things that are actually not in the language. So let me see if I can find some explanations about that. So very simple operations. So yeah, for example here let's generate some data. So the. So very simple things like operations without ignoring zeros. That sounds quite trivial. So mathematics can handle complex infinity, infinity and everything else. But the moment you're working with numeric arrays, they're typically packed arrays in the Wolfram language. And you can do really fast numerical computational that if one of these values 1 million pixels you have in your data set becomes an integer or a complex infinity, a lot of these functions become much slower.
Sure. Right. Because you're using exact rather than machine precision at that point. Yeah. Okay.
Yeah. So. So a lot of these functionalities that I've added, for example is like mean and median without with ignoring zeros, taking the exponent and a log of things that actually don't generate. So this. So for me, log. So this would not be allowed. So just give zero. So zero is background. Voxel doesn't contain information. I don't care about those locations. If this happens, I can put infinity, complex infinity. But a zero for me is just, just as fine. So these are quite simple things that I can actually do. What's another thing that I use a lot is. Yeah, so this is something I use a lot. So when you have a vector, you have multiplicative function. Rotate left, rotate right. So you have a vector rotate right three times. So this is sort of rotating dimensions of data. So this dimension is 25 by 160. 160. And I said rotate dimensions left. It actually does. So this is a transpose. So it would be transpose 3, 1, 2. That's the same as rotating the dimensions. But everything about like, okay, which transpose do I need now I can just say, well rotate dimensions left three times, for example two times. And I get that three times. I would get back to the original dimension again, reverse dimension. So it's XYZ becomes CY X. So these kinds of very simple basic data operations I've also put into this.
So yeah, that's very handy independent of QMRI work. That's awesome.
Yeah. So this for another example is for example when you have singleton dimensions, you want to get rid of them. So I think multiplies is a nice function. Squeeze. So I made squeeze for vectorizing stuff. So Mathematica is really good in like not caring about dimensionality and you say map over whatever dimension. But in many specific cases vectorizing your data is much more computational beneficial. You only have to loop over one dimension, keep track of what's what. Also for example, we have a lot of background voxels you don't want to loop over to do the check. Do I need this? You say well get me all the data that's in this. So the this data set, put it into a vector and then you have like a one dimensional vector actually where you can just always loop over the first dimension and then you have to vector the original dimensions and the coordinates that belong to it and you can make back the original data set. So this makes it really simple for example to do logical operators like if value is first value 0, then delete the coordinates and only process the coordinates that are developing. So in these, these kinds of like higher level things are very specific to working with numeric arrays which actually Mathematica is not. It can do it, but it's not designed to do it right. So there's a lot of languages actually to designed to handle large numerical arrays and Mathematica you have to really force Mathematica think numerical. But default says well no, I want to do symbolic. No, no, no, you're going to do things. Everything has to run numerical now. So there's a lot of things that I use in my functions to Actually not allow any symbolic values in these arrays always. So I think most of my functions start with make numerical 2 packed array. Remove symbolic values.
Very cool.
Numeric Q. Stop. Like how you're not giving me numeric array.
Right, Right.
Yeah.
This is one of the first comparing.
Apples and oranges here.
Yeah, this is one of definitely one of the first speed tips that we, we always want people to know is that if you think something is going slower than it should, make sure that you're actually working numerically rather than with. With exact values because that, that will be a big difference.
Yeah. Here you see it. So the signal goes in, it's like numeric signal.
First step is. Yep.
Because of course it's easy to make an integer or something like that. So you can test it. For example, if you have a big array, you just generate a big array with random numbers, do transpose round and then change the first value to an integer and see what happens. So that's actually. Well, even with these low level computations, the moment something symbolic happens in this array, it handles it just as fine. But if you really want speed and in general you don't notice it like for most of the things you do, you do once. But when you start looping over huge data sets over millions of voxels, then the difference between a millisecond or 10 milliseconds makes a huge difference because it's a vector. So when you fit a function and this function fit takes a 1 millisecond I'm happy. But if it takes 10 milliseconds I'm not happy because that's the difference between a day and one and a half weeks, that's a factor 10. So that's sort of then, then, then this really. So then speed optimization. So I use compile a lot. So not the new C compiler framework, but the old fashioned compile as a list. So I have this function here, very powerful function. Yeah, compilable. What's it called?
Possibly compiled function.
I saw it in the list of ones that you displayed at the very beginning. The exact name is. Yeah, there we are.
So this is all the functions that, that can be called by the compile function that actually will actually speed up. So you can put everything you want in compile, but if it's not in this list, it doesn't really make sense to put it into this especially.
Well for.
So these, these, these. I think this. I found this code online somewhere you can actually exchange per version, but this actually runs something that actually gets everything that's in this compile list. So like random real or log or stuff like that, that can actually be sped up a lot by putting it into compile and compile can be made listable on any dimension. So that's nice. So the normal listable function in Mathematica native is only going to last dimension always. So you do it on numerical values and these actually can actually be put into compile. So this typically I take a look at like am I using this function heavily that's in this list. So then I can put it into comp function to make that core part quicker.
I know we've got about 15 minutes left before a pretty hard out for you. So I wanted to ask, you mentioned some 3D functionality and I was wondering you think of MRIs especially as looking inside of things. So I wondered what sort of 3D results do you get that are not just the surface level but actually yeah.
So it would be the nice closure for this, I think. So I'm talking about model fitting. So this diffusion signal, we fit a two dimensional tensor, so tensor to this signal. So that's basically an ellipsoid in 3D space. And this ellipsoid actually aligns with the underlying tissue properties ellipsoid. The signal can actually be quantitatively described. So you can actually look at the. So for example when we do this, so we can actually look at how spherical is it, how elongated is it. So you can get these quantitative parameter maps and I'm going to switch to something more quantitative. So now we're actually looking at quantitative values. So where zero is not having this value. So here we go from linear to planar to spherical. So the stencil shape within muscle is mostly spherical, but does have a planar component and mostly a linear component to it. So this linear component is actually most interesting one because if this ellipsoid aligns with the tissue, I think I have on the.
Form.
So let me just do things simultaneously here. Meanwhile I'm going to run something here.
Fiber tractography.
Yeah, that's.
That sounds interesting.
So I think I have something better explaining it. Here. So I made a post on it a while ago on the. This actually explains more. So this is in this case for brain. So this is what we see here. Now it's not the muscle anymore. So for each location you can get this nice candy shape. So these are the tensors I was talking about. And then the main direction of this tensor actually is sort of a small line and then you basically play connect dots. So you get a vector field and you perform interpolation for integration of this vector field. And from integration vector fields, you get streamlines. Oh, my goodness. I think it's a streamlined plot. So here we're actually visualizing the main white matter pathways in the human brain with this technique. So I've also something that, that's doing that in muscle.
So what does white matter mean?
I, I oh, sorry. Yeah. So our brain is composed of different structures. So we have this, if you look at the outside, sort of this folded, blobby space, and outside with the cortex, which is called gray matter. Right. Where all the processing happens. And then there's pathways running from one location right to the other. So that's actually white matter. That's the wiring of our brain. And it really runs in the core of our brain. So that's actually has neurons connecting one part of the brain to the other.
Oh, my goodness.
And that's highly anisotropic. And therefore we can actually visualize these neural neurological pathways and actually say, well, this part of the brain is connected to this part of the brain, for example.
Oh, my goodness.
And then these colors actually have meaning because blue goes up, down, red goes left, right, and green goes back, back and forth. So it is the same thing we can do for, for muscle. So let me just show the same data set again. This and this. So now actually we have this tensor spectrum field derived from tensors for this lower leg and apply the fiber cryptography. So this is one of these functions that did optimize a lot. So now it's going seeding 50,000 random voxels in this data set. And from each of these locations, it will do this following the vector field. So does this, this interpolation of this vector field, but then 50,000 times, and it also checks if it needs to continue. So, for example, if the curvature becomes too high, it stops.
Are we still tracking neurons here, or.
Is it now we're doing muscle fibers. So I'm doing the lower leg muscle fibers in this specific case.
Right. I remembered you saying with the lower leg, but I was wondering, are we tracking neurons?
There's nerves in there as well, of course, because the signal from the brain goes through the spinal cords to your muscles. Your muscles are innervated by nerves. So there's also nerves running in your muscle tissue. So we did some experiments on that as well. So you can actually visualize peripheral nerves as well. So now it is actually. So here I do care about time. So it's a. Well, this took 53 seconds. I started 50,000, 24,000. They were valid. This is the average length I generate with it. So this is sort of something that actually gets it. And this has been, let me see. Then we need to go to, I'm going to filter it a bit and then we're going to select some specific tracts. So then if I look at the tracks and I'm going to plot 5,000 of these, 24,000 valid ones. So these are all lines in 3D. So here again dimensionality and size actually matters because what is the color function.
Showing in this particular example?
So it's the same as in the brain. So blue is up, down and more muscle fibers actually run up down the leg, most of them because they have to contract. For example you tilt your foot like this, these muscle fibers contracts have to pull this way and therefore they all run in this direction. So this is again a small part of the calf. You can see the, the hole here where the bones are muscle fibers attached to the bone. And then internal structures of each muscle is different. So here we can clearly see for example that we have called a biped muscle. So that's internal. This is actually Achilles tendon running in the middle here. So Soleus, let me change this to method tube. This was a struggle to get working in quite okay speeds because the pre computation this takes a while and rendering is actually quite good now. But also hopefully it won't crash. Probably should have lowered the 5,000 a bit. These things were also.
It's good to live dangerously.
Yeah, so we're living on the edge, but we're also getting to. Yeah, there we go.
Oh my goodness.
Everything's computed. So now instead of using the, the line hat, I'm using the tube head for graphics 3D doing the same computation, the same visualization. So once it's generated it's actually quite fast. But generating all these objects is actually quite computational intensive. So once the front end has like this, so if you convert this to input form you have this long list of graphics directives and primitives and stuff like that. And the front end has to render it. But once it's there you can actually see more of depth to it. And of course then we can also start filtering the tracks. So let's say we, we only want to look at specific muscles and also change the color coding not from this directionality. So for example like red is left, right, blue is up, down. We can also just color code them for example for length. So now I'm length track coloring 20 to 120 millimeters. So everything lives in world coordinates like anatomically correct, 1 millimeter represents really 1 millimeter in the real world. So that's why. So there's now one specific part of the muscle extracted of the two legs where you can see internal structure. But also now it's color coded that we have some longer fibers here, some shorter fibers in the center example. So this is sort of where we. So of course the getting. So you would get macroscopic architecture of the muscle and this generates pretty pictures which is quite nice for covers of journals and, and pictures and images in publications. Of course we also have the quantitative analysis a bit. So we want to have something like what's the distribution of length, what's the angle of these vectors compared to the bone, for example. So now, so we're now up to this stage and from here we're going to do again quantitative analysis on the things we derive from this. So it's layering functionality on functionality and functionality and functionality. And the nice thing is that once all these things are thoroughly tested, you can just hook them all together. So one of these process scripts will actually be me just calling import process, fit, analyze, do tractography, extract muscles, those steps and then it's a script and then you have something automated. But of course each of these functions individually take takes quite a while.
And so if there is someone who's curious about what that workflow looks like, where would you direct them? Is there a different community post for that or is there maybe a paper that you've written or some particular place that would sort of be a good.
Place to see over the years? I, I would say so it's like science is a continuation, right? So you get new insights. So I improve on my methods. So I write new papers. So I have to do it better. But I think that one of the nice things. So I this in this. So this is a muscle bits tool. So that's another notebook and here actually is this automation. So actually have functions that say well process and that's really a high level function that you say this is the data. Have fun with it. So here you would have muscle bits process for example, this one, this is a huge script that actually says well if you have this type of data and you say process with method diction, then call some logging tools that actually will automatic logs, import some information, do masking, go through face correction, add functions to do fitting dictionary construction. So this is basically all these functions I just mentioned string together into one concise framework and then you can switch to a different processing. So this is actually, so this, this, this, this Collection of functions, actually really high level things that, that, that you only touch when you're like, we want to do something from A to Z so to say. And of course you have to just go to. So I have my. The toolbox itself has a website where I explain a lot of these things. So this is of course.
And I'm hearing you say that it didn't start off this complicated.
No, no, no, no, no, no, no, no. I, I think 10 years ago, I've never seen this happening, becoming so big. I started with five functions and then it became 10 and then became 20.
Just whatever improves it, whatever.
And then before you knew it, you had a pipeline.
Yeah. Now it's 450. And so at some point I think I went, went to like 80 functions. Then I started doing documentation because I actually started like losing track of.
Sure.
What I'm actually at the program five years ago. So this is therefore this, this documentation. So it's actually documentation via the browser. So then I started actually adding documentation to it. I wish I started sooner because then going through 80 functions, figuring out what it did and commenting everything, but now I'm quite, quite, quite concise in that. So when I write a function and I'm added to the toolbox, then I comment the code, so what does the snippets of code do? And then I read the documentation for it and then all these pages are automatically generated from the usage message that you get from the documentation. So basically function as a user's message that uses message, generates a documentation page that you can add to the guide pages and then most of it is automated.
Luckily, there's an old story about a king who loved roosters, wanted to hire an artist to draw just an amazing poster, the picture of the rooster. And the artist said, okay, it'll take me some time. The king said, no problem, absolutely. How long is it going to take? I don't know, I don't know. And so the artist goes off, starts doing his work. King periodically sends someone, say, hey, is it done? The artist keeps saying, I need more time. Another month, another whatever. The king's patient for a while, but eventually just brings his whole army to the door of the artist. Just kicks down the door and says, I want my picture now. The artist says, I got it, hang on. And in five minutes makes the best picture of a rooster the king's ever seen. Now the king's happy, but also mad because it's been so long. That took you five minutes. What's going on? He said, hang on. And the Artist takes him to a back room. Wall to ceiling pictures of roosters. Every surface just stacks and stacks of pictures of roosters. He says it took me years to be able to draw the perfect rooster in five minutes.
Yeah.
And just looking at this tool, it definitely reminds me of that, that it seems like something that's going to be simple. It's actually very complicated under the hood, but in operation it's incredibly efficient, it's incredibly versatile.
That's, that's, that's just skills take time to learn and once you master them, it looks easy. Yeah, never have to. Yeah, I'm still learning every day using mathematics. I still find new functions that I didn't know exists. Sometimes on the community forum I read a post like, does this function exist? Oh, that actually solves a problem. I was doing like a different way. And so never, never stop learning and reading. I think in that sense, because once you're happy with what you can do, you can always improve on it. And, and I think the same with science. If you stop being innovative or innovative, then science screeched to a halt. And I think that's the, the goal of science is advanced the knowledge. So you can only advance the knowledge by knowing what has been known up to then to add to it.
So.
And that takes years and then. Yeah, you never stop learning. Definitely.
I, I can't think of a better parting thought than that. I'll ask if you have any other ones, but I know that your, your time that you have available with us today is nearing its end, so thank you very much for joining us. I know our audience has found this really valuable and will definitely enjoy looking into this tool set. So are there any other things that you just like to make sure that people are aware about there?
No. Yeah. So you can find everything I just showed on my GitHub page, so that's maybe nice and full in GitHub and there you can actually download everything here. So all the data that I showed are just here in the resources but better is just to go to the, to the release file here where you can actually just download the packlet. Just.
Will the instructions to do this be in the notebook that you're uploading? Yeah, we'll upload. Great.
Yeah, that's great. So the installation instructions are in the readme or on the website and then the packlet should install all the demo data, all the functionality and you should be able just to open the demo notebook, run the first line and should all work if the packlet installed correctly. So that's sort of the. Yeah, my last question. So I really enjoyed talking to you guys. We really enjoyed having you talk about this work in a slightly different context than I do normally. So really happy I could could have added to, to your nice series of things and things to come.
Yeah, I know I have a lot of follow up questions about, you know, people who are interested in getting into this area, backgrounds and training, all this kind of stuff, but we've only just scratched the surface of QMRI tools and the sort of interesting intellectual history that brings us to the point where we can have tools like this and you can download them and try them out yourself.
Yeah, that's very true.
Yep. Thank you. Definitely. And like you said, for things to come, we look forward to any further interaction we can have with you because this has been fantastic.
Yeah, definitely hope to see you all at the user forum. That's where I spend a lot of my time as well, so.
Very good.
Okay, nice talking to you all.
Nice talking to you and thank you all everyone who has watched, all the viewers, thank you very much. We will see you next time.
More from Guy

Cheryl Strauss Einhorn | The Human Edge: Smarter Decisions in the Age of AI | Talks at Google

Rachel Glennerster | Innovation and the Center for Global Development | Talks at Google

Rebecca Winthrop | Rethinking the Purpose of Education in the Age of AI | Talks at Google

Dr. Robert Wachter | A Giant Leap: How AI Is Transforming Healthcare... | Talks at Google






