From f98eda52a1d1b25d02c4b6fe8bb6bfa9e55fdf73 Mon Sep 17 00:00:00 2001 From: Jaden Diefenbaugh <blakcap@users.noreply.github.com> Date: Thu, 2 Mar 2017 11:27:12 +0100 Subject: [PATCH] add experimentsService to handle experiment data --- .../app/controllers/reportController.js | 7 +- .../app/services/experimentsService.js | 183 ++++++++++++++++++ 2 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 beat/web/reports/static/reports/app/services/experimentsService.js diff --git a/beat/web/reports/static/reports/app/controllers/reportController.js b/beat/web/reports/static/reports/app/controllers/reportController.js index 1187c3c6d..d3fcede13 100644 --- a/beat/web/reports/static/reports/app/controllers/reportController.js +++ b/beat/web/reports/static/reports/app/controllers/reportController.js @@ -21,7 +21,7 @@ */ //This controller retrieves data from the reportFactory/experimentFactory through the REST API and associates it with the $scope //The $scope is ultimately bound to the report view -angular.module('reportApp').controller('reportController',['$scope', 'reportFactory', 'experimentFactory', 'plotterFactory', 'dataFactory', '$q', 'GroupsService', function ($scope, reportFactory, experimentFactory, plotterFactory, dataFactory, $q, GroupsService){ +angular.module('reportApp').controller('reportController',['$scope', 'reportFactory', 'experimentFactory', 'plotterFactory', 'dataFactory', '$q', 'GroupsService', 'ExperimentsService', function ($scope, reportFactory, experimentFactory, plotterFactory, dataFactory, $q, GroupsService, ExperimentsService){ $scope.q = $q; $scope.user; $scope.report_id; @@ -148,6 +148,7 @@ angular.module('reportApp').controller('reportController',['$scope', 'reportFact } function getExperimentDataReportNumber(report_number){ + ExperimentsService.loadExperiments($scope.url_prefix, report_number); experimentFactory.getAllExperimentResults($scope.url_prefix, report_number) .then(function (experiments){ mutateSave($scope.report_experiments, experiments); @@ -192,6 +193,7 @@ angular.module('reportApp').controller('reportController',['$scope', 'reportFact } function getExperimentDataForAuthor(all_experiments){ + ExperimentsService.loadExperiments($scope.user, $scope.report_id, $scope.url_prefix); experimentFactory.getAllExperimentResultsForAuthor($scope.user, $scope.report_id, $scope.url_prefix) .then(function (experiments){ mutateSave($scope.report_experiments, experiments); @@ -266,6 +268,7 @@ angular.module('reportApp').controller('reportController',['$scope', 'reportFact plotterFactory.getPlotters($scope.url_prefix) .success(function (plottersData){ $scope.report.plotters = plottersData; + console.log(plottersData); getPlotterParameterData(); }) .error(function (error){ @@ -277,6 +280,7 @@ angular.module('reportApp').controller('reportController',['$scope', 'reportFact plotterFactory.getDefaultPlotters($scope.url_prefix) .success(function (defaultPlottersData){ $scope.report.defaultplotters = defaultPlottersData; + console.log(defaultPlottersData); checkContent(); }) .error(function (error){ @@ -288,6 +292,7 @@ angular.module('reportApp').controller('reportController',['$scope', 'reportFact plotterFactory.getPlotterParameter($scope.url_prefix) .success(function (plotterParameterData){ $scope.report.plotterparameter = plotterParameterData; + console.log(plotterParameterData); //$scope.report.plotterparameter.push({"name":"Default"}); getDefaultPlotters(); }) diff --git a/beat/web/reports/static/reports/app/services/experimentsService.js b/beat/web/reports/static/reports/app/services/experimentsService.js new file mode 100644 index 000000000..8b2bf785e --- /dev/null +++ b/beat/web/reports/static/reports/app/services/experimentsService.js @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ + * Contact: beat.support@idiap.ch + * + * This file is part of the beat.web module of the BEAT platform. + * + * Commercial License Usage + * Licensees holding valid commercial BEAT licenses may use this file in + * accordance with the terms contained in a written agreement between you + * and Idiap. For further information contact tto@idiap.ch + * + * Alternatively, this file may be used under the terms of the GNU Affero + * Public License version 3 as published by the Free Software and appearing + * in the file LICENSE.AGPL included in the packaging of this file. + * The BEAT platform is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero Public License along + * with the BEAT platform. If not, see http://www.gnu.org/licenses/. + */ + +/* + * ExperimentsService + * Desc: + * Manages the experiments data, including storing it and generating + * different views of the data + */ +angular.module('reportApp').factory('ExperimentsService', ['experimentFactory', 'GroupsService', function(experimentFactory, GroupsService){ + // holds the raw exp data received from the server + const expData = {}; + // holds the view generated from `getTableablesFromExpName` + const tableData = {}; + // holds the view generated from `getPlottablesFromExpName` + const plotData = {}; + + // lots of experiments have fields that are differently-named + // but mean the same thing. + // These fields are the *only* available field in the obj. + const getVarProp = (obj, dontLogErrors) => { + let keys = Object.keys(obj); + if(keys.length !== 1 && !dontLogErrors){ + console.warn(`Found bad obj for getVarProp:`); + console.log(obj); + } + + return obj[keys[0]]; + }; + + // analyzer + const getAnalyzerFromExpName = (expName) => getVarProp(expData[expName].declaration.analyzers, true).algorithm; + + // get all possible objects that could be shown in a table + const getTableablesFromExpName = (expName) => { + let currExp = expData[expName]; + + console.log(currExp); + // get all result objs that have a type that doesnt start with 'plot/' + // these results can be displayed in a table + let results = Object.entries(getVarProp(currExp.results)) + // type not starting with plot + .filter(([res_name, obj]) => !obj.type.startsWith('plot/')) + // after we've filtered fields, make it into an obj + .map(([res_name, obj]) => { return {[res_name]: obj}; }) + // concat objs via reduce + .reduce((o, curr) => Object.assign(o, curr), {}) + ; + + // get block parameters + let blockVars = Object.entries(currExp.declaration.blocks) + // only look at blocks with parameters + .filter(([blockName, block]) => block.parameters) + // loop through each block + .map(([blockName, block]) => { + // flatten the block's execution infos + return Object.entries(block.parameters) + .map(([fieldName, field]) => { + return { [`${blockName}.${fieldName}`]: field }; + }) + .reduce((o, fieldObj) => Object.assign(o, fieldObj), {}) + ; + }) + // flatten the exp's blocks' params + .reduce((o, blockObj) => Object.assign(o, blockObj), {}) + ; + + // get global experiment variables + let globalVars = Object.entries(currExp.declaration.globals) + // properties that have a '/' in the name + .filter(([name, obj]) => name.includes('/')) + .map(([algName, alg]) => { + // flatten the alg's fields + return Object.entries(alg) + .map(([fieldName, field]) => { + return { [`${algName}.${fieldName}`]: field }; + }) + .reduce((o, fieldObj) => Object.assign(o, fieldObj), {}) + ; + }) + // flatten the exp's algs' fields + .reduce((o, algObj) => Object.assign(o, algObj), {}) + ; + + // get block timing infos + let blockTiming = Object.entries(currExp.execution_info) + // loop through each block + .map(([blockName, block]) => { + // flatten the block's execution infos + return Object.entries(block) + .map(([fieldName, field]) => { + return { [`${blockName}.${fieldName}`]: field }; + }) + .reduce((o, fieldObj) => Object.assign(o, fieldObj), {}) + ; + }) + // flatten the exp's execution infos + .reduce((o, blockObj) => Object.assign(o, blockObj), {}) + ; + + // get total timing info + let expTiming = { + 'total_execution_time': Object.entries(blockTiming) + .filter(([name, val]) => name.includes('linear_execution_time')) + .map(([name, val]) => val) + .reduce((n, v) => n + v, 0) + }; + + // concat all objs + let allObj = Object.assign({}, + results, + globalVars, + blockVars, + blockTiming, + expTiming + ); + + return allObj; + }; + + // get all result objs that have a type that starts with 'plot/' + // these results can be displayed in a plot + const getPlottablesFromExpName = (expName) => { + return Object.entries(getVarProp(expData[expName].results)) + .filter(([res_name, obj]) => obj.type.startsWith('plot/')) + .map(([res_name, obj]) => obj); + }; + + const loadExperiments = (...args) => { + let expFetch; + if(args.length === 2){ + // 2 args -> get exps by report num + expFetch = experimentFactory.getAllExperimentResults(...args); + + } else if (args.length === 3){ + // 3 args -> by report author + expFetch = experimentFactory.getAllExperimentResultsForAuthor(...args); + } + + return expFetch + .then((exps) => { + Object.entries(exps) + .forEach(([expName, exp]) => { + expData[expName] = exp; + tableData[expName] = getTableablesFromExpName(expName); + plotData[expName] = getPlottablesFromExpName(expName); + }); + + console.log(expData); + console.log(tableData); + console.log(plotData); + + return expData; + }); + }; + + return { + experiments: expData, + plottables: plotData, + tableables: tableData, + getAnalyzerFromExpName, + loadExperiments + }; +}]); -- GitLab