66import os
77import re
88import numpy as np
9+ import yaml
910
1011def get_windownames_list (dict ):
1112 """Get the unique window names from the paramdict."""
@@ -44,50 +45,119 @@ def get_arrays_list(dict):
4445 n_arrays += 1
4546 return n_arrays , sv_list , ar_list
4647
47- def get_spectra_list (dict ):
48+ # to get around delimiters...
49+ def get_sv_and_m_from_sv_m (sv_m , sv_m_list , sv_list , m_list ):
50+ idx = sv_m_list .index (sv_m )
51+ return sv_list [idx ], m_list [idx ]
52+
53+ # given a dictionary of rules, test if a pair of two dicts of tags passes
54+ def eval_mpair_rules (t1 , t2 , rules ):
55+ if not rules :
56+ return True
57+
58+ # 1. Require specific tags (strict list pools expected)
59+ for tag_key , (pool1 , pool2 ) in rules .get ('require_tags' , {}).items ():
60+ v1 = t1 .get (tag_key )
61+ v2 = t2 .get (tag_key )
62+
63+ # Check standard and flipped orientations using the pools
64+ match_standard = (v1 in pool1 ) and (v2 in pool2 )
65+ match_flipped = (v1 in pool2 ) and (v2 in pool1 )
66+
67+ if not (match_standard or match_flipped ):
68+ return False
69+
70+ # 2. Dynamic matching (must have the same value for these tags)
71+ if 'match_any_tag' in rules :
72+ if not any (t1 .get (key ) == t2 .get (key ) for key in rules ['match_any_tag' ]):
73+ return False
74+
75+ if 'match_all_tags' in rules :
76+ if not all (t1 .get (key ) == t2 .get (key ) for key in rules ['match_all_tags' ]):
77+ return False
78+
79+ return True
80+
81+ def get_spec2nullgroup2nullflag_mpairs (d , return_spectra_list = False ):
82+ with open (d ['spec2nullgroup2nullflag_mpairs_yaml' ], 'r' ) as file :
83+ inp = yaml .safe_load (file )
84+
85+ _ , _sv_list , _m_list = get_arrays_list (d )
86+ _sv_m_list = ['_' .join (_sv_m ) for _sv_m in zip (_sv_list , _m_list )] # assume delimiter = '_' to match against tags dict
87+ _full_mpairs_list = list (cwr (_sv_m_list , r = 2 ))
88+ _full_mpairs_list_with_reversed = list (product (_sv_m_list , repeat = 2 ))
89+
90+ spec2nullgroup2nullflag_mpairs = {}
91+ _spec_name_list = [], []
92+ for spec , nullgroup2nullflag_mpairrules in inp .items ():
93+ if spec [0 ] == spec [1 ]:
94+ mpairs_iter = _full_mpairs_list
95+ else :
96+ mpairs_iter = _full_mpairs_list_with_reversed
97+
98+ spec2nullgroup2nullflag_mpairs [spec ] = {}
99+ for nullgroup , nullflag_mpairrules in nullgroup2nullflag_mpairrules .items ():
100+ spec2nullgroup2nullflag_mpairs [spec ][nullgroup ] = [nullflag_mpairrules ['nullflag' ]]
101+
102+ mpairrules = nullflag_mpairrules .get ('mpair_rules' , {})
103+ mpairs = [f'{ m1 } x{ m2 } ' for m1 , m2 in mpairs_iter if eval_mpair_rules (d [f'tags_{ m1 } ' ], d [f'tags_{ m2 } ' ], mpairrules )]
104+
105+ assert len (mpairs ) == len (np .unique (mpairs )), \
106+ f'mpairs from spec2nullgroup2nullflag_mpairs_yaml, { spec } not unique'
107+
108+ spec2nullgroup2nullflag_mpairs [spec ][nullgroup ].append (mpairs )
109+
110+ for mpair in mpairs :
111+ for _mpair in (mpair , 'x' .join (mpair .split ('x' )[::- 1 ])):
112+ if _mpair in _full_mpairs_list and _mpair not in _spec_name_list :
113+ _spec_name_list .append (_mpair )
114+
115+ # from _spec_name_list to spectra list.
116+ # do this because "spectra_list" is more fundamental even though spec_name_list is used as
117+ # an intermediary above because it's easier to test membership in
118+ n_spec = 0
119+ sv1_list , ar1_list , sv2_list , ar2_list = [], [], [], []
120+ for _spec_name in _spec_name_list :
121+ n1 , n2 = _spec_name .split ('x' )
122+ sv1 , ar1 = get_sv_and_m_from_sv_m (n1 , _sv_m_list , _sv_list , _m_list )
123+ sv2 , ar2 = get_sv_and_m_from_sv_m (n2 , _sv_m_list , _sv_list , _m_list )
124+ sv1_list += [sv1 ]
125+ ar1_list += [ar1 ]
126+ sv2_list += [sv2 ]
127+ ar2_list += [ar2 ]
128+ n_spec += 1
129+
130+ if return_spectra_list :
131+ return spec2nullgroup2nullflag_mpairs , (n_spec , sv1_list , ar1_list , sv2_list , ar2_list )
132+ else :
133+ return spec2nullgroup2nullflag_mpairs
134+
135+ def get_spectra_list (dict , from_spec_nullgroups = False ):
48136 """This function creates the lists over which mpi is done
49- when we parallelized over each spectra
50- If combinations_infos appears in the paramfile, precompute the list of skipped computations
51- It look at keys (sv1, sv2) in d["comibations_infos"] that should be a list of :
52- "skip": skips all combinations of sv1 with sv2
53- "tube": skips all combinations except with same tube (using tags_sv*_ar*)
54- "freq": skips all combinations except with same freq (using tags_sv*_ar*)
55- "smthg": skips all combinations except with same "smthg" (using tags_sv*_ar*)
56- "tube" and "freq" are used by convention but you can put anything,
57- as long as it appears in tags_sv*_ar*.
58- If the list is empty, then it will skip everything (like "skip").
59- To not skip anything, d["comibations_infos"][sv1, sv2] must be None
60- or [sv1, sv2] must not appear in d["comibations_infos"].
137+ when we parallelized over each spectra.
61138
62139 Parameters
63140 ----------
64141 dict : dict
65142 the global dictionnary file used in pspipe
66143
67144 """
68- surveys = dict ["surveys" ]
69-
70- def check_combination (sv1 , ar1 , sv2 , ar2 , comb_list ):
71- if comb_list is None : return True
72- elif 'skip' in comb_list : return False # If skip, doesnot even need tags_...
73-
74- tags_ar1 = dict [f'tags_{ sv1 } _{ ar1 } ' ]
75- tags_ar2 = dict [f'tags_{ sv2 } _{ ar2 } ' ]
76-
77- return any (tags_ar1 [kw ] == tags_ar2 [kw ] for kw in comb_list )
145+ if from_spec_nullgroups :
146+ _ , (n_spec , sv1_list , ar1_list , sv2_list , ar2_list ) = get_spec2nullgroup2nullflag_mpairs (dict , return_spec_name_list = True )
78147
79- sv1_list , ar1_list , sv2_list , ar2_list = [], [], [], []
80- n_spec = 0
81- for id_sv1 , sv1 in enumerate (surveys ):
82- arrays_1 = dict [f"arrays_{ sv1 } " ]
83- for id_ar1 , ar1 in enumerate (arrays_1 ):
84- for id_sv2 , sv2 in enumerate (surveys ):
85- arrays_2 = dict [f"arrays_{ sv2 } " ]
86- for id_ar2 , ar2 in enumerate (arrays_2 ):
87- if (id_sv1 > id_sv2 ) : continue
88- if (id_sv1 == id_sv2 ) & (id_ar1 > id_ar2 ) : continue
89- if ('combination_args' not in dict ) or (check_combination (sv1 , ar1 , sv2 , ar2 , dict ['combination_args' ][(sv1 , sv2 )])):
90- # This ensures that we do not repeat redundant computations
148+ else :
149+ surveys = dict ["surveys" ]
150+
151+ sv1_list , ar1_list , sv2_list , ar2_list = [], [], [], []
152+ n_spec = 0
153+ for id_sv1 , sv1 in enumerate (surveys ):
154+ arrays_1 = dict [f"arrays_{ sv1 } " ]
155+ for id_ar1 , ar1 in enumerate (arrays_1 ):
156+ for id_sv2 , sv2 in enumerate (surveys ):
157+ arrays_2 = dict [f"arrays_{ sv2 } " ]
158+ for id_ar2 , ar2 in enumerate (arrays_2 ):
159+ if (id_sv1 > id_sv2 ) : continue
160+ if (id_sv1 == id_sv2 ) & (id_ar1 > id_ar2 ) : continue
91161 sv1_list += [sv1 ]
92162 ar1_list += [ar1 ]
93163 sv2_list += [sv2 ]
@@ -96,7 +166,7 @@ def check_combination(sv1, ar1, sv2, ar2, comb_list):
96166
97167 return n_spec , sv1_list , ar1_list , sv2_list , ar2_list
98168
99- def get_covariances_list (dict , delimiter = "&" ):
169+ def get_covariances_list (dict , delimiter = "&" , from_spec_nullgroups = False ):
100170 """This function creates the lists over which mpi is done
101171 when we parallelized over each covariance element
102172
@@ -107,7 +177,7 @@ def get_covariances_list(dict, delimiter="&"):
107177
108178 """
109179
110- spec_name = get_spec_name_list (dict , delimiter )
180+ spec_name = get_spec_name_list (dict , delimiter = delimiter , from_spec_nullgroups = from_spec_nullgroups )
111181 na_list , nb_list , nc_list , nd_list = [], [], [], []
112182 ncovs = 0
113183
@@ -124,7 +194,7 @@ def get_covariances_list(dict, delimiter="&"):
124194
125195 return ncovs , na_list , nb_list , nc_list , nd_list
126196
127- def get_spec_name_list (dict , delimiter = "&" ):
197+ def get_spec_name_list (dict , delimiter = "&" , from_spec_nullgroups = False ):
128198 """This function creates a list with the name of all spectra we consider
129199
130200 Parameters
@@ -136,7 +206,7 @@ def get_spec_name_list(dict, delimiter="&"):
136206 """
137207
138208 spec_name_list = []
139- n_spec , sv1_list , ar1_list , sv2_list , ar2_list = get_spectra_list (dict )
209+ n_spec , sv1_list , ar1_list , sv2_list , ar2_list = get_spectra_list (dict , from_spec_nullgroups = from_spec_nullgroups )
140210 for sv1 , ar1 , sv2 , ar2 in zip (sv1_list , ar1_list , sv2_list , ar2_list ):
141211 spec_name_list += [f"{ sv1 } { delimiter } { ar1 } x{ sv2 } { delimiter } { ar2 } " ]
142212
0 commit comments