Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Calculating Angular Separation

00:01 And this is the top of the calculating loop. I’m going to do OBSERVATION_COUNT times number of calculations. Python’s timedelta allows you to do math on dates.

00:12 Here I’m calculating the date for the current row by adding DAY_INTERVAL times the iteration value. The first time through this will be zero.

00:20 Then for the constants I defined at the top, it would be every seven days.

00:25 There are several ways of adding rows to a data frame, and in fact, one of the ways in pandas 1.0 got removed in 2.0. So careful when you’re Googling out there, it might not be the most recent information.

00:37 The procedure I’m going to use to add data to the original data frame is to create a second one and concat it with the first. Not only are there several ways of adding information to a data frame, there’s also several ways of creating a data frame.

00:50 You already saw me create an empty one. This time I’m going to use a dictionary where the keys are, the column names and the values are lists of data.

00:59 As my new data frame will only have one row, there will only be one thing in each of those lists.

01:05 This dictionary starts with the timestamp column containing a value for the first and only row, which is going to be in this data frame, and that’s the date just calculated.

01:14 Now for the inner loop, this creates a column for each planet being compared to our reference of Mercury by updating the row dictionary.

01:24 As I mentioned, Astro’s time class doesn’t take a Python datetime, but it will parse an ISO time string. So here I’m outputting the date of the row as a string and appending the time of midnight to it.

01:37 Technically, my first calculation will be in the past as midnight on today’s date is behind us, whatever. What’s a few hours between friends?

01:45 I mentioned that Astropy can be a little chatty in order to silence complaints about doing calculations too far in the future, I’m using a catch_warnings context block.

01:56 Inside the block, the warnings.simplefilter() call changes the warning level just for this block. Now whatever Astropy spits out, we’ll get ignored because I set it to ignore.

02:07 Doing this in a context block is the safest thing to do. This way I won’t accidentally suppress warnings from elsewhere in the code.

02:15 And spoiler alert, there are going to be warnings elsewhere in the code. Finally, let’s do the actual astronomy math. This is Astropy’s get_body() call.

02:25 It takes the coordinates for Mercury. This iteration’s date in Astropy time format and the location defined in our comp file. ref will contain the coordinates for the reference body.

02:36 And then I do something similar to determine the coordinates of the target. In this case, the target will be the planet being compared against Mercury once for each time in this inner loop.

02:47 With those two values in hand, I take the right ascension and declination for the reference and the right ascension and declination for the target, and pass those to the angular_separation() call to determine the angle of separation between the reference and the target.

03:04 The default calculation is in radians. So here I’m using the .to() method to convert it to degrees. Finally, I add the angle that is the result to the dictionary.

03:16 And remember, this dictionary is going to be used to create the new row.

03:21 Speaking of, once you’ve flipped through all the planets, it’s time to create the new row. These two lines create a new data frame using the row dictionary, and then set the index for it to the timestamp column.

03:34 Now I want to combine that row to the existing data. To do that, you can use the pandas concat() function. concat() takes a list of things to concatenate together.

03:44 This one doesn’t use inplace. So I replace my current reference of df with the new object returned from concat(), which contains the original table concatenated with the new row.

03:55 I couldn’t find a way in pandas to do this without creating copies, at least not with functions. There’s a hacky method to create new rows using .loc, but concat() seems to be the recommendation.

04:06 And I wanted to show you how to do that. So this is the one I chose.

04:10 In the slides, I showed the tricky call to add a column containing the count of planets whose angle is less than seven. This is essentially that call. I made a small difference here in the slides.

04:23 I showed you how to operate on a single row. The first value to .loc was zero, so it was the first row here. Instead, I’m using a colon. This is pandas’ way of saying do all the rows.

04:37 So with this single call to .iloc, I’m adding a value to every single row of the data frame. And that value is the count of the number of columns whose angle of separation is less than or equal to seven.

04:50 The call to .assign() then takes that information that is calculated as an independent column and adds that column to the table data frame. Alright, that’s the hard part.

05:02 Now all that is left is to print out the results.

Become a Member to join the conversation.