max_inter_ll.cpp.html | mathcode2html |
Source file: max_inter_ll.cpp | |
Converted: Sat May 9 2015 at 14:46:13 | |
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-2014 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/>. */ /*
|
See also: Up: Index |
*/ #ifdef _WIN32 #include <windows.h> #else #include <stdlib.h> #define BOOL int #define TRUE 1 #define FALSE 0 #endif #include <string.h> #include <iostream> #include <fstream> #include <string.h> #include <set> #include <boost/math/special_functions/next.hpp> #define TDEAD_DELTA_FLOATS 5 #include "max_inter_ll.h" #include "../qubfast/max_ll_util.h" #include "../qubfast/ublas_matrixutil.h" using std::cout; using std::cerr; using std::endl; using std::set; extern "C" MAXILL_API int inter_ll_arr( int Ns, int *clazz, double *P0_in, double *K0_in, double *K1_in, double *K2_in, int *Ligand_in, int *Voltage_in, int *Pressure_in, double *Constants, double tdead, int Nseg, int *dwellCounts, int **classeses, float **durationses, double *ll) { std::vector<double*> K0, K1, K2; std::vector<int*> Lig, Vol, Pres; for (int i=0; i<Ns; ++i) { K0.push_back( K0_in + i*Ns ); K1.push_back( K1_in + i*Ns ); K2.push_back( K2_in + i*Ns ); Lig.push_back( Ligand_in + i*Ns ); Vol.push_back( Voltage_in + i*Ns ); Pres.push_back( Pressure_in + i*Ns ); } return inter_ll(Ns, clazz, P0_in, &(K0[0]), &(K1[0]), &(K2[0]), &(Lig[0]), &(Vol[0]), &(Pres[0]), Constants, tdead, Nseg, dwellCounts, classeses, durationses, ll); } extern "C" MAXILL_API int inter_ll( int Ns, int *clazz, double *P0_in, double **K0_in, double **K1_in, double **K2_in, int **Ligand_in, int **Voltage_in, int **Pressure_in, double *Constants, double tdead, int Nseg, int *dwellCounts, int **classeses, float **durationses, double *ll) { //std::ofstream logger; //logger.open("s:\\maxill_log.txt"); matrix<double> K0; matrix_from_arrays(K0, K0_in, Ns, Ns); matrix<double> K1; matrix_from_arrays(K1, K1_in, Ns, Ns); matrix<double> K2; matrix_from_arrays(K2, K1_in, Ns, Ns); matrix<int> Ligand; matrix_from_arrays(Ligand, Ligand_in, Ns, Ns); matrix<int> Voltage; matrix_from_arrays(Voltage, Voltage_in, Ns, Ns); matrix<int> Pressure; matrix_from_arrays(Pressure, Voltage_in, Ns, Ns); matrix<double> Q; BuildQ_p(Ns, Q, K0, K1, K2, Ligand, Voltage, Pressure, Constants); matrix<double> eQ; QtoQe(Q, clazz, tdead, eQ); matrix<double> P0; if ( P0_in ) { matrix_from_array(P0, P0_in, 1, Ns); double sum = 0.0; for (int i=0; i<Ns; ++i) sum += P0_in[i]; for (int i=0; i<Ns; ++i) P0(0,i) = (sum > 1e-8 ) ? (P0(0,i) / sum) : (1.0 / Ns); } else QtoPe(eQ, P0); int Na; //logger << "K0: " << K0 << endl; //logger << "K1: " << K1 << endl; //logger << "K2: " << K2 << endl; //logger << "L: " << Ligand << endl; //logger << "V: " << Voltage << endl; //logger << "P: " << Pressure << endl; //logger << "Q: " << Q << endl; //logger << "eQ: " << eQ << endl; //logger << "P0: " << P0 << endl; // max class int maxcls = clazz[0]; for (int i=1; i<Ns; ++i) if ( clazz[i] > maxcls ) maxcls = clazz[i]; std::vector< std::vector<int> > clazz_states(maxcls+1); for (int i=0; i<Ns; ++i) clazz_states[clazz[i]].push_back(i); int maxcls_data = -1; for (int i=0; i<Nseg; ++i) { int *end = classeses[i] + dwellCounts[i]; for (int *cl = classeses[i]; cl != end; ++cl) if ( *cl > maxcls_data ) maxcls_data = *cl; } if ( maxcls_data > maxcls ) { cerr << "Not enough classes in the model." << endl; return -8; } // we eigendecompose each submatrix eQaa for quick exponentiation in the inner loop: std::vector< std::vector<double> > eigvals_aa(maxcls+1); std::vector< matrix<double> > eigvecs_aa(maxcls+1); std::vector< matrix<double> > eiginvs_aa(maxcls+1); vector<double> eig_imag(Ns); for (int a=0; a<=maxcls; ++a) { Na = (int) clazz_states[a].size(); if ( Na ) { int *aa = &(clazz_states[a][0]); matrix<double> eQaa; matrix_to_partition(eQ, Na, Na, aa, aa, eQaa); eigvals_aa[a].resize(Na); eigvecs_aa[a].resize(Na, Na); eiginvs_aa[a].resize(Na, Na); if ( ! eigen_vals_vecs(eQaa, &(eigvals_aa[a][0]), &(eig_imag[0]), eigvecs_aa[a], eiginvs_aa[a], cerr) ) { //output << "No convergence in eigen calculations" << endl; return -2; } for (int i=0; i<Na; ++i) { if ( fabs(eig_imag[i]) > 1e-5 ) { //output << "Complex eigenvalues found: " << eig_imag[i] << endl; return -2; } if ( eigvals_aa[a][i] > 1e-5 ) { //output << "Positive eigenvalues found: " << eigvals_aa[a][i] << endl; return -2; } } } } // Then for efficiency, allocate space for expm_eigen temps std::vector< matrix<double> > tmp_nxn(Ns+1), tmp_nxn_diag(Ns+1); for (int i=1; i<=Ns; ++i) { tmp_nxn[i].resize(i, i); tmp_nxn_diag[i].resize(i, i); for (int j=0; j<i; ++j) for (int k=0; k<i; ++k) tmp_nxn_diag[i](j,k) = 0.0; } // and a place for the final exponentiated matrices: std::vector< matrix<double> > eQ_aa(maxcls+1); for (int a=0; a<=maxcls; ++a) { Na = (int) clazz_states[a].size(); if ( Na ) eQ_aa[a].resize(Na, Na); } // partitions eQab are used for transition probability (per second) std::vector< std::vector< matrix<double> > > eQab; eQab.resize(maxcls+1); for (int a=0; a<=maxcls; ++a) { eQab[a].resize(maxcls+1); Na = (int) clazz_states[a].size(); if ( Na ) { for (int b=0; b<=maxcls; ++b) { int Nb = (int) clazz_states[b].size(); if ( (b != a) && Nb ) { matrix<double>& subQ = eQab[a][b]; subQ.resize(Na, Nb); matrix_to_partition(eQ, Na, Nb, &(clazz_states[a][0]), &(clazz_states[b][0]), subQ); } } } } // alpha (temp) rows per class, since they're different sizes // actually a pair apiece to avoid temporaries alpha_a <- alpha_a * At std::vector< vector<double> > alpha_pre(maxcls+1), alpha_post(maxcls+1); for (int a=0; a<=maxcls; ++a) { alpha_pre[a].resize( clazz_states[a].size() ); // 1, clazz...size alpha_post[a].resize( clazz_states[a].size() ); // 1, clazz...size } // scale accumulator *ll = 0.0; for (int iseg = 0; iseg<Nseg; ++iseg) { int Nd = dwellCounts[iseg]; int *classes = classeses[iseg]; float *durations = durationses[iseg]; int a = classes[0]; Na = (int) clazz_states[a].size(); int b = a; int Nb = Na; // normalized P0 among possible start states double tot = 0.0; for (int i=0; i<Na; ++i) { alpha_pre[a](i) = P0(0,clazz_states[a][i]); tot += alpha_pre[a](i); } if ( tot ) { for (int i=0; i<Na; ++i) alpha_pre[a](i) /= tot; } else { for (int i=0; i<Na; ++i) alpha_pre[a](i) = 1.0 / Na; } *ll += alpha_logscale(alpha_pre[a]); for (int d=1; d<Nd; ++d) { a = b; Na = Nb; b = classes[d]; Nb = (int) clazz_states[b].size(); // * exp(Qaa * dur) [scale?] * eQab [scale] expm_eig(&(eigvals_aa[a][0]), eigvecs_aa[a], eiginvs_aa[a], durations[d-1], tmp_nxn_diag[Na], tmp_nxn[Na], eQ_aa[a]); noalias(alpha_post[a]) = prod(alpha_pre[a], eQ_aa[a]); // *ll += alpha_logscale(alpha_post[a]); noalias(alpha_pre[b]) = prod(alpha_post[a], eQab[a][b]); *ll += alpha_logscale(alpha_pre[b]); } a = b; Na = Nb; expm_eig(&(eigvals_aa[a][0]), eigvecs_aa[a], eiginvs_aa[a], durations[Nd-1], tmp_nxn_diag[Na], tmp_nxn[Na], eQ_aa[a]); noalias(alpha_post[a]) = prod(alpha_pre[a], eQ_aa[a]); // *ll += alpha_logscale(alpha_post[a]); std::vector<int> not_a; for (int i=0; i<Ns; ++i) if ( clazz[i] != a ) not_a.push_back(i); int Nz = (int) not_a.size(); matrix<double> eQaz(Na, Nz); matrix_to_partition(eQ, Na, Nz, &(clazz_states[a][0]), &(not_a[0]), eQaz); vector<double> alpha_z(Nz); noalias(alpha_z) = prod(alpha_post[a], eQaz); *ll += alpha_logscale(alpha_z); } return 0; // success } extern "C" MAXILL_API void mil_prep_events( int *ndwt, int *idwt, float *tdwt, double tdead_ms ) { float td = float(tdead_ms * 1.0e-3); int ndwells = *ndwt; int i; // outgoing index int j; // incoming index int cls; float tm; // first, drop initial too-short events for ( j=0; j<ndwells; j++ ) { tm = tdwt[j] * 1.0e-3f; if ( (boost::math::float_distance(tm, td) < TDEAD_DELTA_FLOATS) || (tm > td) ) break; } // then add the time-values of other too-shorts to the prev. dwell for ( i=0; j<ndwells; j++ ) { cls = idwt[j]; tm = tdwt[j] * 1.0e-3f; if ( (i > 0) && (idwt[i-1] == cls) ) tdwt[i-1] = (float)(tdwt[i-1] + tm); else if ( (i > 0) && ((boost::math::float_distance(tm, td) >= TDEAD_DELTA_FLOATS) && (tm <= td)) ) tdwt[i-1] = (float)(tdwt[i-1] + tm); else { idwt[i] = cls; tdwt[i] = (float) (tm - td); i++; } } *ndwt = i; } extern "C" MAXILL_API void mil_prep_segments( int Nseg, int *dwellCounts, int **classeses, float **durationses, double tdead_ms ) { for (int i=0; i<Nseg; ++i) mil_prep_events(dwellCounts+i, classeses[i], durationses[i], tdead_ms); }