scope 0.4.1__tar.gz → 0.4.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: scope
3
- Version: 0.4.1
3
+ Version: 0.4.3
4
4
  Summary: Metrics logging and analysis
5
5
  Home-page: http://github.com/danijar/scope
6
6
  Classifier: Intended Audience :: Science/Research
scope-0.4.3/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # 🔬 Scope
2
+
3
+ Scalable metrics logging and analysis.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Scalable:** Quickly log and view petabytes of metrics, thousands of keys, and large videos.
8
+ - 🎞️ **Formats:** Log and view scalars, text, images, and videos. Easy to extend with custom formats.
9
+ - 🧑🏻‍🔬 **Productivity:** Metrics viewer with focus on power users and full keyboard support.
10
+ - ☁️ **Cloud support:** Directly write to and read from Cloud storage via pathlib interface.
11
+ - 🍃 **Lightweight:** The writer and reader measure only ~400 lines of Python code.
12
+ - 🧱 **Reliability:** Unit tested and used across diverse research projects.
13
+
14
+ ## Usage
15
+
16
+ ### Installation
17
+
18
+ ```sh
19
+ pip install scope
20
+ ```
21
+
22
+ ### Writing
23
+
24
+ ```python
25
+ import scope
26
+
27
+ writer = scope.Writer(logdir)
28
+ for step in range(3)
29
+ video = np.zeros((100, 640, 360, 3), np.uint8)
30
+ writer.add(step, {'foo': 42, 'bar': video, 'baz': 'Hello World'})
31
+ writer.flush()
32
+ ```
33
+
34
+ ### Viewing
35
+
36
+ ```sh
37
+ python -m scope.viewer --basedir ... --port 8000
38
+ ```
39
+
40
+ ### Reading
41
+
42
+ ```python
43
+ import scope
44
+
45
+ reader = scope.Reader(logdir)
46
+ print(reader.keys()) # ('foo', 'bar', 'baz')
47
+
48
+ print(reader.length('foo')) # 3
49
+ steps, values = reader['foo']
50
+ print(steps) # np.array([0, 1, 2], np.int64)
51
+ print(values) # np.array([42, 42, 42], np.float64)
52
+
53
+ steps, filenames = reader['bar']
54
+ reader.load('bar', filenames[-1]) # np.zeros((100, 640, 360, 3), np.uint8)
55
+ ```
@@ -1,4 +1,4 @@
1
- __version__ = '0.4.1'
1
+ __version__ = '0.4.3'
2
2
 
3
3
  from .reader import Reader
4
4
  from .writer import Writer
@@ -21,7 +21,7 @@ class Reader:
21
21
  self.logdir = logdir / 'scope'
22
22
  self.fmts = {x.extension: x for x in formats}
23
23
  self.cols = {}
24
- for child in sorted(logdir.glob('*')):
24
+ for child in sorted(self.logdir.glob('*')):
25
25
  basename, ext = child.name.rsplit('.', 1)
26
26
  key = basename.replace('-', '/')
27
27
  assert re.match(r'[a-z0-9_]+(/[a-z0-9_]+)?', key), key
@@ -12,9 +12,10 @@ class TestFloat:
12
12
  writer.add(0, {'foo': 12})
13
13
  writer.add(5, {'foo': 42, 'bar': np.float64(np.pi)})
14
14
  writer.flush()
15
- assert {x.name for x in logdir.glob('*')} == {'foo.float', 'bar.float'}
16
- assert (logdir / 'foo.float').stat().st_size == (8 + 8) * 2
17
- assert (logdir / 'bar.float').stat().st_size == (8 + 8) * 1
15
+ filenames = (logdir / 'scope').glob('*')
16
+ assert {x.name for x in filenames} == {'foo.float', 'bar.float'}
17
+ assert (logdir / 'scope/foo.float').stat().st_size == (8 + 8) * 2
18
+ assert (logdir / 'scope/bar.float').stat().st_size == (8 + 8) * 1
18
19
  reader = scope.Reader(logdir)
19
20
  assert reader.keys() == tuple(sorted(['foo', 'bar']))
20
21
  assert reader.length('foo') == 2
@@ -29,9 +30,10 @@ class TestFloat:
29
30
  writer.add(step, {'foo': step, 'bar': step})
30
31
  writer.flush()
31
32
  writer.flush() # Block until previous flush is done.
32
- assert {x.name for x in logdir.glob('*')} == {'foo.float', 'bar.float'}
33
- assert (logdir / 'foo.float').stat().st_size == (8 + 8) * 10
34
- assert (logdir / 'bar.float').stat().st_size == (8 + 8) * 10
33
+ filenames = (logdir / 'scope').glob('*')
34
+ assert {x.name for x in filenames} == {'foo.float', 'bar.float'}
35
+ assert (logdir / 'scope/foo.float').stat().st_size == (8 + 8) * 10
36
+ assert (logdir / 'scope/bar.float').stat().st_size == (8 + 8) * 10
35
37
  reader = scope.Reader(logdir)
36
38
  assert equal(reader['foo'], (np.arange(10), np.arange(10)))
37
39
  assert equal(reader['bar'], (np.arange(10), np.arange(10)))
@@ -41,27 +43,13 @@ class TestFloat:
41
43
  writer = scope.Writer(logdir, workers=0)
42
44
  writer.add(0, {'foo/bar': 12})
43
45
  writer.flush()
44
- assert {x.name for x in logdir.glob('*')} == {'foo-bar.float'}
46
+ filenames = (logdir / 'scope').glob('*')
47
+ assert {x.name for x in filenames} == {'foo-bar.float'}
45
48
  reader = scope.Reader(logdir)
46
49
  assert reader.keys() == ('foo/bar',)
47
50
  assert reader.length('foo/bar') == 1
48
51
  assert equal(reader['foo/bar'], ([0], [12]), (np.int64, np.float64))
49
52
 
50
- # def test_slicing(self, tmpdir):
51
- # logdir = pathlib.Path(tmpdir)
52
- # writer = scope.Writer(logdir, workers=0)
53
- # writer.add(0, {'foo': 12})
54
- # writer.add(5, {'foo': 42})
55
- # writer.flush()
56
- # reader = scope.Reader(logdir)
57
- # assert equal(reader['foo', 0], ([0], [12]))
58
- # assert equal(reader['foo', :2], ([0], [12]))
59
- # assert equal(reader['foo', :5], ([0], [12]))
60
- # assert equal(reader['foo', :6], ([0, 5], [12, 42]))
61
- # assert equal(reader['foo', 1:6], ([5], [42]))
62
- # assert equal(reader['foo', :-1], ([], []))
63
- # assert equal(reader['foo', 7:], ([], []))
64
-
65
53
 
66
54
  def equal(actuals, references, dtypes=None):
67
55
  dtypes = dtypes or [x.dtype for x in actuals]
@@ -14,9 +14,9 @@ class TestImage:
14
14
  writer.add(0, {'foo': img1})
15
15
  writer.add(5, {'foo': img2})
16
16
  writer.flush()
17
- assert {x.name for x in logdir.glob('*')} == {'foo.png'}
18
- assert (logdir / 'foo.png' / 'index').stat().st_size == (8 + 8) * 2
19
- assert len(list((logdir / 'foo.png').glob('*'))) == 1 + 2
17
+ assert {x.name for x in (logdir / 'scope').glob('*')} == {'foo.png'}
18
+ assert (logdir / 'scope/foo.png/index').stat().st_size == (8 + 8) * 2
19
+ assert len(list((logdir / 'scope/foo.png').glob('*'))) == 1 + 2
20
20
  reader = scope.Reader(logdir)
21
21
  assert reader.keys() == ('foo',)
22
22
  assert reader.length('foo') == 2
@@ -33,11 +33,11 @@ class TestImage:
33
33
  writer.add(step, {key: np.full((64, 128, 3), step, np.uint8)})
34
34
  writer.flush()
35
35
  writer.flush() # Block until previous flush is done.
36
- assert {x.name for x in logdir.glob('*')} == {
36
+ assert {x.name for x in (logdir / 'scope').glob('*')} == {
37
37
  'foo.png', 'bar.png', 'baz.png'}
38
38
  for key in ('foo', 'bar', 'baz'):
39
- assert (logdir / f'{key}.png' / 'index').stat().st_size == (8 + 8) * 5
40
- assert len(list((logdir / f'{key}.png').glob('*'))) == 1 + 5
39
+ assert (logdir / f'scope/{key}.png/index').stat().st_size == (8 + 8) * 5
40
+ assert len(list((logdir / f'scope/{key}.png').glob('*'))) == 1 + 5
41
41
  reader = scope.Reader(logdir)
42
42
  assert reader.keys() == tuple(sorted(['foo', 'bar', 'baz']))
43
43
  for key in ('foo', 'bar', 'baz'):
@@ -55,34 +55,11 @@ class TestImage:
55
55
  writer = scope.Writer(logdir, workers=0)
56
56
  writer.add(0, {'foo/bar': img})
57
57
  writer.flush()
58
- assert {x.name for x in logdir.glob('*')} == {'foo-bar.png'}
59
- assert len(list((logdir / 'foo-bar.png').glob('*'))) == 1 + 1
58
+ assert {x.name for x in (logdir / 'scope').glob('*')} == {'foo-bar.png'}
59
+ assert len(list((logdir / 'scope/foo-bar.png').glob('*'))) == 1 + 1
60
60
  reader = scope.Reader(logdir)
61
61
  assert reader.keys() == ('foo/bar',)
62
62
  assert reader.length('foo/bar') == 1
63
63
  _, filenames = reader['foo/bar']
64
64
  assert len(filenames) == 1
65
65
  assert (reader.load('foo/bar', filenames[0]) == img).all()
66
-
67
- # def test_slicing(self, tmpdir):
68
- # logdir = pathlib.Path(tmpdir)
69
- # writer = scope.Writer(logdir, workers=0)
70
- # img1 = np.ones((64, 128, 3), np.uint8) + 12
71
- # img2 = np.ones((64, 128, 3), np.uint8) + 255
72
- # writer.add(0, {'foo': img1})
73
- # writer.add(5, {'foo': img2})
74
- # writer.flush()
75
- # assert {x.name for x in logdir.glob('*')} == {'foo.png'}
76
- # assert (logdir / 'foo.png' / 'index').stat().st_size == (8 + 8) * 2
77
- # reader = scope.Reader(logdir)
78
- # assert reader.keys() == ('foo',)
79
- # assert reader.length('foo') == 2
80
- # steps, values = reader['foo']
81
- # assert (steps == np.array([0, 5])).all()
82
- # assert (values == np.array([img1, img2])).all()
83
- # assert (reader['foo', 0][1] == img1[None]).all()
84
- # assert (reader['foo', :5][1] == img1[None]).all()
85
- # assert (reader['foo', :6][1] == np.array([img1, img2])).all()
86
- # assert (reader['foo', 1:6][1] == img2[None]).all()
87
- # assert reader['foo', :-1][1] == ()
88
- # assert reader['foo', 6:][1] == ()
@@ -14,12 +14,12 @@ class TestVideo:
14
14
  writer.add(0, {'foo': vid1})
15
15
  writer.add(5, {'foo': vid2})
16
16
  writer.flush()
17
- names = {x.name for x in logdir.glob('*')}
17
+ names = {x.name for x in (logdir / 'scope').glob('*')}
18
18
  assert len(names) == 1
19
19
  name = list(names)[0]
20
20
  assert name in ('foo.mp4', 'foo.webm')
21
- assert (logdir / name / 'index').stat().st_size == (8 + 8) * 2
22
- assert len(list((logdir / name).glob('*'))) == 1 + 2
21
+ assert (logdir / 'scope' / name / 'index').stat().st_size == (8 + 8) * 2
22
+ assert len(list((logdir / 'scope' / name).glob('*'))) == 1 + 2
23
23
  reader = scope.Reader(logdir)
24
24
  assert reader.keys() == ('foo',)
25
25
  assert reader.length('foo') == 2
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes