Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

23 August 2017

645. Moodle on Debian

I want to play around with moodle on my own desktop so I can experiment before making any major commits to a course website.

I first had a look at, but, realising that moodle is in sid, decided to build my own .deb package.

This was done on debian jessie (8.9), which has at this point been overtaken by stretch as stable. I'm thus three releases behind sid.

1. Add the sid /src/ repo to sources.list
deb-src sid main non-free contrib

2. Get source and build
I don't know exactly what dependencies you'll need. Error messages will tell you.
sudo apt-get update sudo apt-get install build-essential dpkg-dev mysql-server mysql-client php5-xmlrpc php5-intl sudo service mysql start mkdir ~/tmp/moodle -p cd ~/tmp/moodle sudo apt-get source moodle
Edit debian/control (necessary if you're on Jessie/8.9 -- newer debian versions may not need this):
14 Depends: ${misc:Depends}, 15 php5, php5-mysql | php5-pgsql, php5-gd, php5-curl, php5-cli, 16 apache2 | httpd, ucf, postgresql-client | default-mysql-client | virtual-mysql-client, 17 dbconfig-common, libphp-phpmailer, libphp-adodb, php-htmlpurifier, php-tcpdf, 18 php-cas (>= 1.3.3-1), libjs-jquery-migrate-1 19 Pre-Depends: debconf (>= 0.5) | debconf-2.0
Then continue in the terminal:
cd ~/tmp/moodle-2.7.19+dfsg sudo dpkg-buildpackage -us -uc cd .. sudo dpkg -i moodle_2.7.19+dfsg-2_all.deb sudo apt-get -f install sudo cp /etc/moodle/apache.conf /etc/apache2/sites-available/moodle.conf sudo ln -s /etc/apache2/sites-available/moodle.conf /etc/apache2/sites-enabled/moodle.conf sudo chmod o+r /etc/apache2/sites-available/moodle.conf sudo chmod go+w /var/lib/moodle sudo service apache2 reload
Navigate to http://localhost/moodle and follow the prompts

20 November 2014

603. Mobile bankid; works fine in a VM too

Turns out I got it wrong in my earlier post -- mobile bankid has nothing to do with the telecom network.

How it works:
1. Phone: Start BankID on your phone. The program will say that it's waiting for a connection.
2. Computer: You go to your bank/government service web page, select Mobile BankID, then type in your 'person nummer' (like SSN).
3. Phone: BankID on your phone will then prompt you for your PIN.
4. Computer: You're logged in.

It's all happening over the internet. Sure, it might not work if you change SIM, for example, but at least it's not telephony based.

Best of all, I could get an activation code for mobile bankid using the win 7 bankid instance I set up in and now I never have to use it again.

[if you're on linux and in Scandinavia, just install mobile bankid on your phone or on android in a vm]

So, if you're on linux and you've been using the official bankid application and you happen to be a couple of continents removed from Scandinavia follow this post which basically does the following:
1. Install ubuntu 10.04 LTS in a VM
2. Install bankid 4.19.XXXX or earlier in the ubuntu VM
3. Copy your ~/.personal from your regular linux computer to the ubuntu VM
4. export your key using persadm export to a USB stick
5. Install windows 7 in a VM using the free, legal isos and the free, legal installation key. The copy will expire after 30 days (but will still continue working).
6. Install bankid in the Win 7 VM
7. Under File/Preferences in bankid add the directory on your USB stick with the exported bankid key
8. Log in to your BankID issuer (probably your bank) using bankid 'on file', and request a mobile bankid. You'll get an activation code
9. Install the bankid app on your phone (e.g. bankid from the play store on android)
10. Start the bankid app on your phone, and type in your personnummer and the activation code. Create a pin, which is your password
11. You're done.

I mean, sure, it's a very awkward way of going about it, but it works and is conceptually simple.

Android in a VM
And there's absolutely no reason you can't use mobile bankid it in a virtualbox VM if you want to -- I used an android 4.4 x86 iso and created a virtual machine, and then set up bankid which works fine.

28 July 2014

587. Very Briefly: Getting pictures off of a corrupted Compact Flash card using testdisk

Nothing terribly complicated here. My CFII card (above, at /dev/sdb1)  is about a decade old and occasionally becomes corrupted. To recover the photos I use photorec which is part of testdisk:

sudo apt-get install testdisk
sudo photorec

Select the correct device, in this case /dev/sdb


Pick the correct file system, typically FAT16 or 32
Also select a place to store the recovered photos. Then recover:

And you're done.

586.Very Briefly: Gnuradio, RTL-SDR, GQRX and an R280T device on debian jessie

* I did this on debian jessie which at the time has gnuradio v 3.7.3-9+b1 and rtl-sdr v 0.5.3-3

* I'm having a lot of trouble getting gqrx working on debian wheezy even with backports. Whereas the backports versions of gnuradio, rtl-sdr and gqrx-sdr install just fine, when running gqrx I get the following error:
gqrx: symbol lookup error: /usr/lib/x86_64-linux-gnu/ undefined symbol: _ZN16QIODevicePrivate13putCharHelperEc
* gqrx won't work on debian wheezy systems with 2 Gb of memory for some reason. I get the same error as is shown in this post:!topic/gqrx/20F8RMWkNbU

The post:
I recently bought a DVB USB dongle based on RTL2832 and R280T: AU$11for a TV card which actually works flawlessly under linux really isn't bad!

As I already have a mythtv setup using leadtek DTV 1000S I was more interested in exploring the R820T dongle as a software defined radio (SDR).

 So, after glancing at I did the following

sudo apt-get install rtl-sdr gnuradio gnuradio-dev libgnuradio-osmosdr0.1.1.4 git libboost-dev liblog4cpp5-dev libboost-system-dev libboost-program-options-dev checkinstall
mkdir ~/tmp
cd ~/tmp
git clone gqrx.git
cd gqrx.git/
mkdir build
cd build
qmake ../
sudo checkinstall --install=no
0 - Maintainer: [ root@niobium ] 1 - Summary: [ gqrx ] 2 - Name: [ gqrx ] 3 - Version: [ 20140726 ] 4 - Release: [ 1 ] 5 - License: [ GPL ] 6 - Group: [ checkinstall ] 7 - Architecture: [ amd64 ] 8 - Source location: [ build ] 9 - Alternate source location: [ ] 10 - Requires: [ ] 11 - Provides: [ build ] 12 - Conflicts: [ ] 13 - Replaces: [ ]
sudo dpkg -i gqrx_20140726-1_amd64.deb

Starting gqrx and using it is easy:
So far I haven't managed to get anything other than regular commercial radio signals (I've only explored the FM band).

29 May 2014

579. TEMPerHum (0c45:7402 ) on debian linux wheezy

Yet another little usb device from PC sensors (I seem to have been giving them a fair amount of money recently ).

This is the device in question: (note that I buy my devices via ebay where the prices are apparently always the campaign ones -- I paid AUD25 , not USD80)

It didn't come in a box so I have no scans or shots to show.

[See here for the regular TEMPer USB device (0c45:7401), and here for the TEMPer 1K4  (0c45:7403) USB thermocouple reader. Note that since the temper-usb code is in  a lot of flux you can't use the line numbers in those posts directly -- you'll have to read and understand the code before pasting it in. Luckily, it's quite simple -- even I managed to sort it out!]

I couldn't get temper-usb to work even when making (what I consider) the necessary edits, but instead got lots of errors (including " usb.USBError: could not detach kernel driver from interface 1: No data available"). So I finally gave up.

Instead, web searching led me to -- one of the replies by eg1l spelled out the solution -- I'll grant myself the liberty to repost it here, but please remember where it originally came from and link to the original article (exclusively or in addition).

mkdir ~/tmp
cd ~/tmp/
sudo apt-get install libudev-dev libusb-1.0.0-dev libfox-1.6-dev autoconf cmake

git clone git://
cd hidapi/
cd libusb/
sudo make install

cd ../../

git clone git://
cd TEMPered/
mkdir build
cd build/
cmake ..
cd utils/
sudo ./tempered 
cd ../
sudo make install

sudo ln -s /usr/local/lib/x86_64-linux-gnu/ /usr/local/lib/
sudo ln -s /usr/local/lib/x86_64-linux-gnu/ /usr/local/lib/
sudo ldconfig

sudo tempered
0006:000e:01 0: temperature 21.75 °C, relative humidity 49.1%, dew point 10.6 °C

Create an 80-temper.rules file in /etc/udev/rules.d:
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0c45", ATTRS{idProduct}=="7401", GROUP="users", MODE="0666"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0c45", ATTRS{idProduct}=="7402", GROUP="users", MODE="0666"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0c45", ATTRS{idProduct}=="7403", GROUP="users", MODE="0666"

Then do
sudo usermod -a -G users $USER

sudo service udev restart

Unplug and re-plug your device, then open a new terminal and you're set (type group to make sure that users show up).

me@boron:~$ tempered
0006:000f:01 0: temperature 23.34 °C, relative humidity 46.8%, dew point 11.3 °C

13 May 2014

576. Shortening the bash prompt in debian

This is yet another post in which I'm (almost) simply reposting a solution that someone else has already posted online.

Let's say that my contribution is to put it in context of debian.

Either way, here's the problem that needed solving: the debian prompt by default lists all directories, which sometimes means that the prompt itself breaks across two lines.

Luckily, it's not difficult to chop the prompt down to a more manageable, yet still informative, length. The solution is here (we do like a descriptive URL):

That particular solution also allows you to change the permissible length of the path that will be shown -- change the 50 in the argument to droppath to set the number of chars.

Edit your ~/.bashrc and add the bits in red:
# drops first portion of a path $1 if length is greater than $2 function __droppath { if [[ ${#1} -gt $2 ]]; then p=$1 while [ ${#p} -gt $2 ]; do p="/"$(echo "$p"|cut -d"/" -f3-) done echo "..."$p else echo $1 fi } if [ "$color_prompt" = yes ]; then PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]$(_droppath "\w" 50)\[\033[00m\]\$ ' else PS1='${debian_chroot:+($debian_chroot)}\u@\h: $(__droppath "\w" 50)\$ ' fi

and here's an example using a length of 25 chars (which is a bit short).

me@niobium: /usr/local/lib/python2.7/site-packages$\

me@niobium: .../python2.7/site-packages$

You can always use pwd to figure out what the full path is if necessary:
me@niobium: .../python2.7/site-packages$ pwd

20 April 2014

573. PCSensors K-type USB thermocouple adapter TEMPer1K4 (0c45:7403) on debian

UPDATE 1 May 2014:
I've rewritten the code now to properly deal with the presence of both a 0c45:7401 and a 0c45:7403 simultaneously. Note that I'm not convince about the accuracy of the temperature readings (accuracy as in whether there's any systematic bias to the output. The reproducibility seems to be excellent though).

Original post:
I just received this usb thermocouple reader (TEMPer1k4):

About the product:
lsusb shows 0c45:7403 (Microdia Foot Switch)

dmesg shows
[13448.536120] usb 6-1: new low-speed USB device number 3 using uhci_hcd [13448.709126] usb 6-1: New USB device found, idVendor=0c45, idProduct=7403 [13448.709139] usb 6-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 [13448.709146] usb 6-1: Product: TH1000isoV1.5 [13448.709152] usb 6-1: Manufacturer: RDing

Getting it to work:
You can use the same program as in this post: with some minor modifications. Before running
sudo python install

make some changes in temperusb/

Firstly, you need to allow for the detection of devices with the 0c45:7403 ID
15 VIDPIDs = [(0x0c45L,0x7401L),(0x0c45L,0x7403L)]
Secondly, you need to make sure that the program knows which device is which and treats them differently. Finally, you need to collect the right data-- the TEMPer1k4 returns a data_s with a length of 8 (caveat -- I haven't checked what the output from 0c45:7401 looks like. Maybe it too yields 8 fields), and the [2:4] data block contains the internal temperature of the USB device, while the [4:6] data block holds the thermocouple junction temperature. Of a sort -- you get a number which you need to translate into a temperature. See the bottom of this post for how I worked it all out. Please note that you should calibrate the thermocouple -- the uncorrected output seems to be at least 2-3 degrees too high.
 15 VIDPIDs = [(0x0c45L,0x7401L),(0x0c45L,0x7403L)]

 63     def getid(self):
 64         return self._device.idProduct

125             if self._device.idProduct==29697:
126                 temp_c = 125.0/32000.0*(struct.unpack('>h', data_s[2:4])[0])+0.0025
127                 if format == 'celsius':
128                     temp_c = temp_c * self._scale + self._offset
129                     return temp_c
130                 elif format == 'fahrenheit':
131                     return temp_c*1.8+32.0
132                 elif format == 'millicelsius':
133                     return int(temp_c*1000)
134                 else:
135                     raise ValueError("Unknown format")
136             elif self._device.idProduct==29699:
137                 temp_c = (struct.unpack('>h', data_s[4:6])[0])*0.25-2.00
138                 temp_internal=(125.0/32000.0*(struct.unpack('>h', data_s[2:4])[0]))+0.0025
139                 if format == 'celsius':
140                     temp_c = temp_c * self._scale + self._offset
141                     return temp_c
142                 elif format == 'fahrenheit':
143                     if self._device.idProduct==29697: #0x7401
144                         return temp_c*1.8+32.0
145                     elif self._device.idProduct==29699: #0x7403
146                         return temp_internal
 31     for i, dev in enumerate(devs):
 32         readings.append({'device': i,
 33                          'id':dev.getid(),
 34                          'temperature_c': dev.get_temperature(),
 35                          'temperature_f':
 36                          dev.get_temperature(format="fahrenheit"),
 37                          'ports': dev.get_ports(),
 38                          'bus': dev.get_bus()
 39                          })
 41     for reading in readings:
 42         if disp_ports:
 43             portinfo = " (bus %s - port %s)" % (reading['bus'],
 44                                                 reading['ports'])
 45         else:
 46             portinfo = ""
 47         if reading['id']==29697:
 48             print('Device #%i%s: %0.1f°C %0.1f°F'
 49                   % (reading['device'],
 50                      portinfo,
 51                      reading['temperature_c'],
 52                      reading['temperature_f']))
 53         elif reading['id']==29699:
 54             print('Device #%i%s: %0.1f°C %0.1f°C'
 55                   % (reading['device'],
 56                      portinfo,
 57                      reading['temperature_c'],
 58                      reading['temperature_f']))

Beyond this, follow the instructions in and make sure to set up a rules file with the correct USB ID for this device.


If you're curious about the details, have a look below.

Analysing USB traffic:
Since I wasn't quite sure where to start I figured the easiest approach would be to sniff the traffic between the usb device and the offically supported programme from PC Sensors. So I installed it Win XP in virtualbox, read a couple of temperatures and compared them with the captured data.

To capture data I did:
sudo apt-get install tshark
sudo modprobe usbmon
Bus 008 Device 003: ID 17ef:4815 Lenovo Integrated Webcam [R5U877] Bus 008 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 004 Device 043: ID 0c45:7403 Microdia Foot Switch Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 007 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
sudo tshark -D
1. eth0 2. wlan0 3. nflog 4. nfqueue 5. usbmon1 6. usbmon2 7. usbmon3 8. usbmon4 9. usbmon5 10. usbmon6 11. usbmon7 12. usbmon8 13. any 14. lo (Loopback)
touch 1.pcap chmod ugo+w 1.pcap sudo tshark -i usbmon4 -w $HOME/1.pcap

I opened the 1.pcap file in wireshark and looked for fields called leftover data.

Here are two examples of such 'leftover data' fields:
Host to USB: 01 80 00 00 00 00 00 00
USB to Host: 80 06 17 f0 00 5c 0f ff

Subjecting the system to different temperatures helped me figure out what fields where changing -- I've marked them in bold above (blue for the thermocouple, red for the internal temperature). Interestingly, I got overflow when freezing the thermocouple between two ice cubes, which indicated that there was a fairly high lower limit (1.5 degrees)
The following are some of the data I harvested. The temperature is in the first column, the hex code is in the second one and the decimal value is in the third one:
23.63 17a 378
23.69 17b 379
23.94 17f 383
23.75 17c 380
21.88 15e 350
22.31 165 357
22.88 16e 366

Thermocouple: 23.75 05f 95 23.50 05e 9 38.25 099 153 24.00 066 102 87.50 15e 350 79.50 13e 318
In other words, T(thermo)=output(thermo)*0.25+1.50 and T(int.)=(output(int.)-0.0025)/0.0625. Because the internal data is in fields 2:4 it's seen as e.g. 17b0 instead of 17b, so the decimal version needs to be divided by 16 (line 126 above).

I also set up an /etc/temper.conf file and did chown $USER /etc/temper.conf in order to be able to read it (must be a better way). I tried to calibrate the thermocouple in my kitchen with iced water and boiling water. The boiling water gave a reading of 102 degrees, while the iced water gave me 7.5 degrees Celsius even after what should've been long enough to achieve equilibrium. I'll calibrate it in the lab later. So for now a simple offset might be enough to give a working temperature.
temper-poll -p
Device #0 (bus 2 - port 2)
so temper.conf became
2-2: scale = 1.00, offset = -4.0

The temper-usb code is changing too quickly!. You'll thus need to read and understand the code rather than just pasting it in. Here are the full, edited an files.
# encoding: utf-8
from __future__ import print_function
from temper import TemperHandler

def main():
    th = TemperHandler()
    devs = th.get_devices()
    readings = []
    print("Found %i devices" % len(devs))

    for i, dev in enumerate(devs):
        readings.append({'device': i,
                         'temperature_c': dev.get_temperature(),

    for reading in readings:
  if reading['id']==29697:
   print('Device #%i: %0.1f°C %0.1f°F' % (reading['device'],
  elif reading['id']==29699:
   print('Device #%i: %0.1f°C %0.1f°C' % (reading['device'],
# encoding: utf-8
# Handles devices reporting themselves as USB VID/PID 0C45:7401 (mine also says RDing TEMPerV1.2).
# Copyright 2012, 2013 Philipp Adelt 
# This code is licensed under the GNU public license (GPL). See for details.

import usb
import sys
import struct

VIDPIDs = [(0x0c45L,0x7401L),(0x0c45L,0x7402L),(0x0c45L,0x7403L)]
TIMEOUT = 2000

class TemperDevice():
    def __init__(self, device):
        self._device = device
        self._handle = None

    def get_temperature(self, format='celsius'):
            if not self._handle:
                self._handle =
                except usb.USBError:
                except usb.USBError:
                self._handle.controlMsg(requestType=0x21, request=0x09, value=0x0201, index=0x00, buffer="\x01\x01", timeout=TIMEOUT) # ini_control_transfer

            self._control_transfer(self._handle, "\x01\x80\x33\x01\x00\x00\x00\x00") # uTemperatura
            self._control_transfer(self._handle, "\x01\x82\x77\x01\x00\x00\x00\x00") # uIni1
            self._control_transfer(self._handle, "\x01\x86\xff\x01\x00\x00\x00\x00") # uIni2
            self._control_transfer(self._handle, "\x01\x80\x33\x01\x00\x00\x00\x00") # uTemperatura
            data = self._interrupt_read(self._handle)
            data_s = "".join([chr(byte) for byte in data])

            if self._device.idProduct==29697: 
    temp_c = 125.0/32000.0*(struct.unpack('>h', data_s[2:4])[0])+0.0025
    if format == 'celsius':
     return temp_c
    elif format == 'fahrenheit':
     return temp_c*1.8+32.0
    elif format == 'millicelsius':
     return int(temp_c*1000)
     raise ValueError("Unknown format")
            elif self._device.idProduct==29699: 
    temp_c = (struct.unpack('>h', data_s[4:6])[0])*0.25-4.00
    temp_internal=(125.0/32000.0*(struct.unpack('>h', data_s[2:4])[0]))+0.0025
    if format == 'celsius':
     return temp_c
    elif format == 'fahrenheit':
     if self._device.idProduct==29697: #0x7401
      return temp_c*1.8+32.0
     elif self._device.idProduct==29699: #0x7403
      return temp_internal
    elif format == 'millicelsius':
     return int(temp_c*1000)
     raise ValueError("Unknown format")
        except usb.USBError, e:
            if "not permitted" in str(e):
                raise Exception("Permission problem accessing USB. Maybe I need to run as root?")
    def getid(self):
        #print self._device.idProduct
        return self._device.idProduct

    def close(self):
        if self._handle:
            except ValueError:
            self._handle = None

    def _control_transfer(self, handle, data):
        handle.controlMsg(requestType=0x21, request=0x09, value=0x0200, index=0x01, buffer=data, timeout=TIMEOUT)

    def _interrupt_read(self, handle):
        return handle.interruptRead(0x82, REQ_INT_LEN)

class TemperHandler():
    def __init__(self):
        busses = usb.busses()
        self._devices = []
        for bus in busses:
            self._devices.extend([TemperDevice(x) for x in bus.devices if (x.idVendor,x.idProduct) in VIDPIDs])

    def get_devices(self):
        return self._devices

28 February 2014

558. More options for PDF annotation: Master PDF Editor and I, Librarian

This is an update to my previous posts (here and here) about annotating PDFs on Linux.

Master PDF Editor
The linux version of this software is free and closed source. It will not run on Debian Wheezy, as it requires glibc >= 2.14, whereas Wheezy has version 2.13. You can either pull in a newer libc from testing, or simply use testing (Jessie). See here for how to use glibc > 2.13 on wheezy:

So I tried it on Jessie.

While it almost works, I can't prevent the program from screwing up the fonts in the process. Also, the annotations don't show up in acroread for some reason. Saving as PDF/A didn't make any positive difference.

The annotation shows up in evince -- but the font's weird now

Same goes for Xournal

In acrobat reader before editing with Master PDF Editor
in acrobat reader after adding an annotation. The annotation doesn't show up, but the fonts are screwed up.

So we're almost there -- Master PDF Editor does everything I want in terms of PDF annotation, but at least on linux there are issues with the fonts in the resulting PDFs.

I, Librarian
I, Librarian is both free and open source. It claims to be web-based -- which is true but can be misunderstood. What it means is that it is browser-based and runs a server on your computer. My first thought when I see 'web-based' is that I'm handing over my data to someone else, but luckily that's not the case here.

I installed the .deb file meant for ubuntu.

Using I, Librarian is quite straight forward, but I could not see the annotations in any other program that I tried, which makes it of little use for me -- I make annotations in galley drafts for journal editors, and for students to give them feedback on latex documents.

Either way, to start, just go to

Make sure to edit the settings to make I, Librarian use the internal pdf viewer in order for editing to work.

No matter what I did, I could not export my pinned annotations though. They did not show up in either evince or acroread.

19 February 2014

557. Briefly: Drawing Molecules on Linux: ACD/ChemSketch in Wine

This is another post where I'm cheating a bit -- this is a windows program running in wine.

Let me explain. Sometimes you absolutely need to get a task done -- I use linux at work and I can't not do something just because I can't write/find a piece of software that does it for me. Science is the goal, and the route there is immaterial. So sometimes you need to be pragmatic about your software choices.

I much prefer to use free and open source software since it allows me to keep a copy of the source code which I can recompile in case the prebuilt binary suddenly won't work with a future version of debian. Having the source makes me feel more secure in the assertion that it's worth my time learning how to use that piece of software.

Second to that, I prefer native linux software -- although unfortunately 'native' here often means 'written in java', and -- while not knowing too much about java -- from a user point of view java software tends to be comparatively slow to load and run. Certainly it appears slower than a comparable C/C++ program.

As a last resort, I can accept having to run a windows binary in wine. It doesn't make me happy, and often there are small, niggling issues associated with it -- but if it can get the job done, so be it.

Note that I'm unwilling to actually run a native windows program on a native windows installation -- one has to have some standards...

Either way, this is why I look at windows programs as well for drawing structures and processing NMR spectra.

So I recently tested marvinsketch (linux), bkchem (linux), easychem (linux), chemtool (linux), gchempaint (linux), ISISDraw (wine) and ChemSketch (wine). Out of those I prefer MarvinSketch. However, I'm still exploring the alternatives.

ACD/ChemSketch for Linux is really just an older (2006) version of ACD/LABS free ChemSketch (the windows version is from 2013). To get it, go to and click on Download. I tried the version 'for linux', and not the windows one. I'm making the presumption that the newer binary won't play well with wine.

You don't need to be an academic to qualify for the free version.

wine ~/Downloads/chemsk50.exe

Once it's installed you can explore ChemSketch. Overall it's fairly similar to e.g. ISISDraw.

18 February 2014

556. Briefly: Drawing molecules on linux: ghempaint, chemtool and easychem

chemtool, easychem and gchempaint are in the Wheezy repos.
See also the following posts for ISISDraw, MarvinSketch and BKChem.

I didn't get along with this at all. I managed to import a few structures from the templates, but e.g. the clean molecule function didn't actually work, although it's there. Selecting, deleting etc. were all a bit non-intuitive (to me -- this is obviously very subjective)

I can't find any templates. Drawing becomes a bit tedious since I didn't find an easy way of converting an existing bond from e.g. single to double.

It's pretty straightforward to use and I like it the best of the three. However, it's still very sparse even compared to e.g. bkchem. It certainly works if you quickly need to make a simple structure. There's no clean function.

555. Very Briefly: Drawing molecules on linux: bkchem

I can't evaluate drawing programs on linux without giving bkchem a look. In fact, up till now this has been my preferred drawing application on linux, in particular since it uses .svg as it's native file format i.e. it's very easy to post-process drawing and turn them into proper .eps files for inclusion in latex documents.

bkchem is in the debian repos:
sudo apt-get install bkchem

It's a very basic program, although looking through the options it isn't too feature sparse either.

However, there's one important feature that ISISDraw and MarvinSketch have that I can't find in bkchem: it's lacking a function to clean molecules i.e. to make them look nice.

554. Briefly: Drawing molecules on linux: Marvinsketch

I don't remember how I installed this, but marvinsketch is by far the fanciest molecular drawing application on linux. It's written in java, which means that it runs natively (well, as natively as something like java can run).

Note: it's free for academia only and you will need to register.

To get MarvinBeans, go to and register as an academic. Then go to and download the 64 bit linux installer with jre.

Presumable you can install it by doing

in the download directory.
Once it's installed create a file called ~/.local/share/applications/marvinsketch.desktop:
[Desktop Entry] Name=MarvinSketch GenericName=MarvinSketch Comment=Software for drawing molecules Exec=sh /home/me/ChemAxon/MarvinBeans/MarvinSketch Terminal=false Type=Application Categories=Science Version=6.1

You should now be able to find it in GNOME 3.

There are a lot of similarities between ISISDraw and MarvinSketch -- and that's a good thing since it allows people like myself to draw molecules quickly without thinking too much about it.
A Blank slate

Running Chem Inspector

It didn't like my wedges

I turned the structure into 3D and rotated it

Elemental analysis

553. Briefly: Drawing molecules on Debian Wheezy: ISISDraw under wine (very briefly)

I'm cheating here: this isn't a program for linux. Instead we're running a windows program under wine, which is not ideal. On the other hand, it's so easy to do that it's worth exploring as an option to 'pure' linux offerings.

I'll be posting about native linux offerings later.

Either way, I've kept a copy of ISISDraw 2.5 around since the early 2000s. Luckily, other people are mirroring the installation file for it as well. See e.g. for ISISDraw 2.4

 You'll need to install wine:i386 and for that you'll need to enable multiarch if you're on amd64:
sudo dpkg --add-architecture
sudo apt-get update
sudo apt-get install wine:i386
wine DRAW24.EXE

As always, if you have problems with e.g. weird fonts, use winetricks to install at least corefonts, or ideally allfonts:
sudo mv winetricks /usr/bin/winetricks
chmod +x /usr/bin/winetricks 
winetricks allfonts

Then run ISISDraw:
A blank slate
 ISISDraw has a lot of options, including templates and journal settings.
Chem Inspector
 There's a bug under wine: to get the menus for the buttons on the left side to show up, click on the button on the left panel, and then move the mouse left while still holding the button down.
To get the menus to work, click and while still holding the left button down move right
 ISISDraw is not going to blow you away, but it's free and it works under wine.