Skip to content
Snippets Groups Projects
Commit 4308273f authored by David Hendriks's avatar David Hendriks
Browse files

Processed alot of what pylint suggested. Might change the naming conventions...

Processed alot of what pylint suggested. Might change the naming conventions rules tho, the short parameter names are an issue, but lets not get too strict..
parent 9388cc0c
No related branches found
No related tags found
No related merge requests found
"""
Module containing functions for the custom logging functionality.
The functions here make it possible for the user to define binaryc output logs on runtime
"""
import os
import textwrap
import subprocess
import socket
import ctypes
import random
import uuid
from binarycpython.utils.functions import temp_dir, remove_file
......@@ -11,24 +15,23 @@ from binarycpython.utils.functions import temp_dir, remove_file
def autogen_C_logging_code(logging_dict, verbose=0):
"""
Function that autogenerates PRINTF statements for binaryc.
Input is a dictionary where the key is the header of that logging line and items which are lists of parameters
that will be put in that logging line
Function that autogenerates PRINTF statements for binaryc.
Input is a dictionary where the key is the header of that logging line
and items which are lists of parameters that will be put in that logging line
Example::
{'MY_STELLAR_DATA':
[
'model.time',
'star[0].mass',
'model.probability',
'model.dt'
]
}
{'MY_STELLAR_DATA':
[
'model.time',
'star[0].mass',
'model.probability',
'model.dt'
]
}
"""
# Check if the input is of the correct form
if not type(logging_dict) == dict:
if not isinstance(logging_dict, dict):
print("Error: please use a dictionary as input")
return None
......@@ -44,7 +47,7 @@ def autogen_C_logging_code(logging_dict, verbose=0):
logging_dict_entry = logging_dict[key]
# Check if item is of correct type:
if type(logging_dict_entry) == list:
if isinstance(logging_dict_entry, list):
# Construct print statement
code += 'Printf("{}'.format(key)
......@@ -119,8 +122,8 @@ def binary_c_write_log_code(code, filename, verbose=0):
print("Writing the custom logging code to {}".format(filePath))
# Write again
with open(filePath, "w") as f:
f.write(code)
with open(filePath, "w") as file:
file.write(code)
def from_binary_c_config(config_file, flag):
......@@ -165,7 +168,6 @@ def return_compilation_dict(verbose=0):
# TODO: build in check to see whether the file exists
else:
raise NameError("Envvar BINARY_C doesnt exist")
return None
# TODO: make more options for the compiling
cc = from_binary_c_config(BINARY_C_CONFIG, "cc")
......@@ -195,14 +197,15 @@ def return_compilation_dict(verbose=0):
"ld": "ld", # 'ld': $Config{ld}, # default linker
"debug": 0,
"inc": "{} -I{}".format(bincincdirs, BINARY_C_SRC_DIR),
# inc => ' '.($Config{inc}//' ').' '.$bincincdirs." -I$srcdir ", # include the defaults plus # GSL and binary_c
# inc => ' '.($Config{inc}//' ').' '.$bincincdirs." -I$srcdir ",
# include the defaults plus # GSL and binary_c
# 'libname': libname, # libname is usually just binary_c corresponding to libbinary_c.so
"libs": binclibs,
}
# set values with defaults. TODO: make other input possile.
ld = defaults["ld"]
debug = defaults["debug"]
# debug = defaults["debug"]
inc = defaults[
"inc"
] # = ($ENV{BINARY_GRID2_INC} // $defaults{inc}).' '.($ENV{BINARY_GRID2_EXTRAINC} // '');
......@@ -211,7 +214,8 @@ def return_compilation_dict(verbose=0):
] # = ($ENV{BINARY_GRID2_LIBS} // $defaults{libs}).' '.($ENV{BINARY_GRID2_EXTRALIBS}//'');
ccflags = defaults[
"ccflags"
] # = $ENV{BINARY_GRID2_CCFLAGS} // ($defaults{ccflags}) . ($ENV{BINARY_GRID2_EXTRACCFLAGS} // '');
] # = $ENV{BINARY_GRID2_CCFLAGS}
# // ($defaults{ccflags}) . ($ENV{BINARY_GRID2_EXTRACCFLAGS} // '');
# you must define _SEARCH_H to prevent it being loaded twice
ccflags += " -shared -D_SEARCH_H"
......@@ -240,7 +244,6 @@ def return_compilation_dict(verbose=0):
def compile_shared_lib(code, sourcefile_name, outfile_name, verbose=0):
"""
Function to write the custom logging code to a file and then compile it.
TODO: nicely put in the -fPIC
"""
......@@ -289,7 +292,7 @@ def compile_shared_lib(code, sourcefile_name, outfile_name, verbose=0):
def create_and_load_logging_function(custom_logging_code, verbose=0):
"""
Function to automatically compile the shared library with the given
Function to automatically compile the shared library with the given
custom logging code and load it with ctypes
returns:
......@@ -328,7 +331,8 @@ def create_and_load_logging_function(custom_logging_code, verbose=0):
if verbose > 0:
print(
"loaded shared library for custom logging. custom_output_function is loaded in memory at {}".format(
"loaded shared library for custom logging. \
custom_output_function is loaded in memory at {}".format(
func_memaddr
)
)
......
"""
Module containing the predefined distribution functions
The user can use any of these distribution functions to
generate probability distributions for sampling populations
"""
import math
import binarycpython.utils.useful_funcs
from binarycpython.utils.useful_funcs import (
calc_period_from_sep,
)
###
# File containing probability distributions
......@@ -11,12 +22,11 @@ import binarycpython.utils.useful_funcs
# TODO: make global constants stuff
# TODO: make description of module submodule
log_ln_converter = 1.0 / math.log(10.0)
LOG_LN_CONVERTER = 1.0 / math.log(10.0)
def flat(parameter):
def flat():
"""
Dummt distribution function that returns 1
Dummy distribution function that returns 1
"""
return 1
......@@ -26,6 +36,7 @@ def number(value):
"""
Dummy distribution function that returns the input
"""
return value
......@@ -59,21 +70,25 @@ def powerlaw(min_val, max_val, k, x):
print("input value is out of bounds!")
return 0
else:
const = powerlaw_constant(min_val, max_val, k)
powerlaw_const = powerlaw_constant(min_val, max_val, k)
# powerlaw
y = const * (x ** k)
# print(
# "Power law from {} to {}: const = {}, y = {}".format(
# min_val, max_val, const, y
# )
# )
return y
# powerlaw
prob = powerlaw_const * (x ** k)
# print(
# "Power law from {} to {}: const = {}, y = {}".format(
# min_val, max_val, const, y
# )
# )
return prob
def calculate_constants_three_part_powerlaw(m0, m1, m2, m_max, p1, p2, p3):
# print("Initialising constants for the three-part powerlaw: m0={} m1={} m2={} m_max={} p1={} p2={} p3={}\n".format(m0, m1, m2, m_max, p1, p2, p3))
"""
Function to calculate the constants for a three-part powerlaw
"""
# print("Initialising constants for the three-part powerlaw: m0={} m1={} m2={}\
# m_max={} p1={} p2={} p3={}\n".format(m0, m1, m2, m_max, p1, p2, p3))
array_constants_three_part_powerlaw = [0, 0, 0]
......@@ -130,17 +145,17 @@ def three_part_powerlaw(M, M0, M1, M2, M_MAX, P1, P2, P3):
#
if M < M0:
p = 0 # Below lower bound
prob = 0 # Below lower bound
elif M0 < M <= M1:
p = three_part_powerlaw_constants[0] * (M ** P1) # Between M0 and M1
prob = three_part_powerlaw_constants[0] * (M ** P1) # Between M0 and M1
elif M1 < M <= M2:
p = three_part_powerlaw_constants[1] * (M ** P2) # Between M1 and M2
prob = three_part_powerlaw_constants[1] * (M ** P2) # Between M1 and M2
elif M2 < M <= M_MAX:
p = three_part_powerlaw_constants[2] * (M ** P3) # Between M2 and M_MAX
prob = three_part_powerlaw_constants[2] * (M ** P3) # Between M2 and M_MAX
else:
p = 0 # Above M_MAX
prob = 0 # Above M_MAX
return p
return prob
def const(min_bound, max_bound, val=None):
......@@ -149,12 +164,12 @@ def const(min_bound, max_bound, val=None):
"""
if val:
if not (min_bound < val <= max_bound):
if not min_bound < val <= max_bound:
print("out of bounds")
p = 0
return p
p = 1.0 / (min_bound - max_bound)
return p
prob = 0
return prob
prob = 1.0 / (min_bound - max_bound)
return prob
def set_opts(opts, newopts):
......@@ -168,29 +183,29 @@ def set_opts(opts, newopts):
if newopts:
for opt in newopts.keys():
if opt in opts.keys():
opts[key] = newopts[key]
opts[opt] = newopts[opt]
return opt
return opts
def gaussian(x, mean, sigma, gmin, gmax):
"""
Gaussian distribution function. used for e..g Duquennoy + Mayor 1991
Input: location, mean, sigma, min and max:
"""
# # location (X value), mean and sigma, min and max range
# my ($x,$mean,$sigma,$gmin,$gmax) = @_;
if (x < gmin) or (x > gmax):
p = 0
prob = 0
else:
# normalize over given range
# TODO: add loading into global var
normalisation = gaussian_normalizing_const(mean, sigma, gmin, gmax)
p = normalisation * gaussian_func(x, mean, sigma)
prob = normalisation * gaussian_func(x, mean, sigma)
return p
return prob
def gaussian_normalizing_const(mean, sigma, gmin, gmax):
......@@ -215,11 +230,11 @@ def gaussian_func(x, mean, sigma):
"""
Function to evaluate a gaussian at a given point
"""
GAUSSIAN_PREFACTOR = 1.0 / math.sqrt(2.0 * math.pi)
gaussian_prefactor = 1.0 / math.sqrt(2.0 * math.pi)
r = 1.0 / (sigma)
y = (x - mean) * r
return GAUSSIAN_PREFACTOR * r * math.exp(-0.5 * y ** 2)
return gaussian_prefactor * r * math.exp(-0.5 * y ** 2)
#####
......@@ -229,9 +244,9 @@ def gaussian_func(x, mean, sigma):
def Kroupa2001(m, newopts=None):
"""
Probability distribution function for kroupa 2001 IMF
Probability distribution function for kroupa 2001 IMF
Input: Mass, (and optional: dict of new options. Input the
Input: Mass, (and optional: dict of new options. Input the
default = {'m0':0.1, 'm1':0.5, 'm2':1, 'mmax':100, 'p1':-1.3, 'p2':-2.3, 'p3':-2.3}
"""
......@@ -245,9 +260,12 @@ def Kroupa2001(m, newopts=None):
"p2": -2.3,
"p3": -2.3,
}
value_dict = default.copy()
if newopts:
value_dict.update(newopts)
return three_part_powerlaw(
m,
value_dict["m0"],
......@@ -291,7 +309,9 @@ def ktg93(m, newopts):
# }
# set options
# opts = set_opts({'m0':0.1, 'm1':0.5, 'm2':1.0, 'mmax':80, 'p1':-1.3, 'p2':-2.2, 'p3':-2.7}, newopts)
# opts = set_opts({'m0':0.1, 'm1':0.5, 'm2':1.0, 'mmax':80, 'p1':-1.3, 'p2':-2.2, 'p3':-2.7},
# newopts)
defaults = {
"m0": 0.1,
"m1": 0.5,
......@@ -301,9 +321,11 @@ def ktg93(m, newopts):
"p2": -2.2,
"p3": -2.7,
}
value_dict = default.copy()
value_dict = defaults.copy()
if newopts:
value_dict.update(newopts)
return three_part_powerlaw(
m,
value_dict["m0"],
......@@ -348,34 +370,36 @@ def imf_scalo1998(m):
def imf_chabrier2003(m):
"""
# IMF of Chabrier 2003 PASP 115:763-795
IMF of Chabrier 2003 PASP 115:763-795
"""
Chabrier_logmc = math.log10(0.079)
Chabrier_sigma2 = 0.69 * 0.69
Chabrier_A1 = 0.158
Chabrier_A2 = 4.43e-2
Chabrier_x = -1.3
chabrier_logmc = math.log10(0.079)
chabrier_sigma2 = 0.69 * 0.69
chabrier_a1 = 0.158
chabrier_a2 = 4.43e-2
chabrier_x = -1.3
if m < 0:
print("below bounds")
raise ValueError
if 0 < m < 1.0:
A = 0.158
dm = math.log10(m) - Chabrier_logmc
p = Chabrier_A1 * math.exp(-(dm ** 2) / (2.0 * Chabrier_sigma2))
dm = math.log10(m) - chabrier_logmc
prob = chabrier_a1 * math.exp(-(dm ** 2) / (2.0 * chabrier_sigma2))
else:
p = Chabrier_A2 * (m ** Chabrier_x)
p = p / (0.1202462 * m * math.log(10))
return p
prob = chabrier_a2 * (m ** chabrier_x)
prob = prob / (0.1202462 * m * math.log(10))
return prob
########################################################################
# Binary fractions
########################################################################
def Arenou2010_binary_fraction(m):
# Arenou 2010 function for the binary fraction as f(M1)
#
# GAIA-C2-SP-OPM-FA-054
# www.rssd.esa.int/doc_fetch.php?id=2969346
"""
Arenou 2010 function for the binary fraction as f(M1)
GAIA-C2-SP-OPM-FA-054
www.rssd.esa.int/doc_fetch.php?id=2969346
"""
return 0.8388 * math.tanh(0.688 * m + 0.079)
......@@ -385,14 +409,14 @@ def Arenou2010_binary_fraction(m):
def raghavan2010_binary_fraction(m):
"""
Fit to the Raghavan 2010 binary fraction as a function of
Fit to the Raghavan 2010 binary fraction as a function of
spectral type (Fig 12). Valid for local stars (Z=Zsolar).
The spectral type is converted mass by use of the ZAMS
The spectral type is converted mass by use of the ZAMS
effective temperatures from binary_c/BSE (at Z=0.02)
and the new "long_spectral_type" function of binary_c
(based on Jaschek+Jaschek's Teff-spectral type table).
Rob then fitted the result
"""
......@@ -422,10 +446,10 @@ def duquennoy1991(x):
return gaussian(x, 4.8, 2.3, -2, 12)
def sana12(M1, M2, a, P, amin, amax, x0, x1, p): # TODO: ? wtf. vague input
def sana12(M1, M2, a, P, amin, amax, x0, x1, p):
"""
distribution of initial orbital periods as found by Sana et al. (2012)
which is a flat distribution in ln(a) and ln(P) respectively for stars
which is a flat distribution in ln(a) and ln(P) respectively for stars
* less massive than 15Msun (no O-stars)
* mass ratio q=M2/M1<0.1
* log(P)<0.15=x0 and log(P)>3.5=x1
......@@ -434,6 +458,9 @@ def sana12(M1, M2, a, P, amin, amax, x0, x1, p): # TODO: ? wtf. vague input
arguments are M1, M2, a, Period P, amin, amax, x0=log P0, x1=log P1, p
example args: 10, 5, ?, P, ?, ?, -2, 12, -0.55
# TODO: ? wtf. vague input
# TODO: Fix this function!
"""
res = 0
......@@ -443,11 +470,12 @@ def sana12(M1, M2, a, P, amin, amax, x0, x1, p): # TODO: ? wtf. vague input
else:
p1 = 1.0 + p
# For more details see the LyX document of binary_c for this distribution where the variables and normalizations are given
# For more details see the LyX document of binary_c for this distribution
# where the variables and normalizations are given
# we use the notation x=log(P), xmin=log(Pmin), x0=log(P0), ... to determine the
x = log_ln_converter * math.log(p)
xmin = log_ln_converter * math.log(calc_period_from_sep(m1, m2, amin))
xmin = log_ln_converter * math.log(calc_period_from_sep(m1, m2, amax))
x = LOG_LN_CONVERTER * math.log(p)
xmin = LOG_LN_CONVERTER * math.log(calc_period_from_sep(M1, M2, amin))
xmax = LOG_LN_CONVERTER * math.log(calc_period_from_sep(M1, M2, amax))
# my $x0 = 0.15;
# my $x1 = 3.5;
......@@ -459,11 +487,11 @@ def sana12(M1, M2, a, P, amin, amax, x0, x1, p): # TODO: ? wtf. vague input
A2 = A1 * x1 ** p
if x < x0:
res = 3.0 / 2.0 * log_ln_converter * A0
res = 3.0 / 2.0 * LOG_LN_CONVERTER * A0
elif x > x1:
res = 3.0 / 2.0 * log_ln_converter * A2
res = 3.0 / 2.0 * LOG_LN_CONVERTER * A2
else:
res = 3.0 / 2.0 * log_ln_converter * A1 * x ** p
res = 3.0 / 2.0 * LOG_LN_CONVERTER * A1 * x ** p
return res
......@@ -477,9 +505,11 @@ def sana12(M1, M2, a, P, amin, amax, x0, x1, p): # TODO: ? wtf. vague input
def flatsections(x, opts):
"""
opts = list of dicts with settings for the flat sections
Function to generate flat distributions, possibly in multiple sections
opts: list of dicts with settings for the flat sections
x: location to calculate the y value
TODO: figure out why it has to be a list of dict. why not just 1
"""
......@@ -488,7 +518,8 @@ def flatsections(x, opts):
for opt in opts:
dc = (opt["max"] - opt["min"]) * opt["height"]
# print("added flatsection ({}-{})*{} = {}\n".format(opt['max'], opt['min'], opt['height'], dc))
# print("added flatsection ({}-{})*{} = {}\n".format(
# opt['max'], opt['min'], opt['height'], dc))
c += dc
if opt["min"] <= x <= opt["max"]:
y = opt["height"]
......
This diff is collapsed.
This diff is collapsed.
"""
Module that contains the default options for the population gric code.
"""
import os
import sys
from binarycpython.utils.custom_logging_functions import temp_dir
......@@ -30,14 +33,17 @@ grid_options_defaults_dict = {
##########################
# Custom logging
##########################
"C_auto_logging": None, # Should contain a dictionary where the kes are they headers and the values are lists of parameters that should be logged. This will get parsed by autogen_C_logging_code in custom_loggion_functions.py
"C_auto_logging": None, # Should contain a dictionary where the kes are they headers
# and the values are lists of parameters that should be logged.
# This will get parsed by autogen_C_logging_code in custom_loggion_functions.py
"C_logging_code": None, # Should contain a string which holds the logging code.
"custom_logging_func_memaddr": -1, # Contains the custom_logging functions memory address
"custom_logging_shared_library_file": None,
##########################
# Store pre-loading:
##########################
"store_memaddr": -1, # Contains the store object memory adress, useful for preloading. defaults to -1 and isnt used if thats the default then.
"store_memaddr": -1, # Contains the store object memory adress, useful for preloading.
# defaults to -1 and isnt used if thats the default then.
##########################
# Log args: logging of arguments
##########################
......@@ -52,7 +58,8 @@ grid_options_defaults_dict = {
"mp",
"linear",
], # available choices for type of population evolution
"system_generator": None, # value that holds the function that generates the system (result of building the grid script)
"system_generator": None, # value that holds the function that generates the system
# (result of building the grid script)
"population_type": "grid", #
"population_type_options": [
"grid",
......@@ -136,7 +143,8 @@ grid_options_defaults_dict = {
# condor_jobid=>'', # condor job id
# condor_postpone_join=>0, # if 1, data is not joined, e.g. if you
# # want to do it off the condor grid (e.g. with more RAM)
# condor_join_machine=>undef, # if defined then this is the machine on which the join command should be launched (must be sshable and not postponed)
# condor_join_machine=>undef, # if defined then this is the machine on which the join command
#should be launched (must be sshable and not postponed)
# condor_join_pwd=>undef, # directory the join should be in
# # (defaults to $ENV{PWD} if undef)
# condor_memory=>1024, # in MB, the memory use (ImageSize) of the job
......@@ -144,9 +152,11 @@ grid_options_defaults_dict = {
# condor_snapshot_on_kill=>0, # if 1 snapshot on SIGKILL before exit
# condor_load_from_snapshot=>0, # if 1 check for snapshot .sv file and load it if found
# condor_checkpoint_interval=>0, # checkpoint interval (seconds)
# condor_checkpoint_stamp_times=>0, # if 1 then files are given timestamped names (warning: lots of files!), otherwise just store the lates
# condor_checkpoint_stamp_times=>0, # if 1 then files are given timestamped names
# (warning: lots of files!), otherwise just store the lates
# condor_streams=>0, # stream stderr/stdout by default (warning: might cause heavy network load)
# condor_save_joined_file=>0, # if 1 then results/joined contains the results (useful for debugging, otherwise a lot of work)
# condor_save_joined_file=>0, # if 1 then results/joined contains the results
# (useful for debugging, otherwise a lot of work)
# condor_requirements=>'', # used?
# # resubmit options : if the status of a condor script is
# # either 'finished','submitted','running' or 'crashed',
......@@ -330,7 +340,8 @@ grid_options_defaults_dict = {
# sort_args=>0, # do not sort args
# save_args=>0, # do not save args in a string
# log_args_dir=>$tmp, # where to output the args files
# always_reopen_arg_files=>0, # if 1 then arg files are always closed and reopened (may cause a lot of disk I/O)
# always_reopen_arg_files=>0, # if 1 then arg files are always closed and reopened
# (may cause a lot of disk I/O)
# lazy_arg_sending=>1, # if 1, the previous args are remembered and
# # only args that changed are sent (except M1, M2 etc. which always
# # need sending)
......
"""
Module that contains plotting routines for single systems.
The idea to do this is to provide the user with some quick
The idea to do this is to provide the user with some quick
commands to plot the evolution of a system
There is no preloaded matplotlib rc, you should do that yourself
TODO: This module is not finished yet.
"""
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# import matplotlib.pyplot as plt
from binarycpython.utils.functions import (
output_lines,
)
from binarycpython.utils.run_system_wrapper import run_system
from binarycpython.utils.custom_logging_functions import binary_c_log_code
from david_phd_functions.plotting.plot_functions import (
plot_orbit,
plot_masses,
plot_HR_diagram,
)
from binarycpython.utils.functions import get_arg_keys, output_lines
from binarycpython.utils.run_system_wrapper import run_system
from binarycpython.utils.custom_logging_functions import binary_c_log_code
# Define the custom_logging_strings. These are kept to the minimum necessary for each plotting routine.
# Define the custom_logging_strings.
# These are kept to the minimum necessary for each plotting routine.
custom_logging_string_masses = ""
custom_logging_string_orbit = ""
CUSTOM_LOGGING_STRING_MASSES = ""
custom_logging_string_HR_diagram = """
CUSTOM_LOGGING_STRING_ORBIT = ""
CUSTOM_LOGGING_STRING_HR_DIAGRAM = """
Printf("HR_PLOTTING %30.12e %d %d %g %g %g %g %g %g\\n",
//
stardata->model.time, // 1
......@@ -50,9 +58,9 @@ Printf("HR_PLOTTING %30.12e %d %d %g %g %g %g %g %g\\n",
# Define the parse functions for the plotting routines
def dummy():
"""Placeholder"""
pass
def parse_function_hr_diagram(output):
"""
Parsing function for the HR plotting routine
......@@ -75,12 +83,12 @@ def parse_function_hr_diagram(output):
]
# Go over the output.
for el in output_lines(output):
headerline = el.split()[0]
for line in output_lines(output):
headerline = line.split()[0]
# Check the header and act accordingly
if headerline == "HR_PLOTTING":
values = el.split()[1:]
values = line.split()[1:]
values_list.append(values)
df = pd.DataFrame(values_list)
......@@ -98,12 +106,13 @@ def plot_system(plot_type, **kwargs):
TODO: Complex Function!
TODO: make sure this way of passing args works correctly.
TODO: make the plotting specific keywords available via the inspect stuff
Function to plot the evolution of the system.
Function to plot the evolution of the system.
This goes (in general) via the following steps:
- a preset custom logging for a specific plotting routine is loaded.
- This is used for the run_system call
- The output of this run_system is loaded into a dataframe by parsing it with a corresponding parsing function
- The output of this run_system is loaded into a dataframe by
parsing it with a corresponding parsing function
- The dataframe is passed to the plotting routine
- plot is shown or returned.
......@@ -111,11 +120,16 @@ def plot_system(plot_type, **kwargs):
All keywords are considered kwargs, except for plot_type
input:
plot_type: string input should be one of the following types: ['mass_evolution', 'orbit_evolution', 'hr_diagram'].
Input will be matched against this, and then go through a dictionary to pick the correct plotting function.
return_fig: boolean whether to return the fig object instead of plotting the plot (makes so that you can customize it)
show_stellar_types: whether to plot the stellar type evolution on a second pane. This is not included in all the plotting routines.
Other input: other kwargs that are passed to run_system (inspect the docstring of run_system for more info)
plot_type: string input should be one of the following types:
['mass_evolution', 'orbit_evolution', 'hr_diagram'].
Input will be matched against this,
and then go through a dictionary to pick the correct plotting function.
return_fig: boolean whether to return the fig object instead of plotting the plot
(makes so that you can customize it)
show_stellar_types: whether to plot the stellar type evolution on a second pane.
This is not included in all the plotting routines.
Other input: other kwargs that are passed to run_system
(inspect the docstring of run_system for more info)
"""
# set defaults and options
......@@ -125,32 +139,35 @@ def plot_system(plot_type, **kwargs):
plot_types_dict = {
"mass_evolution": {
"plot_function": plot_masses,
"custom_logging_string": custom_logging_string_masses,
"custom_logging_string": CUSTOM_LOGGING_STRING_MASSES,
"parse_function": dummy,
},
"orbit_evolution": {
"plot_function": plot_orbit,
"custom_logging_string": custom_logging_string_orbit,
"custom_logging_string": CUSTOM_LOGGING_STRING_ORBIT,
"parse_function": dummy,
},
"hr_diagram": {
"plot_function": plot_HR_diagram,
"custom_logging_string": custom_logging_string_HR_diagram,
"custom_logging_string": CUSTOM_LOGGING_STRING_HR_DIAGRAM,
"parse_function": parse_function_hr_diagram,
},
}
plot_system_specific_keywords = ["plot_type", "show_plot", "show_stellar_types"]
# First check on the plot_type input
if not plot_type in plot_types_dict.keys():
if not plot_type in plot_types_dict:
print(
"Warning, the provided plot type is not known. Please choose one from the following:\n\t{}".format(
"Warning, the provided plot type is not known. \
Please choose one from the following:\n\t{}".format(
plot_types_dict.keys()
)
)
raise ValueError
# First: check all the arguments. Chosen to not check all the keywords for run_system and binary_c specifically, but just to pick out the ones needed for this routine. run_system will handle the rest
# First: check all the arguments. Chosen to not check all the keywords for run_system
# and binary_c specifically, but just to pick out the ones needed for this routine.
# run_system will handle the rest
run_system_arg_dict = {}
for key in kwargs.keys():
......@@ -163,7 +180,8 @@ def plot_system(plot_type, **kwargs):
else:
run_system_arg_dict[key] = kwargs[key]
# TODO: When a list of plot_types is passed, make it so that the strings are chained, and that the output of the binary_c call is handled by multiple parsers
# TODO: When a list of plot_types is passed, make it so that the strings are chained,
# and that the output of the binary_c call is handled by multiple parsers
custom_logging_code = binary_c_log_code(
plot_types_dict[plot_type]["custom_logging_string"]
)
......
import binary_c_python_api
"""
Module containing the utility function run_system,
which handles a lot of things by analysing the passed kwargs
"""
from binarycpython.utils.functions import (
get_defaults,
create_arg_string,
get_arg_keys,
remove_file,
......@@ -10,29 +13,37 @@ from binarycpython.utils.functions import (
from binarycpython.utils.custom_logging_functions import (
create_and_load_logging_function,
)
import binary_c_python_api
def run_system(**kwargs):
"""
Function that runs a system. Mostly as a useful utility function that handles all the setup of argument lists etc.
Function that runs a system.
Mostly as a useful utility function that handles all the setup of argument lists etc.
All~ the arguments known to binary_c can be passed to this function as kwargs.
Several extra arguments can be passed through the kwargs:
* custom_logging_code (string): Should contain a string containing the c-code for the shared library.
* custom_logging_code (string):
Should contain a string containing the c-code for the shared library.
If this is provided binary_c will use that custom logging code to output its data
* log_filename (string): Should contain name of the binary_c system logfile.
Passing this will make sure that the filename gets written for a run (its default behaviour is NOT to write a logfile for a system)
* parse_function (function): should contain a function that parses the output. The parse function should take 1 required parameter: the output of the binaryc run
Passing this will call the parse_function by passing it the output of the binary_c call and returns what the parse_function returns
* log_filename (string):
Should contain name of the binary_c system logfile.
Passing this will make sure that the filename gets written for a run
(its default behaviour is NOT to write a logfile for a system)
* parse_function (function):
should contain a function that parses the output.
The parse function should take 1 required parameter: the output of the binaryc run
Passing this will call the parse_function by passing it the output of the binary_c call
and returns what the parse_function returns
examples:
* run_system(M_1=10): will run a system with ZAMS mass 1 = 10
* run_system(M_1=10, log_filename="~/example_log.txt"): Will run a system and write the logfile to
* run_system(M_1=10, log_filename="~/example_log.txt"): Will run a system
and write the logfile too
* run_system(M_1=10, parse_function=fancy_parsing_function)
Todo:
* Expand functionality.
* Notify user when an unknown keyword is passed
TODO: Expand functionality.
TODO: Notify user when an unknown keyword is passed.
"""
# Load available arg keywords
......@@ -48,7 +59,7 @@ def run_system(**kwargs):
binary_c_args = {}
# Check which binary_c arguments have been passed and put them into a dict
for key in kwargs.keys():
for key in kwargs:
if key in available_binary_c_arg_keywords:
binary_c_args[key] = kwargs[key]
......@@ -88,5 +99,4 @@ def run_system(**kwargs):
if "parse_function" in kwargs:
return kwargs["parse_function"](output)
else:
return output
return output
"""
Module containing the spacing functions for the binarycpython package
"""
import numpy as np
def const(min, max, steps):
return np.linspace(min, max, steps)
def const(min_bound, max_bound, steps):
"""
Samples a range linearly. Uses numpy linspace.
"""
return np.linspace(min_bound, max_bound, steps)
stellar_type_dict = {
"""
Module containing stellar type dicts
"""
STELLAR_TYPE_DICT = {
0: "low mass main sequence",
1: "Main Sequence",
2: "Hertzsprung Gap",
......@@ -17,7 +21,7 @@ stellar_type_dict = {
15: "MASSLESS REMNANT",
}
stellar_type_dict_short = {
STELLAR_TYPE_DICT_SHORT = {
0: "LMMS",
1: "MS",
2: "HG",
......
############################################################
# Collection of useful functions.
# Part of this is copied/inspired by Robs
# Rob's binary_stars module
# Has functions to convert period to separation and vice versa.
# calc_period_from_sep($m1,$m2,$sep) calculate the period given the separation.
# calc_sep_from_period($m1,$m2,per) does the inverse.
# M1,M2,separation are in solar units, period in days.
# rzams($m,$z) gives you the ZAMS radius of a star
# ZAMS_collision($m1,$m2,$e,$sep,$z) returns 1 if stars collide on the ZAMS
###
"""
Collection of useful functions.
Part of this is copied/inspired by Robs
Rob's binary_stars module
Has functions to convert period to separation and vice versa.
calc_period_from_sep($m1,$m2,$sep) calculate the period given the separation.
calc_sep_from_period($m1,$m2,per) does the inverse.
M1,M2,separation are in solar units, period in days.
rzams($m,$z) gives you the ZAMS radius of a star
ZAMS_collision($m1,$m2,$e,$sep,$z) returns 1 if stars collide on the ZAMS
# TODO: check whether these are correct
"""
import math
AURSUN = 2.150445198804013386961742071435e02
YEARDY = 3.651995478818308811241877265275e02
......@@ -23,7 +25,7 @@ def calc_period_from_sep(M1, M2, sep):
args : M1, M2, separation (Rsun)
"""
return YEARDY * (sep / AURSUN) * sqrt(sep / (AURSUN * (M1 + M2)))
return YEARDY * (sep / AURSUN) * math.sqrt(sep / (AURSUN * (M1 + M2)))
def calc_sep_from_period(M1, M2, period):
......@@ -41,7 +43,7 @@ def roche_lobe(q):
"""
p = q ** (1.0 / 3.0)
return 0.49 * p * p / (0.6 * p * p + log(1.0 + p))
return 0.49 * p * p / (0.6 * p * p + math.log(1.0 + p))
def ragb(m, z):
......@@ -55,9 +57,10 @@ def ragb(m, z):
def zams_collission(m1, m2, sep, e, z):
"""
# given m1,m2, separation and eccentricity (and metallicity)
# determine if two stars collide on the ZAMS
given m1,m2, separation and eccentricity (and metallicity)
determine if two stars collide on the ZAMS
"""
# calculate periastron distance
peri_distance = (1.0 - e) * sep
......@@ -67,14 +70,14 @@ def zams_collission(m1, m2, sep, e, z):
if r1 + r2 > peri_distance:
return 1
else:
return 0
return 0
def rzams(m, z):
"""
Function to determine the radius of a ZAMS star as a function of m and z:
"""
lzs = math.log10(z / 0.02)
#
......
"""
Setup script for binarycpython
"""
from distutils.core import setup, Extension
# from setuptools import find_packages
......@@ -5,12 +9,12 @@ from distutils.core import setup, Extension
import os
import subprocess
import re
import sys
GSL_DIR = os.getenv("GSL_DIR", None)
if not GSL_DIR:
print(
"Warning: GSL_DIR is not set, this might lead to errors along the installation if there is no other version of GSL in the include dirs"
"Warning: GSL_DIR is not set, this might lead to errors along the installation if\
there is no other version of GSL in the include dirs"
)
# TODO: write code to know exact parent directory of this file.
......@@ -21,90 +25,90 @@ CWD = os.getcwd()
############################################################
# binary_c must be installed.
binary_c_config = os.environ["BINARY_C"] + "/binary_c-config"
BINARY_C_CONFIG = os.environ["BINARY_C"] + "/binary_c-config"
binary_c_incdirs = (
subprocess.run([binary_c_config, "incdirs_list"], stdout=subprocess.PIPE)
BINARY_C_INCDIRS = (
subprocess.run([BINARY_C_CONFIG, "incdirs_list"], stdout=subprocess.PIPE, check=True)
.stdout.decode("utf-8")
.split()
)
binary_c_libdirs = (
subprocess.run([binary_c_config, "libdirs_list"], stdout=subprocess.PIPE)
BINARY_C_LIBDIRS = (
subprocess.run([BINARY_C_CONFIG, "libdirs_list"], stdout=subprocess.PIPE, check=True)
.stdout.decode("utf-8")
.split()
)
binary_c_cflags = (
subprocess.run([binary_c_config, "cflags"], stdout=subprocess.PIPE)
BINARY_C_CFLAGS = (
subprocess.run([BINARY_C_CONFIG, "cflags"], stdout=subprocess.PIPE, check=True)
.stdout.decode("utf-8")
.split()
)
# binary_c_cflags.remove('-fvisibility=hidden')
binary_c_libs = (
subprocess.run([binary_c_config, "libs_list"], stdout=subprocess.PIPE)
# BINARY_C_CFLAGS.remove('-fvisibility=hidden')
BINARY_C_LIBS = (
subprocess.run([BINARY_C_CONFIG, "libs_list"], stdout=subprocess.PIPE, check=True)
.stdout.decode("utf-8")
.split()
)
# create list of tuples of defined macros
binary_c_define_macros = []
defines = (
subprocess.run([binary_c_config, "define_macros"], stdout=subprocess.PIPE)
BINARY_C_DEFINE_MACROS = []
DEFINES = (
subprocess.run([BINARY_C_CONFIG, "define_macros"], stdout=subprocess.PIPE, check=True)
.stdout.decode("utf-8")
.split()
)
lone = re.compile("^-D(.+)$")
partner = re.compile("^-D(.+)=(.+)$")
LONE = re.compile("^-D(.+)$")
PARTNER = re.compile("^-D(.+)=(.+)$")
for x in defines:
y = partner.match(x)
for x in DEFINES:
y = PARTNER.match(x)
if y:
binary_c_define_macros.extend([(y.group(1), y.group(2))])
BINARY_C_DEFINE_MACROS.extend([(y.group(1), y.group(2))])
else:
y = lone.match(x)
y = LONE.match(x)
if y:
binary_c_define_macros.extend([(y.group(1), None)])
BINARY_C_DEFINE_MACROS.extend([(y.group(1), None)])
# add API header file
API_h = os.environ["BINARY_C"] + "/src/API/binary_c_API.h"
binary_c_define_macros.extend([("BINARY_C_API_H", API_h)])
BINARY_C_DEFINE_MACROS.extend([("BINARY_C_API_H", API_h)])
############################################################
# Setting all directories and libraries to their final values
# Setting all directories and LIBRARIES to their final values
############################################################
include_dirs = (
INCLUDE_DIRS = (
[os.environ["BINARY_C"] + "/src", os.environ["BINARY_C"] + "/src/API", "include",]
+ binary_c_incdirs
+ BINARY_C_INCDIRS
+ [os.path.join(GSL_DIR, "include")]
if GSL_DIR
else []
)
libraries = ["binary_c"] + binary_c_libs + ["binary_c_api"]
LIBRARIES = ["binary_c"] + BINARY_C_LIBS + ["binary_c_api"]
library_dirs = [
LIBRARY_DIRS = [
os.environ["BINARY_C"] + "/src",
"./",
os.path.join(CWD, "lib/"),
# os.path.join(CWD, "binarycpython/core/"),
] + binary_c_libdirs
] + BINARY_C_LIBDIRS
runtime_library_dirs = [
RUNTIME_LIBRARY_DIRS = [
os.environ["BINARY_C"] + "/src",
"./",
os.path.join(CWD, "lib/"),
# os.path.join(CWD, "binarycpython/core/"),
] + binary_c_libdirs
] + BINARY_C_LIBDIRS
# print('\n')
# print("binary_c_config: ", str(binary_c_config) + "\n")
# print("incdirs: ", str(include_dirs) + "\n")
# print("binary_c_libs: ", str(binary_c_libs) + "\n")
# print("libraries: ", str(libraries) + "\n")
# print("library_dirs: ", str(library_dirs) + "\n")
# print("runtime_library_dirs: ", str(runtime_library_dirs) + "\n")
# print("binary_c_cflags: ", str(binary_c_cflags) + "\n")
# print("BINARY_C_CONFIG: ", str(BINARY_C_CONFIG) + "\n")
# print("incdirs: ", str(INCLUDE_DIRS) + "\n")
# print("BINARY_C_LIBS: ", str(BINARY_C_LIBS) + "\n")
# print("LIBRARIES: ", str(LIBRARIES) + "\n")
# print("LIBRARY_DIRS: ", str(LIBRARY_DIRS) + "\n")
# print("RUNTIME_LIBRARY_DIRS: ", str(RUNTIME_LIBRARY_DIRS) + "\n")
# print("BINARY_C_CFLAGS: ", str(BINARY_C_CFLAGS) + "\n")
# print("API_h: ", str(API_h) + "\n")
# print("macros: ", str(binary_c_define_macros) + "\n")
# print("macros: ", str(BINARY_C_DEFINE_MACROS) + "\n")
# print('\n')
############################################################
......@@ -112,15 +116,15 @@ runtime_library_dirs = [
############################################################
# TODO: fix that this one also compiles the code itself
binary_c_python_api_module = Extension(
BINARY_C_PYTHON_API_MODULE = Extension(
# name="binarycpython.core.binary_c",
name="binary_c_python_api",
sources=["src/binary_c_python.c"],
include_dirs=include_dirs,
libraries=libraries,
library_dirs=library_dirs,
runtime_library_dirs=runtime_library_dirs,
define_macros=[] + binary_c_define_macros,
INCLUDE_DIRS=INCLUDE_DIRS,
LIBRARIES=LIBRARIES,
LIBRARY_DIRS=LIBRARY_DIRS,
RUNTIME_LIBRARY_DIRS=RUNTIME_LIBRARY_DIRS,
define_macros=[] + BINARY_C_DEFINE_MACROS,
extra_objects=[],
extra_compile_args=[],
language="C",
......@@ -128,8 +132,9 @@ binary_c_python_api_module = Extension(
def readme():
with open("README.md") as f:
return f.read()
"""Opens readme file and returns content"""
with open("README.md") as file:
return file.read()
############################################################
......@@ -139,9 +144,11 @@ def readme():
setup(
name="binarycpython",
version="0.2",
description="This is a python API for binary_c by David Hendriks, Rob Izzard and collaborators. Based on the initial set up by Jeff andrews",
description="This is a python API for binary_c by David Hendriks, Rob Izzard and collaborators.\
Based on the initial set up by Jeff andrews",
author=" David Hendriks, Robert Izzard and Jeff Andrews",
author_email="davidhendriks93@gmail.com/d.hendriks@surrey.ac.uk, r.izzard@surrey.ac.uk/rob.izzard@gmail.com andrews@physics.uoc.gr",
author_email="davidhendriks93@gmail.com/d.hendriks@surrey.ac.uk,\
r.izzard@surrey.ac.uk/rob.izzard@gmail.com andrews@physics.uoc.gr",
long_description=readme(),
url="https://gitlab.eps.surrey.ac.uk/ri0005/binary_c-python",
license="",
......@@ -158,5 +165,5 @@ setup(
# package_data={
# 'binarycpython.core': ['libbinary_c_api.so'],
# },
ext_modules=[binary_c_python_api_module], # binary_c must be loaded
ext_modules=[BINARY_C_PYTHON_API_MODULE], # binary_c must be loaded
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment