archeo 2.0.0.dev5__tar.gz → 2.0.0.dev7__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 (62) hide show
  1. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/PKG-INFO +1 -1
  2. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/bayesian/ancestral_posterior.py +5 -4
  3. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/bayesian/importance_sampling/__init__.py +1 -0
  4. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/bayesian/importance_sampling/bayes_factor_curve.py +3 -8
  5. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/bayesian/importance_sampling/resampler/base.py +3 -2
  6. archeo-2.0.0.dev7/archeo/constants/bayesian.py +3 -0
  7. archeo-2.0.0.dev7/archeo/constants/physics.py +58 -0
  8. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/data_structures/bayesian/bayes_factor.py +5 -2
  9. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/visualization/base.py +2 -2
  10. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/visualization/estimation.py +2 -2
  11. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo.egg-info/PKG-INFO +1 -1
  12. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo.egg-info/SOURCES.txt +1 -0
  13. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/pyproject.toml +1 -1
  14. archeo-2.0.0.dev5/archeo/constants/physics.py +0 -70
  15. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/LICENSE +0 -0
  16. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/README.md +0 -0
  17. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/__init__.py +0 -0
  18. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/__main__.py +0 -0
  19. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/bayesian/__init__.py +0 -0
  20. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/bayesian/importance_sampling/resampler/__init__.py +0 -0
  21. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/bayesian/importance_sampling/resampler/assume_independence.py +0 -0
  22. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/bayesian/importance_sampling/resampler/generic.py +0 -0
  23. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/bayesian/importance_sampling/resampler/interface.py +0 -0
  24. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/constants/__init__.py +0 -0
  25. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/constants/enum.py +0 -0
  26. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/data_structures/__init__.py +0 -0
  27. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/data_structures/annotation.py +0 -0
  28. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/data_structures/distribution.py +0 -0
  29. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/data_structures/math.py +0 -0
  30. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/data_structures/physics/__init__.py +0 -0
  31. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/data_structures/physics/binary.py +0 -0
  32. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/data_structures/physics/black_hole.py +0 -0
  33. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/data_structures/physics/mahapatra.py +0 -0
  34. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/data_structures/physics/simulation.py +0 -0
  35. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/data_structures/visualization.py +0 -0
  36. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/postprocessing/__init__.py +0 -0
  37. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/postprocessing/dataframe.py +0 -0
  38. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/preset/__init__.py +0 -0
  39. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/preset/cli.py +0 -0
  40. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/preset/forward/__init__.py +0 -0
  41. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/preset/forward/compute_bayes_factor_curve.py +0 -0
  42. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/preset/simulation/__init__.py +0 -0
  43. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/preset/simulation/agnostic.py +0 -0
  44. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/preset/simulation/n_generation.py +0 -0
  45. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/preset/simulation/second_generation.py +0 -0
  46. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/py.typed +0 -0
  47. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/simulation/__init__.py +0 -0
  48. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/simulation/simulate_merger.py +0 -0
  49. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/utils/__init__.py +0 -0
  50. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/utils/decorator.py +0 -0
  51. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/utils/env.py +0 -0
  52. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/utils/fs.py +0 -0
  53. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/utils/logger.py +0 -0
  54. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/utils/parallel.py +0 -0
  55. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/version.py +0 -0
  56. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/visualization/__init__.py +0 -0
  57. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/visualization/animation.py +0 -0
  58. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo/visualization/distribution.py +0 -0
  59. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo.egg-info/dependency_links.txt +0 -0
  60. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo.egg-info/requires.txt +0 -0
  61. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/archeo.egg-info/top_level.txt +0 -0
  62. {archeo-2.0.0.dev5 → archeo-2.0.0.dev7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: archeo
3
- Version: 2.0.0.dev5
3
+ Version: 2.0.0.dev7
4
4
  Summary: Bayesian framework for inferring natal kick, ancestral masses and spins of black holes.
5
5
  Author-email: wyhwong <wyhwong@link.cuhk.edu.hk>
6
6
  License-Expression: MIT
@@ -1,6 +1,7 @@
1
1
  import numpy as np
2
2
  import pandas as pd
3
3
 
4
+ from archeo.constants.bayesian import DEFAULT_BINSIZE_MASS, DEFAULT_BINSIZE_SPIN
4
5
  from archeo.utils.parallel import get_n_workers, multiprocess_run, multithread_run
5
6
 
6
7
 
@@ -8,8 +9,8 @@ def _retrieve_sample(
8
9
  df_binaries: pd.DataFrame,
9
10
  mass_measure: float,
10
11
  spin_measure: float,
11
- binsize_mass: float = 2.0,
12
- binsize_spin: float = 0.1,
12
+ binsize_mass: float = DEFAULT_BINSIZE_MASS,
13
+ binsize_spin: float = DEFAULT_BINSIZE_SPIN,
13
14
  ) -> pd.DataFrame:
14
15
  """Retrieve the samples from data frame of binaries"""
15
16
 
@@ -36,8 +37,8 @@ def infer_ancestral_posterior_distribution(
36
37
  df_binaries: pd.DataFrame,
37
38
  mass_posterior_samples: list[float],
38
39
  spin_posterior_samples: list[float],
39
- binsize_mass: float = 2.0,
40
- binsize_spin: float = 0.1,
40
+ binsize_mass: float = DEFAULT_BINSIZE_MASS,
41
+ binsize_spin: float = DEFAULT_BINSIZE_SPIN,
41
42
  random_state: int = 42,
42
43
  n_workers: int = 1,
43
44
  ) -> pd.DataFrame:
@@ -1,2 +1,3 @@
1
1
  from archeo.bayesian.importance_sampling.bayes_factor_curve import BayesFactorCurve, CandidatePrior
2
2
  from archeo.bayesian.importance_sampling.resampler.interface import ImportanceSamplingData
3
+ from archeo.data_structures.bayesian.bayes_factor import BayesFactorCurveMetadata
@@ -38,7 +38,7 @@ class CandidatePrior(BaseModel):
38
38
  df_bh1_prior = self.df_bh1.loc[self.df_bh1["v_esc"] <= v_esc]
39
39
  df_bh2_prior = self.df_bh2.loc[self.df_bh2["v_esc"] <= v_esc]
40
40
 
41
- if df_bh1_prior.empty and df_bh2_prior.empty:
41
+ if df_bh1_prior.empty or df_bh2_prior.empty:
42
42
  return pd.DataFrame(columns=self.df_bh1.columns.union(self.df_bh2.columns))
43
43
 
44
44
  n_samples = max(len(df_bh1_prior), len(df_bh2_prior), n_min)
@@ -57,14 +57,10 @@ class CandidatePrior(BaseModel):
57
57
  v_esc_max = max(self.df_bh1["v_esc"].max(), self.df_bh2["v_esc"].max())
58
58
 
59
59
  if log_scale:
60
- v_escs = np.logspace(np.log10(v_esc_min), np.log10(v_esc_max), n_pts)
60
+ v_escs = np.logspace(max(np.log10(v_esc_min), np.log10(0.1)), np.log10(v_esc_max), n_pts)
61
61
  else:
62
62
  v_escs = np.linspace(v_esc_min, v_esc_max, n_pts)
63
63
 
64
- # Add zero in the beginning of the list if it's not already included
65
- if v_escs[0] > 0:
66
- v_escs = np.insert(v_escs, 0, 0.0)
67
-
68
64
  # Add 5000 km/s in the end of the list if it's not already included
69
65
  if v_escs[-1] < 5000:
70
66
  v_escs = np.append(v_escs, 5000.0)
@@ -78,7 +74,6 @@ class BayesFactorCurve(BaseModel, frozen=True):
78
74
  n_bootstrapping: int = 50
79
75
  n_pts: int = 10
80
76
  log_scale: bool = False
81
- assume_parameter_independence: bool = False
82
77
  metadata: BayesFactorCurveMetadata = BayesFactorCurveMetadata()
83
78
 
84
79
  def _sample_bayes_factor(
@@ -95,7 +90,7 @@ class BayesFactorCurve(BaseModel, frozen=True):
95
90
  new_prior_samples=candidate_prior.get_conditional_prior(v_esc),
96
91
  binsize_spin=self.metadata.binsize_spin,
97
92
  binsize_mass=self.metadata.binsize_mass,
98
- assume_parameter_independence=self.assume_parameter_independence,
93
+ assume_parameter_independence=self.metadata.assume_parameter_independence,
99
94
  ).sample_bayes_factor(n=self.n_bootstrapping, is_parallel=True)
100
95
 
101
96
  @pre_release
@@ -2,6 +2,7 @@ import numpy as np
2
2
  import pandas as pd
3
3
  from pydantic import BaseModel, ConfigDict
4
4
 
5
+ from archeo.constants.bayesian import DEFAULT_BINSIZE_MASS, DEFAULT_BINSIZE_SPIN
5
6
  from archeo.data_structures.math import Domain
6
7
  from archeo.utils.logger import get_logger
7
8
 
@@ -17,8 +18,8 @@ class ImportanceSamplingDataBase(BaseModel, frozen=True):
17
18
  posterior_samples: pd.DataFrame
18
19
  prior_samples: pd.DataFrame
19
20
  new_prior_samples: pd.DataFrame
20
- binsize_spin: float = 0.05
21
- binsize_mass: float = 1.0
21
+ binsize_spin: float = DEFAULT_BINSIZE_SPIN
22
+ binsize_mass: float = DEFAULT_BINSIZE_MASS
22
23
  ztol: float = 1e-8
23
24
 
24
25
  @property
@@ -0,0 +1,3 @@
1
+ DEFAULT_BINSIZE_MASS: float = 2.0
2
+ DEFAULT_BINSIZE_SPIN: float = 0.1
3
+ ASSUME_PARAMETER_INDEPENDENCE: bool = False
@@ -0,0 +1,58 @@
1
+ import enum
2
+
3
+ import pandas as pd
4
+ from pydantic import BaseModel, NonNegativeFloat
5
+
6
+
7
+ SPEED_OF_LIGHT = 299792.458 # km/s
8
+
9
+
10
+ class _TypicalHostEscapeVelocityMeta(BaseModel):
11
+ v_esc: NonNegativeFloat # km s^-1
12
+ short: str
13
+ latex: str
14
+
15
+
16
+ class TypicalHostEscapeVelocity(enum.Enum):
17
+ """Escape velocity (units: km s^-1)."""
18
+
19
+ GLOBULAR_CLUSTER = _TypicalHostEscapeVelocityMeta(v_esc=50.0, short="GC", latex=r"$v_{esc, GC}$")
20
+ MILKY_WAY = _TypicalHostEscapeVelocityMeta(v_esc=600.0, short="MW", latex=r"$v_{esc, MW}$")
21
+ NUCLEAR_STAR_CLUSTER = _TypicalHostEscapeVelocityMeta(v_esc=1500.0, short="NSC", latex=r"$v_{esc, NSC}$")
22
+ ELLIPTICAL_GALAXY = _TypicalHostEscapeVelocityMeta(v_esc=2500.0, short="EG", latex=r"$v_{esc, EG}$")
23
+
24
+ @property
25
+ def v_esc(self) -> float:
26
+ return self.value.v_esc
27
+
28
+ @property
29
+ def short(self) -> str:
30
+ return self.value.short
31
+
32
+ @property
33
+ def latex(self) -> str:
34
+ return self.value.latex
35
+
36
+ def compute_p2g(
37
+ self,
38
+ df: pd.DataFrame,
39
+ max_mass: float = 65.0,
40
+ kf_col: str = "k_f",
41
+ m1_col: str = "m_1",
42
+ m2_col: str = "m_2",
43
+ ) -> float:
44
+ """Probability of being 2nd-generation under this escape velocity."""
45
+
46
+ if df.empty:
47
+ return 0.0
48
+
49
+ mask = (df[kf_col] <= self.v_esc) & (df[m1_col] <= max_mass) & (df[m2_col] <= max_mass)
50
+ return mask.mean() * 100.0
51
+
52
+ @classmethod
53
+ def latex_to_values(cls) -> dict[str, float]:
54
+ return {m.latex: m.v_esc for m in cls}
55
+
56
+ @classmethod
57
+ def short_to_values(cls) -> dict[str, float]:
58
+ return {m.short: m.v_esc for m in cls}
@@ -3,6 +3,8 @@ from typing import TypeAlias
3
3
  import numpy as np
4
4
  from pydantic import BaseModel, NonNegativeFloat
5
5
 
6
+ from archeo.constants.bayesian import ASSUME_PARAMETER_INDEPENDENCE, DEFAULT_BINSIZE_MASS, DEFAULT_BINSIZE_SPIN
7
+
6
8
 
7
9
  class BayesFactor(BaseModel, frozen=True):
8
10
  """Data class for Bayes factor with bootstrapping samples."""
@@ -33,5 +35,6 @@ class BayesFactorCurveMetadata(BaseModel, frozen=True):
33
35
 
34
36
  reference_candidate_name: str = "original"
35
37
  reference_bayes_factor: NonNegativeFloat = 1.0
36
- binsize_spin: float = 0.05
37
- binsize_mass: float = 1.0
38
+ binsize_spin: float = DEFAULT_BINSIZE_SPIN
39
+ binsize_mass: float = DEFAULT_BINSIZE_MASS
40
+ assume_parameter_independence: bool = ASSUME_PARAMETER_INDEPENDENCE
@@ -5,7 +5,7 @@ import matplotlib.pyplot as plt
5
5
  import numpy as np
6
6
  import pandas as pd
7
7
 
8
- from archeo.constants.physics import EscapeVelocity
8
+ from archeo.constants.physics import TypicalHostEscapeVelocity
9
9
  from archeo.data_structures.visualization import Labels, Padding
10
10
  from archeo.utils.fs import check_and_create_dir
11
11
  from archeo.utils.logger import get_logger
@@ -112,7 +112,7 @@ def add_escape_velocity(ax, v_max: float, y_max: float, log_xscale: bool = False
112
112
 
113
113
  colors = iter(mcolors.TABLEAU_COLORS.keys())
114
114
  # Plot vertical lines and labels (escape velocities)
115
- for label, v_esc in EscapeVelocity.to_vlines().items():
115
+ for label, v_esc in TypicalHostEscapeVelocity.latex_to_values().items():
116
116
  # Skip if out of scope
117
117
  if v_esc > v_max:
118
118
  return
@@ -8,7 +8,7 @@ import numpy as np
8
8
  import pandas as pd
9
9
  import seaborn as sns
10
10
 
11
- from archeo.constants.physics import EscapeVelocity
11
+ from archeo.constants.physics import TypicalHostEscapeVelocity
12
12
  from archeo.data_structures.visualization import Labels, Padding
13
13
  from archeo.utils.logger import get_logger
14
14
  from archeo.visualization import base
@@ -363,7 +363,7 @@ def table_estimates(
363
363
  data = {
364
364
  "": dfs.keys(),
365
365
  "Recovery Rate": [df["m_1"].notna().sum() / df.shape[0] for df in dfs.values()],
366
- **{f"p2g_{v_esc.short()}": [v_esc.compute_p2g(df) for df in dfs.values()] for v_esc in EscapeVelocity},
366
+ **{f"p2g_{v_esc.short}": [v_esc.compute_p2g(df) for df in dfs.values()] for v_esc in TypicalHostEscapeVelocity},
367
367
  }
368
368
 
369
369
  for col, name in col_to_names.items():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: archeo
3
- Version: 2.0.0.dev5
3
+ Version: 2.0.0.dev7
4
4
  Summary: Bayesian framework for inferring natal kick, ancestral masses and spins of black holes.
5
5
  Author-email: wyhwong <wyhwong@link.cuhk.edu.hk>
6
6
  License-Expression: MIT
@@ -20,6 +20,7 @@ archeo/bayesian/importance_sampling/resampler/base.py
20
20
  archeo/bayesian/importance_sampling/resampler/generic.py
21
21
  archeo/bayesian/importance_sampling/resampler/interface.py
22
22
  archeo/constants/__init__.py
23
+ archeo/constants/bayesian.py
23
24
  archeo/constants/enum.py
24
25
  archeo/constants/physics.py
25
26
  archeo/data_structures/__init__.py
@@ -16,7 +16,7 @@ classifiers = [
16
16
  "Operating System :: OS Independent"
17
17
  ]
18
18
  keywords = ["black-holes", "gravitational-waves", "black-hole-archeology"]
19
- version = "2.0.0.dev5"
19
+ version = "2.0.0.dev7"
20
20
  readme = "README.md"
21
21
  requires-python = ">=3.11,<3.14"
22
22
  dependencies = [
@@ -1,70 +0,0 @@
1
- import enum
2
-
3
- import pandas as pd
4
-
5
-
6
- SPEED_OF_LIGHT = 299792.458 # km/s
7
-
8
-
9
- class EscapeVelocity(enum.Enum):
10
- """Escape velocity (Unit in km s^-1)"""
11
-
12
- GLOBULAR_CLUSTER = 50.0
13
- MILKY_WAY = 600.0
14
- NUCLEAR_STAR_CLUSTER = 1500.0
15
- ELLIPTICAL_GALAXY = 2500.0
16
-
17
- def label(self) -> str:
18
- """Return the escape velocity label"""
19
-
20
- if self is EscapeVelocity.GLOBULAR_CLUSTER:
21
- return "$v_{esc, GC}$"
22
-
23
- if self is EscapeVelocity.MILKY_WAY:
24
- return "$v_{esc, MW}$"
25
-
26
- if self is EscapeVelocity.NUCLEAR_STAR_CLUSTER:
27
- return "$v_{esc, NSC}$"
28
-
29
- if self is EscapeVelocity.ELLIPTICAL_GALAXY:
30
- return "$v_{esc, EG}$"
31
-
32
- raise ValueError(f"Unknown escape velocity {self}")
33
-
34
- def short(self) -> str:
35
- """Return the short name of the escape velocity"""
36
-
37
- if self is EscapeVelocity.GLOBULAR_CLUSTER:
38
- return "GC"
39
-
40
- if self is EscapeVelocity.MILKY_WAY:
41
- return "MW"
42
-
43
- if self is EscapeVelocity.NUCLEAR_STAR_CLUSTER:
44
- return "NSC"
45
-
46
- if self is EscapeVelocity.ELLIPTICAL_GALAXY:
47
- return "EG"
48
-
49
- raise ValueError(f"Unknown escape velocity {self}")
50
-
51
- def compute_p2g(self, df: pd.DataFrame) -> float:
52
- """Return the probability of
53
- the black hole being a 2nd generation black hole
54
- under different escape velocity conditions."""
55
-
56
- if df.empty:
57
- return 0.0
58
-
59
- mask = (df["k_f"] <= self.value) & (df["m_1"] <= 65) & (df["m_2"] <= 65)
60
- return mask.sum() / len(df) * 100.0
61
-
62
- @classmethod
63
- def to_vlines(cls) -> dict[str, float]:
64
- """Return a dictionary for vlines plotting
65
-
66
- Returns:
67
- vlines (Dict[str, float]): The escape velocity vlines.
68
- """
69
-
70
- return {esc_vel.label(): esc_vel.value for esc_vel in cls}
File without changes
File without changes
File without changes
File without changes