Skip to content

Commit e167b79

Browse files
authored
Merge pull request #144 from stared/i141-script-mode
Added script mode and autodetecting
2 parents 9021fa3 + 2c5c9a2 commit e167b79

File tree

5 files changed

+72
-24
lines changed

5 files changed

+72
-24
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Look at notebook files with full working [examples](https://github.com/stared/li
4949

5050
- [keras.ipynb](https://github.com/stared/livelossplot/blob/master/examples/keras.ipynb) - a Keras callback
5151
- [minimal.ipynb](https://github.com/stared/livelossplot/blob/master/examples/minimal.ipynb) - a bare API, to use anywhere
52+
- [script.py](https://github.com/stared/livelossplot/blob/master/examples/script.py) - to be run as a script, `python script.py`
5253
- [bokeh.ipynb](https://github.com/stared/livelossplot/blob/master/examples/bokeh.ipynb) - a bare API, plots with Bokeh ([open it in Colab to see the plots](https://colab.research.google.com/github/stared/livelossplot/blob/master/examples/bokeh.ipynb))
5354
- [pytorch.ipynb](https://github.com/stared/livelossplot/blob/master/examples/pytorch.ipynb) - a bare API, as applied to PyTorch
5455
- [2d_prediction_maps.ipynb](https://github.com/stared/livelossplot/blob/master/examples/2d_prediction_maps.ipynb) - example of custom plots - 2d prediction maps (0.4.1+)

examples/minimal.ipynb

Lines changed: 20 additions & 20 deletions
Large diffs are not rendered by default.

examples/script.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# from livelossplot 0.5.6
2+
3+
from time import sleep
4+
import numpy as np
5+
from livelossplot import PlotLosses
6+
7+
plotlosses = PlotLosses(mode="script")
8+
9+
for i in range(10):
10+
plotlosses.update(
11+
{
12+
"acc": 1 - np.random.rand() / (i + 2.0),
13+
"val_acc": 1 - np.random.rand() / (i + 0.5),
14+
"loss": 1.0 / (i + 2.0),
15+
"val_loss": 1.0 / (i + 0.5),
16+
}
17+
)
18+
plotlosses.send()
19+
sleep(0.5)

livelossplot/outputs/matplotlib_plot.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import math
2-
from typing import Tuple, List, Dict, Optional, Callable
2+
from typing import Tuple, List, Dict, Optional, Callable, Literal
33

44
import warnings
55

@@ -50,6 +50,7 @@ def __init__(
5050
self._before_plots = before_plots if before_plots else self._default_before_plots
5151
self._after_plots = after_plots if after_plots else self._default_after_plots
5252
self.figsize = figsize
53+
self.output_mode: Literal['notebook', 'script'] = "notebook"
5354

5455
def send(self, logger: MainLogger):
5556
"""Draw figures with metrics and show"""
@@ -110,7 +111,11 @@ def _default_after_plots(self, fig: plt.Figure):
110111
if self.figpath is not None:
111112
fig.savefig(self.figpath.format(i=self.file_idx))
112113
self.file_idx += 1
113-
plt.show()
114+
if self.output_mode == "script":
115+
plt.draw()
116+
plt.pause(0.1)
117+
else:
118+
plt.show()
114119

115120
def _draw_metric_subplot(self, ax: plt.Axes, group_logs: Dict[str, List[LogItem]], group_name: str, x_label: str):
116121
"""
@@ -139,3 +144,6 @@ def _not_inline_warning(self):
139144
"livelossplot requires inline plots.\nYour current backend is: {}"
140145
"\nRun in a Jupyter environment and execute '%matplotlib inline'.".format(backend)
141146
)
147+
148+
def _set_output_mode(self, mode: Literal['notebook', 'script']):
149+
self.output_mode = mode

livelossplot/plot_losses.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import warnings
2-
from typing import Type, TypeVar, List, Union, Optional, Tuple
2+
from typing import Type, TypeVar, List, Union, Optional, Tuple, Literal
33

44
import livelossplot
55
from livelossplot.main_logger import MainLogger
@@ -9,14 +9,32 @@
99
BO = TypeVar('BO', bound=outputs.BaseOutput)
1010

1111

12+
def get_mode() -> Literal['notebook', 'script']:
13+
try:
14+
from IPython import get_ipython
15+
ipython = get_ipython()
16+
if ipython is None:
17+
return 'script'
18+
name = ipython.__class__.__name__
19+
if name == "ZMQInteractiveShell" or name == "Shell":
20+
# Shell is in Colab
21+
return "notebook"
22+
elif name == "TerminalInteractiveShell":
23+
return "script"
24+
print(f"Unknown IPython mode: {name}. Assuming notebook mode.")
25+
return "notebook"
26+
except ImportError:
27+
return "script"
28+
29+
1230
class PlotLosses:
1331
"""
1432
Class collect metrics from the training engine and send it to plugins, when send is called
1533
"""
1634
def __init__(
1735
self,
1836
outputs: List[Union[Type[BO], str]] = ['MatplotlibPlot', 'ExtremaPrinter'],
19-
mode: str = 'notebook',
37+
mode: Optional[Literal['notebook', 'script']] = None,
2038
figsize: Optional[Tuple[int, int]] = None,
2139
**kwargs
2240
):
@@ -31,6 +49,8 @@ def __init__(
3149
"""
3250
self.logger = MainLogger(**kwargs)
3351
self.outputs = [getattr(livelossplot.outputs, out)() if isinstance(out, str) else out for out in outputs]
52+
if mode is None:
53+
mode = get_mode()
3454
for out in self.outputs:
3555
out.set_output_mode(mode)
3656
if figsize is not None and isinstance(out, MatplotlibPlot):

0 commit comments

Comments
 (0)