MLTutorBeispielerstellung

Aus Physik
Wechseln zu: Navigation, Suche

Allgemeine Fragen und Antworten zum Adaptieren der Übungsbeispiele

Jedes Beispiel einer Übung eigenes Projekt? Benennung?

  • JA, jedes Beispie/Funktion als eigenes Projekt; In der Regel werden die Dateien gleich benannt wie die von den Studierenden.
    • ÄNDERUNG: Sogar jede Funktion soll ein eigenes Projekt werden. Eine Übung besteht dann aus der Aufgabe mehrere Projekte zu programmieren! Deshalb bitte merken, welche Projekte zu welcher Übung gehören!
      • Wenn in der Übung gefordert wird, eine Funktion und ein Script zu schreiben wobei in diesem Script die Funktion aufgerufen wird, da sollte ein Projekt reichen? Wenn die Funktion in einem anderen Projekt sein sollte, dann ist sie auch in einem anderen Verzeichnis. Das Script könnte dann die Funktion nur mit dem entsprechenden Pfad aufrufen...
        • Die Funktion soll trotzdem ein eigenes Projekt sein. Es ist im XML-File möglich Abhängigkeiten zu definieren. Damit wird die Funktion gefunden.

Test von Funktionen?

Es wird eine Referenzfunktion geschrieben und beide Funktionen werden aufgerufen. Danach werden die Variablen verglichen.

Laden von Übungsdaten?

NEIN

Die Datenfiles sollen einfach im gleichen Verzeichnis wie der Matlab-File liegen. Sie werden dann automatisch an die entsprechende Stelle kopiert damit der Test funktioniert.

Wie werden Variablen gesetzt?

  • ENTWEDER es wird ganz klar gefordert welche Werte den Variablen zugewiesen werden müssen,
  • ODER es werden Variablen im Praescript definiert und in der Angabe wird mitgeteilt, dass diese Variablen existieren.


Umgang mit input?

Es wird im before-script die Variable MLTutor_INPUT_ANSWERS gesetzt. Dies ist eine Zelle, die Strings der zu setzenden Werte enthält. Es muss allerdings die Reihenfolge der Abfrage vorgegeben sein. Will man tatsächlich einen String setzen so ist dieser in dreifache single-quotes einzuschließen.

Beispiel:

MLTutor_INPUT_ANSWERS={'[1:5]',Kegel,'[]'};

Bitte beachtet, wie ein leerer Input einzugeben ist ('[]'). Bei Zeichenketten braucht man jeweils drei Hochkommas am Anfang und am Ende, was bei obigem Beispiel dann 'Kegel' als Input liefert.

Input - Fragen

Die Fragen, die mit dem Befehl input gestellt werden, können auch überprüft werden. Beim Beispiel

x = input('Bitte geben Sie x ein: ');

könnte man angeben

MLTutor_INPUT_REGEXP = { ...
   {'[B,b][I,i][T,t][T,t][E,e]','geben','x'} ...
   };

was folgendes bedeutet (in beliebiger Reihenfolge):

das Wort Bitte in beliebiger Schreibweise BItte, BITTE, ...
das Wort geben
das Zeichen x 

Eine andere Möglichkeit

MLTutor_INPUT_REGEXP = { ...
   {'\<Bitte\>.+\<geben\>.+y.*:'} ...
   };

Was in richtiger Reihenfolge bedeutet:

das Wort Bitte
zumindest ein beliebiges Zeichen dazwischen .+
das Wort bitte
zumindest ein beliebiges Zeichen dazwischen .+
der Buchstabe y
beliebig viele Zeichen .* (auch null)
der Doppelpunkt

Näheres zum Thema unter: #Regular Expressions bei Fehlern oder Regular Expressions

Wie bei disp stehen die Ergebnisse dann in

MLTutor_INPUT_REGEXP_CORRECT
MLTutor_INPUT_REGEXP_ALL_CORRECT
MLTutor_INPUT_REGEXP_REALALL_CORRECT

wobei MLTutor_INPUT_REGEXP_ALL_CORRECT für jedes input 0 oder 1 enthält und das Gesamtergebnis in MLTutor_INPUT_REGEXP_REALALL_CORRECT steht.

Kann man den Text den help liefert überprüfen

Ja, ebenfalls mit Regular Expressions. Als Variable stehen zur Verfügung f\r die Definition

MLTutor_HELP_REGEXP = {'regexp1','regexp2','regexp3','usw'};

bzw. die Überprüfung

MLTutor_HELP_REGEXP_CORRECT
MLTutor_HELP_REGEXP_ALL_CORRECT

Näheres zum Thema unter: #Regular Expressions bei Fehlern, #Regular Expressions bei Warnungen, #Regular Expressions bei disp, #Regular Expressions bei input

Zählen von input-Aufrufen

Der Zähler für die Aufrufe von input ist

MLTutor_INPUT_COUNT

Damit kann man feststellen, wie oft die Funktion input aufgerufen wurde.

Umgang mit rand?

Die Testumgebung setzt vor dem Ausführen der Skripte den Seed des Zufallszahlengenerators auf den gleichen Wert. Wichtig ist, dass danach die Reihenfolge in der Variablen erzeugt werden vorgegeben wird und AUF ALLE FÄLLE einzuhalten ist.

Was passiert wenn jemand "clear all" in seinem Script stehen hat?

Naja, ich sehe das als Fehler des Benutzers, da er ja weiß dass Variablen vorgegeben werden.
Eine andere Möglichkeit wäre das aufmerksam machen des Benutzers auf seinen Fehler. Muss man noch entscheiden..

Kein Problem. Alle kritischen Aktionen des Benutzers (Studenten) werden abgefangen.

Na ja, das Problem ist Folgendes: Ich habe jetzt clear abgefangen, wenn etwas von den Studenten laufen kann. Damit beschütze ich auch meine Infrastruktur von MLTutor-Variablen. Damit läuft aber u.U. ein Programm im Testbetieb, das ausserhalb nicht laufen würde. Ich sehe dafür aber jetzt keine bessere Lösung.

In der Variablen

MLTutor_CLEAR_COUNT

wird mitgezählt wie oft clear aufgerufen wird. Man kann es in den Test aufnehmen, dann bekommt man einen Fehler, wenn clear verwendet wird, weil MLTutor_CLEAR_COUNT dann nicht Null ist.

Verbotene Funktionen (z.B. for ).

Es gibt einen Punkt in der XML-Datei, die zum Test gehört, wo man einfach angibt, welche Funktionen der Benutzer nicht verwenden darf. Wenn du kompliziertere Tests des Script schreiben willst, könnte man natürlich in ml_test?_after.m eine Variable ausrechnen und diese mit ml_test?_check.m überprüfen

LaTeX-Angabe? (Referenzen, Kurzbefehle)

Es existiert ein Projekt kernbich.testbeispiele.shorts.de in dem hilfreiche Kurzbefehle definiert sind. Dieses kann am Beginn eines Dokuments folgendermaßen eingebunden werden:

\documentclass[12pt,a4paper]{article}
\input{../kernbich.testbeispiele.shorts.de/shorts}

Wobei der Pfad zum Projekt (hier ..) jeweils angepasst werden muss. Diese Angabe hier sollte aber funktionieren, wenn sich alle Projekte im gleichen Workspace befinden.

In kernbich.testbeispiele.shorts.de existieren einige Kürzel, deren Bedeutung selbserklärend sein sollte:

\matrefe{sqrt}
\matrefe{Wurzel}{sqrt}
\matref{arithmetische Operatoren}{arithmeticoperators}

Bei den Kapiteln bitte unbedingt die neuen Kapitelnummern verwenden.

\appsoftskriptum
\appsoftkapitel{n} % Kapitelnummer n von 1 bis 20
\MatlabLearning
\MatlabReference
\MatlabMathematics
\MatlabCreatingPlots
\MatlabPrograming
\MatlabDataAnalysis
\MatlabEnvironment
\MatlabVisualize
\MatlabCreatingGUIs
\MatlabExternalInterfacesReference
\MatlabExternalInterfaces
\MatlabReferenceFunctionsCategoricalList
\MatlabReferenceMathematics
\MatlabReferenceMathematicsArraysAndMatrices
\MatlabReferenceMathematicsLinearAlgebra
\MatlabReferenceMathematicsElementaryMath
\MatlabReferenceMathematicsPolynomials
\MatlabReferenceMathematicsInterporlationAndComputationalGeometry
\MatlabReferenceMathematicsCoordinateSystemConversion
\MatlabReferenceMathematicsNonlinearNumericalMethods
\MatlabReferenceMathematicsSpecializedMath
\MatlabReferenceMathematicsSparseMatrices
\MatlabReferenceMathematicsMathConstants

Es gibt jetzt auch noch ein Kürzel für die MLTutor - Hints

\mltutorhint{Strichpunkt}{MLTutor Hinweisen}

Dies führt auf MLTutor - Hints#Strichpunkt.

Fehlermitteilungen überprüfen

Im before- oder after-Skript wird definiert ob die gesamte Fehlermitteilung einer Vorgabe entsprechen soll, oder ob es genügt, dass sie eine gewisse Zeichenfolge enthält. Im after-script wird anschließend die Variable MLTutor_ERROR_CORRECT abgefragt. Diese ist 1 wenn die Fehlermitteilungen die gewünschten Kriterien erfüllt.

Weitere Möglichkeiten gibt es auch unter #Regular Expressions bei Fehlern.

% func.m

function [x,y] = func(t)
if nargin < 1; error('time vector is undefined'); end
x = t;
y = t.^2;
% ml_test1_before.m

% request an exact error message
MLTutor_ERROR_REQUEST.message = 'time vector is undefined';
MLTutor_ERROR_REQUEST.type = 'e';

% alternative 'n' means - not exact
%MLTutor_ERROR_REQUEST.message = 'time vector';
%MLTutor_ERROR_REQUEST.type = 'n';
% ml_test1_check.m

MLTutor_ERROR_CORRECT
% ml_test1_after.m

func()

Das Gleiche funktioniert nicht nur für message sondern auch für identifier:

MLTutor_ERROR_REQUEST.message
MLTutor_ERROR_REQUEST.type

mit der Antwort in

MLTutor_ERRORID_CORRECT

Regular Expressions bei Fehlern

Darüberhinaus gibt es auch noch eine bessere Variante, die sich bei der Überprüfung der sogenannten "Regular Expressions" bedient. Man hat im simplen Fall die Möglihkeit zu schreiben

MLTutor_ERROR_REGEXP.message = 'time vector is undefined';

und die Variablen

MLTutor_ERROR_REGEXP_CORRECT
MLTutor_ERROR_REGEXP_ALL_CORRECT

wären dann entweder 1 (richtig) oder 0 (falsch). Ein Unterschied zur ersten Methode besteht aber, da man jetzt die Antwort 1 bekommt, wenn die Zeichenfolge 'time vector is undefined' genau so in der Fehlermitteilung vor kommt, auch wenn vorher oder nachher etwas anderes steht (eigentlich wie type 'n'). Um den type 'e' zu simulieren, müsste man eigentlich

MLTutor_ERROR_REGEXP.message = '^time vector is undefined$';

schreiben. Das Zeichen ^ steht für Anfang und $ steht für Ende.

Details zu Regular Expressions in Matlab geben weitere Hinweise. Einige Möglichkeiten wären

MLTutor_ERROR_REGEXP.message = '^[T|t]ime'; % Time oder time am Anfang
MLTutor_ERROR_REGEXP.message = {'^[T|t]ime'}; % gleich wie vorige Zeile
MLTutor_ERROR_REGEXP.message = {'time', 'vector', 'undefined'}; % beliebige Reihenfolge der drei Worte
MLTutor_ERROR_REGEXP.message = {'time.+vector.+undefined'}; % die drei Worte mit zumindest einem Zeichen dazwischen

Bei der dritten Zeile würde, wenn alles richtig ist,

MLTutor_ERROR_REGEXP_CORRECT = 1 1 1
MLTutor_ERROR_REGEXP_ALL_CORRECT = 1

sein. Wäre vector falsch oder fehlend, dann hätte man

MLTutor_ERROR_REGEXP_CORRECT = 1 0 1
MLTutor_ERROR_REGEXP_ALL_CORRECT = 0

als Resultat. Die Variable MLTutor_ERROR_REGEXP_ALL_CORRECT ist somit eine endgültige Antwort, ob etwas falsch oder richtig ist.

Das Ganze funktioniert auch für Error Identifier, die Variablen heissen dann

MLTutor_ERROR_REGEXP.identifier
MLTutor_ERRORID_REGEXP_CORRECT
MLTutor_ERRORID_REGEXP_ALL_CORRECT

Überprüfung von Warnungen

Funktioniert "gleich" wie bei Fehlermitteilungen.
Request:

MLTutor_WARNING_REQUEST.message
MLTutor_WARNING_REQUEST.type

Überprüfung:

MLTutor_WARNING_CORRECT

Interessiert man sich (auch) für den Idetifier der Warnung, dann kann man das gleiche mit

MLTutor_WARNING_REQUEST.identifier
MLTutor_WARNING_REQUEST.type

mit der Antwort in

MLTutor_WARNINGID_CORRECT

machen.

Regular Expressions bei Warnungen

Wie bei den Fehlern gibt es auch noch eine bessere Variante, die sich bei der Überprüfung der sogenannten "Regular Expressions" bedient (siehe #Regular Expressions bei Fehlern, Regular Expressions).

Die Definitions-Variablen sind jetzt einfach

MLTutor_WARNING_REGEXP.message
MLTutor_WARNING_REGEXP.identifier

und die Lösung der Überprüfung steht in

MLTutor_WARNING_REGEXP_CORRECT
MLTutor_WARNING_REGEXP_ALL_CORRECT
MLTutor_WARNINGID_REGEXP_CORRECT
MLTutor_WARNINGID_REGEXP_ALL_CORRECT

Überprüfung von Ausgaben von disp

Funktioniert ebenfalls wie bei Fehlermitteilungen.

MLTutor_DISP_REQUEST.message
MLTutor_DISP_REQUEST.type

Überprüfung:

MLTutor_DISP_CORRECT

Beispiel:

a = pi;
b = [1:4];
disp(['Variable a: ',num2str(a)])
disp(['Variable b: ',mat2str(b)])
disp(a)
disp(b)
MLTutor_DISP_REQUEST.message = { ...
    ['Variable a: ',num2str(a)], ...
    ['Variable b: ',mat2str(b)], ...
    a, ...
    b ...
    };
MLTutor_DISP_REQUEST.type = {'e','e','e','e'};

Die Anweisung für MLTutor_DISP_REQUEST.message und MLTutor_DISP_REQUEST.type können in test_before oder test_after stehen. Das Problem besteht aber darin, dass man u.U. die Variablennamen nicht kennt. Wenn man z.B. den Studenten nicht anweist, dass der Variablenname a ist, dann kann man im test_after nicht num2str(a) verwenden. Ausserdem geht es bei Funktionen auch nicht, da alle internen Variablen der Funktion im test_after nicht sichtbar sind.

Insgesamt empfiehlt es sich immer Strings wie ['a = ',num2str(a)] zu verwenden und nicht einfach a. Bei Zahlen funktioniert, die nichtexakte Überprüfung nämlich nicht.

Was immer möglich ist, ist MLTutor_DISP_RESULTS. Diese Größe enthält, das Ergebnis der Ausgabe, wobei noch keine Überprüfung durchgeführt wird. Die Überprüfung liegt dann wie bei allen anderen Variablen in den Händen von David. Damit müssen die Strings aber exakt übereinstimmen. Eine nichtexakte Überprüfung ist da nicht möglich.

Regular Expressions bei disp

Auch bei disp (oder fprintf) kann man jetzt Regular Expressions (siehe auch #Regular Expressions bei Fehlern) verwenden.

Auch hier ist vorausgesetzt, dass man die Variablen a und b im after-Skript kennt:

astr = num2str(a);
astr = strrep(astr(1:5),'.','\.');
bstr = mat2str(b);
bstr=strrep(bstr,'[','\[');
bstr=strrep(bstr,']','\]');
MLTutor_DISP_REGEXP = { ...
    {'Variable\s+a\s*[:|-]',astr}, ...
    {'Variable','b:',bstr}, ...
    {astr}, ...
    {b}, ...
    };

Beim ersten Ergebnis wird überprüft, ob die Antwort besteht aus

dem Wort Variable
zumindest einem Whitespace-Character (z.B. Leerzeichen) \s+
dem Buchstaben a
beliebig vielen Whitespace-Characters (auch Null) \s*
einem Doppelpunkt oder einem Bindestrich [:|-]

und dann, ob das Ergebnis von a vorkommt, und zwar

die ersten fünf Zeichen, wobei . durch \. ersetzt wurde

Bei der zweiten Zeile wird überprüft, ob die Antwort besteht aus

dem Wort Variable
der Kombination b:
dem Ergebnis von mat2str(b), wobei [ durch \[ und ] durch \] ersetzt wurde

Bei der dritten Zeile wieder

astr aus num2str mit dem Dezimalpunkt ersetzt

Bei der vierten Zeile

b

hier erfolgt automatisch eine Umwandlung mit num2str(b). Dies funktioniert klaglos aber nur, weil b ein Zeilenvektor aus Integerzahlen ist. Im Prinzip ist das keine gute Idee, viel besser ist die Überprüfung, wenn die Variablen schon vorher in Strings umgewandelt wurden.

Die Ergebnisse stehen dann in

MLTutor_DISP_REGEXP_CORRECT
MLTutor_DISP_REGEXP_ALL_CORRECT
MLTutor_DISP_REGEXP_REALALL_CORRECT

wobei MLTutor_DISP_REGEXP_ALL_CORRECT für jedes disp 0 oder 1 enthält und das Gesamtergebnis in MLTutor_DISP_REGEXP_REALALL_CORRECT steht.

Zählen von disp-Aufrufen

Der Zähler für die Aufrufe von disp ist

MLTutor_DISP_COUNT

Damit kann man feststellen, wie oft die Funktion disp oder fprintf (mit fid 1 oder 2) aufgerufen wurde.

Überprüfung von Plots

Funktioniert ähnlich wie das Testen von Fehlermeldungen. Im before-script wird mit Hilfe von MLTutor_GRAPHICS_REQUEST festgelegt, welche Eigenschaften des Plots überprüft werden sollen. Darin kann jedes Element das im Handle Graphics Property Browser zu finden ist überprüft werden. Die Numerierung (siehe Beispiel) in der Anforderung der Ergebnisse ergibt sich aus der Reihenfolge in der die Objekte im Plot erzeugt werden. Somit muss diese in der Angabe zu einem Projekt fix vorgegeben sein. Beispiele:

  • siehe unten
  • kernbich.testbeispiele.sgraph*
% main.m

x = -2:0.1:3;

g1 = normpdf(x,0,1);
g2 = normpdf(x,1,0.5);

plot(x,g1,x,g2,'r');  %line1 & line2

hold on
plot(x,g1+g2,'k'); %line 3
hold off

line(x,g1-g2,'color','green'); %draw line in current axes without the use of hold on .... hold off

xlabel('x');
ylabel('y');
title('Just an example')

% end main.m
% ml_test1_before.m

% check properties of axes
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.request = {'xlabel','ylabel','title'};

% check data of line 1 (g1)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_1.request = {'xdata','ydata'};

% check data and color of line 2 (g2)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_2.request = {'xdata','ydata','color'};

% check data and color of line 3 (g1 + g2)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_3.request = {'xdata','ydata','color'};

% check data and color of line 4 (g1 - g2)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_4.request = {'xdata','ydata','color'};

So können die Figures unsichtbar gemacht werden.

% ml_test1_before.m
MLTutor_FIGURE_HIDE = 1;

Beispiel für Legende:

MLTutor_GRAPHICS_REQUEST.figure_1.axes_2.text_1.request = {{'string',{'\<Gauss\>|\<gauss\>|\<GAUSS\>'}}};
% ml_test1_check.m

MLTutor_GRAPHICS_RESULTS
% ml_test1_after.m
% nothing to do

Regular Expressions

Auch hier kann man nun Regular Expressions verwenden, und zwar geht das bei allen Größen die Zeichenketten als Resultat haben. Obiges Beispiel könnte also so modifiziert werden:

MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.request = { ...
 { 'xlabel', '^x$' }, ...
 { 'ylabel', '^y$' }, ...
 { 'title', {'[J|j]ust', '[E|e]xample'} } ...
};

Die Beispiele funktionieren wie bei disp, Fehlern, Warnungen und input.

Im Unterschied zur Verwendung ohne Regular Expressions steht dann im Ergebnis z.B. bei xlabel nicht x sondern 1 (richtig) oder 0 (falsch). Die Outputvariable ist aber die selbe Struktur:

MLTutor_GRAPHICS_RESULTS

Eigenheiten bei errorbar

Bei errorbar und bei anderen Befehlen, welche die neuen Gruppierungsfeatures von Matlab verwenden, gibt es das Problem, dass die Reihenfolge der Linien nicht so ist wie erwartet.

x = linspace(0,pi,100)
y = sin(x);
xd = x(1:5:end);
yd = sin(xd);
y1 = cos(x);
yd1 = cos(xd);

sig = 0.2;
rd = rand(size(xd))*sig

figure
plot(x,y,'r-')

hold on
errorbar(xd,yd,rd,'ob')
plot(x,y1,'k-')
errorbar(xd,yd1,rd,'og')
hold off

legend({'Fit1','Data1','Fit2','Data2'},'Location','sw')

Normalerweise würde man erwarten, dass

MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_1.request = {'xdata','ydata','color'};   % sin(x)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_2.request = {'xdata','ydata','color'};   % sin(xd)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_3.request = {'xdata','ydata','color'};   % Fehler zu sin(xd)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_4.request = {'xdata','ydata','color'};   % cos(x)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_5.request = {'xdata','ydata','color'};   % cos(xd)
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_6.request = {'xdata','ydata','color'};   % Fehler zu cos(xd)

liefert. In der Realität ist die Reihenfolge aber

MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_1.request = {'xdata','ydata','color'};   % Fehler zu sin(xd) - Erste hggroup
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_2.request = {'xdata','ydata','color'};   % sin(xd) - Erste hggroup
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_3.request = {'xdata','ydata','color'};   % Fehler zu cos(xd) - Zweite hggroup
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_4.request = {'xdata','ydata','color'};   % cos(xd) - Zweite hggroup
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_5.request = {'xdata','ydata','color'};   % sin(x) - Erster Plotbefehl
MLTutor_GRAPHICS_REQUEST.figure_1.axes_1.line_6.request = {'xdata','ydata','color'};   % cos(x) - Zeiter Plotbefehl

Seid also bitte vorsichtig, welche Linien ihr überprüft. Ich habe keine Möglichkeit, dass zu korrigieren, jedenfalls nicht mit vertretbarem Aufwand.

Legende

Beim Befehl legend gibt es eine neue Syntax:

legend({'Fit1','Data1','Fit2','Data2'},'Location','nw')

Es ist gut wenn man die Liste der Beschriftung jetzt in einer Zelle {} schreibt und dann den Ort in der neuen Syntax. Siehe dazu legend.

Will man auch Fehler in der Legende ehen, dann muss man obiges Beispiel so ändern:

figure
lh1 = plot(x,y,'r-')

hold on
ebh1 = errorbar(xd,yd,rd,'ob') % hggroup
ebh1_ch = get(ebh1,'children');
lh2 = plot(x,y1,'k-')
ebh2 = errorbar(xd,yd1,rd,'og') % hggroup
ebh2_ch = get(ebh2,'children');
hold off

legend([lh1;ebh1_ch;lh2;ebh2_ch],{'Fit1','Data1','Fehler1','Fit2','Data2','Fehler2'},'Location','sw')

Dazu muss man die Handles auf alle gewünschten Graphikobjekte verwenden und daraus einen Vektor formen. Die Handles ebh1 und ebh2 sind Handles auf hggroup und man muss daher zuerst auch noch ihre Kinder (children) abfragen.

Polarplot

Der Befehl polar funktioniert wie erwartet. De extra Linien, die den Polarplot schmücken (Kreise, radiale Linien) sind alle versteckt (hidden) und machen daher keine Probleme. Die Abfrage nach den Linien geht daher wunderbar und es gibt auch kein Problem mir der Reihenfolge.

Figure

Während der Tests werden für figure noninteger-Handles verwendet. Daher sieht man, auch wenn man es z.B. mit figure(1) versucht keine Zeichnung mit dem Handle 1 sondern mit einem anderen Handle. Daher funktioniert auf keinen Fall:

figure(1);
set(1,'Color','red')

Will man so etwas, muss man schreiben

fh=figure;
set(fh,'Color','red')

Ein anfänglicher Fehler wurde mit einem Update behoben.

Wie wird dem Benutzer der Testaufruf der Funktion mitgeteilt?

Alles was in einem Script von %### eingeschlossen ist, ist dem Benutzer zugänglich.

 %ml_test1_after.m
 %###
 t = linspace(0,10,100);
 [x,y] = foo(t,[],4);
 %###

 test_size = size(x);

Hier sieht der Benutzer also, welche Werte t zugewiesen werden, und wie die Funktion foo aufgerufen wird. Er sieht allerdings nicht, dass anschließend auch noch eine Variable test_size erzeugt wird.

Bei Skripts braucht man das nur, wenn im before-Skript Variablen gesetzt werden. Dann sollten diese auch zwischen

%###
a = 3; b = 5;
%###

gesetzt werden.

In den Skripts und Funktionen UNBEDINGT Strichpunkte am Ende von Zeilen verwenden, die eine Ausgabe haben!

Verbesserung

Möglich wäre obiges Beispiel auch in dieser Form:

%ml_test1_after.m
%###
t = linspace(0,10,100);
%###

mltutor_function_switch(1);
%###
[x,y] = foo(t,[],4);
%###
mltutor_function_switch(0);

test_size = size(x);

Der Aufruf mltutor_function_switch(1); teilt der Testroutine mit, dass jetzt wirklich die Funktion des Studenten bearbeitet wird. Mit mltutor_function_switch(0); schaltet man das wieder aus. Wenn man das nicht macht, läuft das gesamte after-Skript in diesem Modus, was normalerweise keine Problem ist, da es nur Auswirkungen auf

MLTutor_DISPLAY_COUNT % Anzahl vergessener Strichpunkte
MLTutor_CPU_TIME % cpu-Time während der Abarbeitung

Verwendet man das Feature nicht, wird das gesamte after-Skript in diesem Modus betrieben. Dann ist es eben noch wichtiger, dass man ordnungsgemäß Strichpunkte am Ende der Zeile macht!

CPU Time

Die CPU Time, die von jenem Teil des Programms verbraucht wird, die vom Studenten stammt, findet sich in

MLTutor_CPU_TIME % cpu-Time während der Abarbeitung

(siehe dazu auch #Verbesserung).

Anzahl der vergessenen Strichpunkte

Gute Skripts und Funktionen sollten keinen Output am Schirm produzieren, der nur durch Weglassen des Strichpunktes am Ende einer Anweisung entsteht. Das sollte man auch in den before- und after-Skripts beherzigen. Wenn man in einem Test zählen will, wie oft der Student den Strichpunkt vergessen hat, dan kann man folgende Variable verwenden

MLTutor_CPU_TIME