├── .gitignore ├── LICENSE └── analyzer.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | *.pyc 10 | 11 | # Packages # 12 | ############ 13 | # it's better to unpack these files and commit the raw source 14 | # git has its own built in compression methods 15 | *.7z 16 | *.dmg 17 | *.gz 18 | *.iso 19 | *.rar 20 | #*.tar 21 | *.zip 22 | 23 | # Logs and databases # 24 | ###################### 25 | *.log 26 | *.sqlite 27 | *.xml 28 | _windows/ 29 | 30 | # OS generated files # 31 | ###################### 32 | .DS_Store 33 | ehthumbs.db 34 | Icon 35 | Thumbs.db 36 | .tmtags 37 | .idea/ 38 | mydjangosite/.idea/ 39 | tags 40 | vendor.tags 41 | tmtagsHistory 42 | *.sublime-project 43 | *.sublime-workspace 44 | .bundle 45 | 46 | data/ 47 | result/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Intelligent-distributed Cloud and Security Laboratory (ICNS Lab.) 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /analyzer.py: -------------------------------------------------------------------------------- 1 | # This file is part of Qualified Caching-as-a-Service. 2 | # BSD 3-Clause License 3 | # 4 | # Copyright (c) 2019, Intelligent-distributed Cloud and Security Laboratory (ICNS Lab.) 5 | # All rights reserved. 6 | # 7 | # Redistribution and use in source and binary forms, with or without 8 | # modification, are permitted provided that the following conditions are met: 9 | # 10 | # * Redistributions of source code must retain the above copyright notice, this 11 | # list of conditions and the following disclaimer. 12 | # 13 | # * Redistributions in binary form must reproduce the above copyright notice, 14 | # this list of conditions and the following disclaimer in the documentation 15 | # and/or other materials provided with the distribution. 16 | # 17 | # * Neither the name of the copyright holder nor the names of its 18 | # contributors may be used to endorse or promote products derived from 19 | # this software without specific prior written permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | # 32 | # title : analyzer.py 33 | # description : python analyzer 34 | # author : Yunkon(Alvin) Kim 35 | # date : 20190228 36 | # version : 0.1 37 | # python_version : 3.6 38 | # notes : This file is an implementation of result analyzer for EDCrammer testlog 39 | # in the Python Programming Language. 40 | # ============================================================================== 41 | import csv 42 | import glob 43 | import os 44 | 45 | import numpy as np 46 | 47 | 48 | def list_a2f_and_mean(mlist): 49 | return sum([float(i) for i in mlist], 0.0) / len(mlist) 50 | 51 | 52 | def get_xy_projection_mean(list_3d, x, y): 53 | xy_list = [float(list_3d[i][x][y]) for i in range(len(list_3d))] 54 | xy_mean = list_a2f_and_mean(xy_list) 55 | return xy_mean 56 | 57 | 58 | if __name__ == '__main__': 59 | 60 | directory = os.path.join('.', 'data') 61 | 62 | scenario_no = 1 63 | total_scenarios = 4 64 | 65 | while scenario_no <= total_scenarios: 66 | filename_format = str(scenario_no) + "-*" 67 | file_paths = glob.glob(os.path.join(directory, filename_format)) 68 | list_len = len(file_paths) 69 | 70 | i = 0 71 | 72 | # check the fewest number of lines 73 | 74 | number_of_lines = [] 75 | 76 | for filepath in file_paths: 77 | with open(filepath, 'r', newline='') as csvfile: 78 | reader = csv.reader(csvfile, delimiter=' ', quotechar='|') 79 | number_of_lines.append(sum(1 for row in reader)) 80 | 81 | csvfile.close() 82 | 83 | minimum_cycle_number = min(number_of_lines) - 2 84 | 85 | running_times = [] 86 | achieved_percentages = [] 87 | feedbacks = [] 88 | outputs = [] 89 | difference_ratios = [] 90 | variances = [] 91 | standard_deviations = [] 92 | 93 | # read csv files 94 | for filepath in file_paths: 95 | print(filepath) 96 | line_number = 1 97 | achieved_percentage = [] 98 | feedback = [] 99 | output = [] 100 | difference_ratio = [] 101 | variance = None 102 | standard_deviation = None 103 | 104 | with open(filepath, 'r', newline='') as csvfile: 105 | reader = csv.reader(csvfile, delimiter=' ', quotechar='|') 106 | for row in reader: 107 | if line_number == 1: 108 | arr = ', '.join(row).split(',') 109 | running_times.append(float(arr[2])) 110 | line_number += 1 111 | elif line_number == 2: 112 | arr = ', '.join(row).split(',') 113 | variance = float(arr[0]) 114 | standard_deviation = float(arr[1]) 115 | line_number += 1 116 | else: 117 | arr = ', '.join(row).split(',') 118 | achieved_percentage.append(float(arr[1])) 119 | feedback.append(float(arr[4])) 120 | output.append(float(arr[2])) 121 | difference_ratio.append(float(arr[5])) 122 | line_number += 1 123 | 124 | # split a list based on minimum length because number of cycles are different due to processing time. 125 | achieved_percentages.append(achieved_percentage[0:minimum_cycle_number]) 126 | feedbacks.append(feedback[0:minimum_cycle_number]) 127 | outputs.append(output[0:minimum_cycle_number]) 128 | difference_ratios.append(difference_ratio[0:minimum_cycle_number]) 129 | variances.append(variance) 130 | standard_deviations.append(standard_deviation) 131 | csvfile.close() 132 | 133 | # Start analyzing 134 | # --------- Running time 135 | print("running_times: \n%s" % running_times) 136 | avg_running_times = sum(running_times) / len(running_times) 137 | print("Average Running Time: %s " % avg_running_times) 138 | 139 | # --------- Variance and standard deviation 140 | print("variances: \n%s" % variances) 141 | avg_variance = sum(variances) / len(variances) 142 | print("Average variances: %s " % avg_variance) 143 | 144 | print("standard_deviations: \n%s" % standard_deviations) 145 | avg_standard_deviation = sum(standard_deviations) / len(standard_deviations) 146 | print("Average standard deviation: %s " % avg_standard_deviation) 147 | 148 | # --------- Achieved percentages 149 | print("Length of achieved_percentages: %s" % len(achieved_percentages)) 150 | print("achieved_percentages: \n%s" % achieved_percentages) 151 | 152 | # !IMPORTANCE, np.transpose does NOT work on for a jagged list of different lengths. 153 | transposed_ap = np.transpose(achieved_percentages) 154 | print("Length of transposed: %s" % len(transposed_ap)) 155 | print("Transposed: \n%s" % transposed_ap) 156 | 157 | avg_achieved_percentages = [] 158 | 159 | for values in transposed_ap: 160 | avg_achieved_percentages.append(sum(values) / len(values)) 161 | 162 | print("Length of avg_achieved_percentages: %s" % len(avg_achieved_percentages)) 163 | print("Average Achieved Percentages: \n%s" % avg_achieved_percentages) 164 | 165 | # --------- Feedbacks 166 | print("Length of feedbacks: %s" % len(feedbacks)) 167 | print("feedbacks: \n%s" % feedbacks) 168 | 169 | # !IMPORTANCE, np.transpose does NOT work on for a jagged list of different lengths. 170 | transposed_f = np.transpose(feedbacks) 171 | print("Length of transposed: %s" % len(transposed_f)) 172 | print("Transposed: \n%s" % transposed_f) 173 | 174 | avg_feedbacks = [] 175 | 176 | for values in transposed_f: 177 | avg_feedbacks.append(sum(values) / len(values)) 178 | 179 | print("Length of avg_achieved_percentages: %s" % len(avg_feedbacks)) 180 | print("Average Achieved Percentages: \n%s" % avg_feedbacks) 181 | 182 | # --------- Outputs 183 | print("Length of outputs: %s" % len(outputs)) 184 | print("Outputs: \n%s" % outputs) 185 | 186 | # !IMPORTANCE, np.transpose does NOT work on for a jagged list of different lengths. 187 | transposed_f = np.transpose(outputs) 188 | print("Length of transposed: %s" % len(transposed_f)) 189 | print("Transposed: \n%s" % transposed_f) 190 | 191 | avg_outputs = [] 192 | 193 | for values in transposed_f: 194 | avg_outputs.append(sum(values) / len(values)) 195 | 196 | print("Length of avg_achieved_percentages: %s" % len(avg_outputs)) 197 | print("Average Achieved Percentages: \n%s" % avg_outputs) 198 | 199 | # --------- difference_ratios 200 | print("Length of difference_ratios: %s" % len(difference_ratios)) 201 | print("difference_ratios: \n%s" % difference_ratios) 202 | 203 | # !IMPORTANCE, np.transpose does NOT work on for a jagged list of different lengths. 204 | transposed_dr = np.transpose(difference_ratios) 205 | print("Length of transposed: %s" % len(transposed_dr)) 206 | print("Transposed: \n%s" % transposed_dr) 207 | 208 | avg_difference_ratios = [] 209 | 210 | for values in transposed_dr: 211 | avg_difference_ratios.append(sum(values) / len(values)) 212 | 213 | print("Length of avg_achieved_percentages: %s" % len(avg_difference_ratios)) 214 | print("Average Achieved Percentages: \n%s" % avg_difference_ratios) 215 | 216 | result_file_name = str(scenario_no) + "-result.csv" 217 | result_path = os.path.join(os.path.join(".", "result"), result_file_name) 218 | print(result_path) 219 | 220 | time_list = [i for i in range(minimum_cycle_number)] 221 | percentage_setpoint_list = [90 for i in range(minimum_cycle_number)] 222 | 223 | with open(result_path, 'w', newline='') as csvfile: 224 | writer = csv.writer(csvfile, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL) 225 | # print running time 226 | 227 | # print data 228 | for idx in range(minimum_cycle_number): 229 | writer.writerow( 230 | [time_list[idx], avg_achieved_percentages[idx], (avg_outputs[idx] / (5 << 20) * 100), 231 | percentage_setpoint_list[idx], avg_feedbacks[idx], avg_difference_ratios[idx]]) 232 | 233 | writer.writerow([avg_running_times, minimum_cycle_number, avg_running_times/minimum_cycle_number]) 234 | writer.writerow([avg_variance]) 235 | writer.writerow([avg_standard_deviation]) 236 | 237 | csvfile.close() 238 | 239 | # # ################ plot plot plot plot plot 240 | # time_sm = np.array(time_list) 241 | # time_smooth = np.linspace(time_sm.min(), time_sm.max(), 300) 242 | # 243 | # # feedback_smooth = spline(time_list, percentage_list, time_smooth) 244 | # # Using make_interp_spline to create BSpline 245 | # helper_x3 = make_interp_spline(time_list, avg_achieved_percentages) 246 | # feedback_smooth = helper_x3(time_smooth) 247 | # 248 | # plt.plot(time_smooth, feedback_smooth) 249 | # plt.plot(time_list, percentage_setpoint_list) 250 | # 251 | # plt.xlim((0, len(percentage_setpoint_list))) 252 | # # plt.ylim((min(percentage_list) - 0.5, max(percentage_list) + 0.5)) 253 | # # plt.ylim(0, 100) 254 | # plt.xlabel('time (s)') 255 | # plt.ylabel('PID (PV)') 256 | # plt.title('TEST PID') 257 | # 258 | # # plt.ylim((1 - 0.5, 1 + 0.5)) 259 | # 260 | # plt.grid(True) 261 | # plt.show() 262 | 263 | # variation_list = [book[i][1][4] for i in range(len(book))] 264 | 265 | # read files of each scenario 266 | 267 | # open file 268 | 269 | # add running time 270 | 271 | # calc average of each cycle 272 | 273 | # calc gap of setpoint and c(t) 274 | 275 | # calc average of all cycle 276 | 277 | scenario_no += 1 278 | 279 | # loop 280 | # while scenario_no < 5: 281 | # filename_format = str(scenario_no) + "-*" 282 | # file_paths = glob.glob(os.path.join(directory, filename_format)) 283 | # list_len = len(file_paths) 284 | # 285 | # i = 0 286 | # book = [] 287 | # 288 | # # read csv files 289 | # for filepath in file_paths: 290 | # print(filepath) 291 | # with open(filepath, 'r', newline='') as csvfile: 292 | # reader = csv.reader(csvfile, delimiter=' ', quotechar='|') 293 | # page = [] 294 | # for row in reader: 295 | # arr = ', '.join(row).split(',') 296 | # page.append(arr) 297 | # book.append(page) 298 | # 299 | # print(book) 300 | # print(book[0]) 301 | # print(book[1]) 302 | # print(book[0][0]) 303 | # print(book[0][0][2]) 304 | # 305 | # print("--- testing ---") 306 | # running_time_mean = get_xy_projection_mean(book, 0, 2) 307 | # print(running_time_mean) 308 | # 309 | # print("Length: %s " % len(book[0])) 310 | # avg_percentage_list = [float(get_xy_projection_mean(book, i, 1)) for i in range(1, len(book[0])-1)] 311 | # 312 | # time_list = [i for i in range(73)] 313 | # percentage_setpoint_list = [90 for i in range(73)] 314 | # 315 | # 316 | # # ################ plot plot plot plot plot 317 | # time_sm = np.array(time_list) 318 | # time_smooth = np.linspace(time_sm.min(), time_sm.max(), 300) 319 | # 320 | # # feedback_smooth = spline(time_list, percentage_list, time_smooth) 321 | # # Using make_interp_spline to create BSpline 322 | # helper_x3 = make_interp_spline(time_list, avg_percentage_list) 323 | # feedback_smooth = helper_x3(time_smooth) 324 | # 325 | # plt.plot(time_smooth, feedback_smooth) 326 | # plt.plot(time_list, percentage_setpoint_list) 327 | # 328 | # plt.xlim((0, len(percentage_setpoint_list))) 329 | # # plt.ylim((min(percentage_list) - 0.5, max(percentage_list) + 0.5)) 330 | # # plt.ylim(0, 100) 331 | # plt.xlabel('time (s)') 332 | # plt.ylabel('PID (PV)') 333 | # plt.title('TEST PID') 334 | # 335 | # # plt.ylim((1 - 0.5, 1 + 0.5)) 336 | # 337 | # plt.grid(True) 338 | # plt.show() 339 | # 340 | # # variation_list = [book[i][1][4] for i in range(len(book))] 341 | # 342 | # break 343 | # # read files of each scenario 344 | # 345 | # # open file 346 | # 347 | # # add running time 348 | # 349 | # # calc average of each cycle 350 | # 351 | # # calc gap of setpoint and c(t) 352 | # 353 | # # calc average of all cycle 354 | # 355 | # scenario_no += 1 356 | 357 | --------------------------------------------------------------------------------