@@ -163,111 +163,140 @@ def noise_coeval_power_spectrum_1d(ncells, z, depth_mhz, obs_time=1000, subarray
163163
164164def get_uv_map_lightcone (ncells , zs , subarray_type = "AA4" , total_int_time = 6. , int_time = 10. , boxsize = None , declination = - 30. ,
165165 save_uvmap = None , n_jobs = 4 , verbose = True , checkpoint = 16 ):
166- """
167- Generates or loads a lightcone of UV coverage maps, one for each redshift.
166+ """
167+ Generates or loads a lightcone of UV coverage maps, one for each redshift.
168168
169- This function handles the creation of UV maps across a range of redshifts,
170- using parallel processing for efficiency and providing an option to cache
171- the results to a file to speed up subsequent runs.
169+ This function handles the creation of UV maps across a range of redshifts,
170+ using parallel processing for efficiency and providing an option to cache
171+ the results to a file to speed up subsequent runs.
172172
173- Parameters
174- ----------
175- ncells : int
176- The number of grid cells.
177- zs : np.ndarray or list
178- An array or list of redshift values for the lightcone.
179- subarray_type, total_int_time, etc. : various, optional
180- Observational parameters passed to `get_uv_map`.
181- save_uvmap : str, optional
182- File path to save or load the UV map dictionary. If the file exists,
183- maps are loaded; otherwise, they are generated and saved.
184- n_jobs : int, optional
185- Number of CPUs for parallel generation of UV maps.
186- verbose : bool, optional
187- If True, enables progress bars and informational messages.
188- checkpoint : int, optional
189- If provided, the number of redshifts to process before saving the results
190- to `save_uvmap`. This is useful for long runs to prevent data loss.
173+ Parameters
174+ ----------
175+ ncells : int
176+ The number of grid cells.
177+ zs : np.ndarray or list
178+ An array or list of redshift values for the lightcone.
179+ subarray_type, total_int_time, etc. : various, optional
180+ Observational parameters passed to `get_uv_map`.
181+ save_uvmap : str, optional
182+ File path to save or load the UV map dictionary. If the file exists,
183+ maps are loaded; otherwise, they are generated and saved.
184+ n_jobs : int, optional
185+ Number of CPUs for parallel generation of UV maps.
186+ verbose : bool, optional
187+ If True, enables progress bars and informational messages.
188+ checkpoint : int, optional
189+ If provided, the number of redshifts to process before saving the results
190+ to `save_uvmap`. This is useful for long runs to prevent data loss.
191191
192- Returns
193- -------
194- dict
195- A dictionary containing the UV maps for each redshift, keyed by the
196- redshift value formatted to three decimal places, along with metadata
197- about the simulation parameters.
198- """
199- antxyz , N_ant = subarray_type_to_antxyz (subarray_type , verbose = verbose )
200- if boxsize is None : boxsize = conv .LB
201- if isinstance (zs , list ): zs = np .array (zs )
192+ Returns
193+ -------
194+ dict
195+ A dictionary containing the UV maps for each redshift, keyed by the
196+ redshift value formatted to three decimal places, along with metadata
197+ about the simulation parameters.
198+ """
199+ antxyz , N_ant = subarray_type_to_antxyz (subarray_type , verbose = verbose )
200+ if boxsize is None : boxsize = conv .LB
201+ if isinstance (zs , list ): zs = np .array (zs )
202+
203+ # Define a dictionary of simulation parameters
204+ params = {
205+ 'ncells' : ncells ,
206+ 'boxsize' : boxsize ,
207+ 'total_int_time' : total_int_time ,
208+ 'int_time' : int_time ,
209+ 'declination' : declination ,
210+ 'subarray_type' : subarray_type ,
211+ 'N_ant' : N_ant ,
212+ }
213+
214+ # Attempt to load existing UV maps
215+ if save_uvmap and os .path .exists (save_uvmap ):
216+ if verbose : print (f"Loading existing UV maps from { save_uvmap } " )
217+ uvs = read_dictionary_data (save_uvmap )
218+
219+ # Validate using the params dictionary
220+ mismatches = []
221+ for key , current_val in params .items ():
222+ cached_val = uvs .get (key )
223+ # Check for a mismatch
224+ if cached_val is not None and cached_val != current_val :
225+ # Add the error message to a list instead of raising immediately
226+ mismatch_msg = f" - '{ key } ': Cached value is '{ cached_val } ', but current call requested '{ current_val } '."
227+ mismatches .append (mismatch_msg )
228+
229+ if mismatches :
230+ all_errors = "\n " .join (mismatches )
231+ raise ValueError (
232+ f"Parameter mismatches found in cached file '{ save_uvmap } ':\n "
233+ f"{ all_errors } \n "
234+ f"Please use a different save_uvmap path or delete the old file."
235+ )
236+ else :
237+ # Initialize from the defined dictionary
238+ uvs = params .copy ()
202239
203- # Attempt to load existing UV maps or initialize a new dictionary
204- if save_uvmap and os .path .exists (save_uvmap ):
205- if verbose : print (f"Loading existing UV maps from { save_uvmap } " )
206- uvs = read_dictionary_data (save_uvmap )
207- else :
208- uvs = {'ncells' : ncells , 'boxsize' : boxsize , 'total_int_time' : total_int_time , 'int_time' : int_time , 'declination' : declination }
209-
210- # Identify which redshifts need a UV map to be generated
211- z_to_run = [zi for zi in zs if '{:.3f}' .format (zi ) not in uvs ]
240+ # Identify which redshifts need a UV map to be generated
241+ z_to_run = [zi for zi in zs if '{:.3f}' .format (zi ) not in uvs ]
212242
213- if z_to_run :
214- if verbose : print (f'Found { len (z_to_run )} new redshifts to generate UV maps for.' )
215-
216- # Define the worker function for a single redshift
217- _uvmap_worker = lambda zi : get_uv_map (ncells , zi , subarray_type = antxyz , total_int_time = total_int_time , int_time = int_time , boxsize = boxsize , declination = declination , verbose = False )[0 ]
218-
219- # Condition for using chunked parallel processing with checkpoints
220- use_chunked_parallel = n_jobs > 1 and checkpoint is not None and checkpoint > 0
221-
222- if use_chunked_parallel :
223- num_chunks = (len (z_to_run ) + checkpoint - 1 ) // checkpoint
224- if verbose : print (f"Processing in { num_chunks } chunks of size up to { checkpoint } ..." )
225-
226- for i in tqdm (range (0 , len (z_to_run ), checkpoint ), desc = "Processing Chunks" , disable = not verbose ):
227- z_chunk = z_to_run [i :i + checkpoint ]
228-
229- # Run the parallel job on the current chunk
230- # Set inner verbose to 0 to avoid clutter; outer tqdm handles progress
231- results_chunk = Parallel (n_jobs = n_jobs , verbose = 0 )(delayed (_uvmap_worker )(zi ) for zi in z_chunk )
232-
233- # Update the main dictionary with the results from the chunk
234- for zi , uv_map in zip (z_chunk , results_chunk ):
235- uvs ['{:.3f}' .format (zi )] = uv_map
236-
237- # Save after processing the chunk
238- if save_uvmap :
239- if verbose : print (f"\n Checkpoint: Saving results to { save_uvmap } " )
240- write_dictionary_data (uvs , save_uvmap )
241-
242- else : # Original behavior: either sequential or parallel without checkpoints
243- if n_jobs > 1 :
244- # Parallel processing for all z's at once
245- if verbose : print (f"Generating all { len (z_to_run )} maps in parallel..." )
246- results = Parallel (n_jobs = n_jobs , verbose = 10 if verbose else 0 )(delayed (_uvmap_worker )(i ) for i in z_to_run )
247- for zi , uv_map in zip (z_to_run , results ):
248- uvs ['{:.3f}' .format (zi )] = uv_map
249- else :
250- # Sequential processing
251- iterator = tqdm (z_to_run , desc = "Generating UV maps sequentially" , disable = not verbose )
252- for i , zi in enumerate (iterator ):
253- uvs ['{:.3f}' .format (zi )] = _uvmap_worker (zi )
254- # Checkpoint logic for sequential mode
255- is_checkpoint_step = checkpoint and (i + 1 ) % checkpoint == 0
256- is_not_last_step = (i + 1 ) < len (z_to_run )
257- if save_uvmap and is_checkpoint_step and is_not_last_step :
258- if verbose : print (f"\n Checkpoint: Saving results to { save_uvmap } " )
259- write_dictionary_data (uvs , save_uvmap )
260-
261- uvs ['Nant' ] = N_ant
262- # Final save to ensure the last chunk or the full result is written
263- if save_uvmap :
264- if verbose : print (f"Saving final updated UV maps to { save_uvmap } " )
265- write_dictionary_data (uvs , save_uvmap )
266-
267- elif verbose :
268- print ("All requested redshift UV maps are already present." )
269-
270- return uvs
243+ if z_to_run :
244+ if verbose : print (f'Found { len (z_to_run )} new redshifts to generate UV maps for.' )
245+
246+ # Define the worker function for a single redshift
247+ _uvmap_worker = lambda zi : get_uv_map (ncells , zi , subarray_type = antxyz , total_int_time = total_int_time , int_time = int_time , boxsize = boxsize , declination = declination , verbose = False )[0 ]
248+
249+ # Condition for using chunked parallel processing with checkpoints
250+ use_chunked_parallel = n_jobs > 1 and checkpoint is not None and checkpoint > 0
251+
252+ if use_chunked_parallel :
253+ num_chunks = (len (z_to_run ) + checkpoint - 1 ) // checkpoint
254+ if verbose : print (f"Processing in { num_chunks } chunks of size up to { checkpoint } ..." )
255+
256+ for i in tqdm (range (0 , len (z_to_run ), checkpoint ), desc = "Processing Chunks" , disable = not verbose ):
257+ z_chunk = z_to_run [i :i + checkpoint ]
258+
259+ # Run the parallel job on the current chunk
260+ # Set inner verbose to 0 to avoid clutter; outer tqdm handles progress
261+ results_chunk = Parallel (n_jobs = n_jobs , verbose = 0 )(delayed (_uvmap_worker )(zi ) for zi in z_chunk )
262+
263+ # Update the main dictionary with the results from the chunk
264+ for zi , uv_map in zip (z_chunk , results_chunk ):
265+ uvs ['{:.3f}' .format (zi )] = uv_map
266+
267+ # Save after processing the chunk
268+ if save_uvmap :
269+ if verbose : print (f"\n Checkpoint: Saving results to { save_uvmap } " )
270+ write_dictionary_data (uvs , save_uvmap )
271+
272+ else : # Original behavior: either sequential or parallel without checkpoints
273+ if n_jobs > 1 :
274+ # Parallel processing for all z's at once
275+ if verbose : print (f"Generating all { len (z_to_run )} maps in parallel..." )
276+ results = Parallel (n_jobs = n_jobs , verbose = 10 if verbose else 0 )(delayed (_uvmap_worker )(i ) for i in z_to_run )
277+ for zi , uv_map in zip (z_to_run , results ):
278+ uvs ['{:.3f}' .format (zi )] = uv_map
279+ else :
280+ # Sequential processing
281+ iterator = tqdm (z_to_run , desc = "Generating UV maps sequentially" , disable = not verbose )
282+ for i , zi in enumerate (iterator ):
283+ uvs ['{:.3f}' .format (zi )] = _uvmap_worker (zi )
284+ # Checkpoint logic for sequential mode
285+ is_checkpoint_step = checkpoint and (i + 1 ) % checkpoint == 0
286+ is_not_last_step = (i + 1 ) < len (z_to_run )
287+ if save_uvmap and is_checkpoint_step and is_not_last_step :
288+ if verbose : print (f"\n Checkpoint: Saving results to { save_uvmap } " )
289+ write_dictionary_data (uvs , save_uvmap )
290+
291+ # Final save to ensure the last chunk or the full result is written
292+ if save_uvmap :
293+ if verbose : print (f"Saving final updated UV maps to { save_uvmap } " )
294+ write_dictionary_data (uvs , save_uvmap )
295+
296+ elif verbose :
297+ print ("All requested redshift UV maps are already present." )
298+
299+ return uvs
271300
272301def noise_map (ncells , z , depth_mhz , obs_time = 1000 , subarray_type = "AA4" , boxsize = None , total_int_time = 6. , int_time = 10. , declination = - 30. , uv_map = None , N_ant = None , uv_weighting = 'natural' , sefd_data = None , nu_data = None , fft_wrap = False , verbose = True , suppress_sharp_features_uv_map = False ):
273302 """
0 commit comments