nullpol 0.1.1__tar.gz → 0.1.2__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 (80) hide show
  1. {nullpol-0.1.1 → nullpol-0.1.2}/PKG-INFO +1 -1
  2. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/__init__.py +1 -1
  3. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/asimov/asimov.py +24 -7
  4. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/asimov/nullpol.ini +6 -3
  5. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/asimov/tgrflow.py +2 -0
  6. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/injection/injection.py +1 -1
  7. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/job_creation/nullpol_pipe_dag_creator.py +2 -1
  8. nullpol-0.1.2/src/nullpol/job_creation/pe_summary_node.py +47 -0
  9. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/source/simple_map.py +1 -1
  10. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/config.ini +4 -2
  11. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/data_generation.py +32 -13
  12. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/input.py +1 -1
  13. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/main.py +1 -1
  14. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/parser.py +11 -1
  15. {nullpol-0.1.1 → nullpol-0.1.2}/LICENSE +0 -0
  16. {nullpol-0.1.1 → nullpol-0.1.2}/README.rst +0 -0
  17. {nullpol-0.1.1 → nullpol-0.1.2}/pyproject.toml +0 -0
  18. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/.gitignore +0 -0
  19. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/asimov/__init__.py +0 -0
  20. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/asimov/analysis_defaults.yaml +0 -0
  21. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/asimov/nullpol_analysis.yaml +0 -0
  22. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/asimov/pesummary.py +0 -0
  23. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/asimov/utility.py +0 -0
  24. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/calibration/__init__.py +0 -0
  25. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/calibration/antenna_pattern.py +0 -0
  26. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/clustering/__init__.py +0 -0
  27. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/clustering/clustering.py +0 -0
  28. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/clustering/plot.ipynb +0 -0
  29. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/clustering/plot.py +0 -0
  30. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/clustering/single.py +0 -0
  31. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/clustering/sky_maximized_spectrogram.py +0 -0
  32. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/clustering/test.png +0 -0
  33. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/clustering/threshold_filter.py +0 -0
  34. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/detector/__init__.py +0 -0
  35. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/detector/networks.py +0 -0
  36. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/detector/whiten.py +0 -0
  37. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/injection/__init__.py +0 -0
  38. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/job_creation/__init__.py +0 -0
  39. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/job_creation/analysis_node.py +0 -0
  40. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/job_creation/generation_node.py +0 -0
  41. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/likelihood/__init__.py +0 -0
  42. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/likelihood/chi2_time_frequency_likelihood.py +0 -0
  43. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/likelihood/fractional_projection_time_frequency_likelihood.py +0 -0
  44. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/likelihood/gaussian_time_frequency_likelihood.py +0 -0
  45. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/likelihood/time_frequency_likelihood.py +0 -0
  46. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/null_stream/__init__.py +0 -0
  47. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/null_stream/antenna_pattern.py +0 -0
  48. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/null_stream/encoding.py +0 -0
  49. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/null_stream/null_stream.py +0 -0
  50. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/null_stream/projector.py +0 -0
  51. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/null_stream/signal_estimator.py +0 -0
  52. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/null_stream/time_shift.py +0 -0
  53. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/prior/__init__.py +0 -0
  54. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/prior/default.py +0 -0
  55. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/prior/prior_files/polarization.prior +0 -0
  56. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/result/__init__.py +0 -0
  57. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/result/result.py +0 -0
  58. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/source/__init__.py +0 -0
  59. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/time_frequency_transform/__init__.py +0 -0
  60. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/time_frequency_transform/helper.py +0 -0
  61. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/time_frequency_transform/inverse_wavelet_freq_funcs.py +0 -0
  62. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/time_frequency_transform/inverse_wavelet_time_funcs.py +0 -0
  63. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/time_frequency_transform/stft.py +0 -0
  64. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/time_frequency_transform/transform_freq_funcs.py +0 -0
  65. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/time_frequency_transform/transform_time_funcs.py +0 -0
  66. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/time_frequency_transform/wavelet_transforms.py +0 -0
  67. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/__init__.py +0 -0
  68. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/create_injection.py +0 -0
  69. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/create_time_frequency_filter_from_sample.py +0 -0
  70. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/data_analysis.py +0 -0
  71. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/default_config_create_injection.ini +0 -0
  72. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/default_config_create_time_frequency_filter_from_sample.ini +0 -0
  73. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/example_signal_parameters_create_injection.json +0 -0
  74. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/tools/get_asimov_yaml.py +0 -0
  75. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/utils/__init__.py +0 -0
  76. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/utils/config.py +0 -0
  77. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/utils/convert_type.py +0 -0
  78. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/utils/error.py +0 -0
  79. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/utils/filesystem.py +0 -0
  80. {nullpol-0.1.1 → nullpol-0.1.2}/src/nullpol/utils/log.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nullpol
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: A package to perform model-independent polarization test of gravitational-wave signals.
5
5
  Author: Thomas Ng, Balázs Cirok
6
6
  Author-email: "Isaac C.F. Wong" <chunfung.wong@kuleuven.be>
@@ -5,7 +5,7 @@ from . import (asimov, calibration, clustering, detector, injection,
5
5
  time_frequency_transform, utils)
6
6
  from .utils import logger
7
7
 
8
- __version__ = '0.1.1'
8
+ __version__ = '0.1.2'
9
9
 
10
10
 
11
11
  def get_version_information() -> str:
@@ -12,9 +12,6 @@ from asimov import config
12
12
  from asimov.pipeline import Pipeline, PipelineException, PipelineLogger
13
13
  from asimov.pipelines.bilby import Bilby
14
14
 
15
- from .pesummary import PESummaryPipeline
16
-
17
-
18
15
  class Nullpol(Bilby):
19
16
  """
20
17
  The nullpol pipeline.
@@ -86,13 +83,33 @@ class Nullpol(Bilby):
86
83
  ) + glob.glob(os.path.join(rundir, "result", f"*_{subrun_label}_merge*_result.json"))
87
84
 
88
85
  def after_completion(self):
89
- post_pipeline = PESummaryPipeline(production=self.production)
90
- self.logger.info("Job has completed. Running PE Summary.")
91
- cluster = post_pipeline.submit_dag()
92
- self.production.meta["job id"] = int(cluster)
86
+ """Wait for the PEsummary node that is part of the analysis DAG."""
87
+ if self.detect_completion_processing():
88
+ self.after_processing()
89
+ return
90
+
91
+ self.logger.info("Analysis DAG completed; waiting for its PE summary.")
93
92
  self.production.status = "processing"
94
93
  self.production.event.update_data()
95
94
 
95
+ def detect_completion_processing(self):
96
+ """Check for the combined PEsummary result produced by the DAG."""
97
+ result = os.path.join(
98
+ config.get("general", "webroot"),
99
+ self.production.event.name,
100
+ self.production.name,
101
+ "pesummary",
102
+ "samples",
103
+ "posterior_samples.h5",
104
+ )
105
+ return os.path.isfile(result)
106
+
107
+ def after_processing(self):
108
+ """Publish the completed DAG-contained PEsummary result."""
109
+ self.logger.info("DAG-contained PE summary is available.")
110
+ self.production.status = "uploaded"
111
+ self.production.event.update_data()
112
+
96
113
  @property
97
114
  def config_file_path(self):
98
115
  """Path of the configuration file.
@@ -115,6 +115,7 @@ request-memory-generation={{ scheduler['request generation memory'] | default: N
115
115
  request-cpus={{ scheduler['request cpus'] | default: 1 }}
116
116
  request-disk={{ scheduler['request disk'] | default: 1 }}
117
117
  scheduler={{ scheduler['type'] | default: 'condor' }}
118
+ requirements={{ scheduler['requirements'] | default: None }}
118
119
  scheduler-args=None
119
120
  scheduler-module=None
120
121
  scheduler-env=None
@@ -125,6 +126,7 @@ online-pe=False
125
126
  osg={{ scheduler['osg'] | default: False }}
126
127
  desired-sites={{ scheduler['desired sites'] | default: None }}
127
128
  analysis-executable={{ config['pipelines']['environment'] }}/bin/nullpol_pipe_analysis
129
+ conda-env={{ config['pipelines']['environment'] }}
128
130
  environment-variables={{ scheduler['environment variables'] | default: "{'HDF5_USE_FILE_LOCKING': False, 'OMP_NUM_THREADS'=1, 'OMP_PROC_BIND'=False}" }}
129
131
 
130
132
  ################################################################################
@@ -155,13 +157,13 @@ plot-marginal=False
155
157
  plot-skymap=True
156
158
  plot-waveform=False
157
159
  plot-format=png
158
- create-summary=False
160
+ create-summary=True
159
161
  email=None
160
162
  notification=Error
161
163
  queue=None
162
164
  existing-dir=None
163
- webdir={{ config['general']['webroot'] }}/{{ production.event.name }}/{{ production.name }}
164
- summarypages-arguments=None
165
+ webdir={{ config['general']['webroot'] }}/{{ production.event.name }}/{{ production.name }}/pesummary
166
+ summarypages-arguments={gw: True}
165
167
  result-format=hdf5
166
168
  final-result=True
167
169
  final-result-nsamples=20000
@@ -239,6 +241,7 @@ sampler-kwargs={{ sampler['sampler kwargs'] | default: "{'nlive': 1000, 'naccep
239
241
  time-frequency-clustering-method={{ likelihood['time frequency clustering method'] | default: 'maxL' }}
240
242
  time-frequency-clustering-injection-parameters-filename={{ likelihood['time frequency clustering injection parameters filename'] | default: None}}
241
243
  time-frequency-clustering-pe-samples-filename={{ likelihood['time frequency clustering pe samples filename'] | default: gr_pe_info['result file path']}}
244
+ time-frequency-filter-file={{ likelihood['time frequency filter file'] | default: None}}
242
245
  time-frequency-clustering-threshold={{ likelihood['time frequency clustering threshold'] | default: 1.0 }}
243
246
  time-frequency-clustering-threshold-type={{ likelihood['time frequency clustering threshold type'] | default: 'variance' }}
244
247
  time-frequency-clustering-time-padding={{ likelihood['time frequency clustering time padding'] | default: 0.1 }}
@@ -560,6 +560,8 @@ class Applicator:
560
560
  output['psds'] = {}
561
561
  for key, value in gr_pe['psds'].items():
562
562
  filename = os.path.join(copied_data_folder, f'{key}_psd.dat')
563
+ if os.path.exists(filename):
564
+ os.chmod(filename, 0o644)
563
565
  shutil.copy(value, filename)
564
566
  output['psds'][key] = filename
565
567
  event = Event.from_dict(output)
@@ -4,7 +4,7 @@ from bilby.gw.conversion import convert_to_lal_binary_black_hole_parameters
4
4
  from bilby.gw.source import lal_binary_black_hole
5
5
  from bilby.gw.waveform_generator import WaveformGenerator
6
6
 
7
- DEFAULT_BBH_WAVEFORM_ARGUMENTS = {"waveform_approximant": "IMRPhenomPv2",
7
+ DEFAULT_BBH_WAVEFORM_ARGUMENTS = {"waveform_approximant": "IMRPhenomXPHM",
8
8
  "reference_frequency": 50}
9
9
 
10
10
 
@@ -7,13 +7,14 @@ from bilby_pipe.job_creation.bilby_pipe_dag_creator import (
7
7
  get_parallel_list, get_trigger_time_list)
8
8
  from bilby_pipe.job_creation.dag import Dag
9
9
  from bilby_pipe.job_creation.nodes import (FinalResultNode, MergeNode,
10
- PESummaryNode, PlotNode,
10
+ PlotNode,
11
11
  PostProcessAllResultsNode,
12
12
  PostProcessSingleResultsNode)
13
13
  from bilby_pipe.job_creation.overview import create_overview
14
14
  from bilby_pipe.utils import get_colored_string
15
15
 
16
16
  from ..utils import NullpolError, logger
17
+ from .pe_summary_node import NullpolPESummaryNode as PESummaryNode
17
18
  from .analysis_node import AnalysisNode
18
19
  from .generation_node import GenerationNode
19
20
 
@@ -0,0 +1,47 @@
1
+ import copy
2
+ import re
3
+
4
+ from bilby_pipe.job_creation.nodes import PESummaryNode
5
+
6
+
7
+ class NullpolPESummaryNode(PESummaryNode):
8
+ """PESummaryNode that:
9
+
10
+ - Passes --psd and --calibration from the bilby_pipe config to the
11
+ summarypages command (bilby_pipe's PESummaryNode has access to these
12
+ for HTCondor file-transfer but does not add them as command arguments,
13
+ so PESummary cannot generate PSD or calibration plots without this).
14
+
15
+ - Shortens the auto-generated labels from bilby_pipe's full run ID
16
+ (e.g. nullpol_data0_..._analysis_H1L1V1_pc_p_merge) to just the
17
+ polarization mode and basis (e.g. pc_p).
18
+ """
19
+
20
+ def __init__(self, inputs, merged_node_list, generation_node_list, dag):
21
+ self._n_results = len(merged_node_list)
22
+
23
+ short_labels = [
24
+ re.sub(r'^.*_analysis_[A-Z0-9]+_(.+)_merge$', r'\1', node.label)
25
+ for node in merged_node_list
26
+ ]
27
+
28
+ # Shallow-copy inputs so we don't mutate the shared object, then
29
+ # replace summarypages_arguments with a new dict that includes labels.
30
+ inputs = copy.copy(inputs)
31
+ base_args = inputs.summarypages_arguments or {}
32
+ inputs.summarypages_arguments = {**base_args, "labels": short_labels}
33
+
34
+ super().__init__(inputs, merged_node_list, generation_node_list, dag)
35
+
36
+ def process_node(self):
37
+ psd_dict = self.inputs.psd_dict
38
+ if psd_dict:
39
+ psd_str = " ".join(f"{ifo}:{path}" for ifo, path in psd_dict.items())
40
+ self.arguments.add("psd", (" " + psd_str) * self._n_results)
41
+
42
+ cal_dict = self.inputs.spline_calibration_envelope_dict
43
+ if cal_dict:
44
+ cal_str = " ".join(f"{ifo}:{path}" for ifo, path in cal_dict.items())
45
+ self.arguments.add("calibration", (" " + cal_str) * self._n_results)
46
+
47
+ super().process_node()
@@ -11,7 +11,7 @@ def lal_binary_black_hole_non_gr_simple_map(
11
11
  **kwargs,
12
12
  ):
13
13
  waveform_kwargs = dict(
14
- waveform_approximant='IMRPhenomPv2', reference_frequency=50.0,
14
+ waveform_approximant='IMRPhenomXPHM', reference_frequency=50.0,
15
15
  minimum_frequency=20.0, maximum_frequency=frequency_array[-1],
16
16
  catch_waveform_errors=False, pn_spin_order=-1, pn_tidal_order=-1,
17
17
  pn_phase_order=-1, pn_amplitude_order=0)
@@ -312,7 +312,7 @@ waveform-generator=bilby.gw.waveform_generator.LALCBCWaveformGenerator
312
312
  # The reference frequency
313
313
  reference-frequency=20
314
314
  # The name of the waveform approximant to use for PE.
315
- waveform-approximant=IMRPhenomPv2
315
+ waveform-approximant=IMRPhenomXPHM
316
316
  # Turns on waveform error catching
317
317
  catch-waveform-errors=True
318
318
  # Post-newtonian order to use for the spin
@@ -345,8 +345,10 @@ generation-function=None
345
345
  time-frequency-clustering-method=None
346
346
  # If `injection_parameters_file` is chosen in --time-frequency-clustering-method, provide the path to the injection parameters file.
347
347
  time-frequency-clustering-injection-parameters-filename=None
348
- # If `maxL`, `maxP` or `random` is chosen in --time-frequency-clustering-method, provide the path to the bilby result file.
348
+ # If `maxL`, `maP` or `random` is chosen in --time-frequency-clustering-method, provide the path to the bilby result file.
349
349
  time-frequency-clustering-pe-samples-filename=None
350
+ # Path to a previously saved NumPy time-frequency filter. When supplied, it takes precedence over time-frequency-clustering-method.
351
+ time-frequency-filter-file=None
350
352
  # Quantile threshold to filter the excess power.
351
353
  time-frequency-clustering-threshold=0.95
352
354
  # Type of threshold.
@@ -4,9 +4,7 @@ import sys
4
4
 
5
5
  import bilby
6
6
  import bilby_pipe.utils
7
- import h5py
8
7
  import numpy as np
9
- import pandas as pd
10
8
  from bilby_pipe.data_generation import \
11
9
  DataGenerationInput as BilbyDataGenerationInput
12
10
  from bilby_pipe.main import parse_args
@@ -130,6 +128,7 @@ class DataGenerationInput(BilbyDataGenerationInput, Input):
130
128
  self.time_frequency_clustering_method = args.time_frequency_clustering_method
131
129
  self.time_frequency_clustering_injection_parameters_filename = args.time_frequency_clustering_injection_parameters_filename
132
130
  self.time_frequency_clustering_pe_samples_filename = args.time_frequency_clustering_pe_samples_filename
131
+ self.time_frequency_filter_file = args.time_frequency_filter_file
133
132
  self.time_frequency_clustering_threshold = args.time_frequency_clustering_threshold
134
133
  self.time_frequency_clustering_threshold_type = args.time_frequency_clustering_threshold_type
135
134
  self.time_frequency_clustering_time_padding = args.time_frequency_clustering_time_padding
@@ -224,8 +223,12 @@ class DataGenerationInput(BilbyDataGenerationInput, Input):
224
223
 
225
224
  def run_time_frequency_clustering(self):
226
225
  logger.info(f"Running time-frequency clustering with method: {self.time_frequency_clustering_method}")
226
+ if self.time_frequency_filter_file is not None:
227
+ time_frequency_filter = np.load(self.time_frequency_filter_file, allow_pickle=False)
228
+ sky_maximized_spectrogram = None
229
+ logger.info(f"Loaded time-frequency filter from {self.time_frequency_filter_file}.")
227
230
  # Build the strain data for time-frequency clustering
228
- if self.time_frequency_clustering_method in [
231
+ elif self.time_frequency_clustering_method in [
229
232
  "data",
230
233
  "injection",
231
234
  "injection_parameters_file",
@@ -239,6 +242,12 @@ class DataGenerationInput(BilbyDataGenerationInput, Input):
239
242
  "maxL",
240
243
  "maP",
241
244
  "random"]:
245
+ if self.time_frequency_clustering_method in [
246
+ "injection", "injection_parameters_file"]:
247
+ waveform_generator_class = self.waveform_generator_class
248
+ frequency_domain_source_model = self.bilby_frequency_domain_source_model
249
+ parameter_conversion = self.parameter_conversion
250
+ waveform_arguments = self.get_injection_waveform_arguments()
242
251
  if self.time_frequency_clustering_method == "injection":
243
252
  parameters = self.meta_data["injection_parameters"]
244
253
  elif self.time_frequency_clustering_method == "injection_parameters_file":
@@ -255,17 +264,25 @@ class DataGenerationInput(BilbyDataGenerationInput, Input):
255
264
  if self.time_frequency_clustering_pe_samples_filename is None:
256
265
  raise NullpolError(f"time-frequency-clustering-method = {self.time_frequency_clustering_method}, but time-frequency-clustering-pe-samples-filename is not provided.")
257
266
  try:
258
- posterior = bilby.core.result.read_in_result(self.time_frequency_clustering_pe_samples_filename).posterior
259
- except:
260
- logger.warning(f"Trying to read the posterior as a .h5 file.")
261
- with h5py.File(self.time_frequency_clustering_pe_samples_filename, "r") as f:
262
- posterior = pd.DataFrame(f[list(f.keys())[0]]['posterior_samples'][()]) # Use the first waveform result
267
+ pe_result = bilby.core.result.read_in_result(
268
+ self.time_frequency_clustering_pe_samples_filename)
269
+ posterior = pe_result.posterior
270
+ pe_waveform = pe_result.meta_data["likelihood"]
271
+ waveform_generator_class = pe_waveform["waveform_generator_class"]
272
+ frequency_domain_source_model = pe_waveform["frequency_domain_source_model"]
273
+ parameter_conversion = pe_waveform["parameter_conversion"]
274
+ waveform_arguments = pe_waveform["waveform_arguments"]
275
+ except Exception as exception:
276
+ raise NullpolError(
277
+ "Unable to recover the waveform metadata from the Bilby PE result. "
278
+ "PE-driven time-frequency clustering requires a Bilby result with "
279
+ "likelihood waveform metadata.") from exception
263
280
  if self.time_frequency_clustering_method == "maxL":
264
281
  parameters = posterior.loc[posterior["log_likelihood"].idxmax()].to_dict()
265
282
  elif self.time_frequency_clustering_method == "maP":
266
283
  parameters = posterior.loc[(posterior["log_likelihood"]+posterior["log_prior"]).idxmax()].to_dict()
267
284
  elif self.time_frequency_clustering_method == "random":
268
- parameters = posterior.sample().to_dict()
285
+ parameters = posterior.sample(n=1).iloc[0].to_dict()
269
286
  else:
270
287
  raise NullpolError(f"Unexpected error with time-frequency-clustering-method = {self.time_frequency_clustering_method}. Contact the developers.")
271
288
  # Remove log_likelihood and log_prior from parameters
@@ -302,14 +319,13 @@ class DataGenerationInput(BilbyDataGenerationInput, Input):
302
319
  duration=self.duration,
303
320
  start_time=self.start_time
304
321
  )
305
- waveform_arguments = self.get_injection_waveform_arguments()
306
322
  logger.info(f"Using waveform arguments: {waveform_arguments}")
307
- waveform_generator = self.waveform_generator_class(
323
+ waveform_generator = waveform_generator_class(
308
324
  duration=self.duration,
309
325
  start_time=self.start_time,
310
326
  sampling_frequency=self.sampling_frequency,
311
- frequency_domain_source_model=self.bilby_frequency_domain_source_model,
312
- parameter_conversion=self.parameter_conversion,
327
+ frequency_domain_source_model=frequency_domain_source_model,
328
+ parameter_conversion=parameter_conversion,
313
329
  waveform_arguments=waveform_arguments,
314
330
  )
315
331
  ifos.inject_signal(
@@ -334,6 +350,9 @@ class DataGenerationInput(BilbyDataGenerationInput, Input):
334
350
  skypoints=self.time_frequency_clustering_skypoints,
335
351
  return_sky_maximized_spectrogram=True,
336
352
  threshold_type=self.time_frequency_clustering_threshold_type)
353
+ time_frequency_filter_filename = f"{self.data_directory}/{self.label}_time_frequency_filter.npy"
354
+ np.save(time_frequency_filter_filename, time_frequency_filter, allow_pickle=False)
355
+ logger.info(f"Saved time-frequency filter to {time_frequency_filter_filename}.")
337
356
  # Generate the cumulative distribution of the spectrogram.
338
357
  reversed_cumulative_distribution_fig_fname = f"{self.data_directory}/{self.label}_reversed_cumulative_distribution_of_whitened_energy_pixels.png"
339
358
  plot_reverse_cumulative_distribution(spectrogram=sky_maximized_spectrogram,
@@ -192,7 +192,7 @@ class Input(BilbyInput):
192
192
 
193
193
  Defaults the injection-waveform-approximant to waveform-approximant, if
194
194
  no injection-waveform-approximant provided. Note that the default
195
- waveform-approximant is `IMRPhenomPv2`.
195
+ waveform-approximant is `IMRPhenomXPHM`.
196
196
  """
197
197
  if self.injection_waveform_approximant is None:
198
198
  self.injection_waveform_approximant = self.waveform_approximant
@@ -163,7 +163,7 @@ class MainInput(BilbyMainInput, Input):
163
163
  self.check_injection()
164
164
 
165
165
  self.extra_lines = []
166
- self.requirements = []
166
+ self.requirements = args.requirements
167
167
 
168
168
  @property
169
169
  def analysis_executable(self):
@@ -131,6 +131,12 @@ def create_nullpol_parser(top_level=True):
131
131
  remove_argument(parser, "--epsilon")
132
132
  remove_argument(parser, "--default-prior")
133
133
  remove_argument(parser, "--version")
134
+ add_argument_to_group(parser,
135
+ "Job submission arguments",
136
+ "--requirements",
137
+ type=nonestr,
138
+ default=None,
139
+ help="Additional HTCondor requirements expression.")
134
140
  add_argument_to_group(parser,
135
141
  "Likelihood arguments",
136
142
  "--likelihood-type",
@@ -196,8 +202,12 @@ def create_nullpol_parser(top_level=True):
196
202
  "provide the path to the injection parameters file."))
197
203
  clustering_parser.add("--time-frequency-clustering-pe-samples-filename",
198
204
  type=nonestr,
199
- help=("If `maxL`, `maxP` or `random` is chosen in --time-frequency-clustering-method, "
205
+ help=("If `maxL`, `maP` or `random` is chosen in --time-frequency-clustering-method, "
200
206
  "provide the path to the bilby result file."))
207
+ clustering_parser.add("--time-frequency-filter-file",
208
+ type=nonestr,
209
+ help=("Path to a previously saved NumPy time-frequency filter. When supplied, it "
210
+ "takes precedence over time-frequency-clustering-method."))
201
211
  clustering_parser.add('--time-frequency-clustering-threshold',
202
212
  type=float,
203
213
  default=1.0,
File without changes
File without changes
File without changes
File without changes