In [1]:
    
import pandas as pd
import struct
import re
import numpy as np
import matplotlib.colors as cols
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# %matplotlib inline
    
In [2]:
    
def read_pos(f):
    # read in the data
    n = len(file(f).read())/4
    d = struct.unpack('>'+'f'*n,file(f).read(4*n)) 
                    # '>' denotes 'big-endian' byte order
    # unpack data
    pos = pd.DataFrame({'x': d[0::4],
                        'y': d[1::4],
                        'z': d[2::4],
                        'Da': d[3::4]})
    return pos
    
In [3]:
    
pos = read_pos('../example-data/voldata.pos')
    
In [2]:
    
def read_epos(f):
    # read in the data
    n = len(file(f).read())/4
    rs = n / 11
    d = struct.unpack('>'+'fffffffffII'*rs,file(f).read(4*n)) 
                    # '>' denotes 'big-endian' byte order
    # unpack data
    pos = pd.DataFrame({'x': d[0::11],
                        'y': d[1::11],
                        'z': d[2::11],
                        'Da': d[3::11],
                        'ns': d[4::11],
                        'DC_kV': d[5::11],
                        'pulse_kV': d[6::11],
                        'det_x': d[7::11],
                        'det_y': d[8::11],
                        'pslep': d[9::11], # pulses since last event pulse
                        'ipp': d[10::11]}) # ions per pulse
    return pos
    
In [3]:
    
epos = read_epos('../example-data/voldata.epos')
    
In [4]:
    
epos
    
    Out[4]:
In [5]:
    
len(epos.loc[epos.ipp != 1, :]) / float(len(epos))
    
    Out[5]:
In [6]:
    
len(epos)
    
    Out[6]:
In [7]:
    
def read_rrng(f):
    rf = open(f,'r').readlines()
    patterns = re.compile(r'Ion([0-9]+)=([A-Za-z0-9]+).*|Range([0-9]+)=(\d+.\d+) +(\d+.\d+) +Vol:(\d+.\d+) +([A-Za-z:0-9 ]+) +Color:([A-Z0-9]{6})')
    ions = []
    rrngs = []
    for line in rf:
        m = patterns.search(line)
        if m:
            if m.groups()[0] is not None:
                ions.append(m.groups()[:2])
            else:
                rrngs.append(m.groups()[2:])
    ions = pd.DataFrame(ions, columns=['number','name'])
    ions.set_index('number',inplace=True)
    rrngs = pd.DataFrame(rrngs, columns=['number','lower','upper','vol','comp','colour'])
    rrngs.set_index('number',inplace=True)
    
    rrngs[['lower','upper','vol']] = rrngs[['lower','upper','vol']].astype(float)
    rrngs[['comp','colour']] = rrngs[['comp','colour']].astype(str)
    
    return ions,rrngs
    
In [8]:
    
ions, rrngs = read_rrng('../example-data/rangefile.rrng')
    
In [9]:
    
def label_ions(pos,rrngs):
    pos['comp'] = ''
    pos['colour'] = '#FFFFFF'
    
    for n,r in rrngs.iterrows():
        pos.loc[(pos.Da >= r.lower) & (pos.Da <= r.upper),['comp','colour']] = [r['comp'],'#' + r['colour']]
    
    return pos
    
In [10]:
    
lpos = label_ions(pos,rrngs)
    
    
In [28]:
    
def deconvolve(lpos):
    """Takes a composition-labelled pos file, and deconvolves
    the complex ions. Produces a dataframe of the same input format
    with the extra columns:
       'element': element name
       'n': stoichiometry
    For complex ions, the location of the different components is not
    altered - i.e. xyz position will be the same for several elements."""
      
    out = []
    pattern = re.compile(r'([A-Za-z]+):([0-9]+)')
    for g,d in lpos.groupby('comp'):
        if g is not '':
            for i in range(len(g.split(' '))):
                tmp = d.copy()
                cn = pattern.search(g.split(' ')[i]).groups()
                tmp['element'] = cn[0]
                tmp['n'] = cn[1]
                out.append(tmp.copy())
    return pd.concat(out)
    
In [29]:
    
dpos = deconvolve(lpos)