[00:00.000 --> 00:10.120] All right. Good morning, everyone. Welcome to the HPC Dev Room. Thanks for being here [00:10.120 --> 00:15.600] so early in the morning, maybe not entirely sober. We'll let Nicolas get started with [00:15.600 --> 00:19.680] opening a Dev Room with a talk on paraffin. Thank you, Nicolas. [00:19.680 --> 00:29.680] Hello, everyone. Thanks to be here early in the morning to begin this HPC day. I trust [00:29.680 --> 00:34.560] them. A big thanks to everyone who organized this room. That's really great to be here. [00:34.560 --> 00:40.860] Thanks, Kenneth, on all your team. So, about me, I'm Nicolas Vieille. I'm a [00:40.860 --> 00:46.120] C++ developer, and I have the chance to make my job about making first-code [00:46.120 --> 00:51.640] contributions. I'm working at Kitware Europe, and I work mainly on ParaView, [00:51.640 --> 00:57.840] so developing the software, but also interacting with the community. So, as my [00:57.840 --> 01:04.720] may want to reach me later. So, ParaView, it's an end-user applications that work [01:04.720 --> 01:10.880] for scientific data analysis and visualizations. We have an open community [01:10.880 --> 01:16.640] on the GitLab for the code and discourse for discussions. It's supported by [01:16.640 --> 01:21.600] Kitware, which is also behind VTK for visualization toolkits, and to make you [01:21.600 --> 01:29.600] potentially already know about. So, what do we do with ParaView? It's for [01:29.600 --> 01:34.240] displaying and analyzing scientific data sets. So, it's mainly a 3D visualizer, but [01:34.240 --> 01:38.880] you've got also some charts and spreadsheets and so on. It's also intended for [01:38.880 --> 01:44.360] data processing. So, we have a concept of filters to take an input and compute [01:44.360 --> 01:48.880] some stuff on it and get your outputs. So, basically, you can extract the data [01:48.880 --> 01:54.200] of interest of your raw data. We also have some other module like realistic [01:54.200 --> 01:59.600] rendering. So, you can do your communications with directly your real [01:59.600 --> 02:06.160] data sets or not with just some kind of fake one. So, here is some basic [02:06.160 --> 02:14.320] screenshot of the applications. Who is using ParaView? We cover its generic [02:14.320 --> 02:19.040] application. So, we cover a large range of domains like fluid dynamics. So, we can [02:19.040 --> 02:25.160] compute streamlines, particle tracking, and so on. We have also volume rendering [02:25.160 --> 02:29.280] that is real nice for our medical applications with you have some 3D scan [02:29.280 --> 02:34.320] and you want to understand what happened inside. So, that's just, that's [02:34.320 --> 02:40.000] non-finite list. We have a lot of domains that can be covered, but here is the more [02:40.000 --> 02:47.080] well-known one. Oh, we do use ParaView. So, as I said, that's an application. So, [02:47.080 --> 02:52.000] basically, the first way to learn is to use the GUI. So, you click on buttons, you [02:52.000 --> 02:57.840] do some stuff, and you're happy. But you can also use the Python wrapping to [02:57.840 --> 03:02.680] write some scripts. And so, you can run the script on that processing without [03:02.680 --> 03:08.480] having to be behind the computer. It has a framework because you can code your [03:08.480 --> 03:13.640] own extensions, your own derivative work from ParaView in the native [03:13.640 --> 03:19.200] simplest language, but also some features can be done in Python code. And it's [03:19.200 --> 03:24.040] all based on the visualization tool kit. I mean, all the hard work of processing [03:24.040 --> 03:31.720] the data and do the rendering come from VTK. So, as I said, that's also supported [03:31.720 --> 03:37.240] by Kitware. So, I do work sometimes on VTK to have some bug fix or some small new [03:37.240 --> 03:44.840] features. Where we can run ParaView, on which hardware is it possible to use it? [03:44.840 --> 03:50.600] Basically, on your small, classical, big stop, we have some official binaries you [03:50.600 --> 03:54.880] can try to download and just run. It should be, it's cross-platform, I didn't say, [03:54.880 --> 04:01.280] but you can run it on, as well, on proprietary software like Mac or Windows, [04:01.280 --> 04:08.040] but it should be out of the box for Linux 2. You can also build it. We have a large [04:08.040 --> 04:12.080] selection of build options, depending on what you want to do exactly. You can [04:12.080 --> 04:16.360] enable or disable it. So, if you want to have Python data distribution, [04:16.360 --> 04:22.560] parallelizations, or custom rendering, a lot of stuff. We have some documentation [04:22.560 --> 04:27.160] about it, and we can help you on the discourse if you have to try to achieve [04:27.160 --> 04:34.040] some specific build of it. And which kind of usage do we have of ParaView? [04:34.040 --> 04:40.680] So, either a research and industry are using it. For instance, recently, there [04:40.680 --> 04:46.840] were the Super... So, before winter, a supercomputing conference in the US, and [04:46.840 --> 04:52.000] they organized a service contest where people are asked to upload some nice [04:52.000 --> 04:56.480] videos made about their scientific analysis, and most of them are using [04:56.480 --> 05:00.800] ParaView, either for just the data processing, but also sometimes for the [05:00.800 --> 05:07.160] video generations, and animate their data. So, why all those people are using [05:07.160 --> 05:13.400] ParaView? Because ParaView does some stuff efficiently to process the data [05:13.400 --> 05:19.720] and their infrastructures. So, that's what I want to talk in the next part of [05:19.720 --> 05:27.080] my... of my talk. So, what's ParaView used behind the hood to make it [05:27.080 --> 05:33.120] possible? So, first, we have a client-server architecture. So, I always say [05:33.120 --> 05:39.080] that you can do it from Python, but the degree on Python are just two [05:39.080 --> 05:45.120] clients. So, you can do exactly the same stuff with one or the other. There's no [05:45.120 --> 05:53.400] real limitation about using one or the other second. You can also run with [05:53.400 --> 06:00.600] remote server, so, and you can run in a distributed environment your server. So, [06:00.600 --> 06:06.080] in that case, you can connect your... you can either just run the server parts to [06:06.080 --> 06:10.560] analysis with a script analysis, but you can also connect your local clients to [06:10.560 --> 06:15.960] your distance server, and again, using the graphical interface to do the stuff [06:15.960 --> 06:22.880] as if it was on your local machine, but instead, it's... yeah, the [06:22.880 --> 06:29.040] supercomputer or the remote architecture. At the bottom, two other [06:29.040 --> 06:33.240] modes that are available. If you... typically, if you have some graphic nodes on [06:33.240 --> 06:39.960] your server, you can use them for just the rendering part and stay the data [06:39.960 --> 06:45.760] management on the CPU nodes, and still, you can connect your client on it to see [06:45.760 --> 06:50.880] what happened and to control from a graphical interface. And last mode, I will [06:50.880 --> 06:56.440] go back on it later. We have an institute infrastructure, so, basically, your [06:56.440 --> 07:02.640] simulation can call an IPI that's Fluid Paraview script analysis, and you can [07:02.640 --> 07:06.840] even connect with a graphical client to see time step per time step what is [07:06.840 --> 07:14.440] happening on your simulation. So, that's for the different mode of use for [07:14.440 --> 07:21.960] Paraview. So, first, to run on HP infrastructure, we [07:21.960 --> 07:26.520] implement data distributions for the analysis. So, basically, we rely on the [07:26.520 --> 07:33.280] MPI standards. So, our readers are MPI aware, so they can distribute the data [07:33.280 --> 07:38.920] over the rank early in the process when you read your data on the disk. Then, [07:38.920 --> 07:45.680] most of the filters are okay to run just with their support of data, but some [07:45.680 --> 07:50.600] other filters need to know about the neighborhood to execute correctly. So, for [07:50.600 --> 07:55.920] that, we support the concept of ghost cells, where each rank knows a little bit [07:55.920 --> 08:02.160] about the rank that is next to it. In that case, mainly, we split the data [08:02.160 --> 08:07.680] geometrically. So, a subset is really a geometric subset of your data, and [08:07.680 --> 08:16.600] different one can know and communicate with the other for specific tasks. At [08:16.600 --> 08:21.480] least, we have some filters. So, what I call a filter is really something that [08:21.480 --> 08:27.160] the user can instantiate from the client and ask to process. So, we can [08:27.160 --> 08:36.160] ensure a load balancing by redistributing the data during the process. The [08:36.160 --> 08:40.440] visualizations can also be distributed over several ranks. So, for that, we use [08:40.440 --> 08:46.000] an inner library that call IST, that's also based on the MPI process to do that, [08:46.000 --> 08:51.760] and parallel view support has a different kind of model of rendering. So, you [08:51.760 --> 08:56.560] can, if you have dedicated rendering node, you can, as I said, create parallel [08:56.560 --> 09:01.240] view server just for the rendering part and connect it to the data server. You [09:01.240 --> 09:06.040] can have multiple GPUs per rank, yeah, multiple GPUs per rank to do the [09:06.040 --> 09:11.800] rendering, but that's also possible locally if you have just one machine that [09:11.800 --> 09:19.440] have multiple GPUs, you can ask to do a rendering on both simil-tune-y. [09:19.440 --> 09:27.680] Concerning the performances now, so that distributions is not about [09:27.680 --> 09:32.880] performance, it's just about running with too big data so you cannot just run on [09:32.880 --> 09:38.640] your machine, that's a requirement when you have huge data to be able to [09:38.640 --> 09:44.640] distribute it over your computer or your supercomputer. Now, we're talking a [09:44.640 --> 09:48.800] little bit about performance because if you have big data, you also need to be [09:48.800 --> 09:55.680] performant on how you analyze it, on how you are proceed with it. So, for that, we [09:55.680 --> 10:01.520] have a thin layer for CPU parallelism, we call that a simple tool in our code [10:01.520 --> 10:10.360] base. The goal is to parallelize, do code parallelizations for many for loop, and [10:10.360 --> 10:16.360] main purpose is that you can choose at build time and then at run time, if you [10:16.360 --> 10:21.720] enable the OpenMP or TBB backends, and if you don't want external live, you can [10:21.720 --> 10:32.680] also use the C++ thread to do that. And so, as it just, for instance, to [10:32.680 --> 10:38.600] parallelize a for loop or field operations, it's really widely used in a lot [10:38.600 --> 10:44.360] of our, in our algorithm, and you have some environment variable that can [10:44.360 --> 10:50.200] control the back end on some of the number of, of thread, the size of the [10:50.200 --> 10:55.840] thread pools, or if you allow nested pools or so on, depending on the, on your [10:55.840 --> 11:01.960] resources and back end. So, it has some documentation on it, and we made some [11:01.960 --> 11:12.120] improvements last year about that. Still, still about performances, we also use as [11:12.120 --> 11:19.200] an optional dependency, the VTKM, VTKM projects that stand for, yes, somewhat [11:19.200 --> 11:25.600] some many core that is intended to be used on heterogeneous systems. So, basically, [11:25.600 --> 11:31.920] when you want to have performance on supercomputer or even, you, you still need [11:31.920 --> 11:37.280] to be aware of the current technology and the state of the art, and as we saw in [11:37.280 --> 11:43.760] the past decades, a lot of new architectures emerging. We, we think about [11:43.760 --> 11:52.240] using a dedicated library to, to be able to use this, this new architecture. So, [11:52.240 --> 11:57.360] with VTKM, the goal, inside VTKM library, the goal is to split all [11:57.360 --> 12:03.400] operations into really atomic operations, and then the, the, at runtime, it can [12:03.400 --> 12:09.080] dispatch all, all that on the hardware you find on the back end that are [12:09.080 --> 12:14.800] available. So, with VTKM, you can use CUDA, OpenMP, TBB also, to do the [12:14.800 --> 12:21.960] computation. This time, with VTKM is not just accelerating some specific loop [12:21.960 --> 12:27.960] inside an algorithm, it's more about VTKM is implementing some whole algorithm [12:27.960 --> 12:37.720] like extracting ISO control or, or so. And then, we embed this into, into [12:37.720 --> 12:44.840] Paraview with some kind of wrapper to, to communicate with all VTKM works. So, [12:44.840 --> 12:51.320] that's optional, that's enabled by default in the binaries we, we provide. [12:51.320 --> 12:58.520] Another point about performance, but that's really depending on the use case, [12:58.520 --> 13:04.400] on, on the data you are using is the in-situ wall. So, basically, when you, [13:04.400 --> 13:09.080] traditionally, when you have your simulation, it dumps every time step or [13:09.080 --> 13:13.480] every end time step some data on the disk. And then, to analyze, you have to load [13:13.480 --> 13:19.680] back to the data with post-processing tools. But that adds a cost of writing [13:19.680 --> 13:25.320] and reading from your disk. And you, you should have the size on your disk, the [13:25.320 --> 13:29.720] whole size of the disk. So, you should have big disk. And then, it's, it have [13:29.720 --> 13:35.000] really a cost in term of time, when you should write a full, a full mesh or full [13:35.000 --> 13:39.600] data on disk. And then, read back with another process. So, basically, the goal [13:39.600 --> 13:45.000] of in-situ is to, to make the simulation communicate directly with the [13:45.000 --> 13:49.560] processing tools. And then, the processing tools can wrap the memory in place and [13:49.560 --> 13:55.480] analyze directly in, in the RAM without writing on the disk to save some [13:55.480 --> 14:05.000] higher time. So, in the context of ParaView, we have a standalone API that's [14:05.000 --> 14:11.200] called Catalysts. That was recently released, as we make big improvements into [14:11.200 --> 14:19.720] Catalysts past years. And the goal of Catalysts is to have a really minimal API [14:19.720 --> 14:26.400] and stable API. So, you can choose and run time the implementation you, you want. [14:26.400 --> 14:32.240] And one other goal is to minimize the instrumentation you need to do in your [14:32.240 --> 14:36.160] simulation code directly. So, it's really easy for simulation developer to [14:36.160 --> 14:41.120] understand the few key places where they have to put a new code to call our [14:41.120 --> 14:47.640] API. So, here is a really basic example from one on the tutorial we have. We need [14:47.640 --> 14:51.360] to initialize, of course, and you need to call some method at each time step [14:51.360 --> 14:59.680] where you want the processing to happen. And finalizations. Of course, the, you [14:59.680 --> 15:05.800] still have to do a little layer to describe your, your data. For that, we [15:05.800 --> 15:15.160] do some sort of a partial library to, to help us. So, ParaView, so Catalyst is a [15:15.160 --> 15:21.440] standard, I say standalone, is not, is independent project, no, independent of [15:21.440 --> 15:25.920] ParaView. But of course, the first real implementation is an implementation for [15:25.920 --> 15:38.600] ParaView. So, we, sorry. So, yes, we, we implement Catalyst. So, the back end, so [15:38.600 --> 15:44.040] you can run ParaView pipeline directly from your simulation. It's each time [15:44.040 --> 15:53.480] step or when, when you call it. So, how does it, how does it work? Or do you, you [15:53.480 --> 15:58.240] can, the idea is that you are, are called the communication between your [15:58.240 --> 16:03.160] simulation and the, on Catalyst through the API. But then the actual script that [16:03.160 --> 16:07.560] is executed, the actual pipeline and visualization, visualization you want to [16:07.560 --> 16:14.280] produce. It's all scriptable thanks to the Python wrapping of, of ParaView. You [16:14.280 --> 16:19.040] can even, you can even, sorry, load some representative data in the graphical [16:19.040 --> 16:23.720] interface of ParaView. Do some analysis, export this as a Python script and use [16:23.720 --> 16:28.880] the script to feed Catalyst. And then, when you run your simulation with [16:28.880 --> 16:34.320] Catalyst enable, it will reuse the script you produce directly from the GUI. So, [16:34.320 --> 16:40.160] people that are not at all developers still can do some stuff with, with [16:40.160 --> 16:45.480] Catalyst. And last point is that, when you have a running simulation with the [16:45.480 --> 16:49.880] Catalyst pipeline on your dedicated server, you also can use the GUI to [16:49.880 --> 16:56.240] connect to this ParaView server and to see real-time get some screenshots of the [16:56.240 --> 17:01.040] visualization on the analysis that is proceeding on the server. So, you can have [17:01.040 --> 17:06.440] a feedback, a time step per test, a time step on what happened on the simulation. [17:06.440 --> 17:10.640] So, if you see that something is diverging or going wrong, you can stop [17:10.640 --> 17:16.200] your simulation directly and you don't waste all the time before seeing that [17:16.200 --> 17:21.880] something went wrong and that you should tweak the parameter and start again. [17:23.640 --> 17:32.760] So, yeah, I was quite faster than expected for me. So, in the conclusions of [17:32.760 --> 17:39.280] to, to be able to run efficiently on the, on the supercomputer with ParaView, we [17:39.280 --> 17:44.440] implemented a client-server mode. The server can be, is MPIO rare and can be run [17:44.440 --> 17:49.600] on distributed environments. We are relying on old, on well-known libraries [17:49.600 --> 17:57.160] such as implementation of MPI to the distributions, but we are also really [17:57.160 --> 18:07.160] looking for, toward new, new library that can help us. Yeah, and we, we are able to [18:07.160 --> 18:13.640] integrate new library to, to do some performance analysis on new library that [18:13.640 --> 18:20.080] is aware of a new architecture of supercomputer or new technology. That's [18:20.080 --> 18:27.080] okay with, for instance, with VTKM or, or others. And we have this API to do [18:27.080 --> 18:34.120] institute that can save a lot of time and disk space. Yeah, just a slide to [18:34.120 --> 18:38.560] summarize the organize. So, we have different kind of way to interact with [18:38.560 --> 18:44.000] ParaView. Yeah, the grid, the Python scripting, the catalyst in city stuff. You [18:44.000 --> 18:50.120] can also build some custom one. We have some web example of clients. And at the [18:50.120 --> 18:56.680] bottom, we have a list, a non-finite list of library on which we will like to, to, [18:56.680 --> 19:05.320] to do the effective work. So, basically, open GL, MPI, open, open MP. And so, [19:05.320 --> 19:11.360] concerning roadmap, we have several improvements that are coming. First, I [19:11.360 --> 19:17.720] talk about in, in situ, in the current implementation, you have each rank that [19:17.720 --> 19:23.080] does the simulation, does also the, the co-processing work. So, that's not always [19:23.080 --> 19:28.200] what is intended. Sometimes, you want to do the co-processing on the other rank. [19:28.200 --> 19:33.200] Just because, for instance, you have dedicated the rank for visualization. So, [19:33.200 --> 19:38.360] you want to do all the processing on the visualization nodes. That's for not [19:38.360 --> 19:41.760] possible just with the in situ implementation, but we have an in-transit [19:41.760 --> 19:47.880] implementation where the simulation can communicate with those different nodes. [19:47.880 --> 19:54.720] And, and the analysis can happen on other ranks than the simulation. So, the [19:54.720 --> 20:01.600] simulation can go forward directly. We use, we also use some new library, [20:01.600 --> 20:08.320] recently used a library called DIY. That's here to do some wrapper for us. It's, we [20:08.320 --> 20:17.120] take it as a wrapper around the MPI. So, DIY, I love to do some to, to cut the [20:17.120 --> 20:23.560] data into different blocks. And then, the, at runtime DIY itself is a rare to do. [20:23.560 --> 20:30.080] Okay, I should put three blocks on each rank. So, only one block. And, yeah, it's a, [20:30.080 --> 20:38.200] yeah, just a new abstraction over cutting your, your data for distribution. We [20:38.200 --> 20:45.440] are also looking for better VTK on always, yeah, better VTK integrations to, to be [20:45.440 --> 20:51.160] able to, to run on a lot of hardware. And something very cool that is very new. It's [20:51.160 --> 20:56.160] just in the development branch of VTK. So, absolutely not in Paraview yet. That was [20:56.160 --> 21:00.360] merged, I think, one or two weeks ago. It's what we call implicit arrays. And, [21:00.360 --> 21:07.200] basically, it's really cool for memory point of view because we, it's some kind [21:07.200 --> 21:13.560] of views on memory. For now, in the Paraview process, your data is really an [21:13.560 --> 21:21.000] array in the, in the memory, in your memory. So, with the implicit array, we have [21:21.000 --> 21:27.680] some views. So, you can implement an open, open pattern on it. For instance, when [21:27.680 --> 21:33.520] you do an isocontrol of your data, you know that the, the, that, the resulting [21:33.520 --> 21:38.800] data will all have the same values. So, if you want, if you, after the isocontrol, [21:38.800 --> 21:42.600] you still have one million points, you will know that all the points will share [21:42.600 --> 21:48.280] the same value. For now, it's one million times duplicate in your memory. So, that's [21:48.280 --> 21:52.200] a not-efficient. With implicit array, you can sort only one time the value and say, [21:52.200 --> 21:57.920] okay, this should, this should be an array of size one million. And the value you [21:57.920 --> 22:04.720] should return is this one. But you can imagine as a, a compressed array in your [22:04.720 --> 22:12.840] memory and have an on-the-fly, uncompressed algorithm to when you just want, just [22:12.840 --> 22:16.880] when you want to, to read your data. So, it has a cost in terms of time of [22:16.880 --> 22:21.840] computations. But if you run out of memory with too huge data, that's, that can be [22:21.840 --> 22:31.280] really great. Okay, I still can have a lot of things to, to say, but that's what [22:31.280 --> 22:35.680] is the, the end of what I, I put in the slides. So, thanks for attending these [22:35.680 --> 22:39.560] songs to be here early in the morning. And if you have any questions, I think it [22:39.560 --> 22:44.200] will, it will be the time. I put just a lot of resources at the end of the [22:44.200 --> 22:49.200] slides so you can get it from the website of the phone. Thank you. [22:49.200 --> 22:55.200] Thanks, everyone. [22:55.200 --> 23:05.640] Thank you very much, Nikol. Do we have any questions? Thank you. In our group, we [23:05.640 --> 23:11.760] are happy users of ParaView. One thing that maybe I could add to a wishlist or [23:11.760 --> 23:22.000] some, well, maybe just for discussion is that we have quite some headache when [23:22.000 --> 23:28.000] using ParaView on GitHub Actions for multiple platforms. So, like to set up [23:28.000 --> 23:31.760] environments for Linux, Mac and Windows with the same version of ParaView [23:31.760 --> 23:39.280] coupling with Python just, just to be ready to use it. It's a bit of a headache, [23:39.280 --> 23:44.120] especially when you go to Windows and you need to download things, brew things, up [23:44.120 --> 23:48.840] to get install things and then they not necessarily work all together. So, wishlist [23:48.840 --> 23:54.960] thing, GitHub Actions, ParaView, set up a thing. Unless it doesn't, it exists [23:54.960 --> 24:02.880] already but I haven't found it. And the truth is, if there are questions here? [24:02.880 --> 24:07.560] The use of ParaView and GitHub Actions, so in like a continuous integration, [24:07.560 --> 24:13.480] limited environment, I guess? Yeah, it's a wishlist. Yeah, well, we don't [24:13.480 --> 24:20.400] choose GitHub directly. We have a, we have a, the GitLab where you can find a lot [24:20.400 --> 24:25.960] of stuff with our CI and CDO. We produce, we produce nightly releases of [24:25.960 --> 24:35.760] ParaView through the GitLab. So, I don't know if I, if it's some sort of part of the question, but. [24:35.760 --> 24:39.960] So, what kind of stuff are you doing with ParaView and GitHub Actions? Is it [24:39.960 --> 24:45.640] rendering or, rendering with Python? The fact is, I don't really know about GitHub [24:45.640 --> 24:49.960] Actions because I don't choose GitHub anymore. So, I don't see what you can do [24:49.960 --> 24:59.000] with that, that you should not able to do otherwise. Any other questions? [24:59.000 --> 25:07.440] There's a question on the chat. Okay. Yeah, there's a question on the chat. If I want to put [25:07.440 --> 25:12.640] Catalyst in my simulation, what is the first step? Oh, sorry. If you want to use [25:12.640 --> 25:17.720] Catalyst. In your, yeah. What's the first step? We have some, I think we have some [25:17.720 --> 25:22.160] tutorials on example in the code base of ParaView. We have some examples where [25:22.160 --> 25:27.440] there are some dummy simulations with just a main, so you can [25:27.440 --> 25:34.640] enter from it to, to see how it is organized. And, and yeah, the first, one [25:34.640 --> 25:41.120] first thing is to be able to know what do you want, which data do you want to, to [25:41.120 --> 25:47.160] send through, through Catalyst and where you can access it in your code. And then, [25:47.160 --> 25:55.000] it's, and then so you, at this time you, you have located the entry points from [25:55.000 --> 26:00.560] your simulation code and then you will be able to, to start writing the, the small [26:00.560 --> 26:07.520] wrapper you need to wrap your data on the need to the actual API of ParaView. [26:07.520 --> 26:15.920] Thanks. Okay. Any other burning questions? Maybe one last, yeah. Last question? [26:16.440 --> 26:25.640] Thank you for the talk. A very naive question, because I, is it working? A very [26:25.640 --> 26:30.040] naive question because I know almost nothing about, about ParaView. You had [26:30.040 --> 26:32.160] many components there. One of them was the client that does the [26:32.160 --> 26:37.760] visualizations. Yeah. Is it, would it be possible at some point in the future to [26:37.760 --> 26:42.000] be like a web client where you just log into the website and it just displays [26:42.000 --> 26:46.840] everything? Or is it just, due to the architecture is it like super complicated [26:46.840 --> 26:55.160] to do it that way? We, so the question is, yeah, the question is, are we able to use [26:55.160 --> 27:00.000] a web client for ParaView? Just, just for the part that does the visual [27:00.000 --> 27:04.920] ization, if that could be like a, we are, we have some web client for ParaView [27:04.920 --> 27:11.560] already. So we have a framework called Trame, T-R-R-M-E, that's intended to, to [27:11.560 --> 27:16.920] connect to a ParaView server. And then you build your own front end for [27:16.920 --> 27:23.720] these applications. So basically it's, we don't have a, yeah, you should build your [27:23.720 --> 27:30.760] own. But it can be, okay, I have a server on, I open the, always this data and the [27:30.760 --> 27:35.800] front end is just a 3D round of view. That's already possible quite easily, I [27:35.800 --> 27:40.680] think, with the Trame framework. And Jupyter Notebooks also, right? [27:40.680 --> 27:43.200] Jupyter Notebooks, I think I saw it on the user interface line. [27:43.200 --> 27:49.200] Yeah. Well, we are, yeah, as we use intensively Python, we also make the [27:49.200 --> 27:53.120] step to, to be supported from a Jupyter Notebook and we also have a plugin that [27:53.120 --> 27:58.600] allows you to control a ParaView GUI. So you can do some stuff in the Notebook. [27:58.600 --> 28:02.480] And if something goes wrong or you don't understand, you can launch a magic [28:02.480 --> 28:05.960] command run ParaView that's open the ParaView client with all your Python, [28:05.960 --> 28:10.520] Python, and you can introspect in the GUI. And then you can go back to your, to [28:10.520 --> 28:14.600] your Notebook. Okay. Thank you very much, Nicholas. [28:14.600 --> 28:15.600] Thanks. [28:15.600 --> 28:22.600] Thank you very much.