-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #99 from clamsproject/97-cli
Merging CLI code
- Loading branch information
Showing
6 changed files
with
175 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
"""cli.py | ||
Command Line Interface for the SWT app. | ||
This script can be called with the same arguments as the _annotate method on the app, | ||
except that we add --input, --output and --metadata parameters. | ||
Example invocation: | ||
$ python cli.py \ | ||
--modelName 20240409-093229.convnext_tiny | ||
--input example-mmif-local.json | ||
--output out.json | ||
--map B:bars S:slate | ||
--pretty true | ||
""" | ||
|
||
|
||
import sys | ||
import yaml | ||
import argparse | ||
|
||
from mmif import Mmif | ||
from clams.app import ClamsApp | ||
|
||
from metadata import appmetadata | ||
from app import SwtDetection | ||
|
||
|
||
json_type_map = { | ||
"integer": int, | ||
"number": float, | ||
"string": str, | ||
"boolean": bool, | ||
} | ||
|
||
parameter_names = ( | ||
'metadata', 'map', 'minFrameCount', 'minFrameScore', 'minTimeframeScore', | ||
'modelName', 'pretty', 'sampleRate', 'startAt', 'stopAt', 'useStitcher') | ||
|
||
|
||
def get_metadata(): | ||
"""Gets the metadata from the metadata.py file, with the universal parameters added.""" | ||
metadata = appmetadata() | ||
for param in ClamsApp.universal_parameters: | ||
metadata.add_parameter(**param) | ||
return metadata | ||
|
||
|
||
def create_argparser(metadata): | ||
parser = argparse.ArgumentParser( | ||
description=f"Command-Line Interface for {metadata.identifier}") | ||
parser.add_argument( | ||
"--metadata", | ||
help="Return the apps metadata and exit", | ||
action="store_true") | ||
parser.add_argument("--input", help="The input MMIF file") | ||
parser.add_argument("--output", help="The output MMIF file") | ||
for parameter in metadata.parameters: | ||
nargs = '*' if parameter.type == 'map' else '?' | ||
parser.add_argument( | ||
f"--{parameter.name}", | ||
help=parameter.description, | ||
nargs=nargs, | ||
type=json_type_map.get(parameter.type), | ||
choices=parameter.choices, | ||
default=parameter.default, | ||
action="store") | ||
return parser | ||
|
||
|
||
def print_parameters(metadata): | ||
for parameter in metadata.parameters: | ||
continue | ||
print(f'\n{parameter.name}') | ||
print(f' type={parameter.type}') | ||
print(f' default={parameter.default}') | ||
print(f' choices={parameter.choices}') | ||
|
||
|
||
def print_args(args): | ||
print(args) | ||
print() | ||
for arg in vars(args): | ||
value = getattr(args, arg) | ||
print(f'{arg:18s} {str(type(value)):15s} {value}') | ||
|
||
|
||
def build_app_parameters(args): | ||
parameters = {} | ||
for arg in vars(args): | ||
if arg in ('input', 'output', 'metadata'): | ||
continue | ||
value = getattr(args, arg) | ||
parameters[arg] = value | ||
return parameters | ||
|
||
|
||
def adjust_parameters(parameters, args): | ||
# Adding the empty directory makes the app code work, but it still won't be able | ||
# to print the parameters as given by the user on the command line. So we loop | ||
# over the arguments to populate the raw parameters dictionary. | ||
parameters[ClamsApp._RAW_PARAMS_KEY] = {} | ||
for arg in sys.argv[1:]: | ||
if arg.startswith('--'): | ||
argname = arg[2:] | ||
argval = vars(args)[argname] | ||
argval = argval if type(argval) is list else [str(argval)] | ||
parameters[ClamsApp._RAW_PARAMS_KEY][argname] = argval | ||
|
||
|
||
|
||
if __name__ == '__main__': | ||
|
||
app = SwtDetection() | ||
metadata = get_metadata() | ||
|
||
argparser = create_argparser(metadata) | ||
args = argparser.parse_args() | ||
|
||
if args.metadata: | ||
print(metadata.jsonify(pretty=args.pretty)) | ||
else: | ||
parameters = build_app_parameters(args) | ||
# Simply calling _annotate() breaks when we try to create the view and copy the | ||
# parameters into it because the CLAMS code expects there to be raw parameters. | ||
# So we first adjust the parameters to match what the CLAMS code expects. | ||
adjust_parameters(parameters, args) | ||
mmif = Mmif(open(args.input).read()) | ||
app._annotate(mmif, **parameters) | ||
with open(args.output, 'w') as fh: | ||
fh.write(mmif.serialize(pretty=args.pretty)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,11 @@ | ||
negative_label = 'NEG' | ||
positive_label = 'POS' | ||
|
||
# full typology from https://github.com/clamsproject/app-swt-detection/issues/1 | ||
FRAME_TYPES = ["B", "S", "S:H", "S:C", "S:D", "S:B", "S:G", "W", "L", "O", | ||
"M", "I", "N", "E", "P", "Y", "K", "G", "T", "F", "C", "R"] | ||
|
||
# These are time frames that are typically static (that is, the text does not | ||
# move around or change as with rolling credits). These are frame names after | ||
# the label mapping. | ||
static_frames = ['bars', 'slate', 'chyron'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +0,0 @@ | ||
model_file: "modeling/models/20240409-091401.convnext_lg.pt" | ||
model_config_file: "modeling/models/20240409-091401.convnext_lg.yml" | ||
|
||
# Milliseconds between sampled frames | ||
sampleRate: 1000 | ||
|
||
# Minimum score for a frame to be included in a potential timeframe | ||
minFrameScore: 0.01 | ||
|
||
# Minimum score for a timeframe to be selected | ||
minTimeframeScore: 0.5 | ||
|
||
# Minimum number of sampled frames required for a timeframe to be included | ||
minFrameCount: 2 | ||
|
||
# These are time frames that are typically static (that is, the text does not | ||
# move around or change as with rolling credits). These are frame names after | ||
# the label mapping. | ||
staticFrames: [bars, slate, chyron] | ||
|
||
# Set to False to turn off the stitcher | ||
useStitcher: True | ||
|
||
# This was the most frequent label mapping the previous configuration file, | ||
# which had default mappings for each model. | ||
labelMap: [ | ||
"B:bars", | ||
"S:slate", "S-H:slate", "S-C:slate", "S-D:slate", "S-G:slate", | ||
"W:other_opening", "L:other_opening", "O:other_opening", "M:other_opening", | ||
"I:chyron", "N:chyron", "Y:chyron", | ||
"C:credit", "R:credit", | ||
"E:other_text", "K:other_text", "G:other_text", "T:other_text", "F:other_text" ] | ||
Oops, something went wrong.