PyTransit 2.8.1__tar.gz → 2.9.0__tar.gz

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.
Files changed (168) hide show
  1. {pytransit-2.8.1 → pytransit-2.9.0}/PKG-INFO +1 -1
  2. {pytransit-2.8.1 → pytransit-2.9.0}/PyTransit.egg-info/PKG-INFO +1 -1
  3. {pytransit-2.8.1 → pytransit-2.9.0}/PyTransit.egg-info/SOURCES.txt +9 -0
  4. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/__init__.py +2 -1
  5. pytransit-2.9.0/pytransit/lpf/baselines/lstsqbaseline.py +236 -0
  6. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/lpf.py +10 -4
  7. pytransit-2.9.0/pytransit/models/limb_darkening/__init__.py +31 -0
  8. pytransit-2.9.0/pytransit/models/limb_darkening/evaluation.py +55 -0
  9. pytransit-2.9.0/pytransit/models/limb_darkening/exponential.py +15 -0
  10. pytransit-2.9.0/pytransit/models/limb_darkening/general.py +21 -0
  11. pytransit-2.9.0/pytransit/models/limb_darkening/logarithmic.py +14 -0
  12. pytransit-2.9.0/pytransit/models/limb_darkening/nonlinear.py +13 -0
  13. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/limb_darkening/power_2.py +17 -3
  14. pytransit-2.9.0/pytransit/models/limb_darkening/square_root.py +14 -0
  15. pytransit-2.9.0/pytransit/models/numba/ldmodels.py +21 -0
  16. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/roadrunner/common.py +24 -1
  17. pytransit-2.9.0/pytransit/models/roadrunner/ecintersection.py +564 -0
  18. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/roadrunner/model_full.py +63 -19
  19. pytransit-2.9.0/pytransit/models/roadrunner/model_simple.py +120 -0
  20. pytransit-2.9.0/pytransit/models/roadrunner/opmodel.py +249 -0
  21. pytransit-2.9.0/pytransit/models/roadrunner/opmodel_full.py +276 -0
  22. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/roadrunner/rrmodel.py +40 -19
  23. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/roadrunner/rrmodel_cl.py +13 -9
  24. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/roadrunner/tsmodel.py +2 -2
  25. pytransit-2.9.0/tests/test_ecintersection.py +202 -0
  26. pytransit-2.9.0/tests/test_limb_darkening.py +422 -0
  27. pytransit-2.9.0/tests/test_lstsqbaseline.py +320 -0
  28. pytransit-2.9.0/tests/test_opmodel.py +174 -0
  29. pytransit-2.9.0/tests/test_rrmodel.py +90 -0
  30. pytransit-2.8.1/pytransit/models/limb_darkening/general.py +0 -10
  31. pytransit-2.8.1/pytransit/models/limb_darkening/nonlinear.py +0 -6
  32. pytransit-2.8.1/pytransit/models/numba/ldmodels.py +0 -175
  33. pytransit-2.8.1/pytransit/models/roadrunner/ecintersection.py +0 -220
  34. pytransit-2.8.1/pytransit/models/roadrunner/model_simple.py +0 -139
  35. pytransit-2.8.1/pytransit/models/roadrunner/opmodel.py +0 -111
  36. pytransit-2.8.1/pytransit/models/roadrunner/opmodel_full.py +0 -248
  37. pytransit-2.8.1/pytransit/utils/io/__init__.py +0 -0
  38. pytransit-2.8.1/tests/test_limb_darkening.py +0 -199
  39. {pytransit-2.8.1 → pytransit-2.9.0}/LICENSE +0 -0
  40. {pytransit-2.8.1 → pytransit-2.9.0}/MANIFEST.in +0 -0
  41. {pytransit-2.8.1 → pytransit-2.9.0}/PyTransit.egg-info/dependency_links.txt +0 -0
  42. {pytransit-2.8.1 → pytransit-2.9.0}/PyTransit.egg-info/requires.txt +0 -0
  43. {pytransit-2.8.1 → pytransit-2.9.0}/PyTransit.egg-info/top_level.txt +0 -0
  44. {pytransit-2.8.1 → pytransit-2.9.0}/README.md +0 -0
  45. {pytransit-2.8.1 → pytransit-2.9.0}/pyproject.toml +0 -0
  46. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/contamination/__init__.py +0 -0
  47. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/contamination/contamination.py +0 -0
  48. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/contamination/data/spectra.h5 +0 -0
  49. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/contamination/data/transmission.nc +0 -0
  50. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/contamination/filter.py +0 -0
  51. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/contamination/instrument.py +0 -0
  52. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/contamination/plotting.py +0 -0
  53. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/limb_darkening.py +0 -0
  54. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/__init__.py +0 -0
  55. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/baselines/__init__.py +0 -0
  56. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/baselines/legendrebaseline.py +0 -0
  57. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/baselines/linearbaseline.py +0 -0
  58. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/cntlpf.py +0 -0
  59. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/eclipselpf.py +0 -0
  60. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/loglikelihood/__init__.py +0 -0
  61. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/loglikelihood/celeriteloglikelihood.py +0 -0
  62. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/loglikelihood/clloglikelihood.py +0 -0
  63. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/loglikelihood/fmcloglikelihood.py +0 -0
  64. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/loglikelihood/logisticloglikelihood.py +0 -0
  65. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/loglikelihood/multiceleriteloglikelihood.py +0 -0
  66. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/loglikelihood/wnloglikelihood.py +0 -0
  67. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/logposteriorfunction.py +0 -0
  68. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/mclpf.py +0 -0
  69. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/mptlpf.py +0 -0
  70. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/ocllpf.py +0 -0
  71. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/ocltdvlpf.py +0 -0
  72. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/oclttvlpf.py +0 -0
  73. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/phasecurvelpf.py +0 -0
  74. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/rvlpf.py +0 -0
  75. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/tdvlpf.py +0 -0
  76. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/tess/__init__.py +0 -0
  77. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/tess/ctesslpf.py +0 -0
  78. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/tess/tessttvlpf.py +0 -0
  79. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/tess/tgclpf.py +0 -0
  80. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/tess/tgcmplpf.py +0 -0
  81. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/tess/tmpclpf.py +0 -0
  82. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/tesslpf.py +0 -0
  83. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/tessoclttvlpf.py +0 -0
  84. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/transitanalysis.py +0 -0
  85. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/transitlpf.py +0 -0
  86. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/lpf/ttvlpf.py +0 -0
  87. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/__init__.py +0 -0
  88. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/eclipse_model.py +0 -0
  89. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/gdmodel.py +0 -0
  90. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/general.py +0 -0
  91. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/ldmodel.py +0 -0
  92. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/ldtkldm.py +0 -0
  93. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/limb_darkening/linear.py +0 -0
  94. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/limb_darkening/quadratic.py +0 -0
  95. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/limb_darkening/quadratic_tri.py +0 -0
  96. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/limb_darkening/uniform.py +0 -0
  97. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/ma_chromosphere.py +0 -0
  98. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/ma_quadratic.py +0 -0
  99. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/ma_quadratic_cl.py +0 -0
  100. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/ma_uniform.py +0 -0
  101. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/ma_uniform_cl.py +0 -0
  102. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/new_eclipse_model.py +0 -0
  103. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/numba/__init__.py +0 -0
  104. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/numba/gdmodel.py +0 -0
  105. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/numba/general_nb.py +0 -0
  106. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/numba/ldtkldm.py +0 -0
  107. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/numba/ma_chromosphere_nb.py +0 -0
  108. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/numba/ma_quadratic_nb.py +0 -0
  109. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/numba/ma_uniform_nb.py +0 -0
  110. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/numba/phasecurves.py +0 -0
  111. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/numba/qpower2_nb.py +0 -0
  112. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/numba/spmodel.py +0 -0
  113. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/numba/udmodel.py +0 -0
  114. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/opencl/ma_quadratic.cl +0 -0
  115. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/opencl/ma_uniform.cl +0 -0
  116. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/opencl/orbits.cl +0 -0
  117. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/opencl/qpower2.cl +0 -0
  118. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/osmodel.py +0 -0
  119. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/qpower2.py +0 -0
  120. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/qpower2_cl.py +0 -0
  121. {pytransit-2.8.1/pytransit/models/limb_darkening → pytransit-2.9.0/pytransit/models/roadrunner}/__init__.py +0 -0
  122. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/roadrunner/esmodel.py +0 -0
  123. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/roadrunner/model_eclipse.py +0 -0
  124. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/roadrunner/model_ecspec.py +0 -0
  125. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/roadrunner/model_trspec.py +0 -0
  126. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/roadrunner/rrmodel.cl +0 -0
  127. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/transitmodel.py +0 -0
  128. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/models/uniform.py +0 -0
  129. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/orbits/__init__.py +0 -0
  130. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/orbits/orbits.py +0 -0
  131. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/orbits/orbits_py.py +0 -0
  132. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/orbits/taylor_z.py +0 -0
  133. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/param/__init__.py +0 -0
  134. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/param/parameter.py +0 -0
  135. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/param/prior.py +0 -0
  136. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/param/utilities.py +0 -0
  137. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/stars/__init__.py +0 -0
  138. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/stars/btsettl.py +0 -0
  139. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/stars/data/avg_bt_settl.fits +0 -0
  140. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/stars/data/avg_husser2013.fits +0 -0
  141. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/stars/husser2013.py +0 -0
  142. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/__init__.py +0 -0
  143. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/astrometry.py +0 -0
  144. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/constants.py +0 -0
  145. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/de.py +0 -0
  146. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/downsample.py +0 -0
  147. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/eclipses.py +0 -0
  148. {pytransit-2.8.1/pytransit/models/roadrunner → pytransit-2.9.0/pytransit/utils/io}/__init__.py +0 -0
  149. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/io/lightcurvedata.py +0 -0
  150. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/keplerlc.py +0 -0
  151. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/mdwarfs.py +0 -0
  152. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/misc.py +0 -0
  153. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/mocklc.py +0 -0
  154. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/octasphere.py +0 -0
  155. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/phasecurves.py +0 -0
  156. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/physics.py +0 -0
  157. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/rv.py +0 -0
  158. {pytransit-2.8.1 → pytransit-2.9.0}/pytransit/utils/tess.py +0 -0
  159. {pytransit-2.8.1 → pytransit-2.9.0}/requirements.txt +0 -0
  160. {pytransit-2.8.1 → pytransit-2.9.0}/setup.cfg +0 -0
  161. {pytransit-2.8.1 → pytransit-2.9.0}/tests/test_contamination.py +0 -0
  162. {pytransit-2.8.1 → pytransit-2.9.0}/tests/test_ma_quadratic.py +0 -0
  163. {pytransit-2.8.1 → pytransit-2.9.0}/tests/test_ma_quadratic_nb.py +0 -0
  164. {pytransit-2.8.1 → pytransit-2.9.0}/tests/test_qpower2_nb.py +0 -0
  165. {pytransit-2.8.1 → pytransit-2.9.0}/tests/test_roadrunner_eclipse.py +0 -0
  166. {pytransit-2.8.1 → pytransit-2.9.0}/tests/test_uniform_model.py +0 -0
  167. {pytransit-2.8.1 → pytransit-2.9.0}/tests/test_uniform_model_nb.py +0 -0
  168. {pytransit-2.8.1 → pytransit-2.9.0}/tests/test_z.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyTransit
3
- Version: 2.8.1
3
+ Version: 2.9.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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyTransit
3
- Version: 2.8.1
3
+ Version: 2.9.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
@@ -38,6 +38,7 @@ pytransit/lpf/ttvlpf.py
38
38
  pytransit/lpf/baselines/__init__.py
39
39
  pytransit/lpf/baselines/legendrebaseline.py
40
40
  pytransit/lpf/baselines/linearbaseline.py
41
+ pytransit/lpf/baselines/lstsqbaseline.py
41
42
  pytransit/lpf/loglikelihood/__init__.py
42
43
  pytransit/lpf/loglikelihood/celeriteloglikelihood.py
43
44
  pytransit/lpf/loglikelihood/clloglikelihood.py
@@ -69,12 +70,16 @@ pytransit/models/qpower2_cl.py
69
70
  pytransit/models/transitmodel.py
70
71
  pytransit/models/uniform.py
71
72
  pytransit/models/limb_darkening/__init__.py
73
+ pytransit/models/limb_darkening/evaluation.py
74
+ pytransit/models/limb_darkening/exponential.py
72
75
  pytransit/models/limb_darkening/general.py
73
76
  pytransit/models/limb_darkening/linear.py
77
+ pytransit/models/limb_darkening/logarithmic.py
74
78
  pytransit/models/limb_darkening/nonlinear.py
75
79
  pytransit/models/limb_darkening/power_2.py
76
80
  pytransit/models/limb_darkening/quadratic.py
77
81
  pytransit/models/limb_darkening/quadratic_tri.py
82
+ pytransit/models/limb_darkening/square_root.py
78
83
  pytransit/models/limb_darkening/uniform.py
79
84
  pytransit/models/numba/__init__.py
80
85
  pytransit/models/numba/gdmodel.py
@@ -138,11 +143,15 @@ pytransit/utils/tess.py
138
143
  pytransit/utils/io/__init__.py
139
144
  pytransit/utils/io/lightcurvedata.py
140
145
  tests/test_contamination.py
146
+ tests/test_ecintersection.py
141
147
  tests/test_limb_darkening.py
148
+ tests/test_lstsqbaseline.py
142
149
  tests/test_ma_quadratic.py
143
150
  tests/test_ma_quadratic_nb.py
151
+ tests/test_opmodel.py
144
152
  tests/test_qpower2_nb.py
145
153
  tests/test_roadrunner_eclipse.py
154
+ tests/test_rrmodel.py
146
155
  tests/test_uniform_model.py
147
156
  tests/test_uniform_model_nb.py
148
157
  tests/test_z.py
@@ -41,7 +41,7 @@ Date
41
41
 
42
42
  """
43
43
 
44
- __version__ = '2.8.1'
44
+ __version__ = '2.9.0'
45
45
 
46
46
  # Generic
47
47
  # -------
@@ -86,6 +86,7 @@ from .lpf.transitlpf import TransitLPF
86
86
  from .lpf.cntlpf import PhysContLPF
87
87
  from .lpf.baselines.legendrebaseline import LegendreBaseline
88
88
  from .lpf.baselines.linearbaseline import LinearModelBaseline
89
+ from .lpf.baselines.lstsqbaseline import LSTSQBaseline
89
90
  from .lpf.transitanalysis import TransitAnalysis
90
91
 
91
92
  # Utilities
@@ -0,0 +1,236 @@
1
+ # PyTransit: fast and easy exoplanet transit modelling in Python.
2
+ # Copyright (C) 2010-2019 Hannu Parviainen
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+
17
+ from typing import Optional
18
+
19
+ from numpy import (asarray, atleast_2d, ones, zeros, hstack, unique, isfinite, nan, ndarray,
20
+ errstate, where)
21
+ from numpy.linalg import pinv, LinAlgError, cond
22
+
23
+
24
+ class LSTSQBaseline:
25
+ """A parameterless multiplicative baseline fitted by linear least squares.
26
+
27
+ ``LSTSQBaseline`` models the same linear-in-covariates baseline as
28
+ :class:`~pytransit.lpf.baselines.linearbaseline.LinearModelBaseline`, but adds *no*
29
+ free parameters to the LPF's parameter set. Instead, the baseline coefficients are
30
+ solved for directly at every evaluation by least-squares fitting the relative
31
+ residuals ``flux_obs / flux_model``.
32
+
33
+ This works because the baseline is linear in its coefficients, so conditional on the
34
+ transit model they have a closed-form maximum-likelihood solution. The coefficients
35
+ are *profiled out* rather than sampled.
36
+
37
+ .. note::
38
+ Profiling is not marginalisation. The posterior conditions on the best-fit
39
+ baseline rather than integrating over it, so parameter uncertainties are somewhat
40
+ underestimated relative to a fully marginalised treatment.
41
+
42
+ The design matrix is fixed (it depends only on the covariates, never on the parameter
43
+ vector), so its pseudoinverse is computed once in :meth:`init_data`. Each call is then
44
+ two small matrix products, fully vectorised over the parameter vector population.
45
+
46
+ Usage
47
+ -----
48
+ ``LSTSQBaseline`` does not join the ``BaseLPF._baseline_models`` chain: those models
49
+ are called as ``blm(pv, bl)`` and are evaluated *before* the transit model, an ordering
50
+ a least-squares baseline cannot satisfy. An LPF opts in by overriding ``flux_model``::
51
+
52
+ class MyLPF(BaseLPF):
53
+ def _init_baseline(self):
54
+ self.lstsq_baseline = LSTSQBaseline(self)
55
+
56
+ def flux_model(self, pv):
57
+ fmod = self.transit_model(pv)
58
+ return fmod * self.lstsq_baseline(fmod) + self.trends(pv)
59
+
60
+ Because the model is not registered with ``_add_baseline_model``, ``lpf.baseline(pv)``
61
+ will *not* return this baseline. Plotting helpers that rely on ``lpf.baseline(pv)``
62
+ should call ``lpf.lstsq_baseline(lpf.transit_model(pv))`` instead.
63
+
64
+ Parameters
65
+ ----------
66
+ lpf
67
+ The log posterior function the baseline belongs to. Its data must already be
68
+ initialised, and it must have been given covariates.
69
+ name
70
+ Name of the baseline model.
71
+ lcids
72
+ Indices of the light curves the baseline is applied to. Defaults to all of them.
73
+ Points belonging to light curves not covered keep a baseline of exactly 1.0.
74
+ """
75
+
76
+ def __init__(self, lpf, name: str = 'lstsq', lcids=None):
77
+ self.name = name
78
+ self.lpf = lpf
79
+
80
+ if lpf.lcids is None:
81
+ raise ValueError('The LPF data needs to be initialised before initialising LSTSQBaseline.')
82
+
83
+ if lpf.covariates is None:
84
+ raise ValueError('LSTSQBaseline requires the LPF to be initialised with covariates.')
85
+
86
+ self._bl: Optional[ndarray] = None
87
+ self.init_data(lcids)
88
+
89
+ @staticmethod
90
+ def normalize_covariates(covariates: ndarray) -> ndarray:
91
+ """Normalise a light curve's covariate matrix before the intercept column is added.
92
+
93
+ Each column is standardised to zero mean and unit standard deviation. Mixing a
94
+ column on an arbitrary scale (raw BJD ~2.46e6, pixel positions ~1e3) with an
95
+ intercept column of ones makes the design matrix badly conditioned, and ``pinv``
96
+ returns a numerically poor solution rather than raising.
97
+
98
+ ``BaseLPF._init_data`` already standardises the covariates it stores, so this is
99
+ normally a no-op. It is applied anyway because standardisation is idempotent and
100
+ this class may be handed covariates that did not come through that path.
101
+
102
+ Constant columns are only centred: they carry no information, and scaling them
103
+ would divide by zero. A design matrix left rank deficient by such a column is
104
+ caught by :meth:`_check_conditioning`.
105
+
106
+ Parameters
107
+ ----------
108
+ covariates
109
+ Covariate matrix of shape ``(npt, ncov)``.
110
+
111
+ Returns
112
+ -------
113
+ The standardised covariate matrix, same shape as the input.
114
+ """
115
+ cs = covariates.std(0)
116
+ return (covariates - covariates.mean(0)) / where(cs > 0.0, cs, 1.0)
117
+
118
+ def init_data(self, lcids=None):
119
+ """Build the per-light-curve design matrices and their pseudoinverses."""
120
+ self.lcids = lcids if lcids is not None else unique(self.lpf.lcids)
121
+ self.nlc = self.lcids.size
122
+ self.slices = [self.lpf.lcslices[lcid] for lcid in self.lcids]
123
+
124
+ self.covs = []
125
+ self.pinvs = []
126
+ for i, lcid in enumerate(self.lcids):
127
+ cv = self.normalize_covariates(asarray(self.lpf.covariates[lcid], 'd'))
128
+ if cv.ndim == 1:
129
+ cv = cv[:, None]
130
+ x = hstack([ones((cv.shape[0], 1)), cv])
131
+ self._check_conditioning(x, lcid)
132
+ try:
133
+ self.pinvs.append(pinv(x))
134
+ except LinAlgError as e:
135
+ raise LinAlgError(f'Failed to invert the {self.name} design matrix for light curve {lcid}: {e}')
136
+ self.covs.append(x)
137
+
138
+ self.ncoef = [x.shape[1] for x in self.covs]
139
+
140
+ # Flat mask of the points this baseline covers. Points outside it stay at 1.0.
141
+ self.mask = zeros(self.lpf.lcids.size, bool)
142
+ for sl in self.slices:
143
+ self.mask[sl] = 1
144
+
145
+ @staticmethod
146
+ def _check_conditioning(x: ndarray, lcid: int, limit: float = 1e10) -> None:
147
+ with errstate(all='ignore'):
148
+ c = cond(x)
149
+ if not isfinite(c) or c > limit:
150
+ raise ValueError(
151
+ f'The design matrix for light curve {lcid} is singular or badly conditioned '
152
+ f'(condition number {c:.3e}). The covariates are standardised automatically, so '
153
+ f'this points to duplicate, constant, or linearly dependent covariate columns.')
154
+
155
+ def _baseline_array(self, npv: int) -> ndarray:
156
+ """Return the cached output buffer, reallocating it only when `npv` changes."""
157
+ if self._bl is None or self._bl.shape[0] != npv:
158
+ self._bl = ones((npv, self.lpf.timea.size))
159
+ return self._bl
160
+
161
+ def _observed_flux(self, oflux) -> ndarray:
162
+ """Validate the observed flux and return it as a 2D array broadcastable over `npv`."""
163
+ of = atleast_2d(self.lpf.ofluxa if oflux is None else asarray(oflux, 'd'))
164
+ if of.shape[-1] != self.lpf.timea.size:
165
+ raise ValueError(f'The observed flux has {of.shape[-1]} points, but the LPF data has '
166
+ f'{self.lpf.timea.size}.')
167
+ return of
168
+
169
+ def _fit(self, fmod: ndarray, oflux: ndarray, i: int) -> ndarray:
170
+ """Least-squares coefficients for light curve `i`, for all parameter vectors."""
171
+ sl = self.slices[i]
172
+ with errstate(divide='ignore', invalid='ignore'):
173
+ res = oflux[:, sl] / fmod[:, sl] # (npv, npt_lc)
174
+ return res @ self.pinvs[i].T # (npv, ncoef)
175
+
176
+ def coefficients(self, fmod, oflux=None):
177
+ """Fit the baseline and return its coefficients rather than its evaluation.
178
+
179
+ Parameters
180
+ ----------
181
+ fmod
182
+ Model fluxes, either a 1D ``(npt,)`` array or a 2D ``(npv, npt)`` array.
183
+ oflux
184
+ Observed fluxes to fit against, either a 1D ``(npt,)`` array or a 2D
185
+ ``(npv, npt)`` array. Defaults to the LPF's own ``ofluxa``.
186
+
187
+ Returns
188
+ -------
189
+ A list with one entry per covered light curve. Each entry has shape
190
+ ``(npv, ncoef)`` for a 2D `fmod` and ``(ncoef,)`` for a 1D one, where the first
191
+ coefficient is the intercept. The coefficient count may differ between light
192
+ curves, which is why this is a list rather than an array.
193
+ """
194
+ fmod = asarray(fmod, 'd')
195
+ fm = atleast_2d(fmod)
196
+ of = self._observed_flux(oflux)
197
+ cs = [self._fit(fm, of, i) for i in range(self.nlc)]
198
+ return cs if fmod.ndim > 1 else [c[0] for c in cs]
199
+
200
+ def __call__(self, fmod, oflux=None):
201
+ """Fit and evaluate the baseline for a set of model fluxes.
202
+
203
+ Parameters
204
+ ----------
205
+ fmod
206
+ Model fluxes, either a 1D ``(npt,)`` array or a 2D ``(npv, npt)`` array,
207
+ where `npt` is the total number of datapoints in the LPF.
208
+ oflux
209
+ Observed fluxes to fit against, either a 1D ``(npt,)`` array or a 2D
210
+ ``(npv, npt)`` array. Defaults to the LPF's own ``ofluxa``, which is what a
211
+ likelihood evaluation wants; pass it explicitly to fit the baseline against
212
+ simulated or otherwise modified data.
213
+
214
+ Returns
215
+ -------
216
+ The multiplicative baseline, shaped like `fmod`. A parameter vector whose fit
217
+ fails, or whose residuals are not finite, gets an all-NaN baseline, which
218
+ propagates to a non-finite log likelihood and is rejected by the sampler.
219
+
220
+ .. warning::
221
+ The returned array is a reused internal buffer that the next call overwrites.
222
+ Copy it if you need to keep it.
223
+ """
224
+ fmod = asarray(fmod, 'd')
225
+ fm = atleast_2d(fmod)
226
+ of = self._observed_flux(oflux)
227
+ bl = self._baseline_array(fm.shape[0])
228
+
229
+ for i, sl in enumerate(self.slices):
230
+ b = self._fit(fm, of, i) @ self.covs[i].T # (npv, npt_lc)
231
+ bad = ~isfinite(b).all(axis=1)
232
+ if bad.any():
233
+ b[bad] = nan
234
+ bl[:, sl] = b
235
+
236
+ return bl if fmod.ndim > 1 else bl[0]
@@ -303,9 +303,15 @@ class BaseLPF(LogPosteriorFunction):
303
303
  # Initialise the covariate arrays, if given
304
304
  # -----------------------------------------
305
305
  if covariates is not None:
306
- self.covariates = covariates
307
- for cv in self.covariates:
308
- cv = (cv - cv.mean(0)) / cv.std(0)
306
+ # Standardise the covariates to zero mean and unit standard deviation. This keeps
307
+ # the baseline design matrices well conditioned and makes the covariate coefficient
308
+ # priors comparable across covariates. Constant columns are only centred, since
309
+ # they cannot be scaled.
310
+ self.covariates = []
311
+ for cv in covariates:
312
+ cv = asarray(cv, 'd')
313
+ cs = cv.std(0)
314
+ self.covariates.append((cv - cv.mean(0)) / where(cs > 0.0, cs, 1.0))
309
315
  #self.ncovs = self.covariates[0].shape[1]
310
316
  #self.covsize = array([c.size for c in self.covariates])
311
317
  #self.covstart = concatenate([[0], self.covsize.cumsum()[:-1]])
@@ -561,7 +567,7 @@ class BaseLPF(LogPosteriorFunction):
561
567
  if self.errors is not None:
562
568
  errors.append(self.errors[i][mask])
563
569
 
564
- self._init_data(times=times, fluxes=fluxes, covariates=self.covariates, pbids=self.pbids,
570
+ self._init_data(times=times, fluxes=fluxes, covariates=covariates, pbids=self.pbids,
565
571
  errors=(errors if self.errors is not None else None), wnids=self.noise_ids,
566
572
  nsamples=self.nsamples, exptimes=self.exptimes)
567
573
 
@@ -0,0 +1,31 @@
1
+ """Numba-accelerated limb darkening models.
2
+
3
+ Each model is defined by an intensity profile function ``ld_<model>(mu, pv)``
4
+ and, where an analytic solution exists, a disk-integrated stellar intensity
5
+ function ``ldi_<model>(pv)`` returning 2*pi * int_0^1 I(mu) mu dmu, and a
6
+ derivative function ``ldd_<model>(mu, pv)``.
7
+ """
8
+ from .evaluation import evaluate_ld, evaluate_ldi
9
+ from .exponential import ld_exponential, ldi_exponential
10
+ from .general import ld_general, ldi_general
11
+ from .linear import ld_linear, ldi_linear, ldd_linear
12
+ from .logarithmic import ld_logarithmic, ldi_logarithmic
13
+ from .nonlinear import ld_nonlinear, ldi_nonlinear
14
+ from .power_2 import ld_power_2, ldi_power_2, ldd_power_2, ld_power_2_pm, ldi_power_2_pm
15
+ from .quadratic import ld_quadratic, ldi_quadratic, ldd_quadratic
16
+ from .quadratic_tri import ld_quadratic_tri, ldi_quadratic_tri
17
+ from .square_root import ld_square_root, ldi_square_root
18
+ from .uniform import ld_uniform, ldi_uniform
19
+
20
+ __all__ = ['ld_uniform', 'ldi_uniform',
21
+ 'ld_linear', 'ldi_linear', 'ldd_linear',
22
+ 'ld_quadratic', 'ldi_quadratic', 'ldd_quadratic',
23
+ 'ld_quadratic_tri', 'ldi_quadratic_tri',
24
+ 'ld_nonlinear', 'ldi_nonlinear',
25
+ 'ld_general', 'ldi_general',
26
+ 'ld_power_2', 'ldi_power_2', 'ldd_power_2',
27
+ 'ld_power_2_pm', 'ldi_power_2_pm',
28
+ 'ld_square_root', 'ldi_square_root',
29
+ 'ld_logarithmic', 'ldi_logarithmic',
30
+ 'ld_exponential', 'ldi_exponential',
31
+ 'evaluate_ld', 'evaluate_ldi']
@@ -0,0 +1,55 @@
1
+ from numba import njit
2
+ from numpy import zeros
3
+
4
+
5
+ @njit
6
+ def evaluate_ld(ldm, mu, pvo):
7
+ """Evaluate a limb darkening model for 1D, 2D, or 3D parameter arrays.
8
+
9
+ The parameters can be given as a 1D array with a shape (nldc), a 2D array
10
+ with a shape (npb, nldc), or a 3D array with a shape (npv, npb, nldc),
11
+ where nldc is the number of limb darkening coefficients, npb is the number
12
+ of passbands, and npv is the number of parameter vectors.
13
+
14
+ Returns the limb darkening profiles as a 3D array with a shape
15
+ (npv, npb, nmu).
16
+ """
17
+ if pvo.ndim == 1:
18
+ pv = pvo.reshape((1, 1, -1))
19
+ elif pvo.ndim == 2:
20
+ pv = pvo.reshape((1, pvo.shape[0], -1))
21
+ else:
22
+ pv = pvo
23
+
24
+ npv = pv.shape[0]
25
+ npb = pv.shape[1]
26
+ ldp = zeros((npv, npb, mu.size))
27
+ for ipv in range(npv):
28
+ for ipb in range(npb):
29
+ ldp[ipv, ipb, :] = ldm(mu, pv[ipv, ipb])
30
+ return ldp
31
+
32
+
33
+ @njit
34
+ def evaluate_ldi(ldi, pvo):
35
+ """Evaluate a disk-integrated stellar intensity for 1D, 2D, or 3D parameter arrays.
36
+
37
+ The parameters follow the same conventions as in ``evaluate_ld``.
38
+
39
+ Returns the disk-integrated stellar intensities as a 2D array with a
40
+ shape (npv, npb).
41
+ """
42
+ if pvo.ndim == 1:
43
+ pv = pvo.reshape((1, 1, -1))
44
+ elif pvo.ndim == 2:
45
+ pv = pvo.reshape((1, pvo.shape[0], -1))
46
+ else:
47
+ pv = pvo
48
+
49
+ npv = pv.shape[0]
50
+ npb = pv.shape[1]
51
+ istar = zeros((npv, npb))
52
+ for ipv in range(npv):
53
+ for ipb in range(npb):
54
+ istar[ipv, ipb] = ldi(pv[ipv, ipb])
55
+ return istar
@@ -0,0 +1,15 @@
1
+ from math import pi
2
+
3
+ from numba import njit
4
+ from numpy import exp
5
+
6
+
7
+ @njit(fastmath=True)
8
+ def ld_exponential(mu, pv):
9
+ return 1. - pv[0] * (1. - mu) - pv[1] / (1. - exp(mu))
10
+
11
+
12
+ @njit(fastmath=True)
13
+ def ldi_exponential(pv):
14
+ # -int_0^1 mu/(1-exp(mu)) dmu = pi^2/6 + ln(1-1/e) - Li2(1/e)
15
+ return 2 * pi * (0.5 - pv[0] / 6 + 0.7775046341122480 * pv[1])
@@ -0,0 +1,21 @@
1
+ from math import pi
2
+
3
+ from numba import njit
4
+ from numpy import ones
5
+
6
+
7
+ @njit(fastmath=True)
8
+ def ld_general(mu, pv):
9
+ """Giménez (2006) general limb darkening model: I(mu) = 1 - sum c_i (1 - mu^(i+1))."""
10
+ ldp = ones(mu.size)
11
+ for i in range(pv.size):
12
+ ldp -= pv[i] * (1.0 - mu ** (i + 1))
13
+ return ldp
14
+
15
+
16
+ @njit(fastmath=True)
17
+ def ldi_general(pv):
18
+ istar = 0.5
19
+ for i in range(pv.size):
20
+ istar -= pv[i] * (0.5 - 1.0 / (i + 3))
21
+ return 2 * pi * istar
@@ -0,0 +1,14 @@
1
+ from math import pi
2
+
3
+ from numba import njit
4
+ from numpy import log
5
+
6
+
7
+ @njit(fastmath=True)
8
+ def ld_logarithmic(mu, pv):
9
+ return 1. - pv[0] * (1. - mu) - pv[1] * mu * log(mu)
10
+
11
+
12
+ @njit(fastmath=True)
13
+ def ldi_logarithmic(pv):
14
+ return 2 * pi * (0.5 - pv[0] / 6 + pv[1] / 9)
@@ -0,0 +1,13 @@
1
+ from math import pi
2
+
3
+ from numba import njit
4
+
5
+
6
+ @njit(fastmath=True)
7
+ def ld_nonlinear(mu, pv):
8
+ return 1. - pv[0] * (1. - mu**0.5) - pv[1] * (1. - mu) - pv[2] * (1. - mu**1.5) - pv[3] * (1. - mu ** 2)
9
+
10
+
11
+ @njit(fastmath=True)
12
+ def ldi_nonlinear(pv):
13
+ return 2 * pi * (0.5 - pv[0] / 10 - pv[1] / 6 - 3 * pv[2] / 14 - pv[3] / 4)
@@ -1,7 +1,7 @@
1
1
  from math import pi
2
2
 
3
3
  from numba import njit
4
- from numpy import zeros, log
4
+ from numpy import zeros, log, log2
5
5
 
6
6
 
7
7
  @njit(fastmath=True)
@@ -10,7 +10,7 @@ def ld_power_2(mu, pv):
10
10
 
11
11
 
12
12
  @njit
13
- def ldi_power_2(mu, pv):
13
+ def ldi_power_2(pv):
14
14
  return 2 * pi * (0.5 - 0.5 * pv[0] + pv[0] / (pv[1] + 2.0))
15
15
 
16
16
 
@@ -20,4 +20,18 @@ def ldd_power_2(mu, pv):
20
20
  ldd[0] = pv[0]*pv[1]*mu**(pv[1]-1.0)
21
21
  ldd[1] = mu**pv[1] - 1.0
22
22
  ldd[2] = pv[0]*mu**pv[1] * log(mu)
23
- return ldd
23
+ return ldd
24
+
25
+
26
+ @njit(fastmath=True)
27
+ def ld_power_2_pm(mu, pv):
28
+ c = 1 - pv[0] + pv[1]
29
+ a = log2(c/pv[1])
30
+ return 1. - c * (1. - mu**a)
31
+
32
+
33
+ @njit
34
+ def ldi_power_2_pm(pv):
35
+ c = 1 - pv[0] + pv[1]
36
+ a = log2(c/pv[1])
37
+ return 2 * pi * (0.5 - 0.5 * c + c / (a + 2.0))
@@ -0,0 +1,14 @@
1
+ from math import pi
2
+
3
+ from numba import njit
4
+ from numpy import sqrt
5
+
6
+
7
+ @njit(fastmath=True)
8
+ def ld_square_root(mu, pv):
9
+ return 1. - pv[0] * (1. - mu) - pv[1] * (1. - sqrt(mu))
10
+
11
+
12
+ @njit(fastmath=True)
13
+ def ldi_square_root(pv):
14
+ return 2 * pi * (0.5 - pv[0] / 6 - pv[1] / 10)
@@ -0,0 +1,21 @@
1
+ # PyTransit: fast and easy exoplanet transit modelling in Python.
2
+ # Copyright (C) 2010-2020 Hannu Parviainen
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
16
+ """Deprecated: the limb darkening models live in ``pytransit.models.limb_darkening``.
17
+
18
+ This module re-exports them for backwards compatibility.
19
+ """
20
+ from ..limb_darkening import *
21
+ from ..limb_darkening import __all__
@@ -237,4 +237,27 @@ def interpolate_mean_limb_darkening_v(gs, dg, lda):
237
237
  r = zeros(gs.size)
238
238
  for i in range(gs.size):
239
239
  r[i] = interpolate_mean_limb_darkening_s(gs[i], dg, lda)
240
- return r
240
+ return r
241
+
242
+ @njit(fastmath=True)
243
+ def interpolate_limb_darkening_s(z, zm, ldp):
244
+ """Interpolate a tabulated limb darkening profile at a normalized distance z.
245
+
246
+ Linear interpolation of the limb darkening profile over the (non-uniform) profile node
247
+ grid `zm`, clamped to the last node beyond the edge of the grid. Used by the small-planet
248
+ approximation, where the mean intensity blocked by the planet is approximated by the
249
+ stellar intensity at the planet's center.
250
+ """
251
+ if z < 0.0:
252
+ return nan
253
+ if z >= zm[-1]:
254
+ return ldp[-1]
255
+ i = zm.size // 2
256
+ if z > zm[i]:
257
+ while z > zm[i + 1]:
258
+ i += 1
259
+ else:
260
+ while z < zm[i]:
261
+ i -= 1
262
+ a = (z - zm[i]) / (zm[i + 1] - zm[i])
263
+ return (1.0 - a) * ldp[i] + a * ldp[i + 1]