itrm 0.2.0__tar.gz → 0.2.2__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: itrm
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Interactive Terminal Utilities
5
5
  Home-page: https://gitlab.com/davidwoodburn/itrm
6
6
  Author: David Woodburn
@@ -59,7 +59,8 @@ call to `itrm`. The following table lists the configuration options:
59
59
  | `ar` | `0.48` | aspect ratio of characters |
60
60
 
61
61
  There is also a method for changing the color map: `itrm.config.cmap()`. It
62
- takes a string: `"colors"`, `"grays"`, `"reds"`, `"greens"`, or `"blues"`.
62
+ takes a string: `"colors"`, `"viridis"`, `"grays"`, `"reds"`, `"greens"`, or
63
+ `"blues"`.
63
64
 
64
65
  ## Interactive Plots
65
66
 
@@ -44,7 +44,8 @@ call to `itrm`. The following table lists the configuration options:
44
44
  | `ar` | `0.48` | aspect ratio of characters |
45
45
 
46
46
  There is also a method for changing the color map: `itrm.config.cmap()`. It
47
- takes a string: `"colors"`, `"grays"`, `"reds"`, `"greens"`, or `"blues"`.
47
+ takes a string: `"colors"`, `"viridis"`, `"grays"`, `"reds"`, `"greens"`, or
48
+ `"blues"`.
48
49
 
49
50
  ## Interactive Plots
50
51
 
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = itrm
3
- version = 0.2.0
3
+ version = 0.2.2
4
4
  author = David Woodburn
5
5
  author_email = david.woodburn@icloud.com
6
6
  description = Interactive Terminal Utilities
@@ -37,16 +37,18 @@ import numpy as np
37
37
 
38
38
  # Constants
39
39
  # (blue, green, yellow, orange, magenta, purple)
40
- DARK_COLORS = [33, 40, 220, 202, 201, 93]
41
- LITE_COLORS = [75, 82, 228, 214, 213, 135]
42
- DARK_GRAYS = [253, 250, 247, 244, 241, 238]
43
- LITE_GRAYS = [255, 252, 249, 246, 243, 240]
44
- DARK_REDS = [197, 196, 160, 124, 88, 52]
45
- LITE_REDS = [198, 197, 196, 160, 124, 88]
46
- DARK_GREENS = [47, 46, 40, 34, 28, 22]
47
- LITE_GREENS = [48, 47, 46, 40, 34, 28]
48
- DARK_BLUES = [27, 21, 20, 19, 18, 17]
49
- LITE_BLUES = [33, 27, 21, 20, 19, 18]
40
+ DARK_COLORS = [ 33, 40, 220, 202, 201, 93]
41
+ LITE_COLORS = [ 75, 82, 228, 214, 213, 135]
42
+ DARK_VIRIDIS = [184, 113, 36, 30, 60, 53]
43
+ LITE_VIRIDIS = [227, 156, 79, 73, 103, 96]
44
+ DARK_GRAYS = [253, 250, 247, 244, 241, 238]
45
+ LITE_GRAYS = [255, 252, 249, 246, 243, 240]
46
+ DARK_REDS = [197, 196, 160, 124, 88, 52]
47
+ LITE_REDS = [198, 197, 196, 160, 124, 88]
48
+ DARK_GREENS = [ 47, 46, 40, 34, 28, 22]
49
+ LITE_GREENS = [ 48, 47, 46, 40, 34, 28]
50
+ DARK_BLUES = [ 27, 21, 20, 19, 18, 17]
51
+ LITE_BLUES = [ 33, 27, 21, 20, 19, 18]
50
52
  COLOR_CNT = 6 # number of colors in the color map
51
53
  eps = 1e-32 # minimum magnitude
52
54
 
@@ -58,13 +60,16 @@ class config: # configuration settings
58
60
  ar = 0.48 # aspect ratio of characters
59
61
  darks = DARK_COLORS # dark color map
60
62
  lites = LITE_COLORS # light color map
61
-
63
+
62
64
  def cmap(cmap="colors"):
63
65
  if not isinstance(cmap, str):
64
66
  raise ValueError(f"cmap must be a string: {cmap}")
65
67
  if cmap == "colors":
66
68
  config.darks = DARK_COLORS
67
69
  config.lites = LITE_COLORS
70
+ elif cmap == "viridis":
71
+ config.darks = DARK_VIRIDIS
72
+ config.lites = LITE_VIRIDIS
68
73
  elif cmap == "grays":
69
74
  config.darks = DARK_GRAYS
70
75
  config.lites = LITE_GRAYS
@@ -78,14 +83,16 @@ class config: # configuration settings
78
83
  config.darks = DARK_BLUES
79
84
  config.lites = LITE_BLUES
80
85
  else:
81
- raise ValueError("cmap must be one of "
82
- + "'colors', 'grays', 'reds', 'greens', or 'blues'")
86
+ raise ValueError('cmap must be one of '
87
+ + '"colors", "viridis", "grays", '
88
+ + '"reds", "greens", or "blues"')
83
89
 
84
90
 
85
91
  class persistent: # persistent, run-time values
86
92
  t_last = None # last time value
87
93
  orig_term_attr = None # original terminal attributes
88
94
  rows_last = None # last number of plot rows
95
+ tmp = 0.0
89
96
 
90
97
 
91
98
  class limits: # x and y data limits
@@ -98,7 +105,6 @@ class limits: # x and y data limits
98
105
  self.k_min = k_min # indices of minimum x
99
106
  self.k_max = k_max # indices of maximum x
100
107
  self.k_xc = k_xc # indices of x near cursor
101
- self.tmp = 0.0
102
108
 
103
109
 
104
110
  class term_ws: # terminal window size and sub-character resolution
@@ -415,8 +421,8 @@ def iplot(x, y=None, label=None, rows=1, cols=1, lg=None, overlay=False):
415
421
  first = False
416
422
  else:
417
423
  if report:
418
- rstr = view_str + f" < t:{tupdate:4f} >"
419
- #rstr = view_str + f" < {view.tmp}, {K} >"
424
+ #rstr = view_str + f" < t:{tupdate:4f} >"
425
+ rstr = view_str + f" < {persistent.tmp} >" # FIXME
420
426
  redraw_graph(C, D, F, row_zero, rstr, label,
421
427
  ccol, cstr, cF, view, lims)
422
428
  else:
@@ -645,7 +651,7 @@ def heat(matrix):
645
651
  for row in range(0, (rows - rows%2), 2):
646
652
  for col in range(cols):
647
653
  print("\x1b[38;5;%dm\x1b[48;5;%dm\u2580" %
648
- (M[row, col], M[row + 1, col]), end="", flush=True)
654
+ (M[row, col], M[row+1, col]), end="", flush=True)
649
655
  print("\x1b[0m", flush=True)
650
656
  if rows % 2 == 1:
651
657
  for col in range(cols):
@@ -1167,20 +1173,69 @@ def limits_xy(x, y, tws, equal_axes):
1167
1173
 
1168
1174
 
1169
1175
  def get_row_zero(lims, tws):
1170
- # Expand the limits to align zero with the nearest half row so that the zero
1171
- # marker is true. FIXME This formula is likely wrong!
1172
- if (lims.y_min < 0) and (lims.y_max > 0):
1173
- idx_zero = round((tws.rows - 1.0/tws.subrows)
1174
- * lims.y_max/(lims.y_max - lims.y_min)
1175
- - 0.5)*tws.subrows + tws.subrows/2
1176
- slope = max((tws.subrows*tws.rows - 1 - idx_zero)/lims.y_min,
1177
- -idx_zero/lims.y_max)
1178
- lims.y_min = (tws.subrows*tws.rows - 1 - idx_zero)/slope
1179
- lims.y_max = -idx_zero/slope
1180
- row_zero = math.floor((tws.rows - 1/tws.subrows)*
1181
- (lims.y_max)/(lims.y_max - lims.y_min))
1176
+ """
1177
+ Expand the limits to align zero with the nearest row so that the zero marker
1178
+ is true.
1179
+ """
1180
+
1181
+ # Alias the current min and max y values.
1182
+ a = lims.y_min
1183
+ b = lims.y_max
1184
+
1185
+ if (a < 0) and (b > 0):
1186
+ # Get the real-valued and integer-valued center rows.
1187
+ C = tws.rows*b/(b-a) - 0.5
1188
+ Cl = math.floor(C) # lower value
1189
+ Ch = math.ceil(C) # higher value
1190
+
1191
+ # Get the scaling factors.
1192
+ kl = (Cl + 0.5)/tws.rows
1193
+ kh = (Ch + 0.5)/tws.rows
1194
+
1195
+ # Given the two scaling factors, get the new low values from fixed high
1196
+ # values and the new high values from fixed low values.
1197
+ Al = b*(kl - 1)/kl
1198
+ Ah = b*(kh - 1)/kh
1199
+ Bl = a*kl/(kl - 1)
1200
+ Bh = a*kh/(kh - 1)
1201
+
1202
+ # Between the two new low values, check which is at least as low as the
1203
+ # original.
1204
+ if Al <= a:
1205
+ A = Al
1206
+ CA = Cl
1207
+ elif Ah <= a:
1208
+ A = Ah
1209
+ CA = Ch
1210
+ else:
1211
+ A = -np.inf
1212
+
1213
+ # Between the two new high values, check which is at least as high as
1214
+ # the original.
1215
+ if Bl >= b:
1216
+ B = Bl
1217
+ CB = Cl
1218
+ elif Bh >= b:
1219
+ B = Bh
1220
+ CB = Ch
1221
+ else:
1222
+ B = np.inf
1223
+
1224
+ # Pick the pair which results in the smallest increase in range.
1225
+ if (b - A > 2*(b - a)) and (B - a > 2*(b - a)):
1226
+ row_zero = -1
1227
+ elif (b - A) < (B - a):
1228
+ lims.y_min = A
1229
+ lims.y_max = b
1230
+ row_zero = CA
1231
+ else:
1232
+ lims.y_min = a
1233
+ lims.y_max = B
1234
+ row_zero = CB
1182
1235
  else:
1236
+ # Set the zero row to something invalid.
1183
1237
  row_zero = -1
1238
+
1184
1239
  return row_zero, lims
1185
1240
 
1186
1241
 
@@ -1234,8 +1289,8 @@ def data_to_matrix(x, y, view, tws, j_cursor):
1234
1289
  # Scale the data to dots. First dot is 0; last dot is Cols - 1.
1235
1290
  X = Cols*(x[j, mm] - view.x_min)/x_span - 0.5
1236
1291
  Y = Rows*(view.y_max - y[j, mm])/y_span - 0.5
1237
- X = np.clip(np.round(X).astype(int), 0, Cols - 1)
1238
- Y = np.clip(np.round(Y).astype(int), 0, Rows - 1)
1292
+ X = np.clip(np.round(X).astype(int), 0, Cols-1)
1293
+ Y = np.clip(np.round(Y).astype(int), 0, Rows-1)
1239
1294
 
1240
1295
  # Map locations to a large matrix.
1241
1296
  M[Y, X] = 1 # Puts a 1 wherever the curve coordinates are.
@@ -1354,7 +1409,7 @@ def zoom_in_indices(x, view):
1354
1409
  # Get subset of `x` within the old view.
1355
1410
  ka = view.k_min[j]
1356
1411
  kb = view.k_max[j]
1357
- xj_view = x[j, ka:kb + 1]
1412
+ xj_view = x[j, ka:kb+1]
1358
1413
 
1359
1414
  # Get the new index of minimum.
1360
1415
  mm_min = (xj_view >= view.x_min).nonzero()[0]
@@ -1374,7 +1429,7 @@ def zoom_out_indices(x, view):
1374
1429
  # Get subsets of `x` left or right of the old view.
1375
1430
  kb = view.k_min[j]
1376
1431
  ka = view.k_max[j]
1377
- xj_left = x[j, :kb + 1]
1432
+ xj_left = x[j, :kb+1]
1378
1433
  xj_right = x[j, ka:]
1379
1434
 
1380
1435
  # Get the new index of minimum.
@@ -1396,17 +1451,17 @@ def pan_indices(x, view):
1396
1451
  ka = view.k_min[j]
1397
1452
  kb = view.k_max[j]
1398
1453
  if (x[j, ka] >= view.x_min) and (x[j, kb] >= view.x_max): # <--
1399
- xj_min = x[j, :ka + 1]; k_min_ref = 0
1400
- xj_max = x[j, :kb + 1]; k_max_ref = 0
1454
+ xj_min = x[j, :ka+1]; k_min_ref = 0
1455
+ xj_max = x[j, :kb+1]; k_max_ref = 0
1401
1456
  elif (x[j, ka] < view.x_min) and (x[j, kb] < view.x_max): # -->
1402
1457
  xj_min = x[j, ka:]; k_min_ref = ka
1403
1458
  xj_max = x[j, kb:]; k_max_ref = kb
1404
1459
  elif (x[j, ka] >= view.x_min) and (x[j, kb] < view.x_max): # <->
1405
- xj_min = x[j, :ka + 1]; k_min_ref = 0
1460
+ xj_min = x[j, :ka+1]; k_min_ref = 0
1406
1461
  xj_max = x[j, kb:]; k_max_ref = kb
1407
1462
  elif (x[j, ka] < view.x_min) and (x[j, kb] >= view.x_max): # >-<
1408
- xj_min = x[j, ka:kb + 1]; k_min_ref = ka
1409
- xj_max = x[j, ka:kb + 1]; k_max_ref = ka
1463
+ xj_min = x[j, ka:kb+1]; k_min_ref = ka
1464
+ xj_max = x[j, ka:kb+1]; k_max_ref = ka
1410
1465
 
1411
1466
  # Get the new index of minimum.
1412
1467
  mm_min = (xj_min >= view.x_min).nonzero()[0]
@@ -1427,7 +1482,7 @@ def center_view_x(xc, view):
1427
1482
  def get_column(xc, view, tws):
1428
1483
  x_span = view.x_max - view.x_min
1429
1484
  ccol = round(tws.cols*(xc - view.x_min)/x_span - 0.5)
1430
- ccol = min(max(ccol, 0), tws.cols - 1)
1485
+ ccol = min(max(ccol, 0), tws.cols-1)
1431
1486
  return ccol
1432
1487
 
1433
1488
 
@@ -1447,8 +1502,8 @@ def get_cursor_y(x, y, view, tws, ccol, j_cursor):
1447
1502
  for j in jj:
1448
1503
  ka = view.k_min[j]
1449
1504
  kb = view.k_max[j]
1450
- xj_view = x[j, ka:kb + 1]
1451
- yj_view = y[j, ka:kb + 1]
1505
+ xj_view = x[j, ka:kb+1]
1506
+ yj_view = y[j, ka:kb+1]
1452
1507
  is_valid_x = np.isfinite(xj_view)
1453
1508
  is_valid_y = np.isfinite(yj_view)
1454
1509
  is_in = (xj_view >= xc_a) & (xj_view <= xc_b)
@@ -1479,8 +1534,8 @@ def get_view_y(x, y, view, j_cursor):
1479
1534
  for j in jj:
1480
1535
  ka = view.k_min[j]
1481
1536
  kb = view.k_max[j]
1482
- xj_view = x[j, ka:kb + 1]
1483
- yj_view = y[j, ka:kb + 1]
1537
+ xj_view = x[j, ka:kb+1]
1538
+ yj_view = y[j, ka:kb+1]
1484
1539
  is_valid_x = np.isfinite(xj_view)
1485
1540
  is_valid_y = np.isfinite(yj_view)
1486
1541
  mm = (is_valid_x & is_valid_y).nonzero()[0]
@@ -1552,7 +1607,7 @@ def matrix_to_ascii(M):
1552
1607
 
1553
1608
  def matrix_to_stars(M):
1554
1609
  I, J = M.shape
1555
- C = 0x20*np.ones((I, 2*J + 1), dtype=int)
1610
+ C = 0x20*np.ones((I, 2*J+1), dtype=int)
1556
1611
  C[:, 1:-1:2] += 0xA*M
1557
1612
  return C
1558
1613
 
@@ -1723,7 +1778,7 @@ def redraw_graph(C, D, F=None, row_zero=-1, view_str=None, label=None,
1723
1778
  x_view = (view.x_max + view.x_min)/2
1724
1779
  col_center = round(cols*(x_view - lims.x_min)/x_span)
1725
1780
  col_a = max(0, round(col_center - bar_width/2))
1726
- col_b = min(cols - 1, col_a + bar_width)
1781
+ col_b = min(cols-1, col_a + bar_width)
1727
1782
  # Draw the bar.
1728
1783
  print("\x1b[38;5;238m", end="", flush=True)
1729
1784
  for col in range(cols):
@@ -1880,3 +1935,37 @@ def draw_bar(n, N, colorize, fat):
1880
1935
 
1881
1936
  # Show the cursor.
1882
1937
  print("\x1b[?25h", end="", flush=True)
1938
+
1939
+
1940
+ def viridis_map():
1941
+ """
1942
+ Display the viridis color palette. The original RGB values came from
1943
+ https://waldyrious.net/viridis-palette-generator/.
1944
+ """
1945
+
1946
+ # Input colors.
1947
+ vir = np.array([
1948
+ [253, 231, 37],
1949
+ [122, 209, 81],
1950
+ [34, 168, 132],
1951
+ [42, 120, 142],
1952
+ [65, 68, 135],
1953
+ [68, 1, 84]])
1954
+
1955
+ # Show dark colors.
1956
+ for n in range(6):
1957
+ r = int(5*vir[n, 0]/255)
1958
+ g = int(5*vir[n, 1]/255)
1959
+ b = int(5*vir[n, 2]/255)
1960
+ c = 16 + 36*r + 6*g + b
1961
+ print(f"\x1b[48;5;{c}m {c:03d} \x1b[0m ", end="")
1962
+ print()
1963
+
1964
+ # Show dark colors.
1965
+ for n in range(6):
1966
+ r = int(5*vir[n, 0]/255 + 1)
1967
+ g = int(5*vir[n, 1]/255 + 1)
1968
+ b = int(5*vir[n, 2]/255 + 1)
1969
+ c = 16 + 36*r + 6*g + b
1970
+ print(f"\x1b[48;5;{c}m {c:03d} \x1b[0m ", end="")
1971
+ print()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: itrm
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Interactive Terminal Utilities
5
5
  Home-page: https://gitlab.com/davidwoodburn/itrm
6
6
  Author: David Woodburn
@@ -59,7 +59,8 @@ call to `itrm`. The following table lists the configuration options:
59
59
  | `ar` | `0.48` | aspect ratio of characters |
60
60
 
61
61
  There is also a method for changing the color map: `itrm.config.cmap()`. It
62
- takes a string: `"colors"`, `"grays"`, `"reds"`, `"greens"`, or `"blues"`.
62
+ takes a string: `"colors"`, `"viridis"`, `"grays"`, `"reds"`, `"greens"`, or
63
+ `"blues"`.
63
64
 
64
65
  ## Interactive Plots
65
66
 
File without changes
File without changes
File without changes
File without changes