def process_calculus( data, input_tmp, mod, output_tmp, xcolumn, fcolumn, foo, newcolumn, scale=DEFAULT_SCALE, shift=DEFAULT_SHIFT, overwrite=False, verbose=False, ): """manages I/O for performing calculations on a large number of files """ N = len(data) for ind, eos in enumerate(data): tmp = {'moddraw': eos // mod, 'draw': eos} path = input_tmp % tmp if verbose: print(' %d/%d %s' % (ind + 1, N, path)) d, c = io.load(path) ans, cols = calculus(d, c, xcolumn, fcolumn, foo, newcolumn, scale=scale, shift=shift, overwrite=overwrite) new = output_tmp % tmp if verbose: print(' writing: ' + new) newdir = os.path.dirname(new) if not os.path.exists(newdir): try: os.makedirs(newdir) except OSError: pass ### directory already exists io.write(new, ans, cols) ### save the result to the same file
def process2count( data, tmp, mod, reference_column, verbose=False, ): """handles I/O and extracts the number of lines in a particular file (like the number of branches, etc) """ N = len(data) ans = np.empty(N, dtype=int) for i, eos in enumerate(data): path = tmp % {'moddraw': eos // mod, 'draw': eos} if verbose: print(' %d/%d %s' % (i + 1, N, path)) d, _ = io.load(path, [reference_column]) ans[i] = data2count(d) return ans, COUNT_TEMPLATE % reference_column
def process2sequences(eos, eostmp, mactmp, min_central_pressurec2, max_central_pressurec2, central_baryon_density_range=None, central_energy_densityc2_range=None, mod=1000, pressurec2_column=DEFAULT_PRESSUREC2_COLUMN, energy_densityc2_column=DEFAULT_ENERGY_DENSITYC2_COLUMN, baryon_density_column=DEFAULT_BARYON_DENSITY_COLUMN, cs2c2_column=None, central_eos_column=[], central_column_template=DEFAULT_CENTRAL_COLUMN_TEMPLATE, formalism=DEFAULT_FORMALISM, verbose=False, Verbose=False, **kwargs): '''integrate stellar models for a whole set of EoS in a process ''' verbose |= Verbose for draw in eos: tmp = {'draw': draw, 'moddraw': draw // mod} eospath = eostmp % tmp if verbose: print('loading EoS data from: ' + eospath) cols = [ pressurec2_column, energy_densityc2_column, baryon_density_column ] if cs2c2_column is not None: cols.append(cs2c2_column) data, cols = io.load( eospath, cols + central_eos_column ) ### NOTE: this will not produce duplicated columns pressurec2 = data[:, cols.index(pressurec2_column)] energy_densityc2 = data[:, cols.index(energy_densityc2_column)] baryon_density = data[:, cols.index(baryon_density_column)] if cs2c2_column is not None: cs2c2 = data[:, cols.index(cs2c2_column)] else: cs2c2 = utils.num_dfdx(energy_densityc2, pressurec2) ### get local copy of bounds for just this EoS max_central_pc2 = max_central_pressurec2 min_central_pc2 = min_central_pressurec2 ### sanity check that our integration range is compatible with the EoS data available max_pressurec2 = np.max(pressurec2) if max_central_pc2 > max_pressurec2: if verbose: print( 'limitting central_pressurec2 <= %.6e based on EoS data\'s range' % max_pressurec2) max_central_pc2 = max_pressurec2 min_pressurec2 = np.min(pressurec2) if min_central_pc2 < min_pressurec2: if verbose: print( 'limitting central_pressurec2 >= %.6e based on EoS data\'s range' % min_pressurec2) min_central_pc2 = min_pressurec2 ### additionally check whether we're obeying the requested bounds on central baryon and energy densities if central_baryon_density_range is not None: min_baryon_density, max_baryon_density = central_baryon_density_range # check minimum min_pc2 = np.interp(min_baryon_density, baryon_density, pressurec2) if min_pc2 > min_central_pc2: if verbose: print( 'limitting central_pressurec2 >= %.6e based on min_baryon_density = %.6e' % (min_pc2, min_baryon_density)) min_central_pc2 = min_pc2 # check maximum max_pc2 = np.interp(max_baryon_density, baryon_density, pressurec2) if max_pc2 < max_central_pc2: if verbose: print( 'limitting central_pressurec2 <= %.6e based on max_baryon_density = %.6e' % (max_pc2, max_baryon_density)) max_central_pc2 = max_pc2 if central_energy_densityc2_range is not None: min_energy_densityc2, max_energy_densityc2 = central_energy_densityc2_range # check minimum min_pc2 = np.interp(min_energy_densityc2, energy_densityc2, pressurec2) if min_pc2 > min_central_pc2: if verbose: print( 'limitting central_pressurec2 >= %.6e based on min_energy_densityc2 = %.6e' % (min_pc2, min_energy_densityc2)) min_central_p2 = min_pc2 # check maximum max_pc2 = np.interp(max_baryon_density, energy_densityc2, pressurec2) if max_pc2 < max_central_pc2: if verbose: print( 'limitting central_pressurec2 <= %.6e based on max_energy_densityc2 = %.6e' % (max_pc2, max_energy_densityc2)) max_central_pc2 = max_pc2 ### check to make sure the pressure bounds are sane, futz them if they are not if max_central_pc2 < min_central_pc2: if verbose: print( '''WARNING: central pressure bounds are out of order! Reverting to original bounds! min_central_pressurec2 = %.6e max_central_pressurec2 = %.6e''' % (min_central_pressurec2, max_central_pressurec2)) min_central_pc2, max_central_pc2 = min_central_pressurec2, max_central_pressurec2 if verbose: print('''proceeding with central pressure bounds: min_central_pressurec2 = %.6e max_central_pressurec2 = %.6e''' % (min_central_pc2, max_central_pc2)) ### now compute the stellar sequence if verbose: print('solving for sequence of stellar models with formalism=%s' % formalism) central_pressurec2, macro, macro_cols = stellar_sequence( min_central_pc2, max_central_pc2, (pressurec2, energy_densityc2, baryon_density, cs2c2), verbose=Verbose, formalism=formalism, **kwargs) if verbose: print(' evaluated %d stellar models' % len(central_pressurec2)) sequence, columns = append_central_values( central_pressurec2, pressurec2, data, cols, macro, macro_cols, central_eos_column=central_eos_column, central_column_template=central_column_template, verbose=verbose, ) ### write the output macpath = mactmp % tmp if verbose: print('writing stellar sequence to: ' + macpath) io.write(macpath, sequence, columns)
def process2branch_properties( data, eos_template, eos_num_per_dir, mac_template, macro_num_per_dir, summary_template, eos_rho, macro_rhoc, macro_mass, output_eos_columns=DEFAULT_EOS_COLUMNS, output_macro_columns=DEFAULT_MACRO_COLUMNS, branch_template=None, verbose=False, ): """extract the branches for each EoS specified """ tmp = dict() if branch_template is not None: # do this backflip to make sure we can build string correctly branch_template = branch_template.replace('%(branch)06d', '%(branch_string)s') tmp['branch_string'] = '%(branch)06d' N = len(data) for ind, eos in enumerate(data): ### construct paths # where we're going to read in data eos_path = eos_template % { 'moddraw': eos // eos_num_per_dir, 'draw': eos } tmp.update({'moddraw': eos // macro_num_per_dir, 'draw': eos}) mac_path = mac_template % tmp # where we're going to write data sum_path = summary_template % tmp if verbose: print(' %d/%d' % (ind + 1, N)) print(' loading macro: %s' % mac_path) mac_data, mac_cols = io.load( mac_path, [macro_rhoc, macro_mass] + output_macro_columns ) ### NOTE: we load all columns because we're going to re-write them all into subdir as separate branches if verbose: print(' loading eos: %s' % eos_path) eos_data, eos_cols = io.load( eos_path, [eos_rho] + output_eos_columns ) ### NOTE: this guarantees that eos_rho is the first column! baryon_density = eos_data[:, 0] ### separate this for convenience # use macro data to identify separate stable branches # NOTE: we expect this to be ordered montonically in rhoc M = mac_data[:, mac_cols.index(macro_mass)] rhoc = mac_data[:, mac_cols.index(macro_rhoc)] if branch_template is not None: branch_tmp = branch_template % tmp else: branch_tmp = None params, names = data2branch_properties( rhoc, M, baryon_density, mac_data, mac_cols, eos_data, eos_cols, branch_template=branch_tmp, verbose=verbose, ) if verbose: print(' writing summary into: %s' % sum_path) newdir = os.path.dirname(sum_path) if not os.path.exists(newdir): try: os.makedirs(newdir) except OSError: pass ### directory already exists io.write(sum_path, params, names)
def process2extrema( data, tmp, mod, columns, static_ranges=None, dynamic_minima=None, dynamic_maxima=None, verbose=False, ): """manages I/O and extracts max, min for the specified columns """ N = len(data) Ncol = len(columns) loadcolumns = columns[:] if static_ranges is not None: loadcolumns += [ key for key in static_ranges.keys() if key not in loadcolumns ] ### avoid duplicates static_ranges = [(loadcolumns.index(column), val) for column, val in static_ranges.items()] else: static_ranges = [] if dynamic_minima is not None: for val in dynamic_minima.values(): assert len( val) == N, 'dynamic minima must have the same length as data' loadcolumns += [ key for key in dynamic_minima.keys() if key not in loadcolumns ] dynamic_minima = [(loadcolumns.index(key), val) for key, val in dynamic_minima.items()] else: dynamic_minima = [] if dynamic_maxima is not None: for val in dynamic_maxima.values(): assert len( val) == N, 'dynamic minima must have the same length as data' loadcolumns += [ key for key in dynamic_maxima.keys() if key not in loadcolumns ] dynamic_maxima = [(loadcolumns.index(key), val) for key, val in dynamic_maxima.items()] else: dynamic_maxima = [] ans = np.empty((N, 2 * len(columns)), dtype=float) for i, eos in enumerate(data): path = tmp % {'moddraw': eos // mod, 'draw': eos} if verbose: sys.stdout.write('\r %d/%d %s' % (i + 1, N, path)) sys.stdout.flush() d, _ = io.load(path, loadcolumns) minima = [(j, val[i]) for j, val in dynamic_minima] maxima = [(j, val[i]) for j, val in dynamic_maxima] ans[i] = data2extrema(d, Ncol, static_ranges=static_ranges, dynamic_minima=minima, dynamic_maxima=maxima) if verbose: sys.stdout.write('\n') sys.stdout.flush() return ans
def process2moi_features( data, eos_template, eos_num_per_dir, mac_template, macro_num_per_dir, summary_template, eos_rho, eos_cs2c2, macro_rhoc, macro_mass, macro_moi, output_eos_columns=DEFAULT_EOS_COLUMNS, output_macro_columns=DEFAULT_MACRO_COLUMNS, flatten_thr=DEFAULT_FLATTEN_THR, smoothing_width=DEFAULT_SMOOTHING_WIDTH, diff_thr=DEFAULT_DIFF_THR, cs2c2_cofactor=DEFAULT_CS2C2_COFACTOR, verbose=False, ): """extract the branches for each EoS specified """ N = len(data) for ind, eos in enumerate(data): ### construct paths # where we're going to read in data eos_path = eos_template % { 'moddraw': eos // eos_num_per_dir, 'draw': eos } tmp = {'moddraw': eos // macro_num_per_dir, 'draw': eos} mac_path = mac_template % tmp # where we're going to write data sum_path = summary_template % tmp if verbose: print(' %d/%d' % (ind + 1, N)) print(' loading macro: %s' % mac_path) mac_data, mac_cols = io.load( mac_path, [macro_rhoc, macro_mass, macro_moi] + output_macro_columns ) ### NOTE: we load all columns because we're going to re-write them all into subdir as separate branches if verbose: print(' loading eos: %s' % eos_path) eos_data, eos_cols = io.load( eos_path, [eos_rho, eos_cs2c2] + output_eos_columns ) ### NOTE: this guarantees that eos_rho is the first column! baryon_density = eos_data[:, eos_cols.index( eos_rho)] ### separate this for convenience cs2c2 = eos_data[:, eos_cols.index(eos_cs2c2)] # use macro data to identify separate stable branches # NOTE: we expect this to be ordered montonically in rhoc M = mac_data[:, mac_cols.index(macro_mass)] I = mac_data[:, mac_cols.index(macro_moi)] rhoc = mac_data[:, mac_cols.index(macro_rhoc)] params, names = data2moi_features( rhoc, M, I, baryon_density, cs2c2, mac_data, mac_cols, eos_data, eos_cols, flatten_thr=flatten_thr, smoothing_width=smoothing_width, diff_thr=diff_thr, cs2c2_cofactor=cs2c2_cofactor, verbose=verbose, ) if verbose: print( ' writing summary of %d identified moi-features into: %s' % (len(params), sum_path)) io.write(sum_path, params, names)
def process2samples( data, tmp, mod, xcolumn, ycolumns, static_x_test=None, dynamic_x_test=None, x_multiplier=1., verbose=False, selection_rule=DEFAULT_SELECTION_RULE, branches_mapping=None, default_values=None, ): """manages I/O and extracts samples at the specified places returns an array that is ordered as follows for each ycolumn: for each static x_test """ loadcolumns = [xcolumn] + ycolumns if static_x_test is None: static_x_test = [] static_x_test = list(static_x_test) ### make sure this is a list Nref = len(static_x_test) if dynamic_x_test is not None: assert len(dynamic_x_test) == len(data) Ndyn = np.shape(dynamic_x_test)[1] else: Ndyn = 0 Ntot = Nref + Ndyn assert Ntot > 0, 'must provide at least one static_x_test or dynamic_x_test' if (Nref > 0) and (selection_rule == 'nearest_neighbor'): print( 'WARNING! selection_rule="nearest_neighbor" may not be safe when specifying static_x_test. \ Instead, please use it only with dynamic_x_test that correspond to the exact values of individual samples \ that have already been extracted from the curves (e.g., the maximum)') if branches_mapping is not None: assert default_values is not None, 'must specify default_values when branches_mapping is not None' assert len(default_values) == len( ycolumns), 'must specify exactly 1 default value for each ycolumn!' branches_tmp, affine, affine_start, affine_stop = branches_mapping loadcolumns.append(affine) else: branches_tmp = None N = len(data) ans = np.empty((N, (Nref + Ndyn) * len(ycolumns)), dtype=float) for i, eos in enumerate(data): path = tmp % {'moddraw': eos // mod, 'draw': eos} if verbose: sys.stdout.write('\r %d/%d %s' % (i + 1, N, path)) sys.stdout.flush() d, c = io.load(path, loadcolumns) if branches_mapping is not None: a = d[:, c.index(affine)] x = d[:, c.index(xcolumn)] * x_multiplier d = d[:, [c.index(col) for col in ycolumns]] if branches_tmp is not None: branches_path = branches_tmp % {'moddraw': eos // mod, 'draw': eos} if verbose: sys.stdout.write('\r %d/%d %s' % (i + 1, N, branches_path)) sys.stdout.flush() b, _ = io.load(branches_path, [affine_start, affine_stop]) branches = [(start <= a) * (a <= stop) for start, stop in b ] ### define booleans to represent branches else: branches = None x_test = static_x_test + (list(dynamic_x_test[i]) if dynamic_x_test is not None else []) ans[i] = data2samples( x, d, x_test, selection_rule=selection_rule, branches=branches, default_values=default_values, ) if verbose: sys.stdout.write('\n') sys.stdout.flush() return ans
def set_crust(crust_eos=DEFAULT_CRUST_EOS): global CRUST_PRESSUREC2, CRUST_ENERGY_DENSITYC2, CRUST_BARYON_DENSITY CRUST_PRESSUREC2, CRUST_ENERGY_DENSITYC2, CRUST_BARYON_DENSITY = \ load(eospaths.get(crust_eos, crust_eos), columns=['pressurec2', 'energy_densityc2', 'baryon_density'])[0].transpose()