1 /*
2  * Copyright (c) 2017 Google Inc. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you
5  * may not use this file except in compliance with the License. You may
6  * obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13  * implied. See the License for the specific language governing
14  * permissions and limitations under the License.
15  */
16 
17 package com.android.vts.util;
18 
19 import com.android.vts.entity.ProfilingPointRunEntity;
20 import com.android.vts.proto.VtsReportMessage;
21 import com.google.gson.Gson;
22 import com.google.gson.JsonObject;
23 import java.util.ArrayList;
24 import java.util.Comparator;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 
31 /** Helper object for describing time-series box plot data. */
32 public class BoxPlot extends Graph {
33     private static final String LABEL_KEY = "label";
34     private static final String SERIES_KEY = "seriesList";
35     private static final String MEAN_KEY = "mean";
36     private static final String STD_KEY = "std";
37     private static final String COUNT_KEY = "count";
38 
39     private static final String DAY = "Day";
40 
41     private final GraphType type = GraphType.BOX_PLOT;
42     private final String name;
43     private final String xLabel;
44     private final String yLabel;
45     private final Map<String, Map<String, StatSummary>> labelSeriesMap;
46     private final Set<String> seriesSet;
47 
48     private int count;
49     private List<String> labels;
50 
BoxPlot(String name, String xLabel, String yLabel)51     public BoxPlot(String name, String xLabel, String yLabel) {
52         this.name = name;
53         this.xLabel = xLabel == null ? DAY : xLabel;
54         this.yLabel = yLabel;
55         this.count = 0;
56         this.labelSeriesMap = new HashMap<>();
57         this.seriesSet = new HashSet<>();
58         this.labels = new ArrayList<>();
59     }
60 
61     /**
62      * Get the x axis label.
63      *
64      * @return The x axis label.
65      */
66     @Override
getXLabel()67     public String getXLabel() {
68         return xLabel;
69     }
70 
71     /**
72      * Get the graph type.
73      *
74      * @return The graph type.
75      */
76     @Override
getType()77     public GraphType getType() {
78         return type;
79     }
80 
81     /**
82      * Get the name of the graph.
83      *
84      * @return The name of the graph.
85      */
86     @Override
getName()87     public String getName() {
88         return name;
89     }
90 
91     /**
92      * Get the y axis label.
93      *
94      * @return The y axis label.
95      */
96     @Override
getYLabel()97     public String getYLabel() {
98         return yLabel;
99     }
100 
101     /**
102      * Get the number of data points stored in the graph.
103      *
104      * @return The number of data points stored in the graph.
105      */
106     @Override
size()107     public int size() {
108         return this.count;
109     }
110 
111     /**
112      * Add data to the graph.
113      *
114      * @param label The name of the category.
115      * @param profilingPoint The ProfilingPointRunEntity containing data to add.
116      */
117     @Override
addData(String label, ProfilingPointRunEntity profilingPoint)118     public void addData(String label, ProfilingPointRunEntity profilingPoint) {
119         StatSummary stat =
120                 new StatSummary(
121                         label, VtsReportMessage.VtsProfilingRegressionMode.UNKNOWN_REGRESSION_MODE);
122         for (long value : profilingPoint.getValues()) {
123             stat.updateStats(value);
124         }
125         addSeriesData(label, "", stat);
126     }
127 
addSeriesData(String label, String series, StatSummary stats)128     public void addSeriesData(String label, String series, StatSummary stats) {
129         if (!labelSeriesMap.containsKey(label)) {
130             labelSeriesMap.put(label, new HashMap<>());
131         }
132         Map<String, StatSummary> seriesMap = labelSeriesMap.get(label);
133         seriesMap.put(series, stats);
134         seriesSet.add(series);
135         count += stats.getCount();
136     }
137 
setLabels(List<String> labels)138     public void setLabels(List<String> labels) {
139         this.labels = labels;
140     }
141 
142     /**
143      * Serializes the graph to json format.
144      *
145      * @return A JsonElement object representing the graph object.
146      */
147     @Override
toJson()148     public JsonObject toJson() {
149         JsonObject json = super.toJson();
150         List<JsonObject> stats = new ArrayList<>();
151         List<String> seriesList = new ArrayList<>(seriesSet);
152         seriesList.sort(Comparator.naturalOrder());
153         for (String label : labels) {
154             JsonObject statJson = new JsonObject();
155             String boxLabel = label;
156             List<JsonObject> statList = new ArrayList<>(seriesList.size());
157             Map<String, StatSummary> seriesMap = labelSeriesMap.get(label);
158             for (String series : seriesList) {
159                 JsonObject statSummary = new JsonObject();
160                 Double mean = null;
161                 Double std = null;
162                 Integer count = null;
163                 if (seriesMap.containsKey(series) && seriesMap.get(series).getCount() > 0) {
164                     StatSummary stat = seriesMap.get(series);
165                     mean = stat.getMean();
166                     std = 0.;
167                     if (stat.getCount() > 1) {
168                         std = stat.getStd();
169                     }
170                     count = stat.getCount();
171                 }
172                 statSummary.addProperty(MEAN_KEY, mean);
173                 statSummary.addProperty(STD_KEY, std);
174                 statSummary.addProperty(COUNT_KEY, count);
175                 statList.add(statSummary);
176             }
177             statJson.addProperty(LABEL_KEY, boxLabel);
178             statJson.add(VALUE_KEY, new Gson().toJsonTree(statList));
179             stats.add(statJson);
180         }
181         json.add(VALUE_KEY, new Gson().toJsonTree(stats));
182         json.add(SERIES_KEY, new Gson().toJsonTree(seriesList));
183         return json;
184     }
185 }
186