Я просмотрел код, и я не думаю, что весь README файл и его документация соответствуют тому, что на самом деле реализовано. По большей части он скопирован из исходного проекта mlabwrap
.
Это сбивает с толку, потому что mlabwrap
реализован с использованием модуля расширения C для взаимодействия с API MATLAB Engine. Однако код mlab
, похоже, заменил эту часть чистой реализацией Python в качестве бэкэнда MATLAB-bridge. Источник: "Dana Pe'er Lab. " и использует два разных метода взаимодействия с MATLAB в зависимости от платформы (COM/ActiveX в Windows и каналы в Linux/Mac).
Теперь, когда мы понимаем, как реализован бэкенд, можно приступить к рассмотрению ошибки импорта.
Примечание: часть кода для Linux/Mac пытается найти исполняемый файл MATLAB в некоторых жестко закодированных фиксированных местах и позволяет выбирать между различными версиями.
Однако вы работаете в Windows, и код на самом деле не реализует какой-либо способ выбора между выпусками MATLAB для этой платформы (поэтому все методы, такие как discover_location
и find_available_releases
, бесполезны в Windows). В итоге COM-объект создается как а>:
self.client = win32com.client.Dispatch('matlab.application')
Как объяснено здесь, ProgID matlab.application
не зависит от версии и будет просто использовать то, что было зарегистрирован как сервер MATLAB COM по умолчанию. Мы можем явно указать, какую версию MATLAB мы хотим (при условии, что у вас несколько установок), например, matlab.application.8.3
выберет MATLAB R2014a.
Таким образом, чтобы исправить код, IMO самым простым способом было бы избавиться от всей этой логики о нескольких версиях MATLAB (в часть кода для Windows), и просто создайте COM-объект MATLAB как есть. Я не пробовал, но не думаю, что это слишком сложно... Удачи!
РЕДАКТИРОВАТЬ:
Я загружаю модуль, и мне удалось заставить его работать в Windows (я использую Python 2.7.6 и MATLAB R2014a). Вот изменения:
$ git diff
diff --git a/src/mlab/matlabcom.py b/src/mlab/matlabcom.py
index 93f075c..da1c6fa 100644
--- a/src/mlab/matlabcom.py
+++ b/src/mlab/matlabcom.py
@@ -21,6 +21,11 @@ except:
print 'win32com in missing, please install it'
raise
+def find_available_releases():
+ # report we have all versions
+ return [('R%d%s' % (y,v), '')
+ for y in range(2006,2015) for v in ('a','b')]
+
def discover_location(matlab_release):
pass
@@ -62,7 +67,7 @@ class MatlabCom(object):
"""
self._check_open()
try:
- self.eval('quit();')
+ pass #self.eval('quit();')
except:
pass
del self.client
diff --git a/src/mlab/mlabraw.py b/src/mlab/mlabraw.py
index 3471362..16e0e2b 100644
--- a/src/mlab/mlabraw.py
+++ b/src/mlab/mlabraw.py
@@ -42,6 +42,7 @@ def open():
if is_win:
ret = MatlabConnection()
ret.open()
+ return ret
else:
if settings.MATLAB_PATH != 'guess':
matlab_path = settings.MATLAB_PATH + '/bin/matlab'
diff --git a/src/mlab/releases.py b/src/mlab/releases.py
index d792b12..9d6cf5d 100644
--- a/src/mlab/releases.py
+++ b/src/mlab/releases.py
@@ -88,7 +88,7 @@ class MatlabVersions(dict):
# Make it a module
sys.modules['mlab.releases.' + matlab_release] = instance
sys.modules['matlab'] = instance
- return MlabWrap()
+ return instance
def pick_latest_release(self):
return get_latest_release(self._available_releases)
Сначала я добавил недостающую функцию find_available_releases
. Я сделал так, чтобы он сообщал, что доступны все версии MATLAB (как я объяснил выше, это не имеет большого значения из-за способа создания COM-объекта). Еще лучшим решением было бы обнаружение установленных/зарегистрированных версий MATLAB с помощью реестра Windows (проверьте ключи HKCR\Matlab.Application.X.Y
и следуйте их CLSID в HKCR\CLSID
). Таким образом, вы действительно можете выбирать, какую версию запускать.
Я также исправил две несвязанные ошибки (в одной автор забыл возвращаемое значение функции, а в другой дважды создавался объект-оболочка без необходимости).
Примечание. Во время тестирования может быть быстрее НЕ запускать/закрывать экземпляр MATLAB каждый раз, когда вызывается скрипт. Вот почему я прокомментировал self.eval('quit();')
в функции close
. Таким образом, вы можете запустить MATLAB, используя matlab.exe -automation
(выполните это только один раз), а затем повторно использовать сеанс, не закрывая его. Просто убейте процесс, когда закончите :)
Вот пример Python для тестирования модуля (я также показываю сравнение с NumPy/SciPy/Matplotlib):
test_mlab.py
# could be anything from: latest_release, R2014b, ..., R2006a
# makes no difference :)
from mlab.releases import R2014a as matlab
# show MATLAB version
print "MATLAB version: ", matlab.version()
print matlab.matlabroot()
# compute SVD of a NumPy array
import numpy as np
A = np.random.rand(5, 5)
U, S, V = matlab.svd(A, nout=3)
print "S = \n", matlab.diag(S)
# compare MATLAB's SVD against Scipy's SVD
U, S, V = np.linalg.svd(A)
print S
# 3d plot in MATLAB
X, Y, Z = matlab.peaks(nout=3)
matlab.figure(1)
matlab.surf(X, Y, Z)
matlab.title('Peaks')
matlab.xlabel('X')
matlab.ylabel('Y')
matlab.zlabel('Z')
# compare against matplotlib surface plot
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='jet')
ax.view_init(30.0, 232.5)
plt.title('Peaks')
plt.xlabel('X')
plt.ylabel('Y')
ax.set_zlabel('Z')
plt.show()
Вот что я получаю:
C:\>python test_mlab.py
MATLAB version: 8.3.0.532 (R2014a)
C:\Program Files\MATLAB\R2014a
S =
[[ 2.41632007]
[ 0.78527851]
[ 0.44582117]
[ 0.29086795]
[ 0.00552422]]
[ 2.41632007 0.78527851 0.44582117 0.29086795 0.00552422]
РЕДАКТИРОВАТЬ2:
Указанные выше изменения были приняты и объединены в mlab
.
person
Amro
schedule
15.07.2014