“Serena” Quasar’s sparcl ID: 719e7ea6-8b79-11ef-be93-525400f334e1
Adding Interactivity to marimo
00:00 In the previous lesson, I showed you how to add our spectral lines to the dashboard. In this lesson, I’ll finish the dashboard off by adding the interactive components.
00:10 Alright, this is the final push. The goal here is to make the dashboard interactive, allowing a user to change what lines are displayed and how much they get redshifted. The formula to redshift a wave is pretty simple.
00:23 It’s one plus the value of redshift times the wavelength being shifted. There are two kinds of interactive elements to be added to the board. First, some switches for the spectral elements to turn them on and off.
00:35 And second, a slider to adjust the redshift value. In the background, I’m going to run marimo edit again and I’ll meet you at the browser. marimo comes with interactive components.
00:47 They live within the UI submodule of marimo. Let’s start by creating our slider. Let me add a new cell.
01:09 This declares the slider and puts it in a Python object. Any cells that use this slider are marked as dependent on the slider’s value. When you adjust the slider, then any cells that use that value are going to get recalculated automatically.
01:25 I want to do something similar for the spectral lines, creating a switch for each line. I’m going to put these switches in a dictionary corresponding to the element name.
01:46 This is a dictionary comprehension, creating a key-value pair of the element name and a marimo switch for each of the names in our graph lines list. This will work, but it has a problem.
02:00 Remember when I said earlier that marimo looks for changes in an object and updates any corresponding cells? Well, it’s only able to monitor objects at the global level.
02:11 Changing the redshift slider causes cells to refresh, but as it stands here, changing the switches won’t because they’re buried inside of a dictionary and marimo won’t see it.
02:22 marimo does have a solution for this though. They have their own dictionary. By using it instead, this problem gets solved.
02:32 By using this special dictionary, the switches will be included in the dependency calculation and will trigger other cells to refresh if they change. Let me run the cell.
02:43 Notice that nothing’s updated. All I’ve done is create the UI components, not display them. To do that, you use a markdown cell, right-clicking on the plus, choosing markdown cell, and I want my markdown to work kind of like an f-string so that I can evaluate Python objects inside of it.
03:03 To do that, you click this very hard to see little F. Now for some markdown, that’s my title and that’s evaluating the redshift_slider object, which will present it if I hit play.
03:21 There you go. I can move the slider around. Remember, you have to use the little F here in order for this to get evaluated. It might be nice to show the current value, even if you aren’t touching the slider.
03:46 Now the slider and its value are shown. Let’s add the switches.
03:56
marimo has components for grouping UI elements together. I’m going to use the hstack
for a horizontal grouping. Remember, the switches are in the dictionary, so I get at the switch components themselves with a call to the dict’s .values
method.
04:17
With the UI components in place, it’s time to actually make them affect our plot. I need to edit our iteration here to use the switches instead of the names of the lines, I’ll need both the name of the element and the switch object itself, so I can iterate the dictionary with .items
.
04:37
I still need a count though, so I’ll have to leave this enumerate
in place.
04:45
Items returns a key-value tuple for each thing in the dictionary. When you use enumerate()
on it, you need to keep the tuple together on the left-hand side.
04:58 With that in place, I’m now iterating over our switches. The original code drew all the lines. I want to draw only those lines that have a switch turned on.
05:15
Like with the redshift slider, the .value
attribute here gives the state of the switch component. With the if
block in place, the line will only get drawn if the switch is on.
05:25 The last thing to do is to apply the redshift to our element line.
05:46 That replaces this line.
05:52 And updating my variable name, running it and hoping I did everything correctly. Didn’t blow up, and there isn’t anything on the screen. Let me turn one of the switches on.
06:09
And I mucked something up. Ah, element
is not defined. I should have replaced the name here as well. Trying again, and there you go. One switch on and it’s on the board.
06:30 Now let’s try to adjust the redshift,
06:38 and there you go. A couple of lessons back, when I grabbed the spectral data, Sparcl said the quasar had a redshift of 3.2, and as you can see, that’s what’s showing up on the graph.
06:52 Alright. It isn’t real homework because it’s up to you to play around, but if you’re looking for some ideas, you could try to add some more spectral line switches.
07:01 That’s actually a one-line change. Once you’ve got some more switches, especially if you’ve added more switches than colors, how about combining the idea of progressing over the colors with progressing over different line styles?
07:14 That way, when you have to reuse a color, it could be with a different line style. If you Google Matplotlib and linestyle as one word, you’ll see all the different choices.
07:25
In the previous lesson, I changed the lower boundary on the graph, so you could see the spectral lines. How about adding a UI component for each of the lower and upper bounds of .xlim()
?
07:36 One possible approach would be to use a marimo UI text widget. Just remember that the contents will need to be converted from a string to a number. Finally, for a real challenge, go back and play with the quasar data. Create more CSV files and see if you can use the redshift information in the database to find what elements got used in the calculation.
07:59 Last up, I’ll summarize and point you at other courses you might like.
Become a Member to join the conversation.