diff --git a/.gitignore b/.gitignore index 9f38193..1a2913a 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ venv/ # Build build/ + +# Ignore vim swp files +*.swp diff --git a/.main.py.swp b/.main.py.swp new file mode 100644 index 0000000..d088aa4 Binary files /dev/null and b/.main.py.swp differ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9e26b03 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,29 @@ +# Changelog +--- +## const.py + * Added LIST_OBJECTS as a common source for assignement of the + default Object list + * Added list with ten planest for modern astrology - LIST_TEN_PLANETS + * Added list of aspecing planets - LIST_ASP_PLANTES + * Added list with harmonious aspects - LIST_ASPECTS_POS + * Added list with hard aspects - LIST_ASPECTS_NEG + * Added list with tight orbs - LIST_ORBS_TIGHT + * Added list with wide orbs - LIST_WIDE_ORBS + * Defined a common orbs list LIST_IRBS for asignement + * Added constant MINUTE for Julian calendar claculations + * Added constant HOUR for Julian calendar calculations + +--- +## chart.py + * Changed Traditional list of objects with the general list LIST_OBJECTS + so the asignement can happen in the *const.py* + * Removed assignement of a default house system @ 166 + * Changed default house system to Placidus + +--- +## object.py + * Changed the traditional house offset from -5deg to 0deg + +--- +## props.py + * Feeds orbs from the const.py rather than being hardcoded diff --git a/flatlib/angle.py b/flatlib/angle.py index 2ba790f..7f8e4bc 100644 --- a/flatlib/angle.py +++ b/flatlib/angle.py @@ -61,7 +61,7 @@ def _fixSlist(slist): def _roundSlist(slist): """ Rounds a signed list over the last element and removes it. """ slist[-1] = 60 if slist[-1] >= 30 else 0 - for i in range(len(slist) - 1, 1, -1): + for i in range(len(slist)-1, 0, -1): if slist[i] == 60: slist[i] = 0 slist[i - 1] += 1 diff --git a/flatlib/chart.py b/flatlib/chart.py index fe0de7f..ed1797e 100644 --- a/flatlib/chart.py +++ b/flatlib/chart.py @@ -45,8 +45,8 @@ def __init__(self, date, pos, **kwargs): """ # Handle optional arguments hsys = kwargs.get('hsys', const.HOUSES_DEFAULT) - IDs = kwargs.get('IDs', const.LIST_OBJECTS_TRADITIONAL) - + IDs = kwargs.get('IDs', const.LIST_OBJECTS) + self.date = date self.pos = pos self.hsys = hsys @@ -161,4 +161,4 @@ def solarReturn(self, year): '00:00', self.date.utcoffset) srDate = ephem.nextSolarReturn(date, sun.lon) - return Chart(srDate, self.pos, hsys=self.hsys) + return Chart(srDate, self.pos) diff --git a/flatlib/const.py b/flatlib/const.py index 77f2a5b..f62c10d 100644 --- a/flatlib/const.py +++ b/flatlib/const.py @@ -159,7 +159,7 @@ HOUSES_POLICH_PAGE = 'Polich Page' HOUSES_ALCABITUS = 'Alcabitus' HOUSES_MORINUS = 'Morinus' -HOUSES_DEFAULT = HOUSES_ALCABITUS +HOUSES_DEFAULT = HOUSES_PLACIDUS # === Angles === */ @@ -267,6 +267,19 @@ LIST_SEVEN_PLANETS = [ SUN, MOON, MERCURY, VENUS, MARS, JUPITER, SATURN ] +"""MH on 2018/3/3 - List of 10 plantes for modern astrology""" +LIST_TEN_PLANETS = [ + SUN, MOON, MERCURY, VENUS, MARS, JUPITER, SATURN, NEPTUNE, URANUS, PLUTO +] + +"""MH on 2018/3/4 - List of aspecting planets""" + +#LIST_OBJECTS = LIST_TEN_PLANETS + +LIST_ASP_PLANETS = [ + SUN, MERCURY, VENUS, MARS, JUPITER, SATURN, NEPTUNE, URANUS, PLUTO, NORTH_NODE, SOUTH_NODE +] + LIST_HOUSES = [ HOUSE1, HOUSE2, HOUSE3, HOUSE4, HOUSE5, HOUSE6, @@ -289,3 +302,74 @@ STAR_LESATH, STAR_VEGA, STAR_ALTAIR, STAR_DENEB_ALGEDI, STAR_FOMALHAUT, STAR_DENEB_ADIGE, STAR_ACHERNAR, ] + +"""MH on 2018/3/6 - List of Positive Aspects""" +LIST_ASPECTS_POS = [ + SEXTILE, TRINE +] + +"""MH on 2018/3/6 - List of Negative Aspects""" +LIST_ASPECTS_NEG = [ + SQUARE, OPPOSITION +] + +"""MH on 2018/3/6 - List of tight orbs""" + +LIST_ORBS_TIGHT = { + NO_PLANET: 0, + SUN: 15, + MOON: 12, + MERCURY: 7, + VENUS: 7, + MARS: 8, + JUPITER: 9, + SATURN: 9, + URANUS: 5, + NEPTUNE: 5, + PLUTO: 5, + CHIRON: 5, + NORTH_NODE: 12, + SOUTH_NODE: 12, + SYZYGY: 0, + PARS_FORTUNA: 0 +} + +"""MH on 2018/3/6 - List of wide orbs""" +LIST_ORBS_WIDE = { + NO_PLANET: 0, + SUN: 5, + MOON: 4, + MERCURY: 2, + VENUS: 2, + MARS: 3, + JUPITER: 3, + SATURN: 3, + URANUS: 2, + NEPTUNE: 1, + PLUTO: 3, + CHIRON: 1, + NORTH_NODE: 2, + SOUTH_NODE: 2, + SYZYGY: 0, + PARS_FORTUNA: 0 +} + +LIST_ORBS = LIST_ORBS_TIGHT + +"""MH on 2018/3/18""" +LIST_RULERS = {ARIES:MARS, + TAURUS:VENUS, + GEMINI:MERCURY, + CANCER:MOON, + LEO:SUN, + VIRGO:MERCURY, + LIBRA:VENUS, + SCORPIO:PLUTO, + SAGITTARIUS:JUPITER, + CAPRICORN:SATURN, + AQUARIUS:URANUS, + PISCES:NEPTUNE} + +"""MH on 2018/3/9 - Time constants""" +MINUTE = 0.00069444440305233 +HOUR = 0.04166666651144624 diff --git a/flatlib/ephem/eph.py b/flatlib/ephem/eph.py index b824f8a..94e6ba0 100644 --- a/flatlib/ephem/eph.py +++ b/flatlib/ephem/eph.py @@ -106,13 +106,6 @@ def lastSunset(jd, lat, lon): return nextSunset(jd - 1.0, lat, lon) -# === Stations === # - -def nextStation(ID, jd): - """ Returns the aproximate jd of the next station. """ - return tools.nextStationJD(ID, jd) - - # === Other functions === # def _signInfo(obj): @@ -121,4 +114,4 @@ def _signInfo(obj): obj.update({ 'sign': const.LIST_SIGNS[int(lon / 30)], 'signlon': lon % 30 - }) + }) \ No newline at end of file diff --git a/flatlib/ephem/ephem.py b/flatlib/ephem/ephem.py index bb077d9..29bc7fe 100644 --- a/flatlib/ephem/ephem.py +++ b/flatlib/ephem/ephem.py @@ -14,7 +14,6 @@ """ from . import eph -from . import swe from flatlib.datetime import Datetime from flatlib.object import (GenericObject, Object, @@ -114,53 +113,3 @@ def lastSunset(date, pos): """ Returns the date of the last sunset. """ jd = eph.lastSunset(date.jd, pos.lat, pos.lon) return Datetime.fromJD(jd, date.utcoffset) - - -# === Station === # - -def nextStation(ID, date): - """ Returns the aproximate date of the next station. """ - jd = eph.nextStation(ID, date.jd) - return Datetime.fromJD(jd, date.utcoffset) - - -# === Eclipses === # - -def prevSolarEclipse(date): - """ Returns the Datetime of the maximum phase of the - previous global solar eclipse. - - """ - - eclipse = swe.solarEclipseGlobal(date.jd, backward=True) - return Datetime.fromJD(eclipse['maximum'], date.utcoffset) - - -def nextSolarEclipse(date): - """ Returns the Datetime of the maximum phase of the - next global solar eclipse. - - """ - - eclipse = swe.solarEclipseGlobal(date.jd, backward=False) - return Datetime.fromJD(eclipse['maximum'], date.utcoffset) - - -def prevLunarEclipse(date): - """ Returns the Datetime of the maximum phase of the - previous global lunar eclipse. - - """ - - eclipse = swe.lunarEclipseGlobal(date.jd, backward=True) - return Datetime.fromJD(eclipse['maximum'], date.utcoffset) - - -def nextLunarEclipse(date): - """ Returns the Datetime of the maximum phase of the - next global lunar eclipse. - - """ - - eclipse = swe.lunarEclipseGlobal(date.jd, backward=False) - return Datetime.fromJD(eclipse['maximum'], date.utcoffset) diff --git a/flatlib/ephem/swe.py b/flatlib/ephem/swe.py index fad14b0..378c081 100644 --- a/flatlib/ephem/swe.py +++ b/flatlib/ephem/swe.py @@ -144,35 +144,3 @@ def sweFixedStar(star, jd): 'lon': sweList[0], 'lat': sweList[1] } - - -# === Eclipses === # - -def solarEclipseGlobal(jd, backward): - """ Returns the jd details of previous or next global solar eclipse. """ - - sweList = swisseph.sol_eclipse_when_glob(jd, backward=backward) - return { - 'maximum': sweList[1][0], - 'begin': sweList[1][2], - 'end': sweList[1][3], - 'totality_begin': sweList[1][4], - 'totality_end': sweList[1][5], - 'center_line_begin': sweList[1][6], - 'center_line_end': sweList[1][7], - } - - -def lunarEclipseGlobal(jd, backward): - """ Returns the jd details of previous or next global lunar eclipse. """ - - sweList = swisseph.lun_eclipse_when(jd, backward=backward) - return { - 'maximum': sweList[1][0], - 'partial_begin': sweList[1][2], - 'partial_end': sweList[1][3], - 'totality_begin': sweList[1][4], - 'totality_end': sweList[1][5], - 'penumbral_begin': sweList[1][6], - 'penumbral_end': sweList[1][7], - } diff --git a/flatlib/ephem/tools.py b/flatlib/ephem/tools.py index b1ac8f3..b490bd1 100644 --- a/flatlib/ephem/tools.py +++ b/flatlib/ephem/tools.py @@ -82,26 +82,10 @@ def solarReturnJD(jd, lon, forward=True): if forward: dist = angle.distance(sun, lon) else: - dist = -angle.distance(lon, sun) - + dist = angle.distance(lon, sun) + while abs(dist) > MAX_ERROR: jd = jd + dist / 0.9833 # Sun mean motion sun = swe.sweObjectLon(const.SUN, jd) dist = angle.closestdistance(sun, lon) - return jd - - -# === Other algorithms === # - -def nextStationJD(ID, jd): - """ Finds the aproximate julian date of the - next station of a planet. - - """ - speed = swe.sweObject(ID, jd)['lonspeed'] - for i in range(2000): - nextjd = jd + i / 2 - nextspeed = swe.sweObject(ID, nextjd)['lonspeed'] - if speed * nextspeed <= 0: - return nextjd - return None + return jd \ No newline at end of file diff --git a/flatlib/moonca.py b/flatlib/moonca.py new file mode 100644 index 0000000..7848984 --- /dev/null +++ b/flatlib/moonca.py @@ -0,0 +1,69 @@ +from flatlib import const +from flatlib.chart import Chart +from flatlib.datetime import Datetime +from flatlib.ephem import swe + +""" +Module to calcualate the moon next ingress and +voc +""" + +# Assign a minute in Julian Calendar +MINUTE = const.MINUTE +# List of house distances +DIST = [0, 2, 3, 4, 6, 8, 9, 10] + +# Mean Moon motion in deg/s +MEAN_MOTION_MOON_S = const.MEAN_MOTION_MOON / 86400 + +MAX_ERROR = 0.0003 + +def next_moon_ingress(chart): + """ + Calculates datetime of the next Moon ingress + """ + + # Define the sign angles + angles = [30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330, 360] + + # Initate local variables + # The next sign angle from the current moon position + angle = 0.0 + # Distance between the current Moon position and the next sign + dist = 0.0 + # Intiate iteration counter for statistical purposes + i = 0 + + # Load the current Moon position + moon_lon = swe.sweObjectLon(const.MOON, chart.date.jd) + + # Find the next sign angle + for ang in angles: + if moon_lon < ang: + angle = ang + dist = ang - moon_lon + break + + # Evalute a mean time in days before the next Moon ingress + jd = dist / const.MEAN_MOTION_MOON + + # Add the 'jd' into the the current Moon position + jd = jd + chart.date.jd + + # Run the loop for calculating the ingress time + while abs(dist) > MAX_ERROR: + # Get Moon longtitude + moon_lon = swe.sweObjectLon(const.MOON, jd) + # Correct value of the moon's longtitude if ingress + # to Aries + if angle == 360 and moon_lon >= 0.0 and moon_lon < 30.0: + moon_lon = moon_lon + 360.0 + + # Calcualte distance + dist = angle - moon_lon + # Calculate position differential + jd = jd + dist / const.MEAN_MOTION_MOON + + i += 1 + return {'Date':Datetime.fromJD(jd, '+00:00'), 'Iter':i} + diff --git a/flatlib/object.py b/flatlib/object.py index f3a6769..5ea8f71 100644 --- a/flatlib/object.py +++ b/flatlib/object.py @@ -176,10 +176,11 @@ def isFast(self): class House(GenericObject): """ This class represents a generic house cusp. """ - + #MH on 2018/04/17 - Removes the tradditional offset of -5deg + _OFFSET = 0.0 # The traditional house offset - _OFFSET = -5.0 - + #_OFFSET = -5.0 + def __init__(self): super().__init__() self.type = const.OBJ_HOUSE diff --git a/flatlib/predictives/primarydirections.py b/flatlib/predictives/primarydirections.py index 26a917a..af40441 100644 --- a/flatlib/predictives/primarydirections.py +++ b/flatlib/predictives/primarydirections.py @@ -5,12 +5,6 @@ This module implements the Primary Directions method. - - Default assumptions: - - only directions with the primary motion (direct) - - only semi-arc method - - in-zodiaco aspects of promissors to significators - - in-mundo directions uses latitude of both promissors and significators """ @@ -266,10 +260,13 @@ def getList(self, aspList): # Promissors objects = self._elements(self.SIG_OBJECTS, self.N, aspList) + houses = self._elements(self.SIG_HOUSES, self.N, [0]) + angles = self._elements(self.SIG_ANGLES, self.N, [0]) terms = self._terms() antiscias = self._elements(self.SIG_OBJECTS, self.A, [0]) cantiscias = self._elements(self.SIG_OBJECTS, self.C, [0]) - promissors = objects + terms + antiscias + cantiscias + promissors = objects + houses + angles + terms + \ + antiscias + cantiscias # Compute all res = [] @@ -289,8 +286,8 @@ def getList(self, aspList): ]) return sorted(res) - - + + # ------------------ # # PD Table Class # # ------------------ # @@ -298,24 +295,24 @@ def getList(self, aspList): class PDTable: """ Represents the Primary Directions table for a chart. - + """ - + def __init__(self, chart, aspList=const.MAJOR_ASPECTS): pd = PrimaryDirections(chart) self.table = pd.getList(aspList) - + def view(self, arcmin, arcmax): """ Returns the directions within the min and max arcs. - + """ res = [] for direction in self.table: if arcmin < direction[0] < arcmax: res.append(direction) return res - + def bySignificator(self, ID): """ Returns all directions to a significator. """ res = [] @@ -323,11 +320,11 @@ def bySignificator(self, ID): if ID in direction[2]: res.append(direction) return res - + def byPromissor(self, ID): """ Returns all directions to a promissor. """ res = [] for direction in self.table: if ID in direction[1]: res.append(direction) - return res + return res \ No newline at end of file diff --git a/flatlib/props.py b/flatlib/props.py index 925f123..492a6d5 100644 --- a/flatlib/props.py +++ b/flatlib/props.py @@ -197,22 +197,22 @@ class object: # Object orbs orb = { - const.NO_PLANET: 0, - const.SUN: 15, - const.MOON: 12, - const.MERCURY: 7, - const.VENUS: 7, - const.MARS: 8, - const.JUPITER: 9, - const.SATURN: 9, - const.URANUS: 5, - const.NEPTUNE: 5, - const.PLUTO: 5, - const.CHIRON: 5, - const.NORTH_NODE: 12, - const.SOUTH_NODE: 12, - const.SYZYGY: 0, - const.PARS_FORTUNA: 0 + const.NO_PLANET: const.LIST_ORBS[const.NO_PLANET], + const.SUN: const.LIST_ORBS[const.SUN], + const.MOON: const.LIST_ORBS[const.MOON], + const.MERCURY: const.LIST_ORBS[const.MERCURY], + const.VENUS: const.LIST_ORBS[const.VENUS], + const.MARS: const.LIST_ORBS[const.MARS], + const.JUPITER: const.LIST_ORBS[const.JUPITER], + const.SATURN: const.LIST_ORBS[const.SATURN], + const.URANUS: const.LIST_ORBS[const.URANUS], + const.NEPTUNE: const.LIST_ORBS[const.NEPTUNE], + const.PLUTO: const.LIST_ORBS[const.PLUTO], + const.CHIRON: const.LIST_ORBS[const.CHIRON], + const.NORTH_NODE: const.LIST_ORBS[const.NORTH_NODE], + const.SOUTH_NODE: const.LIST_ORBS[const.SOUTH_NODE], + const.SYZYGY: const.LIST_ORBS[const.SYZYGY], + const.PARS_FORTUNA: const.LIST_ORBS[const.PARS_FORTUNA] } # Planet elements diff --git a/flatlib/tools/chartdynamics.py b/flatlib/tools/chartdynamics.py index e4095a3..6f69efd 100644 --- a/flatlib/tools/chartdynamics.py +++ b/flatlib/tools/chartdynamics.py @@ -70,8 +70,10 @@ def validAspects(self, ID, aspList): """ obj = self.chart.getObject(ID) res = [] + + #for otherID in const.LIST_SEVEN_PLANETS: + for otherID in const.LIST_TEN_PLANETS: - for otherID in const.LIST_SEVEN_PLANETS: if ID == otherID: continue @@ -113,25 +115,20 @@ def aspectsByCat(self, ID, aspList): }) return res - + def immediateAspects(self, ID, aspList): """ Returns the last separation and next application considering a list of possible aspects. - + """ asps = self.aspectsByCat(ID, aspList) - - applications = asps[const.APPLICATIVE] - separations = asps[const.SEPARATIVE] - exact = asps[const.EXACT] - - # Get applications and separations sorted by orb - - applications = applications + [val for val in exact if val['orb'] >= 0] - - applications = sorted(applications, key=lambda var: var['orb']) - separations = sorted(separations, key=lambda var: var['orb']) - + + # Get application and separations sorted by orb + applications = sorted(asps[const.APPLICATIVE], + key=lambda var: var['orb']) + separations = sorted(asps[const.SEPARATIVE], + key=lambda var: var['orb']) + return ( separations[0] if separations else None, applications[0] if applications else None @@ -147,3 +144,43 @@ def isVOC(self, ID): applications = asps[const.APPLICATIVE] exacts = asps[const.EXACT] return len(applications) == 0 and len(exacts) == 0 + + def isMVOC(self): + """MH on 2018/3/4 - Returns if the Moon is void of course + taking into consideration sign status""" + + """Loading all objects except the Moon""" + obj = [] + for ob in const.LIST_ASP_PLANETS: + obj.append(self.chart.get(ob)) + """Loading the Moon""" + moon = self.chart.get(const.MOON) + + """Check if any other object has a greater lon in the sign + If that is the case, check if any major aspect may exist before + th Moon leaves the sign""" + asp_type = const.NO_ASPECT + for ob in obj: + if ob.signlon >= moon.signlon: #Check if any other object has a greater lon in sign than the Moon + + """Calculate a distance between the signs""" + dist = abs(const.LIST_SIGNS.index(moon.sign) - const.LIST_SIGNS.index(ob.sign)) + #asp_type = const.NO_ASPECT + if dist == 0: + if ob.id in [const.SUN, + const.MERCURY, + const.VENUS, + const.JUPITER, + const.NEPTUNE]: #Conjunction + asp_type = 1 + else: + asp_type = 0 + if dist == 2 or dist == 10: #Sextile + asp_type = 1 + if dist == 3 or dist == 9: #Square + asp_type = 0 + if dist == 4 or dist == 8: #Trine + asp_type = 1 + if dist == 6: #Opposition + asp_type = 0 + return {"isVOC" : asp_type == const.NO_ASPECT,"asp" : asp_type} diff --git a/js/package.json b/js/package.json new file mode 100644 index 0000000..8e3f616 --- /dev/null +++ b/js/package.json @@ -0,0 +1,19 @@ +{ + "name": "flatlib-js", + "version": "0.1.0", + "description": "JavaScript port of the flatlib astrology library", + "main": "src/flatlib/index.js", + "type": "module", + "scripts": { + "test": "jest" + }, + "keywords": [ + "astrology", + "flatlib" + ], + "author": "Port", + "license": "MIT", + "devDependencies": { + "jest": "^29.0.0" + } +} \ No newline at end of file diff --git a/js/src/flatlib/const.js b/js/src/flatlib/const.js new file mode 100644 index 0000000..4ea26a3 --- /dev/null +++ b/js/src/flatlib/const.js @@ -0,0 +1,3 @@ +// constant definitions will be ported later + +export const ARIES = 'Aries'; diff --git a/js/src/flatlib/index.js b/js/src/flatlib/index.js new file mode 100644 index 0000000..d71386f --- /dev/null +++ b/js/src/flatlib/index.js @@ -0,0 +1,17 @@ +// Entry point for flatlib-js. Re-export common modules. + +export * from './const.js'; +export * from './angle.js'; +export * from './utils.js'; +export * from './datetime.js'; +export * from './geopos.js'; +export * from './object.js'; +export * from './lists.js'; +export * from './chart.js'; + +// subpackages can be imported directly +export * as ephem from './ephem/index.js'; +export * as dignities from './dignities/index.js'; +export * as predictives from './predictives/index.js'; +export * as protocols from './protocols/index.js'; +export * as tools from './tools/index.js'; diff --git a/js/tests/initial.test.js b/js/tests/initial.test.js new file mode 100644 index 0000000..973b6af --- /dev/null +++ b/js/tests/initial.test.js @@ -0,0 +1,3 @@ +test('environment set up', () => { + expect(true).toBe(true); +}); \ No newline at end of file