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

removed testing stuff. fixed example

parent ebba9983
No related branches found
No related tags found
No related merge requests found
Showing
with 6 additions and 643 deletions
* Todo list for the binary_c-python
** Logging functionality:
*** Idea
Idea is to be able to give a string via python that will be used in the through the libbinary_c.so so that log_every_timestep.c
The code below is the piece in log_every_timestep that uses it.
if(stardata->preferences->custom_output_function != NULL)
{
Dprint("calling custom output function %p\n",
stardata->preferences->custom_output_function);
stardata->preferences->custom_output_function(stardata);
}
So the function should recieve 'stardata' as input.
We can do that with providing a logging string alltogether, or generate a logging function
In either way, this should be passed to stardata->preferences->custom_output_function as a pointer to that function
*** Provide string for logging
In perl this is done in the following way:
**** code to input
And then to use it via
$population->set(
C_logging_code => '
PRINTF("MY_STELLAR_DATA %g %g %g %g\n",
stardata->model.time,
stardata->star[0].mass,
stardata->model.probability,
stardata->model.dt);
'
);
**** code to handle that input
sub binary_c_log_code
{
my ($code) = @_;
return "
#pragma push_macro(\"MAX\")
#pragma push_macro(\"MIN\")
#undef MAX
#undef MIN
#include \"binary_c.h\"
void custom_output_function(SV * x);
SV * custom_output_function_pointer(void);
SV * custom_output_function_pointer()
{
/*
* use PTR2UV to convert the function pointer
* &custom_output_function to an unsigned int,
* which is then converted to a Perl SV
*/
return (SV*)newSVuv(PTR2UV(&custom_output_function));
}
void custom_output_function(SV * x)
{
struct stardata_t * stardata = (struct stardata_t *)x;
$code;
}
#undef MAX
#undef MIN
#pragma pop_macro(\"MIN\")
#pragma pop_macro(\"MAX\")
";
}
Or use it via:
*** auto logging
We should also try to be able to have the code autogenerate some logging function via the following:
**** input in perl
$population->set( C_auto_logging => {
'MY_STELLAR_DATA' =>
[
'model.time',
'star[0].mass',
'model.probability',
'model.dt'
]
});
**** code to handle that input
Which is handled in perl via (see binary_grid2.pm
sub autogen_C_logging_code
{
# given a hash of arrays of variable names, where the hash
# key is the header, autogenerate PRINTF statements
my ($self) = @_;
my $code = undef;
if(defined $self->{_grid_options}->{C_auto_logging} &&
ref $self->{_grid_options}->{C_auto_logging} eq 'HASH'
)
{
$code = '';
foreach my $header (keys %{$self->{_grid_options}->{C_auto_logging}})
{
if(ref $self->{_grid_options}->{C_auto_logging}->{$header} eq 'ARRAY')
{
$code .= 'PRINTF("'.$header.' ';
foreach my $x (@{$self->{_grid_options}->{C_auto_logging}->{$header}})
{
$code .= '%g ';
}
$code .= '\n"';
foreach my $x (@{$self->{_grid_options}->{C_auto_logging}->{$header}})
{
$code .= ',((double)stardata->'.$x.')';
}
$code .= ');'
}
}
}
print "MADE AUTO CODE \n\n************************************************************\n\n$code\n\n************************************************************\n";
return $code;
}
*** DONE Make function in python that puts code into c function
CLOSED: [2019-10-31 Thu 11:13]
*** DONE Make function in python that generates c-function from a list of arguments
CLOSED: [2019-10-29 Tue 23:52]
*** DONE Resolve current issue malloc
CLOSED: [2019-11-08 Fri 11:12]
➜ binary_c-python git:(master) ✗ python python_API_test.py
Traceback (most recent call last):
File "python_API_test.py", line 3, in <module>
import binary_c
ImportError: /home/david/projects/binary_c_root/binary_c-python/libbinary_c_api.so: undefined symbol: MALLOC
I get this error when I am using the master version of binary_c with either branches of the python wrapper..
That went very deep haha. alot of memory allocation stuff
*** DONE Make sure this works with the last major release of binaryc
CLOSED: [2019-11-08 Fri 15:00]
*** DONE Finish testing a simpler case (see other repo)
CLOSED: [2019-11-08 Fri 09:37]
*** DONE Make master master work
CLOSED: [2019-11-08 Fri 15:00]
*** DONE Sync master with david_branch
CLOSED: [2019-11-08 Fri 15:00]
*** DONE make tag of old master branch for future reference
CLOSED: [2019-11-08 Fri 15:00]
*** DONE Implement the autogeneration of the library
CLOSED: [2019-11-08 Fri 15:48]
*** DONE Load all the things with the c-types
CLOSED: [2019-11-08 Fri 18:49]
*** DONE Implement new function for run_binary_with_custom_logging
CLOSED: [2019-11-08 Fri 21:19]
*** DONE Make new c function run_binary_with_custom_logging
CLOSED: [2019-11-08 Fri 21:19]
*** TODO Put in some new tests in the python test api
*** DONE Make sure the sharedlibs get written to the correct directory
CLOSED: [2019-11-10 Sun 00:21]
** General:
*** DONE Get a more reliable way of loading the default values (running a ./tbse echo or something?)
CLOSED: [2019-10-29 Tue 17:44]
*** DONE make routine that reads out all the lines, splits them into pieces and reads out the correct key
CLOSED: [2019-10-29 Tue 17:43]
*** TODO Put header and other source files in a dedicated directory
*** TODO Use sphinx or read the docs for auto generation of documentation
*** TODO Have the compiled files put into a build directory
*** TODO add pythonpath thing to readme
*** TODO make script that will set up binaryc automatically so that this can become an out of the box thing
*** TODO Test the importing of this code from different places
** Population ideas
*** TODO Queuing system and some multiprocessing to run many systems
*** TODO Consider rewriting the work that perl does
...@@ -34,7 +34,7 @@ def run_example_binary(): ...@@ -34,7 +34,7 @@ def run_example_binary():
output = binary_c.run_binary(argstring) output = binary_c.run_binary(argstring)
print (output) print (output)
# run_example_binary() run_example_binary()
def run_example_binary_with_run_system(): def run_example_binary_with_run_system():
""" """
...@@ -71,7 +71,7 @@ def run_example_binary_with_run_system(): ...@@ -71,7 +71,7 @@ def run_example_binary_with_run_system():
# Some routine to plot. # Some routine to plot.
# run_example_binary_with_run_system() run_example_binary_with_run_system()
def run_example_binary_with_custom_logging(): def run_example_binary_with_custom_logging():
...@@ -110,7 +110,7 @@ def run_example_binary_with_custom_logging(): ...@@ -110,7 +110,7 @@ def run_example_binary_with_custom_logging():
# Do whatever you like with the dataframe. # Do whatever you like with the dataframe.
print(df) print(df)
# run_example_binary_with_custom_logging() run_example_binary_with_custom_logging()
def run_example_binary_with_writing_logfile(): def run_example_binary_with_writing_logfile():
""" """
...@@ -119,9 +119,10 @@ def run_example_binary_with_writing_logfile(): ...@@ -119,9 +119,10 @@ def run_example_binary_with_writing_logfile():
import pandas as pd import pandas as pd
import numpy as np import numpy as np
import tempfile
# Run system. all arguments can be given as optional arguments. # Run system. all arguments can be given as optional arguments.
output = run_system(M_1=10, M_2=20, separation=0, orbital_period=100000000000, log_filename=os.getcwd()+'/test_log.txt') output = run_system(M_1=10, M_2=20, separation=0, orbital_period=100000000000, log_filename=tempfile.gettempdir()+'/test_log.txt')
# Catch results that start with a given header. (Mind that binary_c has to be configured to print them if your not using a custom logging function) # Catch results that start with a given header. (Mind that binary_c has to be configured to print them if your not using a custom logging function)
result_example_header = parse_output(output, 'example_header') result_example_header = parse_output(output, 'example_header')
...@@ -140,4 +141,4 @@ def run_example_binary_with_writing_logfile(): ...@@ -140,4 +141,4 @@ def run_example_binary_with_writing_logfile():
# Some routine to plot. # Some routine to plot.
# run_example_binary_with_writing_logfile() run_example_binary_with_writing_logfile()
\ No newline at end of file \ No newline at end of file
This diff is collapsed.
import os, sys
import matplotlib.pyplot as plt
# Append root dir of this project to include functionality
sys.path.append(os.path.dirname(os.getcwd()))
import binary_c
from utils.defaults import physics_defaults
from utils.functions import create_arg_string
def example_with_loading_default_args():
"""
Example function loading the default physics args for a binary_c system. Got
it from the binary_grid2 perl module
This function works if binary_c is set to log something every timestep so that we can plot the evolution of a system
"""
# Load args
physics_args = physics_defaults.copy()
# Manually set M_1, M_2, orbital_period and separation values:
physics_args['M_1'] = 20
physics_args['M_2'] = 15
physics_args['separation'] = 0 # 0 = ignored, use period
physics_args['orbital_period'] = 4530.0
arg_string = create_arg_string(physics_args)
arg_string = f'binary_c {arg_string}'
buffer = ""
output = binary_c.run_binary(arg_string)
# Make some
results = {}
time_arr = []
mass_arr = []
mass_2_arr = []
# split output on newlines
for line in output.split('\n'):
# Skip any blank lines
if not line=='':
split_line = line.split()
header = split_line[0]
value_array = split_line[1:]
# Use parse data here:
if header=='TESTLOG':
# Add values to lists
time_arr.append(float(value_array[0]))
mass_arr.append(float(value_array[1]))
mass_2_arr.append(float(value_array[4]))
# Save in results dir
results['time'] = time_arr
results['mass'] = mass_arr
results['mass2'] = mass_2_arr
return results
results = example_with_loading_default_args()
# Plot some stuff
plt.plot(results['time'], results['mass'])
plt.plot(results['time'], results['mass2'])
plt.xscale('log')
plt.show()
{
"cells": [],
"metadata": {},
"nbformat": 4,
"nbformat_minor": 2
}
import argparse
class grid(object):
def __init__(self, name):
self.name = name
self.grid_options = {}
def load_grid_options(self):
self.grid_options = {
'test1': 0,
'test2': 1,
}
def argparse(self):
"""
This function handles the arg parsing of the grid.
Make sure that every grid_option key/value is included in this,
preferably with an explanation on what that parameter will do
"""
parser = argparse.ArgumentParser(description='Arguments for the binary_c python wrapper grid')
# add arguments here
parser.add_argument('--test1', type=int, help='input for test1')
parser.add_argument('--test2', type=int, help='input for test2')
# Load the args from the cmdline
args = parser.parse_args()
# Copy current grid_option set
new_grid_options = self.grid_options.copy()
# loop over grid_options
for arg in vars(args):
# print ("arg: {arg} value: {value}".format(arg=arg, value=getattr(args, arg)))
# If an input has been given in the cmdline: override the previous value of grid_options
if getattr(args, arg):
new_grid_options[arg] = getattr(args, arg)
# Put the new grid options back
self.grid_options = new_grid_options.copy()
newgrid = grid('test')
newgrid.load_grid_options()
print(newgrid.grid_options)
newgrid.argparse()
print(newgrid.grid_options)
# Custom set a single value:
newgrid.grid_options['test2'] = 2
print(newgrid.grid_options)
# Custom set multiple values:
newgrid.grid_options.update({
'test1':4,
'test2':-2,
})
print(newgrid.grid_options)
import multiprocessing
import time
def doubler(number):
return number ** 2
def count(number):
nr = 0
for i in range(number):
nr += i
return number
if __name__ == '__main__':
numbers = range(2, 100000)
pool = multiprocessing.Pool(processes=6)
# print()
rs = pool.map_async(pool.map(count, numbers), range(len(numbers)))
pool.close() # No more work
while (True):
if (rs.ready()): break
remaining = rs._number_left
print("Waiting for", remaining, "tasks to complete...")
time.sleep(0.5)
\ No newline at end of file
import time
def basic_func(x):
if x == 0:
return 'zero'
elif x%2 == 0:
return 'even'
else:
return 'odd'
starttime = time.time()
for i in range(0,10):
y = i*i
time.sleep(2)
print('{} squared results in a/an {} number'.format(i, basic_func(y)))
print('That took {} seconds'.format(time.time() - starttime))
\ No newline at end of file
import time
import multiprocessing
def basic_func(x):
if x == 0:
return 'zero'
elif x%2 == 0:
return 'even'
else:
return 'odd'
def multiprocessing_func(x):
y = x*x
time.sleep(2)
print('{} squared results in a/an {} number'.format(x, basic_func(y)))
if __name__ == '__main__':
starttime = time.time()
processes = []
for i in range(0,100):
p = multiprocessing.Process(target=multiprocessing_func, args=(i,))
processes.append(p)
p.start()
for process in processes:
process.join()
print('That took {} seconds'.format(time.time() - starttime))
\ No newline at end of file
import time
import multiprocessing
# https://medium.com/@urban_institute/using-multiprocessing-to-make-python-code-faster-23ea5ef996ba
def basic_func(x):
if x == 0:
return 'zero'
elif x%2 == 0:
return 'even'
else:
return 'odd'
def multiprocessing_func(x):
y = x*x
time.sleep(2)
print('{} squared results in a/an {} number'.format(x, basic_func(y)))
if __name__ == '__main__':
starttime = time.time()
pool = multiprocessing.Pool()
pool.map(multiprocessing_func, range(0,10))
pool.close()
print('That took {} seconds'.format(time.time() - starttime))
\ No newline at end of file
from multiprocessing import Process, Queue
import time
import sys
def reader_proc(queue):
## Read from the queue; this will be spawned as a separate Process
while True:
msg = queue.get() # Read from the queue and do nothing
if (msg == 'DONE'):
break
def writer(count, queue):
## Write to the queue
for ii in range(0, count):
queue.put(ii) # Write 'count' numbers into the queue
queue.put('DONE')
if __name__=='__main__':
pqueue = Queue() # writer() writes to pqueue from _this_ process
for count in [10**4, 10**5, 10**6]:
### reader_proc() reads from pqueue as a separate process
reader_p = Process(target=reader_proc, args=((pqueue),))
reader_p.daemon = True
reader_p.start() # Launch reader_proc() as a separate python process
_start = time.time()
writer(count, pqueue) # Send a lot of stuff to reader()
reader_p.join() # Wait for the reader to finish
print("Sending {0} numbers to Queue() took {1} seconds".format(count,
(time.time() - _start)))
\ No newline at end of file
import os, sys, time
import matplotlib.pyplot as plt
from collections import defaultdict
import numpy as np
import pandas as pd
# sys.path.append('../')
import binary_c
from binaryc_python_utils.functions import create_arg_string, parse_output, run_system
"""
Script to test some auto reading out.
todo: make to hdf5
"""
start = time.time()
output = run_system(M_1=10, M_2=20, separation=0, orbital_period=100000000000)
result = parse_output(output, 'DAVID_SINGLE_ANALYSIS')
stop = time.time()
print("Took {:.2f}s to run single system".format(stop-start))
print("The following keys are present in the results:\n{}".format(result.keys()))
#### Now do whatever you want with it:
#t_res = np.asarray(result['t'], dtype=np.float64, order='C')
#m_res = np.asarray(result['mass'], dtype=np.float64, order='C')
# Cast the data into a dataframe.
df = pd.DataFrame.from_dict(result, dtype=np.float64)
sliced_df = df[df.t < 1000] # Cut off late parts of evolution
# print(sliced_df["t"])
plt.plot(sliced_df['omega'], sliced_df['radius'])
plt.xlabel('Time (Myr)')
plt.ylabel('omega (Rsol)')
plt.show()
\ No newline at end of file
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