diff --git a/__init__.py b/__init__.py deleted file mode 100644 index 06d7405..0000000 Binary files a/__init__.py and /dev/null differ diff --git a/sbmy_control.egg-info/PKG-INFO b/sbmy_control.egg-info/PKG-INFO new file mode 100644 index 0000000..f3ef9c4 --- /dev/null +++ b/sbmy_control.egg-info/PKG-INFO @@ -0,0 +1,35 @@ +Metadata-Version: 2.4 +Name: sbmy_control +Version: 0.1.0 +Summary: Simbelmyne control package +Home-page: https://git.aquila-consortium.org/maubin/sbmy_control +Author: Mayeul Aubin +Author-email: mayeul.aubin@iap.fr +License: GPL-3.0 +Classifier: Development Status :: 3 - Alpha +Classifier: Intended Audience :: Science/Research +Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3) +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 +Classifier: Programming Language :: Python :: 3.11 +Requires-Python: >=3.8 +Description-Content-Type: text/markdown +Requires-Dist: pysbmy +Requires-Dist: numpy +Requires-Dist: matplotlib +Requires-Dist: h5py +Requires-Dist: tqdm +Dynamic: author +Dynamic: author-email +Dynamic: classifier +Dynamic: description +Dynamic: description-content-type +Dynamic: home-page +Dynamic: license +Dynamic: requires-dist +Dynamic: requires-python +Dynamic: summary + +This package provides control functionalities for Simbelmyne. It allows to create automatically all the required files and scripts to run a N-body simulation with Simbelmyne, using monofonIC for initial conditions. The subpackage `analysis` provides tools to analyze the results of the simulation (slices and power spectra), while the subpackage `scripts` includes tools to handle snapshots, tiles and density fields. diff --git a/sbmy_control.egg-info/SOURCES.txt b/sbmy_control.egg-info/SOURCES.txt new file mode 100644 index 0000000..5fadffd --- /dev/null +++ b/sbmy_control.egg-info/SOURCES.txt @@ -0,0 +1,30 @@ +setup.py +sbmy_control/ICs.py +sbmy_control/__init__.py +sbmy_control/args_main.py +sbmy_control/cosmo_params.py +sbmy_control/low_level.py +sbmy_control/main.py +sbmy_control/monofonic.py +sbmy_control/parameters_card.py +sbmy_control/parameters_monofonic.py +sbmy_control/progress_bar.py +sbmy_control/scola.py +sbmy_control/simbelmyne.py +sbmy_control/slurm_submission.py +sbmy_control/timestepping.py +sbmy_control.egg-info/PKG-INFO +sbmy_control.egg-info/SOURCES.txt +sbmy_control.egg-info/dependency_links.txt +sbmy_control.egg-info/entry_points.txt +sbmy_control.egg-info/requires.txt +sbmy_control.egg-info/top_level.txt +sbmy_control/analysis/__init__.py +sbmy_control/analysis/colormaps.py +sbmy_control/analysis/power_spectrum.py +sbmy_control/analysis/slices.py +sbmy_control/scripts/__init__.py +sbmy_control/scripts/convert_snapshot_to_density.py +sbmy_control/scripts/field_to_field.py +sbmy_control/scripts/gather_tiles.py +sbmy_control/scripts/scola_submit.py \ No newline at end of file diff --git a/sbmy_control.egg-info/dependency_links.txt b/sbmy_control.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/sbmy_control.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/sbmy_control.egg-info/entry_points.txt b/sbmy_control.egg-info/entry_points.txt new file mode 100644 index 0000000..2481b2f --- /dev/null +++ b/sbmy_control.egg-info/entry_points.txt @@ -0,0 +1,8 @@ +[console_scripts] +convert_snapshot_to_density = sbmy_control.scripts.convert_snapshot_to_density:console_main +field_to_field = sbmy_control.scripts.field_to_field:console_main +gather_tiles = sbmy_control.scripts.gather_tiles:console_main +power_spectrum = sbmy_control.analysis.power_spectrum:console_main +sbmy_control = sbmy_control.main:console_main +scola_submit = sbmy_control.scripts.scola_submit:console_main +slices = sbmy_control.analysis.slices:console_main diff --git a/sbmy_control.egg-info/requires.txt b/sbmy_control.egg-info/requires.txt new file mode 100644 index 0000000..ad720a3 --- /dev/null +++ b/sbmy_control.egg-info/requires.txt @@ -0,0 +1,5 @@ +pysbmy +numpy +matplotlib +h5py +tqdm diff --git a/sbmy_control.egg-info/top_level.txt b/sbmy_control.egg-info/top_level.txt new file mode 100644 index 0000000..8f3970f --- /dev/null +++ b/sbmy_control.egg-info/top_level.txt @@ -0,0 +1 @@ +sbmy_control diff --git a/.gitignore b/sbmy_control/.gitignore similarity index 100% rename from .gitignore rename to sbmy_control/.gitignore diff --git a/ICs.py b/sbmy_control/ICs.py similarity index 100% rename from ICs.py rename to sbmy_control/ICs.py diff --git a/analysis/__init__.py b/sbmy_control/__init__.py similarity index 100% rename from analysis/__init__.py rename to sbmy_control/__init__.py diff --git a/scripts/__init__.py b/sbmy_control/analysis/__init__.py similarity index 100% rename from scripts/__init__.py rename to sbmy_control/analysis/__init__.py diff --git a/analysis/colormaps.py b/sbmy_control/analysis/colormaps.py similarity index 100% rename from analysis/colormaps.py rename to sbmy_control/analysis/colormaps.py diff --git a/analysis/power_spectrum.py b/sbmy_control/analysis/power_spectrum.py similarity index 98% rename from analysis/power_spectrum.py rename to sbmy_control/analysis/power_spectrum.py index 9d44005..f47466e 100644 --- a/analysis/power_spectrum.py +++ b/sbmy_control/analysis/power_spectrum.py @@ -1,4 +1,5 @@ import numpy as np +import os kmin = 1e-1 kmax = 2e0 @@ -262,7 +263,9 @@ def get_ylims_and_yticks(ylims): return ylims, yticks -if __name__ == "__main__": + + +def console_main(): from argparse import ArgumentParser parser = ArgumentParser(description='Plot power spectra of fields') @@ -286,6 +289,10 @@ if __name__ == "__main__": if not args.power_spectrum and not args.cross_correlation: print('You must choose between power_spectrum and cross_correlation.') exit() + + for _k,f in enumerate(args.filenames): + if not os.path.exists(args.directory+f): + raise FileNotFoundError(f"File {args.directory+f} does not exist.") if args.reference is not None: from pysbmy.field import read_field @@ -398,5 +405,8 @@ if __name__ == "__main__": fig.savefig(args.output) else: fig.savefig(args.directory+'power_spectrum.png') - + +if __name__ == "__main__": + console_main() + \ No newline at end of file diff --git a/analysis/slices.py b/sbmy_control/analysis/slices.py similarity index 95% rename from analysis/slices.py rename to sbmy_control/analysis/slices.py index 2febe16..cb78bbc 100755 --- a/analysis/slices.py +++ b/sbmy_control/analysis/slices.py @@ -1,6 +1,7 @@ import numpy as np import sys +import os sys.path.append('/home/aubin/Simbelmyne/sbmy_control/') fs = 18 @@ -10,11 +11,11 @@ def add_ax_ticks(ax, ticks, tick_labels): from matplotlib import ticker ax.set_xticks(ticks) ax.set_yticks(ticks) - ax.set_xticklabels(tick_labels) - ax.set_yticklabels(tick_labels) + ax.set_xticklabels([int(t) for t in tick_labels]) + ax.set_yticklabels([int(t) for t in tick_labels]) ax.set_xlabel('Mpc/h') - ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%d')) - ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%d')) + # ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%d')) # Does not work + # ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%d')) @@ -53,7 +54,7 @@ def plot_imshow_with_reference( data_list, sep = 10 if L[0] < 50 else 20 if L[0] < 100 else 50 if L[0]<250 else 100 if L[0] < 500 else 200 if L[0] < 1000 else 500 if L[0] < 2500 else 1000 ticks = [np.arange(0, l+1, sep)*len(dat)/l for l, dat in zip(L,data_list)] tick_labels = [np.arange(0, l+1, sep) for l in L] - + def score(data, reference): return np.linalg.norm(data-reference)/np.linalg.norm(reference) @@ -148,8 +149,7 @@ def plot_imshow_diff(data_list, return fig, axes - -if __name__ == "__main__": +def console_main(): from argparse import ArgumentParser parser = ArgumentParser(description='Comparisons of fields slices.') @@ -177,6 +177,8 @@ if __name__ == "__main__": ref_field = read_field(args.directory+args.reference) if args.reference is not None else None fields = [] for k,f in enumerate(args.filenames): + if not os.path.exists(args.directory+f): + raise FileNotFoundError(f"File {args.directory+f} does not exist.") if args.reference is not None and f == args.reference: fields.append(ref_field) # Simply copy the reference field instead of reading it again if args.labels is not None: @@ -220,3 +222,8 @@ if __name__ == "__main__": fig.savefig(args.output,bbox_inches='tight') else: fig.savefig(args.directory+'slices.jpg',bbox_inches='tight') + + + +if __name__ == "__main__": + console_main() diff --git a/args_main.py b/sbmy_control/args_main.py similarity index 100% rename from args_main.py rename to sbmy_control/args_main.py diff --git a/cosmo_params.py b/sbmy_control/cosmo_params.py similarity index 100% rename from cosmo_params.py rename to sbmy_control/cosmo_params.py diff --git a/low_level.py b/sbmy_control/low_level.py similarity index 100% rename from low_level.py rename to sbmy_control/low_level.py diff --git a/main.py b/sbmy_control/main.py similarity index 99% rename from main.py rename to sbmy_control/main.py index 357f93a..a3e7859 100644 --- a/main.py +++ b/sbmy_control/main.py @@ -220,7 +220,7 @@ def check_consistency(card_dict, mode): raise ValueError(f"ModulePMCOLA is not 1: ModulePMCOLA={card_dict["ModulePMCOLA"]}") -if __name__ == "__main__": +def console_main(): from argparse import ArgumentParser from args_main import register_arguments_main from timestepping import register_arguments_timestepping, main_timestepping @@ -238,4 +238,9 @@ if __name__ == "__main__": register_arguments_card(parser) register_arguments_cosmo(parser) parsed_args = parser.parse_args() - main(parsed_args) \ No newline at end of file + main(parsed_args) + + +if __name__ == "__main__": + console_main() + \ No newline at end of file diff --git a/monofonic.py b/sbmy_control/monofonic.py similarity index 100% rename from monofonic.py rename to sbmy_control/monofonic.py diff --git a/parameters_card.py b/sbmy_control/parameters_card.py similarity index 100% rename from parameters_card.py rename to sbmy_control/parameters_card.py diff --git a/parameters_monofonic.py b/sbmy_control/parameters_monofonic.py similarity index 100% rename from parameters_monofonic.py rename to sbmy_control/parameters_monofonic.py diff --git a/progress_bar.py b/sbmy_control/progress_bar.py similarity index 100% rename from progress_bar.py rename to sbmy_control/progress_bar.py diff --git a/scola.py b/sbmy_control/scola.py similarity index 100% rename from scola.py rename to sbmy_control/scola.py diff --git a/sbmy_control/scripts/__init__.py b/sbmy_control/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/scripts/convert_snapshot_to_density.py b/sbmy_control/scripts/convert_snapshot_to_density.py similarity index 97% rename from scripts/convert_snapshot_to_density.py rename to sbmy_control/scripts/convert_snapshot_to_density.py index aed11ee..dadefed 100644 --- a/scripts/convert_snapshot_to_density.py +++ b/sbmy_control/scripts/convert_snapshot_to_density.py @@ -36,8 +36,7 @@ def convert_snapshot_to_density(snapshot_path, output_path, N=None, corner=(0.0, print("Done.") - -if __name__ == "__main__": +def console_main(): parser = argparse.ArgumentParser(description="Convert snapshot to density.") parser.add_argument( "-S", @@ -76,4 +75,8 @@ if __name__ == "__main__": output_path=args.output, N=args.N, corner=args.corner, - ) \ No newline at end of file + ) + + +if __name__ == "__main__": + console_main() \ No newline at end of file diff --git a/scripts/field_to_field.py b/sbmy_control/scripts/field_to_field.py similarity index 67% rename from scripts/field_to_field.py rename to sbmy_control/scripts/field_to_field.py index 236e283..c9137e2 100644 --- a/scripts/field_to_field.py +++ b/sbmy_control/scripts/field_to_field.py @@ -1,5 +1,5 @@ from pysbmy.density import mesh_to_mesh -from pysbmy.Field import Field, read_field +from pysbmy.field import Field, read_field import numpy as np import os @@ -8,23 +8,43 @@ def field_to_field( input_file:str, output_file:str, output_size:int|tuple[int,int,int]|list[int], + output_L:float|tuple[float,float,float]|list[float], output_dpm:float|tuple[float,float,float]|list[float], output_corner:tuple[float,float,float]|list[float], boundary_conditions:int, ): + ### Make sure all inputs are valid + if output_L is not None and output_dpm is not None: + raise ValueError("Either output_L or output_dpm can be specified, not both.") + if isinstance(output_size, int): output_size = (output_size, output_size, output_size) # N0, N1, N2 + elif len(output_size) == 1: + output_size = (output_size[0], output_size[0], output_size[0]) + + if output_L is not None: + if isinstance(output_L, float): + output_L = (output_L, output_L, output_L) + elif len(output_L) == 1: + output_L = (output_L[0], output_L[0], output_L[0]) - if isinstance(output_dpm, float): + if output_dpm is None: + if output_L is None: + output_dpm = (-1, -1, -1) + else: + output_dpm = (output_L[0] / output_size[0], output_L[1] / output_size[1], output_L[2] / output_size[2]) + elif isinstance(output_dpm, float): output_dpm = (output_dpm, output_dpm, output_dpm) # d0, d1, d2 - elif output_dpm is None: - output_dpm = (-1, -1, -1) + elif len(output_dpm) == 1: + output_dpm = (output_dpm[0], output_dpm[0], output_dpm[0]) if not os.path.exists(input_file): raise FileNotFoundError(f"Input file {input_file} does not exist.") + + # Read the input field print(f"Reading input field from {input_file}") input_field = read_field(input_file) @@ -59,9 +79,9 @@ def field_to_field( print(f"Output field size: {output_size[0]} x {output_size[1]} x {output_size[2]}") print(f"Input field dpm: {d0_in:.3f} x {d1_in:.3f} x {d2_in:.3f}") print(f"Output field dpm: {d0_out:.3f} x {d1_out:.3f} x {d2_out:.3f}") - print(f"Input field corner: {corner0:.1f} x {corner1:.1f} x {corner2:.1f}") - print(f"Output field corner: {output_corner[0]:.1f} x {output_corner[1]:.1f} x {output_corner[2]:.1f}") - print(f"Boundary conditions: {boundary_conditions}") + print(f"Input field corner: ({corner0:.1f}, {corner1:.1f}, {corner2:.1f})") + print(f"Output field corner: ({output_corner[0]:.1f}, {output_corner[1]:.1f}, {output_corner[2]:.1f})") + print(f"Boundary conditions: {'periodic' if boundary_conditions == 1 else 'non-periodic'}") print("-----------------------------------------") input_grid = input_field.data @@ -95,16 +115,20 @@ def field_to_field( print("Done.") - -if __name__ == "__main__": +def console_main(): import argparse parser = argparse.ArgumentParser(description="Convert a field from one size to another.") parser.add_argument("-i","--input_file", type=str, help="Input field file") parser.add_argument("-o","--output_file", type=str, help="Output field file") - parser.add_argument("-N","--output_size", type=int, nargs=3, help="Output field size (N0, N1, N2)") - parser.add_argument("-dpm","--output_dpm", type=float, nargs=3, default=None, help="Output field dpm (d0, d1, d2)") + parser.add_argument("-N","--output_size", type=int, nargs="+", help="Output field size (N0, N1, N2)") + parser.add_argument("-L","--output_L", type=float, nargs="+", default=None, help="Output field size (L0, L1, L2)") + parser.add_argument("-dpm","--output_dpm", type=float, nargs="+", default=None, help="Output field dpm (d0, d1, d2)") parser.add_argument("-corner","--output_corner", type=float, nargs=3, default=(0.,0.,0.), help="Output field corner (corner0, corner1, corner2)") - parser.add_argument("-BC","--boundary_conditions", type=int, default=1, help="Boundary conditions (0: periodic, 1: non-periodic)") + parser.add_argument("-BC","--boundary_conditions", type=int, default=1, help="Boundary conditions (1: periodic, 3: non-periodic)") args = parser.parse_args() - field_to_field(args.input_file, args.output_file, args.output_size, args.output_dpm, args.output_corner, args.boundary_conditions) \ No newline at end of file + field_to_field(args.input_file, args.output_file, args.output_size, args.output_L, args.output_dpm, args.output_corner, args.boundary_conditions) + + +if __name__ == "__main__": + console_main() \ No newline at end of file diff --git a/scripts/gather_tiles.py b/sbmy_control/scripts/gather_tiles.py similarity index 97% rename from scripts/gather_tiles.py rename to sbmy_control/scripts/gather_tiles.py index a71a273..13d3eda 100644 --- a/scripts/gather_tiles.py +++ b/sbmy_control/scripts/gather_tiles.py @@ -99,8 +99,7 @@ def gather_tiles(folder, tile_base, L, Np, N_TILES, buffer): - -if __name__ == "__main__": +def console_main(): parser = argparse.ArgumentParser(description="Gather density from tiles.") parser.add_argument("-d","--folder", type=str, default="./", help="Folder containing the tiles") parser.add_argument("--tile_base", type=str, default="sCOLA_tile", help="Base name of the tiles") @@ -121,4 +120,9 @@ if __name__ == "__main__": Np_tile = Np//N_TILES dpm = L/Np_tile - gather_tiles(folder, tile_base, L, Np, N_TILES, buffer) \ No newline at end of file + gather_tiles(folder, tile_base, L, Np, N_TILES, buffer) + + + +if __name__ == "__main__": + console_main() \ No newline at end of file diff --git a/scripts/scola_submit.py b/sbmy_control/scripts/scola_submit.py similarity index 98% rename from scripts/scola_submit.py rename to sbmy_control/scripts/scola_submit.py index d0b1007..e68e56f 100644 --- a/scripts/scola_submit.py +++ b/sbmy_control/scripts/scola_submit.py @@ -255,7 +255,7 @@ def check_previous_jobs(workdir,slurmdir,slurmfile,tilefile,sleeptime,job_ids_ar if os.path.exists(workdir+f"{tilefile}{prev_box}.h5"): job_status_categories['CP'].append(prev_box) # Classify as completed else: - resubmit_job(slurmdir,slurmfile,job_ids_array,prev_box,resubmit_count,error_count,MAX_RESUBMIT,MAX_ERRORS) + resubmit_count, error_count = resubmit_job(slurmdir,slurmfile,job_ids_array,prev_box,resubmit_count,error_count,MAX_RESUBMIT,MAX_ERRORS) job_status_categories[status].append(prev_box) # Classify as failed # Sleep for a while before resubmitting the next job time.sleep(sleeptime) @@ -445,6 +445,7 @@ def scola_submit(directory, job_status_categories, resubmit_count, error_count = check_previous_jobs(workdir,slurmdir,slurmfile,tilefile,sleep,job_ids_array,N_tiles**3+1,resubmit_count,error_count,MAX_RESUBMIT,MAX_ERRORS) + print_summary_job_status(job_status_categories, box, resubmit_count, error_count) # Now wait for all jobs to finish while len(job_status_categories['CP'])