001/* An actor that evaluates matlab expressions with input ports 002 providing variables 003 004 Copyright (c) 1998-2018 The Regents of the University of California and 005 Research in Motion Limited. 006 All rights reserved. 007 Permission is hereby granted, without written agreement and without 008 license or royalty fees, to use, copy, modify, and distribute this 009 software and its documentation for any purpose, provided that the above 010 copyright notice and the following two paragraphs appear in all copies 011 of this software. 012 013 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA OR RESEARCH IN MOTION 014 LIMITED BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, 015 INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS 016 SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA 017 OR RESEARCH IN MOTION LIMITED HAVE BEEN ADVISED OF THE POSSIBILITY OF 018 SUCH DAMAGE. 019 020 THE UNIVERSITY OF CALIFORNIA AND RESEARCH IN MOTION LIMITED 021 SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 022 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 023 PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" 024 BASIS, AND THE UNIVERSITY OF CALIFORNIA AND RESEARCH IN MOTION 025 LIMITED HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 ENHANCEMENTS, OR MODIFICATIONS. 027 028 PT_COPYRIGHT_VERSION_2 029 COPYRIGHTENDKEY 030 031 */ 032package ptolemy.matlab; 033 034import java.util.HashMap; 035import java.util.Iterator; 036import java.util.Map; 037import java.util.Set; 038import java.util.StringTokenizer; 039 040import ptolemy.actor.Director; 041import ptolemy.actor.IOPort; 042import ptolemy.actor.TypedAtomicActor; 043import ptolemy.actor.TypedIOPort; 044import ptolemy.actor.gui.style.CheckBoxStyle; 045import ptolemy.actor.gui.style.TextStyle; 046import ptolemy.data.BooleanToken; 047import ptolemy.data.DoubleToken; 048import ptolemy.data.IntToken; 049import ptolemy.data.StringToken; 050import ptolemy.data.Token; 051import ptolemy.data.expr.Parameter; 052import ptolemy.data.expr.StringParameter; 053import ptolemy.data.expr.UtilityFunctions; 054import ptolemy.data.expr.Variable; 055import ptolemy.data.type.BaseType; 056import ptolemy.graph.Inequality; 057import ptolemy.kernel.CompositeEntity; 058import ptolemy.kernel.util.IllegalActionException; 059import ptolemy.kernel.util.NameDuplicationException; 060import ptolemy.kernel.util.Workspace; 061import ptolemy.matlab.Engine.ConversionParameters; 062 063/////////////////////////////////////////////////////////////////// 064//// Expression 065 066/** 067 On each firing send an expression for evaluation to a matlab {@link 068 Engine}. The expression is any valid matlab expression, e.g.: 069 070 <pre> 071 [out1, out2, ... ] = SomeMatlabFunctionOrExpression( in1, in2, ... );... 072 </pre> 073 074 <p>The expression may include references to the input port names, current 075 time (<i>time</i>), and a count of the firing (<i>iteration</i>). This 076 is similar to <a href="../../ptolemy/actor/lib/Expression.html">Expression</a>. 077 To refer to parameters in scope, use $name or ${name} within 078 the expression.</p> 079 080 <p>The matlab engine is opened (started) during prefire() by the first 081 matlab Expression actor. Subsequent open()s simply increment a use 082 count.</p> 083 084 <p>At the start of fire(), <i>clear variables;clear globals</i> commands are 085 sent to matlab to clear its workspace. This helps detect errors where the 086 matlab expression refers to a matlab variable not initialized from the 087 input ports of this actor instance.</p> 088 089 <p>After the evaluation of the matlab expression is complete, the fire() 090 method iterates through names of output ports and converts matlab 091 variables with corresponding names to Tokens that are sent to the 092 corresponding output ports. Incorrect expressions are usually first 093 detected at this point by not finding the expected variables. If an 094 output port variable is not found in the matlab {@link Engine}, an 095 exception is thrown. The exception description string contains the last 096 stdout of the matlab engine that usually describes the error.</p> 097 098 <p>The {@link #get1x1asScalars} and {@link #getIntegerMatrices} control 099 data conversion (see {@link Engine} and 100 {@link Engine.ConversionParameters}).</p> 101 102 <p>A Parameter named <i>packageDirectories</i> may be added to this actor 103 to augment the search path of the matlab engine during the firing of this 104 actor. The value of this parameter should evaluate to a StringToken, 105 e.g.: 106 107 <pre> 108 "path1, path2, ..." 109 </pre> 110 111 <p> containing a comma-separated list of paths to be prepended to the matlab 112 engine search path before <i>expression</i> is evaluated. The list may 113 contain paths relative to the directory in which ptolemy was started, 114 or any directory listed in the current classpath (in that order, first 115 match wins). See {@link ptolemy.data.expr.UtilityFunctions#findFile(String)}. 116 After evaluation, the previous search path is restored.</p> 117 118 <p>A Parameter named <i>_debugging</i> may be used to turn on debug print 119 statements to stdout from {@link Engine} and the ptmatlab JNI. An IntToken 120 with a value of 1 turns on Engine debug statements, a value of 2 adds 121 ptmatlab debug statements as well. A value of 0 or the absence of the 122 <i>_debugging</i> parameter yields normal operation.</p> 123 124 <p>For this actor to work, Matlab must be installed on your local 125 machine. In addition, your environment must be set properly. The 126 <code>$PTII/bin/vergil</code> script does this for you, below are 127 instructions for users, such as Eclipse users, who are not using 128 <code>$PTII/bin/vergil</code>.</p> 129 130 <p>Add the Matlab shared libraries to your the library path. In the examples 131 below <code>$MATLAB</code> 132 should be the location of your Matlab installation. For example, if 133 /usr/bin/matlab is a link: 134 <pre> 135 bash-3.2$ which matlab 136 /usr/bin/matlab 137 bash-3.2$ ls -l /usr/bin/matlab 138 lrwxr-xr-x 1 root wheel 42 Jan 15 20:57 /usr/bin/matlab -> /Applications/MATLAB_R2009b.app/bin/matlab 139 bash-3.2$ 140 </pre> 141 142 Then $MATLAB would be /Applications/MATLAB_R2009b.app 143 144 <dl> 145 <dt>32 Bit Mac (10.5?, Edit ~/.MacOSX/environment.plist)</dt> 146 <dd><code>export DYLD_LIBRARY_PATH=$MATLAB/bin/maci</code></dd> 147 <dt>64 Bit Mac (10.6?, Edit ~/.MacOSX/environment.plist)</dt> 148 <dd><code>export DYLD_LIBRARY_PATH=$MATLAB/bin/maci64</code></dd> 149 <dt>32 Bit Linux (Edit</dt> 150 <dd><code>export LD_LIBRARY_PATH=$MATLAB/bin/gnlx86</code></dd> 151 <dt>64 Bit Linux</dt> 152 <dd><code>export LD_LIBRARY_PATH=$MATLAB/bin/glnxa64</code></dd> 153 <dt>Windows (Start|My Computer|Properties|Advanced 154 Environment Variables| Add the directory that contains 155 matlab.exe to your path)</dt> 156 <dd><code>Be sure that the matlab binary is in your path</code></dd> 157 </dl> 158 159 <h2>Notes about Matlab 10.8 and later</h2> 160 161 <p>Note that under recent version of MacOS, the DYLD_LIBRARY_PATH is no longer used. 162 The workaround is to be sure that matlab is in your path and to run ./configure.</p> 163 164 <p>For example:</p> 165 <pre> 166 bash-3.2$ bash-3.2$ which matlab 167 /Applications/MATLAB_R2018a.app/bin/matlab 168 </pre> 169 170 <p>Then, running:</p> 171 <pre> 172 ./configure --enable-verbose 173 </pre> 174 175 <p>shows:</p> 176 177 <pre> 178 checking for matlab... /Applications/MATLAB_R2018a.app/bin/matlab 179 checking the value of the Matlab root directory ... '/Applications/MATLAB_R2018a.app' 180 checking for gcc... checking for gcc... /usr/bin/gcc 181 checking for malloc_size... yes 182 checking the extension for Matlab .mex files... mexmaci64 183 checking which major type of OS we are running under... MacOSX 184 using '/Applications/MATLAB_R2018a.app/bin/maci' for Matlab's engine libraries 185 </pre> 186 187 <p>Then run</p> 188 <pre> 189 cd $PTII 190 ant 191 cd $PTII/bin 192 make 193 cd $PTII/ptolemy/matlab 194 make clean; make 195 </pre> 196 197 <p>Here's what libraries are used by libptmatlab.jnilib</p> 198 199 <pre> 200 bash-3.2$ otool -L libptmatlab.jnilib 201 libptmatlab.jnilib: 202 libptmatlab64.jnilib (compatibility version 0.0.0, current version 0.0.0) 203 @rpath/libeng.dylib (compatibility version 0.0.0, current version 0.0.0) 204 @rpath/libmx.dylib (compatibility version 0.0.0, current version 0.0.0) 205 @rpath/libmex.dylib (compatibility version 0.0.0, current version 0.0.0) 206 /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.0.0) 207 bash-3.2$ 208 </pre> 209 210 <p>To see the value of rpath:</p> 211 212 <pre> 213 otool -l libptmatlab.jnilib 214 ... 215 Load command 14 216 cmd LC_RPATH 217 cmdsize 56 218 path /Applications/MATLAB_R2018a.app/bin/maci64 (offset 12) 219 </pre> 220 221 <p>So, the above says that the shared library has an RPATH of /Applications/MATLAB_R2018a.app/bin/maci64, which is where libeng.dylib is:</p> 222 223 <pre> 224 bash-3.2$ ls -l /Applications/MATLAB_R2018a.app/bin/maci64/libeng.dylib 225 -r-xr-xr-x 1 cxh admin 15664 Feb 6 01:17 /Applications/MATLAB_R2018a.app/bin/maci64/libeng.dylib 226 </pre> 227 228 </p>Edit loadLibrary() in 229 $PTII/ptolemy/data/expr/UtilityFunctions.java and set debug to true, 230 then I can see what file is loaded by loading the demo</p> 231 232 <pre> 233 bash-3.2$ $PTII/bin/vergil $PTII/ptolemy/matlab/demo/MatlabExpression/MatlabExpression.xml 234 UtilityFunctions.loadLibrary(ptolemy/matlab/ptmatlab) 235 UtilityFunctions.loadLibrary(ptolemy/matlab/ptmatlab): System.load() 236 UtilityFunctions.loadLibrary(ptolemy/matlab/ptmatlab): java.lang.UnsatisfiedLinkError: Expecting an absolute path ofthe library: ptolemy/matlab/ptmatlab 237 UtilityFunctions._loadLibrary(ptolemy/matlab/ptmatlab, jnilib): osName: Mac OS X 238 UtilityFunctions._loadLibrary(ptolemy/matlab/libptmatlab, jnilib): libraryWithSuffix: ptolemy/matlab/libptmatlab.jniib libraryPathExiststrue 239 UtilityFunctions._loadLibrary(ptolemy/matlab/libptmatlab, jnilib): System.load(/Users/cxh/src/ptII11.0.devel/ptolemy/matlab/libptmatlab.jnilib) 240 <pre> 241 242 <p>Use the <code>otool</code> <code>-L</code> and <code>-l</code> 243 commands to ensure that <code>libeng.dylib</code> can be found.</p> 244 245 @author Zoltan Kemenczy and Sean Simmons, Research in Motion Limited 246 @version $Id$ 247 @since Ptolemy II 2.0 248 @Pt.ProposedRating Yellow (zkemenczy) 249 @Pt.AcceptedRating Red (cxh) 250 */ 251public class Expression extends TypedAtomicActor { 252 /** Construct an actor with the given container and name. 253 * @param container The container. 254 * @param name The name of this actor. 255 * @exception IllegalActionException If the actor cannot be contained 256 * by the proposed container. 257 * @exception NameDuplicationException If the container already has an 258 * actor with this name. 259 */ 260 public Expression(CompositeEntity container, String name) 261 throws NameDuplicationException, IllegalActionException { 262 super(container, name); 263 264 output = new TypedIOPort(this, "output", false, true); 265 expression = new StringParameter(this, "expression"); 266 new TextStyle(expression, "Matlab expression"); 267 268 _dataParameters = new Engine.ConversionParameters(); 269 270 get1x1asScalars = new Parameter(this, "get1x1asScalars", 271 new BooleanToken(_dataParameters.getScalarMatrices)); 272 new CheckBoxStyle(get1x1asScalars, "style"); 273 274 getIntegerMatrices = new Parameter(this, "getIntegerMatrices", 275 new BooleanToken(_dataParameters.getIntMatrices)); 276 new CheckBoxStyle(getIntegerMatrices, "style"); 277 278 clearEnvironment = new Parameter(this, "clearEnvironment", 279 new BooleanToken(true)); 280 clearEnvironment.setTypeEquals(BaseType.BOOLEAN); 281 clearEnvironment.setToken(BooleanToken.TRUE); 282 283 // _time is not needed, fire() sets a matlab variable directly 284 _iteration = new Variable(this, "_iteration", new IntToken(1)); 285 } 286 287 /////////////////////////////////////////////////////////////////// 288 //// ports and parameters //// 289 290 /** The output port. */ 291 public TypedIOPort output; 292 293 /** The parameter that is evaluated to produce the output. 294 * Typically, this parameter evaluates an expression involving 295 * the inputs. To refer to parameters in scope within the expression, 296 * use $name or ${name}, where "name" is the name of the parameter. 297 */ 298 public StringParameter expression; 299 300 /** If true (checked), 1x1 matrix results are converted to 301 ScalarTokens instead of a 1x1 MatrixToken, default is 302 <i>true</i>. */ 303 public Parameter get1x1asScalars; 304 305 /** If true, all double-valued matrix results are checked to see if 306 all elements represent integers, and if so, an IntMatrixToken is 307 returned, default is <i>false</i> for performance reasons. */ 308 public Parameter getIntegerMatrices; 309 310 /** If true, clear variables and globals before each execution. */ 311 public Parameter clearEnvironment; 312 313 /////////////////////////////////////////////////////////////////// 314 //// public methods //// 315 316 /** Clone the actor into the specified workspace. This calls the 317 * base class and then sets the <code>iteration</code> 318 * public member to the parameters of the new actor. 319 * @param workspace The workspace for the new object. 320 * @return A new actor. 321 * @exception CloneNotSupportedException If a derived class contains 322 * an attribute that cannot be cloned. 323 */ 324 @Override 325 public Object clone(Workspace workspace) throws CloneNotSupportedException { 326 Expression newObject = (Expression) super.clone(workspace); 327 328 newObject._addPathCommand = null; 329 newObject._iteration = (Variable) newObject.getAttribute("_iteration"); 330 newObject._iterationCount = 1; 331 newObject._previousPath = null; 332 newObject._inputTokens = new HashMap<String, Token>(); 333 return newObject; 334 } 335 336 /** Open a matlab engine. 337 * @exception IllegalActionException If matlab engine not found. 338 */ 339 @Override 340 public void preinitialize() throws IllegalActionException { 341 super.preinitialize(); 342 _initializeEngine(); 343 } 344 345 /** Initialize the iteration count to 1. 346 * @exception IllegalActionException If the parent class throws it. 347 */ 348 @Override 349 public void initialize() throws IllegalActionException { 350 super.initialize(); 351 352 // Check to make sure that the engine has been initialized. 353 synchronized (Engine.semaphore) { 354 if (engine == null) { 355 _initializeEngine(); 356 } 357 } 358 359 _iterationCount = 1; 360 _iteration.setToken(new IntToken(_iterationCount)); 361 362 // Process any additional directories to be added to matlab's 363 // path. The list may contain paths relative to the directory in 364 // which ptolemy was started or any directory listed in the current 365 // classpath (in this order, first match wins). See 366 // UtilityFunctions.findFile() 367 _addPathCommand = null; // Assume none 368 _previousPath = null; 369 370 Parameter packageDirectories = (Parameter) getAttribute( 371 "packageDirectories"); 372 373 if (packageDirectories != null) { 374 StringTokenizer dirs = new StringTokenizer( 375 ((StringToken) packageDirectories.getToken()).stringValue(), 376 ","); 377 StringBuffer cellFormat = new StringBuffer(512); 378 cellFormat.append("{"); 379 380 if (dirs.hasMoreTokens()) { 381 cellFormat.append("'" 382 + UtilityFunctions.findFile(dirs.nextToken()) + "'"); 383 } 384 385 while (dirs.hasMoreTokens()) { 386 cellFormat.append(",'" 387 + UtilityFunctions.findFile(dirs.nextToken()) + "'"); 388 } 389 390 cellFormat.append("}"); 391 392 if (cellFormat.length() > 2) { 393 _addPathCommand = "addedPath_ = " + cellFormat.toString() 394 + ";addpath(addedPath_{:});"; 395 396 synchronized (Engine.semaphore) { 397 matlabEngine.evalString(engine, "previousPath_=path"); 398 _previousPath = matlabEngine.get(engine, "previousPath_"); 399 } 400 } 401 } 402 403 _dataParameters.getScalarMatrices = ((BooleanToken) get1x1asScalars 404 .getToken()).booleanValue(); 405 _dataParameters.getIntMatrices = ((BooleanToken) getIntegerMatrices 406 .getToken()).booleanValue(); 407 } 408 409 /** Return true if all input ports have at least one token. 410 * @return True if this actor is ready for firing, false otherwise. 411 * @exception IllegalActionException Not thrown in this base class. 412 */ 413 @Override 414 public boolean prefire() throws IllegalActionException { 415 Iterator inputPorts = inputPortList().iterator(); 416 417 while (inputPorts.hasNext()) { 418 IOPort port = (IOPort) inputPorts.next(); 419 420 if (!port.hasToken(0)) { 421 return false; 422 } 423 } 424 425 return super.prefire(); 426 } 427 428 /** Evaluate the expression and send its result to the output. 429 * @exception IllegalActionException If the evaluation of the expression 430 * triggers it, or the evaluation yields a null result, or the evaluation 431 * yields an incompatible type, or if there is no director. 432 */ 433 @Override 434 public void fire() throws IllegalActionException { 435 super.fire(); 436 Director director = getDirector(); 437 438 if (director == null) { 439 throw new IllegalActionException(this, "No director!"); 440 } 441 442 boolean clearEnvironmentValue = ((BooleanToken) clearEnvironment 443 .getToken()).booleanValue(); 444 445 try { 446 447 // Read the input ports before acquiring the engine lock since 448 // get() may block depending on the director, e.g., PN. 449 for (TypedIOPort port : inputPortList()) { 450 _inputTokens.put(port.getName(), port.get(0)); 451 } 452 453 synchronized (Engine.semaphore) { 454 455 if (clearEnvironmentValue) { 456 // The following clears variables, but preserves any 457 // persistent storage created by a function (this usually 458 // for speed-up purposes to avoid recalculation on every 459 // function call) 460 matlabEngine.evalString(engine, 461 "clear variables;clear globals"); 462 } 463 464 if (_addPathCommand != null) { 465 matlabEngine.evalString(engine, _addPathCommand); 466 } 467 468 try { 469 matlabEngine.put(engine, "time", new DoubleToken( 470 director.getModelTime().getDoubleValue())); 471 } catch (IllegalActionException ex) { 472 throw new IllegalActionException(this, ex, 473 "Failed to set the \"time\" variable in the Matlab " 474 + "engine to " + new DoubleToken(director 475 .getModelTime().getDoubleValue())); 476 } 477 try { 478 matlabEngine.put(engine, "iteration", 479 _iteration.getToken()); 480 } catch (IllegalActionException ex) { 481 throw new IllegalActionException(this, ex, 482 "Failed to set the \"iteration\" variable in the Matlab " 483 + "engine to " + _iteration.getToken()); 484 } 485 486 for (Map.Entry<String, Token> entry : _inputTokens.entrySet()) { 487 matlabEngine.put(engine, entry.getKey(), entry.getValue()); 488 } 489 490 matlabEngine.evalString(engine, expression.stringValue()); 491 492 Iterator outputPorts = outputPortList().iterator(); 493 494 while (outputPorts.hasNext()) { 495 IOPort port = (IOPort) outputPorts.next(); 496 497 // FIXME: Handle multiports 498 if (port.isOutsideConnected()) { 499 port.send(0, matlabEngine.get(engine, port.getName(), 500 _dataParameters)); 501 } 502 } 503 504 // Restore previous path if path was modified above 505 if (_previousPath != null) { 506 matlabEngine.put(engine, "previousPath_", _previousPath); 507 matlabEngine.evalString(engine, "path(previousPath_);"); 508 } 509 } 510 } finally { 511 // Remove references to any tokens that were read from input ports. 512 _inputTokens.clear(); 513 } 514 } 515 516 /** Increment the iteration count. 517 * @exception IllegalActionException If the superclass throws it. 518 */ 519 @Override 520 public boolean postfire() throws IllegalActionException { 521 _iterationCount++; 522 _iteration.setToken(new IntToken(_iterationCount)); 523 524 // This actor never requests termination. 525 return super.postfire(); 526 } 527 528 /** Close matlab engine if it was open. 529 * @exception IllegalActionException Not thrown in this base class. 530 */ 531 @Override 532 public void wrapup() throws IllegalActionException { 533 super.wrapup(); 534 535 synchronized (Engine.semaphore) { 536 if (matlabEngine != null) { 537 matlabEngine.close(engine); 538 } 539 } 540 541 engine = null; 542 } 543 544 /////////////////////////////////////////////////////////////////// 545 //// protected methods //// 546 547 /** Default type constraints do not apply in this case, since the input 548 * type may be totally unrelated to the output type and cannot be 549 * inferred; return null. 550 * @return null 551 */ 552 @Override 553 protected Set<Inequality> _defaultTypeConstraints() { 554 return null; 555 } 556 557 /////////////////////////////////////////////////////////////////// 558 //// private methods //// 559 560 /** Initialize the Matlab Engine. 561 * @exception IllegalActionException If the connection to the 562 * Matlab engine cannot be intialized. 563 */ 564 private void _initializeEngine() throws IllegalActionException { 565 synchronized (Engine.semaphore) { 566 // The intialization used to occur in preinitialize(), but this 567 // meant that the Matlab Expression actor could not be used 568 // in a RunComposite because RunComposite invokes _executeInsideModel() 569 // which does not invoke preinitialize(). If _executeInsideModel() 570 // invokes preinitialize(), then the PortParameters of the RunComposite 571 // are constantly reset to the value of the _persistentExpression. 572 try { 573 matlabEngine = new Engine(); 574 } catch (Throwable throwable) { 575 // LinkageError is and Error, not an exceptoin 576 throw new IllegalActionException(this, throwable, 577 "There was a problem invoking the Ptolemy II Matlab " 578 + "interface.\nThe interface has been tested under " 579 + "Linux, Mac OS X, and Windows.\n" 580 + "The interface requires that Matlab be installed " 581 + "on the local machine and that the ptmatlab " 582 + "shared library available.\n" 583 + "* Under Linux, you must have the LD_LIBRARY_PATH " 584 + "environment variable set to include the directories " 585 + "that contain libmx.so and libptmatlab.so.\n" 586 + "* Under Mac OS X, you must have the DYLD_LIBRARY_PATH " 587 + "environment variable set to include the directories " 588 + "that contain libmx.dylib and libptmatlab.jnilib.\n" 589 + "* Under Windows, you must have your PATH set to include " 590 + "the Matlab bin/win32 or equivalent directory so that " 591 + "libmex.dll is found and the directory that contains " 592 + "libptmatlab.dll. " 593 + "In addition, if you are running under Windows from " 594 + "the Cygwin bash prompt, then you must start Vergil with " 595 + "the -jni argument: $PTII/bin/vergil -jni. For details, " 596 + "see $PTII/jni/package.html.\n" 597 + "Refer to $PTII/ptolemy/matlab/makefile for more " 598 + "information."); 599 } 600 601 // First set default debugging level, then check for more 602 matlabEngine.setDebugging((byte) 0); 603 604 Parameter debugging = (Parameter) getAttribute("_debugging"); 605 606 if (debugging != null) { 607 Token t = debugging.getToken(); 608 609 if (t instanceof IntToken) { 610 matlabEngine.setDebugging((byte) ((IntToken) t).intValue()); 611 } 612 } 613 614 engine = matlabEngine.open(); 615 } 616 } 617 618 private transient Engine matlabEngine = null; 619 620 long[] engine = null; 621 622 private Variable _iteration; 623 624 private int _iterationCount = 1; 625 626 private String _addPathCommand = null; 627 628 private Token _previousPath = null; 629 630 private transient ConversionParameters _dataParameters; 631 632 /** A map of input port names to tokens. */ 633 private Map<String, Token> _inputTokens = new HashMap<String, Token>(); 634}