def __init__( self, calendar: "Calendar", ymd: Tuple[int, int, int], hours: Real = Sexagesimal(12), ): """ :param calendar: Calendar used in this date. :type calendar: Calendar :param ymd: Year, month and days, expressed in the specified calendar. :type ymd: Tuple[int, int, int] :param hours: Number of hours, defaults to Sexagesimal(12); :type hours: Real, optional """ if not 0 <= float(hours) < 24: raise ValueError("Time must be in the range [0;24,0[") self._calendar = calendar self._ymd = ymd self._hours = ( hours.resize(1) if isinstance(hours, Sexagesimal) else Sexagesimal.from_float(float(hours), 2) ) self._jdn = calendar.jdn_at_ymd(*ymd) - 0.5 + hours_to_day(hours)
def test_truncable(self): bcol = HColumn([1, 2, 3]).astype(Sexagesimal) assert bcol.significant == 0 bcol = bcol.resize(2) bcol += Sexagesimal(31) >> 2 assert bcol.significant == 2 assert np.array_equal( [ Sexagesimal("1;1"), Sexagesimal("2;1"), Sexagesimal("3;1"), ], bcol.ceil(1), ) assert np.array_equal([1, 2, 3], bcol.truncate(0)) assert np.array_equal( [ Sexagesimal("1;0"), Sexagesimal("2;0"), Sexagesimal("3;0"), ], bcol.floor(1), ) assert np.array_equal( [ Sexagesimal("1;1"), Sexagesimal("2;1"), Sexagesimal("3;1"), ], round(bcol, 1), )
def test_read(): table: HTable = HTable.read("180", format="dishas") assert table["Mean Argument of the Sun"].unit is u.degree assert table["Mean Argument of the Sun"].basedtype is IntegerAndSexagesimal assert table["Entries"].significant == 2 assert table.values_equal(HTable.read(180)) assert table.loc[1] == table[0] assert table.loc[3]["Entries"].equals(Sexagesimal("-00 ; 06,27")) assert table.loc[3]["Entries"].equals(table.get(Sexagesimal(3), with_unit=False)) assert len(table.symmetry) == 1 sym = table.symmetry[0] assert table.get(1) == -table.get(37) assert sym.symtype == "mirror" assert "Sexagesimal" in repr(table) assert table.table_type == Sun.equ_of_the_sun with pytest.raises(FileNotFoundError): HTable.read(181, format="dishas")
def test_misc(): s = Sexagesimal(5) assert (s or 1) == 5 assert not s.equals("5") assert s.to_fraction() == Fraction(5) assert 5 / s == 1 assert s**-1 == 1 / 5 assert s**1 == s assert 1**s == 1 assert Sexagesimal(0)**1 == 0 with pytest.raises(ValueError): (-Sexagesimal(5))**2.5 assert s > 4 assert (s / 1).equals(s) assert (s / -1).equals(-s) with pytest.raises(ZeroDivisionError): s / 0 assert Sexagesimal("1,0;2,30,1").subunit_quantity(1) == 3602 assert 5 % Sexagesimal(2) == 1 assert 5 // Sexagesimal(2) == 2 assert divmod(Sexagesimal(5), 3) == divmod(5, 3)
def test_declination(params, result): data: str = get_nb("declination", params).cells[7].outputs[0].data["text/html"] lines = data.split("<tr>") line5 = [li for li in lines if "<td>05 ;" in li][0] line90 = [li for li in lines if "<td>01,30 ;" in li][0] assert repr(Sexagesimal(result[0])).strip() in line5 assert repr(Sexagesimal(result[1])).strip() in line90
class Venus(InferiorPlanet): mean_argument = mean_motion(Sexagesimal("0 ; 36,59,27,23,59,31"), Sexagesimal("2,9;22,2,36")) center_equation = read_from_table(189) arg_equation = read_from_table(190) min_prop = read_from_table(252) long_longior = read_from_table(250) long_propior = read_from_table(251)
def test_comparisons(x): s = Sexagesimal("1, 2; 30") xs = Sexagesimal.from_float(x, 1) for comp in (op.lt, op.le, op.eq, op.ne, op.ge, op.gt): if comp(float(s), x): assert comp(s, xs) else: assert not comp(s, xs)
def test_wrapper(self): @_with_context_precision def func(a, b): return 1 with pytest.raises(TypeError): func(Sexagesimal(1), Sexagesimal(2)) assert func(1, 2) == 1
class Moon(CelestialBody): mean_argument = mean_motion(Sexagesimal("13 ; 03,53,57,30,21,04,13"), Sexagesimal("3,19;0,14,31,16")) mean_motion = mean_motion(Sexagesimal("13 ; 10,35,01,15,11,04,35"), Sexagesimal("2,2;46,50,16,39")) equation_center = read_from_table(181) equation_arg = read_from_table(182) minuta_proportionalia = read_from_table(239) diameter_diversion = read_from_table(240)
class Mercury(InferiorPlanet): apogee_radix = Sexagesimal("3,10;39,33,4") * degree mean_argument = mean_motion(Sexagesimal("03 ; 06,24,07,42,40,52"), Sexagesimal("45;23,58,0")) center_equation = read_from_table(191) arg_equation = read_from_table(192) min_prop = read_from_table(255) long_longior = read_from_table(253) long_propior = read_from_table(254)
class Saturn(SuperiorPlanet): apogee_radix = Sexagesimal("3,53;23,42,4") * degree mean_motion = mean_motion(Sexagesimal("0 ; 02,00,35,17,40,21"), Sexagesimal("1,14;5,20,12")) center_equation = read_from_table(235) arg_equation = read_from_table(184) min_prop = read_from_table(243) long_longior = read_from_table(241) long_propior = read_from_table(242)
class Jupiter(SuperiorPlanet): apogee_radix = Sexagesimal("2,33;37,0,4") * degree mean_motion = mean_motion(Sexagesimal("0 ; 04,59,15,27,07,23,50"), Sexagesimal("3,0;37,20,43")) center_equation = read_from_table(185) arg_equation = read_from_table(186) min_prop = read_from_table(246) long_longior = read_from_table(244) long_propior = read_from_table(245)
class Mars(SuperiorPlanet): apogee_radix = Sexagesimal("1,55;12,13,4") * degree mean_motion = mean_motion(Sexagesimal("0 ; 31,26,38,40,05"), Sexagesimal("0,41;25,29,43")) center_equation = read_from_table(187) arg_equation = read_from_table(188) min_prop = read_from_table(249) long_longior = read_from_table(247) long_propior = read_from_table(248)
def test_sqrt(): assert Sexagesimal(9).sqrt().equals(Sexagesimal(3)) assert Sexagesimal(0).sqrt() == 0 assert Sexagesimal("12;15").sqrt(5) == 3.5 with pytest.raises(ValueError): Sexagesimal("-5").sqrt()
def test_range(start: int, stop: int, step: int): based_range = Sexagesimal.range(start, stop, step) normal_range = range(start, stop, step) assert list(normal_range) == [int(x) for x in based_range] based_range_stop = Sexagesimal.range(stop) normal_range_stop = range(stop) assert list(normal_range_stop) == [int(x) for x in based_range_stop]
def test_init_basedquantity(self): q = Sexagesimal(1) * degree assert isinstance(q, BasedQuantity) assert q.unit == degree assert q.value.equals(Sexagesimal(1)) q = Sexagesimal(1) / degree assert isinstance(q, BasedQuantity) assert q.unit == 1 / degree assert q.value.equals(Sexagesimal(1)) assert type(BasedQuantity(1, degree)) is Quantity
def test_shifting(self): q = Sexagesimal("1;0,1,31") * degree assert (q << 2).value.equals(q.value << 2) assert (q >> 2).value.equals(q.value >> 2) arcmq = q << 1 * arcminute assert arcmq.unit == arcminute assert arcmq.value.equals(Sexagesimal("1,0;1,31,0")) with pytest.raises(TypeError): q >> 1 * arcminute
class FixedStars(CelestialBody): access_recess_mm = mean_motion(Sexagesimal("0 ; 00,00,30,24,49"), Sexagesimal("5,59;12,34")) mean_motion = mean_motion(Sexagesimal("0 ; 00,00,04,20,41,17,12"), Sexagesimal(0)) access_recess_eq = read_from_table( 238, symmetry=[ mirror, Symmetry("periodic", targets=[Sexagesimal(3, 1)]), ], )
def test_distributed(self): df = pd.DataFrame([5] + [np.nan] * 8 + [45], list(range(6, 16))) convex = df.pipe(distributed_interpolation, direction="convex") assert list(convex[0]) == [5, 9, 13, 17, 21, 25, 30, 35, 40, 45] concave = df.pipe(distributed_interpolation, direction="concave") assert list(concave[0]) == [5, 10, 15, 20, 25, 29, 33, 37, 41, 45] df = pd.DataFrame([5] + [np.nan] * 6 + [45], [i / 4 for i in range(8)]) concave = df.pipe(distributed_interpolation, direction="concave") assert len(concave) == 8 and not np.isnan(concave[0]).any() df = pd.DataFrame([5] + [np.nan] * 6 + [45] + [np.nan] * 6 + [100], [i / 4 for i in range(15)]) concave = df.pipe(distributed_interpolation, direction="concave") assert len(concave) == 15 and not np.isnan(concave[0]).any() with pytest.raises(ValueError) as err: df = pd.DataFrame([5] + [np.nan] * 8 + [45], list(range(6, 15)) + [31]) df.pipe(distributed_interpolation, direction="convex") assert str(err.value) == "The DataFrame must have regular steps" with pytest.raises(ValueError) as err: df = pd.DataFrame([5] + [np.nan] * 9, list(range(6, 16))) df.pipe(distributed_interpolation, direction="convex") assert str(err.value ) == "The DataFrame must start and end with non nan values" with pytest.raises(ValueError) as err: df.pipe(distributed_interpolation, direction="unknown") assert "unknown" in str(err.value) from kanon.units import Sexagesimal df = pd.DataFrame([Sexagesimal(5)] + [np.nan] * 8 + [Sexagesimal(45)], list(range(6, 16))) convex = df.pipe(distributed_interpolation, direction="convex") assert list(convex[0]) == [5, 9, 13, 17, 21, 25, 30, 35, 40, 45] df = pd.DataFrame( [Sexagesimal("0;0,5")] + [np.nan] * 8 + [Sexagesimal("0;0,45")], list(range(6, 16)), ) convex = df.pipe(distributed_interpolation, direction="convex") assert list(convex[0]) == [ Sexagesimal.from_int(x).shift(2) for x in [5, 9, 13, 17, 21, 25, 30, 35, 40, 45] ] assert convex.index[0].dtype == "int64"
def test_truncations(): s = Sexagesimal("1, 2, 30; 18, 52, 23") assert round(s).equals(s) assert round(s, 1).equals(Sexagesimal("1,2,30;19")) assert s.truncate(1).equals(Sexagesimal("1,2,30;18")) assert s.truncate(100).equals(s) assert m.trunc(s) == 3750 assert m.floor(s) == 3750 assert m.ceil(s) == 3751 assert m.floor(-s) == -3749 assert m.ceil(-s) == -3750 assert Sexagesimal(1, 2, 3).minimize_precision().equals(Sexagesimal(1, 2, 3)) assert (Sexagesimal("1, 2, 3; 0, 0").minimize_precision().equals( Sexagesimal(1, 2, 3)))
def from_julian_days(self, jdn: float) -> Date: """Builds a `Date` object at the specified julian day number.""" time = (jdn - 0.5) % 1 jdn = round(jdn) year = ( int(self.era.days_from_epoch(jdn) * sum(self.cycle) // self.cycle_length) + 1 ) if year < 1: year -= 1 rem = jdn - self.jdn_at_ymd(year, 1, 1) for y in range(year, year + self.cycle_length): ylength = self.leap_year if self.intercalation(y) else self.common_year if rem >= ylength: rem -= ylength year += 1 else: break leap = self.intercalation(year) for i, m in enumerate(self.months): ndays = m.days(leap) if rem < ndays: month = i + 1 days = rem + 1 break else: rem -= ndays return Date(self, (year, month, int(days)), Sexagesimal("24;0") * time)
def test_parse(value, result): if isinstance(result, str): parsed_number = parse(value, Sexagesimal) assert parsed_number == Sexagesimal(result) else: with pytest.raises(result) as err: parse(value, Sexagesimal) assert "Invalid syntax" in str(err.value)
def get_ascendant( latitude: float = Query(..., ge=-90, le=90), date_params: DateParams = Depends() ): date = safe_date(JULIAN_CALENDAR, date_params) pos = ascendant(date.days_from_epoch(), latitude) return {"value": str(round(Sexagesimal(pos.value, 2)))}
def test_dates_fraction(): cal = Calendar.registry["Julian A.D."] assert cal.from_julian_days(5000.6) != cal.from_julian_days(5000) date = Date(cal, (5, 2, 3), Sexagesimal(24) * 0.4) assert math.isclose(hours_to_day((date + 1).hours), 0.4) assert (date + 1).ymd == (5, 2, 4)
def read_historical(values: List[int], shift: int, sign: Sign = 1) -> Historical: integer = values[0] # Special case for non true Historical in DISHAS with 2 values if len(values) == 2 and shift == 0: return Historical(integer * 30 + Sexagesimal(values[1])) return Historical(values[:-shift or None], values[-shift or len(values):], sign=sign)
def test_shift(): s = Sexagesimal("20, 1, 2, 30; 0") assert (s >> 1).equals(Sexagesimal("20, 1, 2; 30, 0")) assert (s << 1).equals(Sexagesimal("20, 1, 2, 30, 0")) assert (s >> -1).equals(s << 1) assert (s >> 7).equals(Sexagesimal("0; 0, 0, 0, 20, 1, 2, 30, 0")) s = Sexagesimal((20, ), (0, 2, 0), remainder=Decimal(0.5)) assert (s << 2).equals( Sexagesimal((20, 0, 2), (0, ), remainder=Decimal(0.5))) assert (s << 5).equals(Sexagesimal(20, 0, 2, 0, 30, 0))
def get_houses( method: HouseMethods = Depends(safe_houses_method), latitude: float = Query(..., ge=-90, le=90), date_params: DateParams = Depends(), ): date = safe_date(JULIAN_CALENDAR, date_params) asc = ascendant(date.days_from_epoch(), latitude) houses_list = method(asc, latitude) return [str(round(Sexagesimal(x, 2))) for x in houses_list]
def test_attribute_forwarding(self): q = Sexagesimal("1;0,1,31") * degree with pytest.raises(AttributeError): q._from_string() with pytest.raises(AttributeError): q.does_not_exist() assert q.truncate(2).value.equals(q.value.truncate(2)) assert q.left == (1, ) assert round(q, 2).value.equals(round(q.value, 2))
def test_based_populate(): tab = sin_table_grid.populate(list(range(91))) assert tab["Arg"].basedtype == Sexagesimal assert len(tab) == 91 tab_int = sin_table_grid.copy() tab_int.remove_indices("Arg") tab_int["Arg"] = tab_int["Arg"].astype(int) tab_int.set_index("Arg") tab = tab_int.populate(list(Sexagesimal.range(91))) assert tab["Arg"].basedtype is None assert tab["Arg"].dtype == int assert len(tab) == 91
def test_get(): s = Sexagesimal("1, 2, 30; 18, 12, 23") assert s[-2] == 1 assert s[0] == 30 assert s[1] == 18 assert s[:] == (1, 2, 30, 18, 12, 23) assert s[:0] == (1, 2) assert s[3::-1] == (23, 12, 18, 30, 2, 1) assert s[-1:] == (2, 30, 18, 12, 23) assert s[-1:2] == (2, 30, 18) with pytest.raises(IndexError): s[100] with pytest.raises(TypeError): s["5"]