pspipe 0.12__tar.gz → 0.14__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 (32) hide show
  1. {pspipe-0.12 → pspipe-0.14}/PKG-INFO +2 -2
  2. {pspipe-0.12 → pspipe-0.14}/pspipe/settings.py +19 -2
  3. {pspipe-0.12 → pspipe-0.14}/pspipe/tasks.py +91 -20
  4. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/default_settings.toml +7 -0
  5. {pspipe-0.12 → pspipe-0.14}/pyproject.toml +2 -2
  6. {pspipe-0.12 → pspipe-0.14}/LICENSE +0 -0
  7. {pspipe-0.12 → pspipe-0.14}/README.md +0 -0
  8. {pspipe-0.12 → pspipe-0.14}/pspipe/__init__.py +0 -0
  9. {pspipe-0.12 → pspipe-0.14}/pspipe/database.py +0 -0
  10. {pspipe-0.12 → pspipe-0.14}/pspipe/obsdata.py +0 -0
  11. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/eor_bins_a12.parset +0 -0
  12. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/eor_bins_alo.parset +0 -0
  13. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/eor_bins_hba.parset +0 -0
  14. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/eor_bins_nenufar.parset +0 -0
  15. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/flagger.parset +0 -0
  16. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/flagger_pre_combine.parset +0 -0
  17. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/gpr_config_a12.parset +0 -0
  18. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/gpr_config_hba.parset +0 -0
  19. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/gpr_config_nenufar.parset +0 -0
  20. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/gpr_config_v.parset +0 -0
  21. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/ps_config_a12.parset +0 -0
  22. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/ps_config_alo.parset +0 -0
  23. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/ps_config_hba.parset +0 -0
  24. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/config/ps_config_nenufar.parset +0 -0
  25. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/default_a12.toml +0 -0
  26. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/default_alo.toml +0 -0
  27. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/default_hba.toml +0 -0
  28. {pspipe-0.12 → pspipe-0.14}/pspipe/templates/default_nenufar.toml +0 -0
  29. {pspipe-0.12 → pspipe-0.14}/pspipe/tools/__init__.py +0 -0
  30. {pspipe-0.12 → pspipe-0.14}/pspipe/tools/psdb.py +0 -0
  31. {pspipe-0.12 → pspipe-0.14}/pspipe/tools/pspipe.py +0 -0
  32. {pspipe-0.12 → pspipe-0.14}/pspipe/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pspipe
3
- Version: 0.12
3
+ Version: 0.14
4
4
  Summary: Power spectra pipeline for Cosmic Dawn, Epoch of Reionization radio interferometric experiments
5
5
  License-Expression: GPL-3.0-or-later
6
6
  License-File: LICENSE
@@ -18,7 +18,7 @@ Provides-Extra: docs
18
18
  Provides-Extra: ml-gpr
19
19
  Requires-Dist: astropy (>6.0)
20
20
  Requires-Dist: click (>=8.0)
21
- Requires-Dist: libpipe (>=0.8)
21
+ Requires-Dist: libpipe (>=0.9)
22
22
  Requires-Dist: myst-parser (>=2) ; extra == "docs"
23
23
  Requires-Dist: ps-eor (>=1.0)
24
24
  Requires-Dist: ps-eor[ml-gpr] (>=1.0) ; extra == "ml-gpr"
@@ -5,13 +5,20 @@
5
5
  import os
6
6
 
7
7
  import astropy.units as u
8
- from libpipe import futils
8
+ from libpipe import futils, worker
9
9
  from libpipe.settings import BaseSettings
10
10
 
11
11
  # Lazy loaded:
12
12
  # - ps_eor.datacube in Settings.validate_vis_cube()
13
13
  from . import utils
14
14
 
15
+
16
+ def worker_resources(s_worker):
17
+ '''worker.resources as {category: {'cpus': .., 'mem': ..}}, or None.'''
18
+ resources = s_worker.get('resources') or {}
19
+ return {k: dict(v) for k, v in resources.items()} or None
20
+
21
+
15
22
  TEMPLATE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates')
16
23
 
17
24
  TEMPLATE_NAMES = ['a12', 'nenufar', 'hba', 'alo']
@@ -51,9 +58,19 @@ class Settings(BaseSettings):
51
58
  def validate_worker(self, val_fct):
52
59
  val_fct(isinstance(self.worker.max_concurrent, int), 'max_concurrent')
53
60
  val_fct(not self.worker.env_file or futils.is_file(self.worker.env_file), 'env_file')
54
- val_fct(self.worker.get('max_time') is None
61
+ val_fct(not self.worker.get('max_time')
55
62
  or (isinstance(self.worker.max_time, (int, float)) and self.worker.max_time > 0),
56
63
  'max_time')
64
+ slurm_nodes = self.worker.get('slurm_nodes') or 0
65
+ val_fct(isinstance(slurm_nodes, int) and slurm_nodes >= 0, 'slurm_nodes')
66
+ try:
67
+ resources = worker.resolve_resources(worker_resources(self.worker))
68
+ except (ValueError, TypeError):
69
+ resources = None
70
+ val_fct(resources is not None, 'resources')
71
+ categories = self.worker.get('categories') or {}
72
+ val_fct(resources is None or all(c in resources for c in categories.values()),
73
+ 'categories')
57
74
 
58
75
  def validate_merge_ms(self, val_fct):
59
76
  val_fct(isinstance(self.merge_ms.apply_aoflagger, bool), 'apply_aoflagger')
@@ -14,7 +14,7 @@ import astropy.io.fits as pf
14
14
  import numpy as np
15
15
  from libpipe import futils, worker
16
16
 
17
- from . import database, utils
17
+ from . import database, settings, utils
18
18
 
19
19
  CWD = os.getcwd()
20
20
 
@@ -48,6 +48,11 @@ def get_target_host(in_file, worker_settings):
48
48
 
49
49
  class AbstractSubTask:
50
50
 
51
+ # Task type (worker.categories key, usage summary) and resource category as a job step of an
52
+ # allocation (worker.slurm_nodes): small, medium, high_mem, cpu or heavy
53
+ label = None
54
+ category = 'heavy'
55
+
51
56
  def __init__(self, settings_obj, exec_name):
52
57
  self.settings = settings_obj
53
58
  self.exec_name = exec_name
@@ -74,23 +79,24 @@ class AbstractTask:
74
79
  self.name = name
75
80
  self.settings = settings_obj.copy()
76
81
  self.settings.worker.update(worker_kargs)
77
- s_worker = self.settings.worker
78
82
 
79
83
  if not self.settings.validate('worker'):
80
84
  raise ValueError('Invalid worker settings.')
81
85
 
82
- self.worker = worker.get_worker_pool(
86
+ self.worker = self._worker_pool(name)
87
+
88
+ def _worker_pool(self, name):
89
+ s_worker = self.settings.worker
90
+ # 0 and '' (the defaults) leave max_time unset and slurm_options from the environment
91
+ return worker.get_worker_pool(
83
92
  name, nodes=s_worker.nodes, max_concurrent=s_worker.max_concurrent,
84
- env_file=s_worker.env_file, max_time=s_worker.get('max_time'),
85
- slurm_options=s_worker.get('slurm_options'))
93
+ env_file=s_worker.env_file, max_time=s_worker.get('max_time') or None,
94
+ slurm_options=s_worker.get('slurm_options') or None,
95
+ slurm_nodes=s_worker.get('slurm_nodes') or None,
96
+ resources=settings.worker_resources(s_worker))
86
97
 
87
98
  def init_for_new_task(self, post_task_name):
88
- s_worker = self.settings.worker
89
- self.worker = worker.get_worker_pool(post_task_name, nodes=s_worker.nodes,
90
- max_concurrent=s_worker.max_concurrent,
91
- env_file=s_worker.env_file,
92
- max_time=s_worker.get('max_time'),
93
- slurm_options=s_worker.get('slurm_options'))
99
+ self.worker = self._worker_pool(post_task_name)
94
100
 
95
101
  def add_sub_task(self, sub_task, run_on_host=None):
96
102
  log_file = sub_task.get_log_file()
@@ -103,8 +109,10 @@ class AbstractTask:
103
109
  cmd = sub_task.build_command()
104
110
  if self.settings.debug:
105
111
  print(cmd)
112
+ label = sub_task.label or sub_task.exec_name
113
+ category = (self.settings.worker.get('categories') or {}).get(label, sub_task.category)
106
114
  self.worker.add(cmd, output_file=log_file, done_callback=sub_task.done_callback,
107
- run_on_host=run_on_host)
115
+ run_on_host=run_on_host, category=category, label=label)
108
116
 
109
117
  def run(self, obs_ids):
110
118
  raise NotImplementedError()
@@ -128,6 +136,9 @@ class AbstractTask:
128
136
 
129
137
  class ImagingSubTask(AbstractSubTask):
130
138
 
139
+ label = 'image'
140
+ category = 'heavy'
141
+
131
142
  def __init__(self, settings_obj, obs_id, inp_ms_files, even=False, odd=False, index=0,
132
143
  even_odd=False):
133
144
  AbstractSubTask.__init__(self, settings_obj, settings_obj.image.imager)
@@ -180,10 +191,8 @@ class ImagingSubTask(AbstractSubTask):
180
191
  odd=self.odd if odd is None else odd, img_name=img_name)
181
192
  meta.save()
182
193
 
183
- def done_callback(self):
184
- for file in glob.glob(f'{self.get_fits_prefix()}*-MFS-*.fits'):
185
- os.remove(file)
186
-
194
+ def fits_keywords(self):
195
+ '''Integration time, total time and channel width of the images, for their headers.'''
187
196
  img = self.settings.image
188
197
 
189
198
  if img.time_start_index != img.time_end_index:
@@ -193,6 +202,15 @@ class ImagingSubTask(AbstractSubTask):
193
202
  else:
194
203
  total_time = self.obs_meta.total_time
195
204
 
205
+ return {'PEINTTIM': int(self.obs_meta.int_time), 'PETOTTIM': int(total_time),
206
+ 'PECHWIDT': int(self.obs_meta.chan_width)}
207
+
208
+ def done_callback(self):
209
+ for file in glob.glob(f'{self.get_fits_prefix()}*-MFS-*.fits'):
210
+ os.remove(file)
211
+
212
+ img = self.settings.image
213
+
196
214
  if self.even_odd:
197
215
  parts = [('-even', True, False), ('-odd', False, True)]
198
216
  else:
@@ -209,10 +227,12 @@ class ImagingSubTask(AbstractSubTask):
209
227
  files = glob.glob(f'{prefix}*.fits')
210
228
  img_name = 'image'
211
229
 
212
- for file in files:
213
- pf.setval(file, 'PEINTTIM', value=int(self.obs_meta.int_time))
214
- pf.setval(file, 'PETOTTIM', value=int(total_time))
215
- pf.setval(file, 'PECHWIDT', value=int(self.obs_meta.chan_width))
230
+ # psimager writes the keywords with the files (-fits-keyword)
231
+ if img.imager != 'psimager':
232
+ keywords = self.fits_keywords()
233
+ for file in files:
234
+ with pf.open(file, mode='update') as hdul:
235
+ hdul[0].header.update(keywords)
216
236
 
217
237
  if not img.lst_bins:
218
238
  self.register_files(files, img_name=img_name, even=even, odd=odd)
@@ -267,6 +287,9 @@ class ImagingSubTask(AbstractSubTask):
267
287
 
268
288
  args.append(f'-temp-dir {self.temp_dir}')
269
289
 
290
+ if img.imager == 'psimager':
291
+ args.append(' '.join(f'-fits-keyword {k}={v}' for k, v in self.fits_keywords().items()))
292
+
270
293
  if self.even_odd:
271
294
  args.append('-even-odd')
272
295
  elif self.even:
@@ -368,6 +391,9 @@ class ImagingTask(AbstractTask):
368
391
 
369
392
  class GenVisCubeSubTask(AbstractSubTask):
370
393
 
394
+ label = 'gen_vis_cube'
395
+ category = 'small'
396
+
371
397
  def __init__(self, settings_obj, obs_id, stokes, even=False, odd=False, lst_idx=None):
372
398
  AbstractSubTask.__init__(self, settings_obj, 'pstool gen_vis_cube')
373
399
  self.obs_id = obs_id
@@ -423,6 +449,9 @@ class GenVisCubeSubTask(AbstractSubTask):
423
449
 
424
450
  class EvenOddToSumDiffSubTask(AbstractSubTask):
425
451
 
452
+ label = 'even_odd_to_sum_diff'
453
+ category = 'small'
454
+
426
455
  def __init__(self, settings_obj, obs_id, stokes, lst_idx=None):
427
456
  AbstractSubTask.__init__(self, settings_obj, 'pstool even_odd_to_sum_diff')
428
457
  self.obs_id = obs_id
@@ -523,6 +552,9 @@ class GenVisCubeTask(AbstractTask):
523
552
 
524
553
 
525
554
  class ConcatMSSubTask(AbstractSubTask):
555
+
556
+ label = 'concat_ms'
557
+ category = 'medium'
526
558
  """
527
559
  Subtask that calls the CLI 'mstool concat <MS...> <OUT.MS>'
528
560
  to concatenate MS files in time.
@@ -604,6 +636,9 @@ class ConcatMSTask(AbstractTask):
604
636
 
605
637
  class MergeMSSubTask(AbstractSubTask):
606
638
 
639
+ label = 'merge_ms'
640
+ category = 'heavy'
641
+
607
642
  def __init__(self, settings_obj, ms_files, obs_id_out):
608
643
  AbstractSubTask.__init__(self, settings_obj, 'DP3')
609
644
  self.db = database.Database(self.settings)
@@ -718,6 +753,9 @@ class MergeMSTask(AbstractTask):
718
753
 
719
754
  class AOFlaggerSubTask(AbstractSubTask):
720
755
 
756
+ label = 'ao_flag'
757
+ category = 'medium'
758
+
721
759
  def __init__(self, settings_obj, ms_file):
722
760
  AbstractSubTask.__init__(self, settings_obj, 'DP3')
723
761
  self.ms_file = ms_file
@@ -771,6 +809,9 @@ class AOFlaggerTask(AbstractTask):
771
809
 
772
810
  class DP3SubTask(AbstractSubTask):
773
811
 
812
+ label = 'dp3'
813
+ category = 'heavy'
814
+
774
815
  def __init__(self, settings_obj, ms_file):
775
816
  AbstractSubTask.__init__(self, settings_obj, 'DP3')
776
817
  self.ms_file = ms_file
@@ -818,6 +859,9 @@ class DP3Task(AbstractTask):
818
859
 
819
860
  class MakePSSubTask(AbstractSubTask):
820
861
 
862
+ label = 'make_ps'
863
+ category = 'small'
864
+
821
865
  def __init__(self, settings_obj, obs_id, lst_idx=None):
822
866
  AbstractSubTask.__init__(self, settings_obj, 'pstool make_ps')
823
867
  self.obs_id = obs_id
@@ -881,6 +925,9 @@ class MakePSTask(AbstractTask):
881
925
 
882
926
  class RunGPRSubTask(AbstractSubTask):
883
927
 
928
+ label = 'run_gpr'
929
+ category = 'cpu'
930
+
884
931
  def __init__(self, settings_obj, obs_id, lst_idx=None):
885
932
  AbstractSubTask.__init__(self, settings_obj, 'pstool run_gpr')
886
933
  self.obs_id = obs_id
@@ -951,6 +998,9 @@ class RunGPRTask(AbstractTask):
951
998
 
952
999
  class RunMLGPRSubTask(AbstractSubTask):
953
1000
 
1001
+ label = 'run_ml_gpr'
1002
+ category = 'cpu'
1003
+
954
1004
  def __init__(self, settings_obj, obs_id, lst_idx=None):
955
1005
  AbstractSubTask.__init__(self, settings_obj, 'pstool run_ml_gpr')
956
1006
  self.obs_id = obs_id
@@ -1024,6 +1074,9 @@ class RunMLGPRTask(AbstractTask):
1024
1074
 
1025
1075
  class RunMLGPRInjSubTask(AbstractSubTask):
1026
1076
 
1077
+ label = 'run_ml_gpr_inj'
1078
+ category = 'cpu'
1079
+
1027
1080
  def __init__(self, settings_obj, obs_id, var_21_over_noise, x1, x2, lst_idx=None):
1028
1081
  AbstractSubTask.__init__(self, settings_obj, 'pstool run_ml_gpr_inj')
1029
1082
  self.obs_id = obs_id
@@ -1230,6 +1283,9 @@ class CombineTask(AbstractTask):
1230
1283
 
1231
1284
  class RunFlaggerSubTask(AbstractSubTask):
1232
1285
 
1286
+ label = 'run_flagger'
1287
+ category = 'small'
1288
+
1233
1289
  def __init__(self, settings_obj, obs_id):
1234
1290
  AbstractSubTask.__init__(self, settings_obj, 'pstool run_flagger')
1235
1291
  self.vis_rev = database.VisRevision(self.settings)
@@ -1244,6 +1300,9 @@ class RunFlaggerSubTask(AbstractSubTask):
1244
1300
 
1245
1301
  class VisToSphSubTask(AbstractSubTask):
1246
1302
 
1303
+ label = 'vis_to_sph'
1304
+ category = 'small'
1305
+
1247
1306
  def __init__(self, settings_obj, obs_id_out, stokes, h5_input, h5_out, h5_flag):
1248
1307
  AbstractSubTask.__init__(self, settings_obj, 'pstool vis_to_sph')
1249
1308
  self.vis_rev = database.VisRevision(self.settings)
@@ -1318,6 +1377,9 @@ class VisToSphTask(AbstractTask):
1318
1377
 
1319
1378
  class ApplyFlagSubTask(AbstractSubTask):
1320
1379
 
1380
+ label = 'apply_flag'
1381
+ category = 'small'
1382
+
1321
1383
  def __init__(self, settings_obj, ms_file, h5_file):
1322
1384
  AbstractSubTask.__init__(self, settings_obj, 'flagtool restore')
1323
1385
  self.ms_file = ms_file
@@ -1405,6 +1467,9 @@ class RestoreFlagTask(AbstractTask):
1405
1467
 
1406
1468
  class DelayFlaggerSubTask(AbstractSubTask):
1407
1469
 
1470
+ label = 'delay_flagger'
1471
+ category = 'medium'
1472
+
1408
1473
  def __init__(self, settings_obj, ms_file):
1409
1474
  AbstractSubTask.__init__(self, settings_obj, 'flagtool delay_flagger')
1410
1475
  self.ms_file = ms_file
@@ -1462,6 +1527,9 @@ class DelayFlagger(AbstractTask):
1462
1527
 
1463
1528
  class VisFlaggerSubTask(AbstractSubTask):
1464
1529
 
1530
+ label = 'vis_flagger'
1531
+ category = 'medium'
1532
+
1465
1533
  def __init__(self, settings_obj, ms_file):
1466
1534
  AbstractSubTask.__init__(self, settings_obj, 'flagtool vis_flagger')
1467
1535
  self.ms_file = ms_file
@@ -1513,6 +1581,9 @@ class VisFlagger(AbstractTask):
1513
1581
 
1514
1582
  class SSINSSubTask(AbstractSubTask):
1515
1583
 
1584
+ label = 'ssins'
1585
+ category = 'medium'
1586
+
1516
1587
  def __init__(self, settings_obj, ms_file):
1517
1588
  AbstractSubTask.__init__(self, settings_obj, 'flagtool ssins')
1518
1589
  self.ms_file = ms_file
@@ -10,6 +10,13 @@ max_concurrent = 4
10
10
  env_file = ''
11
11
  run_on_file_host = false
12
12
  run_on_file_host_pattern = ''
13
+ slurm_options = ''
14
+ max_time = 0
15
+ slurm_nodes = 0
16
+
17
+ [worker.resources]
18
+
19
+ [worker.categories]
13
20
 
14
21
  [merge_ms]
15
22
  apply_aoflagger = true
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [project]
6
6
  name = "pspipe"
7
- version = "0.12"
7
+ version = "0.14"
8
8
  description = "Power spectra pipeline for Cosmic Dawn, Epoch of Reionization radio interferometric experiments"
9
9
  readme = "README.md"
10
10
  license = "GPL-3.0-or-later"
@@ -20,7 +20,7 @@ dependencies = [
20
20
  "tables>=3.2",
21
21
  "tabulate>=0.8",
22
22
  "ps-eor>=1.0",
23
- "libpipe>=0.8",
23
+ "libpipe>=0.9",
24
24
  "python-casacore>=3.0",
25
25
  ]
26
26
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes