Skip to content

Commit 2b4625f

Browse files
authored
Merge pull request #137 from nwittler/log-reader
Updated log reader and added docs.
2 parents dcdb2be + a2771fa commit 2b4625f

File tree

6 files changed

+112
-29
lines changed

6 files changed

+112
-29
lines changed

c3/utils/log_reader.py

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,25 @@
1-
#!/usr/bin/python -u
1+
#!/usr/bin/env python3
22

33
import time
44
import argparse
55
import hjson
6-
from c3.c3objs import hjson_decode
6+
from typing import Any, Dict
7+
78
from c3.utils.utils import num3str
89
from rich.console import Console
910
from rich.table import Table
1011

1112

12-
parser = argparse.ArgumentParser()
13-
parser.add_argument("log_file")
14-
parser.add_argument("-w", "--watch", action="store_true")
15-
args = parser.parse_args()
16-
17-
log = None
18-
19-
try:
20-
with open(args.log_file) as file:
21-
log = hjson.load(file, object_pairs_hook=hjson_decode)
22-
except FileNotFoundError:
23-
print("Logfile not found.")
13+
def show_table(log: Dict[str, Any], console: Console) -> None:
14+
"""Generate a rich table from an optimization status and display it on the console.
2415
25-
26-
def show_table():
16+
Parameters
17+
----------
18+
log : Dict
19+
Dictionary read from a json log file containing a c3-toolset optimization status.
20+
console : Console
21+
Rich console for output.
22+
"""
2723
if log:
2824
opt_map = log["opt_map"]
2925
optim_status = log["optim_status"]
@@ -35,19 +31,16 @@ def show_table():
3531
table.add_column("Parameter")
3632
table.add_column("Value", justify="right")
3733
table.add_column("Gradient", justify="right")
38-
for ii in range(len(opt_map)):
39-
equiv_ids = opt_map[ii]
34+
for ii, equiv_ids in enumerate(opt_map):
4035
par = params[ii]
4136
grad = grads[ii]
4237
par = num3str(par)
4338
grad = num3str(grad)
4439
par_id = equiv_ids[0]
45-
nice_id = "-".join(par_id)
46-
table.add_row(nice_id, par + units[ii], grad + units[ii])
40+
table.add_row(par_id, par + units[ii], grad + units[ii])
4741
if len(equiv_ids) > 1:
4842
for par_id in equiv_ids[1:]:
49-
nice_id = "-".join(par_id)
50-
table.add_row(nice_id, "''", "''")
43+
table.add_row(par_id, "''", "''")
5144

5245
console.clear()
5346
print(
@@ -56,10 +49,27 @@ def show_table():
5649
console.print(table)
5750

5851

59-
console = Console()
60-
if args.watch:
61-
while True:
62-
show_table()
63-
time.sleep(5)
64-
else:
65-
show_table()
52+
if __name__ == "__main__":
53+
parser = argparse.ArgumentParser()
54+
parser.add_argument("log_file")
55+
parser.add_argument(
56+
"-w",
57+
"--watch",
58+
type=int,
59+
default=0,
60+
help="Update the table every WATCH seconds.",
61+
)
62+
args = parser.parse_args()
63+
64+
try:
65+
with open(args.log_file) as file:
66+
log = hjson.load(file)
67+
console = Console()
68+
if args.watch:
69+
while True:
70+
show_table(log, console)
71+
time.sleep(args.watch)
72+
else:
73+
show_table(log, console)
74+
except FileNotFoundError:
75+
print("Logfile not found. Quiting...")

c3/utils/parsers.py

Whitespace-only changes.

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ When combined in sequence, these three procedures represent a recipe for system
3232
optimal_control
3333
Simulated_calibration
3434
Simulated_Model_Learning
35+
log_reader
3536
c3_qiskit_example
3637
c3
3738

docs/log_reader.rst

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
Logs and current optimization status
2+
====================================
3+
4+
During optimizations (optimal control, calibration, model learning), a
5+
current best point is stored in the log folder to monitor progress.
6+
Called on a log file it will print a
7+
`rich <https://github.com/willmcgugan/rich>`__ table of the current
8+
status. With the ``-w`` or ``-- watch`` options the table will keep
9+
updating.
10+
11+
.. code:: bash
12+
13+
c3/utils/log_reader.py -h
14+
15+
16+
.. code-block::
17+
18+
usage: log_reader.py [-h] [-w WATCH] log_file
19+
20+
positional arguments:
21+
log_file
22+
23+
optional arguments:
24+
-h, --help show this help message and exit
25+
-w WATCH, --watch WATCH
26+
Update the table every WATCH seconds.
27+
28+
29+
Using the example log from the test folder:
30+
31+
.. code:: bash
32+
33+
c3/utils/log_reader.py test/sample_optim_log.c3log
34+
35+
36+
.. parsed-literal::
37+
38+
Optimization reached 0.00462 at Tue Aug 17 15:28:09 2021
39+
40+
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┓
41+
┃ Parameter ┃ Value ┃ Gradient ┃
42+
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━┩
43+
│ rx90p[0]-d1-gauss-amp │ 497.311 mV │ 18.720 mV │
44+
│ rx90p[0]-d1-gauss-freq_offset │ -52.998 MHz 2pi │ -414.237 µHz 2pi │
45+
│ rx90p[0]-d1-gauss-xy_angle │ -47.409 mrad │ 2.904 mrad │
46+
│ rx90p[0]-d1-gauss-delta │ -1.077 │ 6.648 m │
47+
└───────────────────────────────┴─────────────────┴──────────────────┘
48+

test/sample_optim_log.c3log

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"opt_map": [["rx90p[0]-d1-gauss-amp"], ["rx90p[0]-d1-gauss-freq_offset"], ["rx90p[0]-d1-gauss-xy_angle"], ["rx90p[0]-d1-gauss-delta"]], "units": ["V", "Hz 2pi", "rad", ""], "optim_status": {"params": [0.49731057256150457, -52997604.24565414, -0.0474089606329513, -1.0765842275871154], "goal": 0.004623751716391289, "time": "Tue Aug 17 15:28:09 2021", "gradient": [0.018719753658557353, -0.00041423747880565335, 0.0029041996681835715, 0.006648118709775015]}}

test/test_cli_utils.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""
2+
Tests for command line utilities.
3+
"""
4+
5+
import pytest
6+
import hjson
7+
from rich.console import Console
8+
9+
from c3.c3objs import hjson_decode
10+
from c3.utils.log_reader import show_table
11+
12+
SAMPLE_LOG = "test/sample_optim_log.c3log"
13+
14+
15+
@pytest.mark.unit
16+
def test_log_viewer():
17+
"""
18+
Check that the log is read and processed without error. This does not check if
19+
the output is correct.
20+
"""
21+
console = Console()
22+
with open(SAMPLE_LOG) as logfile:
23+
show_table(hjson.load(logfile, object_pairs_hook=hjson_decode), console)

0 commit comments

Comments
 (0)