ちょっとpythonのコードを試したり、電卓代わりに使ったり、そういうときは、pythonのインタラクティブシェルをよく使います。でも、forループやちょっと関数定義してみたりしたときには、やり直すのが面倒だなと思いながらも、テキストエディタでスクリプトファイルを書いては、コマンドラインから実行していました。
そうこうしているうちに、エディタで書きつつ、その一部を実行してみたりしたいなと思ったしだいです。Mac OS 8.6を使っていたときには、pythonではないですが、そんな感じのメモ帳があってしばしば利用して便利だった覚えがありましたし、SqueakのWorkspaceで遊んでいると、あらためてエディタから、コードを実行できるといいなと思いました。
そこでpythonでも、ちょっとしたエディタを書いてみました。選択したテキストをexecや、eval()に渡すだけというものですが、使ってみると便利ですね。GUIにはいつもwxPythonを利用していますが、今回は、pythonをインストールしたら利用できるTkinterを使いました。pythonのTurtle graphicsで遊ぶときにも、こういうエディタは便利かと思います。
2014年4月8日火曜日
2014年1月31日金曜日
matplotlibのMultiCursor
matplotlibは、wxPythonと簡単に組み合わせて利用できて便利ですね。
matplotlibのグラフ上にマウスカーソルに合わせて動く十字のカーソルを表示するMultiCursorというものがありますが、 twinx()してY2軸を利用すると奇妙なことがおこりました。
カーソルは、Y軸に描画されながらも、その表示位置はY2軸上の値になるという状態です。
もちろん、カーソルを描画する対象をY2軸のほうにすると矛盾のない状態にはなります。
そもそもMultiCursorを利用する対象にY2軸を追加するような利用の仕方は、あまりなさそうです。そうはいっても、そのような要求があったため、Y2軸を追加しても、カーソル位置は、Y軸のほうで決まるようにしてみました。
マウス移動のイベントを処理するonmove()に渡されるeventからキャンバス上のx,y座標が得られるので、それを利用してグラフ軸上のデータに焼きなおすようにしました。
使い方はオリジナルのMultiCursorとほぼ同じですが、parentウィンドウを渡すようにして、そちらへ座標を通知するイベントをポストしています。parentウィンドウでそのイベントを拾えば、カーソル移動にあわせて座標位置を表示できます。
matplotlibのグラフ上にマウスカーソルに合わせて動く十字のカーソルを表示するMultiCursorというものがありますが、 twinx()してY2軸を利用すると奇妙なことがおこりました。
カーソルは、Y軸に描画されながらも、その表示位置はY2軸上の値になるという状態です。
もちろん、カーソルを描画する対象をY2軸のほうにすると矛盾のない状態にはなります。
そもそもMultiCursorを利用する対象にY2軸を追加するような利用の仕方は、あまりなさそうです。そうはいっても、そのような要求があったため、Y2軸を追加しても、カーソル位置は、Y軸のほうで決まるようにしてみました。
マウス移動のイベントを処理するonmove()に渡されるeventからキャンバス上のx,y座標が得られるので、それを利用してグラフ軸上のデータに焼きなおすようにしました。
使い方はオリジナルのMultiCursorとほぼ同じですが、parentウィンドウを渡すようにして、そちらへ座標を通知するイベントをポストしています。parentウィンドウでそのイベントを拾えば、カーソル移動にあわせて座標位置を表示できます。
from matplotlib.widgets import MultiCursor
import wx
import wx.lib.newevent
class MyMultiCursor(MultiCursor):
def __init__(self, parent, canvas, axes, color='r', lw=1,
useblit = True, horizOn=True, vertOn=True):
if matplotlib.__version__ >= '1.3.0':
MultiCursor.__init__(self, canvas, axes, color=color,
lw=lw, useblit=useblit, horizOn=horizOn, vertOn=vertOn)
else:
MultiCursor.__init__(self, canvas, axes, color=color, lw=lw, useblit=useblit)
# Produce New Event for Cursor Move Notification to parent window.
self.parent = parent
self.CursorMoveEvent, self.EVT_CURSOR_MOVE = wx.lib.newevent.NewEvent()
self.visible = False
def xydata(self, x, y):
#make new xdata, ydata
cwidth, cheight = self.canvas.GetSize()
target = None
for ax in self.axes:
#find the axes in which the mouse cursor is.
bbox = ax.get_position()
[[left,bottom], [right, top]] = bbox.get_points()
xc = (x+1)/float(cwidth)
yc = y/float(cheight)
if ((left < xc) and (xc < right) and
(bottom < yc) and (yc < top)):
target = ax
break
if not target:
# if there is no target
return (None, None)
width = right-left
height =top-bottom
xmin, xmax = ax.get_xlim()
ymin, ymax = ax.get_ylim()
xdata = xmin + (xc - left) * (xmax - xmin)/width
ydata = ymin + (yc - bottom) * (ymax - ymin)/height
return (xdata, ydata)
def onmove(self, event):
event.xdata, event.ydata = self.xydata(event.x, event.y)
MultiCursor.onmove(self, event)
#make event data
evt = self.CursorMoveEvent(pos = (event.xdata, event.ydata))
#post event to parent window
wx.PostEvent(self.parent, evt)
self.visible = True
2014年1月27日月曜日
matplotlibでorthogonal projectionの3D plot
グラフを作るのに、gnuplotもよいけど、pythonからmatplotlibを使うのももよいですよね。
下の図は、matplotlibで3次元プロットした例ですが、遠近感(perspective effect)が観られます。
しばしば、そのような遠近感の効果をなくして3次元プロットしてみたいという要求があります。
言い換えると、透視投影(perspective projection)から平行投影(orthogonal projection)に変更したいわけです。調べてみたところ、mpl_toolkits.mplot3dの中のproj3dにあるpersp_transformation関数を書き換えればよいということです。
ということで、以下のようにしてみました。
下の図は、matplotlibで3次元プロットした例ですが、遠近感(perspective effect)が観られます。
しばしば、そのような遠近感の効果をなくして3次元プロットしてみたいという要求があります。
言い換えると、透視投影(perspective projection)から平行投影(orthogonal projection)に変更したいわけです。調べてみたところ、mpl_toolkits.mplot3dの中のproj3dにあるpersp_transformation関数を書き換えればよいということです。
ということで、以下のようにしてみました。
#!/usr/bin/env python
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy
#--------- Patch for Orthogonal Projection of 3Dplot ------
from mpl_toolkits.mplot3d import proj3d
def orthogonal_transformation(zfront, zback):
a = 2/(zfront-zback)
b = -1*(zfront+zback)/(zfront-zback)
c = zback
return numpy.array([[1,0,0,0],
[0,1,0,0],
[0,0,a,b],
[0,0,0,c]])
proj3d.persp_transformation = orthogonal_transformation
#-----------------------------------------------------
#---------- make canvas for figure -------------
fig = plt.figure(figsize=(6, 6), facecolor='w')
#---------- 3D Plot ----------------
ax = fig.add_subplot(111, projection='3d', axisbg='w')
# making sample data
x = numpy.arange(-3, 3, 0.25)
y = numpy.arange(-3, 3, 0.25)
xm, ym = numpy.meshgrid(x, y)
z = numpy.exp(-1*xm**2) * numpy.exp(-1*ym**2)
# draw x, y, z labels
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
# plot 3d
surf = ax.plot_surface(xm, ym, z, rstride=1, cstride=1,
linewidth=1, antialiased=True)
# set view point
ax.view_init(elev=30, azim=-45)
# display the figures
plt.show()
このスクリプトでプロットすると、下のようになりました。2014年1月24日金曜日
WindowsでGraffiti入力っぽいキーボードを修正してみた
Cの関数をPythonから呼び出す方法を使って、例のGraffitiっぽい入力のソフトウェアキーボードをgKeyを修正してみた。
ストロークの判定ルーチンをC言語で書き直して、その部分だけ置き換えてみた。判定用のモジュール内のPythonで書かれた従来関数と同じ名前でラッピングして、モジュール差し替えを行うと、ほとんどいじらずにCルーチンを利用したものができあがる。
pythonでプロトタイプを作って、徐々にCに置き換えていくような作り方もよいかもしれないですね。Cの関数のテストにPythonを使うというのもよさそうです。
ところでgKeyの使用感に違いがあったかというと、pythonのみで作ったものでも十分快適だったので、それほどでもなかった。もともと軽い処理になので、非線形最小二乗フィットほどの効果はないようですね。でも、Cで書いたらもっともっと快適かもという思いに対して、すっきりできた気分。
ストロークの判定ルーチンをC言語で書き直して、その部分だけ置き換えてみた。判定用のモジュール内のPythonで書かれた従来関数と同じ名前でラッピングして、モジュール差し替えを行うと、ほとんどいじらずにCルーチンを利用したものができあがる。
pythonでプロトタイプを作って、徐々にCに置き換えていくような作り方もよいかもしれないですね。Cの関数のテストにPythonを使うというのもよさそうです。
ところでgKeyの使用感に違いがあったかというと、pythonのみで作ったものでも十分快適だったので、それほどでもなかった。もともと軽い処理になので、非線形最小二乗フィットほどの効果はないようですね。でも、Cで書いたらもっともっと快適かもという思いに対して、すっきりできた気分。
2014年1月20日月曜日
wxPython 3.0を使ってみた
wxPythonのページを見に行ったら、3.0がリリースされていました。これまで、2.8を使っていて、2.9を見送ってしまいました。さっそく、3.0をインストールして使ってみたところ、これまでのスクリプトが動かない部分もちらほら。
これまで、wx.Color()使っていたけど、wx.Colour()になったようで、エラーでとまったり。
これはすぐに修正できましたが、matplotlib1.3.1での動作がいまいち。
以下のスクリプト、python2.7 + wxPython2.8ではちゃんとmatplotlibのFigureCanvasのサイズが設定できていました。
#!/usr/bin/env python
# coding: shift_jis
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import wx
class myFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Matplotlib Test',
style=wx.DEFAULT_FRAME_STYLE)
self.fig = matplotlib.figure.Figure()
ax = self.fig.add_axes([0.2, 0.2, 0.6, 0.6])
ax.plot([0, 1], [0, 1])
self.canvas = FigureCanvas(self, -1, self.fig)
self.canvas.SetSize((1024, 600))
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas, 0, wx.EXPAND|wx.ALL, 0)
self.SetSizer(sizer)
self.Fit()
self.canvas.draw()
print self.canvas.GetSize()
print self.GetClientSize()
if __name__ == '__main__':
app = wx.App(False)
frame = myFrame()
frame.Show()
app.MainLoop()
しかし、wxPython 3.0にしたところ、サイズが変更されません。
これってwxPython 2.9からでしょうか。
しかたがないので、入れ物(FrameとかPanel)のサイズを変更する方法を使うようにしました。
#!/usr/bin/env python
# coding: shift_jis
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import wx
class myFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Matplotlib Test',
style=wx.DEFAULT_FRAME_STYLE)
self.fig = matplotlib.figure.Figure()
ax = self.fig.add_axes([0.2, 0.2, 0.6, 0.6])
ax.plot([0, 1], [0, 1])
self.canvas = FigureCanvas(self, -1, self.fig)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas, 1, wx.EXPAND|wx.ALL, 0)
self.SetSizer(sizer)
self.Fit()
self.canvas.draw()
self.SetClientSize((1024, 600))
print self.canvas.GetSize()
print self.GetClientSize()
if __name__ == '__main__':
app = wx.App(False)
frame = myFrame()
frame.Show()
app.MainLoop()
これまでwxPythonを使ったスクリプトは、動作を確認してそれほど多くの変更が必要ではないことが分かって一安心です。
これまで、wx.Color()使っていたけど、wx.Colour()になったようで、エラーでとまったり。
これはすぐに修正できましたが、matplotlib1.3.1での動作がいまいち。
以下のスクリプト、python2.7 + wxPython2.8ではちゃんとmatplotlibのFigureCanvasのサイズが設定できていました。
#!/usr/bin/env python
# coding: shift_jis
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import wx
class myFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Matplotlib Test',
style=wx.DEFAULT_FRAME_STYLE)
self.fig = matplotlib.figure.Figure()
ax = self.fig.add_axes([0.2, 0.2, 0.6, 0.6])
ax.plot([0, 1], [0, 1])
self.canvas = FigureCanvas(self, -1, self.fig)
self.canvas.SetSize((1024, 600))
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas, 0, wx.EXPAND|wx.ALL, 0)
self.SetSizer(sizer)
self.Fit()
self.canvas.draw()
print self.canvas.GetSize()
print self.GetClientSize()
if __name__ == '__main__':
app = wx.App(False)
frame = myFrame()
frame.Show()
app.MainLoop()
しかし、wxPython 3.0にしたところ、サイズが変更されません。
これってwxPython 2.9からでしょうか。
しかたがないので、入れ物(FrameとかPanel)のサイズを変更する方法を使うようにしました。
#!/usr/bin/env python
# coding: shift_jis
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import wx
class myFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Matplotlib Test',
style=wx.DEFAULT_FRAME_STYLE)
self.fig = matplotlib.figure.Figure()
ax = self.fig.add_axes([0.2, 0.2, 0.6, 0.6])
ax.plot([0, 1], [0, 1])
self.canvas = FigureCanvas(self, -1, self.fig)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas, 1, wx.EXPAND|wx.ALL, 0)
self.SetSizer(sizer)
self.Fit()
self.canvas.draw()
self.SetClientSize((1024, 600))
print self.canvas.GetSize()
print self.GetClientSize()
if __name__ == '__main__':
app = wx.App(False)
frame = myFrame()
frame.Show()
app.MainLoop()
これまでwxPythonを使ったスクリプトは、動作を確認してそれほど多くの変更が必要ではないことが分かって一安心です。
2014年1月17日金曜日
MinGW gcc とctypesモジュールを用いてpythonからc関数を呼び出してみる
Fortranで記述して、f2pyを使うのもよいのですが、Cで記述した関数が手元にあるもので、そちらを使いたいと思ったしだいです。
Python APIを使ったり、SWIGやCythonを利用したりと、いろいろ方法はある様子ですが、ctypesモジュールを利用して、呼び出す方法を試してみました。
コンパイラは、Visual Studioではなくて、MinGWのgccを使います。関数をコンパイルするだけなら、コンソールからちょっとコマンドを打つだけなので、こちらのほうが楽そうです。
簡単なものから順番に試していきたいと思います。
まずは、一つの整数を渡して二倍して返す関数です。
/* doublenumber.c */
#include
int doublenumber(int n)
{
return n * 2;
}
コンパイルします
gcc -Wall -fPIC -c doublenumber.c
windowsでは、-fPICは無視されるとの警告がでました。
どうやらデフォルトでPICオプションが適用される様子です。
オブジェクトファイルdoublenumber.oができました。
共有ライブラリを作成します。
gcc -shared -o doublenumber.so doublenumber.o
共有ライブラリdoublenumber.soファイルができました。
pythonから利用してみようと思います。
import ctypes
mydll = ctypes.CDLL('doublenumber.so')
mydll.doublenumber(5)
10
とちゃんと利用できています。
実数を引数として与えると、ctypes.ArgumentErrorが発生します。
さて、次に実数型を利用してみましょう。
C関数の引数をdouble vにして、同様に二倍した値を返すものにします。
/* doubledouble.c */
#include
double doublenumber(double v)
{
return v * 2.0;
}
コンパイルして、共有ライブラリにします。
gcc -Wall -c doubledouble.c
gcc -shared -o doubledouble.so doubledouble.o
実数を渡してもエラーが出ます。
型をc言語用に変換して、渡します。
mydll.doublenumber(ctypes.c_double(5.3))
1075131187
あれ、エラーは出ませんが、返り値がおかしいですね。
どうやらデフォルトで、関数はc_intを返すと仮定されているようです。
関数オブジェクトのrestype属性を設定するとよいようです。
mydll.doublenumber.restype = ctypes.c_double
mydll.doublenumber(ctypes.c_double(5.3))
10.6
ちゃんと値が得られました。
さて、引数でc_double指定をするのも大変です。
argtypesを設定してみます。
mydll.doublenumber.argtypes = [ctypes.c_double]
mydll.doublenumber(5.3)
10.6
簡単に5.3を渡すことができました。
整数5を渡しても、自動的に変換されるようです。
次は、文字列を渡す関数を試してみます。
/* charcount.c */
#include
int charcount(char *s)
{
int c;
c = 0;
while (s[c] != '\0')
c++;
return c;
}
そういえばstrlen()なんて関数もありましたね。
コンパイルして共有ライブラリを作成します。
gcc -Wall -c charcount.c
gcc -shared -o charcount.so charcount.o
テストするPythonスクリプトは以下の通り
C言語の文字列は、文字配列のポインタになります。
文字型のポインタは、ctypes.c_char_pで指定できます。
import ctypes
mydll = ctypes.CDLL("charcount.so")
mydll.charcount.argtypes = [ctypes.c_char_p]
mydll.charcount.restype = ctypes.c_int
print mydll.charcount("Hello")
実行すると文字列の長さの 5 がプリントされました。
次に、文字列を渡して、それを変更して返すような関数を作ってみます。
/* editstring.c */
#include
#include
char *editstring(char *s)
{
char buff[1024];
sprintf(buff, "*** %s ***", s);
strcpy(s, buff);
return s;
}
バッファ内で文字列を編集して、それを渡された文字列領域にコピーして、
そのポインタを返す関数です。
渡した文字列領域が編集されることになります。
Pythonの文字列は変更できないので、編集のための文字列バッファを用意するらしいです。
Pythonスクリプトは以下の通りです。
import ctypes
mydll = ctypes.CDLL("editstring.so")
mydll.editstring.argtypes = [ctypes.c_char_p]
mydll.editstring.restype = ctypes.c_char_p
s = ctypes.create_string_buffer("Hello", 1024)
result = mydll.editstring(s)
print '[%s]' % result
実行すると、
[*** Hello ***]
と表示され、編集されたのが確認できます。
返り値の型をc_char_pにして受け取ったresultは、
そのまま文字列としてプリントされますが、sはそうはいきません。
print sとすると c_char_arrayのオブジェクトであると表示されます。
その中の文字列をプリントするときは、
print '%s' % s.value
とするとよいようです。
でも、普通にbuffのポインタを返したらよいかな。
/* newstring.c */
#include
char *newstring(char *s)
{
char buff[1024];
sprintf(buff, "*** %s ***", s);
return buff;
}
こちら、コンパイルすると「関数が局所変数のアドレスを返します」
と警告が出ます。それはそうですよね。
この関数を抜けると、このメモリ領域は、解放されてしまいそうですが、、、。
Pythonスクリプトは以下の通り。
import ctypes
mydll = ctypes.CDLL("newstring.so")
mydll.newstring.argtypes = [ctypes.c_char_p]
mydll.newstring.restype = ctypes.c_char_p
string = mydll.newstring("Hello")
print string
ちゃんと*** Hello ***と出力されました。
このような書き方のほうが書きやすいですね。
直接渡した文字列をいじる必要がなければ、create_string_buffer()
は使わなくてもよいのでしょうか。
type(string)すると、となります。
でもちょっとメモリが心配。
Python側で文字列バッファを用意したほうがいいかな。
次は、複数の実数値が入った配列をPythonから渡して、その和を返すようなC関数を試してみます。
/* sumvalues.c */
#include
double sumvalues(double *v, int n)
{
int i;
double sum;
sum = 0.0;
for (i=0; i {
sum = sum + v[i];
printf("%f\n", v[i]);
}
return sum;
}
配列の長さはCの関数から分かりませんので、その長さも渡すようにしています。
コンパイルして、共有ライブラリを作ります。
gcc -c sumvalues.c
gcc -shared -o sumvalues.so sumvalues.o
Pythonスクリプトは以下の通り
import ctypes
mydll = ctypes.CDLL("sumvalues.so")
mydll.sumvalues.restype = ctypes.c_double
n = 10
nvalues = ctypes.c_double * n
vlist = nvalues(*[1.0+i*1.0 for i in range(n)])
print vlist, len(vlist)
v = mydll.sumvalues(vlist, ctypes.c_int(n))
print v
共有ライブラリをを呼び出すところと、返り値を指定するのは同じです。
配列を使うときは、まず長さ分の型を作ります。
nvaluesという型で、長さがnのctypes.cdoubleの型を作ります。
その型でvlistというn個の実数値が配列に入ったものを作成します。
len()を用いてvlistの長さを調べることができます。
vlistは、c_double_Array_10オブジェクトになっています。
vlistは、ctypesの型になっていますので、あらためてargtypesで設定する必要もありません。長さだけ、ctypes.c_int()の型にして渡します。
1から10までの足し算をすることができました。
実際に利用するときは、Pythonの関数でラッピングするとよいかと思いました。
そのように書いたPythonスクリプトは以下の通りです。
import ctypes
mydll = ctypes.CDLL("sumvalues.so")
mydll.sumvalues.restype = ctypes.c_double
def sumvalues(vlist):
n = len(vlist)
nvalues = ctypes.c_double * n
arg1 = nvalues(*vlist)
v = mydll.sumvalues(arg1, ctypes.c_int(n))
return v
if __name__ == '__main__':
vlist = [1.0+i*1.0 for i in range(10)]
v = sumvalues(vlist)
print v
次は、複数の値を返してもらう関数を書いてみます。
関数は、基本的に一つの値しか返しません。
ですので、引数に値を入れてもらうための変数(へのポインタ)を渡すことにします。
ソースファイル
/* summean.c */
#include
int summean(double *v, int n, double *sum, double *mean)
{
int i;
double s;
s = 0.0;
for (i=0; i {
s = s + v[i];
}
*sum = s;
*mean = s/n;
return 0;
}
コンパイルして共有ライブラリを作成します。
gcc -c summean.c
gcc -shared -o summean.so summean.o
Pythonスクリプトは以下の通り
import ctypes
mydll = ctypes.CDLL("summean.so")
def summean(vs):
n = len(vs)
nvalues = ctypes.c_double * n
vlist = nvalues(*vs)
s = ctypes.c_double(0.0)
m = ctypes.c_double(0.0)
mydll.summean(vlist, ctypes.c_int(n), ctypes.pointer(s), ctypes.pointer(m))
return (s.value, m.value)
if __name__ == '__main__':
vs = [1.0+i*1.0 for i in range(10)]
s, m = summean(vs)
print s, m
前と同様にPythonスクリプトでsummean関数としてラッピングしました。
結果を保存する変数sおよびmをc_double(0.0)で用意します。
関数summeanには、そのポインタを渡す必要があるため、ctypes.pointer()関数を利用しています。
Pythonの関数の返り値として、s.valueおよびm.valueをタプルにして返します。
つぎは、いよいよ構造体です。まずは、シンプルな構造体を渡して、その内容を参照した計算結果が返ってくる関数を作ってみたいと思います。
ここでは、四角の左、右、下、上の座標を格納する構造体です。
ソースファイル
/* squarearea.c *\
#include
typedef struct {
double left;
double right;
double bottom;
double top;
} SQUARE;
double squarearea(SQUARE sq)
{
double area;
double width;
double height;
width = sq.right - sq.left;
height = sq.top - sq.bottom;
area = width * height;
return area;
}
コンパイルして、共有ライブラリを作成します。
gcc -c squarearea.c
gcc -shared -o squarearea.so squarearea.o
次に、Pythonスクリプトです。
Pythonスクリプト側で構造体を取り扱うためには、ctypes.Structureを継承したクラスを作ります。
そのクラスに、_fields_属性を設定することで、Cの構造体と一致させるということです。
_fields_属性は、フィールド名 と フィールド型 を持つ 2要素タプル のリストです。
ctypes.Structureで定義されているコンストラクタが、このフィールドを参照して、初期化するようです。
Pythonスクリプトは、以下のようになりました。
import ctypes
mydll = ctypes.CDLL("squarearea.so")
class SQUARE(ctypes.Structure):
_fields_ = [('left', ctypes.c_double),
('right', ctypes.c_double),
('bottom', ctypes.c_double),
('top', ctypes.c_double)]
if __name__ == '__main__':
sq = SQUARE(0.3, 0.8, 0.4, 3.4)
mydll.squarearea.restype = ctypes.c_double
v = mydll.squarearea(sq)
print v
幅0.5、高さ3ですので、1.5が返ってきます。
返り値の型を設定するのを忘れないようにしましょう。
C言語で返り値として構造体を使うと、複数の値を返すことができて便利ですよね。
先ほどの関数で、高さを1/2したものを返すようにしてみましょう。
ソースファイル
/* squarehalf.c */
#include
typedef struct {
double left;
double right;
double bottom;
double top;
} SQUARE;
SQUARE squarehalf(SQUARE sq)
{
double area;
double width;
double height;
SQUARE hsq;
hsq = sq;
height = sq.top - sq.bottom;
hsq.top = hsq.bottom + height/2.0;
return hsq;
}
hsqにsqを入れて、そのtopの値を、半分の高さになるように設定しなおしています。
コンパイルして、共有ライブラリを作ります。
gcc -c squarehalf.c
gcc -shared -o squarehalf.so squarehalf.o
Pythonスクリプト
import ctypes
mydll = ctypes.CDLL("squarehalf.so")
class SQUARE(ctypes.Structure):
_fields_ = [('left', ctypes.c_double),
('right', ctypes.c_double),
('bottom', ctypes.c_double),
('top', ctypes.c_double)]
if __name__ == '__main__':
sq = SQUARE(0.3, 0.8, 0.4, 3.4)
v = SQUARE()
mydll.squarehalf.restype = SQUARE
v = mydll.squarehalf(sq)
print sq.left, sq.right, sq.bottom, sq.top
print v.left, v.right, v.bottom, v.top
返り値をSQUAREにすることと、返り値を入れる変数vをSQUARE()クラスのインスタンスにしただけです。
0.3 0.8 0.4 3.4
0.3 0.8 0.4 1.9
と出力され、半分の高さの四角を表すデータになりました。
構造体の中に、別の構造体がある場合はどう書けるのでしょうか。
先ほど面積を求めた四角を、左下、右上の座標データPOINTで表してみます。
/* squarearea2.c */
#include
typedef struct {
double x;
double y;
} POINT;
typedef struct {
POINT leftbottom;
POINT righttop;
} SQUARE;
double squarearea(SQUARE sq)
{
double area;
double width;
double height;
width = sq.righttop.x - sq.leftbottom.x;
height = sq.righttop.y - sq.leftbottom.y;
area = width * height;
return area;
}
コンパイルして共有ライブラリにします。
gcc -c squarearea2.c
gcc -shared -o squarearea2.so squarearea2.o
Pythonスクリプトは以下のようになりました。
import ctypes
mydll = ctypes.CDLL("squarearea2.so")
class POINT(ctypes.Structure):
_fields_ = [('x', ctypes.c_double),
('y', ctypes.c_double)]
class SQUARE(ctypes.Structure):
_fields_ = [('leftbottom', POINT),
('righttop', POINT)]
if __name__ == '__main__':
sq = SQUARE(POINT(0.3, 0.4), POINT(0.8, 3.4))
v = SQUARE()
mydll.squarearea.restype = ctypes.c_double
v = mydll.squarearea(sq)
print v
それぞれ対応するクラスを書いただけで、意外なところはないですね。
ただ、クラス定義する順番で、POINTをSQUAREの後で行うと、
SQUAREで利用しているPOINTが定義できないというエラーが起こります。
構造体の定義では、その中に自分自身をもつものもありますね。
再帰的な構造は、中に同じ自分自身の型へのポインタを入れたりします。
不完全型と呼ばれているようです。
簡単のため、
(v1, (v2, (v3, (v4, (v5, NULL)))))
のようなリストに似た形のデータを考えてみます。
ソースファイル
/* showlist.c */
#include
struct CELL {
int value;
struct CELL *next;
};
int showlist(struct CELL *c, int flg)
{
printf("(%d, ", c->value);
if ((struct CELL *)NULL != c->next)
showlist(c->next, 0);
else
printf("NULL");
if (1 == flg)
printf(")\n");
else
printf(")");
return 0;
}
CELLという型の定義の中に、CELLへのポインタが含まれています。
前の例のように、typedef struct { ... } CELL; のような書き方をすると、コンパイル時にエラーがでます。使われるより前の方に、CELLというワードが入るような記述をする必要があるということです。
showlistは、再帰的に呼び出される関数で、渡されたCELLの値を出力したのちに、続くCELLの描画を行うため、showlistを呼び出します。nextに、NULLポインタが入っていれば、そこで終了です。
flgは、最初に呼び出すときに1をセットすると、それ以降とを区別することができます。
コンパイルして、共有ライブラリにします。
gcc -c showlist.c
gcc -shared -o showlist.so sholist.o
このような不完全な構造体定義の場合、Pythonスクリプトは、次のようにするようです。
import ctypes
mydll = ctypes.CDLL("showlist.so")
class CELL(ctypes.Structure):
pass
CELL._fields_ = [('value', ctypes.c_int),
('next', ctypes.POINTER(CELL))]
if __name__ == '__main__':
c = CELL(0, None)
for i in range(5):
c = CELL((i+1), ctypes.pointer(c))
mydll.showlist(ctypes.pointer(c), ctypes.c_int(1))
クラスCELLの定義では、なにも行わずに、あとから改めて_fields_属性を設定するようです。
ctypes.POINTER(CELL)で、CELLへのポインタ型という指定ができます。
実際に利用するときに、CELL型のcというもののポインタは、ctypes.pointer(c)で得ます。紛らわしいですね。
Pythonスクリプトでcの値を設定していき、showlistにcへのポインタと整数1を渡すと、
(5, (4, (3, (2, (1, (0, NULL))))))
と表示されます。この表示は、C関数内で行われたものです。
このようにctypesを使って共有ライブラリを呼び出す方法だと、CのソースファイルにPythonで利用するという配慮をせずに、Pythonから呼び出すことができました。
Pythonスクリプト側で、ちょっと使いやすいように包んであげれば呼び出しやすくなるかと思います。
f2pyを使ってFortranプログラムで計算するのもいいのですが、すでにCの関数を作っているようなら、この方法は便利ですね。
ということで、自作のガウス分布をフィットするルーチンをPythonから呼び出してみました。速度の比較のために、Pythonスクリプトでも書いてみました。numpyを利用せずに、Cのソースをほぼ1対1に直したものです。
#--- C func ---
#1.02713 0.0241351
#4.93666 0.0580069
#-0.938185 0.023901
#2.49769 0.0360503
# time_c = 0.000507835 s
#--- Python func ---
#1.02713 0.0241351
#4.93666 0.0580069
#-0.938185 0.023901
#2.49769 0.0360503
# time_py = 0.00944325 s
#-------------------
# time_py/time_c = 18.5951
#-------------------
200点のデータをフィットしました。やっぱりCで記述されたものは早いですね。
Pythonスクリプトの方は、numpyの機能を利用して実装すると、どこまで速くなるのでしょうか。
Python APIを使ったり、SWIGやCythonを利用したりと、いろいろ方法はある様子ですが、ctypesモジュールを利用して、呼び出す方法を試してみました。
コンパイラは、Visual Studioではなくて、MinGWのgccを使います。関数をコンパイルするだけなら、コンソールからちょっとコマンドを打つだけなので、こちらのほうが楽そうです。
簡単なものから順番に試していきたいと思います。
まずは、一つの整数を渡して二倍して返す関数です。
/* doublenumber.c */
#include
int doublenumber(int n)
{
return n * 2;
}
コンパイルします
gcc -Wall -fPIC -c doublenumber.c
windowsでは、-fPICは無視されるとの警告がでました。
どうやらデフォルトでPICオプションが適用される様子です。
オブジェクトファイルdoublenumber.oができました。
共有ライブラリを作成します。
gcc -shared -o doublenumber.so doublenumber.o
共有ライブラリdoublenumber.soファイルができました。
pythonから利用してみようと思います。
import ctypes
mydll = ctypes.CDLL('doublenumber.so')
mydll.doublenumber(5)
10
とちゃんと利用できています。
実数を引数として与えると、ctypes.ArgumentErrorが発生します。
さて、次に実数型を利用してみましょう。
C関数の引数をdouble vにして、同様に二倍した値を返すものにします。
/* doubledouble.c */
#include
double doublenumber(double v)
{
return v * 2.0;
}
コンパイルして、共有ライブラリにします。
gcc -Wall -c doubledouble.c
gcc -shared -o doubledouble.so doubledouble.o
実数を渡してもエラーが出ます。
型をc言語用に変換して、渡します。
mydll.doublenumber(ctypes.c_double(5.3))
1075131187
あれ、エラーは出ませんが、返り値がおかしいですね。
どうやらデフォルトで、関数はc_intを返すと仮定されているようです。
関数オブジェクトのrestype属性を設定するとよいようです。
mydll.doublenumber.restype = ctypes.c_double
mydll.doublenumber(ctypes.c_double(5.3))
10.6
ちゃんと値が得られました。
さて、引数でc_double指定をするのも大変です。
argtypesを設定してみます。
mydll.doublenumber.argtypes = [ctypes.c_double]
mydll.doublenumber(5.3)
10.6
簡単に5.3を渡すことができました。
整数5を渡しても、自動的に変換されるようです。
次は、文字列を渡す関数を試してみます。
/* charcount.c */
#include
int charcount(char *s)
{
int c;
c = 0;
while (s[c] != '\0')
c++;
return c;
}
そういえばstrlen()なんて関数もありましたね。
コンパイルして共有ライブラリを作成します。
gcc -Wall -c charcount.c
gcc -shared -o charcount.so charcount.o
テストするPythonスクリプトは以下の通り
C言語の文字列は、文字配列のポインタになります。
文字型のポインタは、ctypes.c_char_pで指定できます。
import ctypes
mydll = ctypes.CDLL("charcount.so")
mydll.charcount.argtypes = [ctypes.c_char_p]
mydll.charcount.restype = ctypes.c_int
print mydll.charcount("Hello")
実行すると文字列の長さの 5 がプリントされました。
次に、文字列を渡して、それを変更して返すような関数を作ってみます。
/* editstring.c */
#include
#include
char *editstring(char *s)
{
char buff[1024];
sprintf(buff, "*** %s ***", s);
strcpy(s, buff);
return s;
}
バッファ内で文字列を編集して、それを渡された文字列領域にコピーして、
そのポインタを返す関数です。
渡した文字列領域が編集されることになります。
Pythonの文字列は変更できないので、編集のための文字列バッファを用意するらしいです。
Pythonスクリプトは以下の通りです。
import ctypes
mydll = ctypes.CDLL("editstring.so")
mydll.editstring.argtypes = [ctypes.c_char_p]
mydll.editstring.restype = ctypes.c_char_p
s = ctypes.create_string_buffer("Hello", 1024)
result = mydll.editstring(s)
print '[%s]' % result
実行すると、
[*** Hello ***]
と表示され、編集されたのが確認できます。
返り値の型をc_char_pにして受け取ったresultは、
そのまま文字列としてプリントされますが、sはそうはいきません。
print sとすると c_char_arrayのオブジェクトであると表示されます。
その中の文字列をプリントするときは、
print '%s' % s.value
とするとよいようです。
でも、普通にbuffのポインタを返したらよいかな。
/* newstring.c */
#include
char *newstring(char *s)
{
char buff[1024];
sprintf(buff, "*** %s ***", s);
return buff;
}
こちら、コンパイルすると「関数が局所変数のアドレスを返します」
と警告が出ます。それはそうですよね。
この関数を抜けると、このメモリ領域は、解放されてしまいそうですが、、、。
Pythonスクリプトは以下の通り。
import ctypes
mydll = ctypes.CDLL("newstring.so")
mydll.newstring.argtypes = [ctypes.c_char_p]
mydll.newstring.restype = ctypes.c_char_p
string = mydll.newstring("Hello")
print string
ちゃんと*** Hello ***と出力されました。
このような書き方のほうが書きやすいですね。
直接渡した文字列をいじる必要がなければ、create_string_buffer()
は使わなくてもよいのでしょうか。
type(string)すると、
でもちょっとメモリが心配。
Python側で文字列バッファを用意したほうがいいかな。
次は、複数の実数値が入った配列をPythonから渡して、その和を返すようなC関数を試してみます。
/* sumvalues.c */
#include
double sumvalues(double *v, int n)
{
int i;
double sum;
sum = 0.0;
for (i=0; i
sum = sum + v[i];
printf("%f\n", v[i]);
}
return sum;
}
配列の長さはCの関数から分かりませんので、その長さも渡すようにしています。
コンパイルして、共有ライブラリを作ります。
gcc -c sumvalues.c
gcc -shared -o sumvalues.so sumvalues.o
Pythonスクリプトは以下の通り
import ctypes
mydll = ctypes.CDLL("sumvalues.so")
mydll.sumvalues.restype = ctypes.c_double
n = 10
nvalues = ctypes.c_double * n
vlist = nvalues(*[1.0+i*1.0 for i in range(n)])
print vlist, len(vlist)
v = mydll.sumvalues(vlist, ctypes.c_int(n))
print v
共有ライブラリをを呼び出すところと、返り値を指定するのは同じです。
配列を使うときは、まず長さ分の型を作ります。
nvaluesという型で、長さがnのctypes.cdoubleの型を作ります。
その型でvlistというn個の実数値が配列に入ったものを作成します。
len()を用いてvlistの長さを調べることができます。
vlistは、c_double_Array_10オブジェクトになっています。
vlistは、ctypesの型になっていますので、あらためてargtypesで設定する必要もありません。長さだけ、ctypes.c_int()の型にして渡します。
1から10までの足し算をすることができました。
実際に利用するときは、Pythonの関数でラッピングするとよいかと思いました。
そのように書いたPythonスクリプトは以下の通りです。
import ctypes
mydll = ctypes.CDLL("sumvalues.so")
mydll.sumvalues.restype = ctypes.c_double
def sumvalues(vlist):
n = len(vlist)
nvalues = ctypes.c_double * n
arg1 = nvalues(*vlist)
v = mydll.sumvalues(arg1, ctypes.c_int(n))
return v
if __name__ == '__main__':
vlist = [1.0+i*1.0 for i in range(10)]
v = sumvalues(vlist)
print v
次は、複数の値を返してもらう関数を書いてみます。
関数は、基本的に一つの値しか返しません。
ですので、引数に値を入れてもらうための変数(へのポインタ)を渡すことにします。
ソースファイル
/* summean.c */
#include
int summean(double *v, int n, double *sum, double *mean)
{
int i;
double s;
s = 0.0;
for (i=0; i
s = s + v[i];
}
*sum = s;
*mean = s/n;
return 0;
}
コンパイルして共有ライブラリを作成します。
gcc -c summean.c
gcc -shared -o summean.so summean.o
Pythonスクリプトは以下の通り
import ctypes
mydll = ctypes.CDLL("summean.so")
def summean(vs):
n = len(vs)
nvalues = ctypes.c_double * n
vlist = nvalues(*vs)
s = ctypes.c_double(0.0)
m = ctypes.c_double(0.0)
mydll.summean(vlist, ctypes.c_int(n), ctypes.pointer(s), ctypes.pointer(m))
return (s.value, m.value)
if __name__ == '__main__':
vs = [1.0+i*1.0 for i in range(10)]
s, m = summean(vs)
print s, m
前と同様にPythonスクリプトでsummean関数としてラッピングしました。
結果を保存する変数sおよびmをc_double(0.0)で用意します。
関数summeanには、そのポインタを渡す必要があるため、ctypes.pointer()関数を利用しています。
Pythonの関数の返り値として、s.valueおよびm.valueをタプルにして返します。
つぎは、いよいよ構造体です。まずは、シンプルな構造体を渡して、その内容を参照した計算結果が返ってくる関数を作ってみたいと思います。
ここでは、四角の左、右、下、上の座標を格納する構造体です。
ソースファイル
/* squarearea.c *\
#include
typedef struct {
double left;
double right;
double bottom;
double top;
} SQUARE;
double squarearea(SQUARE sq)
{
double area;
double width;
double height;
width = sq.right - sq.left;
height = sq.top - sq.bottom;
area = width * height;
return area;
}
コンパイルして、共有ライブラリを作成します。
gcc -c squarearea.c
gcc -shared -o squarearea.so squarearea.o
次に、Pythonスクリプトです。
Pythonスクリプト側で構造体を取り扱うためには、ctypes.Structureを継承したクラスを作ります。
そのクラスに、_fields_属性を設定することで、Cの構造体と一致させるということです。
_fields_属性は、フィールド名 と フィールド型 を持つ 2要素タプル のリストです。
ctypes.Structureで定義されているコンストラクタが、このフィールドを参照して、初期化するようです。
Pythonスクリプトは、以下のようになりました。
import ctypes
mydll = ctypes.CDLL("squarearea.so")
class SQUARE(ctypes.Structure):
_fields_ = [('left', ctypes.c_double),
('right', ctypes.c_double),
('bottom', ctypes.c_double),
('top', ctypes.c_double)]
if __name__ == '__main__':
sq = SQUARE(0.3, 0.8, 0.4, 3.4)
mydll.squarearea.restype = ctypes.c_double
v = mydll.squarearea(sq)
print v
幅0.5、高さ3ですので、1.5が返ってきます。
返り値の型を設定するのを忘れないようにしましょう。
C言語で返り値として構造体を使うと、複数の値を返すことができて便利ですよね。
先ほどの関数で、高さを1/2したものを返すようにしてみましょう。
ソースファイル
/* squarehalf.c */
#include
typedef struct {
double left;
double right;
double bottom;
double top;
} SQUARE;
SQUARE squarehalf(SQUARE sq)
{
double area;
double width;
double height;
SQUARE hsq;
hsq = sq;
height = sq.top - sq.bottom;
hsq.top = hsq.bottom + height/2.0;
return hsq;
}
hsqにsqを入れて、そのtopの値を、半分の高さになるように設定しなおしています。
コンパイルして、共有ライブラリを作ります。
gcc -c squarehalf.c
gcc -shared -o squarehalf.so squarehalf.o
Pythonスクリプト
import ctypes
mydll = ctypes.CDLL("squarehalf.so")
class SQUARE(ctypes.Structure):
_fields_ = [('left', ctypes.c_double),
('right', ctypes.c_double),
('bottom', ctypes.c_double),
('top', ctypes.c_double)]
if __name__ == '__main__':
sq = SQUARE(0.3, 0.8, 0.4, 3.4)
v = SQUARE()
mydll.squarehalf.restype = SQUARE
v = mydll.squarehalf(sq)
print sq.left, sq.right, sq.bottom, sq.top
print v.left, v.right, v.bottom, v.top
返り値をSQUAREにすることと、返り値を入れる変数vをSQUARE()クラスのインスタンスにしただけです。
0.3 0.8 0.4 3.4
0.3 0.8 0.4 1.9
と出力され、半分の高さの四角を表すデータになりました。
構造体の中に、別の構造体がある場合はどう書けるのでしょうか。
先ほど面積を求めた四角を、左下、右上の座標データPOINTで表してみます。
/* squarearea2.c */
#include
typedef struct {
double x;
double y;
} POINT;
typedef struct {
POINT leftbottom;
POINT righttop;
} SQUARE;
double squarearea(SQUARE sq)
{
double area;
double width;
double height;
width = sq.righttop.x - sq.leftbottom.x;
height = sq.righttop.y - sq.leftbottom.y;
area = width * height;
return area;
}
コンパイルして共有ライブラリにします。
gcc -c squarearea2.c
gcc -shared -o squarearea2.so squarearea2.o
Pythonスクリプトは以下のようになりました。
import ctypes
mydll = ctypes.CDLL("squarearea2.so")
class POINT(ctypes.Structure):
_fields_ = [('x', ctypes.c_double),
('y', ctypes.c_double)]
class SQUARE(ctypes.Structure):
_fields_ = [('leftbottom', POINT),
('righttop', POINT)]
if __name__ == '__main__':
sq = SQUARE(POINT(0.3, 0.4), POINT(0.8, 3.4))
v = SQUARE()
mydll.squarearea.restype = ctypes.c_double
v = mydll.squarearea(sq)
print v
それぞれ対応するクラスを書いただけで、意外なところはないですね。
ただ、クラス定義する順番で、POINTをSQUAREの後で行うと、
SQUAREで利用しているPOINTが定義できないというエラーが起こります。
構造体の定義では、その中に自分自身をもつものもありますね。
再帰的な構造は、中に同じ自分自身の型へのポインタを入れたりします。
不完全型と呼ばれているようです。
簡単のため、
(v1, (v2, (v3, (v4, (v5, NULL)))))
のようなリストに似た形のデータを考えてみます。
ソースファイル
/* showlist.c */
#include
struct CELL {
int value;
struct CELL *next;
};
int showlist(struct CELL *c, int flg)
{
printf("(%d, ", c->value);
if ((struct CELL *)NULL != c->next)
showlist(c->next, 0);
else
printf("NULL");
if (1 == flg)
printf(")\n");
else
printf(")");
return 0;
}
CELLという型の定義の中に、CELLへのポインタが含まれています。
前の例のように、typedef struct { ... } CELL; のような書き方をすると、コンパイル時にエラーがでます。使われるより前の方に、CELLというワードが入るような記述をする必要があるということです。
showlistは、再帰的に呼び出される関数で、渡されたCELLの値を出力したのちに、続くCELLの描画を行うため、showlistを呼び出します。nextに、NULLポインタが入っていれば、そこで終了です。
flgは、最初に呼び出すときに1をセットすると、それ以降とを区別することができます。
コンパイルして、共有ライブラリにします。
gcc -c showlist.c
gcc -shared -o showlist.so sholist.o
このような不完全な構造体定義の場合、Pythonスクリプトは、次のようにするようです。
import ctypes
mydll = ctypes.CDLL("showlist.so")
class CELL(ctypes.Structure):
pass
CELL._fields_ = [('value', ctypes.c_int),
('next', ctypes.POINTER(CELL))]
if __name__ == '__main__':
c = CELL(0, None)
for i in range(5):
c = CELL((i+1), ctypes.pointer(c))
mydll.showlist(ctypes.pointer(c), ctypes.c_int(1))
クラスCELLの定義では、なにも行わずに、あとから改めて_fields_属性を設定するようです。
ctypes.POINTER(CELL)で、CELLへのポインタ型という指定ができます。
実際に利用するときに、CELL型のcというもののポインタは、ctypes.pointer(c)で得ます。紛らわしいですね。
Pythonスクリプトでcの値を設定していき、showlistにcへのポインタと整数1を渡すと、
(5, (4, (3, (2, (1, (0, NULL))))))
と表示されます。この表示は、C関数内で行われたものです。
このようにctypesを使って共有ライブラリを呼び出す方法だと、CのソースファイルにPythonで利用するという配慮をせずに、Pythonから呼び出すことができました。
Pythonスクリプト側で、ちょっと使いやすいように包んであげれば呼び出しやすくなるかと思います。
f2pyを使ってFortranプログラムで計算するのもいいのですが、すでにCの関数を作っているようなら、この方法は便利ですね。
ということで、自作のガウス分布をフィットするルーチンをPythonから呼び出してみました。速度の比較のために、Pythonスクリプトでも書いてみました。numpyを利用せずに、Cのソースをほぼ1対1に直したものです。
#--- C func ---
#1.02713 0.0241351
#4.93666 0.0580069
#-0.938185 0.023901
#2.49769 0.0360503
# time_c = 0.000507835 s
#--- Python func ---
#1.02713 0.0241351
#4.93666 0.0580069
#-0.938185 0.023901
#2.49769 0.0360503
# time_py = 0.00944325 s
#-------------------
# time_py/time_c = 18.5951
#-------------------
200点のデータをフィットしました。やっぱりCで記述されたものは早いですね。
Pythonスクリプトの方は、numpyの機能を利用して実装すると、どこまで速くなるのでしょうか。
2013年10月19日土曜日
Latitude10にWindows8.1をインストール
WindowsストアにWindows8.1のアップデートがきました。
評判はあまりよくない様子もあり、ドライバの互換性など心配もありましたが、
さっそくインストールしてみました。
念のため電源ケーブルを接続して、Latitude10を起動します。
まず、WindowsストアからWindows8.1のダウンロードを開始しました。
「ダウンロード中もほかの作業ができます」と表示されますが、そのままほっておきます。
30分ほどたった頃、「互換性をチェックしています」と表示されました。
プログレッシブバーは、半分をちょっとすぎたところです。
それから5分ほど経過し、「変更を適用しています」とのこと。
互換性チェックは、問題なかったのでしょうか。
さらに5分後、「情報を集めています」に。
そして20分ほど経過して、「再起動の準備をしています」に。
5分ほどで、再起動を促すメッセージが表示されました。
もちろん「今すぐ再起動」します。
画面が消えた後、DELLのマークが表示され、「設定しています(xx%)」という表示に。
まだ時間はかかりそう。
20分ほどで、「デバイスの準備をしています」に。こちらははやい。
画面が消えて点いて、「準備しています」に。
1分ほどで「PC設定を適用しています」が表示されました。
5分ほど後、画面が2度消えて、「その他の処理を実行しています」に。
その後8分ほどで、「準備しています」になり、すぐに、ライセンス条項が表示されました。
「同意します」で設定に進みます。
「自分で設定する」を選び、「IEの閲覧履歴をMicrosoftに送る」というものをオフにしました。
次に、アカウントのセットアップに進みます。
これまでローカルアカウントで利用していたのですが、設定が見当たりません。
「新しくアカウントを作成」を選んで、「すでにもっているアカウントを使い続ける」を選びました。
すると、次に進むことができて「アプリをインストールしています」が表示されました。
「最後の処理をしています」「PCの電源を切らないでください」と表示され、
5分ほどで、スタート画面が表示されました。
アカウントは、これまで利用していたローカルになっている様子です。
ダウンロードをはじめてから、1時間45分ほどかかりました。
インストールしているストアアプリの起動をチェックしてみます。
タスクリスト OK
Yahoo!天気 OK
NoteAnytimePremium OK
RubyReader OK
乗換NAVITIME OK
FlightAware OK
Skyscanner OK
PDF Touch OK
CamiApp OK
TuneIn Raddio OK
gMaps OK
GoogleSearch OK
Bingの検索が見当たりませんが、使っていなかったので問題ありません。
スタート画面の最後のページの下矢印で「すべてのアプリ」表示になるのですね。
こちらは以前、文字でちゃんと記述されていた方がわかりやすかったと思います。
デスクトップに移って、自分のPythonスクリプトの動作チェックをしました。
ImageViewer OK
QR Camera OK
Pomera Fix OK
gKey OK
Address Book OK
普段使っているものは問題なく動いたので安心しました。
さて、Pomera Fixの動作を確認するときに気がつきましたが、dm100のBluetooth接続は、ドライバーエラーになっています。
Bluetoothデバイスの追加を行うと、管理画面になります。
そこでドライバーエラーとなっているdm100デバイスを、いったん削除します。
その後、dm100の方から、キーボード接続を開始すると、dm100が見つかりペアリングできるようになります。
ペアリングを選んで、ペアリングコードをdm100から入力するとペアリング完了です。
これでまたdm100をBluetoothキーボードとして利用できます。
dmm100とのファイル転送も、様子が変わりました。
コントロールパネルのデバイスとプリンターの表示で、dm100デバイスにファイル転送のサービスを登録するところは、前に書いたとおりです。
その後は、デスクトップのPCを開くと、デバイスとドライブのところにdm100が表示されており、そこを開くとポメラ側の内蔵メモリやSDカードが表示されました。これはわかりやすくなりましたね。
この投稿はポメラで書いて、Win8.1にアップデートしたLatitude10へBluetoothでファイルを転送し、Dropboxを経由して、普段使いのノートPCで追加、修正して投稿しています。
デジタイザペンですが、最近WacomのタブレットPC用ドライバISD_DualTouch_712-9で、スリープ時の電源LEDの点灯問題が解決していたのですが、Windows8.1にアップデートしてから再びスリープ時にも点灯し続けています。
この問題が解決されたから、このドライバをいれたという人は注意が必要かもしれません。
ということで、大きな問題なく、利用できそうなので安心です。
でもLatitude10では、電源シャットダウンは、チャームだしてやっているので、今のところ使い勝手は変わりないかも。
2013/10/20 追記
アップデートと関係があるかわかりませんが、その後のあやしい動作。
一度、画面が点描みたいになりました。再起動したら直りました。
一度、バッテリーが認識できないという表示になった。再起動したら直りました。
BIOS A07、チップセットA06をインストールしたところ、スリープでのLED点灯不具合は解消されました。
2013/10/24 追記
Latitude10のBIOSのA08がでたので、入れてみました。
すると、Windows8.1の設定画面の文字が白く塗りつぶされて見えなくなりました。
デスクトップのIEを開いて、Windows Updateを確認したところ、
Intel(R) Corporation driver update for Intel(R) Graphics Media Accelerator
のドライバ更新がきていたので、それを適用したところ、その問題は解消されました。
BluetoohキーボードのドライバHIDデバイスがエラーになっていましたが(それでも利用できましたが)、それが解消されました。その代わり、ポメラをファイル転送で接続できなくなりました。
コントロールパネルのデバイスの表示で、DM100キーボードを右クリックでプロパティが表示されないのです。前のようにDM100のキーボードにFTPサービスを追加することができません。
しかたがないので、Bluetoothのデバイス追加画面でDM100のキーボードを削除します。そして、DM100からファイル転送をかけてみたところ、今度は、DM100をドライブとして認識しました。デスクトップのPCを開くと、DM100があります)開くと、DM100側のファイルを見ることができ、こちらへコピーしてくることができました。(DM100を開いたところで、ポメラ側が接続状態になりました。)
もちろん今度は、キーボードとして利用できません。
ということで、キーボードかファイル転送か、どちらかとしては利用できるようです。いちいちデバイスを削除するだけですが、以前のように手軽にはいきませんね。とりあえず、Latitude10で外付けキーボードを利用する機会はあまりないので、ファイル転送状態で維持しておきます。
A08で、Wacomドライバを用いても、スリープでLEDが消灯することは確認できました。
ソフトウェアで、いろいろ変わるようで、これからのアップデートも楽しみです。
2013/10/27 追記
その後、Windows Updateや、win8.1用のチップセットドライバーをインストールしたところ、以前のようにデバイス表示で、ポメラdm100を右クリックしたときのメニュー表示も出来るようになっていました。これで、サービスの追加もできるようになったと思うので、以前のようなポメラとの連携もできるかと期待してます。また試してみます。win8.1の動作も安定してきたかな。
2013/10/29 追記
ポメラとBluetooth接続してみました。以前のように、ポメラでキーボードかファイル転送かを選択するだけで、どちらの機能も利用できるようになりました。最初に、ストレージで、ペアリングしてもあとからキーボードのサービスを追加するだけでよいようです。
評判はあまりよくない様子もあり、ドライバの互換性など心配もありましたが、
さっそくインストールしてみました。
念のため電源ケーブルを接続して、Latitude10を起動します。
まず、WindowsストアからWindows8.1のダウンロードを開始しました。
「ダウンロード中もほかの作業ができます」と表示されますが、そのままほっておきます。
30分ほどたった頃、「互換性をチェックしています」と表示されました。
プログレッシブバーは、半分をちょっとすぎたところです。
それから5分ほど経過し、「変更を適用しています」とのこと。
互換性チェックは、問題なかったのでしょうか。
さらに5分後、「情報を集めています」に。
そして20分ほど経過して、「再起動の準備をしています」に。
5分ほどで、再起動を促すメッセージが表示されました。
もちろん「今すぐ再起動」します。
画面が消えた後、DELLのマークが表示され、「設定しています(xx%)」という表示に。
まだ時間はかかりそう。
20分ほどで、「デバイスの準備をしています」に。こちらははやい。
画面が消えて点いて、「準備しています」に。
1分ほどで「PC設定を適用しています」が表示されました。
5分ほど後、画面が2度消えて、「その他の処理を実行しています」に。
その後8分ほどで、「準備しています」になり、すぐに、ライセンス条項が表示されました。
「同意します」で設定に進みます。
「自分で設定する」を選び、「IEの閲覧履歴をMicrosoftに送る」というものをオフにしました。
次に、アカウントのセットアップに進みます。
これまでローカルアカウントで利用していたのですが、設定が見当たりません。
「新しくアカウントを作成」を選んで、「すでにもっているアカウントを使い続ける」を選びました。
すると、次に進むことができて「アプリをインストールしています」が表示されました。
「最後の処理をしています」「PCの電源を切らないでください」と表示され、
5分ほどで、スタート画面が表示されました。
アカウントは、これまで利用していたローカルになっている様子です。
ダウンロードをはじめてから、1時間45分ほどかかりました。
インストールしているストアアプリの起動をチェックしてみます。
タスクリスト OK
Yahoo!天気 OK
NoteAnytimePremium OK
RubyReader OK
乗換NAVITIME OK
FlightAware OK
Skyscanner OK
PDF Touch OK
CamiApp OK
TuneIn Raddio OK
gMaps OK
GoogleSearch OK
Bingの検索が見当たりませんが、使っていなかったので問題ありません。
スタート画面の最後のページの下矢印で「すべてのアプリ」表示になるのですね。
こちらは以前、文字でちゃんと記述されていた方がわかりやすかったと思います。
デスクトップに移って、自分のPythonスクリプトの動作チェックをしました。
ImageViewer OK
QR Camera OK
Pomera Fix OK
gKey OK
Address Book OK
普段使っているものは問題なく動いたので安心しました。
さて、Pomera Fixの動作を確認するときに気がつきましたが、dm100のBluetooth接続は、ドライバーエラーになっています。
Bluetoothデバイスの追加を行うと、管理画面になります。
そこでドライバーエラーとなっているdm100デバイスを、いったん削除します。
その後、dm100の方から、キーボード接続を開始すると、dm100が見つかりペアリングできるようになります。
ペアリングを選んで、ペアリングコードをdm100から入力するとペアリング完了です。
これでまたdm100をBluetoothキーボードとして利用できます。
dmm100とのファイル転送も、様子が変わりました。
コントロールパネルのデバイスとプリンターの表示で、dm100デバイスにファイル転送のサービスを登録するところは、前に書いたとおりです。
その後は、デスクトップのPCを開くと、デバイスとドライブのところにdm100が表示されており、そこを開くとポメラ側の内蔵メモリやSDカードが表示されました。これはわかりやすくなりましたね。
この投稿はポメラで書いて、Win8.1にアップデートしたLatitude10へBluetoothでファイルを転送し、Dropboxを経由して、普段使いのノートPCで追加、修正して投稿しています。
デジタイザペンですが、最近WacomのタブレットPC用ドライバISD_DualTouch_712-9で、スリープ時の電源LEDの点灯問題が解決していたのですが、Windows8.1にアップデートしてから再びスリープ時にも点灯し続けています。
この問題が解決されたから、このドライバをいれたという人は注意が必要かもしれません。
ということで、大きな問題なく、利用できそうなので安心です。
でもLatitude10では、電源シャットダウンは、チャームだしてやっているので、今のところ使い勝手は変わりないかも。
2013/10/20 追記
アップデートと関係があるかわかりませんが、その後のあやしい動作。
一度、画面が点描みたいになりました。再起動したら直りました。
一度、バッテリーが認識できないという表示になった。再起動したら直りました。
BIOS A07、チップセットA06をインストールしたところ、スリープでのLED点灯不具合は解消されました。
2013/10/24 追記
Latitude10のBIOSのA08がでたので、入れてみました。
すると、Windows8.1の設定画面の文字が白く塗りつぶされて見えなくなりました。
デスクトップのIEを開いて、Windows Updateを確認したところ、
Intel(R) Corporation driver update for Intel(R) Graphics Media Accelerator
のドライバ更新がきていたので、それを適用したところ、その問題は解消されました。
BluetoohキーボードのドライバHIDデバイスがエラーになっていましたが(それでも利用できましたが)、それが解消されました。その代わり、ポメラをファイル転送で接続できなくなりました。
コントロールパネルのデバイスの表示で、DM100キーボードを右クリックでプロパティが表示されないのです。前のようにDM100のキーボードにFTPサービスを追加することができません。
しかたがないので、Bluetoothのデバイス追加画面でDM100のキーボードを削除します。そして、DM100からファイル転送をかけてみたところ、今度は、DM100をドライブとして認識しました。デスクトップのPCを開くと、DM100があります)開くと、DM100側のファイルを見ることができ、こちらへコピーしてくることができました。(DM100を開いたところで、ポメラ側が接続状態になりました。)
もちろん今度は、キーボードとして利用できません。
ということで、キーボードかファイル転送か、どちらかとしては利用できるようです。いちいちデバイスを削除するだけですが、以前のように手軽にはいきませんね。とりあえず、Latitude10で外付けキーボードを利用する機会はあまりないので、ファイル転送状態で維持しておきます。
A08で、Wacomドライバを用いても、スリープでLEDが消灯することは確認できました。
ソフトウェアで、いろいろ変わるようで、これからのアップデートも楽しみです。
2013/10/27 追記
その後、Windows Updateや、win8.1用のチップセットドライバーをインストールしたところ、以前のようにデバイス表示で、ポメラdm100を右クリックしたときのメニュー表示も出来るようになっていました。これで、サービスの追加もできるようになったと思うので、以前のようなポメラとの連携もできるかと期待してます。また試してみます。win8.1の動作も安定してきたかな。
2013/10/29 追記
ポメラとBluetooth接続してみました。以前のように、ポメラでキーボードかファイル転送かを選択するだけで、どちらの機能も利用できるようになりました。最初に、ストレージで、ペアリングしてもあとからキーボードのサービスを追加するだけでよいようです。
登録:
投稿 (Atom)



