<p>The Ascendant-Descendant axis is the line of intersection of the ecliptic plane with the rational horizon. The ecliptic is the plane of the Earth's orbit. The rational horizon is the plane through the geocentre (the Earth's centre) which is parallel to the observer's local horizon. So the Ascendant-Descendant axis passes through the geocentre. The Ascendant is to the east, the Descendant is to the west. Hence the Ascendant is the point on the ecliptic that is currently rising.</p>
<p>Here's a diagram from an article on the Astrodienst site, <a href="https://www.astro.com/astrology/cw_astro_houses_e.htm" rel="nofollow noreferrer">Astronomical Foundations of the Astrological Houses</a>, by Christopher A. Weidner.</p>
<p><a href="https://www.astro.com/im/haeuser_horizontsystem_e.gif" rel="nofollow noreferrer"><img src="https://www.astro.com/im/haeuser_horizontsystem_e.gif" alt="Rational horizon, ecliptic, ascendant" /></a></p>
<p>We can easily calculate the Ascendant using spherical trigonometry. <a href="https://en.wikipedia.org/wiki/Ascendant" rel="nofollow noreferrer">Wikipedia</a> gives the equation, but it's in a slightly misleading format. Here's a better version:</p>
<p><span class="math-container">$$\lambda_{\rm Asc} = \arctan \left(\frac{\cos\theta_{\rm L}}{-(\sin\theta_{\rm L} \cos\varepsilon + \tan\phi \sin\varepsilon)} \right)$$</span></p>
<p>where <span class="math-container">$\theta_{\rm L}$</span> is the local sidereal time, expressed as an angle, <span class="math-container">$\varepsilon$</span> is the obliquity of the ecliptic, and <span class="math-container">$\phi$</span> is the latitude of the observer (north positive, south negative).</p>
<p>The mean rotation of the Earth relative to the stars is 360° in 24 sidereal hours. So we can convert sidereal time in hours to sidereal time in degrees by multiplying by 15.</p>
<p>The local sidereal time can be calculated by adding the observer's longitude to the Greenwich sidereal time (east longitude positive, west longitude negative). Of course, for this equation to make sense both quantities must be in the same units, so we need to divide the longitude in degrees by 15 to convert it to hours. Conversely, we can just multiply the sidereal time by 15 to convert it to degrees, since we need it in angle format for the Ascendant calculation.</p>
<p>So,</p>
<p><span class="math-container">$$\theta_{\rm L} = \theta_{\rm G} + \lambda$$</span></p>
<p>where <span class="math-container">$\theta_{\rm G}$</span> is the Greenwich sidereal time expressed as an angle in degrees, and <span class="math-container">$\lambda$</span> is the longitude of the observer (in degrees).</p>
<p>We also need the <a href="https://en.m.wikipedia.org/wiki/Axial_tilt?searchToken=dlcomnfwbh92vkzskxzphnssx#Short_term" rel="nofollow noreferrer">obliquity of the ecliptic</a>. Wikipedia gives various polynomial expressions. The equation from the <em>Astronomical Almanac</em> for 2010 is good for several centuries either side of the present era. There's also an equation from Laskar which is less precise, but it's valid for a span of 10,000 years.</p>
<p>The Greenwich Mean Sidereal Time (GMST) can be computed using a polynomial given in the JPL <a href="https://ssd.jpl.nasa.gov/horizons/manual.html#greenwich-mean-sidereal-time" rel="nofollow noreferrer">Horizons manual</a>.</p>
<hr />
<p>I need to digress briefly to discuss the ecliptic coordinate system. The ecliptic is the Earth's orbital plane, so the Sun's apparent path lies on the ecliptic. The Moon's orbit is inclined by ~5.145° to the ecliptic, so the Moon is always within 5.145° of the ecliptic, and all the planets are within 8° of the ecliptic, as I mention in <a href="https://astronomy.stackexchange.com/a/54313/16685">this answer</a>.</p>
<p>The band 8° either side of the ecliptic is known as the zodiac. In the ecliptic coordinate system the position of a point on the celestial sphere is given in terms of ecliptic longitude and ecliptic latitude. The ecliptic longitude is zero at the March equinox point, and increases in the direction of the Sun's motion. The ecliptic latitude gives the angular distance above or below the ecliptic (north positive, south negative).</p>
<p>Modern astronomy prefers to locate points on the celestial sphere using the equatorial coordinate system of Right Ascension (RA) and Declination, which is based on the celestial equator plane rather than the ecliptic. The March equinox point has zero RA and zero declination. Declination gives the angular distance above or below the celestial equator. This system became prominent after the invention of the telescope. It's very convenient when using a telescope with an equatorial mount.</p>
<p>However, for most of history, the ecliptic coordinate system was the main way to specify celestial points. It goes back to the ancient Babylonian astronomers, if not earlier.</p>
<p>You can give ecliptic longitude in degrees, but it was traditional to use zodiac notation. This notation has fallen out of use in astronomy, but it's still very popular in astrology. This notation simplifies the arithmetic of calculating the angle between two longitudes.</p>
<p>In zodiac notation, the ecliptic is divided into 12 equal sections of 30°. These sections are called signs, and they're named after the constellations near the zodiac. In ancient times, the signs roughly corresponded with the constellations, but they've drifted out of sync in the last couple of millennia, due to the precession of the equinoxes.</p>
<p>The first sign is Aries, the second sign is Taurus, etc. In zodiac notation, ecliptic longitude of 10°20' is written 10 Aries 20. Ecliptic longitude 45°10` is written 15 Taurus 10. Etc. It's traditional to write zodiac notation using the traditional sign symbols. (There are Unicode glyphs for these symbols, but they're a bit bulky, in my opinion).</p>
<p>The March equinox point is 0 Aries 0. It's often called the First Point of Aries, even in modern astronomy. Why the first point? This system is ancient! It was devised long before zero was invented. :)</p>
<p>The sign containing the Ascendant is known as the rising sign. It's literally the section of the ecliptic which is currently rising on the rational horizon.</p>
<hr />
<p>Here's a Python script which calculates the obliquity, GMST, local sidereal time, and the ascendant. You must supply the time in UTC, <em>not</em> local time. The script uses Sage features to read the date &amp; time and location data from the GUI, but the rest of the program is plain Python. It uses the standard <code>datetime</code> module to parse the date &amp; time, but it uses no 3rd party libraries.</p>
<p>The date must be given in <code>YYYY-Mon-DD</code> format. That is, a 4 digit year, followed by the 3 letter abbreviation of the month name, followed by a 1 or 2 digit day, with <code>-</code> between the fields. The UTC time field is a little more flexible. It may be specified with or without seconds, and you may specify fractional seconds, with upto 6 digits after the decimal point.</p>
<p>Latitude and longitude must be given in decimal degrees. However, you can write arithmetic expressions in those input boxes. For example, you can input 40°N 43' latitude as <code>40 + 43/60</code>.</p>
<p>The script prints the Ascendant in both zodiac notation and degrees.</p>
<pre><code>&quot;&quot;&quot; Calculate the ascendant from the UTC time and location

    The ascendant is the ecliptic longitude on the rational horizon
    See https://en.wikipedia.org/wiki/Ascendant

    Obliquity &amp; sidereal time equations from JPL
    Written by PM 2Ring 2024.02.01
&quot;&quot;&quot;

from datetime import datetime, timedelta, timezone
from math import sin, cos, tan, atan2, degrees, radians

def parse_datetime(dtstr):
    for tfmt in (' %H:%M', ' %H:%M:%S', ' %H:%M:%S.%f', ''):
        try:
            dt = datetime.strptime(dtstr, '%Y-%b-%d' + tfmt)
            break
        except ValueError:
            continue
    else:
        print(&quot;Bad date time string:&quot;, dtstr)
        return None
    return dt.replace(tzinfo=timezone.utc)

def hms(t):
    h = int(t)
    t = 60 * (t - h)
    m = int(t)
    t = 60 * (t - m)
    return f&quot;{h:&gt;2}:{m:02}:{t:06.3f}&quot;

zodiac = &quot;Ari Tau Gem Can Leo Vir Lib Sco Sag Cap Aqu Pis&quot;.split()
def sdms(t):
    z = int(float(t) // 30)
    t -= 30 * z
    d = int(t)
    m = 60 * (t - d)
    return f&quot;{d:2} {zodiac[z]} {m:4.1f}&quot;

# J2000 epoch
day_zero = datetime(2000, 1, 1, 12, tzinfo=timezone.utc)

@interact
def _(txt=HtmlBox('&lt;h3&gt;Ascendant&lt;/h3&gt;Date format: YYYY-Mon-DD'),
  dtstr=('Date &amp; Time, UTC', '2000-Jan-1 12:00'),
  lat=('Latitude', 51.4773207),
  lon=('Longitude (east)', 0.0),
  auto_update=False):

    dt = parse_datetime(dtstr.strip())
    if dt is None:
        return

    lon, lat = float(lon), float(lat)

    # Convert to days since Noon, 1 Jan 2000
    d = (dt - day_zero).total_seconds() / 86400

    # Julian centuries
    T = d / 36525

    # Obliquity of the ecliptic. T should be Terrestrial Time
    oe = ((((-4.34e-8*T - 5.76e-7)*T + 0.0020034)*T - 1.831e-4)*T - 46.836769)*T / 3600 + 23.4392794444444
    oer = radians(oe)
    print(&quot;Obliquity:&quot;, oe)

    # Greenwich Mean Sidereal Time
    gmst = (67310.548 + (3155760000 + 8640184.812866) * T
      + 0.093104 * T**2 - 6.2e-6 * T**3) / 3600 % 24
    print('Greenwich sidereal time:', hms(gmst))

    lst = (gmst + lon / 15) % 24
    print('    Local sidereal time:', hms(lst))

    # Local sidereal time, in radians
    lstr = radians(lst * 15)

    # Ascendant
    ascr = atan2(cos(lstr), -(sin(lstr) * cos(oer) + tan(radians(lat)) * sin(oer)))
    asc = degrees(ascr) % 360
    print(f&quot;Ascendant: {sdms(asc)} = {asc}°&quot;)
</code></pre>
<p>I've tested this script against various online calculators, including the <a href="https://aa.usno.navy.mil/data/siderealtime" rel="nofollow noreferrer">Sidereal Time</a> service of the USNO. My sidereal times agree with the USNO values to sub-second precision.</p>
<p>Here's a <a href="https://sagecell.sagemath.org/?z=eJx9Vulu20YQ%5Fq%2DnGDBQRNoixUuUTMRBE7tNYNhtUKspgqIwVuTKWoTkMstlE8vwO%5FUZ%2DmSdWVJXapQw7J2d65tzbVkWXLAiawumOeg1B9ZkvMpZpWGlZGmufltcgBYl8qocCpkxLWQ1GAB%2DiyMN0Rh5nhWi1iJD2epe6DbnICvDUUaVFbCWSmzQCNm45RzWWtdNOpnwyvsqPoua54J5Ut1PiJq82XronP6yLMSXVugHeAmNyLniaNEA5F9a46HpwF99uDYKvyuhNa9g%2DQAfbiD8VVT3EPph7Pmh5wcDy7IGA6OQYxaMIVHWUukdPTbmc15o1h0RO%2D9USqbXW%5FFGVGPIZIMyDE8Mf4djyPm94hwvFcOoqmYwyPkKaqYafrd1YOe60cpJDdyVVKBXJeazAnsEw%5Ffp8GY0hv6UDm%2DPCG%2D4InrUK9On1cOeoC%5FXcL4LxkNP9d4p6g4%5FucOlO8xHcGocO0fKS8zv590N%5F5bxWsNHVrT8R6WkOvaUyUqLquXmkhcN37NrJSptW29ZbqB0FUMAWI3UwjSZDOykFdetquBnSvQBnWtP8bpgGbf1RlQreb4th9fqzOlyuy4bW%5Ff5WGPk5LcPihKR%2DHACtgYX1t1l%2DX8ypXPof2U9rtPX4VP6WKY%2D%5FdGpn3jR6glbaCOxvhkqW2%2DUgAVr4R0vcbwquOYSPgoF12IJt5mEW3aP9zW8%2DdLCB9FYXlMXQtuOQd%5FkB%5FA3PbRVIRkBhMkEIn%2DL0z1HAoFuDJ0fh1EehZF%5FH0aehk%5Fw2GH%2DY%5FMnnss09gITyQu4Cn3fB17LbD3I2cPdhit50EM2sccQdD%5FY5M8X4weEwxXLtAnsztbf9Pl7XRZv5Td79Godvd5N9qsJUpfUFtj9OFMpfMLPvZGVe3k5csYD6Brk3B4ZqZewMHOJu4m6n%2DC4V6xyA0ST%2Dn6ngUsN5a9xJdASQrlp4MWzWRT6s44vK%2DLvtpTNWaMdlPM93wiwVsu7tqaoz39i2M1YlcFuoJ4bYRouUdtOl22xIklci9TG6Xe93VlCDGMCiva6GuOFM96eGdbSiL2AC1n9xXHJaIlVeGho2WQcDZN%2DABg7UBJ2jYBwqOp96RxPS82Ku4bjgOaNjX0E8yRG%2Dd76VVvgbgKsBkITvOm2O1UcJaNkGk63kvvtK1dH695D%2DWYt2yKHJYcFV4pTMnA3U6mMtuSEDD839qKYu%5FOTBYKcerOEuzMHiVNKvY%2DBRLFjeIE3jwLu9lScIJnMkjMiCRf26CmEkRdHZ%2DHsLO6%2D3pVCX%5F3KtSXvCtLvoF0MtHiI18f2Dhd19VVka7jhmI3b7eOyC%2DC%2DbKhSdjKLAt%2DbxnN0b0fBdDpDKAYMZTWYx948COdJ4uD4Lfq6m9jOUC%2Dmy5OTEANKvJC7SUdHzjakIYTxAdzRHtbRc5dip9KqI1BOH0PR4TM4T6m50GYwdf5jko7X%2DJQXz5ss9hZfPCc3prdp%2D571fg%5FzTTBOyPHWxv4JJxr%5FZSBp80Da%2DGCSvMKud23s6o5AdWJgGR16lVhl72zjUBCbRIndzxrapHbtHlubPFDUmM%2DDsFfWDkcKj2bRoqDzhIqPeHj652%5FLGfwLI1CUrw==&amp;lang=python" rel="nofollow noreferrer">live version</a> of the script, running on the SageMathCell server.</p>

CC BY-SA 4.0
2024-02-01T23:14:15.970Z
2024-02-01T23:21:57.997Z
2024-02-01T23:21:57.997Z
PM 2Ring
<p>I am new to astronomy, and trying to learn how to use Skyfield to calculate the rising sign/constellation (typically referred to as the Ascendant in astrology).</p>
<p>I tried a number of approaches based on what I have learnt so far:</p>
<ol>
<li>Using GMST and subtracting 90 degrees, assuming that GMST is providing the Vernal equinox/Aries cusp from the prime meridian, and 90 degree east is rising</li>
<li>Tried subtracting azimuth from planet's longitude - again with the same logic that azimuth is measuring planet's position relative to North.</li>
</ol>
<p>Is there an easier way to determine the rising sign/constellation - and the ascendant? This is a hobby project for me - to try to understand astronomical calculations behind astrology.</p>
<p>Still learning and will appreciate the guidance from the Skyfield community.</p>

CC BY-SA 4.0
2024-02-01T05:10:05.223Z
Sorry, but astrology questions are not popular on this site. They aren't exactly off-topic when they're purely astronomical (or related to the historical development of astronomy), but even then they're merely tolerated, not encouraged. It's probably best to ask such questions without referring to astrology at all, if possible.
PM 2Ring
CC BY-SA 4.0
2024-02-01T05:13:59.447Z
Wikipedia's Ascendant page gives the equation for the ecliptic longitude on an observer's (rational) eastern horizon. You need the local sidereal time, the observer's latitude, and the obliquity of the ecliptic. You can calculate the local sidereal time from the Greenwich sidereal time and the observer's longitude.
PM 2Ring
CC BY-SA 4.0
2024-02-01T06:44:21.333Z
You;re probably better off with "swisseph" package.
James K
CC BY-SA 4.0
2024-02-01T07:05:01.850Z
@PM2Ring *Disagree!* The question asks how to determine a specific thing (a rising star or constellation at a specified time) using the Python package Skyfield. It does not ask any question about astrology. **This is not an "astrology question".** Don't fault the question author for explaining some context. That's the mark of a good question because it helps the answer authors calibrate their answer and perhaps add additional information helpful to the OP. If we don't add helpful background, there's always some user who will then add a "why are you asking, what are you trying to do" comment.
uhoh
CC BY-SA 4.0
2024-02-01T07:10:27.497Z
*Welcome to Stack Exchange* @MGL! You can check these documentation pages. Also, could you explain if you have a time and want to search for what's rising, or want to specify the thing and then ask for its rising time? [API Reference — Almanac](https://rhodesmill.org/skyfield/api-almanac.html), and [Searching for the dates of astronomical events](https://rhodesmill.org/skyfield/searches.html), and [Examples](https://rhodesmill.org/skyfield/examples.html)
uhoh
CC BY-SA 4.0
2024-02-01T07:33:59.230Z
@PM2Ring my concern is that lots of people read comments, and there are many users who seem to go directly from the title to the comment section, and if they see a "Sorry, but..." they vote to insta-close and move on. In Stack Exchange we don't have the concept of private messages - you can't address only the OP. If I wanted to help I would not start with "Sorry" (a negative with some finality) but instead "Welcome to Stack Exchange! I see that you are asking about rise times and Skyfield, but some readers here may incorrectly focus on "Astrology" and think you're asking about that."
uhoh
CC BY-SA 4.0
2024-02-01T07:34:30.757Z
"...so I've gone ahead and made a small edit to your question to emphasize the "rise times with Skyfield" aspects." This way it's clear to even title & comment skimmers that you're not suggesting the question is about Astrology. Once you get more experience *asking* questions and getting them closed incorrectly, you'll better appreciate the power of negative comments.
uhoh
CC BY-SA 4.0
2024-02-01T07:37:12.540Z
@PM2Ring question is related to stars or constellations and which one(s) were rising at a specified time, no?  It doesn't matter why the person wants to do the calculation, it's still an astronomical calculation. Better to close as a duplicate (so the OP can use Skyfield) if there is a good one, than to propose it's off topic, since it isn't.
uhoh
CC BY-SA 4.0
2024-02-01T07:40:27.773Z
Suppose the parenthetical were removed, isn't it the same question? Isn't that a distinction without a difference? "We would answer your question about finding rising times using Skyfield, except that in a parenthetical you mentioned you are playing around with Astrology. Now we're not gonna answer it"?
uhoh
CC BY-SA 4.0
2024-02-01T07:43:03.513Z
Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/151214/discussion-between-pm-2ring-and-uhoh).
PM 2Ring
CC BY-SA 4.0
2024-02-01T07:45:20.720Z
@PM2Ring From [Community Policy Repository](https://astronomy.meta.stackexchange.com/q/560/7982) see [this answer to *Can we consider Indian Astrology as astronomy?*](https://astronomy.meta.stackexchange.com/a/538/7982) "That said, **if the questions are motivated by astrological sources but concern only astronomical phenomena, then they are on topic.**"
uhoh
<skyfield>
Rising sign/constellation at a given time and place
MGL
# Rising sign/constellation at a given time and place

(Asked by: username_0 on 2024-01-31)

I am new to astronomy, and trying to learn how to use Skyfield to calculate the rising sign/constellation (typically referred to as the Ascendant in astrology).

I tried a number of approaches based on what I have learnt so far:

1. Using GMST and subtracting 90 degrees, assuming that GMST is providing the Vernal equinox/Aries cusp from the prime meridian, and 90 degree east is rising
2. Tried subtracting azimuth from planet's longitude - again with the same logic that azimuth is measuring planet's position relative to North.

Is there an easier way to determine the rising sign/constellation - and the ascendant? This is a hobby project for me - to try to understand astronomical calculations behind astrology.

Still learning and will appreciate the guidance from the Skyfield community.

**Tags:** skyfield
> **Comments:**
> **username_1**: Sorry, but astrology questions are not popular on this site. They aren't exactly off-topic when they're purely astronomical (or related to the historical development of astronomy), but even then they're merely tolerated, not encouraged. It's probably best to ask such questions without referring to astrology at all, if possible.  
> **username_1**: Wikipedia's Ascendant page gives the equation for the ecliptic longitude on an observer's (rational) eastern horizon. You need the local sidereal time, the observer's latitude, and the obliquity of the ecliptic. You can calculate the local sidereal time from the Greenwich sidereal time and the observer's longitude.  
> **username_2**: You;re probably better off with "swisseph" package.  
> **username_3**: @PM2Ring *Disagree!* The question asks how to determine a specific thing (a rising star or constellation at a specified time) using the Python package Skyfield. It does not ask any question about astrology. **This is not an "astrology question".** Don't fault the question author for explaining some context. That's the mark of a good question because it helps the answer authors calibrate their answer and perhaps add additional information helpful to the OP. If we don't add helpful background, there's always some user who will then add a "why are you asking, what are you trying to do" comment.  
> **username_3**: *Welcome to Stack Exchange* @MGL! You can check these documentation pages. Also, could you explain if you have a time and want to search for what's rising, or want to specify the thing and then ask for its rising time? [API Reference — Almanac](https://rhodesmill.org/skyfield/api-almanac.html), and [Searching for the dates of astronomical events](https://rhodesmill.org/skyfield/searches.html), and [Examples](https://rhodesmill.org/skyfield/examples.html)  
> **username_3**: @PM2Ring my concern is that lots of people read comments, and there are many users who seem to go directly from the title to the comment section, and if they see a "Sorry, but..." they vote to insta-close and move on. In Stack Exchange we don't have the concept of private messages - you can't address only the OP. If I wanted to help I would not start with "Sorry" (a negative with some finality) but instead "Welcome to Stack Exchange! I see that you are asking about rise times and Skyfield, but some readers here may incorrectly focus on "Astrology" and think you're asking about that."  
> **username_3**: "...so I've gone ahead and made a small edit to your question to emphasize the "rise times with Skyfield" aspects." This way it's clear to even title & comment skimmers that you're not suggesting the question is about Astrology. Once you get more experience *asking* questions and getting them closed incorrectly, you'll better appreciate the power of negative comments.  
> **username_3**: @PM2Ring question is related to stars or constellations and which one(s) were rising at a specified time, no?  It doesn't matter why the person wants to do the calculation, it's still an astronomical calculation. Better to close as a duplicate (so the OP can use Skyfield) if there is a good one, than to propose it's off topic, since it isn't.  
> **username_3**: Suppose the parenthetical were removed, isn't it the same question? Isn't that a distinction without a difference? "We would answer your question about finding rising times using Skyfield, except that in a parenthetical you mentioned you are playing around with Astrology. Now we're not gonna answer it"?  
> **username_1**: Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/151214/discussion-between-pm-2ring-and-uhoh).  
> **username_3**: @PM2Ring From [Community Policy Repository](https://astronomy.meta.stackexchange.com/q/560/7982) see [this answer to *Can we consider Indian Astrology as astronomy?*](https://astronomy.meta.stackexchange.com/a/538/7982) "That said, **if the questions are motivated by astrological sources but concern only astronomical phenomena, then they are on topic.**"  

---

## 1 answers

### Answer by username_1 on 2024-02-01. Score: 2

The Ascendant-Descendant axis is the line of intersection of the ecliptic plane with the rational horizon. The ecliptic is the plane of the Earth's orbit. The rational horizon is the plane through the geocentre (the Earth's centre) which is parallel to the observer's local horizon. So the Ascendant-Descendant axis passes through the geocentre. The Ascendant is to the east, the Descendant is to the west. Hence the Ascendant is the point on the ecliptic that is currently rising.
Here's a diagram from an article on the Astrodienst site, Astronomical Foundations of the Astrological Houses, by Christopher A. Weidner.

We can easily calculate the Ascendant using spherical trigonometry. Wikipedia gives the equation, but it's in a slightly misleading format. Here's a better version:
$$\lambda_{\rm Asc} = \arctan \left(\frac{\cos\theta_{\rm L}}{-(\sin\theta_{\rm L} \cos\varepsilon + \tan\phi \sin\varepsilon)} \right)$$
where $\theta_{\rm L}$ is the local sidereal time, expressed as an angle, $\varepsilon$ is the obliquity of the ecliptic, and $\phi$ is the latitude of the observer (north positive, south negative).
The mean rotation of the Earth relative to the stars is 360° in 24 sidereal hours. So we can convert sidereal time in hours to sidereal time in degrees by multiplying by 15.
The local sidereal time can be calculated by adding the observer's longitude to the Greenwich sidereal time (east longitude positive, west longitude negative). Of course, for this equation to make sense both quantities must be in the same units, so we need to divide the longitude in degrees by 15 to convert it to hours. Conversely, we can just multiply the sidereal time by 15 to convert it to degrees, since we need it in angle format for the Ascendant calculation.
So,
$$\theta_{\rm L} = \theta_{\rm G} + \lambda$$
where $\theta_{\rm G}$ is the Greenwich sidereal time expressed as an angle in degrees, and $\lambda$ is the longitude of the observer (in degrees).
We also need the obliquity of the ecliptic. Wikipedia gives various polynomial expressions. The equation from the Astronomical Almanac for 2010 is good for several centuries either side of the present era. There's also an equation from Laskar which is less precise, but it's valid for a span of 10,000 years.
The Greenwich Mean Sidereal Time (GMST) can be computed using a polynomial given in the JPL Horizons manual.

I need to digress briefly to discuss the ecliptic coordinate system. The ecliptic is the Earth's orbital plane, so the Sun's apparent path lies on the ecliptic. The Moon's orbit is inclined by ~5.145° to the ecliptic, so the Moon is always within 5.145° of the ecliptic, and all the planets are within 8° of the ecliptic, as I mention in this answer.
The band 8° either side of the ecliptic is known as the zodiac. In the ecliptic coordinate system the position of a point on the celestial sphere is given in terms of ecliptic longitude and ecliptic latitude. The ecliptic longitude is zero at the March equinox point, and increases in the direction of the Sun's motion. The ecliptic latitude gives the angular distance above or below the ecliptic (north positive, south negative).
Modern astronomy prefers to locate points on the celestial sphere using the equatorial coordinate system of Right Ascension (RA) and Declination, which is based on the celestial equator plane rather than the ecliptic. The March equinox point has zero RA and zero declination. Declination gives the angular distance above or below the celestial equator. This system became prominent after the invention of the telescope. It's very convenient when using a telescope with an equatorial mount.
However, for most of history, the ecliptic coordinate system was the main way to specify celestial points. It goes back to the ancient Babylonian astronomers, if not earlier.
You can give ecliptic longitude in degrees, but it was traditional to use zodiac notation. This notation has fallen out of use in astronomy, but it's still very popular in astrology. This notation simplifies the arithmetic of calculating the angle between two longitudes.
In zodiac notation, the ecliptic is divided into 12 equal sections of 30°. These sections are called signs, and they're named after the constellations near the zodiac. In ancient times, the signs roughly corresponded with the constellations, but they've drifted out of sync in the last couple of millennia, due to the precession of the equinoxes.
The first sign is Aries, the second sign is Taurus, etc. In zodiac notation, ecliptic longitude of 10°20' is written 10 Aries 20. Ecliptic longitude 45°10` is written 15 Taurus 10. Etc. It's traditional to write zodiac notation using the traditional sign symbols. (There are Unicode glyphs for these symbols, but they're a bit bulky, in my opinion).
The March equinox point is 0 Aries 0. It's often called the First Point of Aries, even in modern astronomy. Why the first point? This system is ancient! It was devised long before zero was invented. :)
The sign containing the Ascendant is known as the rising sign. It's literally the section of the ecliptic which is currently rising on the rational horizon.

Here's a Python script which calculates the obliquity, GMST, local sidereal time, and the ascendant. You must supply the time in UTC, not local time. The script uses Sage features to read the date & time and location data from the GUI, but the rest of the program is plain Python. It uses the standard datetime module to parse the date & time, but it uses no 3rd party libraries.
The date must be given in YYYY-Mon-DD format. That is, a 4 digit year, followed by the 3 letter abbreviation of the month name, followed by a 1 or 2 digit day, with - between the fields. The UTC time field is a little more flexible. It may be specified with or without seconds, and you may specify fractional seconds, with upto 6 digits after the decimal point.
Latitude and longitude must be given in decimal degrees. However, you can write arithmetic expressions in those input boxes. For example, you can input 40°N 43' latitude as 40 + 43/60.
The script prints the Ascendant in both zodiac notation and degrees.
""" Calculate the ascendant from the UTC time and location

    The ascendant is the ecliptic longitude on the rational horizon
    See https://en.wikipedia.org/wiki/Ascendant

    Obliquity & sidereal time equations from JPL
    Written by PM 2Ring 2024.02.01
"""

from datetime import datetime, timedelta, timezone
from math import sin, cos, tan, atan2, degrees, radians

def parse_datetime(dtstr):
    for tfmt in (' %H:%M', ' %H:%M:%S', ' %H:%M:%S.%f', ''):
        try:
            dt = datetime.strptime(dtstr, '%Y-%b-%d' + tfmt)
            break
        except ValueError:
            continue
    else:
        print("Bad date time string:", dtstr)
        return None
    return dt.replace(tzinfo=timezone.utc)

def hms(t):
    h = int(t)
    t = 60 * (t - h)
    m = int(t)
    t = 60 * (t - m)
    return f"{h:>2}:{m:02}:{t:06.3f}"

zodiac = "Ari Tau Gem Can Leo Vir Lib Sco Sag Cap Aqu Pis".split()
def sdms(t):
    z = int(float(t) // 30)
    t -= 30 * z
    d = int(t)
    m = 60 * (t - d)
    return f"{d:2} {zodiac[z]} {m:4.1f}"

# J2000 epoch
day_zero = datetime(2000, 1, 1, 12, tzinfo=timezone.utc)

@interact
def _(txt=HtmlBox('AscendantDate format: YYYY-Mon-DD'),
  dtstr=('Date & Time, UTC', '2000-Jan-1 12:00'),
  lat=('Latitude', 51.4773207),
  lon=('Longitude (east)', 0.0),
  auto_update=False):

    dt = parse_datetime(dtstr.strip())
    if dt is None:
        return

    lon, lat = float(lon), float(lat)

    # Convert to days since Noon, 1 Jan 2000
    d = (dt - day_zero).total_seconds() / 86400

    # Julian centuries
    T = d / 36525

    # Obliquity of the ecliptic. T should be Terrestrial Time
    oe = ((((-4.34e-8*T - 5.76e-7)*T + 0.0020034)*T - 1.831e-4)*T - 46.836769)*T / 3600 + 23.4392794444444
    oer = radians(oe)
    print("Obliquity:", oe)

    # Greenwich Mean Sidereal Time
    gmst = (67310.548 + (3155760000 + 8640184.812866) * T
      + 0.093104 * T**2 - 6.2e-6 * T**3) / 3600 % 24
    print('Greenwich sidereal time:', hms(gmst))

    lst = (gmst + lon / 15) % 24
    print('    Local sidereal time:', hms(lst))

    # Local sidereal time, in radians
    lstr = radians(lst * 15)

    # Ascendant
    ascr = atan2(cos(lstr), -(sin(lstr) * cos(oer) + tan(radians(lat)) * sin(oer)))
    asc = degrees(ascr) % 360
    print(f"Ascendant: {sdms(asc)} = {asc}°")

I've tested this script against various online calculators, including the Sidereal Time service of the USNO. My sidereal times agree with the USNO values to sub-second precision.
Here's a live version of the script, running on the SageMathCell server.


---

