aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Klimczak <benjamin.klimczak@arm.com>2022-11-07 12:04:06 +0000
committerBenjamin Klimczak <benjamin.klimczak@arm.com>2022-11-09 11:23:32 +0000
commitf77ffbd3033d122a375c3be63624ea80507d0541 (patch)
tree0465aafdba081f15a769c5929ed5d3b5610bbed1
parent006c95f3053c89af41726c582c7b4d0f9914553b (diff)
downloadmlia-f77ffbd3033d122a375c3be63624ea80507d0541.tar.gz
MLIA-275 Remove support for CSV output
Change-Id: I212c9cad5f2ac28b75b1d9e2fb8f1f8b444b8397
-rw-r--r--README.md6
-rw-r--r--src/mlia/cli/options.py3
-rw-r--r--src/mlia/core/reporting.py126
-rw-r--r--src/mlia/core/typing.py2
-rw-r--r--tests/test_cli_options.py3
-rw-r--r--tests/test_core_reporting.py79
-rw-r--r--tests/test_devices_ethosu_reporters.py87
7 files changed, 14 insertions, 292 deletions
diff --git a/README.md b/README.md
index 20f80fe..ec4080d 100644
--- a/README.md
+++ b/README.md
@@ -217,7 +217,7 @@ mlia operators --target-profile ethos-u55-256 ~/models/mobilenet_v1_1.0_224_quan
* --output: Name of the file where the report will be saved. The report format
is automatically detected based on the file extension. Supported formats are:
- csv, json.
+ json.
##### Optional arguments
@@ -260,7 +260,7 @@ mlia performance ~/models/mobilenet_v1_1.0_224_quant.tflite \
* --output: Name of the file where the report will be saved. The report format
is automatically detected based on the file extension. Supported formats are:
- csv, json.
+ json.
##### Debug options
@@ -388,7 +388,7 @@ mlia all_tests --output ./report.json ~/models/ds_cnn_l.h5
* --output: Name of the file where the report will be saved. The report format
is automatically detected based on the file extension. Supported formats are:
- csv, json.
+ json.
##### Debug options
diff --git a/src/mlia/cli/options.py b/src/mlia/cli/options.py
index b28fa8f..f6dcf75 100644
--- a/src/mlia/cli/options.py
+++ b/src/mlia/cli/options.py
@@ -11,6 +11,7 @@ from typing import Callable
from mlia.cli.config import get_available_backends
from mlia.cli.config import get_default_backends
from mlia.cli.config import is_corstone_backend
+from mlia.core.reporting import OUTPUT_FORMATS
from mlia.utils.filesystem import get_supported_profile_names
from mlia.utils.types import is_number
@@ -77,7 +78,7 @@ def add_tflite_model_options(parser: argparse.ArgumentParser) -> None:
def add_output_options(parser: argparse.ArgumentParser) -> None:
"""Add output specific options."""
- valid_extensions = ["csv", "json"]
+ valid_extensions = OUTPUT_FORMATS
def check_extension(filename: str) -> str:
"""Check extension of the provided file."""
diff --git a/src/mlia/core/reporting.py b/src/mlia/core/reporting.py
index 0c8fabc..b96a6b5 100644
--- a/src/mlia/core/reporting.py
+++ b/src/mlia/core/reporting.py
@@ -3,7 +3,6 @@
"""Reporting module."""
from __future__ import annotations
-import csv
import json
import logging
from abc import ABC
@@ -36,6 +35,8 @@ from mlia.utils.types import is_list_of
logger = logging.getLogger(__name__)
+OUTPUT_FORMATS = ("json",)
+
class Report(ABC):
"""Abstract class for the report."""
@@ -45,10 +46,6 @@ class Report(ABC):
"""Convert to json serializible format."""
@abstractmethod
- def to_csv(self, **kwargs: Any) -> list[Any]:
- """Convert to csv serializible format."""
-
- @abstractmethod
def to_plain_text(self, **kwargs: Any) -> str:
"""Convert to human readable format."""
@@ -134,10 +131,6 @@ class Cell:
val = self._get_value()
return self._apply_style(val)
- def to_csv(self) -> Any:
- """Cell definition for csv."""
- return self.value
-
def to_json(self) -> Any:
"""Cell definition for json."""
return self.value
@@ -168,10 +161,6 @@ class CountAwareCell(Cell):
super().__init__(value, Format(str_fmt=format_value))
- def to_csv(self) -> Any:
- """Cell definition for csv."""
- return {"value": self.value, "unit": self.unit}
-
def to_json(self) -> Any:
"""Cell definition for json."""
return {"value": self.value, "unit": self.unit}
@@ -239,41 +228,6 @@ class NestedReport(Report):
self.alias = alias
self.items = items
- def to_csv(self, **kwargs: Any) -> list[Any]:
- """Convert to csv serializible format."""
- result = {}
-
- def collect_item_values(
- item: ReportItem,
- _parent: ReportItem | None,
- _prev: ReportItem | None,
- _level: int,
- ) -> None:
- """Collect item values into a dictionary.."""
- if item.value is None:
- return
-
- if not isinstance(item.value, Cell):
- result[item.alias] = item.raw_value
- return
-
- csv_value = item.value.to_csv()
- if isinstance(csv_value, dict):
- csv_value = {
- f"{item.alias}_{key}": value for key, value in csv_value.items()
- }
- else:
- csv_value = {item.alias: csv_value}
-
- result.update(csv_value)
-
- self._traverse(self.items, collect_item_values)
-
- # make list out of the result dictionary
- # first element - keys of the dictionary as headers
- # second element - list of the dictionary values
- return list(zip(*result.items()))
-
def to_json(self, **kwargs: Any) -> Any:
"""Convert to json serializible format."""
per_parent: dict[ReportItem | None, dict] = defaultdict(dict)
@@ -474,32 +428,6 @@ class Table(Report):
return title + formatted_table + footer
- def to_csv(self, **kwargs: Any) -> list[Any]:
- """Convert table to csv format."""
- headers = [[c.header for c in self.columns if c.supports_format("csv")]]
-
- def item_data(item: Any) -> Any:
- if isinstance(item, Cell):
- return item.value
-
- if isinstance(item, Table):
- return ";".join(
- str(item_data(cell)) for row in item.rows for cell in row
- )
-
- return item
-
- rows = [
- [
- item_data(item)
- for (item, col) in zip(row, self.columns)
- if col.supports_format("csv")
- ]
- for row in self.rows
- ]
-
- return headers + rows
-
class SingleRow(Table):
"""Table with a single row."""
@@ -541,46 +469,6 @@ class CompoundReport(Report):
return result
- def to_csv(self, **kwargs: Any) -> list[Any]:
- """Convert to csv serializible format.
-
- CSV format does support only one table. In order to be able to export
- multiply tables they should be merged before that. This method tries to
- do next:
-
- - if all tables have the same length then just concatenate them
- - if one table has many rows and other just one (two with headers), then
- for each row in table with many rows duplicate values from other tables
- """
- csv_data = [item.to_csv() for item in self.reports]
- lengths = [len(csv_item_data) for csv_item_data in csv_data]
-
- same_length = len(set(lengths)) == 1
- if same_length:
- # all lists are of the same length, merge them into one
- return [[cell for item in row for cell in item] for row in zip(*csv_data)]
-
- main_obj_indexes = [i for i, item in enumerate(csv_data) if len(item) > 2]
- one_main_obj = len(main_obj_indexes) == 1
-
- reference_obj_indexes = [i for i, item in enumerate(csv_data) if len(item) == 2]
- other_only_ref_objs = len(reference_obj_indexes) == len(csv_data) - 1
-
- if one_main_obj and other_only_ref_objs:
- main_obj = csv_data[main_obj_indexes[0]]
- return [
- item
- + [
- ref_item
- for ref_table_index in reference_obj_indexes
- for ref_item in csv_data[ref_table_index][0 if i == 0 else 1]
- ]
- for i, item in enumerate(main_obj)
- ]
-
- # write tables one after another if there is no other options
- return [row for item in csv_data for row in item]
-
def to_plain_text(self, **kwargs: Any) -> str:
"""Convert to human readable format."""
return "\n".join(item.to_plain_text(**kwargs) for item in self.reports)
@@ -624,12 +512,6 @@ def text_reporter(report: Report, output: FileLike, **kwargs: Any) -> None:
print(report.to_plain_text(**kwargs), file=output)
-def csv_reporter(report: Report, output: FileLike, **kwargs: Any) -> None:
- """Produce report in csv format."""
- csv_writer = csv.writer(output)
- csv_writer.writerows(report.to_csv(**kwargs))
-
-
def produce_report(
data: Any,
formatter: Callable[[Any], Report],
@@ -639,7 +521,7 @@ def produce_report(
) -> None:
"""Produce report based on provided data."""
# check if provided format value is supported
- formats = {"json": json_reporter, "plain_text": text_reporter, "csv": csv_reporter}
+ formats = {"json": json_reporter, "plain_text": text_reporter}
if fmt not in formats:
raise Exception(f"Unknown format {fmt}")
@@ -764,7 +646,7 @@ def resolve_output_format(output: PathOrFileLike | None) -> OutputFormat:
if isinstance(output, (str, Path)):
format_from_filename = Path(output).suffix.lstrip(".")
- if format_from_filename in ["json", "csv"]:
+ if format_from_filename in OUTPUT_FORMATS:
return cast(OutputFormat, format_from_filename)
return "plain_text"
diff --git a/src/mlia/core/typing.py b/src/mlia/core/typing.py
index bda995c..8244ff5 100644
--- a/src/mlia/core/typing.py
+++ b/src/mlia/core/typing.py
@@ -9,4 +9,4 @@ from typing import Union
FileLike = TextIO
PathOrFileLike = Union[str, Path, FileLike]
-OutputFormat = Literal["plain_text", "csv", "json"]
+OutputFormat = Literal["plain_text", "json"]
diff --git a/tests/test_cli_options.py b/tests/test_cli_options.py
index f898146..d75f7c0 100644
--- a/tests/test_cli_options.py
+++ b/tests/test_cli_options.py
@@ -147,9 +147,6 @@ def test_get_target_opts(args: dict | None, expected_opts: list[str]) -> None:
[["--output", "report.json"], "report.json"],
[["--output", "REPORT.JSON"], "REPORT.JSON"],
[["--output", "some_folder/report.json"], "some_folder/report.json"],
- [["--output", "report.csv"], "report.csv"],
- [["--output", "REPORT.CSV"], "REPORT.CSV"],
- [["--output", "some_folder/report.csv"], "some_folder/report.csv"],
],
)
def test_output_options(output_parameters: list[str], expected_path: str) -> None:
diff --git a/tests/test_core_reporting.py b/tests/test_core_reporting.py
index da7998c..feff5cc 100644
--- a/tests/test_core_reporting.py
+++ b/tests/test_core_reporting.py
@@ -95,9 +95,6 @@ def test_table_representation(with_notes: bool, expected_text_report: str) -> No
)
table = sample_table(with_notes)
- csv_repr = table.to_csv()
- assert csv_repr == [["Header 2", "Header 3"], [2, 3], [5, 123123]]
-
json_repr = table.to_json()
assert json_repr == {
"sample_table": [
@@ -110,48 +107,8 @@ def test_table_representation(with_notes: bool, expected_text_report: str) -> No
assert text_report == expected_text_report
-def test_csv_nested_table_representation() -> None:
- """Test representation of the nested tables in csv format."""
-
- def sample_table(num_of_cols: int) -> Table:
- columns = [
- Column("Header 1", alias="header1"),
- Column("Header 2", alias="header2"),
- ]
-
- rows = [
- (
- 1,
- Table(
- columns=[
- Column(f"Nested column {i+1}") for i in range(num_of_cols)
- ],
- rows=[[f"value{i+1}" for i in range(num_of_cols)]],
- name="Nested table",
- ),
- )
- ]
-
- return Table(columns, rows, name="Sample table", alias="sample_table")
-
- assert sample_table(num_of_cols=2).to_csv() == [
- ["Header 1", "Header 2"],
- [1, "value1;value2"],
- ]
-
- assert sample_table(num_of_cols=1).to_csv() == [
- ["Header 1", "Header 2"],
- [1, "value1"],
- ]
-
- assert sample_table(num_of_cols=0).to_csv() == [
- ["Header 1", "Header 2"],
- [1, ""],
- ]
-
-
@pytest.mark.parametrize(
- "report, expected_plain_text, expected_json_data, expected_csv_data",
+ "report, expected_plain_text, expected_json_data",
[
(
NestedReport(
@@ -168,10 +125,6 @@ Sample report:
{
"sample_report": {"item": "item_value"},
},
- [
- ("item",),
- ("item_value",),
- ],
),
(
NestedReport(
@@ -196,10 +149,6 @@ Sample report:
"item": {"nested_item": "nested_item_value"},
},
},
- [
- ("item", "nested_item"),
- ("item_value", "nested_item_value"),
- ],
),
(
NestedReport(
@@ -224,10 +173,6 @@ Sample report:
"item": {"nested_item": {"unit": "bytes", "value": 10}},
},
},
- [
- ("item", "nested_item_value", "nested_item_unit"),
- ("item_value", 10, "bytes"),
- ],
),
(
NestedReport(
@@ -260,10 +205,6 @@ Sample report:
"item": {"nested_item": 10},
},
},
- [
- ("item", "nested_item"),
- ("item_value", 10),
- ],
),
(
NestedReport(
@@ -296,10 +237,6 @@ Sample report:
"item": {"nested_item": 10},
},
},
- [
- ("item", "nested_item"),
- ("item_value", 10),
- ],
),
(
NestedReport(
@@ -326,10 +263,6 @@ Sample report:
"item": {"nested_item": 10},
},
},
- [
- ("item", "nested_item"),
- ("item_value", 10),
- ],
),
(
NestedReport(
@@ -358,10 +291,6 @@ Sample report:
"item": {"nested_item": 10},
},
},
- [
- ("item", "nested_item"),
- ("item_value", 10),
- ],
),
],
)
@@ -369,7 +298,6 @@ def test_nested_report_representation(
report: NestedReport,
expected_plain_text: str,
expected_json_data: dict,
- expected_csv_data: list,
) -> None:
"""Test representation of the NestedReport."""
plain_text = report.to_plain_text()
@@ -378,9 +306,6 @@ def test_nested_report_representation(
json_data = report.to_json()
assert json_data == expected_json_data
- csv_data = report.to_csv()
- assert csv_data == expected_csv_data
-
def test_single_row_representation() -> None:
"""Test representation of the SingleRow."""
@@ -398,7 +323,6 @@ Single row example:
column1 value1
""".strip()
assert single_row.to_plain_text() == expected_text
- assert single_row.to_csv() == [["column1"], ["value1"]]
assert single_row.to_json() == {"simple_row_example": [{"column1": "value1"}]}
with pytest.raises(Exception, match="Table should have only one row"):
@@ -423,7 +347,6 @@ Single row example:
["", "plain_text"],
["some_file", "plain_text"],
["some_format.some_ext", "plain_text"],
- ["output.csv", "csv"],
["output.json", "json"],
],
)
diff --git a/tests/test_devices_ethosu_reporters.py b/tests/test_devices_ethosu_reporters.py
index f8a7d86..f04270c 100644
--- a/tests/test_devices_ethosu_reporters.py
+++ b/tests/test_devices_ethosu_reporters.py
@@ -68,11 +68,6 @@ from mlia.utils.console import remove_ascii_codes
doesnt_raise(),
],
[
- "csv",
- sys.stdout,
- doesnt_raise(),
- ],
- [
"plain_text",
"report.txt",
doesnt_raise(),
@@ -82,17 +77,12 @@ from mlia.utils.console import remove_ascii_codes
"report.json",
doesnt_raise(),
],
- [
- "csv",
- "report.csv",
- doesnt_raise(),
- ],
],
)
def test_report(
data: Any,
formatters: list[Callable],
- fmt: Literal["plain_text", "json", "csv"],
+ fmt: Literal["plain_text", "json"],
output: Any,
expected_error: Any,
tmp_path: Path,
@@ -111,7 +101,7 @@ def test_report(
@pytest.mark.parametrize(
- "ops, expected_plain_text, expected_json_dict, expected_csv_list",
+ "ops, expected_plain_text, expected_json_dict",
[
(
[
@@ -187,17 +177,6 @@ Operators:
},
]
},
- [
- ["Operator name", "Operator type", "Placement", "Notes"],
- ["npu_supported", "test_type", "NPU", ""],
- ["cpu_only", "test_type", "CPU", "CPU only operator"],
- [
- "npu_unsupported",
- "test_type",
- "CPU",
- "Not supported operator;Reason why operator is not supported",
- ],
- ],
),
],
)
@@ -205,7 +184,6 @@ def test_report_operators(
ops: list[Operator],
expected_plain_text: str,
expected_json_dict: dict,
- expected_csv_list: list,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Test report_operatos formatter."""
@@ -221,12 +199,9 @@ def test_report_operators(
json_dict = report.to_json()
assert json_dict == expected_json_dict
- csv_list = report.to_csv()
- assert csv_list == expected_csv_list
-
@pytest.mark.parametrize(
- "device, expected_plain_text, expected_json_dict, expected_csv_list",
+ "device, expected_plain_text, expected_json_dict",
[
[
EthosUConfiguration("ethos-u55-256"),
@@ -322,58 +297,6 @@ def test_report_operators(
},
}
},
- [
- (
- "target",
- "mac",
- "memory_mode",
- "const_mem_area",
- "arena_mem_area",
- "cache_mem_area",
- "arena_cache_size_value",
- "arena_cache_size_unit",
- "system_config",
- "accelerator_clock_value",
- "accelerator_clock_unit",
- "axi0_port",
- "axi1_port",
- "clock_scales",
- "burst_length_value",
- "burst_length_unit",
- "read_latency_value",
- "read_latency_unit",
- "write_latency_value",
- "write_latency_unit",
- "permanent_storage_mem_area",
- "feature_map_storage_mem_area",
- "fast_storage_mem_area",
- ),
- (
- "ethos-u55",
- 256,
- "Shared_Sram",
- "Axi1",
- "Axi0",
- "Axi0",
- 2096768,
- "bytes",
- "Ethos_U55_High_End_Embedded",
- 500000000.0,
- "Hz",
- "Sram",
- "OffChipFlash",
- 0.125,
- 128,
- "bytes",
- 64,
- "cycles",
- 64,
- "cycles",
- "OffChipFlash",
- "Sram",
- "Sram",
- ),
- ],
],
],
)
@@ -381,7 +304,6 @@ def test_report_device_details(
device: EthosUConfiguration,
expected_plain_text: str,
expected_json_dict: dict,
- expected_csv_list: list,
) -> None:
"""Test report_operatos formatter."""
report = report_device_details(device)
@@ -393,9 +315,6 @@ def test_report_device_details(
json_dict = report.to_json()
assert json_dict == expected_json_dict
- csv_list = report.to_csv()
- assert csv_list == expected_csv_list
-
def test_get_reporter(tmp_path: Path) -> None:
"""Test reporter functionality."""