pspipe 0.3__tar.gz → 0.5__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 (37) hide show
  1. {pspipe-0.3 → pspipe-0.5}/PKG-INFO +6 -5
  2. {pspipe-0.3 → pspipe-0.5}/pspipe/obsdata.py +19 -7
  3. {pspipe-0.3 → pspipe-0.5}/pspipe/tasks.py +271 -17
  4. pspipe-0.5/pspipe/templates/config/eor_bins_hba.parset +4 -0
  5. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/default_settings.toml +26 -0
  6. {pspipe-0.3 → pspipe-0.5}/pspipe/tools/psdb.py +54 -0
  7. {pspipe-0.3 → pspipe-0.5}/pyproject.toml +1 -1
  8. pspipe-0.3/pspipe/templates/config/eor_bins_hba.parset +0 -5
  9. pspipe-0.3/setup.py +0 -47
  10. {pspipe-0.3 → pspipe-0.5}/LICENSE +0 -0
  11. {pspipe-0.3 → pspipe-0.5}/README.md +0 -0
  12. {pspipe-0.3 → pspipe-0.5}/pspipe/__init__.py +0 -0
  13. {pspipe-0.3 → pspipe-0.5}/pspipe/database.py +0 -0
  14. {pspipe-0.3 → pspipe-0.5}/pspipe/settings.py +0 -0
  15. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/eor_bins_a12.parset +0 -0
  16. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/eor_bins_alo.parset +0 -0
  17. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/eor_bins_nenufar.parset +0 -0
  18. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/flagger.parset +0 -0
  19. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/flagger_pre_combine.parset +0 -0
  20. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/gpr_config_a12.parset +0 -0
  21. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/gpr_config_hba.parset +0 -0
  22. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/gpr_config_nenufar.parset +0 -0
  23. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/gpr_config_v.parset +0 -0
  24. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/ps_config_a12.parset +0 -0
  25. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/ps_config_alo.parset +0 -0
  26. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/ps_config_hba.parset +0 -0
  27. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/config/ps_config_nenufar.parset +0 -0
  28. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/default_a12.toml +0 -0
  29. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/default_alo.toml +0 -0
  30. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/default_hba.toml +0 -0
  31. {pspipe-0.3 → pspipe-0.5}/pspipe/templates/default_nenufar.toml +0 -0
  32. {pspipe-0.3 → pspipe-0.5}/pspipe/tests/__init__.py +0 -0
  33. {pspipe-0.3 → pspipe-0.5}/pspipe/tests/test_settings.py +0 -0
  34. {pspipe-0.3 → pspipe-0.5}/pspipe/tests/test_utils.py +0 -0
  35. {pspipe-0.3 → pspipe-0.5}/pspipe/tools/__init__.py +0 -0
  36. {pspipe-0.3 → pspipe-0.5}/pspipe/tools/pspipe.py +0 -0
  37. {pspipe-0.3 → pspipe-0.5}/pspipe/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pspipe
3
- Version: 0.3
3
+ Version: 0.5
4
4
  Summary: Power spectra pipeline for Cosmic Dawn, Epoch of Reionization radio interferometric experiments
5
5
  Home-page: https://gitlab.com/flomertens/pspipe/
6
6
  Author: "Florent Mertens"
@@ -12,14 +12,15 @@ Classifier: Programming Language :: Python :: 3.8
12
12
  Classifier: Programming Language :: Python :: 3.9
13
13
  Classifier: Programming Language :: Python :: 3.10
14
14
  Classifier: Programming Language :: Python :: 3.11
15
- Requires-Dist: astropy (>=4.0,<5.0); python_version >= "3.7" and python_version < "3.8"
16
- Requires-Dist: astropy (>=5.0,<6.0); python_version >= "3.8"
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Requires-Dist: astropy (>=4.0,<5.0) ; python_version >= "3.7" and python_version < "3.8"
17
+ Requires-Dist: astropy (>=5.0,<6.0) ; python_version >= "3.8"
17
18
  Requires-Dist: matplotlib (>=3.0,<4.0)
18
19
  Requires-Dist: nenucal (>=0.1.11)
19
20
  Requires-Dist: ps-eor (>=0.8)
20
21
  Requires-Dist: python-casacore (>=3.0,<4.0)
21
- Requires-Dist: scipy (>=1.6,<2.0); python_version >= "3.7" and python_version < "3.8"
22
- Requires-Dist: scipy (>=1.8,<2.0); python_version >= "3.8"
22
+ Requires-Dist: scipy (>=1.6,<2.0) ; python_version >= "3.7" and python_version < "3.8"
23
+ Requires-Dist: scipy (>=1.8,<2.0) ; python_version >= "3.8"
23
24
  Requires-Dist: tables (>=3.2,<4.0)
24
25
  Requires-Dist: tabulate (>=0.8)
25
26
  Requires-Dist: toml (>=0.10)
@@ -33,7 +33,7 @@ class ObsData(object):
33
33
  assert key in self.all_stokes.keys()
34
34
  return self.get_stokes(self.all_stokes[key])
35
35
 
36
- def __invalid_cache(self):
36
+ def _invalidate_cache(self):
37
37
  self.data = {}
38
38
 
39
39
  def get_stokes_i_like(self):
@@ -48,15 +48,15 @@ class ObsData(object):
48
48
 
49
49
  def set_flag(self, flag):
50
50
  self.flag = flag
51
- self.__invalid_cache()
51
+ self._invalidate_cache()
52
52
 
53
53
  def filter_uvrange(self, umin, umax):
54
54
  self.uvrange = [umin, umax]
55
- self.__invalid_cache()
55
+ self._invalidate_cache()
56
56
 
57
57
  def average_freqs(self, nfreqs):
58
58
  self.nfreqs = nfreqs
59
- self.__invalid_cache()
59
+ self._invalidate_cache()
60
60
 
61
61
  def do_flag(self, flagger_file=None, verbose_flagging=True, plot_flagging=True):
62
62
  if flagger_file is None:
@@ -97,9 +97,21 @@ class ObsData(object):
97
97
 
98
98
  return i_res
99
99
 
100
- def get_ml_gpr_res(self, eor_bin, umin=50, umax=250, name=''):
101
- path = os.path.join(os.path.dirname(self.get_h5_file('I')), name, f'eor{eor_bin}_u{umin}-{umax}')
102
- return ml_gpr.MLGPRResult.load(path, 'ml_gpr_res_I')
100
+ def get_ml_gpr_path(self, eor_bin, umin=50, umax=250, name='', sampler_method='mcmc'):
101
+ return os.path.join(os.path.dirname(self.get_h5_file('I')), name, f'eor{eor_bin}_u{umin}-{umax}')
102
+
103
+ def get_ml_gpr_res(self, eor_bin, umin=50, umax=250, name='', sampler_method='mcmc'):
104
+ path = self.get_ml_gpr_path(eor_bin, umin=umin, umax=umax, name=name, sampler_method=sampler_method)
105
+ return ml_gpr.MLGPRResult.load(path, 'ml_gpr_res_I', sampler_method=sampler_method)
106
+
107
+ def get_ml_gpr_inj_path(self, eor_bin, var_21_over_noise, x1, x2, umin=50, umax=250, name=''):
108
+ d = f'inj_eor{eor_bin}_u{umin}-{umax}_a{var_21_over_noise:.3f}_x1{x1:.3f}_x2{x2:.3f}'
109
+ return os.path.join(os.path.dirname(self.get_h5_file('I')), name, d)
110
+
111
+ def get_ml_gpr_inj_res(self, eor_bin, var_21_over_noise, x1, x2, umin=50, umax=250, name='', sampler_method='mcmc'):
112
+ path = self.get_ml_gpr_inj_path(eor_bin, var_21_over_noise=var_21_over_noise, x1=x1, x2=x2, umin=umin, umax=umax, name=name)
113
+ data_inj = datacube.CartDataCube.load(os.path.join(path, 'c_injected.h5'))
114
+ return ml_gpr.MLGPRInjResult.load(path, 'ml_gpr_res_I', data_inj, sampler_method=sampler_method)
103
115
 
104
116
  def get_ps_gen(self, **kargs):
105
117
  return self.ps_builder.get(self.get_stokes_i_like(), **kargs)
@@ -6,6 +6,8 @@ import os
6
6
  import re
7
7
  import glob
8
8
  import tempfile
9
+ import datetime
10
+ import itertools
9
11
 
10
12
  import numpy as np
11
13
  import astropy.io.fits as pf
@@ -87,6 +89,8 @@ class AbstractTask(object):
87
89
 
88
90
  def add_sub_task(self, sub_task, run_on_host=None):
89
91
  log_file = sub_task.get_log_file()
92
+ if log_file:
93
+ log_file = log_file.rstrip('/')
90
94
 
91
95
  if log_file is not None:
92
96
  if not os.path.exists(os.path.dirname(log_file)):
@@ -137,7 +141,8 @@ class ImagingSubTask(AbstractSubTask):
137
141
  return f'{self.index:04d}'
138
142
 
139
143
  def get_log_file(self):
140
- return os.path.join(self.get_dir(), 'logs', os.path.basename(self.get_fits_prefix()) + '.log')
144
+ date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
145
+ return os.path.join(self.get_dir(), 'logs', os.path.basename(self.get_fits_prefix()) + f'_{date_str}.log')
141
146
 
142
147
  def get_fits_prefix(self):
143
148
  img = self.settings.image
@@ -212,8 +217,8 @@ class ImagingSubTask(AbstractSubTask):
212
217
  channels_out = self.obs_meta.n_channels // int(channels_out[5:])
213
218
  channels_out = int(channels_out)
214
219
 
215
- args.append("-oversampling 4095 -kernel-size 15 -nwlayers 1000 -grid-mode kb -taper-edge 100")
216
- args.append("-padding 2 -visibility-weighting-mode unit -reorder -make-psf -no-dirty")
220
+ args.append(f"-oversampling 4095 -kernel-size 15 -nwlayers 1000 -grid-mode kb -taper-edge {img.taper_edge}")
221
+ args.append(f"-padding {img.padding} -visibility-weighting-mode unit -reorder -make-psf -no-dirty")
217
222
 
218
223
  # If MS directory is not writable, we need to define a temp directory
219
224
  if not all(os.access(ms_file, os.W_OK) for ms_file in self.inp_ms_files):
@@ -346,8 +351,9 @@ class GenVisCubeSubTask(AbstractSubTask):
346
351
  return self.vis_rev.get_h5_file(self.obs_id, self.stokes.upper(), self.even, self.odd, lst_idx=self.lst_idx)
347
352
 
348
353
  def get_log_file(self):
354
+ date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
349
355
  return os.path.join(self.vis_rev.get_h5_path(self.obs_id, self.lst_idx), 'logs',
350
- os.path.basename(self.get_out_file().replace('.h5', '.log')))
356
+ os.path.basename(self.get_out_file().replace('.h5', f'_{date_str}.log')))
351
357
 
352
358
  def done_callback(self):
353
359
  meta = self.vis_rev.get_meta(self.obs_id, self.lst_idx)
@@ -459,7 +465,7 @@ class GenVisCubeTask(AbstractTask):
459
465
  class MergeMSSubTask(AbstractSubTask):
460
466
 
461
467
  def __init__(self, settings_obj, ms_files, obs_id_out):
462
- AbstractSubTask.__init__(self, settings_obj, 'DPPP')
468
+ AbstractSubTask.__init__(self, settings_obj, 'DP3')
463
469
  self.db = database.Database(self.settings)
464
470
  self.ms_files = ms_files
465
471
  self.obs_id_out = obs_id_out
@@ -471,7 +477,8 @@ class MergeMSSubTask(AbstractSubTask):
471
477
  return os.path.join(self.get_dir(), f'{self.obs_id_out}.MS')
472
478
 
473
479
  def get_log_file(self):
474
- return os.path.join(self.get_out_file().replace('.MS', '.log'))
480
+ date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
481
+ return os.path.join(self.get_out_file().replace('.MS', f'_{date_str}.log'))
475
482
 
476
483
  def make_link(self):
477
484
  inp_ms_dir = os.path.join(self.get_dir(), 'input_ms')
@@ -499,7 +506,7 @@ class MergeMSSubTask(AbstractSubTask):
499
506
  merge_ms = self.settings.merge_ms
500
507
 
501
508
  steps = ['filter']
502
- args = [f'msin={inp_ms_dir}/*.MS', f'msin.datacolumn={merge_ms.data_col}']
509
+ args = [f'msin={inp_ms_dir}/*.MS', f'msin.datacolumn={merge_ms.data_col}', f'numthreads={merge_ms.numthreads}']
503
510
  args.append(f'msout={self.get_out_file()} msout.overwrite=true')
504
511
  args.append(f'filter.type=filter filter.blrange=[{merge_ms.blmin},{merge_ms.blmax}]')
505
512
 
@@ -511,7 +518,7 @@ class MergeMSSubTask(AbstractSubTask):
511
518
 
512
519
  if merge_ms.apply_aoflagger:
513
520
  steps.append('flagger')
514
- args.append(f'flagger.type=aoflagger flagger.memoryperc=30 flagger.strategy="{merge_ms.aoflagger_strategy}"')
521
+ args.append(f'flagger.type=aoflagger flagger.memoryperc={merge_ms.memoryperc} flagger.strategy="{merge_ms.aoflagger_strategy}"')
515
522
 
516
523
  if merge_ms.flag_baselines:
517
524
  steps.append('preflag')
@@ -566,6 +573,102 @@ class MergeMSTask(AbstractTask):
566
573
  return all_obs_id_out
567
574
 
568
575
 
576
+ class AOFlaggerSubTask(AbstractSubTask):
577
+
578
+ def __init__(self, settings_obj, ms_file):
579
+ AbstractSubTask.__init__(self, settings_obj, 'DP3')
580
+ self.ms_file = ms_file
581
+
582
+ def get_log_file(self):
583
+ date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
584
+ return os.path.join(self.ms_file.replace('.MS', f'_aoflag_{date_str}.log'))
585
+
586
+ def get_parameters(self):
587
+ ao_flag = self.settings.ao_flag
588
+ args = [f'msin={self.ms_file}', 'msout=.', f'msin.datacolumn={ao_flag.data_col}', 'steps=[flagger]', f'numthreads={ao_flag.numthreads}']
589
+ args.append(f'flagger.type=aoflagger flagger.memoryperc={ao_flag.memoryperc} flagger.strategy="{ao_flag.aoflagger_strategy}"')
590
+
591
+ return args
592
+
593
+
594
+ class AOFlaggerTask(AbstractTask):
595
+
596
+ name = 'ao_flag'
597
+ desc = 'Run AO flagger on the Measurement Set(s)'
598
+
599
+ def __init__(self, settings_obj):
600
+ AbstractTask.__init__(self, 'AOFlagger', settings_obj, max_concurrent=1)
601
+ self.db = database.Database(self.settings)
602
+
603
+ def run(self, obs_ids):
604
+ all_obs_id_out = []
605
+
606
+ for obs_id in obs_ids:
607
+ if not self.db.has_obs_id(obs_id):
608
+ print(f'Error: Obs ID {obs_id} does not exist.')
609
+ return []
610
+
611
+ ms_files = self.db.get_obs_id_meta(obs_id).ms_files
612
+
613
+ if not ms_files:
614
+ print(f'Error: Obs ID {obs_id} has no MS files registered.')
615
+ return []
616
+
617
+ for ms_file in np.array(ms_files).flatten():
618
+ self.add_sub_task(AOFlaggerSubTask(self.settings, ms_file))
619
+ all_obs_id_out.append(obs_id)
620
+
621
+ self.execute()
622
+
623
+ return all_obs_id_out
624
+
625
+
626
+ class DP3SubTask(AbstractSubTask):
627
+
628
+ def __init__(self, settings_obj, ms_file):
629
+ AbstractSubTask.__init__(self, settings_obj, 'DP3')
630
+ self.ms_file = ms_file
631
+
632
+ def get_log_file(self):
633
+ date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
634
+ return os.path.join(self.ms_file.replace('.MS', f'_dp3_{date_str}.log'))
635
+
636
+ def get_parameters(self):
637
+ return [self.settings.dp3.dp3_file, f'msin={self.ms_file}']
638
+
639
+
640
+ class DP3Task(AbstractTask):
641
+
642
+ name = 'dp3'
643
+ desc = 'Run DP3 on the Measurement Set(s)'
644
+
645
+ def __init__(self, settings_obj):
646
+ AbstractTask.__init__(self, 'DP3', settings_obj, max_concurrent=1)
647
+ self.db = database.Database(self.settings)
648
+
649
+ def run(self, obs_ids):
650
+ all_obs_id_out = []
651
+
652
+ for obs_id in obs_ids:
653
+ if not self.db.has_obs_id(obs_id):
654
+ print(f'Error: Obs ID {obs_id} does not exist.')
655
+ return []
656
+
657
+ ms_files = self.db.get_obs_id_meta(obs_id).ms_files
658
+
659
+ if not ms_files:
660
+ print(f'Error: Obs ID {obs_id} has no MS files registered.')
661
+ return []
662
+
663
+ for ms_file in np.array(ms_files).flatten():
664
+ self.add_sub_task(DP3SubTask(self.settings, ms_file))
665
+ all_obs_id_out.append(obs_id)
666
+
667
+ self.execute()
668
+
669
+ return all_obs_id_out
670
+
671
+
569
672
  class MakePSSubTask(AbstractSubTask):
570
673
 
571
674
  def __init__(self, settings_obj, obs_id, lst_idx=None):
@@ -575,7 +678,8 @@ class MakePSSubTask(AbstractSubTask):
575
678
  self.vis_rev = database.VisRevision(self.settings)
576
679
 
577
680
  def get_log_file(self):
578
- return os.path.join(self.vis_rev.get_h5_path(self.obs_id, self.lst_idx), 'logs', 'make_ps.log')
681
+ date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
682
+ return os.path.join(self.vis_rev.get_h5_path(self.obs_id, self.lst_idx), 'logs', f'make_ps_{date_str}.log')
579
683
 
580
684
  def get_parameters(self):
581
685
  h5_i = self.vis_rev.get_h5_file(self.obs_id, 'I', lst_idx=self.lst_idx)
@@ -633,7 +737,8 @@ class RunGPRSubTask(AbstractSubTask):
633
737
  self.vis_rev = database.VisRevision(self.settings)
634
738
 
635
739
  def get_log_file(self):
636
- return os.path.join(self.vis_rev.get_path(), self.obs_id, 'logs', 'run_gpr.log')
740
+ date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
741
+ return os.path.join(self.vis_rev.get_path(), self.obs_id, 'logs', f'run_gpr_{date_str}.log')
637
742
 
638
743
  def get_parameters(self):
639
744
  h5_i = self.vis_rev.get_h5_file(self.obs_id, 'I', lst_idx=self.lst_idx)
@@ -699,13 +804,16 @@ class RunMLGPRSubTask(AbstractSubTask):
699
804
  self.vis_rev = database.VisRevision(self.settings)
700
805
 
701
806
  def get_log_file(self):
702
- return os.path.join(self.vis_rev.get_path(), self.obs_id, 'logs', 'run_ml_gpr.log')
807
+ date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
808
+ return os.path.join(self.vis_rev.get_path(), self.obs_id, 'logs', f'run_ml_gpr_{date_str}.log')
703
809
 
704
810
  def get_parameters(self):
705
- h5_i = self.vis_rev.get_h5_file(self.obs_id, 'I', lst_idx=self.lst_idx)
706
- h5_v = self.vis_rev.get_h5_file(self.obs_id, 'V', lst_idx=self.lst_idx)
707
811
  psc = self.settings.power_spectra
708
812
  gpr = self.settings.ml_gpr
813
+
814
+ h5_i = self.vis_rev.get_h5_file(self.obs_id, gpr.stokes_i, lst_idx=self.lst_idx)
815
+ h5_v = self.vis_rev.get_h5_file(self.obs_id, gpr.stokes_v, lst_idx=self.lst_idx)
816
+
709
817
  out_dir = os.path.join(self.vis_rev.get_h5_path(self.obs_id, self.lst_idx), gpr.name)
710
818
  plot_out_dir = os.path.join(self.vis_rev.get_result_path(self.obs_id, self.lst_idx), gpr.name)
711
819
 
@@ -714,7 +822,7 @@ class RunMLGPRSubTask(AbstractSubTask):
714
822
  args.append(f'-c {psc.get_path("ps_config")} -o {out_dir} -po {plot_out_dir}')
715
823
 
716
824
  if gpr.use_v_dt_as_noise:
717
- h5_v_dt = self.vis_rev.get_h5_file(self.obs_id, 'dt_V', lst_idx=self.lst_idx)
825
+ h5_v_dt = self.vis_rev.get_h5_file(self.obs_id, gpr.stokes_dt, lst_idx=self.lst_idx)
718
826
  args.append(f'--file_noise {h5_v_dt}')
719
827
 
720
828
  if not gpr.plot_results:
@@ -756,6 +864,97 @@ class RunMLGPRTask(AbstractTask):
756
864
  return obs_ids
757
865
 
758
866
 
867
+ class RunMLGPRInjSubTask(AbstractSubTask):
868
+
869
+ def __init__(self, settings_obj, obs_id, var_21_over_noise, x1, x2, lst_idx=None):
870
+ AbstractSubTask.__init__(self, settings_obj, 'pstool run_ml_gpr_inj')
871
+ self.obs_id = obs_id
872
+ self.lst_idx = lst_idx
873
+ self.var_21_over_noise = var_21_over_noise
874
+ self.x1 = x1
875
+ self.x2 = x2
876
+ self.vis_rev = database.VisRevision(self.settings)
877
+
878
+ def get_log_file(self):
879
+ date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
880
+ return os.path.join(self.vis_rev.get_path(), self.obs_id, 'logs', f'run_ml_gpr_inj_{date_str}.log')
881
+
882
+ def get_parameters(self):
883
+ h5_i = self.vis_rev.get_h5_file(self.obs_id, 'I', lst_idx=self.lst_idx)
884
+ h5_v = self.vis_rev.get_h5_file(self.obs_id, 'V', lst_idx=self.lst_idx)
885
+ psc = self.settings.power_spectra
886
+ gpr = self.settings.ml_gpr
887
+ out_dir = os.path.join(self.vis_rev.get_h5_path(self.obs_id, self.lst_idx), gpr.name)
888
+
889
+ args = [h5_i, h5_v, gpr.get_path("config")]
890
+ args.append(f'-f {psc.get_path("flagger")} -e {psc.get_path("eor_bin_list")}')
891
+ args.append(f'-c {psc.get_path("ps_config")} -o {out_dir}')
892
+
893
+ if gpr.use_v_dt_as_noise:
894
+ h5_v_dt = self.vis_rev.get_h5_file(self.obs_id, 'dt_V', lst_idx=self.lst_idx)
895
+ args.append(f'--file_noise {h5_v_dt}')
896
+
897
+ args.append(f'-a {self.var_21_over_noise} --x1 {self.x1} --x2 {self.x2}')
898
+
899
+ if not gpr.plot_results:
900
+ args.append('--no_plot')
901
+
902
+ return args
903
+
904
+
905
+ class RunMLGPRInjTask(AbstractTask):
906
+
907
+ name = 'run_ml_gpr_inj'
908
+ desc = 'Run ML-GPR injection and produce power-spectra'
909
+
910
+ def __init__(self, settings_obj):
911
+ AbstractTask.__init__(self, 'ML-GPR', settings_obj)
912
+ self.vis_rev = database.VisRevision(self.settings)
913
+ self.img_rev = database.ImageRevision(self.settings)
914
+
915
+ def run(self, obs_ids):
916
+ if not (self.settings.validate('power_spectra') and self.settings.validate('gpr')):
917
+ return []
918
+
919
+ if not self.vis_rev.exist():
920
+ print(f'Error: visibility revision does not exist.')
921
+ return []
922
+
923
+ for obs_id in obs_ids:
924
+ if not self.vis_rev.has_obs_id(obs_id):
925
+ print(f'Error: visibility revision for obs ID {obs_id} not available')
926
+ return []
927
+
928
+ all_lst_idx = self.img_rev.get_lst_bins(obs_id).keys() if self.settings.image.lst_bins else [None]
929
+
930
+ for lst_idx in all_lst_idx:
931
+ var = self.settings.ml_gpr_inj.var_21_over_noise
932
+ x1s = self.settings.ml_gpr_inj.x1
933
+ x2s = self.settings.ml_gpr_inj.x2
934
+ x1_x2_file = self.settings.ml_gpr_inj.x1_x2_file
935
+
936
+ try:
937
+ if x1_x2_file:
938
+ x1_x2s = np.loadtxt(x1_x2_file, delimiter=',').tolist()
939
+ else:
940
+ x1_x2s = list(itertools.product(x1s, x2s))
941
+ except IOError as e:
942
+ print(f"Error loading file '{x1_x2_file}': {e}")
943
+ return []
944
+ except ValueError as e:
945
+ print(f"Error parsing file '{x1_x2_file}': {e}")
946
+ return []
947
+
948
+ for v, (x1, x2) in itertools.product(var, x1_x2s):
949
+ self.add_sub_task(RunMLGPRInjSubTask(self.settings, obs_id, v, x1, x2, lst_idx))
950
+
951
+ self.add_sub_task(RunMLGPRInjSubTask(self.settings, obs_id, 0, 0, 0, lst_idx))
952
+
953
+ self.execute()
954
+
955
+ return obs_ids
956
+
957
+
759
958
  class CombineTask(AbstractTask):
760
959
 
761
960
  name = 'combine'
@@ -842,7 +1041,8 @@ class CombineTask(AbstractTask):
842
1041
  umax = self.settings.vis_cube.umax
843
1042
  c = self.settings.combine
844
1043
 
845
- out_log = os.path.join(self.get_path(), f'C{obs_id_out_prefix}.log')
1044
+ date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
1045
+ out_log = os.path.join(self.get_path(), f'C{obs_id_out_prefix}_{date_str}.log')
846
1046
 
847
1047
  if is_sph:
848
1048
  cmd = (f'pstool combine_sph {self.get_combine_file()} -o {output_template} '
@@ -948,6 +1148,10 @@ class ApplyFlagSubTask(AbstractSubTask):
948
1148
  self.ms_file = ms_file
949
1149
  self.h5_file = h5_file
950
1150
 
1151
+ def get_log_file(self):
1152
+ date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
1153
+ return os.path.join(self.ms_file.replace('.MS', f'apply_flags_{date_str}.log'))
1154
+
951
1155
  def get_parameters(self):
952
1156
  return [self.ms_file, self.h5_file]
953
1157
 
@@ -1027,12 +1231,13 @@ class DelayFlaggerSubTask(AbstractSubTask):
1027
1231
  def __init__(self, settings_obj, ms_file):
1028
1232
  AbstractSubTask.__init__(self, settings_obj, 'flagtool delay_flagger')
1029
1233
  self.ms_file = ms_file
1234
+ self.date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
1030
1235
 
1031
1236
  def get_log_file(self):
1032
- return os.path.join(self.ms_file.replace('.MS', '_delay_flagger.log'))
1237
+ return os.path.join(self.ms_file.replace('.MS', f'_delay_flagger_{self.date_str}.log'))
1033
1238
 
1034
1239
  def get_path(self):
1035
- d = os.path.join(os.path.dirname(self.ms_file), 'flagger')
1240
+ d = os.path.join(os.path.dirname(self.ms_file), f'flagger_{self.date_str}')
1036
1241
  futils.mkdir(d)
1037
1242
  return d
1038
1243
 
@@ -1076,6 +1281,55 @@ class DelayFlagger(AbstractTask):
1076
1281
  return obs_ids
1077
1282
 
1078
1283
 
1284
+ class VisFlaggerSubTask(AbstractSubTask):
1285
+
1286
+ def __init__(self, settings_obj, ms_file):
1287
+ AbstractSubTask.__init__(self, settings_obj, 'flagtool vis_flagger')
1288
+ self.ms_file = ms_file
1289
+ self.date_str = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
1290
+
1291
+ def get_log_file(self):
1292
+ return os.path.join(self.ms_file.replace('.MS', f'{self.date_str}_vis_flagger.log'))
1293
+
1294
+ def get_path(self):
1295
+ d = os.path.join(os.path.dirname(self.ms_file), f'vis_flagger_{self.date_str}')
1296
+ futils.mkdir(d)
1297
+ return d
1298
+
1299
+ def get_parameters(self):
1300
+ return [self.ms_file, self.settings.vis_flagger.config_file, f'--plot_dir={self.get_path()}',
1301
+ '--backup', f'--backup_file={H5_FLAG_BACKUP}']
1302
+
1303
+
1304
+ class VisFlagger(AbstractTask):
1305
+
1306
+ name = 'vis_flagger'
1307
+ desc = 'Apply vis flagger on MS'
1308
+
1309
+ def __init__(self, settings_obj):
1310
+ AbstractTask.__init__(self, 'VisFlagger', settings_obj)
1311
+ self.db = database.Database(self.settings)
1312
+
1313
+ def run(self, obs_ids):
1314
+ for obs_id in obs_ids:
1315
+ if not self.db.has_obs_id(obs_id):
1316
+ print(f'Error: Obs ID {obs_id} does not exist.')
1317
+ return []
1318
+
1319
+ ms_files = self.db.get_obs_id_meta(obs_id).ms_files
1320
+
1321
+ if not ms_files:
1322
+ print(f'Error: Obs ID {obs_id} has no MS files registered.')
1323
+ return []
1324
+
1325
+ for ms_file in np.array(ms_files).flatten():
1326
+ self.add_sub_task(VisFlaggerSubTask(self.settings, ms_file))
1327
+
1328
+ self.execute()
1329
+
1330
+ return obs_ids
1331
+
1332
+
1079
1333
  class SSINSSubTask(AbstractSubTask):
1080
1334
 
1081
1335
  def __init__(self, settings_obj, ms_file):
@@ -0,0 +1,4 @@
1
+ # name,fmhz_start,fmhz_end,fmhz_fg_start,fmhz_fg_end
2
+ 1,122.0,134.3,122.0,134.3
3
+ 2,134.3,146.8,134.3,146.8
4
+ 3,146.8,159.3,146.8,159.3
@@ -21,6 +21,18 @@ flag_baselines = ''
21
21
  avg_timestep = 1
22
22
  time_start_index = 0
23
23
  time_end_index = 0
24
+ numthreads = 0
25
+ memoryperc = 30
26
+
27
+ [ao_flag]
28
+ data_col = 'DATA'
29
+ numthreads = 0
30
+ memoryperc = 30
31
+ aoflagger_strategy = ''
32
+
33
+ [dp3]
34
+ numthreads = 0
35
+ dp3_file = ''
24
36
 
25
37
  [ssins]
26
38
  apply_ssins = true
@@ -45,6 +57,9 @@ n_times = 20
45
57
  n_sigma_i = 6
46
58
  n_sigma_v = 6
47
59
 
60
+ [vis_flagger]
61
+ config_file = ''
62
+
48
63
  [image]
49
64
  name = 'default'
50
65
  umin = 50
@@ -64,6 +79,8 @@ clean_auto_threshold = 5
64
79
  clean_mgain = 0.6
65
80
  clean_residual = true
66
81
  clean_spectra_fit_nterms = 4
82
+ taper_edge = 100
83
+ padding = 2
67
84
  wsclean_args = {}
68
85
 
69
86
  [vis_cube]
@@ -100,4 +117,13 @@ use_v_dt_as_noise = false
100
117
  name = ''
101
118
  config = ''
102
119
  plot_results = true
120
+ stokes_i = 'I'
121
+ stokes_v = 'V'
122
+ stokes_dt = 'dt_v'
103
123
  use_v_dt_as_noise = false
124
+
125
+ [ml_gpr_inj]
126
+ var_21_over_noise = [1]
127
+ x1 = [0]
128
+ x2 = [0]
129
+ x1_x2_file = ''
@@ -396,5 +396,59 @@ def remove_obs(settings_file, obs_ids):
396
396
  print('No changes made.')
397
397
 
398
398
 
399
+ def concatenate_datacubes(cubes):
400
+ from ps_eor import datacube
401
+
402
+ key_fct = lambda a: a.freqs[0]
403
+ cubes = sorted(cubes, key=key_fct)
404
+
405
+ assert len(cubes) > 1
406
+ assert np.alltrue([isinstance(cube, datacube.DataCube) for cube in cubes])
407
+ assert np.alltrue([np.allclose(cubes[0].uu, cube.uu) for cube in cubes[1:]])
408
+ assert np.alltrue([np.allclose(cubes[0].vv, cube.vv) for cube in cubes[1:]])
409
+
410
+ data = np.concatenate([c.data for c in cubes])
411
+ weights_data = np.concatenate([c.weights.data for c in cubes])
412
+ freqs = np.concatenate([c.freqs for c in cubes])
413
+ weights = datacube.CartWeightCube(weights_data, cubes[0].uu, cubes[0].vv, freqs, cubes[0].meta)
414
+
415
+ return datacube.CartDataCube(data, cubes[0].uu, cubes[0].vv, freqs, cubes[0].meta, weights=weights)
416
+
417
+
418
+ @main.command('concat_vis_cube')
419
+ @click.argument('settings_file', type=t_file)
420
+ @click.argument('obs_ids', type=str)
421
+ @click.argument('new_obs_id', type=str)
422
+ @click.option('--fmin', type=float, help='Min frequency in MHz', default=None)
423
+ @click.option('--fmax', type=float, help='Max frequency in MHz', default=None)
424
+ def concat_vis_cube(settings_file, obs_ids, new_obs_id, fmin, fmax):
425
+ ''' Remove an Obs ID from the given pspipe database
426
+ '''
427
+ rev = database.VisRevision(load_settings(settings_file))
428
+ db = database.Database(load_settings(settings_file))
429
+ obs_id_set = list(db.filter_obs_ids(obs_ids))
430
+
431
+ if not obs_id_set:
432
+ print(f'Error: No obs_ids matching {obs_ids} in database.')
433
+ return
434
+
435
+ meta = db.get_obs_id_meta(obs_id_set[0])
436
+
437
+ add(db, new_obs_id, None, int_time=meta.int_time, total_time=meta.total_time, chan_width=meta.chan_width)
438
+ data1 = rev.get_data(obs_id_set[0])
439
+
440
+ all_stokes = [s for s in data1.all_stokes.values() if data1.has_stokes(s)]
441
+
442
+ for s in all_stokes:
443
+ data_cube = concatenate_datacubes([rev.get_data(obs_id).get_stokes(s) for obs_id in obs_id_set])
444
+ if fmin is not None and fmax is not None:
445
+ data_cube = data_cube.get_slice(fmin, fmax)
446
+ h5_filename = rev.get_h5_file(new_obs_id, s)
447
+ os.makedirs(os.path.dirname(h5_filename), exist_ok=True)
448
+ data_cube.save(h5_filename)
449
+
450
+ print(f'Combined data for {new_obs_id} successfully added.')
451
+
452
+
399
453
  if __name__ == '__main__':
400
454
  main()
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pspipe"
3
- version = "0.3"
3
+ version = "0.5"
4
4
  description = "Power spectra pipeline for Cosmic Dawn, Epoch of Reionization radio interferometric experiments"
5
5
  authors = ["\"Florent Mertens\" <\"florent.mertens@gmail.com\">"]
6
6
  repository = "https://gitlab.com/flomertens/pspipe/"
@@ -1,5 +0,0 @@
1
- # name,fmhz_start,fmhz_end,fmhz_fg_start,fmhz_fg_end
2
- 1,122,134,122,134
3
- 2,134,146,134,146
4
- 3,146,158,146,158
5
-
pspipe-0.3/setup.py DELETED
@@ -1,47 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- from setuptools import setup
3
-
4
- packages = \
5
- ['pspipe', 'pspipe.tests', 'pspipe.tools']
6
-
7
- package_data = \
8
- {'': ['*'], 'pspipe': ['templates/*', 'templates/config/*']}
9
-
10
- install_requires = \
11
- ['matplotlib>=3.0,<4.0',
12
- 'nenucal>=0.1.11',
13
- 'ps-eor>=0.8',
14
- 'python-casacore>=3.0,<4.0',
15
- 'tables>=3.2,<4.0',
16
- 'tabulate>=0.8',
17
- 'toml>=0.10']
18
-
19
- extras_require = \
20
- {':python_version >= "3.7" and python_version < "3.8"': ['astropy>=4.0,<5.0',
21
- 'scipy>=1.6,<2.0'],
22
- ':python_version >= "3.8"': ['astropy>=5.0,<6.0', 'scipy>=1.8,<2.0']}
23
-
24
- entry_points = \
25
- {'console_scripts': ['psdb = pspipe.tools.psdb:main',
26
- 'pspipe = pspipe.tools.pspipe:main']}
27
-
28
- setup_kwargs = {
29
- 'name': 'pspipe',
30
- 'version': '0.3',
31
- 'description': 'Power spectra pipeline for Cosmic Dawn, Epoch of Reionization radio interferometric experiments',
32
- 'long_description': 'Power Spectra Generation pipeline for CD/EoR experiments\n========================================================\n\npspipe is an analysis pipeline which aims to make generation of high precision power-spectra for Cosmic Dawn and Epoch of Reionization experiments as easy and reproducible as possible. pspipe is the default analysis pipeline of the [Lofar-EoR](http://www.lofar.org/astronomy/eor-ksp/epoch-reionization.html) and [NenuFAR](https://nenufar.obs-nancay.fr/en/homepage-en/) CD projects. It performs all tasks from calibrated data to final the power-spectra, including:\n\n- Post-calibration flagging (using [AOflagger](https://sourceforge.net/p/aoflagger/wiki/Home/) and [SSINS](https://arxiv.org/abs/1906.01093))\n- Visibility gridding (using [WSClean](https://sourceforge.net/p/wsclean/wiki/Home/))\n- Foregrounds modeling and removal (using [GPR](https://doi.org/10.1093/mnras/sty1207), [GMCA](https://arxiv.org/abs/1209.4769), polynomial fitting)\n- Optimal power-spectra generation (using [ps_eor](https://gitlab.com/flomertens/ps_eor))\n\nThanks to its multi-nodes concurrent processing, pspipe is also very fast at crunching hundreds of hour of calibrated data.\n\nInstallation\n------------\n\npspipe can be installed via pip:\n\n $ pip install pspipe\n\nand requires Python 3.7.0 or higher. For certain tasks, you will also need [DPPP](https://github.com/lofar-astron/DP3/tree/master/DPPP) and [WSClean](https://sourceforge.net/p/wsclean/wiki/Home/)\n\nDocumentation\n--------------\n\nPlease check the [wiki page](https://gitlab.com/flomertens/pspipe/-/wikis/home).\n',
33
- 'author': '"Florent Mertens"',
34
- 'author_email': '"florent.mertens@gmail.com"',
35
- 'maintainer': 'None',
36
- 'maintainer_email': 'None',
37
- 'url': 'https://gitlab.com/flomertens/pspipe/',
38
- 'packages': packages,
39
- 'package_data': package_data,
40
- 'install_requires': install_requires,
41
- 'extras_require': extras_require,
42
- 'entry_points': entry_points,
43
- 'python_requires': '>=3.7,<4.0',
44
- }
45
-
46
-
47
- setup(**setup_kwargs)
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
File without changes
File without changes