Laegna / Octave Selector – JSON, Code & Math Reference
This page contains the complete Python generator for octaves.json, a clickable
JSON structure reference, and a compact mathematical explanation of the ZXY base‑3 octave
system. Everything is in one place: copyable code, inspectable schema, and open‑source math.
1. Generator code for octaves.json
Copy this block as‑is into a .py file and run it. It prints the full JSON to stdout.
# Count numbers in digit to create initial data
def countR(R = 1, prefix = None):
if prefix == None: prefix = []
for dig in range(3):
if R == 1:
yield prefix + [dig - 1]
else:
for num in countR(R-1, prefix + [dig - 1]):
yield num
# Find length, elements in given R
def len4R(R = 1):
return 3**R
# Find properties for single number
def numprop(number):
k, L, zoom = octave_props(number["Expr"]["Digits"])
number["Simp"] = {
"D": octave_D(number["Expr"]["Digits"])
}
number["Props"] = {
"k": k,
"L": L,
"zoom": zoom
}
number["Visual"] = visualization_props(number["Expr"]["Digits"])
number["BinSig"] = bin_signature(number["Expr"]["Digits"])
number["BinProps"] = bin_props(number["Expr"]["Digits"])
number["BinAxis"] = bin_axis_sign(number["Expr"]["Digits"])
return number
def octave_D(digits):
"""
digits: list of -1, 0, 1
where -1 = Z, 0 = X, 1 = Y
returns: integer D = sum of digit values
"""
return sum(digits)
def octave_props(digits): # digits in {-1, 0, 1} for Z, X, Y
k = 0
L = 0
mult = 1 # 2^0, 2^1, ...
for dig in reversed(digits): # rightmost = 2^0
if dig == -1: # Z
k -= 1
L -= mult
elif dig == 1: # Y
k += 1
L += mult
# X (0) does nothing to k or L directly
mult *= 2
zoom = 2 ** k
return k, L, zoom
def bin_props(digits):
"""
digits: list of -1, 0, 1
-1 = Z, 0 = X, 1 = Y
returns: dict with binary masks and counts
"""
# Build binary strings
X_mask = ''.join('1' if d == 0 else '0' for d in digits)
notX_mask = ''.join('1' if d != 0 else '0' for d in digits)
Z_mask = ''.join('1' if d == -1 else '0' for d in digits)
Y_mask = ''.join('1' if d == 1 else '0' for d in digits)
# Decimal counts
X_count = X_mask.count('1')
notX_count = notX_mask.count('1')
Z_count = Z_mask.count('1')
Y_count = Y_mask.count('1')
return {
"ZoomFactor": notX_count - X_count,
"Direction": Y_count - Z_count,
"Decimal": {
"X": X_count,
"notX": notX_count,
"Z": Z_count,
"Y": Y_count
},
"Boolean": {
"X": X_mask,
"notX": notX_mask,
"Z": Z_mask,
"Y": Y_mask
}
}
def bin_axis_sign(digits):
PosMask = ''.join('1' if d == 1 else '0' for d in digits)
NegMask = ''.join('1' if d == -1 else '0' for d in digits)
SignMask = ''.join('1' if d != 0 else '0' for d in digits)
PosCount = PosMask.count('1')
NegCount = NegMask.count('1')
return {
"Num": PosCount - NegCount,
"Decimal": {
"Pos": PosCount,
"Neg": NegCount
},
"Boolean": {
"Pos": PosMask,
"Neg": NegMask,
"Sign": SignMask
}
}
def visualization_props(digits):
k, L, zoom = octave_props(digits)
D = octave_D(digits)
Num = zoom
NumExp = zoom * zoom
NumLog = k
ScaledMult = D
# Signed boundaries
signed_bounds = {
"MinusTwo": -2.0,
"MinusOne": -1.0,
"Zero": 0.0,
"PlusOne": 1.0,
"PlusTwo": 2.0
}
# Unsigned boundaries
unsigned_bounds = {
"Zero": 0.0,
"One": 1.0,
"Two": 2.0,
"Three": 3.0,
"Four": 4.0
}
# Percent helpers
def pct(x):
return f"{int(x * 100)}%"
return {
"Num": Num,
"NumExp": NumExp,
"NumLog": NumLog,
"ScaledMult": ScaledMult,
"Signed": {
"Boundaries": {
key: {
"Float": val,
"Percent": pct(val)
}
for key, val in signed_bounds.items()
},
"DigitValues": {
key: val * Num
for key, val in signed_bounds.items()
}
},
"Unsigned": {
"Boundaries": {
key: {
"Float": val,
"Percent": pct(val / 4)
}
for key, val in unsigned_bounds.items()
},
"DigitValues": {
key: val * Num
for key, val in unsigned_bounds.items()
}
}
}
def bin_signature(digits):
code = {
-1: "10", # Z
0: "00", # X
1: "01" # Y
}
signature = ''.join(code[d] for d in digits)
return {
"Num": signature,
"Map": {
"Z": "10",
"X": "00",
"Y": "01"
}
}
# Find whole list for single R
def numberlist(R = 1):
numbers = []
for num in countR(R):
number = { }
number["Expr"] = { }
number["Expr"]["Digits"] = num
numbers += [numprop(number)]
return numbers
class RibX:
def __init__(self, R, b = 3):
self.R = R
self.b = b
self.numbers = numberlist(R)
def to_json(self):
return {
"R": self.R,
"base": self.b,
"numbers": self.numbers
}
class DbX:
def __init__(self):
self.Res = []
for R in range(4):
self.Res.append(RibX(R + 1))
def to_json(self):
return {
"meta": {
"version": 1,
"description": "Laegna / Octave selector number system of Z, X and Y"
},
"chapters": [ ribx.to_json() for ribx in self.Res ]
}
if __name__ == '__main__':
import json
dbx = DbX()
print(json.dumps(dbx.to_json(), indent=2))
2. JSON structure explorer
Click any line to toggle its documentation. Lines are single‑line, no layout tricks; this is meant to be readable on wide screens and small devices alike.
3. Mathematical background (compact)
Digits live in \(\{-1,0,1\}\) and are mapped as \(Z=-1\), \(X=0\), \(Y=1\). A number is a
finite word of these digits, e.g. [Z,X,Y] or in shorthand ZXY.
The octave exponent \(k\) and linear offset \(L\) are computed by scanning digits from right to left. Each position has weight \(2^n\). For each \(Z\) we subtract from \(k\) and \(L\), for each \(Y\) we add:
\[ k = \sum_i d_i,\quad L = \sum_i d_i \cdot 2^i,\quad \text{zoom} = 2^k \] where \(d_i \in \{-1,0,1\}\) is the digit at position \(i\) (rightmost \(i=0\)).
The visualization layer uses: \[ \text{Num} = 2^k,\quad \text{NumExp} = (2^k)^2,\quad \text{NumLog} = k,\quad \text{ScaledMult} = \sum_i d_i \] and projects this onto signed \([-2,2]\) and unsigned \([0,1]\) ranges via fixed boundaries.
Binary masks (BinProps, BinAxis) encode where Z, X, Y occur and
count them, giving directional and zoom‑related summaries that are easy to recompute in any
language.