From 6245ce5e27c062361ec36cabe437050f74fb8ce0 Mon Sep 17 00:00:00 2001 From: Michael Winter Date: Tue, 24 Mar 2026 11:04:21 +0100 Subject: [PATCH] Make JSON output more readable - each pitch on one line --- src/io.py | 115 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 74 insertions(+), 41 deletions(-) diff --git a/src/io.py b/src/io.py index 186159c..997e749 100644 --- a/src/io.py +++ b/src/io.py @@ -11,26 +11,24 @@ from random import seed def write_chord_sequence(seq: list["Chord"], path: str) -> None: """Write a chord sequence to a JSON file.""" - serializable = [] - for chord in seq: - chord_data = [] - for pitch in chord._pitches: - chord_data.append( - { - "hs_array": list(pitch.hs_array), - "fraction": str(pitch.to_fraction()), - "cents": pitch.to_cents(), - } - ) - serializable.append(chord_data) - - content = json.dumps(serializable, indent=2) - content = content.replace("[[[", "[\n\t[[") - content = content.replace(", [[", ",\n\t[[") - content = content.replace("]]]", "]]\n]") + lines = ["["] + for chord_idx, chord in enumerate(seq): + lines.append(" [") + for pitch_idx, pitch in enumerate(chord._pitches): + pitch_obj = { + "hs_array": list(pitch.hs_array), + "fraction": str(pitch.to_fraction()), + "cents": pitch.to_cents(), + } + pitch_json = json.dumps(pitch_obj) + comma = "," if pitch_idx < len(chord._pitches) - 1 else "" + lines.append(f" {pitch_json}{comma}") + chord_bracket = " ]" if chord_idx == len(seq) - 1 else " ]," + lines.append(chord_bracket) + lines.append("]") with open(path, "w") as f: - f.write(content) + f.write("\n".join(lines)) def write_chord_sequence_readable(seq: list["Chord"], path: str) -> None: @@ -70,33 +68,68 @@ def _serialize_edge_data(edge_data: dict) -> dict: return result +def _format_chord_line(pitches: list) -> str: + """Format a chord (list of pitch hs_arrays) as a single line.""" + return json.dumps([list(p) if hasattr(p, "hs_array") else p for p in pitches]) + + +def _format_edge_data_compact(edge_data: dict) -> dict: + """Format edge data for compact JSON output.""" + result = {} + for key, value in edge_data.items(): + if hasattr(value, "hs_array"): + result[key] = list(value.hs_array) + elif isinstance(value, list) and value and hasattr(value[0], "hs_array"): + result[key] = [list(p.hs_array) for p in value] + else: + result[key] = value + return result + + def write_path_steps(path: "Path", output_path: str) -> None: """Write path with all step data to JSON.""" - steps_data = [] - for i, step in enumerate(path.steps): - step_data = { - "step": i, - "source_node": [list(p.hs_array) for p in step.source_node.pitches], - "destination_node": [ - list(p.hs_array) for p in step.destination_node.pitches - ], - "source_chord": [list(p.hs_array) for p in step.source_chord.pitches], - "destination_chord": [ - list(p.hs_array) for p in step.destination_chord.pitches - ], - "transposition": list(step.transposition.hs_array) - if step.transposition - else None, - "movements": {str(k): v for k, v in step.movements.items()}, - "scores": step.scores, - "normalized_scores": step.normalized_scores, - "weight": step.weight, - "edge_data": _serialize_edge_data(step.edge_data), - } - steps_data.append(step_data) + lines = ["["] + for step_idx, step in enumerate(path.steps): + lines.append(" {") + lines.append(f' "step": {step_idx},') + + lines.append( + f' "source_chord": {_format_chord_line(step.source_chord.pitches)},' + ) + lines.append( + f' "destination_chord": {_format_chord_line(step.destination_chord.pitches)},' + ) + + if step.transposition: + trans = list(step.transposition.hs_array) + lines.append(f' "transposition": {json.dumps(trans)},') + else: + lines.append(' "transposition": null,') + + lines.append( + f' "movements": {json.dumps({str(k): v for k, v in step.movements.items()})},' + ) + + if step.scores: + lines.append(f' "scores": {json.dumps(step.scores)},') + + if step.normalized_scores: + lines.append( + f' "normalized_scores": {json.dumps(step.normalized_scores)},' + ) + + if step.weight is not None: + lines.append(f' "weight": {step.weight},') + + edge_data = _format_edge_data_compact(step.edge_data) + lines.append(f' "edge_data": {json.dumps(edge_data)}') + + lines.append(" }" + ("," if step_idx < len(path.steps) - 1 else "")) + + lines.append("]") with open(output_path, "w") as f: - json.dump(steps_data, f, indent=2) + f.write("\n".join(lines)) def graph_to_dict(graph: "nx.MultiDiGraph") -> dict: