PyTransit 2.9.2__py3-none-any.whl → 2.10.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pytransit/__init__.py +4 -1
- pytransit/_version.py +24 -0
- pytransit/lpf/lpf.py +1 -1
- pytransit/models/roadrunner/common.py +95 -13
- pytransit/models/roadrunner/model_trspec.py +105 -135
- pytransit/models/roadrunner/tsmodel.py +2 -1
- {pytransit-2.9.2.dist-info → pytransit-2.10.0.dist-info}/METADATA +2 -1
- {pytransit-2.9.2.dist-info → pytransit-2.10.0.dist-info}/RECORD +11 -10
- {pytransit-2.9.2.dist-info → pytransit-2.10.0.dist-info}/WHEEL +0 -0
- {pytransit-2.9.2.dist-info → pytransit-2.10.0.dist-info}/licenses/LICENSE +0 -0
- {pytransit-2.9.2.dist-info → pytransit-2.10.0.dist-info}/top_level.txt +0 -0
pytransit/__init__.py
CHANGED
pytransit/_version.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '2.10.0'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 10, 0)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = 'gd00e4aa7f'
|
pytransit/lpf/lpf.py
CHANGED
|
@@ -505,7 +505,7 @@ class BaseLPF(LogPosteriorFunction):
|
|
|
505
505
|
self._additional_log_priors.append(T14)
|
|
506
506
|
|
|
507
507
|
def add_as_prior(self, mean: float, std: float) -> None:
|
|
508
|
-
"""Add a normal prior on the scaled semi-major axis :math:`(a / R_\star)`.
|
|
508
|
+
r"""Add a normal prior on the scaled semi-major axis :math:`(a / R_\star)`.
|
|
509
509
|
|
|
510
510
|
Parameters
|
|
511
511
|
----------
|
|
@@ -2,7 +2,7 @@ from numba import njit
|
|
|
2
2
|
from typing import Optional
|
|
3
3
|
|
|
4
4
|
from numpy import (sqrt, sin, arctan2, pi, nan, zeros, floor, arccos, linspace, ndarray, atleast_1d,
|
|
5
|
-
atleast_2d, asarray, full, empty, concatenate, array, broadcast_to)
|
|
5
|
+
atleast_2d, asarray, full, empty, concatenate, array, broadcast_to, int64)
|
|
6
6
|
from numpy.polynomial import Polynomial
|
|
7
7
|
from scipy.special import roots_jacobi, roots_legendre
|
|
8
8
|
|
|
@@ -578,6 +578,72 @@ def ldm_table(mu: ndarray, wf: ndarray, t0: float, dt: float, ldp: ndarray, out:
|
|
|
578
578
|
out[ig] = num / den
|
|
579
579
|
|
|
580
580
|
|
|
581
|
+
@njit(fastmath=True)
|
|
582
|
+
def ldm_table_map(mu: ndarray, wf: ndarray, t0: float, dt: float, nmu: int):
|
|
583
|
+
"""The linear map from a tabulated profile to the mean intensity table.
|
|
584
|
+
|
|
585
|
+
`ldm_table` is linear in the profile, and its nodes, weights, and interpolation stencils depend
|
|
586
|
+
only on the planet, so the map can be built once and applied to any number of profiles with
|
|
587
|
+
`ldm_table_banded`. This is what lets the spectroscopy model share the work between its
|
|
588
|
+
wavelength bins.
|
|
589
|
+
|
|
590
|
+
Each table node only reads the profile across the planet, so its row of the map is nonzero in a
|
|
591
|
+
narrow band. Returns the ``(ng, nmu)`` map and, for every row, the first and one-past-the-last
|
|
592
|
+
nonzero column.
|
|
593
|
+
"""
|
|
594
|
+
ng, nn = mu.shape
|
|
595
|
+
wt = zeros((ng, nmu))
|
|
596
|
+
lo = empty(ng, dtype=int64)
|
|
597
|
+
hi = empty(ng, dtype=int64)
|
|
598
|
+
for ig in range(ng):
|
|
599
|
+
den = 0.0
|
|
600
|
+
for q in range(nn):
|
|
601
|
+
den += wf[ig, q]
|
|
602
|
+
for q in range(nn):
|
|
603
|
+
w = wf[ig, q]
|
|
604
|
+
if w == 0.0:
|
|
605
|
+
continue
|
|
606
|
+
w /= den
|
|
607
|
+
x = (sqrt(mu[ig, q]) - t0) / dt
|
|
608
|
+
if x <= 0.0:
|
|
609
|
+
wt[ig, 0] += w
|
|
610
|
+
elif x >= nmu - 1:
|
|
611
|
+
wt[ig, nmu - 1] += w
|
|
612
|
+
else:
|
|
613
|
+
i = int(x) - 1
|
|
614
|
+
if i < 0:
|
|
615
|
+
i = 0
|
|
616
|
+
elif i > nmu - 4:
|
|
617
|
+
i = nmu - 4
|
|
618
|
+
u = x - i
|
|
619
|
+
wt[ig, i] -= w * (u - 1) * (u - 2) * (u - 3) / 6.0
|
|
620
|
+
wt[ig, i + 1] += w * u * (u - 2) * (u - 3) / 2.0
|
|
621
|
+
wt[ig, i + 2] -= w * u * (u - 1) * (u - 3) / 2.0
|
|
622
|
+
wt[ig, i + 3] += w * u * (u - 1) * (u - 2) / 6.0
|
|
623
|
+
|
|
624
|
+
lo[ig] = 0
|
|
625
|
+
while lo[ig] < nmu - 1 and wt[ig, lo[ig]] == 0.0:
|
|
626
|
+
lo[ig] += 1
|
|
627
|
+
hi[ig] = nmu
|
|
628
|
+
while hi[ig] > lo[ig] + 1 and wt[ig, hi[ig] - 1] == 0.0:
|
|
629
|
+
hi[ig] -= 1
|
|
630
|
+
return wt, lo, hi
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
@njit(fastmath=True)
|
|
634
|
+
def ldm_table_banded(wt: ndarray, lo: ndarray, hi: ndarray, ldp: ndarray, scale: float, out: ndarray) -> None:
|
|
635
|
+
"""The mean intensity table of one profile from the banded map of `ldm_table_map`, times `scale`."""
|
|
636
|
+
for ig in range(wt.shape[0]):
|
|
637
|
+
# Slicing the band first lets the loop index start from zero, which numba needs to drop its
|
|
638
|
+
# negative index check and vectorise the sum.
|
|
639
|
+
w = wt[ig, lo[ig]:hi[ig]]
|
|
640
|
+
p = ldp[lo[ig]:hi[ig]]
|
|
641
|
+
s = 0.0
|
|
642
|
+
for j in range(w.size):
|
|
643
|
+
s += w[j] * p[j]
|
|
644
|
+
out[ig] = scale * s
|
|
645
|
+
|
|
646
|
+
|
|
581
647
|
def _cubic_matrices() -> ndarray:
|
|
582
648
|
"""Maps from four stencil values to the cubic's coefficients in the local interval variable.
|
|
583
649
|
|
|
@@ -608,8 +674,15 @@ def cubic_coefficients(tab: ndarray) -> ndarray:
|
|
|
608
674
|
Lagrange interpolant on a stencil shifted inwards at the ends, so the interpolation is fourth
|
|
609
675
|
order everywhere including the first and last intervals.
|
|
610
676
|
"""
|
|
677
|
+
c = zeros((tab.size - 1, 4))
|
|
678
|
+
cubic_coefficients_into(tab, c)
|
|
679
|
+
return c
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
@njit(fastmath=True)
|
|
683
|
+
def cubic_coefficients_into(tab: ndarray, out: ndarray) -> None:
|
|
684
|
+
"""`cubic_coefficients` written into `out`, which has ``tab.size - 1`` rows."""
|
|
611
685
|
n = tab.size
|
|
612
|
-
c = zeros((n - 1, 4))
|
|
613
686
|
for i in range(n - 1):
|
|
614
687
|
j = i - 1
|
|
615
688
|
if j < 0:
|
|
@@ -618,17 +691,16 @@ def cubic_coefficients(tab: ndarray) -> ndarray:
|
|
|
618
691
|
j = n - 4
|
|
619
692
|
s = i - j
|
|
620
693
|
for r in range(4):
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
return c
|
|
694
|
+
out[i, r] = (CUBIC_MATRICES[s, r, 0] * tab[j] + CUBIC_MATRICES[s, r, 1] * tab[j + 1]
|
|
695
|
+
+ CUBIC_MATRICES[s, r, 2] * tab[j + 2] + CUBIC_MATRICES[s, r, 3] * tab[j + 3])
|
|
624
696
|
|
|
625
697
|
|
|
626
698
|
@njit(fastmath=True)
|
|
627
|
-
def
|
|
628
|
-
"""The
|
|
699
|
+
def ldm_interval(g: float, gc: float, n1: int, nc: int):
|
|
700
|
+
"""The interval of the split cubic table holding grazing parameter g, and g's position in it.
|
|
629
701
|
|
|
630
|
-
`
|
|
631
|
-
|
|
702
|
+
`nc` is the number of intervals in the table. Returns the interval index and the local
|
|
703
|
+
position in [0, 1) that `ldm_lookup` evaluates the interval's cubic at.
|
|
632
704
|
"""
|
|
633
705
|
if g < gc:
|
|
634
706
|
x = g / gc * (n1 - 1)
|
|
@@ -636,14 +708,24 @@ def ldm_lookup(g: float, gc: float, n1: int, coef: ndarray) -> float:
|
|
|
636
708
|
if i > n1 - 2:
|
|
637
709
|
i = n1 - 2
|
|
638
710
|
else:
|
|
639
|
-
n2 =
|
|
711
|
+
n2 = nc - (n1 - 1) + 1
|
|
640
712
|
x = (g - gc) / (1.0 - gc) * (n2 - 1)
|
|
641
713
|
i = int(x)
|
|
642
714
|
if i > n2 - 2:
|
|
643
715
|
i = n2 - 2
|
|
644
716
|
x += n1 - 1
|
|
645
717
|
i += n1 - 1
|
|
646
|
-
|
|
718
|
+
return i, x - i
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
@njit(fastmath=True)
|
|
722
|
+
def ldm_lookup(g: float, gc: float, n1: int, coef: ndarray) -> float:
|
|
723
|
+
"""The mean intensity under the planet at grazing parameter g from the split cubic table.
|
|
724
|
+
|
|
725
|
+
`coef` holds the interval coefficients of both segments back to back: ``n1 - 1`` intervals
|
|
726
|
+
covering [0, gc] and the rest covering [gc, 1].
|
|
727
|
+
"""
|
|
728
|
+
i, a = ldm_interval(g, gc, n1, coef.shape[0])
|
|
647
729
|
return coef[i, 0] + a * (coef[i, 1] + a * (coef[i, 2] + a * coef[i, 3]))
|
|
648
730
|
|
|
649
731
|
|
|
@@ -657,5 +739,5 @@ def split_cubic_coefficients(tab: ndarray, n1: int, out: ndarray) -> None:
|
|
|
657
739
|
"""
|
|
658
740
|
# The split node is stored twice, once as the last node of the first segment and once as
|
|
659
741
|
# the first node of the second, so the second segment starts at index n1.
|
|
660
|
-
out[:n1 - 1]
|
|
661
|
-
out[n1 - 1:]
|
|
742
|
+
cubic_coefficients_into(tab[:n1], out[:n1 - 1])
|
|
743
|
+
cubic_coefficients_into(tab[n1:], out[n1 - 1:])
|
|
@@ -1,19 +1,68 @@
|
|
|
1
|
-
from math import
|
|
1
|
+
from math import floor
|
|
2
2
|
|
|
3
3
|
from meepmeep.backends.numba.point2d import sep_c, solve2d, bounding_box
|
|
4
4
|
from numba import njit, prange, get_num_threads, set_num_threads
|
|
5
|
-
from numpy import zeros,
|
|
5
|
+
from numpy import zeros, ndarray, isnan, nan, mean, max, empty, int64
|
|
6
6
|
|
|
7
|
-
from .common import (g_nodes, ldm_nodes,
|
|
8
|
-
valid_radius_ratios)
|
|
7
|
+
from .common import (g_nodes, ldm_nodes, ldm_table_map, ldm_table_banded, split_cubic_coefficients, split_point,
|
|
8
|
+
ldm_interval, valid_radius_ratios)
|
|
9
9
|
from .common import circle_circle_intersection_area_kite as ccia
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
@njit(
|
|
13
|
-
def
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
@njit(fastmath=False)
|
|
13
|
+
def transit_samples(times: ndarray, t0: float, p: float, xyc: ndarray, k: float, kmax: float,
|
|
14
|
+
gc: float, n1: int, nc: int, nsamples: int, exptime: float,
|
|
15
|
+
interval: ndarray, ipts: ndarray, basis: ndarray, area: ndarray) -> int:
|
|
16
|
+
"""The geometry of every exposure sample that overlaps the star, shared by all the wavelength bins.
|
|
17
|
+
|
|
18
|
+
For each overlapping sample, stores its exposure index, the mean intensity table interval it
|
|
19
|
+
falls in, the cubic basis ``(a, a**2, a**3)`` at its position in that interval, and the three
|
|
20
|
+
overlap area terms the bins combine as ``area[0] + area[1] * (k / k_mean)**2 + area[2] * (k - k_mean)``.
|
|
21
|
+
The area terms are divided by the number of samples, so the bins can sum the samples directly.
|
|
22
|
+
|
|
23
|
+
Returns the number of overlapping samples.
|
|
24
|
+
"""
|
|
25
|
+
bt1, bt4 = bounding_box(k, xyc)
|
|
26
|
+
bt1 -= 0.0015 + exptime
|
|
27
|
+
bt4 += 0.0015 + exptime
|
|
28
|
+
|
|
29
|
+
n = 0
|
|
30
|
+
for ipt in range(times.size):
|
|
31
|
+
epoch = floor((times[ipt] - t0 + 0.5 * p) / p)
|
|
32
|
+
tc = times[ipt] - (t0 + epoch * p)
|
|
33
|
+
if not (bt1 <= tc <= bt4):
|
|
34
|
+
continue
|
|
35
|
+
for isample in range(1, nsamples + 1):
|
|
36
|
+
z = sep_c(tc + exptime * ((isample - 0.5) / nsamples - 0.5), xyc)
|
|
37
|
+
ap0, kappa = ccia(1.0, k, z)
|
|
38
|
+
dadk = 2.0 * k * kappa
|
|
39
|
+
if ap0 == 0.0 and dadk == 0.0:
|
|
40
|
+
continue
|
|
41
|
+
i, a = ldm_interval(z / (1.0 + k), gc, n1, nc)
|
|
42
|
+
ipts[n] = ipt
|
|
43
|
+
interval[n] = i
|
|
44
|
+
basis[n, 0] = a
|
|
45
|
+
basis[n, 1] = a * a
|
|
46
|
+
basis[n, 2] = a * a * a
|
|
47
|
+
|
|
48
|
+
# The area is exact while the planet is fully on the disk, and linear in k - k_mean across the limb.
|
|
49
|
+
if z <= 1.0 - kmax:
|
|
50
|
+
area[n, 0] = 0.0
|
|
51
|
+
area[n, 1] = ap0 / nsamples
|
|
52
|
+
area[n, 2] = 0.0
|
|
53
|
+
else:
|
|
54
|
+
area[n, 0] = ap0 / nsamples
|
|
55
|
+
area[n, 1] = 0.0
|
|
56
|
+
area[n, 2] = dadk / nsamples
|
|
57
|
+
n += 1
|
|
58
|
+
return n
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _tsmodel(times: ndarray,
|
|
62
|
+
k: ndarray, t0: ndarray, p: ndarray, a: ndarray, i: ndarray, e: ndarray, w: ndarray,
|
|
63
|
+
nsamples: ndarray, exptimes: ndarray, ldp: ndarray, istar: ndarray,
|
|
64
|
+
pt0: float, pdt: float, rules: ndarray, ng: int) -> ndarray:
|
|
65
|
+
"""The transmission spectroscopy model. Compiled both serially and in parallel over the wavelength bins."""
|
|
17
66
|
if k.ndim != 2:
|
|
18
67
|
raise ValueError(" The radius ratios must be given as a 2D array with shape (npv, npb)")
|
|
19
68
|
|
|
@@ -26,15 +75,22 @@ def tsmodel_serial(times: ndarray,
|
|
|
26
75
|
npt = times.size
|
|
27
76
|
npv = k.shape[0]
|
|
28
77
|
npb = k.shape[1]
|
|
78
|
+
nmu = ldp.shape[2]
|
|
79
|
+
ns = nsamples[0]
|
|
80
|
+
nc = ng - 2 # Number of intervals in the split mean intensity table
|
|
29
81
|
|
|
30
|
-
|
|
31
|
-
flux = zeros((npv, npb, npt)) # Model flux
|
|
82
|
+
flux = empty((npv, npb, npt)) # Model flux
|
|
32
83
|
nq = rules.shape[2]
|
|
33
|
-
|
|
84
|
+
tables = empty((npb, ng)) # Mean intensity tables
|
|
85
|
+
coef = empty((npb, nc, 4)) # Split cubic coefficients of the mean intensity tables
|
|
34
86
|
mu = empty((ng, 2 * nq))
|
|
35
87
|
wf = zeros((ng, 2 * nq))
|
|
36
|
-
|
|
37
|
-
|
|
88
|
+
|
|
89
|
+
# Geometry of the overlapping exposure samples
|
|
90
|
+
ipts = empty(npt * ns, dtype=int64)
|
|
91
|
+
interval = empty(npt * ns, dtype=int64)
|
|
92
|
+
basis = empty((npt * ns, 3))
|
|
93
|
+
area = empty((npt * ns, 3))
|
|
38
94
|
|
|
39
95
|
for ipv in range(npv):
|
|
40
96
|
if isnan(a[ipv]) or (a[ipv] <= 1.0) or (e[ipv] < 0.0) or not valid_radius_ratios(k[ipv]):
|
|
@@ -44,141 +100,55 @@ def tsmodel_serial(times: ndarray,
|
|
|
44
100
|
kmean = mean(k[ipv])
|
|
45
101
|
kmax = max(k[ipv])
|
|
46
102
|
afac = k[ipv] ** 2 / kmean ** 2
|
|
103
|
+
dk = k[ipv] - kmean
|
|
47
104
|
|
|
48
105
|
# -----------------------------------#
|
|
49
106
|
# Calculate the limb darkening means #
|
|
50
107
|
# -----------------------------------#
|
|
108
|
+
# The table is linear in the profile, so the map from a profile to its table is built once
|
|
109
|
+
# and applied to every bin. Dividing by the stellar intensity here saves a division per bin
|
|
110
|
+
# and exposure later.
|
|
51
111
|
gs, n1 = g_nodes(kmean, ng)
|
|
52
112
|
gc = split_point(kmean)
|
|
53
113
|
ldm_nodes(kmean, gs, rules, mu, wf)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
|
|
114
|
+
wt, lo, hi = ldm_table_map(mu, wf, pt0, pdt, nmu)
|
|
115
|
+
for ipb in prange(npb):
|
|
116
|
+
ldm_table_banded(wt, lo, hi, ldp[ipv, ipb], 1.0 / istar[ipv, ipb], tables[ipb])
|
|
117
|
+
split_cubic_coefficients(tables[ipb], n1, coef[ipb])
|
|
118
|
+
|
|
119
|
+
# ------------------------------------------#
|
|
120
|
+
# Calculate the geometry shared by the bins #
|
|
121
|
+
# ------------------------------------------#
|
|
122
|
+
xyc = solve2d(0.0, p[ipv], a[ipv], i[ipv], e[ipv], w[ipv])
|
|
123
|
+
nsm = transit_samples(times, t0[ipv], p[ipv], xyc, kmean, kmax, gc, n1, nc, ns, exptimes[0],
|
|
124
|
+
interval, ipts, basis, area)
|
|
62
125
|
|
|
63
126
|
# ---------------------------#
|
|
64
|
-
# Calculate the
|
|
127
|
+
# Calculate the light curves #
|
|
65
128
|
# ---------------------------#
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
epoch = floor((times[ipt] - t0[ipv] + 0.5 * p[ipv]) / p[ipv])
|
|
75
|
-
tc = times[ipt] - (t0[ipv] + epoch * p[ipv])
|
|
76
|
-
if not (bt1 <= tc <= bt4):
|
|
77
|
-
flux[ipv, :, ipt] = 1.0
|
|
78
|
-
else:
|
|
79
|
-
for isample in range(1, nsamples[0] + 1):
|
|
80
|
-
time_offset = exptimes[0] * ((isample - 0.5) / nsamples[0] - 0.5)
|
|
81
|
-
z = sep_c(tc + time_offset, xyc)
|
|
82
|
-
ap0, kappa = ccia(1.0, kmean, z)
|
|
83
|
-
dadk = 2.0*kmean*kappa
|
|
84
|
-
if z <= 1.0 - kmax:
|
|
85
|
-
for ipb in range(npb):
|
|
86
|
-
iplanet = ldm_lookup(z / (1.0 + kmean), gc, n1, coef[ipb])
|
|
87
|
-
flux[ipv, ipb, ipt] += (istar[ipv, ipb] - iplanet * ap0 * afac[ipb]) / istar[ipv, ipb]
|
|
88
|
-
else:
|
|
89
|
-
for ipb in range(npb):
|
|
90
|
-
iplanet = ldm_lookup(z / (1.0 + kmean), gc, n1, coef[ipb])
|
|
91
|
-
flux[ipv, ipb, ipt] += (istar[ipv, ipb] - iplanet * (ap0 + (k[ipv, ipb]-kmean)*dadk)) / istar[ipv, ipb]
|
|
92
|
-
flux[ipv, :, ipt] /= nsamples[0]
|
|
129
|
+
for ipb in prange(npb):
|
|
130
|
+
f = flux[ipv, ipb]
|
|
131
|
+
c = coef[ipb]
|
|
132
|
+
f[:] = 1.0
|
|
133
|
+
for s in range(nsm):
|
|
134
|
+
ci = c[interval[s]]
|
|
135
|
+
iplanet = ci[0] + basis[s, 0] * ci[1] + basis[s, 1] * ci[2] + basis[s, 2] * ci[3]
|
|
136
|
+
f[ipts[s]] -= iplanet * (area[s, 0] + area[s, 1] * afac[ipb] + area[s, 2] * dk[ipb])
|
|
93
137
|
return flux
|
|
94
138
|
|
|
95
139
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
nsamples: ndarray, exptimes: ndarray, ldp: ndarray, istar: ndarray,
|
|
100
|
-
pt0: float, pdt: float, rules: ndarray, ng: int,
|
|
101
|
-
nthreads: int) -> ndarray:
|
|
140
|
+
tsmodel_serial = njit(parallel=False, fastmath=False)(_tsmodel)
|
|
141
|
+
_tsmodel_parallel = njit(parallel=True, fastmath=False)(_tsmodel)
|
|
142
|
+
|
|
102
143
|
|
|
144
|
+
@njit
|
|
145
|
+
def tsmodel_parallel(times: ndarray,
|
|
146
|
+
k: ndarray, t0: ndarray, p: ndarray, a: ndarray, i: ndarray, e: ndarray, w: ndarray,
|
|
147
|
+
nsamples: ndarray, exptimes: ndarray, ldp: ndarray, istar: ndarray,
|
|
148
|
+
pt0: float, pdt: float, rules: ndarray, ng: int,
|
|
149
|
+
nthreads: int) -> ndarray:
|
|
103
150
|
nthreads_current = get_num_threads()
|
|
104
151
|
set_num_threads(nthreads)
|
|
105
|
-
|
|
106
|
-
if k.ndim != 2:
|
|
107
|
-
raise ValueError(" The radius ratios must be given as a 2D array with shape (npv, npb)")
|
|
108
|
-
|
|
109
|
-
if ldp.ndim != 3:
|
|
110
|
-
raise ValueError("The limb darkening profiles must be given as a 3D array with shape (npv, npb, nmu)")
|
|
111
|
-
|
|
112
|
-
if k.shape[1] != ldp.shape[1]:
|
|
113
|
-
raise ValueError("The transmission spectrum transit model requires that the number or radius ratios and the number of passbands match.")
|
|
114
|
-
|
|
115
|
-
npt = times.size
|
|
116
|
-
npv = k.shape[0]
|
|
117
|
-
npb = k.shape[1]
|
|
118
|
-
|
|
119
|
-
flux = zeros((npv, npb, npt)) # Model flux
|
|
120
|
-
nq = rules.shape[2]
|
|
121
|
-
coef = zeros((npb, ng - 2, 4)) # Split cubic coefficients of the mean intensity tables
|
|
122
|
-
mu = empty((ng, 2 * nq))
|
|
123
|
-
wf = zeros((ng, 2 * nq))
|
|
124
|
-
ldm = empty(ng)
|
|
125
|
-
xyc = zeros((2, 5)) # Taylor series coefficients for the (x, y) position
|
|
126
|
-
|
|
127
|
-
for ipv in range(npv):
|
|
128
|
-
if isnan(a[ipv]) or (a[ipv] <= 1.0) or (e[ipv] < 0.0) or not valid_radius_ratios(k[ipv]):
|
|
129
|
-
flux[ipv, :, :] = nan
|
|
130
|
-
continue
|
|
131
|
-
|
|
132
|
-
kmean = mean(k[ipv])
|
|
133
|
-
kmax = max(k[ipv])
|
|
134
|
-
afac = k[ipv] ** 2 / kmean ** 2
|
|
135
|
-
|
|
136
|
-
# -----------------------------------#
|
|
137
|
-
# Calculate the limb darkening means #
|
|
138
|
-
# -----------------------------------#
|
|
139
|
-
gs, n1 = g_nodes(kmean, ng)
|
|
140
|
-
gc = split_point(kmean)
|
|
141
|
-
ldm_nodes(kmean, gs, rules, mu, wf)
|
|
142
|
-
for ipb in range(npb):
|
|
143
|
-
ldm_table(mu, wf, pt0, pdt, ldp[ipv, ipb, :], ldm)
|
|
144
|
-
split_cubic_coefficients(ldm, n1, coef[ipb])
|
|
145
|
-
|
|
146
|
-
# -----------------------------------------------------#
|
|
147
|
-
# Calculate the Taylor series expansions for the orbit #
|
|
148
|
-
# -----------------------------------------------------#
|
|
149
|
-
xyc[:, :] = solve2d(0.0, p[ipv], a[ipv], i[ipv], e[ipv], w[ipv])
|
|
150
|
-
|
|
151
|
-
# ---------------------------#
|
|
152
|
-
# Calculate the bounding box #
|
|
153
|
-
# ---------------------------#
|
|
154
|
-
bt1, bt4 = bounding_box(kmean, xyc)
|
|
155
|
-
bt1 -= 0.0015 + exptimes[0]
|
|
156
|
-
bt4 += 0.0015 + exptimes[0]
|
|
157
|
-
|
|
158
|
-
# --------------------------#
|
|
159
|
-
# Calculate the light curve #
|
|
160
|
-
# --------------------------#
|
|
161
|
-
for ipt in prange(npt):
|
|
162
|
-
epoch = floor((times[ipt] - t0[ipv] + 0.5 * p[ipv]) / p[ipv])
|
|
163
|
-
tc = times[ipt] - (t0[ipv] + epoch * p[ipv])
|
|
164
|
-
if not (bt1 <= tc <= bt4):
|
|
165
|
-
flux[ipv, :, ipt] = 1.0
|
|
166
|
-
else:
|
|
167
|
-
for isample in range(1, nsamples[0] + 1):
|
|
168
|
-
time_offset = exptimes[0] * ((isample - 0.5) / nsamples[0] - 0.5)
|
|
169
|
-
z = sep_c(tc + time_offset, xyc)
|
|
170
|
-
ap0, kappa = ccia(1.0, kmean, z)
|
|
171
|
-
dadk = 2.0*kmean*kappa
|
|
172
|
-
for ipb in range(npb):
|
|
173
|
-
if z <= 1.0 - kmax:
|
|
174
|
-
for ipb in range(npb):
|
|
175
|
-
iplanet = ldm_lookup(z / (1.0 + kmean), gc, n1, coef[ipb])
|
|
176
|
-
flux[ipv, ipb, ipt] += (istar[ipv, ipb] - iplanet * ap0 * afac[ipb]) / istar[ipv, ipb]
|
|
177
|
-
else:
|
|
178
|
-
for ipb in range(npb):
|
|
179
|
-
iplanet = ldm_lookup(z / (1.0 + kmean), gc, n1, coef[ipb])
|
|
180
|
-
flux[ipv, ipb, ipt] += (istar[ipv, ipb] - iplanet * (
|
|
181
|
-
ap0 + (k[ipv, ipb] - kmean) * dadk)) / istar[ipv, ipb]
|
|
182
|
-
flux[ipv, :, ipt] /= nsamples[0]
|
|
152
|
+
flux = _tsmodel_parallel(times, k, t0, p, a, i, e, w, nsamples, exptimes, ldp, istar, pt0, pdt, rules, ng)
|
|
183
153
|
set_num_threads(nthreads_current)
|
|
184
|
-
return flux
|
|
154
|
+
return flux
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
29
29
|
from typing import Union, List, Optional
|
|
30
30
|
|
|
31
|
-
from numpy import ndarray, isscalar, atleast_2d, atleast_1d, array, zeros, pi
|
|
31
|
+
from numpy import ndarray, isscalar, atleast_2d, atleast_1d, array, zeros, pi, ascontiguousarray
|
|
32
32
|
from pytransit.models.roadrunner.common import calculate_weights_3d
|
|
33
33
|
from scipy.integrate import trapezoid
|
|
34
34
|
|
|
@@ -154,6 +154,7 @@ class TransmissionSpectroscopyModel(RoadRunnerModel):
|
|
|
154
154
|
for ipv in range(npv):
|
|
155
155
|
for ipb in range(npb):
|
|
156
156
|
istar[ipv, ipb] = 2 * pi * trapezoid(self._ldz * ldpi[ipv, ipb], self._ldz)
|
|
157
|
+
ldp = ascontiguousarray(ldp)
|
|
157
158
|
|
|
158
159
|
if self.parallel:
|
|
159
160
|
flux = tsmodel_parallel(self.time, k, t0, p, a, i, e, w, self.nsamples, self.exptimes,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyTransit
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.10.0
|
|
4
4
|
Summary: Fast and painless exoplanet transit light curve modelling.
|
|
5
5
|
Author-email: Hannu Parviainen <hpparvi@gmail.com>
|
|
6
6
|
License: GPLv2
|
|
@@ -42,6 +42,7 @@ PyTransit
|
|
|
42
42
|
=========
|
|
43
43
|
|
|
44
44
|
[](http://www.gnu.org/licenses/gpl-2.0.html)
|
|
45
|
+
[](https://pytransit.readthedocs.io/en/stable/)
|
|
45
46
|
[](http://mnras.oxfordjournals.org/content/450/3/3233)
|
|
46
47
|
[](http://arxiv.org/abs/1504.07433)
|
|
47
48
|
[](http://ascl.net/1505.024)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
pytransit/__init__.py,sha256=
|
|
1
|
+
pytransit/__init__.py,sha256=IVzjo9sDVfDGfmXNobVblugXWyRZgeWbyTNivP4uNO8,3488
|
|
2
|
+
pytransit/_version.py,sha256=Lxklg9HTweyVZKDc1n479t5P2z89i9gcwyKNcMCstwg,530
|
|
2
3
|
pytransit/limb_darkening.py,sha256=OeBPhUWXGKe_QFWcuSMv0b1sR6HbCdrYtTlYhPX-L_c,3538
|
|
3
4
|
pytransit/contamination/__init__.py,sha256=l2TQSaQSc5S0-6YVB_VXu1ddr4_H8GAw4ypNBV2lgNY,1603
|
|
4
5
|
pytransit/contamination/contamination.py,sha256=-BvHXWTFz3FA7p25YA0ABE5OQhwwZFEsM4oIsgjP7nM,14891
|
|
@@ -11,7 +12,7 @@ pytransit/lpf/__init__.py,sha256=SxPyGKv6BYIAR-C1c7oKfEsyHhbsjNofiFNMEWBOOPA,126
|
|
|
11
12
|
pytransit/lpf/cntlpf.py,sha256=CW88sAfLfeRyT1YWNQqiiG1tQhdFfLoyAa-k0dTEFs0,5915
|
|
12
13
|
pytransit/lpf/eclipselpf.py,sha256=ry4aAijqCuJ2AkRma80KPQT6s0xeteSdyvpinlTK7BU,7924
|
|
13
14
|
pytransit/lpf/logposteriorfunction.py,sha256=4J9cYc5taqCksO8ePDMNAlOrZIXck5k6ZeFEKmEXzPQ,18764
|
|
14
|
-
pytransit/lpf/lpf.py,sha256=
|
|
15
|
+
pytransit/lpf/lpf.py,sha256=DtAJO64fK3tq-VZ_3qK1uCD92PSXeb1kvEoJ8a-EwHw,26779
|
|
15
16
|
pytransit/lpf/mclpf.py,sha256=5hYRu5m5pyf9DKihhI4uKXQ-Wr6vCVI3ZCl6cTaHXgE,2271
|
|
16
17
|
pytransit/lpf/mptlpf.py,sha256=nVqP1wwnKv8DJkrWwIEm5OPzA-LImlQLX4l3IwafewQ,6254
|
|
17
18
|
pytransit/lpf/ocllpf.py,sha256=7U1hb_V7M1UNDNlQamv9sGmzuuE2SFX1q5J7DGQUKjE,3273
|
|
@@ -90,20 +91,20 @@ pytransit/models/opencl/ma_uniform.cl,sha256=p56RTe7y5W4d07ARvNRZc4CkM6JP0Sc5p3c
|
|
|
90
91
|
pytransit/models/opencl/orbits.cl,sha256=MG1QVUXSgnubjUi1JWvz_9AJIXh6nUll1tA4EOfxnZA,4230
|
|
91
92
|
pytransit/models/opencl/qpower2.cl,sha256=KDBItLYAyegPupO4YHjBUlzgVP_mr2st5aLtd-5bItQ,4498
|
|
92
93
|
pytransit/models/roadrunner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
93
|
-
pytransit/models/roadrunner/common.py,sha256=
|
|
94
|
+
pytransit/models/roadrunner/common.py,sha256=YdYymuXvpC1XbAlECJVyxympbi3VWLWq7MSpvSth2v4,26872
|
|
94
95
|
pytransit/models/roadrunner/ecintersection.py,sha256=I-QX-j3cf2nyeyGO_m3thOBgtZlJ8i9sFxCBjqLb-os,20461
|
|
95
96
|
pytransit/models/roadrunner/esmodel.py,sha256=L-9xI-Jo_qXyRFQ1F_IeyJsDS-CbdYhH92Al-FNh21E,5474
|
|
96
97
|
pytransit/models/roadrunner/model_eclipse.py,sha256=UIDCQZPQT52tfad9XtJgJpzAPorly3NvRDWOJMCdI18,3125
|
|
97
98
|
pytransit/models/roadrunner/model_ecspec.py,sha256=uao37pDV2a0_rnyqPuMjkEbj6lUG5Swiu1i_LY7N1wU,2651
|
|
98
99
|
pytransit/models/roadrunner/model_full.py,sha256=o8VB7e1cQdnrd81zPmgG0xdDOhoDPUQ-rlab4xNyYu8,6849
|
|
99
100
|
pytransit/models/roadrunner/model_simple.py,sha256=qEZiDxgXwvnfznzWYlmeLYBnlR8Bp4E1rnC-8t95L-8,5843
|
|
100
|
-
pytransit/models/roadrunner/model_trspec.py,sha256=
|
|
101
|
+
pytransit/models/roadrunner/model_trspec.py,sha256=IOR6OY41vv8qTmSC-DGJ2AD5W1QbiWWoOXU2nyilKF4,6696
|
|
101
102
|
pytransit/models/roadrunner/opmodel.py,sha256=v-Ptc-E2a4Vbe5d0qjjAVJT9rUTX9hb2YItC8Qm_w-U,13876
|
|
102
103
|
pytransit/models/roadrunner/opmodel_full.py,sha256=baH78JCwkWJJE4Yjms2Jf64MVd9_nYPhdibezeJQxPI,12588
|
|
103
104
|
pytransit/models/roadrunner/rrmodel.cl,sha256=MGBDT4bW8vHU0wSjOzF4GFK_YzZlcoMUFvwz_1B8X1Q,16782
|
|
104
105
|
pytransit/models/roadrunner/rrmodel.py,sha256=0qcjayQ7S5EHRUM5KP3qqLAF-97RiV0lKrvPPIihTnM,16180
|
|
105
106
|
pytransit/models/roadrunner/rrmodel_cl.py,sha256=SdnarHFI_yetl8xY1u7Rs6Tgh9p70RZpEYFymtDgvTw,27921
|
|
106
|
-
pytransit/models/roadrunner/tsmodel.py,sha256=
|
|
107
|
+
pytransit/models/roadrunner/tsmodel.py,sha256=FbbgZSD_T6vuuNXkzaokGMmDiIFc0GZ7HhZmk3W2sFQ,7517
|
|
107
108
|
pytransit/orbits/__init__.py,sha256=Asb5OytXI9duU0MGF5ufV0QCD9m5Ku_S-pPOkqQIFfM,884
|
|
108
109
|
pytransit/orbits/orbits.py,sha256=e8Gt3VL8dk9HXnsEDfE6gsjRtE7QyvNgCKYkdTFvk-w,4936
|
|
109
110
|
pytransit/orbits/orbits_py.py,sha256=BqP89e5s7sXe-Q2-SIYFTD5lbJfrHBNRV5xmrNHC0o8,20423
|
|
@@ -136,8 +137,8 @@ pytransit/utils/io/__init__.py,sha256=Wh74NDb7IA_cXpvnQBtoAccZXYzm4oqvHJp8lHgWf7
|
|
|
136
137
|
pytransit/utils/io/base.py,sha256=VH8LPu-Fzjv2kOftf91py_sRlgJBHMUtu0QyCI2kymc,15984
|
|
137
138
|
pytransit/utils/io/lcdata.py,sha256=PIy3iKbuCj_ytk8IZ9bIFsrwNxLnGC2VtO336eg4tJI,32924
|
|
138
139
|
pytransit/utils/io/rvdata.py,sha256=9hx0HjN5xmX6jvu73on6mLYZl50aCzuuz9RoKhJaaIg,7229
|
|
139
|
-
pytransit-2.
|
|
140
|
-
pytransit-2.
|
|
141
|
-
pytransit-2.
|
|
142
|
-
pytransit-2.
|
|
143
|
-
pytransit-2.
|
|
140
|
+
pytransit-2.10.0.dist-info/licenses/LICENSE,sha256=s6DMeIC72jjJFdFX2MTU3lCz_4UCUQAcCMtxAqYBiv0,18045
|
|
141
|
+
pytransit-2.10.0.dist-info/METADATA,sha256=Gnd204JSUeLfeShGWVYvOS8TjE-c8kO73Ruv5JH8A0s,5856
|
|
142
|
+
pytransit-2.10.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
143
|
+
pytransit-2.10.0.dist-info/top_level.txt,sha256=Y4wC10N9yBBNslkDDVW6JTmTjMRD5GPgu992lWf6rwk,10
|
|
144
|
+
pytransit-2.10.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|