-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add value setter for simple logged quantities. #69
Changes from all commits
567147f
28d67ea
afd9274
82facd4
1c01d3e
8895f00
5b97314
493958a
136c637
601238b
2161715
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
#!/usr/bin/env python3 | ||
|
||
from time import sleep | ||
from typing import Any | ||
from random import uniform | ||
from logpyle import (LogManager, add_general_quantities, | ||
add_simulation_quantities, add_run_info, IntervalTimer, | ||
|
@@ -10,6 +11,26 @@ | |
from mpi4py import MPI | ||
|
||
|
||
class PushLogQuantity(LogQuantity): | ||
"""Logging support for arbitrary user quantities.""" | ||
MTCam marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
def __init__(self, name, value=None, unit=None, | ||
description=None) -> None: | ||
LogQuantity.__init__(self, name=name, unit=unit, | ||
description=description) | ||
self._quantity_value = value | ||
|
||
def __call__(self) -> float: | ||
"""Return the actual logged quantity.""" | ||
val = self._quantity_value | ||
self._quantity_value = None | ||
return val | ||
|
||
def set_quantity_value(self, value: Any) -> None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Naming? I think |
||
"""Set the value of the logged quantity.""" | ||
self._quantity_value = value | ||
|
||
|
||
class Fifteen(LogQuantity): | ||
@property | ||
def default_aggregator(self): | ||
|
@@ -43,14 +64,18 @@ def main(): | |
vis_timer = IntervalTimer("t_vis", "Time spent visualizing") | ||
logmgr.add_quantity(vis_timer) | ||
logmgr.add_quantity(Fifteen("fifteen")) | ||
logmgr.add_quantity(PushLogQuantity("q1")) | ||
|
||
# Watches are printed periodically during execution | ||
logmgr.add_watches([("step.max", "step={value} "), | ||
("t_step.min", "\nt_step({value:g},"), ("t_step.max", " {value:g})\n"), | ||
"t_sim.max", "fifteen", "t_vis.max"]) | ||
("t_step.min", "\nt_step({value:g},"), | ||
("t_step.max", " {value:g})\n"), | ||
("q1.max", " UserQ1:({value:g}), "), | ||
"t_sim.max", "fifteen", "t_vis.max"]) | ||
|
||
for istep in range(200): | ||
logmgr.tick_before() | ||
logmgr.set_quantity_value("q1", 2*istep) | ||
|
||
dt = uniform(0.01, 0.1) | ||
set_dt(logmgr, dt) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,6 +97,7 @@ class LogQuantity: | |
.. automethod:: tick | ||
.. autoproperty:: default_aggregator | ||
.. automethod:: __call__ | ||
.. automethod:: set_quantity_value | ||
""" | ||
|
||
sort_weight = 0 | ||
|
@@ -136,6 +137,10 @@ def __call__(self) -> Optional[float]: | |
""" | ||
raise NotImplementedError | ||
|
||
def set_quantity_value(self, value: Any) -> None: | ||
"""Set the logged quantity value.""" | ||
raise NotImplementedError | ||
|
||
|
||
class PostLogQuantity(LogQuantity): | ||
"""A source of a loggable scalar that is gathered after each time step. | ||
|
@@ -289,10 +294,12 @@ def __init__(self, quantity: LogQuantity, interval: int) -> None: | |
|
||
class _QuantityData: | ||
def __init__(self, unit: str, description: str, | ||
default_aggregator: Callable) -> None: | ||
default_aggregator: Callable, | ||
value_setter: Callable = None) -> None: | ||
self.unit = unit | ||
self.description = description | ||
self.default_aggregator = default_aggregator | ||
self.value_setter = value_setter | ||
|
||
|
||
def _join_by_first_of_tuple(list_of_iterables): | ||
|
@@ -741,6 +748,20 @@ def set_constant(self, name: str, value: Any) -> None: | |
|
||
self._commit() | ||
|
||
def set_quantity_value(self, name: str, value: Any) -> None: | ||
"""Set a the value of a named LogQuantity. | ||
|
||
:param name: the name of the logged quantity. | ||
:param value: the value of the logged quantity. | ||
""" | ||
if name in self.quantity_data: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just access it and handle the |
||
value_setter = self.quantity_data[name].value_setter | ||
if value_setter: | ||
value_setter(value) | ||
else: | ||
from warnings import warn | ||
warn(f"No value_setter defined for log quantity (name={name}).") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should probably be an error. |
||
|
||
Comment on lines
+751
to
+764
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make this a function instead. |
||
def _insert_datapoint(self, name: str, value: Optional[float]) -> None: | ||
if value is None: | ||
return | ||
|
@@ -867,12 +888,13 @@ def add_quantity(self, quantity: LogQuantity, interval: int = 1) -> None: | |
:param interval: interval (in time steps) when to gather this quantity. | ||
""" | ||
|
||
def add_internal(name, unit, description, def_agg): | ||
def add_internal(name, unit, description, def_agg, val_set=None): | ||
logger.debug("add log quantity '%s'" % name) | ||
|
||
if name in self.quantity_data: | ||
raise RuntimeError("cannot add the same quantity '%s' twice" % name) | ||
self.quantity_data[name] = _QuantityData(unit, description, def_agg) | ||
self.quantity_data[name] = _QuantityData(unit, description, def_agg, | ||
val_set) | ||
|
||
from pickle import dumps | ||
self.db_conn.execute("""insert into quantities values (?,?,?,?)""", ( | ||
|
@@ -901,8 +923,9 @@ def add_internal(name, unit, description, def_agg): | |
add_internal(name, unit, description, def_agg) | ||
else: | ||
add_internal(quantity.name, | ||
quantity.unit, quantity.description, | ||
quantity.default_aggregator) | ||
quantity.unit, quantity.description, | ||
quantity.default_aggregator, | ||
quantity.set_quantity_value) | ||
|
||
def get_expr_dataset(self, expression, description=None, unit=None): | ||
"""Prepare a time-series dataset for a given expression. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than duplicating it, please move this somewhere and import from there.