Advanced: Undo/Redo

Setup

Let's first make sure we have the latest version of PHOEBE 2.1 installed. (You can comment out this line if you don't use pip for your installation or don't want to update to the latest release).


In [ ]:
!pip install -I "phoebe>=2.1,<2.2"

As always, let's do imports and initialize a logger and a new bundle. See Building a System for more details.


In [1]:
%matplotlib inline

In [2]:
import phoebe
from phoebe import u # units
import numpy as np
import matplotlib.pyplot as plt

logger = phoebe.logger(clevel='INFO')

b = phoebe.default_binary()


/usr/local/lib/python2.7/dist-packages/IPython/kernel/__init__.py:13: ShimWarning: The `IPython.kernel` package has been deprecated. You should import from ipykernel or jupyter_client instead.
  "You should import from ipykernel or jupyter_client instead.", ShimWarning)
WARNING: Constant u'Gravitational constant' is already has a definition in the u'si' system [astropy.constants.constant]
WARNING:astropy:Constant u'Gravitational constant' is already has a definition in the u'si' system
WARNING: Constant u'Solar mass' is already has a definition in the u'si' system [astropy.constants.constant]
WARNING:astropy:Constant u'Solar mass' is already has a definition in the u'si' system
WARNING: Constant u'Solar radius' is already has a definition in the u'si' system [astropy.constants.constant]
WARNING:astropy:Constant u'Solar radius' is already has a definition in the u'si' system
WARNING: Constant u'Solar luminosity' is already has a definition in the u'si' system [astropy.constants.constant]
WARNING:astropy:Constant u'Solar luminosity' is already has a definition in the u'si' system
/usr/local/lib/python2.7/dist-packages/astropy/units/quantity.py:732: FutureWarning: comparison to `None` will result in an elementwise object comparison in the future.
  return super(Quantity, self).__eq__(other)

Enabling/Disabling Logging History

Undo and redo support is built directly into the bundle. Every time you make a change to a parameter or call a method, a new Parameter is created with the 'history' context. These parameters then know how to undo or redo that action. Of course, this can result in a large list of Parameters that you may not want - see the tutorial on Settings for more details on how to change the log size or enable/disable history entirely.

By default history logging is off, so let's first enable it.


In [3]:
b.enable_history()

Undoing

First let's set a value so we know what we're expecting to undo


In [4]:
b['ra@system']


Out[4]:
<Parameter: ra=0.0 deg | keys: description, value, quantity, default_unit, limits, visible_if, copy_for>

In [5]:
b['ra@system'] = 10
b['ra@system']


Out[5]:
<Parameter: ra=10.0 deg | keys: description, value, quantity, default_unit, limits, visible_if, copy_for>

The history context contains a list of parameters, all numbered and ugly. But there is a convenience method which allows you to get history items by index - including reverse indexing. This is probably the most common way to get a history item... and you'll most likely want the LATEST item.


In [6]:
b.get_history(-1)


Out[6]:
<HistoryParameter: hist01 | keys: redo_func, redo_kwargs, undo_func, undo_kwargs>

In [7]:
print b.get_history(-1)['redo_func'], b.get_history(-1)['redo_kwargs']


set_value {'twig': 'ra@system', 'value': <Quantity 10.0 deg>}

Here you can see that redo_func and redo_kwargs shows exactly the last call we made to the bundle that actually changed something (we did b['ra@system'] = 10).

We can also look at what will be called when we undo this item


In [8]:
print b.get_history(-1)['undo_func'], b.get_history(-1)['undo_kwargs']


set_value {'twig': 'ra@system', 'value': 0.0}

If we want, we can then automatically call that undo method (note that you can also pass the index to undo, but it does assume -1 by default)


In [9]:
b.undo()

And we can see that it did exactly what we expected.


In [10]:
b['ra@system']


Out[10]:
<Parameter: ra=0.0 deg | keys: description, value, quantity, default_unit, limits, visible_if, copy_for>