Building a declination table
[1]:
from kanon.units import Sexagesimal
from kanon.units.precision import set_precision, get_context, TruncatureMode
from kanon.tables import HTable
from kanon.tables.htable import join_multiple
import math
# For these calculations we will round after every operations.
get_context().mutate(tmode=TruncatureMode.ROUND)
[2]:
OBLIQUITY = "23;51,20"
[3]:
# We construct a table of sine from 0 to 90.
x = list(Sexagesimal.range(91))
y = [round(Sexagesimal.from_float(math.sin(math.radians(n)), 3)) for n in x]
sin_table = HTable([x, y], names=("Arg", "Val"), index="Arg")
sin_table
[3]:
HTable length=91
Arg | Val |
---|---|
Sexagesimal | Sexagesimal |
00 ; | 00 ; 00,00,00 |
01 ; | 00 ; 01,02,50 |
02 ; | 00 ; 02,05,38 |
03 ; | 00 ; 03,08,25 |
04 ; | 00 ; 04,11,07 |
05 ; | 00 ; 05,13,46 |
06 ; | 00 ; 06,16,18 |
07 ; | 00 ; 07,18,44 |
08 ; | 00 ; 08,21,01 |
09 ; | 00 ; 09,23,10 |
... | ... |
01,21 ; | 00 ; 59,15,41 |
01,22 ; | 00 ; 59,24,58 |
01,23 ; | 00 ; 59,33,10 |
01,24 ; | 00 ; 59,40,17 |
01,25 ; | 00 ; 59,46,18 |
01,26 ; | 00 ; 59,51,14 |
01,27 ; | 00 ; 59,55,04 |
01,28 ; | 00 ; 59,57,48 |
01,29 ; | 00 ; 59,59,27 |
01,30 ; | 01 ; 00,00,00 |
[4]:
# We apply a multiplication on all the sine values to get obl_table = Sin(x) * obl
obl = sin_table.get(Sexagesimal(OBLIQUITY))
obl_table = sin_table.apply("Val", lambda x: x * obl)
obl_table
[4]:
HTable length=91
Arg | Val |
---|---|
Sexagesimal | Sexagesimal |
00 ; | 00 ; 00,00,00 |
01 ; | 00 ; 00,25,25 |
02 ; | 00 ; 00,50,49 |
03 ; | 00 ; 01,16,12 |
04 ; | 00 ; 01,41,33 |
05 ; | 00 ; 02,06,54 |
06 ; | 00 ; 02,32,11 |
07 ; | 00 ; 02,57,26 |
08 ; | 00 ; 03,22,37 |
09 ; | 00 ; 03,47,46 |
... | ... |
01,21 ; | 00 ; 23,58,01 |
01,22 ; | 00 ; 24,01,46 |
01,23 ; | 00 ; 24,05,05 |
01,24 ; | 00 ; 24,07,58 |
01,25 ; | 00 ; 24,10,24 |
01,26 ; | 00 ; 24,12,23 |
01,27 ; | 00 ; 24,13,56 |
01,28 ; | 00 ; 24,15,03 |
01,29 ; | 00 ; 24,15,43 |
01,30 ; | 00 ; 24,15,56 |
[5]:
# Arcsin is sin_table taken from Val to Arg instead of Arg to Val.
arcsin_table = sin_table.copy(set_index="Val")
# For example, if we want arcsin(0.3) :
arcsin_table.get(0.3)
[5]:
17 ; 27,29,50
[6]:
# Finally, we apply arcsin_table.get on every obl_table values to find decl_table = arcsin(obl_table)
decl_table = obl_table.apply("Val", arcsin_table.get)
decl_table
[6]:
HTable length=91
Arg | Val |
---|---|
Sexagesimal | Sexagesimal |
00 ; | 00 ; |
01 ; | 00 ; 24,16,14 |
02 ; | 00 ; 48,31,31 |
03 ; | 01 ; 12,46,15 |
04 ; | 01 ; 36,59,26 |
05 ; | 02 ; 01,12,38 |
06 ; | 02 ; 25,22,23 |
07 ; | 02 ; 49,30,13 |
08 ; | 03 ; 13,35,19 |
09 ; | 03 ; 37,39,20 |
... | ... |
01,21 ; | 23 ; 32,40,53 |
01,22 ; | 23 ; 36,35,12 |
01,23 ; | 23 ; 40,02,26 |
01,24 ; | 23 ; 43,02,35 |
01,25 ; | 23 ; 45,34,38 |
01,26 ; | 23 ; 47,38,33 |
01,27 ; | 23 ; 49,15,24 |
01,28 ; | 23 ; 50,25,10 |
01,29 ; | 23 ; 51,06,49 |
01,30 ; | 23 ; 51,20,22 |
[7]:
# Let's make the same calculation with an interpolated sine table.
# First, extract every 12th row until the 60th then every 6th.
sin_table_grid = sin_table[
[i for i in range(91) if i <= 60 and i % 12 == 0 or i > 60 and i % 6 == 0]
]
sin_table_grid
[7]:
HTable length=11
Arg | Val |
---|---|
Sexagesimal | Sexagesimal |
00 ; | 00 ; 00,00,00 |
12 ; | 00 ; 12,28,29 |
24 ; | 00 ; 24,24,15 |
36 ; | 00 ; 35,16,02 |
48 ; | 00 ; 44,35,19 |
01,00 ; | 00 ; 51,57,41 |
01,06 ; | 00 ; 54,48,46 |
01,12 ; | 00 ; 57,03,48 |
01,18 ; | 00 ; 58,41,20 |
01,24 ; | 00 ; 59,40,17 |
01,30 ; | 01 ; 00,00,00 |
[8]:
# We can populate it with its interpolation method (linear by default).
sin_table_pop_linear = sin_table_grid.populate(list(Sexagesimal.range(91)), method="interpolate")
sin_table_pop_linear
[8]:
HTable length=91
Arg | Val |
---|---|
Sexagesimal | Sexagesimal |
00 ; | 00 ; 00,00,00 |
01 ; | 00 ; 01,02,22 |
02 ; | 00 ; 02,04,44 |
03 ; | 00 ; 03,07,06 |
04 ; | 00 ; 04,09,28 |
05 ; | 00 ; 05,11,50 |
06 ; | 00 ; 06,14,12 |
07 ; | 00 ; 07,16,34 |
08 ; | 00 ; 08,18,56 |
09 ; | 00 ; 09,21,18 |
... | ... |
01,21 ; | 00 ; 59,10,50 |
01,22 ; | 00 ; 59,20,40 |
01,23 ; | 00 ; 59,30,30 |
01,24 ; | 00 ; 59,40,17 |
01,25 ; | 00 ; 59,43,34 |
01,26 ; | 00 ; 59,46,51 |
01,27 ; | 00 ; 59,50,08 |
01,28 ; | 00 ; 59,53,25 |
01,29 ; | 00 ; 59,56,42 |
01,30 ; | 01 ; 00,00,00 |
[9]:
# You can use other types of interpolation, for example a quadratic interpolation.
from kanon.tables.interpolations import quadratic_interpolation
sin_table_grid.interpolate = quadratic_interpolation
# This interpolation method needs a higher precision to avoid weird results.
with set_precision(pmode=5):
sin_table_pop_quadratic = sin_table_grid.populate(list(Sexagesimal.range(91)), method="interpolate")
sin_table_pop_quadratic
[9]:
HTable length=91
Arg | Val |
---|---|
Sexagesimal | Sexagesimal |
00 ; | 00 ; 00,00,00,00,00 |
01 ; | 00 ; 01,03,37,23,33 |
02 ; | 00 ; 02,07,01,09,12 |
03 ; | 00 ; 03,10,11,16,57 |
04 ; | 00 ; 04,13,07,46,48 |
05 ; | 00 ; 05,15,50,38,45 |
06 ; | 00 ; 06,18,19,52,48 |
07 ; | 00 ; 07,20,35,28,57 |
08 ; | 00 ; 08,22,37,27,12 |
09 ; | 00 ; 09,24,25,47,33 |
... | ... |
01,21 ; | 00 ; 59,15,37,52,30 |
01,22 ; | 00 ; 59,24,55,13,20 |
01,23 ; | 00 ; 59,33,08,15,50 |
01,24 ; | 00 ; 59,40,17,00,00 |
01,25 ; | 00 ; 59,46,17,38,20 |
01,26 ; | 00 ; 59,51,12,53,20 |
01,27 ; | 00 ; 59,55,02,45,00 |
01,28 ; | 00 ; 59,57,47,13,20 |
01,29 ; | 00 ; 59,59,26,18,20 |
01,30 ; | 01 ; 00,00,00,00,00 |
[10]:
# Another type of interpolation can come from filling a interpolation grid made from populate
# With this you can use methods interpolating the whole table at once, like euclidean distribution interpolations
sin_table_pop_euclidean = sin_table_grid.populate(list(Sexagesimal.range(91)))
sin_table_pop_euclidean = sin_table_pop_euclidean.fill("distributed_convex")
sin_table_pop_euclidean
[10]:
HTable length=91
Arg | Val |
---|---|
Sexagesimal | Sexagesimal |
00 ; | 00 ; 00,00,00 |
01 ; | 00 ; 01,02,22 |
02 ; | 00 ; 02,04,44 |
03 ; | 00 ; 03,07,06 |
04 ; | 00 ; 04,09,28 |
05 ; | 00 ; 05,11,50 |
06 ; | 00 ; 06,14,12 |
07 ; | 00 ; 07,16,34 |
08 ; | 00 ; 08,18,57 |
09 ; | 00 ; 09,21,20 |
... | ... |
01,21 ; | 00 ; 59,10,47 |
01,22 ; | 00 ; 59,20,37 |
01,23 ; | 00 ; 59,30,27 |
01,24 ; | 00 ; 59,40,17 |
01,25 ; | 00 ; 59,43,34 |
01,26 ; | 00 ; 59,46,51 |
01,27 ; | 00 ; 59,50,08 |
01,28 ; | 00 ; 59,53,25 |
01,29 ; | 00 ; 59,56,42 |
01,30 ; | 01 ; 00,00,00 |
[11]:
# Comparing the 2nd difference between the true sine table and the interpolated ones.
true_2diff = sin_table.diff(n=2, new_name="True Sine 2-diff")
interpolated_linear_2diff = sin_table_pop_linear.diff(n=2, new_name="Linear Sine 2-diff")
interpolated_quadratic_2diff = sin_table_pop_quadratic.diff(n=2, new_name="Quadratic Sine 2-diff")
interpolated_euclidean_2diff = sin_table_pop_euclidean.diff(n=2, new_name="Distributed Sine 2-diff")
# Now we have 4 tables with the same arguments. We can compare them side to side by joining them.
join_multiple(true_2diff, interpolated_linear_2diff, interpolated_quadratic_2diff, interpolated_euclidean_2diff)
[11]:
HTable length=91
Arg | True Sine 2-diff | Linear Sine 2-diff | Quadratic Sine 2-diff | Distributed Sine 2-diff |
---|---|---|---|---|
Sexagesimal | Sexagesimal | Sexagesimal | Sexagesimal | Sexagesimal |
00 ; | 00 ; 00,00,00 | 00 ; 00,00,00 | 00 ; 00,00,00,00,00 | 00 ; 00,00,00 |
01 ; | 00 ; 01,02,50 | 00 ; 01,02,22 | 00 ; 01,03,37,23,33 | 00 ; 01,02,22 |
02 ; | -00 ; 00,00,02 | 00 ; 00,00,00 | -00 ; 00,00,13,37,54 | 00 ; 00,00,00 |
03 ; | -00 ; 00,00,01 | 00 ; 00,00,00 | -00 ; 00,00,13,37,54 | 00 ; 00,00,00 |
04 ; | -00 ; 00,00,05 | 00 ; 00,00,00 | -00 ; 00,00,13,37,54 | 00 ; 00,00,00 |
05 ; | -00 ; 00,00,03 | 00 ; 00,00,00 | -00 ; 00,00,13,37,54 | 00 ; 00,00,00 |
06 ; | -00 ; 00,00,07 | 00 ; 00,00,00 | -00 ; 00,00,13,37,54 | 00 ; 00,00,00 |
07 ; | -00 ; 00,00,06 | 00 ; 00,00,00 | -00 ; 00,00,13,37,54 | 00 ; 00,00,00 |
08 ; | -00 ; 00,00,09 | 00 ; 00,00,00 | -00 ; 00,00,13,37,54 | 00 ; 00,00,01 |
09 ; | -00 ; 00,00,08 | 00 ; 00,00,00 | -00 ; 00,00,13,37,54 | 00 ; 00,00,00 |
... | ... | ... | ... | ... |
01,21 ; | -00 ; 00,01,04 | 00 ; 00,00,00 | -00 ; 00,01,04,18,20 | 00 ; 00,00,00 |
01,22 ; | -00 ; 00,01,06 | 00 ; 00,00,00 | -00 ; 00,01,04,18,20 | 00 ; 00,00,01 |
01,23 ; | -00 ; 00,01,05 | 00 ; 00,00,00 | -00 ; 00,01,04,18,20 | 00 ; 00,00,00 |
01,24 ; | -00 ; 00,01,05 | -00 ; 00,00,03 | -00 ; 00,01,04,18,20 | 00 ; 00,00,00 |
01,25 ; | -00 ; 00,01,06 | -00 ; 00,06,30 | -00 ; 00,01,08,05,50 | -00 ; 00,06,33 |
01,26 ; | -00 ; 00,01,05 | 00 ; 00,00,00 | -00 ; 00,01,05,23,20 | 00 ; 00,00,00 |
01,27 ; | -00 ; 00,01,06 | 00 ; 00,00,00 | -00 ; 00,01,05,23,20 | 00 ; 00,00,00 |
01,28 ; | -00 ; 00,01,06 | 00 ; 00,00,00 | -00 ; 00,01,05,23,20 | 00 ; 00,00,00 |
01,29 ; | -00 ; 00,01,05 | 00 ; 00,00,00 | -00 ; 00,01,05,23,20 | 00 ; 00,00,00 |
01,30 ; | -00 ; 00,01,06 | 00 ; 00,00,01 | -00 ; 00,01,05,23,20 | 00 ; 00,00,01 |
[12]:
# With this newly built table we are able to construct a new declination table.
obl_linear = sin_table_pop_linear.get(Sexagesimal(OBLIQUITY))
obl_table_linear = sin_table_pop_linear.apply("Val", lambda x: x * obl)
arcsin_table_linear = sin_table_pop_linear.copy(set_index="Val")
obl_table_linear.apply("Val", arcsin_table_linear.get)
[12]:
HTable length=91
Arg | Val |
---|---|
Sexagesimal | Sexagesimal |
00 ; | 00 ; |
01 ; | 00 ; 24,15,35 |
02 ; | 00 ; 48,32,08 |
03 ; | 01 ; 12,47,43 |
04 ; | 01 ; 37,03,18 |
05 ; | 02 ; 01,19,51 |
06 ; | 02 ; 25,35,26 |
07 ; | 02 ; 49,51,59 |
08 ; | 03 ; 14,07,34 |
09 ; | 03 ; 38,23,09 |
... | ... |
01,21 ; | 23 ; 31,37,07 |
01,22 ; | 23 ; 35,37,39 |
01,23 ; | 23 ; 39,37,11 |
01,24 ; | 23 ; 43,36,43 |
01,25 ; | 23 ; 44,56,14 |
01,26 ; | 23 ; 46,16,44 |
01,27 ; | 23 ; 47,37,15 |
01,28 ; | 23 ; 48,56,46 |
01,29 ; | 23 ; 50,17,17 |
01,30 ; | 23 ; 51,37,47 |