Skip to content

Commit

Permalink
MDL-64779 tool_analytics: Export selector
Browse files Browse the repository at this point in the history
  • Loading branch information
David Monllaó committed Apr 1, 2019
1 parent 0920f35 commit 75dfc58
Show file tree
Hide file tree
Showing 9 changed files with 166 additions and 21 deletions.
2 changes: 1 addition & 1 deletion admin/tool/analytics/amd/build/model.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 65 additions & 0 deletions admin/tool/analytics/amd/src/model.js
Expand Up @@ -149,6 +149,71 @@ define(['jquery', 'core/str', 'core/log', 'core/notification', 'core/modal_facto
return;
});

modal.show();
return modal;
}).fail(Notification.exception);
});
},

/**
* Displays export options.
*
* We have two main options: export training data and export configuration.
* The 2nd option has an extra option: include the trained algorithm weights.
*
* @param {String} actionId
* @param {Boolean} isTrained
*/
selectExportOptions: function(actionId, isTrained) {
$('[data-action-id="' + actionId + '"]').on('click', function(ev) {
ev.preventDefault();

var a = $(ev.currentTarget);

if (!isTrained) {
// Export the model configuration if the model is not trained. We can't export anything else.
a.attr('href', a.attr('href') + '&action=exportmodel&includeweights=0');
window.location.href = a.attr('href');
return;
}

var stringsPromise = Str.get_strings([
{
key: 'export',
component: 'tool_analytics'
}
]);
var modalPromise = ModalFactory.create({type: ModalFactory.types.SAVE_CANCEL});
var bodyPromise = Templates.render('tool_analytics/export_options', {});

$.when(stringsPromise, modalPromise).then(function(strings, modal) {

modal.getRoot().on(ModalEvents.hidden, modal.destroy.bind(modal));

modal.setTitle(strings[0]);
modal.setSaveButtonText(strings[0]);
modal.setBody(bodyPromise);

modal.getRoot().on(ModalEvents.save, function() {

var exportOption = $("input[name='exportoption']:checked").val();

if (exportOption == 'exportdata') {
a.attr('href', a.attr('href') + '&action=exportdata');

} else {
a.attr('href', a.attr('href') + '&action=exportmodel');
if ($("#id-includeweights").is(':checked')) {
a.attr('href', a.attr('href') + '&includeweights=1');
} else {
a.attr('href', a.attr('href') + '&includeweights=0');
}
}

window.location.href = a.attr('href');
return;
});

modal.show();
return modal;
}).fail(Notification.exception);
Expand Down
35 changes: 20 additions & 15 deletions admin/tool/analytics/classes/output/models_list.php
Expand Up @@ -235,22 +235,27 @@ public function export_for_template(\renderer_base $output) {
$actionsmenu->add($icon);
}

// Export training data.
if (!$model->is_static() && $model->is_trained()) {
$urlparams['action'] = 'exportdata';
$url = new \moodle_url('model.php', $urlparams);
$icon = new \action_menu_link_secondary($url, new \pix_icon('i/export',
get_string('exporttrainingdata', 'tool_analytics')), get_string('exporttrainingdata', 'tool_analytics'));
$actionsmenu->add($icon);
}
// Export.
if (!$model->is_static()) {

// Export model.
if (!$model->is_static() && $model->get_indicators() && !empty($modeldata->timesplitting)) {
$urlparams['action'] = 'exportmodel';
$url = new \moodle_url('model.php', $urlparams);
$icon = new \action_menu_link_secondary($url, new \pix_icon('i/backup',
get_string('exportmodel', 'tool_analytics')), get_string('exportmodel', 'tool_analytics'));
$actionsmenu->add($icon);
$fullysetup = $model->get_indicators() && !empty($modeldata->timesplitting);
$istrained = $model->is_trained();

if ($fullysetup || $istrained) {

$url = new \moodle_url('model.php', $urlparams);
// Clear the previous action param from the URL, we will set it in JS.
$url->remove_params('action');

$actionid = 'export-' . $model->get_id();
$PAGE->requires->js_call_amd('tool_analytics/model', 'selectExportOptions',
[$actionid, $istrained]);

$icon = new \action_menu_link_secondary($url, new \pix_icon('i/export',
get_string('export', 'tool_analytics')), get_string('export', 'tool_analytics'),
['data-action-id' => $actionid]);
$actionsmenu->add($icon);
}
}

// Invalid analysables.
Expand Down
2 changes: 2 additions & 0 deletions admin/tool/analytics/lang/en/tool_analytics.php
Expand Up @@ -66,6 +66,8 @@
$string['evaluationmodecolconfiguration'] = 'Configuration';
$string['evaluationmodeconfiguration'] = 'Evaluate the model configuration';
$string['evaluationinbatches'] = 'The site contents are calculated and stored in batches. The evaluation process may be stopped at any time. The next time it is run, it will continue from the point when it was stopped.';
$string['export'] = 'Export';
$string['exportincludeweights'] = 'Include the weights of the trained model';
$string['exportmodel'] = 'Export configuration';
$string['exporttrainingdata'] = 'Export training data';
$string['getpredictionsresultscli'] = 'Results using {$a->name} (id: {$a->id}) time-splitting method';
Expand Down
5 changes: 4 additions & 1 deletion admin/tool/analytics/model.php
Expand Up @@ -235,8 +235,11 @@
break;

case 'exportmodel':

$includeweights = optional_param('includeweights', 1, PARAM_INT);

$zipfilename = 'model-' . $model->get_unique_id() . '-' . microtime(false) . '.zip';
$zipfilepath = $model->export_model($zipfilename);
$zipfilepath = $model->export_model($zipfilename, $includeweights);
send_temp_file($zipfilepath, $zipfilename);
break;

Expand Down
57 changes: 57 additions & 0 deletions admin/tool/analytics/templates/export_options.mustache
@@ -0,0 +1,57 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template tool_analytics/export_options
Export options.
The purpose of this template is to render the exporting options.
Classes required for JS:
* none
Data attributes required for JS:
* none
Example context (json):
{
}
}}
<div class="form-check">
<input class="form-check-input" type="radio" name="exportoption" id="id-mode-exportdata" value="exportdata">
<label class="form-check-label" for="id-mode-exportdata">{{#str}} exporttrainingdata, tool_analytics {{/str}}</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="exportoption" id="id-mode-exportmodel" value="exportmodel" checked>
<label class="form-check-label" for="id-mode-exportmodel">{{#str}} exportmodel, tool_analytics {{/str}}</label>
</div>
<div class="form-check m-l-2" id="id-includeweights-container">
<input class="form-check-input" type="checkbox" id="id-includeweights" value="1" checked>
<label class="form-check-label" for="id-includeweights">{{#str}} exportincludeweights, tool_analytics {{/str}}</label>
</div>

{{#js}}
require(['jquery'], function($) {
$("input[name='exportoption']:radio").change(function() {
if ($(this).val() == 'exportdata') {
$('#id-includeweights-container').hide();
} else {
$('#id-includeweights-container').show();
}
});
});
{{/js}}
5 changes: 3 additions & 2 deletions analytics/classes/model.php
Expand Up @@ -1408,14 +1408,15 @@ public function export() {
* Exports the model data to a zip file.
*
* @param string $zipfilename
* @param bool $includeweights Include the model weights if available
* @return string Zip file path
*/
public function export_model(string $zipfilename) : string {
public function export_model(string $zipfilename, bool $includeweights = true) : string {

\core_analytics\manager::check_can_manage_models();

$modelconfig = new model_config($this);
return $modelconfig->export($zipfilename);
return $modelconfig->export($zipfilename, $includeweights);
}

/**
Expand Down
5 changes: 3 additions & 2 deletions analytics/classes/model_config.php
Expand Up @@ -58,9 +58,10 @@ public function __construct(?model $model = null) {
* Exports a model to a zip using the provided file name.
*
* @param string $zipfilename
* @param bool $includeweights Include the model weights if available
* @return string
*/
public function export(string $zipfilename) : string {
public function export(string $zipfilename, bool $includeweights = true) : string {

if (!$this->model) {
throw new \coding_exception('No model object provided.');
Expand All @@ -84,7 +85,7 @@ public function export(string $zipfilename) : string {
$zipfiles[self::CONFIG_FILE_NAME] = $jsonfilepath;

// ML backend.
if ($this->model->is_trained()) {
if ($includeweights && $this->model->is_trained()) {
$processor = $this->model->get_predictions_processor(true);
$outputdir = $this->model->get_output_dir(array('execution'));
$mlbackenddir = $processor->export($this->model->get_unique_id(), $outputdir);
Expand Down
11 changes: 11 additions & 0 deletions analytics/tests/prediction_test.php
Expand Up @@ -305,6 +305,10 @@ public function test_ml_export_import($predictionsprocessorclass) {
$zipfilename = 'model-zip-' . microtime() . '.zip';
$zipfilepath = $model->export_model($zipfilename);

$modelconfig = new \core_analytics\model_config();
list($modelconfig, $mlbackend) = $modelconfig->extract_import_contents($zipfilepath);
$this->assertNotFalse($mlbackend);

$importmodel = \core_analytics\model::import_model($zipfilepath);
$importmodel->enable();

Expand All @@ -317,6 +321,13 @@ public function test_ml_export_import($predictionsprocessorclass) {

$this->assertFalse($importmodel->trained_locally());

$zipfilename = 'model-zip-' . microtime() . '.zip';
$zipfilepath = $model->export_model($zipfilename, false);

$modelconfig = new \core_analytics\model_config();
list($modelconfig, $mlbackend) = $modelconfig->extract_import_contents($zipfilepath);
$this->assertFalse($mlbackend);

set_config('enabled_stores', '', 'tool_log');
get_log_manager(true);
}
Expand Down

0 comments on commit 75dfc58

Please sign in to comment.