Skip to content

Commit cfc57e0

Browse files
committed
Merge branch 'matlab-commands'
Adds extensible command plugins to expose static utility-like methods in MATLAB.
2 parents ab032ea + d8d23f8 commit cfc57e0

File tree

9 files changed

+481
-103
lines changed

9 files changed

+481
-103
lines changed

src/main/java/org/scijava/plugins/scripting/matlab/DefaultMATLABService.java

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,29 +31,89 @@
3131

3232
package org.scijava.plugins.scripting.matlab;
3333

34+
import javax.script.ScriptEngine;
35+
3436
import matlabcontrol.extensions.MatlabNumericArray;
3537

38+
import org.scijava.log.LogService;
39+
import org.scijava.plugin.AbstractSingletonService;
3640
import org.scijava.plugin.Parameter;
3741
import org.scijava.plugin.Plugin;
3842
import org.scijava.script.ScriptService;
39-
import org.scijava.service.AbstractService;
4043
import org.scijava.service.Service;
4144

4245
/**
46+
* Default {@link MATLABService} implementation.
47+
*
4348
* @author Mark Hiner
4449
*/
4550
@Plugin(type = Service.class)
46-
public class DefaultMATLABService extends AbstractService implements
47-
MATLABService
51+
public class DefaultMATLABService extends
52+
AbstractSingletonService<MATLABCommands> implements MATLABService
4853
{
4954

5055
@Parameter
5156
private ScriptService scriptService;
5257

58+
@Parameter
59+
private LogService logService;
60+
61+
private boolean initializedCommands = false;
62+
63+
@Override
64+
public String commandHelp() {
65+
String helpMessage = "--- MATLAB Command Plugins ---\n\n";
66+
67+
for (final MATLABCommands command : getInstances()) {
68+
helpMessage += command.usage();
69+
}
70+
71+
helpMessage += "\n";
72+
73+
return helpMessage;
74+
}
75+
76+
@Override
77+
public void initializeCommands() {
78+
if (!initializedCommands) createCommandVariables();
79+
}
80+
81+
@Override
82+
public void makeMATLABVariable(final String name, final Object value) {
83+
final ScriptEngine engine =
84+
scriptService.getLanguageByName("MATLAB").getScriptEngine();
85+
engine.put(name, value);
86+
}
87+
5388
// -- Service methods --
5489

5590
@Override
5691
public void initialize() {
92+
// Register known data type aliases for use in script @parameters
5793
scriptService.addAlias("matrix", MatlabNumericArray.class);
5894
}
95+
96+
// -- Typed methods --
97+
98+
@Override
99+
public Class<MATLABCommands> getPluginType() {
100+
return MATLABCommands.class;
101+
}
102+
103+
// -- Helper methods --
104+
105+
/**
106+
* Helper method to create variables for each {@link MATLABCommands} within
107+
* MATLAB.
108+
*/
109+
private synchronized void createCommandVariables() {
110+
if (!initializedCommands) {
111+
for (final MATLABCommands command : getInstances()) {
112+
final String name = command.getInfo().getName();
113+
114+
makeMATLABVariable(name, command);
115+
}
116+
initializedCommands = true;
117+
}
118+
}
59119
}

src/main/java/org/scijava/plugins/scripting/matlab/MATLABBindings.java

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,23 @@
4141
import javax.script.Bindings;
4242

4343
import matlabcontrol.MatlabInvocationException;
44+
import matlabcontrol.MatlabProxy;
4445
import matlabcontrol.extensions.MatlabNumericArray;
4546
import matlabcontrol.extensions.MatlabTypeConverter;
4647

48+
import org.scijava.options.OptionsService;
49+
import org.scijava.plugin.Parameter;
50+
4751
/**
4852
* A {@link Bindings} wrapper around MATLAB's local variables.
4953
*
5054
* @author Mark Hiner
5155
*/
5256
public class MATLABBindings implements Bindings {
5357

58+
@Parameter
59+
private OptionsService optionsService;
60+
5461
@Override
5562
public int size() {
5663
return getVars().length;
@@ -69,7 +76,7 @@ public boolean containsValue(final Object value) {
6976
@Override
7077
public void clear() {
7178
try {
72-
MATLABControlUtils.proxy().eval("clear");
79+
MATLABControlUtils.proxy(opts()).eval("clear");
7380
}
7481
catch (final MatlabInvocationException e) {}
7582
}
@@ -101,26 +108,31 @@ public Set<java.util.Map.Entry<String, Object>> entrySet() {
101108

102109
@Override
103110
public Object put(final String name, final Object value) {
111+
final MatlabProxy proxy = MATLABControlUtils.proxy(opts());
112+
113+
// Try special MATLAB data types
114+
if (MatlabNumericArray.class.isAssignableFrom(value.getClass())) {
115+
// Convert the dataset to a MATLAB array and set it as a local variable
116+
// within MATLAB.
117+
final MatlabTypeConverter converter =
118+
new MatlabTypeConverter(proxy);
119+
try {
120+
converter.setNumericArray(sanitize(name), (MatlabNumericArray) value);
121+
return value;
122+
}
123+
catch (final MatlabInvocationException e) {
124+
System.err.println(e.getStackTrace());
125+
}
126+
}
127+
104128
try {
105-
MATLABControlUtils.proxy().setVariable(sanitize(name), value);
129+
proxy.setVariable(sanitize(name), value);
106130
return value;
107131
}
108132
catch (final MatlabInvocationException e) {
109-
110-
// Try special MATLAB data types
111-
if (MatlabNumericArray.class.isAssignableFrom(value.getClass())) {
112-
// Convert the dataset to a MATLAB array and set it as a local variable
113-
// within MATLAB.
114-
final MatlabTypeConverter converter =
115-
new MatlabTypeConverter(MATLABControlUtils.proxy());
116-
try {
117-
converter.setNumericArray(name, (MatlabNumericArray) value);
118-
}
119-
catch (final MatlabInvocationException e1) {
120-
throw new IllegalArgumentException(e);
121-
}
122-
}
133+
System.err.println(e.getStackTrace());
123134
}
135+
124136
return null;
125137
}
126138

@@ -160,24 +172,27 @@ private Object retrieveValue(final Object key, final boolean remove) {
160172
if (key instanceof String) k = (String) key;
161173
else return null;
162174
Object v = null;
175+
final MatlabProxy proxy = MATLABControlUtils.proxy(opts());
163176

177+
// Attempt to retrieve special MATLAB types
164178
try {
165-
v = MATLABControlUtils.proxy().getVariable(k);
166-
if (remove) MATLABControlUtils.proxy().eval("clear " + k);
179+
// try recovering key as a MatlabNumericArray
180+
final MatlabTypeConverter converter =
181+
new MatlabTypeConverter(proxy);
182+
v = converter.getNumericArray(k);
167183
}
168184
catch (final MatlabInvocationException e) {
185+
System.err.println(e.getStackTrace());
186+
}
169187

170-
// Attempt to retrieve special MATLAB types
171-
try {
172-
// try recovering key as a MatlabNumericArray
173-
final MatlabTypeConverter converter =
174-
new MatlabTypeConverter(MATLABControlUtils.proxy());
175-
v = converter.getNumericArray(k);
176-
}
177-
catch (final MatlabInvocationException e1) {
178-
System.err.println(e.getStackTrace());
179-
}
188+
try {
189+
v = proxy.getVariable(k);
190+
if (remove) proxy.eval("clear " + k);
191+
}
192+
catch (final MatlabInvocationException e) {
193+
System.err.println(e.getStackTrace());
180194
}
195+
181196
return v;
182197
}
183198

@@ -187,7 +202,7 @@ private Object retrieveValue(final Object key, final boolean remove) {
187202
private String[] getVars() {
188203
try {
189204
final String[] vars =
190-
(String[]) MATLABControlUtils.proxy().returningEval("who", 1)[0];
205+
(String[]) MATLABControlUtils.proxy(opts()).returningEval("who", 1)[0];
191206
return vars;
192207
}
193208
catch (final MatlabInvocationException e) {}
@@ -203,4 +218,13 @@ private String[] getVars() {
203218
private String sanitize(final String name) {
204219
return name.replaceAll("[^\\w]", "_");
205220
}
221+
222+
/**
223+
* Convenience method for access to the {@link MATLABOptions}
224+
*
225+
* @return Active {@code MATLABOptions}
226+
*/
227+
private MATLABOptions opts() {
228+
return optionsService.getOptions(MATLABOptions.class);
229+
}
206230
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* #%L
3+
* MATLAB scripting language plugin.
4+
* %%
5+
* Copyright (C) 2014 Board of Regents of the University of
6+
* Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck
7+
* Institute of Molecular Cell Biology and Genetics.
8+
* %%
9+
* Redistribution and use in source and binary forms, with or without
10+
* modification, are permitted provided that the following conditions are met:
11+
*
12+
* 1. Redistributions of source code must retain the above copyright notice,
13+
* this list of conditions and the following disclaimer.
14+
* 2. Redistributions in binary form must reproduce the above copyright notice,
15+
* this list of conditions and the following disclaimer in the documentation
16+
* and/or other materials provided with the distribution.
17+
*
18+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
* POSSIBILITY OF SUCH DAMAGE.
29+
* #L%
30+
*/
31+
package org.scijava.plugins.scripting.matlab;
32+
33+
import org.scijava.plugin.Plugin;
34+
import org.scijava.plugin.RichPlugin;
35+
import org.scijava.plugin.SingletonPlugin;
36+
37+
38+
/**
39+
* A suite of commands for use in MATLAB. The {@link MATLABService} will create
40+
* variables for each {@link MATLABCommands} using their annotated
41+
* {@link Plugin#name()}, allowing convenient access to any of their methods.
42+
*
43+
* @see MATLABService
44+
*
45+
* @author Mark Hiner
46+
*/
47+
public interface MATLABCommands extends SingletonPlugin, RichPlugin {
48+
49+
/**
50+
* @return A string describing any commands that should be publicized.
51+
*/
52+
String usage();
53+
}

0 commit comments

Comments
 (0)