Compiling Orange 2 on modern Linux

By: Marko Toplak, Jan 10, 2022

We abandoned Orange 2 in 2015 because we did not have enough resources to split between maintaining Orange 2 and building the new version from scratch. Orange was due for a rewrite for quite some time. The core of the pre-3 Orange was written mainly in C++. When Orange was conceived, extending Python with C was the only option to make it run fast enough. Orange was designed before NumPy and even before NumPy’s predecessors, Numarray and Numeric. The resulting code was hard to maintain. In the meantime, Python libraries such as NumPy and scikit-learn matured, so the rewrite seemed reasonable: Orange 3 was born.

Currently, we need Orange 2 as a reference implementation for interaction analysis, something that Orange 3 still lacks. Two features positively interact if observing the features in combination yields more information than the sum of information of observing both features separately. The Interaction Graph widget from Orange 2, which uses the interaction gain measure, is a great tool to discover such interacting features.

As a Linux user, I admire the backward compatibility we learned to expect on Windows: if an application ever did work there, it probably still does. On Windows, an old Orange 2 build from the download archive probably still works. In contrast, old Mac OS Orange packages are likely problematic because recent Mac OS versions stopped supporting 32-bit binaries.

Linux/GNU users do not have the luxury of installing old binary Orange packages. They do not exist because building them presented a lot of work that would benefit a few users. Even if they had, they would be hard to run; while the Linux kernel is highly backward compatible, its userspace is not.

Therefore, we need to dig into the code, starting with a checkout of Orange 2 code for the git repository:

git clone [email protected]:biolab/orange2.git
cd orange2

The source code includes the INSTALL.txt, which suggests installing a bunch of Python libraries with the Linux distribution’s package manager and then compiling Orange. Now, the problems start. The instructions say they were tested with Ubuntu 14.04, which is not more than seven years old. Curiously, a quick git blame confirms that I was the author of the instructions, so Ubuntu 14.04 seems to be the latest distribution I have ever used to install Orange 2.

Here the problems begin. The required libraries no longer exist as packages in Ubuntu 20.04 that I am using, and neither does Python 2. Fortunately, Anaconda comes to the rescue. We can use it to create a new Python 2 environment:

conda create --name py2 -c defaults --override-channels python=2.7
conda activate py2

Then, we can install the needed libraries with conda. I found the list of required packages in the setup.py file.

conda install -c defaults --override-channels numpy scipy setuptools
conda install -c conda-forge --override-channels pyqt=4.11

I needed quite some time to figure out which combination of packages and sources is installable. We can now try to do a development installation of Orange:

python setup.py develop

That fails:

source/include/stat.hpp:33:27: error: 'double abs(double)' conflicts with a previous declaration

Such problems are expected when we compile old code with a newer compiler or libraries. I tried installing older compiler versions, but my distribution only went back to GCC-7, which was already too new. So I had to fix the code. The following change fixed the error:

--- a/source/include/stat.hpp
+++ b/source/include/stat.hpp
@@ -30,8 +30,8 @@ using namespace std;
 #endif
 
 #ifndef _MSC_VER_70
-inline double abs(double x)
-{ return fabs(x); }
+//inline double abs(double x)
+//{ return fabs(x); }
 #endif

There were other errors with return types of C++ functions called from Python. After about 10 changed lines and quite some waiting, Orange was finally installed! The compilation took 10 minutes on my newish laptop. So a lot of code had to be compiled. And someone had to write it! Amazingly, most of the C++ code of Orange 2 was written by a single developer, Janez Demšar.

Well, now Orange is installed, but does it work? Let’s try to run it:

orange-canvas

Nope, not quite:

  ...
  File "/home/marko/dev/orange2/Orange/OrangeCanvas/main.py", line 23, in <module>
    from Orange.OrangeCanvas.application.canvasmain import CanvasMainWindow
  File "/home/marko/dev/orange2/Orange/OrangeCanvas/application/canvasmain.py", line 28, in <module>
    from PyQt4.QtWebKit import QWebView
ImportError: libQtWebKit.so.4: cannot open shared object file: No such file or directory

It seems that the installed Qt package lacks WebKit. I could not find any prebuilt Qt4 with it, and I really did not want to go into compiling Qt and PyQt myself! Remembering that the web interface is mostly used in two places in Orange, help and reports, I tried making WebKit import and its usage optional: see changes to canvasmain.py.

Now, orange-canvas finally opened. But where are the widgets? All widget categories are empty:

To find out why, we need to run with debugging output:

orange-canvas -l4 --force-discovery

We see new exceptions, namely the repeated problems when widgets try to import the reporting functionality:

  ...
  File "/home/marko/dev/orange2/Orange/OrangeWidgets/OWWidget.py", line 319, in <module>
    import OWReport
  File "/home/marko/dev/orange2/Orange/OrangeWidgets/OWReport.py", line 34, in <module>
    from PyQt4.QtWebKit import *
ImportError: libQtWebKit.so.4: cannot open shared object file: No such file or directory

By making reports optional with changes to OWReport.py, some widgets finally appear. Among them, we are lucky to find File and Interaction Graph widgets, precisely the ones we need. For the Interaction Graph to work properly, I also needed to install graphviz:

sudo apt install graphviz

The widgets that still fail to work are mainly visualizations. And for a good reason: Orange 2 visualizations were based on pyqwt5, a library that was already abandoned and hard to install even when Orange 2 was still being actively developed. I did not find any conda-installable packages of pyqwt5, and my first attempts at installing it from the source code failed.

Therefore, I stop. I already have all the parts I need. Now, on to interactions analysis!

This was fun. If anyone attempts a similar journey, I’d love to hear about it, especially if visualizations are working.