Skip to content

Commit 19a1a5c

Browse files
committed
Updating front page
1 parent 2b3978a commit 19a1a5c

File tree

3 files changed

+272
-15
lines changed

3 files changed

+272
-15
lines changed

README.rst

+151-15
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,170 @@
22
ABR Analyze
33
***********
44

5-
ABR_Analyze: A repository for saving, processing, and plotting data from an hdf5 database.
5+
ABR_Analyze: A repository with helper functions wrapping the hdf5 package. Allows for simplified saving, loading, and searching of data.
66

77
Installation
88
============
9+
To install abr_analyze simply run::
910

10-
The ABR_Analyze repo depends on NumPy, SciPy, Matplotlib, and H5Py, and we recommend that
11-
you install these libraries before ABR_Analyze. If you're not sure how to do this,
12-
we recommend using `Anaconda <https://store.continuum.io/cshop/anaconda/>`_.
13-
Note that installing in a clean environment will require compiling of the
14-
dependent libraries, and will take a few minutes.
11+
pip install -e .
1512

16-
ABR_Analyze is tested to work on Python 3.4+.
13+
Features that visualize robotic arms require an install of abr_control::
1714

15+
git clone https://github.com/abr/abr_control.git
16+
17+
cd abr_control
18+
19+
pip install -e .
1820

1921
Setting paths
2022
=============
23+
HFF5 databases can be thought of as a compressed file (.h5) that saves dictionaries. Keys, including keys for nested dictionaries, are treated as folders with the corresponding values being the data entries.
24+
25+
By default, abr_analyze will create a ``data/databases`` folder from the run directory to store databases. This directory can alternatively be set on instantation of a ``DataHandler`` with the ``<database_dir>`` parameter.
26+
27+
To set the default value to avoid passing a folder in on init, update ``abr_analyze/paths.txt`` to have the full path to your save directory following the ``<database_dir:>`` entry.
28+
29+
Manually saving and loading
30+
=====
31+
1. Instantiate a database::
32+
33+
from abr_analyze import DataHandler
34+
35+
database = DataHandler('database_name')
2136

22-
See abr_analyze/paths.py and adjust your default locations for
23-
databases, figures, and cached items
37+
2. Save Results::
2438

25-
A default paths.py is committed, to avoid running into conflicts with
26-
you personal setup, run::
39+
my_results = {'key1': 3, 'key2': [3, 4, 5], 'nested_dict': {'a': 3, 'b': 6}}
40+
database.save(
41+
save_location='experiment1',
42+
data=my_results
43+
}
2744

28-
git update-index --assume-unchanged <path to paths.py>
45+
3. Load Data::
2946

30-
this will assume the file is unchanged and will not commit it.
47+
subset_loaded_data = database.load('experiment1', parameters=['nested_dict'])
48+
# or load all keys
49+
all_loaded_data = database.load('experiment1')
3150

32-
Usage
51+
Automated Saving with data_logger
3352
=====
53+
Alternatively, abr_analyze can automatically save and link results to the parameters that generated them, provided a dictionary of parameters, a dictionary of results, and a unique name for the script that generated the results with the data_logger.searchable_save() function::
54+
55+
from abr_analyze import data_logger
56+
57+
# Instantiate database to save results
58+
db_name = "searchable_results_example"
59+
dat = DataHandler(db_name=db_name)
60+
61+
# generate baseline json
62+
params = {
63+
"sin_params": {
64+
"A": 3,
65+
"shift": 5,
66+
},
67+
"time": [0, 5, 100],
68+
"exp": 2,
69+
}
70+
71+
# if loading from json
72+
# with open(json_fp) as fp:
73+
# params = json.load(fp)
74+
75+
# example function that generates results
76+
# Needs to accept params dict as input and return dictionary of results
77+
def example_results(params):
78+
t = np.linspace(params["time"][0], params["time"][1], params["time"][2])
79+
y = (
80+
params["sin_params"]["A"]
81+
* np.sin(t - params["sin_params"]["shift"]) ** params["exp"]
82+
)
83+
return {"t": t, "y": y}
84+
85+
# unique name for script that generates results
86+
# should update name if something changes in the script that would affect results
87+
script_name = "example_script"
88+
89+
# get results
90+
print("--Getting results for baseline parameters--")
91+
results = example_results(params)
92+
93+
# save in searchable format
94+
print("--Saving baseline results--")
95+
data_logger.searchable_save(dat=dat, results=results, params=params, script_name=script_name)
96+
97+
Running Parameter Variations
98+
=====
99+
The data_logger also has a helper function for quickly generating permutations of a parameter set. These can be saved in the same searchable manner to allow for a quick comparison of results::
100+
101+
# helper function to quickly create some variations of our parameter set
102+
print("--Generating parameter variations--")
103+
param_variations = data_logger.gen_parameter_variations(
104+
params=params, variation_dict={"sin_params/A": [5, 7, 10], "exp": [3, 4]}
105+
)
106+
107+
# get results for each variation and save
108+
print("--Getting results for parameter variations--")
109+
for hash_id, varied_params in param_variations.items():
110+
print(f"\nGetting results for {hash_id}")
111+
# pretty printing of nested dictionaries
112+
data_logger.print_nested(varied_params, indent=0, return_val=False)
113+
114+
results = example_results(varied_params)
115+
print("Saving results")
116+
data_logger.searchable_save(
117+
dat=dat, results=results, params=varied_params, script_name=script_name
118+
)
119+
120+
Searching and Plotting Results
121+
=====
122+
Once some results and their corresponding parameter sets have been saved using data_logger.searchable_save(), the results can be searched for experiments that match a subset of parameters::
123+
124+
# now load all results that have these parameter values
125+
const_params = {
126+
"exp": 3,
127+
}
128+
# result keys to load
129+
result_keys = ["y"]
130+
131+
# Load results that have a set of common parameters
132+
print(f"Loading results with parameters:\n{const_params}")
133+
results = data_logger.load_results(
134+
script_name=script_name,
135+
const_params=const_params,
136+
saved_exp_hashes=None,
137+
result_keys=result_keys,
138+
dat=dat,
139+
ignore_keys=None,
140+
)
141+
142+
# plot the results
143+
plt.figure()
144+
ax = plt.subplot(111)
145+
for hash_name in results:
146+
# ignore const and variable params keys
147+
if "params" in hash_name:
148+
continue
149+
# print(dict_nested2str(results[hash_name]))
150+
ax.plot(results[hash_name]["results"]["y"], label=results[hash_name]["name"])
151+
152+
# print the values that are constant between all tests
153+
ax.text(
154+
0,
155+
-5,
156+
(
157+
"Constant Parameters\n"
158+
+ "___________________\n"
159+
+ data_logger.dict_nested2str(results["const_params"])
160+
),
161+
fontsize=8,
162+
)
163+
plt.subplots_adjust(right=0.6)
164+
165+
plt.legend()
166+
plt.tight_layout()
167+
plt.show()
168+
169+
.. image:: docs/searchable_save_plot.png
34170

35-
To understand how to use this code, check out the code in the examples folder.
171+
See the examples folder for examples covering the full range of functionality of the repository, including: plotting grids of figures, coverting figures to gifs, replaying arm trajectories in 3d plot gifs, and many more.

docs/searchable_save_plot.png

48.1 KB
Loading

examples/searchable_save_and_plot.py

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import numpy as np
2+
3+
from abr_analyze import DataHandler, data_logger
4+
5+
import matplotlib.pyplot as plt
6+
7+
# Instantiate database to save results
8+
db_name = "searchable_results_example"
9+
db_folder = None
10+
dat = DataHandler(db_name=db_name, database_dir=db_folder)
11+
12+
# generate baseline json
13+
params = {
14+
"sin_params": {
15+
"A": 3,
16+
"shift": 5,
17+
},
18+
"time": [0, 5, 100],
19+
"exp": 2,
20+
}
21+
22+
# if loading from json
23+
# with open(json_fp) as fp:
24+
# params = json.load(fp)
25+
26+
# example function that generates results
27+
# Needs to accept params dict as input and return dictionary of results
28+
def example_results(params):
29+
t = np.linspace(params["time"][0], params["time"][1], params["time"][2])
30+
y = (
31+
params["sin_params"]["A"]
32+
* np.sin(t - params["sin_params"]["shift"]) ** params["exp"]
33+
)
34+
return {"t": t, "y": y}
35+
36+
# unique name for script that generates results
37+
# should update name if something changes in the script that would affect results
38+
script_name = "example_script"
39+
40+
# get results
41+
print("--Getting results for baseline parameters--")
42+
results = example_results(params)
43+
44+
# save in searchable format
45+
print("--Saving baseline results--")
46+
data_logger.searchable_save(dat=dat, results=results, params=params, script_name=script_name)
47+
48+
# helper function to quickly create some variations of our parameter set
49+
print("--Generating parameter variations--")
50+
param_variations = data_logger.gen_parameter_variations(
51+
params=params, variation_dict={"sin_params/A": [5, 7, 10], "exp": [3, 4]}
52+
)
53+
54+
# get results for each variation and save
55+
print("--Getting results for parameter variations--")
56+
for hash_id, varied_params in param_variations.items():
57+
print(f"\nGetting results for {hash_id}")
58+
# pretty printing of nested dictionaries
59+
data_logger.print_nested(varied_params, indent=0, return_val=False)
60+
61+
results = example_results(varied_params)
62+
print("Saving results")
63+
data_logger.searchable_save(
64+
dat=dat, results=results, params=varied_params, script_name=script_name
65+
)
66+
67+
# now load all results that have these parameter values
68+
const_params = {
69+
"exp": 3,
70+
}
71+
# result keys to load
72+
result_keys = ["y"]
73+
74+
# Load results that have a set of common parameters
75+
print(f"Loading results with parameters:\n{const_params}")
76+
results = data_logger.load_results(
77+
script_name=script_name,
78+
const_params=const_params,
79+
saved_exp_hashes=None,
80+
result_keys=result_keys,
81+
dat=dat,
82+
ignore_keys=None,
83+
)
84+
85+
# plot the results
86+
plt.figure()
87+
ax = plt.subplot(111)
88+
for hash_name in results:
89+
# ignore const and variable params keys
90+
if "params" in hash_name:
91+
continue
92+
# print(dict_nested2str(results[hash_name]))
93+
ax.plot(results[hash_name]["results"]["y"], label=results[hash_name]["name"])
94+
95+
# print the values that are constant between all tests
96+
ax.text(
97+
0,
98+
-5,
99+
(
100+
"Constant Parameters\n"
101+
+ "___________________\n"
102+
+ data_logger.dict_nested2str(results["const_params"])
103+
),
104+
fontsize=8,
105+
)
106+
plt.subplots_adjust(right=0.6)
107+
108+
plt.legend()
109+
plt.tight_layout()
110+
plt.show()
111+
112+
# Load results from a list of exp hashes
113+
# load_results(
114+
# script_name=script_name,
115+
# const_params=None,
116+
# saved_exp_hashes=saved_exp_hashes,
117+
# result_keys=result_keys,
118+
# dat=dat,
119+
# ignore_keys=None
120+
# )
121+

0 commit comments

Comments
 (0)