Skip to content

Commit

Permalink
Add 'dynamic' sampling and add tracking frames to documentation gener…
Browse files Browse the repository at this point in the history
…ation
  • Loading branch information
jamesmosys committed May 20, 2024
1 parent 5069e87 commit 73a3967
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 33 deletions.
26 changes: 9 additions & 17 deletions src/main/python/camdkit/framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
class Sampling(Enum):
STATIC = "Static"
REGULAR = "Regular"
DYNAMIC = "Dynamic"

@dataclasses.dataclass
class Dimensions:
Expand Down Expand Up @@ -285,18 +286,12 @@ def getter(self):
def _gen_setter(f):
def setter(self, value):
if value is not None:
if self._params[f].sampling is Sampling.STATIC:
if self._params[f].sampling is Sampling.STATIC or self._params[f].sampling is Sampling.DYNAMIC:
if not self._params[f].validate(value):
raise ValueError
elif self._params[f].sampling is Sampling.REGULAR:
try:
# Handle iterable REGULAR objects
i = iter(value)
if not (isinstance(value, tuple) and all(self._params[f].validate(s) for s in value)):
raise ValueError
except TypeError as te:
if not self._params[f].validate(value):
raise ValueError
if not (isinstance(value, tuple) and all(self._params[f].validate(s) for s in value)):
raise ValueError
else:
raise ValueError
self._values[f] = value
Expand All @@ -321,12 +316,9 @@ def to_json(self) -> dict:
elif desc.sampling is Sampling.STATIC:
obj[desc.canonical_name] = desc.to_json(self._values[k])
elif desc.sampling is Sampling.REGULAR:
try:
# Handle iterable REGULAR objects
i = iter(value)
obj[desc.canonical_name] = tuple(map(desc.to_json, value))
except TypeError as te:
obj[desc.canonical_name] = desc.to_json(value)
obj[desc.canonical_name] = tuple(map(desc.to_json, value))
elif desc.sampling is Sampling.DYNAMIC:
obj[desc.canonical_name] = desc.to_json(value)
else:
raise ValueError

Expand All @@ -337,7 +329,7 @@ def from_json(self, json_dict: dict):
for prop, desc in self._params.items():
if desc.canonical_name != json_key:
continue
if desc.sampling is Sampling.STATIC:
if desc.sampling is Sampling.STATIC or desc.sampling is Sampling.DYNAMIC:
self._values[prop] = desc.from_json(json_value)
elif desc.sampling is Sampling.REGULAR:
self._values[prop] = tuple(map(desc.from_json, json_value))
Expand All @@ -353,7 +345,7 @@ def make_json_schema(cls) -> dict:
}

for _, desc in cls._params.items():
if desc.sampling is Sampling.STATIC:
if desc.sampling is Sampling.STATIC or desc.sampling is Sampling.DYNAMIC:
schema[desc.canonical_name] = desc.make_json_schema()
elif desc.sampling is Sampling.REGULAR:
schema[desc.canonical_name] = {
Expand Down
2 changes: 1 addition & 1 deletion src/main/python/camdkit/trackerkit/framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Vector3:

class TrackingParameter(Parameter):
"""All tracking parameters are dynamic."""
sampling = Sampling.REGULAR
sampling = Sampling.DYNAMIC


class Vector3Parameter(TrackingParameter):
Expand Down
48 changes: 33 additions & 15 deletions src/tools/python/make_documentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
import camdkit.model
import camdkit.red.reader
import camdkit.arri.reader
import camdkit.trackerkit
import camdkit.trackerkit.model
import camdkit.venice.reader
import camdkit.canon.reader
import camdkit.trackerkit.mosys.reader

_INTRODUCTION = """# OSVP Clip documentation
_CLIP_INTRODUCTION = """# OSVP documentation
## Introduction
Expand All @@ -20,7 +23,16 @@
Each parameter is identified by a unique name. It also has a general description
as well as a specific set of constraints.
## Parameters
The OSVP Frame (frame) is a collection of metadata parameters that is dynamic and has a
synchronous relationship with a video frame. In an OSVP environment this describes live
camera position ('tracking') and lens data.
## Clip Parameters
"""
_FRAME_INTRODUCTION = """
## Frame Parameters
"""

Expand All @@ -30,10 +42,9 @@
"Sony" : []
}

def generate_documentation(fp: typing.TextIO):
doc = camdkit.model.Clip.make_documentation()
def generate_documentation(fp: typing.TextIO, doc, prefix):

fp.write(_INTRODUCTION)
fp.write(prefix)

for p in doc:
fp.write(f"### `{p['canonical_name']}`\n")
Expand Down Expand Up @@ -62,16 +73,16 @@ def generate_documentation(fp: typing.TextIO):
fp.write("\n")
fp.write("\n")

fp.write("## JSON Schema\n")
def generate_schema(fp: typing.TextIO, schema, title):
fp.write(f"## {title} JSON Schema\n")
fp.write("\n")
fp.write("```")
json.dump(camdkit.model.Clip.make_json_schema(), fp, indent=2)
json.dump(schema, fp, indent=2)
fp.write("\n")
fp.write("```")
fp.write("\n")

# Reader coverage

def generate_clip_reader_coverage(fp: typing.TextIO, doc):
fp.write("## Reader coverage\n")
fp.write("\n")
fp.write("The following table indicates the camera parameters supported by each of the readers.\n")
Expand All @@ -83,7 +94,7 @@ def generate_documentation(fp: typing.TextIO):
fp.write(f"| Reader | {' | '.join(parameter_names)} |\n")
fp.write(f"| ----------- | {'----------- |' * len(parameter_names)}\n")

def _print_reader_coverage(fp, reader_name, doc, clip):
def _generate_reader_coverage(fp, reader_name, doc, clip):
fp.write(f"| {reader_name} |")
for p in doc:
if getattr(clip, p["python_name"], None) is not None:
Expand All @@ -98,28 +109,35 @@ def _print_reader_coverage(fp, reader_name, doc, clip):
open("src/test/resources/red/A001_C066_0303LZ_001.frames.csv", "r", encoding="utf-8") as type_5_file:
clip = camdkit.red.reader.to_clip(type_3_file, type_5_file)

_print_reader_coverage(fp, "RED", doc, clip)
_generate_reader_coverage(fp, "RED", doc, clip)

# ARRI reader

clip = camdkit.arri.reader.to_clip("src/test/resources/arri/B001C001_180327_R1ZA.mov.csv")
_print_reader_coverage(fp, "ARRI", doc, clip)
_generate_reader_coverage(fp, "ARRI", doc, clip)

# Venice reader

with open("src/test/resources/venice/D001C005_210716AGM01.xml", "r", encoding="utf-8") as static_file, \
open("src/test/resources/venice/D001C005_210716AG.csv", "r", encoding="utf-8") as dynamic_file:
clip = camdkit.venice.reader.to_clip(static_file, dynamic_file)

_print_reader_coverage(fp, "Venice", doc, clip)
_generate_reader_coverage(fp, "Venice", doc, clip)

# Canon reader

with open("src/test/resources/canon/20221007_TNumber_CanonCameraMetadata_Static.csv", "r", encoding="utf-8") as static_csv, \
open("src/test/resources/canon/20221007_TNumber_CanonCameraMetadata_Frames.csv", "r", encoding="utf-8") as frame_csv:
clip = camdkit.canon.reader.to_clip(static_csv, frame_csv)

_print_reader_coverage(fp, "Canon", doc, clip)
_generate_reader_coverage(fp, "Canon", doc, clip)

if __name__ == "__main__":
generate_documentation(sys.stdout)
clip_doc = camdkit.model.Clip.make_documentation()
generate_documentation(sys.stdout, clip_doc, _CLIP_INTRODUCTION)
generate_clip_reader_coverage(sys.stdout, clip_doc)
generate_schema(sys.stdout, camdkit.model.Clip.make_json_schema(), "Clip")

frame_doc = camdkit.trackerkit.model.Frame.make_documentation()
generate_documentation(sys.stdout, frame_doc, _FRAME_INTRODUCTION)
generate_schema(sys.stdout, camdkit.trackerkit.model.Frame.make_json_schema(), "Frame")

0 comments on commit 73a3967

Please sign in to comment.