1. Prepare Compiling Environment
Download MSYS2 of your windows version from here.
Follow the instructions on the homepage to update the system. Run commands listed below.
$ update-core $ pacman -Suy
If you have trouble connecting to the official repository of MSYS2, modify the configuration files of pacman, which are located at /etc/pacman.d/.
For those living in China, I recommend a MSYS2 mirror hosted by LUG@USTC. Just follow the instructions on their wiki.
We need to install the mingw64 toolchain (suppose we use 64-bit windows) and some tools like tar and make. The mingw64 toolchain contains compiler and other compiling-related tools. Just run the command below.
$ pacman -S mingw-w64-x86_64-toolchain tar make
After the installation, close the MSYS2 window and run mingw64_shell.bat located at MSYS2 root directory. You may notice the word in purple before tilde changes from MSYS to
MINGW64. According the introduction of MSYS2, the MINGW64 shell is more natively oriented. Meanwhile, and the MSYS2 shell provides some linux features.
The mingw subsystems provide native Windows programs and are the main focus of the project. These programs are built to co-operate well with other Windows programs, independently of the other subsystems.
The msys2 subsystem provides an emulated mostly-POSIX-compliant environment for building software, package management, and shell scripting. These programs live in a virtual single-root filesystem (the root is the MSYS2 installation directory). Some effort is made to have the programs work well with native Windows programs, but it's not seamless.
2. Compile GSL and Libeemd
Libeemd depends on GNU Scientific Library (GSL). Run following command in MINGW64 shell to download GSL source code.
$ curl -o gsl-latest.tar.gz http://mirror.clarkson.edu/gnu/gsl/gsl-latest.tar.gz $ tar zxvf gsl-latest.tar.gz
Change directory to the GSL directory and compile it. (Suppose we have GSL 2.1 here.)
$ cd gsl-2.1 $ ./configure $ make $ make install
GSL is installed to /usr/local/ without assigning --prefix flag. So we need to modify PKG_CONFIG_PATH variable before compiling libeemd so compiler may find GSL libraries.
$ export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig
Then we clone libeemd source code from bitbucket and compile it. A makefile is included so we don't need to run a configure script.
$ git clone https://bitbucket.org/luukko/libeemd.git $ cd libeemd $ make
After compiling, you may use file command to check out file type of libeemd.so. It's a dll file! It sounds weird but I will continue with this convention. Otherwise you may modify Makefile and remake by yourself.
$ file libeemd.so libeemd.so: PE32+ executable (DLL) (console) x86-64, for MS Windows
3. Install pyeemd module to Anaconda2
Anaconda is a great platform based on python for data analytic. It contains lots of modules and make it much simpler to do calculation.
But there're no EMD related modules included in Anaconda by default. And I can't find any one in pypi or by conda search command. (There's one named emd in pypi actually. But there's no document and I don't think it reliable.) That's why I write this blog.
If you tried googling about libeemd and windows before reading this blog, you may have found this issue. Owner of libeemd stated that using libeemd on windows may be unpleasant.
Please also note that installing libeemd on Windows is currently quite unsupported – I haven't tested it, and I have no way to test it.
This unpleasantness may be caused by compiling, which we have already fixed, and dll loading. Library searching is different in linux and windows. I know little about os. So it may be appropriate to quote from tldp.org, rather than gibberishing by myself.
The interface used by Linux is essentially the same as that used in Solaris, which I'll call the ''dlopen()'' API. However, this same interface is not supported by all platforms; HP-UX uses the different shl_load() mechanism, and Windows platforms use DLLs with a completely different interface.
It means, instead of appointing library search work to os, that we need to load dll files libeemd.so depending on on our own. Luckily finding dll dependency and loading them in python is not hard.
You may use objdump to find dll dependency as shown below.
$ objdump -p libeemd.so | grep "\.dll" DLL Name: KERNEL32.dll DLL Name: msvcrt.dll DLL Name: libgomp-1.dll DLL Name: libgsl-19.dll
There's a handy tool named dependencywalker to find dll dependency as well. After opening the dll file, namely libeemd.so here, dependencies will be shown in the top-left column.
We have known that libeemd.so depends on kernel32.dll, msvcrt.dll, libgomp-1.dll and libgsl-19.dll. Kernel32.dll and msvcrt.dll are located in C:/windows/system32 and we don't need to worry about them. We have to worry about libgomp-1.dll's and libgsl-19.dll's dependencies. (pretty messy, right?)
Do basically same to them as to libeemd.so. And we get this dependency tree. (You don't get it directly. I draw this manually.)
libeemd.so |-KERNEL32.dll |-msvcrt.dll |-libgomp-1.dll |-KERNEL32.dll |-msvcrt.dll |-libwinpthread-1.dll |-KERNEL32.dll |-msvcrt.dll |-user32.dll |-libgcc_s_seh-1.dll |-KERNEL32.dll |-msvcrt.dll |-libwinpthread-1.dll |-libgsl-19.dll |-KERNEL32.dll |-msvcrt.dll |-user32.dll |-libgslcblas-0.dll |-KERNEL32.dll |-msvcrt.dll
This tree ends in kernel32.dll, msvcrt.dll and user32.dll. They are all located in C:/windows/system32, which is in system searching path. Other dlls are located in MSYS2 directory. You can find them in MINGW64 shell by find / -name command.
After all these dlls being found, we may begin installing pyeemd to Anaconda.
Change directory to libeemd/pyeemd directory and install pyeemd module to Anaconda2/Lib/site-packages directory.
Make sure you're using Anaconda2's python when running the setup.py script. You can use absolute path in MINGW64 shell like /c/Users/juiceyang/Anaconda/python . (You should replace with your own username here.)
$ /c/Users/juiceyang/Anaconda2/python setup.py install
Change directory to Anaconda2/Lib/site-packages/pyeemd, you may find they are already there. But once you try to run pyeemd.py, a windows error 126 prompt out. That's because python can't find dlls libeemd.so depending on. We may fix this by insert some lines into pyeemd.py. It looks like this after inserting.
# Load libeemd.so # ---------new lines start from here ctypes.WinDLL("kernel32.dll") ctypes.WinDLL("msvcrt.dll") ctypes.WinDLL("user32.dll") ctypes.WinDLL("C:\\msys64\\mingw64\\bin\\libwinpthread-1.dll") ctypes.WinDLL("C:\\msys64\\mingw64\\bin\\libgcc_s_seh-1.dll") ctypes.WinDLL("C:\\msys64\\mingw64\\bin\\libgomp-1.dll") ctypes.WinDLL("C:\\msys64\\home\\YOUR_USERNAME\\gsl-2.1\\cblas\\.libs\\libgslcblas-0.dll") ctypes.WinDLL("C:\\msys64\\home\\YOUR_USERNAME\\gsl-2.1\\.libs\\libgsl-19.dll") # ctypes.WinDLL("C:\\msys64\\home\\YOUR_USERNAME\\libeemd\\libeemd.so") --> This line is commented out. Load libeemd.so in next 3 lines. # ---------new lines end _LIBDIR = os.path.dirname(os.path.realpath(__file__)) _LIBFILE = os.path.join(_LIBDIR, "libeemd.so") _libeemd = ctypes.CDLL(_LIBFILE)
ctypes.WinDLL() function loads dlls. First three dlls are in system32 folder so we need no absolute path. Other dlls is located by absolute path.
Then run following snippet in Jupyter notebook to check out whether it's working!
%matplotlib inline from pyeemd import ceemdan from pyeemd.utils import plot_imfs import matplotlib.pyplot as plt import numpy as np y = np.sin(2*np.pi*np.linspace(0,1,1000))+np.sin(20*np.pi*np.linspace(0,1,1000)) plt.plot(y) plt.show() imfs = ceemdan(y, S_number=4, num_siftings=50) plot_imfs(imfs) plt.show()
Here's my output. Have fun using pyeemd!