15b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
25b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang# Use of this source code is governed by a BSD-style license that can be
35b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang# found in the LICENSE file.
45b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
55b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang"""A module providing the summary for multiple test results.
65b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
75b6a306f752ee6c8e081713d20e13f7ce11db684Joseph HwangThis firmware_summary module is used to collect the test results of
85b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwangmultiple rounds from the logs generated by different firmware versions.
95b6a306f752ee6c8e081713d20e13f7ce11db684Joseph HwangThe test results of the various validators of every gesture are displayed.
105b6a306f752ee6c8e081713d20e13f7ce11db684Joseph HwangIn addition, the test results of every validator across all gestures are
115b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwangalso summarized.
125b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
135b6a306f752ee6c8e081713d20e13f7ce11db684Joseph HwangUsage:
145b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang$ python firmware_summary log_directory
155b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
165b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
175b6a306f752ee6c8e081713d20e13f7ce11db684Joseph HwangA typical summary output looks like
185b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
195b6a306f752ee6c8e081713d20e13f7ce11db684Joseph HwangTest Summary (by gesture)            :  fw_2.41   fw_2.42     count
205b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang---------------------------------------------------------------------
215b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwangone_finger_tracking
225b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  CountTrackingIDValidator           :     1.00      0.90        12
235b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  LinearityBothEndsValidator         :     0.97      0.89        12
245b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  LinearityMiddleValidator           :     1.00      1.00        12
255b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  NoGapValidator                     :     0.74      0.24        12
265b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  NoReversedMotionBothEndsValidator  :     0.68      0.34        12
275b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  NoReversedMotionMiddleValidator    :     1.00      1.00        12
280d074428ab1b7cc71afd30ce1cfc863e13793fffCharlie Mooney  ReportRateValidator                :     1.00      1.00        12
295b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwangone_finger_to_edge
305b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  CountTrackingIDValidator           :     1.00      1.00         4
315b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  LinearityBothEndsValidator         :     0.88      0.89         4
325b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  LinearityMiddleValidator           :     1.00      1.00         4
335b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  NoGapValidator                     :     0.50      0.00         4
345b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  NoReversedMotionMiddleValidator    :     1.00      1.00         4
355b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  RangeValidator                     :     1.00      1.00         4
365b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
375b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  ...
385b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
395b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
405b6a306f752ee6c8e081713d20e13f7ce11db684Joseph HwangTest Summary (by validator)          :   fw_2.4  fw_2.4.a     count
415b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang---------------------------------------------------------------------
425b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  CountPacketsValidator              :     1.00      0.82         6
435b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  CountTrackingIDValidator           :     0.92      0.88        84
445b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
455b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang  ...
465b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
475b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang"""
485b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
495b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
50e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwangimport getopt
515b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwangimport os
525b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwangimport sys
535b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
54ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwangimport firmware_log
557584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwangimport test_conf as conf
565b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
57330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwangfrom collections import defaultdict
58330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang
59ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwangfrom common_util import print_and_exit
60e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwangfrom firmware_constants import OPTIONS
617584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwangfrom test_conf import (log_root_dir, merged_validators, segment_weights,
627584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                       validator_weights)
637584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwangfrom validators import BaseValidator, get_parent_validators
647dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang
657dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang
667dbae7827dae0767bffe303708e19483b80a007eJoseph Hwangclass OptionsDisplayMetrics:
677dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang    """The options of displaying metrics."""
687dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang    # Defining the options of displaying metrics
691551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    HIDE_SOME_METRICS_STATS = '0'
701551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    DISPLAY_ALL_METRICS_STATS = '1'
711551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    DISPLAY_ALL_METRICS_WITH_RAW_VALUES = '2'
721551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    DISPLAY_METRICS_OPTIONS = [HIDE_SOME_METRICS_STATS,
731551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang                               DISPLAY_ALL_METRICS_STATS,
741551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang                               DISPLAY_ALL_METRICS_WITH_RAW_VALUES]
751551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    DISPLAY_METRICS_DEFAULT = DISPLAY_ALL_METRICS_WITH_RAW_VALUES
767dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang
777dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang    def __init__(self, option):
787dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang        """Initialize with the level value.
797dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang
807dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang        @param option: the option of display metrics
817dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang        """
827dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang        if option not in self.DISPLAY_METRICS_OPTIONS:
837dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang            option = self.DISPLAY_METRICS_DEFAULT
847dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang
857dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang        # To display all metrics statistics grouped by validators?
861551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang        self.display_all_stats = (
871551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang                option == self.DISPLAY_ALL_METRICS_STATS or
881551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang                option == self.DISPLAY_ALL_METRICS_WITH_RAW_VALUES)
897dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang
907dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang        # To display the raw metrics values in details on file basis?
911551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang        self.display_raw_values = (
921551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang                option == self.DISPLAY_ALL_METRICS_WITH_RAW_VALUES)
937dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang
947dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang
955b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwangclass FirmwareSummary:
968c5e275df682ef5b0ad52574ae1e2e31fc724509Joseph Hwang    """Summary for touch device firmware tests."""
975b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
98313de5edc48d6af3b8891e69114ddf7d79c8516cJoseph Hwang    def __init__(self, log_dir, display_metrics=False, debug_flag=False,
99b0773e1ff6a735d964b563d494d7a06d19a873baJoseph Hwang                 display_scores=False, individual_round_flag=False,
100ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang                 segment_weights=segment_weights,
101ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang                 validator_weights=validator_weights):
102ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        """ segment_weights and validator_weights are passed as arguments
103180c7259a5753792ef9a044bf1ef8465aabf654bJoseph Hwang        so that it is possible to assign arbitrary weights in unit tests.
104180c7259a5753792ef9a044bf1ef8465aabf654bJoseph Hwang        """
1055b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang        if os.path.isdir(log_dir):
1065b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang            self.log_dir = log_dir
1075b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang        else:
1085b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang            error_msg = 'Error: The test result directory does not exist: %s'
1095b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang            print error_msg % log_dir
110039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang            sys.exit(1)
1115b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
112313de5edc48d6af3b8891e69114ddf7d79c8516cJoseph Hwang        self.display_metrics = display_metrics
113b0773e1ff6a735d964b563d494d7a06d19a873baJoseph Hwang        self.display_scores = display_scores
114c9cdc9527e1087addd1e21cf58608fd75173df5aJoseph Hwang        self.slog = firmware_log.SummaryLog(log_dir,
115c9cdc9527e1087addd1e21cf58608fd75173df5aJoseph Hwang                                            segment_weights,
116c9cdc9527e1087addd1e21cf58608fd75173df5aJoseph Hwang                                            validator_weights,
117c9cdc9527e1087addd1e21cf58608fd75173df5aJoseph Hwang                                            individual_round_flag,
118c9cdc9527e1087addd1e21cf58608fd75173df5aJoseph Hwang                                            debug_flag)
1191d67b1e2e2db87dfcb0348b41b608235c3797877Joseph Hwang
1205b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang    def _print_summary_title(self, summary_title_str):
1215b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang        """Print the summary of the test results by gesture."""
122ce2b1d4612ffdab0f41d3e191cbb4bd470859857Joseph Hwang        # Create a flexible column title format according to the number of
123ce2b1d4612ffdab0f41d3e191cbb4bd470859857Joseph Hwang        # firmware versions which could be 1, 2, or more.
12473200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        #
12573200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        # A typical summary title looks like
12673200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        # Test Summary ()          :    fw_11.26             fw_11.23
12773200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        #                               mean  ssd  count     mean ssd count
12873200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        # ----------------------------------------------------------------------
12973200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        #
13073200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        # The 1st line above is called title_fw.
13173200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        # The 2nd line above is called title_statistics.
13273200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        #
13373200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        # As an example for 2 firmwares, title_fw_format looks like:
13473200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        #     '{0:<37}:  {1:>12}  {2:>21}'
13573200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        title_fw_format_list = ['{0:<37}:',]
136ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        for i in range(len(self.slog.fws)):
13773200d5a267fbae83ce71759b4053c6164653095Joseph Hwang            format_space = 12 if i == 0 else (12 + 9)
13873200d5a267fbae83ce71759b4053c6164653095Joseph Hwang            title_fw_format_list.append('{%d:>%d}' % (i + 1, format_space))
13973200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        title_fw_format = ' '.join(title_fw_format_list)
14073200d5a267fbae83ce71759b4053c6164653095Joseph Hwang
14173200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        # As an example for 2 firmwares, title_statistics_format looks like:
14273200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        #     '{0:>47} {1:>6} {2:>5} {3:>8} {4:>6} {5:>5}'
14373200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        title_statistics_format_list = []
144ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        for i in range(len(self.slog.fws)):
14573200d5a267fbae83ce71759b4053c6164653095Joseph Hwang            format_space = (12 + 35) if i == 0 else 8
14673200d5a267fbae83ce71759b4053c6164653095Joseph Hwang            title_statistics_format_list.append('{%d:>%d}' % (3 * i,
14773200d5a267fbae83ce71759b4053c6164653095Joseph Hwang                                                              format_space))
14873200d5a267fbae83ce71759b4053c6164653095Joseph Hwang            title_statistics_format_list.append('{%d:>%d}' % (3 * i + 1 , 6))
14973200d5a267fbae83ce71759b4053c6164653095Joseph Hwang            title_statistics_format_list.append('{%d:>%d}' % (3 * i + 2 , 5))
15073200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        title_statistics_format = ' '.join(title_statistics_format_list)
15173200d5a267fbae83ce71759b4053c6164653095Joseph Hwang
15273200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        # Create title_fw_list
15373200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        # As an example for two firmware versions, it looks like
15473200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        #   ['Test Summary (by gesture)', 'fw_2.4', 'fw_2.5']
155ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        title_fw_list = [summary_title_str,] + self.slog.fws
15673200d5a267fbae83ce71759b4053c6164653095Joseph Hwang
15773200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        # Create title_statistics_list
15873200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        # As an example for two firmware versions, it looks like
15973200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        #   ['mean', 'ssd', 'count', 'mean', 'ssd', 'count', ]
160ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        title_statistics_list = ['mean', 'ssd', 'count'] * len(self.slog.fws)
161ce2b1d4612ffdab0f41d3e191cbb4bd470859857Joseph Hwang
162ce2b1d4612ffdab0f41d3e191cbb4bd470859857Joseph Hwang        # Print the title.
16373200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        title_fw = title_fw_format.format(*title_fw_list)
16473200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        title_statistics = title_statistics_format.format(
16573200d5a267fbae83ce71759b4053c6164653095Joseph Hwang                *title_statistics_list)
16673200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        print '\n\n', title_fw
16773200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        print title_statistics
16873200d5a267fbae83ce71759b4053c6164653095Joseph Hwang        print '-' * len(title_statistics)
16973200d5a267fbae83ce71759b4053c6164653095Joseph Hwang
170ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang    def _print_result_stats(self, gesture=None):
171ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        """Print the result statistics of validators."""
172ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        for validator in self.slog.validators:
173c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang            stat_scores_data = []
174c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang            statistics_format_list = []
175ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang            for fw in self.slog.fws:
176ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang                result = self.slog.get_result(fw=fw, gesture=gesture,
1777584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                                              validators=validator)
178c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang                scores_data = result.stat_scores.all_data
179c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang                if scores_data:
180c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang                    stat_scores_data += scores_data
181c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang                    statistics_format_list.append('{:>8.2f} {:>6.2f} {:>5}')
182c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang                else:
183c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang                    stat_scores_data.append('')
184c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang                    statistics_format_list.append('{:>21}')
185313de5edc48d6af3b8891e69114ddf7d79c8516cJoseph Hwang
186ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang            # Print the score statistics of all firmwares on the same row.
187c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang            if any(stat_scores_data):
188c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang                stat_scores_data.insert(0, validator)
189c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang                statistics_format_list.insert(0,'  {:<35}:')
190c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang                statistics_format = ' '.join(statistics_format_list)
191c4752b22ff8275d8c3f63e2d6b93c1ca6aa1dabaJoseph Hwang                print statistics_format.format(*tuple(stat_scores_data))
192ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang
193ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang    def _print_result_stats_by_gesture(self):
1945b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang        """Print the summary of the test results by gesture."""
1955b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang        self._print_summary_title('Test Summary (by gesture)')
196ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        for gesture in self.slog.gestures:
1975b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang            print gesture
198ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang            self._print_result_stats(gesture=gesture)
199ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang
200ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang    def _print_result_stats_by_validator(self):
201ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        """Print the summary of the test results by validator. The validator
202ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        results of all gestures are combined to compute the statistics.
203ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        """
2045b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang        self._print_summary_title('Test Summary (by validator)')
205ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        self._print_result_stats()
206ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang
2078047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang    def _get_metric_name_for_display(self, metric_name):
2088047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang        """Get the metric name for display.
2098047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang        We would like to shorten the metric name when displayed.
2108047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang
2118047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang        @param metric_name: a metric name
2128047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang        """
213aa7b540459960d887cd7520f4d6a963a33cc7a85Joseph Hwang        return metric_name.split('--')[0]
2148047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang
2157584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang    def _get_merged_validators(self):
2167584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang        merged = defaultdict(list)
2177584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang        for validator_name in self.slog.validators:
2187584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang            parents = get_parent_validators(validator_name)
2197584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang            for parent in parents:
2207584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                if parent in merged_validators:
2217584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                    merged[parent].append(validator_name)
2227584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                    break
2237584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang            else:
2247584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                merged[validator_name] = [validator_name,]
2257584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang        return sorted(merged.values())
2267584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang
2277584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang    def _print_statistics_of_metrics(self, detailed=True, gesture=None):
228330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang        """Print the statistics of metrics by gesture or by validator.
229330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang
230330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang        @param gesture: print the statistics grouped by gesture
231330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang                if this argument is specified; otherwise, by validator.
2327584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang        @param detailed: print statistics for all derived validators if True;
2337584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                otherwise, print the merged statistics, e.g.,
2347584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                both StationaryFingerValidator and StationaryTapValidator
2357584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                are merged into StationaryValidator.
236330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang        """
237330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang        # Print the complete title which looks like:
238330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang        #   <title_str>  <fw1>  <fw2>  ...  <description>
2397dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang        fws = self.slog.fws
2407dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang        num_fws = len(fws)
241defa4829f2c4bcdca038d6b477d7c7d1c2477266Joseph Hwang        fws_str_max_width = max(map(len, fws))
242defa4829f2c4bcdca038d6b477d7c7d1c2477266Joseph Hwang        fws_str_width = max(fws_str_max_width + 1, 10)
2437584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang        table_name = ('Detailed table (for debugging)' if detailed else
2447584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                      'Summary table')
245330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang        title_str = ('Metrics statistics by gesture: ' + gesture if gesture else
246330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang                     'Metrics statistics by validator')
2472bef8f1757544a8f9f302d6a30e80c16fc940d18Joseph Hwang        description_str = 'description (lower is better)'
248defa4829f2c4bcdca038d6b477d7c7d1c2477266Joseph Hwang        fw_format = '{:>%d}' % fws_str_width
2497dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang        complete_title = ('{:<37}: '.format(title_str) +
250defa4829f2c4bcdca038d6b477d7c7d1c2477266Joseph Hwang                          (fw_format * num_fws).format(*fws) +
2512bef8f1757544a8f9f302d6a30e80c16fc940d18Joseph Hwang                          '  {:<40}'.format(description_str))
2527584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang        print '\n' * 2
2537584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang        print table_name
2547584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang        print complete_title
2552bef8f1757544a8f9f302d6a30e80c16fc940d18Joseph Hwang        print '-' * len(complete_title)
256330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang
257330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang        # Print the metric name and the metric stats values of every firmwares
2587dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang        name_format = ' ' * 6 + '{:<31}:'
2597dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang        description_format = ' {:<40}'
260defa4829f2c4bcdca038d6b477d7c7d1c2477266Joseph Hwang        float_format = '{:>%d.2f}' % fws_str_width
261defa4829f2c4bcdca038d6b477d7c7d1c2477266Joseph Hwang        blank_format = '{:>%d}' % fws_str_width
2627584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang
2637584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang        validators = (self.slog.validators if detailed else
2647584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                      self._get_merged_validators())
2657584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang
2667584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang        for validator in validators:
267330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang            fw_stats_values = defaultdict(dict)
2687dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang            for fw in fws:
269330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang                result = self.slog.get_result(fw=fw, gesture=gesture,
2707584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                                              validators=validator)
271330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang                stat_metrics = result.stat_metrics
272330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang
273330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang                for metric_name in stat_metrics.metrics_values:
274330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang                    fw_stats_values[metric_name][fw] = \
275330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang                            stat_metrics.stats_values[metric_name]
276330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang
2777dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang            fw_stats_values_printed = False
278330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang            for metric_name, fw_values_dict in sorted(fw_stats_values.items()):
27901c5305a76cf57925974566a4928077e275f4079Joseph Hwang                values = []
28001c5305a76cf57925974566a4928077e275f4079Joseph Hwang                values_format = ''
28101c5305a76cf57925974566a4928077e275f4079Joseph Hwang                for fw in fws:
28201c5305a76cf57925974566a4928077e275f4079Joseph Hwang                    value = fw_values_dict.get(fw, '')
28301c5305a76cf57925974566a4928077e275f4079Joseph Hwang                    values.append(value)
284defa4829f2c4bcdca038d6b477d7c7d1c2477266Joseph Hwang                    values_format += float_format if value else blank_format
28501c5305a76cf57925974566a4928077e275f4079Joseph Hwang
2867dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang                # The metrics of some special validators will not be shown
2877dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang                # unless the display_all_stats flag is True or any stats values
2887dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang                # are non-zero.
2897dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang                if (validator not in conf.validators_hidden_when_no_failures or
2907dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang                        self.display_metrics.display_all_stats or any(values)):
2917dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang                    if not fw_stats_values_printed:
2927dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang                        fw_stats_values_printed = True
2937584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                        if isinstance(validator, list):
2947584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                            print (' ' + ' {}' * len(validator)).format(*validator)
2957584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                        else:
2967584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                            print '  ' + validator
2978047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang                    disp_name = self._get_metric_name_for_display(metric_name)
2988047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang                    print name_format.format(disp_name),
2997dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang                    print values_format.format(*values),
3007dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang                    print description_format.format(
3017dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang                            stat_metrics.metrics_props[metric_name].description)
3027dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang
303039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang    def _print_raw_metrics_values(self):
304039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang        """Print the raw metrics values."""
305039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang        # The subkey() below extracts (gesture, variation, round) from
306039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang        # metric.key which is (fw, round, gesture, variation, validator)
307039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang        subkey = lambda key: (key[2], key[3], key[1])
308039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang
309039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang        # The sum_len() below is used to calculate the sum of the length
310039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang        # of the elements in the subkey.
311039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang        sum_len = lambda lst: sum([len(str(l)) if l else 0 for l in lst])
312039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang
3138047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang        mnprops = firmware_log.MetricNameProps()
314039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang        print '\n\nRaw metrics values'
315313de5edc48d6af3b8891e69114ddf7d79c8516cJoseph Hwang        print '-' * 80
316039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang        for fw in self.slog.fws:
3178047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang            print '\n', fw
318039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang            for validator in self.slog.validators:
3197584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang                result = self.slog.get_result(fw=fw, validators=validator)
320039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                metrics_dict = result.stat_metrics.metrics_dict
321039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                if metrics_dict:
322039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                    print '\n' + ' ' * 3 + validator
323039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                for metric_name, metrics in sorted(metrics_dict.items()):
3248047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang                    disp_name = self._get_metric_name_for_display(metric_name)
3258047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang                    print ' ' * 6 + disp_name
3268047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang
3278047eb40635b781cdbfd3fa2b33f423b5ff724e1Joseph Hwang                    metric_note = mnprops.metrics_props[metric_name].note
328039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                    if metric_note:
329039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                        msg = '** Note: value below represents '
330039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                        print ' ' * 9 + msg + metric_note
331039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang
332039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                    # Make a metric value list sorted by
333039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                    #   (gesture, variation, round)
334039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                    value_list = sorted([(subkey(metric.key), metric.value)
335039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                                         for metric in metrics])
336039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang
337039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                    max_len = max([sum_len(value[0]) for value in value_list])
338039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                    template_prefix = ' ' * 9 + '{:<%d}: ' % (max_len + 5)
339039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                    for (gesture, variation, round), value in value_list:
340039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                        template = template_prefix + (
341039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                                '{}' if isinstance(value, tuple) else '{:.2f}')
342039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                        gvr_str = '%s.%s (%s)' % (gesture, variation, round)
343039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                        print template.format(gvr_str, value)
344313de5edc48d6af3b8891e69114ddf7d79c8516cJoseph Hwang
345ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang    def _print_final_weighted_averages(self):
346ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        """Print the final weighted averages of all validators."""
347ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        title_str = 'Test Summary (final weighted averages)'
3481d67b1e2e2db87dfcb0348b41b608235c3797877Joseph Hwang        print '\n\n' + title_str
3491d67b1e2e2db87dfcb0348b41b608235c3797877Joseph Hwang        print '-' * len(title_str)
350ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        weighted_average = self.slog.get_final_weighted_average()
351ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang        for fw in self.slog.fws:
352ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang            print '%s: %4.3f' % (fw, weighted_average[fw])
3531d67b1e2e2db87dfcb0348b41b608235c3797877Joseph Hwang
3545b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang    def print_result_summary(self):
3555b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang        """Print the summary of the test results."""
356bc9dba0f212df1b31ed43032c68f5e07e9ee9974Joseph Hwang        print self.slog.test_version
357330dcded15b07bf1869bd5d4cbf2bccbc6a14537Joseph Hwang        if self.display_metrics:
3587584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang            self._print_statistics_of_metrics(detailed=False)
3597584b3410e81bd7ea282432c2c3c55d9b4a06ea3Joseph Hwang            self._print_statistics_of_metrics(detailed=True)
3607dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang            if self.display_metrics.display_raw_values:
361039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                self._print_raw_metrics_values()
362b0773e1ff6a735d964b563d494d7a06d19a873baJoseph Hwang        if self.display_scores:
363b0773e1ff6a735d964b563d494d7a06d19a873baJoseph Hwang            self._print_result_stats_by_gesture()
364b0773e1ff6a735d964b563d494d7a06d19a873baJoseph Hwang            self._print_result_stats_by_validator()
365b0773e1ff6a735d964b563d494d7a06d19a873baJoseph Hwang            self._print_final_weighted_averages()
3665b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
3675b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang
368a93ce1abdc1ade0e5196eba2510d72b9529ab5fcJoseph Hwangdef _usage_and_exit():
369a93ce1abdc1ade0e5196eba2510d72b9529ab5fcJoseph Hwang    """Print the usage message and exit."""
370e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    prog = sys.argv[0]
371e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    print 'Usage: $ python %s [options]\n' % prog
372e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    print 'options:'
373e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    print '  -D, --%s' % OPTIONS.DEBUG
374e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    print '        enable debug flag'
375039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang    print '  -d, --%s <directory>' % OPTIONS.DIR
376e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    print '        specify which log directory to derive the summary'
377e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    print '  -h, --%s' % OPTIONS.HELP
378e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    print '        show this help'
379c9cdc9527e1087addd1e21cf58608fd75173df5aJoseph Hwang    print '  -i, --%s' % OPTIONS.INDIVIDUAL
380c9cdc9527e1087addd1e21cf58608fd75173df5aJoseph Hwang    print '        Calculate statistics of every individual round separately'
381039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang    print '  -m, --%s <verbose_level>' % OPTIONS.METRICS
3827dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang    print '        display the summary metrics.'
383039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang    print '        verbose_level:'
3841551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    print '          0: hide some metrics statistics if they passed'
3851551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    print '          1: display all metrics statistics'
3861551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    print '          2: display all metrics statistics and ' \
3871551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang                        'the detailed raw metrics values (default)'
3881551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    print '  -s, --%s' % OPTIONS.SCORES
3891551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    print '        display the scores (0.0 ~ 1.0)'
390e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    print
391e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    print 'Examples:'
3927dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang    print '    Specify the log root directory.'
393e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    print '    $ python %s -d /tmp' % prog
3941551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    print '    Hide some metrics statistics.'
3951551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    print '    $ python %s -m 0' % prog
3967dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang    print '    Display all metrics statistics.'
3971551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    print '    $ python %s -m 1' % prog
3981551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    print '    Display all metrics statistics with detailed raw metrics values.'
3991551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    print '    $ python %s         # or' % prog
4001551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang    print '    $ python %s -m 2' % prog
401039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang    sys.exit(1)
402a93ce1abdc1ade0e5196eba2510d72b9529ab5fcJoseph Hwang
403a93ce1abdc1ade0e5196eba2510d72b9529ab5fcJoseph Hwang
404e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwangdef _parsing_error(msg):
405e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    """Print the usage and exit when encountering parsing error."""
406e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    print 'Error: %s' % msg
407e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    _usage_and_exit()
408e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang
409e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang
410e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwangdef _parse_options():
411e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    """Parse the options."""
412e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    # Set the default values of options.
413e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    options = {OPTIONS.DEBUG: False,
414e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang               OPTIONS.DIR: log_root_dir,
415c9cdc9527e1087addd1e21cf58608fd75173df5aJoseph Hwang               OPTIONS.INDIVIDUAL: False,
4161551829cde6f35f97c603c5a575c9d31e96f1208Joseph Hwang               OPTIONS.METRICS: OptionsDisplayMetrics(None),
417b0773e1ff6a735d964b563d494d7a06d19a873baJoseph Hwang               OPTIONS.SCORES: False,
418e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    }
419e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang
420e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    try:
421b0773e1ff6a735d964b563d494d7a06d19a873baJoseph Hwang        short_opt = 'Dd:him:s'
422e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang        long_opt = [OPTIONS.DEBUG,
423e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang                    OPTIONS.DIR + '=',
424e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang                    OPTIONS.HELP,
425c9cdc9527e1087addd1e21cf58608fd75173df5aJoseph Hwang                    OPTIONS.INDIVIDUAL,
426039967354df47f89616776832ec2a9dd9fea9efbJoseph Hwang                    OPTIONS.METRICS + '=',
427b0773e1ff6a735d964b563d494d7a06d19a873baJoseph Hwang                    OPTIONS.SCORES,
428e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang        ]
429e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang        opts, args = getopt.getopt(sys.argv[1:], short_opt, long_opt)
430e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    except getopt.GetoptError, err:
431e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang        _parsing_error(str(err))
432e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang
433e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    for opt, arg in opts:
434e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang        if opt in ('-h', '--%s' % OPTIONS.HELP):
435a93ce1abdc1ade0e5196eba2510d72b9529ab5fcJoseph Hwang            _usage_and_exit()
436e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang        elif opt in ('-D', '--%s' % OPTIONS.DEBUG):
437e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang            options[OPTIONS.DEBUG] = True
438e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang        elif opt in ('-d', '--%s' % OPTIONS.DIR):
439e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang            options[OPTIONS.DIR] = arg
440e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang            if not os.path.isdir(arg):
441e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang                print 'Error: the log directory %s does not exist.' % arg
442e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang                _usage_and_exit()
443c9cdc9527e1087addd1e21cf58608fd75173df5aJoseph Hwang        elif opt in ('-i', '--%s' % OPTIONS.INDIVIDUAL):
444c9cdc9527e1087addd1e21cf58608fd75173df5aJoseph Hwang            options[OPTIONS.INDIVIDUAL] = True
445e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang        elif opt in ('-m', '--%s' % OPTIONS.METRICS):
4467dbae7827dae0767bffe303708e19483b80a007eJoseph Hwang            options[OPTIONS.METRICS] = OptionsDisplayMetrics(arg)
447b0773e1ff6a735d964b563d494d7a06d19a873baJoseph Hwang        elif opt in ('-s', '--%s' % OPTIONS.SCORES):
448b0773e1ff6a735d964b563d494d7a06d19a873baJoseph Hwang            options[OPTIONS.SCORES] = True
449e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang        else:
450e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang            msg = 'This option "%s" is not supported.' % opt
451e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang            _parsing_error(opt)
452a93ce1abdc1ade0e5196eba2510d72b9529ab5fcJoseph Hwang
453e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    return options
454e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang
455e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang
456e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwangif __name__ == '__main__':
457e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    options = _parse_options()
458e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang    summary = FirmwareSummary(options[OPTIONS.DIR],
459313de5edc48d6af3b8891e69114ddf7d79c8516cJoseph Hwang                              display_metrics=options[OPTIONS.METRICS],
460c9cdc9527e1087addd1e21cf58608fd75173df5aJoseph Hwang                              individual_round_flag=options[OPTIONS.INDIVIDUAL],
461b0773e1ff6a735d964b563d494d7a06d19a873baJoseph Hwang                              display_scores=options[OPTIONS.SCORES],
462e9c6a255171607e0467d9025b2a2ed92eb03c87aJoseph Hwang                              debug_flag=options[OPTIONS.DEBUG])
4635b6a306f752ee6c8e081713d20e13f7ce11db684Joseph Hwang    summary.print_result_summary()
464