0

As per the skyfield documentation online, I am able to calculate whether a given time of day is day or night.

import skyfield.api
import skyfield.almanac

ts = skyfield.api.load.timescale()
ephemeris = skyfield.api.load('de421.bsp')

observer = skyfield.api.Topos(latitude_degrees=LAT, longitude_degrees=LON)

is_day_or_night = skyfield.almanac.sunrise_sunset(ephemeris, observer)

day_or_night = is_day_or_night(ts.utc(merged_df.index.to_pydatetime()))

s = pd.Series(data=['Day' if is_day else 'Night' for is_day in day_or_night],
              index = merged_df.index, dtype='category')

merged_df['Day or Night'] = s

Now, I want to also categorize the morning/noon/evening phases of the day according to solar altitude/azimuth. I came up with the following.

earth, sun = ephemeris['earth'], ephemeris['sun']

observer = earth + skyfield.api.Topos(latitude_degrees=LAT,
                                      longitude_degrees=LON)
astrometric = observer.at(ts.utc(merged_df.index.to_pydatetime())).observe(sun)
alt, az, d = astrometric.apparent().altaz()

I need help in understanding how to proceed further since I don't have the related background knowledge about astronomical calculations. Thanks

Atif
  • 345
  • 1
  • 4
  • 16
  • What definition of "noon" will you be using? To help you choose the best definition, it will be helpful to know why you are trying to tell the difference between morning and evening; then a definition can be chosen appropriate to the problem you are solving. – Brandon Rhodes Mar 15 '20 at 15:02
  • Frankly, I can not say how to define noon. However, my idea was to divide the day into three phases based on the solar angle after sunrise. So during the first 3rd of its day time course, I could categorize the time as morning, and so on. But a very basic definition from you would be a better one I think. – Atif Mar 15 '20 at 15:13
  • The purpose is to generate categorical feature for grouping VoC activity based on sunlight intensity. – Atif Mar 15 '20 at 15:15
  • Sunlight intensity should be related to its angular altitude in the sky, which you call `alt`. Maybe you could correlate directly against that value, or else an intensity value you derive from it using a sunlight intensity formula (probably involving the sine or cosine of the angle)? – Brandon Rhodes Mar 15 '20 at 15:45

1 Answers1

0

As per Brandon's comment, I used the cosine of zenith angle to get the sunlight intensity and then hacked together the sunlight intensity with the zenith angle to form a monotonically increasing function for the duration of the day.

temp = pd.DataFrame({'zenith': 90 - alt.degrees,
                     'Day or Night': day_or_night},
                    index=merged_df.index)

temp['cos zenith'] = np.cos(np.deg2rad(temp['zenith']))

temp['feature'] = temp['cos zenith'].diff(periods=-1)*temp['zenith']

temp['Day Phase'] = None

temp.loc[temp['Day or Night'] == False, 'Day Phase'] = 'Night'
temp.loc[(temp['feature'] > -np.inf) & (temp['feature'] <= -0.035), 'Day Phase'] = 'Morning'
temp.loc[(temp['feature'] > -0.035) & (temp['feature'] <= 0.035), 'Day Phase'] = 'Noon'
temp.loc[(temp['feature'] > 0.035) & (temp['feature'] <= np.inf), 'Day Phase'] = 'Evening'

merged_df['Phase of Day'] = temp['Day Phase']

The limits can be adjusted to change the duration required for noon, etc.

Atif
  • 345
  • 1
  • 4
  • 16