max_mac_ll.py.html mathcode2html   
 Source file:   max_mac_ll.py
 Converted:   Sun Aug 7 2016 at 13:47:28
 This documentation file will not reflect any later changes in the source file.

$$\phantom{******** If you see this on the webpage then the browser could not locate *********}$$
$$\phantom{******** jsMath/easy/load.js or the variable root is set wrong in this file *********}$$
$$\newcommand{\vector}[1]{\left[\begin{array}{c} #1 \end{array}\right]}$$ $$\newenvironment{matrix}{\left[\begin{array}{cccccccccc}} {\end{array}\right]}$$ $$\newcommand{\A}{{\cal A}}$$ $$\newcommand{\W}{{\cal W}}$$

#/* Copyright 2008-2013 Research Foundation State University of New York   */
#
#/* This file is part of QUB Express.                                      */
#
#/* QUB Express is free software; you can redistribute it and/or modify    */
#/* it under the terms of the GNU General Public License as published by   */
#/* the Free Software Foundation, either version 3 of the License, or      */
#/* (at your option) any later version.                                    */
#
#/* QUB Express is distributed in the hope that it will be useful,         */
#/* but WITHOUT ANY WARRANTY; without even the implied warranty of         */
#/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
#/* GNU General Public License for more details.                           */
#
#/* You should have received a copy of the GNU General Public License,     */
#/* named LICENSE.txt, in the QUB Express program directory.  If not, see  */
#/* <http://www.gnu.org/licenses/>.                                        */

import numpy
import scipy
import traceback

from qubx.fast.model import *

try:
    importer = ctypes.windll
    base, ext = '','.dll'
except:
    importer = ctypes.cdll
    base, ext = 'lib','.so'

try:
    if ext == '.dll':
        importer.LoadLibrary(base+'OpenCL'+ext) # windows complains if dll's sub-dependencies are missing
    maxmll = importer.LoadLibrary(base+'maxmll_opencl'+ext)
except:
    try:
        maxmll = importer.LoadLibrary(base+'maxmll'+ext)
    except OSError:
        maxmll = importer.LoadLibrary('@executable_path/../Frameworks/libmaxmll_opencl.so') # , mode=ctypes.RTLD_GLOBAL) to be visible from subsequently-loaded libs

class SampleStruct(Structure):
    _fields_ = [('time', c_float),
                ('cur', c_float),
                ('var', c_float)]
PSample = POINTER(SampleStruct)    

class SampleOutStruct(Structure):
    _fields_ = [('fit', c_float),
                ('fit_var', c_float),
                ('ll', c_int)]
PSampleOut = POINTER(SampleOutStruct)    

maxmll.qubx_mac_data_create.argtypes = (c_int, c_int)
maxmll.qubx_mac_data_create.restype = c_void_p
maxmll.qubx_mac_data_reset.argtypes = (c_void_p, c_int, c_int)
maxmll.qubx_mac_data_reset.restype = None
maxmll.qubx_mac_data_free.argtypes = (c_void_p,)
maxmll.qubx_mac_data_free.restype = None
maxmll.qubx_mac_data_append_segment.argtypes = (c_void_p,)
maxmll.qubx_mac_data_append_segment.restype = c_int
maxmll.qubx_mac_data_append_chunk.argtypes = (c_void_p, c_int, c_double, c_int, c_float_p, c_float_p, c_float_p,
                                              c_int_p, c_int_pp, c_float_pp, c_double_pp)
maxmll.qubx_mac_data_append_chunk.restype = None
maxmll.qubx_mac_data_get_stimclasses.argtypes = (c_void_p, c_int_p)
maxmll.qubx_mac_data_get_stimclasses.restype = c_double_p
maxmll.qubx_mac_data_get_stimclass_frac.argtypes = (c_void_p,)
maxmll.qubx_mac_data_get_stimclass_frac.restype = c_double_p
maxmll.qubx_mac_data_get_buffer.argtypes = (c_void_p,)
maxmll.qubx_mac_data_get_buffer.restype = PSampleOut

class Data(object):
    def __init__(self, Nstimsig, data_cap=2**16, file_index=0):
        self.obj = maxmll.qubx_mac_data_create(Nstimsig, data_cap)
        self.Nstimsig = Nstimsig
        self.file_index = file_index
        self.Nsig = Nstimsig + 1
        self.Ndata = 0
    def __del__(self):
        maxmll.qubx_mac_data_free(self.obj)
    def reset(self, Nstimsig, data_cap=2**16):
        maxmll.qubx_mac_data_reset(self.obj, Nstimsig, data_cap)
        self.Nstimsig = Nstimsig
        self.Ndata = 0
    def append_segment(self):
        maxmll.qubx_mac_data_append_segment(self.obj)
    def append_chunk(self, seg_ix, dur_sec, Nd, T, I, V, dwellCounts, classeses, durationses, ampses):
        dcs = numpy.array(dwellCounts, dtype='int32')
        # assuming the elements of classeses and durationses are numpy.arrays of int, float, double respectively
        ccs = (c_int_p*self.Nstimsig)(*[cdata(classes, c_int_p) for classes in classeses])
        dds = (c_float_p*self.Nstimsig)(*[cdata(durations, c_float_p) for durations in durationses])
        aas = (c_double_p*self.Nstimsig)(*[cdata(amps, c_double_p) for amps in ampses])
        maxmll.qubx_mac_data_append_chunk(self.obj, seg_ix, dur_sec, Nd, cdata(T, c_float_p), cdata(I, c_float_p), 
                                          cdata(V, c_float_p), cdata(dcs, c_int_p), ccs, dds, aas)
        self.Ndata += Nd
    def get_stimclasses(self):
        Nstim = c_int()
        self.stimclasses = maxmll.qubx_mac_data_get_stimclasses(self.obj, byref(Nstim))
        self.Nstim = Nstim.value
        return self.stimclasses
    def get_stimclass_frac(self):
        self.sc_frac = maxmll.qubx_mac_data_get_stimclass_frac(self.obj)
        return self.sc_frac
    def get_buffer(self):
        return numpy.frombuffer(pybuf(maxmll.qubx_mac_data_get_buffer(self.obj), int(3*self.Ndata*sizeof(c_float))),
                                dtype='float32', count=3*self.Ndata).reshape((self.Ndata, 3))


class ParamStruct(Structure):
    _fields_ = [('storage', c_void_p),
                ('data', c_void_p),
                ('useVar', c_int),
                ('optNchannel', c_int),
                ('accel', c_int),
                ('Npar', c_int),
                ('NfPar', c_int),
                ('pars', c_double_p),
                ('fPars', c_double_p),
                ('gpu_fail', c_int),
                ('ll', c_double),
                ('float_Nchannel', c_double)]
PParam = POINTER(ParamStruct)

maxmll.qubx_mac_param_create.argtypes = (c_int,)
maxmll.qubx_mac_param_create.restype = PParam
maxmll.qubx_mac_param_free.argtypes = (PParam,)
maxmll.qubx_mac_param_free.restype = None
maxmll.qubx_mac_param_add_model.argtypes = (PParam, PModel, PStimAmps, PStimRates)
maxmll.qubx_mac_param_add_model.restype = None
maxmll.qubx_mac_setup_constraints.argtypes = (PParam,)
maxmll.qubx_mac_setup_constraints.restype = c_int
maxmll.qubx_mac_do_fPars_to_model.argtypes = (PParam,)
maxmll.qubx_mac_do_fPars_to_model.restype = None
maxmll.qubx_mac_calc_std.argtypes = (PParam, c_double_p)
maxmll.qubx_mac_calc_std.restype = None

class Param(object):
    def __init__(self, Nmodel):
        self.obj = maxmll.qubx_mac_param_create(Nmodel)
        self.pars_ = self.fPars_ = []
        self.__data = None
        self.models = []
        self.ampms = []
        self.ratesms = []
    def set_data(self, x):
        self.obj[0].data = x.obj
        self.__data = x
    def add_model(self, fastmodel, ampm, ratesm):
        maxmll.qubx_mac_param_add_model(self.obj, fastmodel.obj, ampm.obj, ratesm.obj)
        self.models.append(fastmodel)
        self.ampms.append(ampm)
        self.ratesms.append(ratesm)
    data = property(lambda self: self.__data, lambda self, x: self.set_data(x))
    def set_useVar(self, x):
        self.obj[0].useVar = x
    useVar = property(lambda self: self.obj[0].useVar, lambda self, x: self.set_useVar(x))
    def set_optNchannel(self, x):
        self.obj[0].optNchannel = x
    optNchannel = property(lambda self: self.obj[0].optNchannel, lambda self, x: self.set_optNchannel(x))
    def set_accel(self, x):
        self.obj[0].accel = x
    accel = property(lambda self: self.obj[0].accel, lambda self, x: self.set_accel(x))
    def set_float_Nchannel(self, x):
        self.obj[0].float_Nchannel = x
    float_Nchannel = property(lambda self: self.obj[0].float_Nchannel, lambda self, x: self.set_float_Nchannel(x))
    Npar = property(lambda self: self.obj[0].Npar)
    NfPar = property(lambda self: self.obj[0].NfPar)
    pars = property(lambda self: self.pars_)
    fPars = property(lambda self: self.fPars_)
    ll = property(lambda self: self.obj[0].ll)
    gpu_fail = property(lambda self: self.obj[0].gpu_fail)
    def __del__(self):
        maxmll.qubx_mac_param_free(self.obj)
    def setup_constraints(self):
        result = maxmll.qubx_mac_setup_constraints(self.obj)
        self.pars_ = numpy.frombuffer(pybuf(self.obj[0].pars, self.Npar*sizeof(c_double)), dtype='float64', count=self.Npar)
        self.fPars_ = numpy.frombuffer(pybuf(self.obj[0].fPars, max(1, self.NfPar)*sizeof(c_double)), dtype='float64', count=max(1, self.NfPar))
        return result
    def do_fPars_to_model(self):
        maxmll.qubx_mac_do_fPars_to_model(self.obj)
    def calc_std(self, InvHessian):
        hess = numpy.array(InvHessian, dtype='float64', copy=True)
        maxmll.qubx_mac_calc_std(self.obj, cdata(hess, c_double_p))
        


maxmll.qubx_mac_ll.argtypes = (PParam,)
maxmll.qubx_mac_ll.restype = c_int

def mac_ll(param):
    if param.data.Ndata == 0:
        return 0.0
    ll = c_double()
    result = maxmll.qubx_mac_ll(param.obj)
    if (0 != result) and (-8 != result):
        raise Exception('Mac error code: %d' % result)
    return param.ll



def setup_test():
    def pr(x):
        print x
    array = numpy.array

    data = Data(1) # TODO: test 0 stim signals
    data.append_segment()
    data.append_chunk(0, .0023, 0, None, None, None, [1], [array([1])], [array([2.3], dtype='float32')], [array([-40.0, 10.0])])
    data.append_chunk(0, .001, 1, array([.003], dtype='float32'), array([50.0], dtype='float32'), array([0.0], dtype='float32'),
                      [1], [array([0])], [array([1.0], dtype='float32')], [array([-40.0, 10.0])])
    model = Model(2, 2, [0, 1], pr)
    model.usePeq = 1
    model.useVar = 1
    model.IeqFv = 1
    model.amp0 = 0.0
    model.var0 = 0.01
    model.Nchannel = 100
    model.iVoltage = 1
    model.Gleak = 0.0
    model.Vrev = -80.0
    model.amp[1] = 10.0
    model.var[1] = 1.0
    model.K0[0,1] = 1000.0
    model.K0[1,0] = 1000.0
    model.K1[0,1] = 0.1
    model.V[0,1] = 1
    model.setup_stim(data)
    model.fix_channelcount()
    model.setup_constraints()
    
    return model, data

def setup_data(data_path, delta):
    file = qubx.data_types.Open(data_path)
    
    for f,l,n in file.segmentation.segments:
        pass ###
    data = Data(Nstimsig) # TODO: test 0 stim signals
    data.append_segment()
    data.append_chunk(0, .0023, 0, None, None, None, [1], [array([1])], [array([2.3], dtype='float32')], [array([-40.0, 10.0])])
    data.append_chunk(0, .001, 1, array([.003], dtype='float32'), array([50.0], dtype='float32'), array([0.0], dtype='float32'),
                      [1], [array([0])], [array([1.0], dtype='float32')], [array([-40.0, 10.0])])

def setup_model(model_path, data):
    def pr(x):
        print x
    array = numpy.array
    
    model, model_file = setup_model(model_path)
    file = qubx.model.QubModel()
    file.from_tree(qubx.tree.Open(model_path, True))
    clazz = ModelToClazz(file)
    Nclass = int(max(clazz) + 1)
    model = max_mac_ll.Model(model.states.size, Nclass, clazz, pr)
    model.usePeq = Peq
    if notPeq:
        model.P0[:] = ModelToP0(file)
    model.useVar = True ##
    model.IeqFv = file.IeqFv
    model.Nchannel = file.channelCount
    model.iVoltage = data.iVoltage
    model.Gleak =Gleak
    model.Vleak =Vleak
    model.Vrev = file.vRev
    if model.IeqFv:
        for s in xrange(Nclass):
            model.amp[s] = file.classes.get(s, 'Cond')
            model.var[s] = file.classes.get(s, 'CondStd')**2
        model.amp0 = file.classes.get(0, 'Amp')
        model.var0 = file.classes.get(0, 'Std')**2
    else:
        for s in xrange(Nclass):
            model.amp[s] = file.classes.get(s, 'Amp')
            model.var[s] = file.classes.get(s, 'Std')**2
    K0, K1, L, V = ModelToRateMatrices(file, data.signal_names)
    model.K0[:] = K0[:]
    model.K1[:] = K1[:]
    model.L[:]  = L[:]
    model.V[:]  = V[:]
    model.setup_stim(data)
    A, B = file.constraints_kin.get_matrices(K0, K1, L, V)
    model.Ain[:A.shape[0],:A.shape[1]] = A
    model.Bin[:B.shape[0]] = B.flatten()
    model.Ncns = B.shape[0]
    model.setup_constraints()

    return model, file

def setup_files(data_path, model_path, delta):
    def pr(x):
        print x
    array = numpy.array
    
    data = setup_data(data_path, delta)
    model, model_file = setup_model(model_path, data)
    
    return model, data

if __name__ == '__main__':
    try:
        import datetime
        import optparse
        import sys
        import qubx.fast
        import qubx.model
        import qubx.model_constraints
        import qubx.data_types
        usage = "usage: %prog [options] file(s)"
        parser = optparse.OptionParser(usage)
        parser.add_option("-a", "--accel-level", dest="accel",
                          action="store",
                          default=2,
                          help="0: single-thread; 1: openmp; 2: opencl")
        parser.add_option("-r", "--resample-delta", dest="delta",
                          action="store", default=0.0,
                          help="if nonzero, resample-by delta")
        parser.add_option("-d", "--data", dest="data_path",
                          action="store", default="",
                          help="/path/to/data.qdf")
        parser.add_option("-m", "--model", dest="model_path",
                          action="store", default="",
                          help="/path/to/model.qmf")
        options, args = parser.parse_args()
        model, data = setup_files(options.data_path, options.model_path, options.delta)
        mac_ll(model, data, options.accel) # get it warmed up
        before = datetime.datetime.now()
        print mac_ll(model, data, options.accel),
        delta = datetime.datetime.now() - before
        print delta.seconds, (delta.microseconds / 1000), (delta.microseconds % 1000)
    except:
        traceback.print_exc()
        model, data = setup_test()
        print 'K0',model.K0
        print 'K1',model.K1
        print 'Nchannel',model.Nchannel
        print 'xamp',model.xamp
        print 'xvar',model.xvar
        print 'fPars',model.fPars
        print 'a'
        print mac_ll(model, data)
        print 'b'
        del data, model
        print 'c'