Join us and get access to thousands of tutorials and a community of expert Pythonistas.
This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.
Graphing HR Diagrams
00:00 Remember when I kvetched and moaned about the context-based graphing mechanism in Matplotlib? Well, this time around, I’m not going to use it. Well, sort of.
00:10
The subplots() function on the pyplt module creates a graph object to manipulate. It then gives you two things related to that graph: the figure, which is the container that everything’s in, and the axes on the graph.
00:25 Personally, I find the fact that Matplotlib calls this the axes confusing. I think of an axis as being the X or Y of a graph. And I guess when you pluralize it like this, you’re getting both back?
00:36
But it definitely wouldn’t have been how I structured or named things. I think I’m grumbling about Matplotlib again. The suptitle() method on figure is the super title, something for the overall figure.
00:49 In this case, I’m titling it “HR Diagram”.
00:52
And remember when I said instead of doing context-based, I’d be using graph objects? And that was kind of why I hesitated. You kind of are and you kind of aren’t, although you’ve got a reference to the figure and the axis here, you still call scatter() directly on the pyplot module.
01:09
scatter() is what plots a scatter chart. The first argument is the data for the x axis, and the second is the argument for the y axis. For the HR Diagram, these are the temperature and luminosity columns from our DataFrame respectively.
01:24
The s argument stands for size and is what specifies the size of the dot in the scatter plot. In this case, I’m passing in our radius_sol column, so the dots will be of different sizes depending on the star.
01:38
The color argument allows you to specify the color of the dot, and the edge_color is for the color of the dot’s outline. This is why I calculated those new columns before.
01:51 Once I’ve got the data plotted, I want to add some info to the axes. First, for the y axis, I’m setting a label and telling it what the range on the axis is to be.
02:02 Matplotlib will default the range to something that fits, but that can mean some weird start and end values, and because I want a log scale, I’m being explicit about these being powers of 10.
02:14
Speaking of the log scale, the set_yscale() call allows you to determine how the scale of the axes gets displayed. Passing in log as a string says to use the log-based 10 scale.
02:26
Logs are tricky in coding. Different libraries will use a different base when you write log without a number. Whenever you are using these kinds of things, make sure to look it up in the docs or you might end up using log base 2 when you mean 10 or e or whatever.
02:43 Next, I do the same thing for the x axis, setting a label, a limit, and changing it to log scale as well.
02:51 If you’d stopped there, you’d find that the x axis was actually kind of unreadable. The values of the temperatures would be displayed in scientific notation and they’d overlap each other on the screen.
03:02 To get around this, I want to use a custom formatter for my tick labels that displays values in thousands. To use a custom formatter, you first need a lambda that returns a string.
03:14
This lambda will be passed the x value and its position. I’m actually only concerned about the x value in this case, so I convert it to an integer, divide it by a thousand, and then tack on k for kilo on the end.
03:27
Matplotlib comes with a bunch of tick formatters out of the box. The one I’m using is the FuncFormatter, and as the name implies, it uses a function to format the tick label.
03:40 A graph in Matplotlib has both major and minor ticks. These would be big ticks and smaller ones between them. Here, for reference, I’m turning the minor ticks on.
03:51
And then finally, this is the call that actually sets the FuncFormatter. set_major_formatter() uses my custom lambda and we’ll use that to produce the actual tick labels.
04:05
That’s our primary graph. Now I want to augment it by adding the absolute magnitude information as an axis on the right. The twinx() call on an axis creates a corresponding second axis.
04:17
Somewhat counterintuitively, calling twinx() creates a new set of axes, plural. You get both of them, a top and a right in our case, but I’ve had challenges getting them to behave when you do it this way.
04:30 So I twin the x and then I set the y inside the twinned set. These three calls set the label, position, and the limit of the axes to display our magnitudes.
04:42 The magic numbers for the limits here were created by me looking up the range of luminosities and calculating the corresponding lower and upper absolute magnitudes.
04:51
And finally, now I do the same thing for the B-V color index on the top. And as I said, although twinx() creates two axes, I couldn’t get them to behave.
05:01
So now I twiny() to get my new top axes. Then I set a label on it and the limits and I’m done. The last line there pops up the resulting graph.
Become a Member to join the conversation.