MDL-37810 roles: added manager case to test_get_user_roles_in_course()
[moodle.git] / lib / mlbackend / python / classes / processor.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * Python predictions processor
19  *
20  * @package   mlbackend_python
21  * @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
22  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 namespace mlbackend_python;
27 defined('MOODLE_INTERNAL') || die();
29 /**
30  * Python predictions processor.
31  *
32  * @package   mlbackend_python
33  * @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
34  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35  */
36 class processor implements  \core_analytics\classifier, \core_analytics\regressor {
38     /**
39      * The required version of the python package that performs all calculations.
40      */
41     const REQUIRED_PIP_PACKAGE_VERSION = '0.0.2';
43     /**
44      * Is the plugin ready to be used?.
45      *
46      * @return bool
47      */
48     public function is_ready() {
50         // Check the installed pip package version.
51         $cmd = 'python -m moodlemlbackend.version';
53         $output = null;
54         $exitcode = null;
55         // Execute it sending the standard error to $output.
56         $result = exec($cmd . ' 2>&1', $output, $exitcode);
58         if ($result === self::REQUIRED_PIP_PACKAGE_VERSION) {
59             return true;
60         }
62         if ($exitcode != 0) {
63             return get_string('pythonpackagenotinstalled', 'mlbackend_python', $cmd);
64         }
66         if ($result) {
67             $a = (object)array('installed' => $result, 'required' => self::REQUIRED_PIP_PACKAGE_VERSION);
68             return get_string('packageinstalledshouldbe', 'mlbackend_python', $a);
69         }
71         return get_string('pythonpackagenotinstalled', 'mlbackend_python', $cmd);
72     }
74     /**
75      * Trains a machine learning algorithm with the provided dataset.
76      *
77      * @param string $uniqueid
78      * @param \stored_file $dataset
79      * @param string $outputdir
80      * @return \stdClass
81      */
82     public function train_classification($uniqueid, \stored_file $dataset, $outputdir) {
84         // Obtain the physical route to the file.
85         $datasetpath = $this->get_file_path($dataset);
87         $cmd = 'python -m moodlemlbackend.training ' .
88             escapeshellarg($uniqueid) . ' ' .
89             escapeshellarg($outputdir) . ' ' .
90             escapeshellarg($datasetpath);
92         if (!PHPUNIT_TEST && CLI_SCRIPT) {
93             debugging($cmd, DEBUG_DEVELOPER);
94         }
96         $output = null;
97         $exitcode = null;
98         $result = exec($cmd, $output, $exitcode);
100         if (!$result) {
101             throw new \moodle_exception('errornopredictresults', 'analytics');
102         }
104         if (!$resultobj = json_decode($result)) {
105             throw new \moodle_exception('errorpredictwrongformat', 'analytics', '', json_last_error_msg());
106         }
108         if ($exitcode != 0) {
109             throw new \moodle_exception('errorpredictionsprocessor', 'analytics', '', implode(', ', $resultobj->errors));
110         }
112         return $resultobj;
113     }
115     /**
116      * Classifies the provided dataset samples.
117      *
118      * @param string $uniqueid
119      * @param \stored_file $dataset
120      * @param string $outputdir
121      * @return \stdClass
122      */
123     public function classify($uniqueid, \stored_file $dataset, $outputdir) {
125         // Obtain the physical route to the file.
126         $datasetpath = $this->get_file_path($dataset);
128         $cmd = 'python -m moodlemlbackend.prediction ' .
129             escapeshellarg($uniqueid) . ' ' .
130             escapeshellarg($outputdir) . ' ' .
131             escapeshellarg($datasetpath);
133         if (!PHPUNIT_TEST && CLI_SCRIPT) {
134             debugging($cmd, DEBUG_DEVELOPER);
135         }
137         $output = null;
138         $exitcode = null;
139         $result = exec($cmd, $output, $exitcode);
141         if (!$result) {
142             throw new \moodle_exception('errornopredictresults', 'analytics');
143         }
145         if (!$resultobj = json_decode($result)) {
146             throw new \moodle_exception('errorpredictwrongformat', 'analytics', '', json_last_error_msg());
147         }
149         if ($exitcode != 0) {
150             throw new \moodle_exception('errorpredictionsprocessor', 'analytics', '', implode(', ', $resultobj->errors));
151         }
153         return $resultobj;
154     }
156     /**
157      * Evaluates this processor classification model using the provided supervised learning dataset.
158      *
159      * @param string $uniqueid
160      * @param float $maxdeviation
161      * @param int $niterations
162      * @param \stored_file $dataset
163      * @param string $outputdir
164      * @return \stdClass
165      */
166     public function evaluate_classification($uniqueid, $maxdeviation, $niterations, \stored_file $dataset, $outputdir) {
168         // Obtain the physical route to the file.
169         $datasetpath = $this->get_file_path($dataset);
171         $cmd = 'python -m moodlemlbackend.evaluation ' .
172             escapeshellarg($uniqueid) . ' ' .
173             escapeshellarg($outputdir) . ' ' .
174             escapeshellarg($datasetpath) . ' ' .
175             escapeshellarg(\core_analytics\model::MIN_SCORE) . ' ' .
176             escapeshellarg($maxdeviation) . ' ' .
177             escapeshellarg($niterations);
179         if (!PHPUNIT_TEST && CLI_SCRIPT) {
180             debugging($cmd, DEBUG_DEVELOPER);
181         }
183         $output = null;
184         $exitcode = null;
185         $result = exec($cmd, $output, $exitcode);
187         if (!$result) {
188             throw new \moodle_exception('errornopredictresults', 'analytics');
189         }
191         if (!$resultobj = json_decode($result)) {
192             throw new \moodle_exception('errorpredictwrongformat', 'analytics', '', json_last_error_msg());
193         }
195         return $resultobj;
196     }
198     /**
199      * Train this processor regression model using the provided supervised learning dataset.
200      *
201      * @throws new \coding_exception
202      * @param string $uniqueid
203      * @param \stored_file $dataset
204      * @param string $outputdir
205      * @return \stdClass
206      */
207     public function train_regression($uniqueid, \stored_file $dataset, $outputdir) {
208         throw new \coding_exception('This predictor does not support regression yet.');
209     }
211     /**
212      * Estimates linear values for the provided dataset samples.
213      *
214      * @throws new \coding_exception
215      * @param string $uniqueid
216      * @param \stored_file $dataset
217      * @param mixed $outputdir
218      * @return void
219      */
220     public function estimate($uniqueid, \stored_file $dataset, $outputdir) {
221         throw new \coding_exception('This predictor does not support regression yet.');
222     }
224     /**
225      * Evaluates this processor regression model using the provided supervised learning dataset.
226      *
227      * @throws new \coding_exception
228      * @param string $uniqueid
229      * @param float $maxdeviation
230      * @param int $niterations
231      * @param \stored_file $dataset
232      * @param string $outputdir
233      * @return \stdClass
234      */
235     public function evaluate_regression($uniqueid, $maxdeviation, $niterations, \stored_file $dataset, $outputdir) {
236         throw new \coding_exception('This predictor does not support regression yet.');
237     }
239     /**
240      * Returns the path to the dataset file.
241      *
242      * @param \stored_file $file
243      * @return string
244      */
245     protected function get_file_path(\stored_file $file) {
246         // From moodle filesystem to the local file system.
247         // This is not ideal, but there is no read access to moodle filesystem files.
248         return $file->copy_content_to_temp('core_analytics');
249     }