changeset 8:b5b38998ef3b

added all that other stuff
author matthiasm
date Fri, 11 Apr 2014 15:54:25 +0100
parents 12abff5474c8
children 4ea6619cb3f5
files _FullBNT/BNT/@assocarray/CVS/Entries _FullBNT/BNT/@assocarray/CVS/Repository _FullBNT/BNT/@assocarray/CVS/Root _FullBNT/BNT/@assocarray/assocarray.m _FullBNT/BNT/@assocarray/subsref.m _FullBNT/BNT/CPDs/@boolean_CPD/CVS/Entries _FullBNT/BNT/CPDs/@boolean_CPD/CVS/Repository _FullBNT/BNT/CPDs/@boolean_CPD/CVS/Root _FullBNT/BNT/CPDs/@boolean_CPD/boolean_CPD.m _FullBNT/BNT/CPDs/@deterministic_CPD/CVS/Entries _FullBNT/BNT/CPDs/@deterministic_CPD/CVS/Repository _FullBNT/BNT/CPDs/@deterministic_CPD/CVS/Root _FullBNT/BNT/CPDs/@deterministic_CPD/deterministic_CPD.m _FullBNT/BNT/CPDs/@discrete_CPD/CPD_to_lambda_msg.m _FullBNT/BNT/CPDs/@discrete_CPD/CPD_to_pi.m _FullBNT/BNT/CPDs/@discrete_CPD/CPD_to_scgpot.m _FullBNT/BNT/CPDs/@discrete_CPD/CVS/Entries _FullBNT/BNT/CPDs/@discrete_CPD/CVS/Entries.Log _FullBNT/BNT/CPDs/@discrete_CPD/CVS/Repository _FullBNT/BNT/CPDs/@discrete_CPD/CVS/Root _FullBNT/BNT/CPDs/@discrete_CPD/Old/CVS/Entries _FullBNT/BNT/CPDs/@discrete_CPD/Old/CVS/Repository _FullBNT/BNT/CPDs/@discrete_CPD/Old/CVS/Root _FullBNT/BNT/CPDs/@discrete_CPD/Old/convert_to_pot.m _FullBNT/BNT/CPDs/@discrete_CPD/Old/convert_to_table.m _FullBNT/BNT/CPDs/@discrete_CPD/Old/prob_CPD.m _FullBNT/BNT/CPDs/@discrete_CPD/Old/prob_node.m _FullBNT/BNT/CPDs/@discrete_CPD/README _FullBNT/BNT/CPDs/@discrete_CPD/convert_CPD_to_table_hidden_ps.m _FullBNT/BNT/CPDs/@discrete_CPD/convert_obs_CPD_to_table.m _FullBNT/BNT/CPDs/@discrete_CPD/convert_to_pot.m _FullBNT/BNT/CPDs/@discrete_CPD/convert_to_sparse_table.c _FullBNT/BNT/CPDs/@discrete_CPD/convert_to_sparse_table.mexmaci _FullBNT/BNT/CPDs/@discrete_CPD/convert_to_table.m _FullBNT/BNT/CPDs/@discrete_CPD/discrete_CPD.m _FullBNT/BNT/CPDs/@discrete_CPD/dom_sizes.m _FullBNT/BNT/CPDs/@discrete_CPD/log_prob_node.m _FullBNT/BNT/CPDs/@discrete_CPD/private/CVS/Entries _FullBNT/BNT/CPDs/@discrete_CPD/private/CVS/Repository _FullBNT/BNT/CPDs/@discrete_CPD/private/CVS/Root _FullBNT/BNT/CPDs/@discrete_CPD/private/prod_CPT_and_pi_msgs.m _FullBNT/BNT/CPDs/@discrete_CPD/prob_node.m _FullBNT/BNT/CPDs/@discrete_CPD/sample_node.m _FullBNT/BNT/CPDs/@gaussian_CPD/CPD_to_lambda_msg.m _FullBNT/BNT/CPDs/@gaussian_CPD/CPD_to_pi.m _FullBNT/BNT/CPDs/@gaussian_CPD/CPD_to_scgpot.m _FullBNT/BNT/CPDs/@gaussian_CPD/CVS/Entries _FullBNT/BNT/CPDs/@gaussian_CPD/CVS/Entries.Log _FullBNT/BNT/CPDs/@gaussian_CPD/CVS/Repository _FullBNT/BNT/CPDs/@gaussian_CPD/CVS/Root _FullBNT/BNT/CPDs/@gaussian_CPD/Old/CPD_to_lambda_msg.m _FullBNT/BNT/CPDs/@gaussian_CPD/Old/CVS/Entries _FullBNT/BNT/CPDs/@gaussian_CPD/Old/CVS/Repository _FullBNT/BNT/CPDs/@gaussian_CPD/Old/CVS/Root _FullBNT/BNT/CPDs/@gaussian_CPD/Old/gaussian_CPD.m _FullBNT/BNT/CPDs/@gaussian_CPD/Old/log_prob_node.m _FullBNT/BNT/CPDs/@gaussian_CPD/Old/maximize_params.m _FullBNT/BNT/CPDs/@gaussian_CPD/Old/update_ess.m _FullBNT/BNT/CPDs/@gaussian_CPD/Old/update_tied_ess.m _FullBNT/BNT/CPDs/@gaussian_CPD/adjustable_CPD.m _FullBNT/BNT/CPDs/@gaussian_CPD/convert_CPD_to_table_hidden_ps.m _FullBNT/BNT/CPDs/@gaussian_CPD/convert_to_pot.m _FullBNT/BNT/CPDs/@gaussian_CPD/convert_to_table.m _FullBNT/BNT/CPDs/@gaussian_CPD/display.m _FullBNT/BNT/CPDs/@gaussian_CPD/gaussian_CPD.m _FullBNT/BNT/CPDs/@gaussian_CPD/gaussian_CPD_params_given_dps.m _FullBNT/BNT/CPDs/@gaussian_CPD/get_field.m _FullBNT/BNT/CPDs/@gaussian_CPD/learn_params.m _FullBNT/BNT/CPDs/@gaussian_CPD/log_prob_node.m _FullBNT/BNT/CPDs/@gaussian_CPD/maximize_params.m _FullBNT/BNT/CPDs/@gaussian_CPD/maximize_params_debug.m _FullBNT/BNT/CPDs/@gaussian_CPD/private/CPD_to_linear_gaussian.m _FullBNT/BNT/CPDs/@gaussian_CPD/private/CVS/Entries _FullBNT/BNT/CPDs/@gaussian_CPD/private/CVS/Repository _FullBNT/BNT/CPDs/@gaussian_CPD/private/CVS/Root _FullBNT/BNT/CPDs/@gaussian_CPD/reset_ess.m _FullBNT/BNT/CPDs/@gaussian_CPD/sample_node.m _FullBNT/BNT/CPDs/@gaussian_CPD/set_fields.m _FullBNT/BNT/CPDs/@gaussian_CPD/update_ess.m _FullBNT/BNT/CPDs/@generic_CPD/CVS/Entries _FullBNT/BNT/CPDs/@generic_CPD/CVS/Entries.Log _FullBNT/BNT/CPDs/@generic_CPD/CVS/Repository _FullBNT/BNT/CPDs/@generic_CPD/CVS/Root _FullBNT/BNT/CPDs/@generic_CPD/Old/BIC_score_CPD.m _FullBNT/BNT/CPDs/@generic_CPD/Old/CPD_to_dpots.m _FullBNT/BNT/CPDs/@generic_CPD/Old/CVS/Entries _FullBNT/BNT/CPDs/@generic_CPD/Old/CVS/Repository _FullBNT/BNT/CPDs/@generic_CPD/Old/CVS/Root _FullBNT/BNT/CPDs/@generic_CPD/README _FullBNT/BNT/CPDs/@generic_CPD/adjustable_CPD.m _FullBNT/BNT/CPDs/@generic_CPD/display.m _FullBNT/BNT/CPDs/@generic_CPD/generic_CPD.m _FullBNT/BNT/CPDs/@generic_CPD/learn_params.m _FullBNT/BNT/CPDs/@generic_CPD/log_prior.m _FullBNT/BNT/CPDs/@generic_CPD/set_clamped.m _FullBNT/BNT/CPDs/@gmux_CPD/CPD_to_lambda_msg.m _FullBNT/BNT/CPDs/@gmux_CPD/CPD_to_pi.m _FullBNT/BNT/CPDs/@gmux_CPD/CVS/Entries _FullBNT/BNT/CPDs/@gmux_CPD/CVS/Entries.Log _FullBNT/BNT/CPDs/@gmux_CPD/CVS/Repository _FullBNT/BNT/CPDs/@gmux_CPD/CVS/Root _FullBNT/BNT/CPDs/@gmux_CPD/Old/CVS/Entries _FullBNT/BNT/CPDs/@gmux_CPD/Old/CVS/Repository _FullBNT/BNT/CPDs/@gmux_CPD/Old/CVS/Root _FullBNT/BNT/CPDs/@gmux_CPD/Old/gmux_CPD.m _FullBNT/BNT/CPDs/@gmux_CPD/convert_to_pot.m _FullBNT/BNT/CPDs/@gmux_CPD/display.m _FullBNT/BNT/CPDs/@gmux_CPD/gmux_CPD.m _FullBNT/BNT/CPDs/@gmux_CPD/sample_node.m _FullBNT/BNT/CPDs/@hhmm2Q_CPD/CPD_to_CPT.m _FullBNT/BNT/CPDs/@hhmm2Q_CPD/CVS/Entries _FullBNT/BNT/CPDs/@hhmm2Q_CPD/CVS/Repository _FullBNT/BNT/CPDs/@hhmm2Q_CPD/CVS/Root _FullBNT/BNT/CPDs/@hhmm2Q_CPD/hhmm2Q_CPD.m _FullBNT/BNT/CPDs/@hhmm2Q_CPD/maximize_params.m _FullBNT/BNT/CPDs/@hhmm2Q_CPD/reset_ess.m _FullBNT/BNT/CPDs/@hhmm2Q_CPD/update_ess.m _FullBNT/BNT/CPDs/@hhmmF_CPD/CVS/Entries _FullBNT/BNT/CPDs/@hhmmF_CPD/CVS/Repository _FullBNT/BNT/CPDs/@hhmmF_CPD/CVS/Root _FullBNT/BNT/CPDs/@hhmmF_CPD/Old/CVS/Entries _FullBNT/BNT/CPDs/@hhmmF_CPD/Old/CVS/Repository _FullBNT/BNT/CPDs/@hhmmF_CPD/Old/CVS/Root _FullBNT/BNT/CPDs/@hhmmF_CPD/Old/hhmmF_CPD.m _FullBNT/BNT/CPDs/@hhmmF_CPD/Old/log_prior.m _FullBNT/BNT/CPDs/@hhmmF_CPD/Old/maximize_params.m _FullBNT/BNT/CPDs/@hhmmF_CPD/Old/reset_ess.m _FullBNT/BNT/CPDs/@hhmmF_CPD/Old/update_CPT.m _FullBNT/BNT/CPDs/@hhmmF_CPD/Old/update_ess.m _FullBNT/BNT/CPDs/@hhmmF_CPD/hhmmF_CPD.m _FullBNT/BNT/CPDs/@hhmmF_CPD/log_prior.m _FullBNT/BNT/CPDs/@hhmmF_CPD/maximize_params.m _FullBNT/BNT/CPDs/@hhmmF_CPD/reset_ess.m _FullBNT/BNT/CPDs/@hhmmF_CPD/update_CPT.m _FullBNT/BNT/CPDs/@hhmmF_CPD/update_ess.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/CVS/Entries _FullBNT/BNT/CPDs/@hhmmQ_CPD/CVS/Repository _FullBNT/BNT/CPDs/@hhmmQ_CPD/CVS/Root _FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/CVS/Entries _FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/CVS/Repository _FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/CVS/Root _FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/hhmmQ_CPD.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/log_prior.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/maximize_params.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/reset_ess.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/update_CPT.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/update_ess.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/update_ess2.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/update_ess3.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/update_ess4.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/hhmmQ_CPD.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/log_prior.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/maximize_params.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/reset_ess.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/update_CPT.m _FullBNT/BNT/CPDs/@hhmmQ_CPD/update_ess.m _FullBNT/BNT/CPDs/@mlp_CPD/CVS/Entries _FullBNT/BNT/CPDs/@mlp_CPD/CVS/Repository _FullBNT/BNT/CPDs/@mlp_CPD/CVS/Root _FullBNT/BNT/CPDs/@mlp_CPD/convert_to_table.m _FullBNT/BNT/CPDs/@mlp_CPD/maximize_params.m _FullBNT/BNT/CPDs/@mlp_CPD/mlp_CPD.m _FullBNT/BNT/CPDs/@mlp_CPD/reset_ess.m _FullBNT/BNT/CPDs/@mlp_CPD/update_ess.m _FullBNT/BNT/CPDs/@noisyor_CPD/CPD_to_CPT.m _FullBNT/BNT/CPDs/@noisyor_CPD/CPD_to_lambda_msg.m _FullBNT/BNT/CPDs/@noisyor_CPD/CPD_to_pi.m _FullBNT/BNT/CPDs/@noisyor_CPD/CVS/Entries _FullBNT/BNT/CPDs/@noisyor_CPD/CVS/Entries.Log _FullBNT/BNT/CPDs/@noisyor_CPD/CVS/Repository _FullBNT/BNT/CPDs/@noisyor_CPD/CVS/Root _FullBNT/BNT/CPDs/@noisyor_CPD/noisyor_CPD.m _FullBNT/BNT/CPDs/@noisyor_CPD/private/CVS/Entries _FullBNT/BNT/CPDs/@noisyor_CPD/private/CVS/Repository _FullBNT/BNT/CPDs/@noisyor_CPD/private/CVS/Root _FullBNT/BNT/CPDs/@noisyor_CPD/private/sum_prod_CPD_and_pi_msgs.m _FullBNT/BNT/CPDs/@root_CPD/CPD_to_pi.m _FullBNT/BNT/CPDs/@root_CPD/CVS/Entries _FullBNT/BNT/CPDs/@root_CPD/CVS/Entries.Log _FullBNT/BNT/CPDs/@root_CPD/CVS/Repository _FullBNT/BNT/CPDs/@root_CPD/CVS/Root _FullBNT/BNT/CPDs/@root_CPD/Old/CPD_to_CPT.m _FullBNT/BNT/CPDs/@root_CPD/Old/CVS/Entries _FullBNT/BNT/CPDs/@root_CPD/Old/CVS/Repository _FullBNT/BNT/CPDs/@root_CPD/Old/CVS/Root _FullBNT/BNT/CPDs/@root_CPD/convert_to_pot.m _FullBNT/BNT/CPDs/@root_CPD/log_marg_prob_node.m _FullBNT/BNT/CPDs/@root_CPD/log_prob_node.m _FullBNT/BNT/CPDs/@root_CPD/root_CPD.m _FullBNT/BNT/CPDs/@root_CPD/sample_node.m _FullBNT/BNT/CPDs/@softmax_CPD/CVS/Entries _FullBNT/BNT/CPDs/@softmax_CPD/CVS/Entries.Log _FullBNT/BNT/CPDs/@softmax_CPD/CVS/Repository _FullBNT/BNT/CPDs/@softmax_CPD/CVS/Root _FullBNT/BNT/CPDs/@softmax_CPD/convert_to_pot.m _FullBNT/BNT/CPDs/@softmax_CPD/convert_to_table.m _FullBNT/BNT/CPDs/@softmax_CPD/display.m _FullBNT/BNT/CPDs/@softmax_CPD/get_field.m _FullBNT/BNT/CPDs/@softmax_CPD/maximize_params.m _FullBNT/BNT/CPDs/@softmax_CPD/private/CVS/Entries _FullBNT/BNT/CPDs/@softmax_CPD/private/CVS/Repository _FullBNT/BNT/CPDs/@softmax_CPD/private/CVS/Root _FullBNT/BNT/CPDs/@softmax_CPD/private/extract_params.m _FullBNT/BNT/CPDs/@softmax_CPD/reset_ess.m _FullBNT/BNT/CPDs/@softmax_CPD/sample_node.m _FullBNT/BNT/CPDs/@softmax_CPD/set_fields.m _FullBNT/BNT/CPDs/@softmax_CPD/softmax_CPD.m _FullBNT/BNT/CPDs/@softmax_CPD/update_ess.m _FullBNT/BNT/CPDs/@tabular_CPD/CPD_to_CPT.m _FullBNT/BNT/CPDs/@tabular_CPD/CVS/Entries _FullBNT/BNT/CPDs/@tabular_CPD/CVS/Entries.Log _FullBNT/BNT/CPDs/@tabular_CPD/CVS/Repository _FullBNT/BNT/CPDs/@tabular_CPD/CVS/Root _FullBNT/BNT/CPDs/@tabular_CPD/Old/BIC_score_CPD.m _FullBNT/BNT/CPDs/@tabular_CPD/Old/CVS/Entries _FullBNT/BNT/CPDs/@tabular_CPD/Old/CVS/Repository _FullBNT/BNT/CPDs/@tabular_CPD/Old/CVS/Root _FullBNT/BNT/CPDs/@tabular_CPD/Old/bayesian_score_CPD.m _FullBNT/BNT/CPDs/@tabular_CPD/Old/log_marg_prob_node_case.m _FullBNT/BNT/CPDs/@tabular_CPD/Old/mult_CPD_and_pi_msgs.m _FullBNT/BNT/CPDs/@tabular_CPD/Old/prob_CPT.m _FullBNT/BNT/CPDs/@tabular_CPD/Old/prob_node.m _FullBNT/BNT/CPDs/@tabular_CPD/Old/sample_node.m _FullBNT/BNT/CPDs/@tabular_CPD/Old/sample_node_single_case.m _FullBNT/BNT/CPDs/@tabular_CPD/Old/tabular_CPD.m _FullBNT/BNT/CPDs/@tabular_CPD/Old/update_params.m _FullBNT/BNT/CPDs/@tabular_CPD/bayes_update_params.m _FullBNT/BNT/CPDs/@tabular_CPD/display.m _FullBNT/BNT/CPDs/@tabular_CPD/get_field.m _FullBNT/BNT/CPDs/@tabular_CPD/learn_params.m _FullBNT/BNT/CPDs/@tabular_CPD/log_marg_prob_node.m _FullBNT/BNT/CPDs/@tabular_CPD/log_nextcase_prob_node.m _FullBNT/BNT/CPDs/@tabular_CPD/log_prior.m _FullBNT/BNT/CPDs/@tabular_CPD/maximize_params.m _FullBNT/BNT/CPDs/@tabular_CPD/reset_ess.m _FullBNT/BNT/CPDs/@tabular_CPD/set_fields.m _FullBNT/BNT/CPDs/@tabular_CPD/tabular_CPD.m _FullBNT/BNT/CPDs/@tabular_CPD/update_ess.m _FullBNT/BNT/CPDs/@tabular_CPD/update_ess_simple.m _FullBNT/BNT/CPDs/@tabular_decision_node/CPD_to_CPT.m _FullBNT/BNT/CPDs/@tabular_decision_node/CVS/Entries _FullBNT/BNT/CPDs/@tabular_decision_node/CVS/Entries.Log _FullBNT/BNT/CPDs/@tabular_decision_node/CVS/Repository _FullBNT/BNT/CPDs/@tabular_decision_node/CVS/Root _FullBNT/BNT/CPDs/@tabular_decision_node/Old/CVS/Entries _FullBNT/BNT/CPDs/@tabular_decision_node/Old/CVS/Repository _FullBNT/BNT/CPDs/@tabular_decision_node/Old/CVS/Root _FullBNT/BNT/CPDs/@tabular_decision_node/Old/tabular_decision_node.m _FullBNT/BNT/CPDs/@tabular_decision_node/display.m _FullBNT/BNT/CPDs/@tabular_decision_node/get_field.m _FullBNT/BNT/CPDs/@tabular_decision_node/set_fields.m _FullBNT/BNT/CPDs/@tabular_decision_node/tabular_decision_node.m _FullBNT/BNT/CPDs/@tabular_kernel/CVS/Entries _FullBNT/BNT/CPDs/@tabular_kernel/CVS/Entries.Log _FullBNT/BNT/CPDs/@tabular_kernel/CVS/Repository _FullBNT/BNT/CPDs/@tabular_kernel/CVS/Root _FullBNT/BNT/CPDs/@tabular_kernel/Old/CVS/Entries _FullBNT/BNT/CPDs/@tabular_kernel/Old/CVS/Repository _FullBNT/BNT/CPDs/@tabular_kernel/Old/CVS/Root _FullBNT/BNT/CPDs/@tabular_kernel/Old/tabular_kernel.m _FullBNT/BNT/CPDs/@tabular_kernel/convert_to_pot.m _FullBNT/BNT/CPDs/@tabular_kernel/convert_to_table.m _FullBNT/BNT/CPDs/@tabular_kernel/get_field.m _FullBNT/BNT/CPDs/@tabular_kernel/set_fields.m _FullBNT/BNT/CPDs/@tabular_kernel/tabular_kernel.m _FullBNT/BNT/CPDs/@tabular_utility_node/CVS/Entries _FullBNT/BNT/CPDs/@tabular_utility_node/CVS/Repository _FullBNT/BNT/CPDs/@tabular_utility_node/CVS/Root _FullBNT/BNT/CPDs/@tabular_utility_node/convert_to_pot.m _FullBNT/BNT/CPDs/@tabular_utility_node/display.m _FullBNT/BNT/CPDs/@tabular_utility_node/tabular_utility_node.m _FullBNT/BNT/CPDs/@tree_CPD/CVS/Entries _FullBNT/BNT/CPDs/@tree_CPD/CVS/Repository _FullBNT/BNT/CPDs/@tree_CPD/CVS/Root _FullBNT/BNT/CPDs/@tree_CPD/display.m _FullBNT/BNT/CPDs/@tree_CPD/evaluate_tree_performance.m _FullBNT/BNT/CPDs/@tree_CPD/get_field.m _FullBNT/BNT/CPDs/@tree_CPD/learn_params.m _FullBNT/BNT/CPDs/@tree_CPD/readme.txt _FullBNT/BNT/CPDs/@tree_CPD/set_fields.m _FullBNT/BNT/CPDs/@tree_CPD/tree_CPD.m _FullBNT/BNT/CPDs/CVS/Entries _FullBNT/BNT/CPDs/CVS/Entries.Log _FullBNT/BNT/CPDs/CVS/Repository _FullBNT/BNT/CPDs/CVS/Root _FullBNT/BNT/CPDs/mk_isolated_tabular_CPD.m _FullBNT/BNT/CVS/Entries _FullBNT/BNT/CVS/Entries.Log _FullBNT/BNT/CVS/Repository _FullBNT/BNT/CVS/Root _FullBNT/BNT/README.txt _FullBNT/BNT/copyright.txt _FullBNT/BNT/general/CVS/Entries _FullBNT/BNT/general/CVS/Entries.Log _FullBNT/BNT/general/CVS/Repository _FullBNT/BNT/general/CVS/Root _FullBNT/BNT/general/Old/CVS/Entries _FullBNT/BNT/general/Old/CVS/Repository _FullBNT/BNT/general/Old/CVS/Root _FullBNT/BNT/general/Old/bnet_to_gdl_graph.m _FullBNT/BNT/general/Old/calc_mpe.m _FullBNT/BNT/general/Old/calc_mpe_bucket.m _FullBNT/BNT/general/Old/calc_mpe_dbn.m _FullBNT/BNT/general/Old/calc_mpe_given_inf_engine.m _FullBNT/BNT/general/Old/calc_mpe_global.m _FullBNT/BNT/general/Old/compute_interface_nodes.m _FullBNT/BNT/general/Old/mk_gdl_graph.m _FullBNT/BNT/general/add_ev_to_dmarginal.m _FullBNT/BNT/general/add_evidence_to_gmarginal.m _FullBNT/BNT/general/bnet_to_fgraph.m _FullBNT/BNT/general/compute_fwd_interface.m _FullBNT/BNT/general/compute_interface_nodes.m _FullBNT/BNT/general/compute_joint_pot.m _FullBNT/BNT/general/compute_minimal_interface.m _FullBNT/BNT/general/convert_dbn_CPDs_to_pots.m _FullBNT/BNT/general/convert_dbn_CPDs_to_tables.m _FullBNT/BNT/general/convert_dbn_CPDs_to_tables1.m _FullBNT/BNT/general/convert_dbn_CPDs_to_tables_slow.m _FullBNT/BNT/general/dbn_to_bnet.m _FullBNT/BNT/general/dbn_to_hmm.m _FullBNT/BNT/general/determine_elim_constraints.m _FullBNT/BNT/general/dispcpt.m _FullBNT/BNT/general/do_intervention.m _FullBNT/BNT/general/dsep.m _FullBNT/BNT/general/dsep_test.m _FullBNT/BNT/general/enumerate_scenarios.m _FullBNT/BNT/general/fgraph_to_bnet.m _FullBNT/BNT/general/hodbn_to_bnet.m _FullBNT/BNT/general/is_mnet.m _FullBNT/BNT/general/linear_gaussian_to_cpot.m _FullBNT/BNT/general/log_lik_complete.m _FullBNT/BNT/general/log_marg_lik_complete.m _FullBNT/BNT/general/mk_bnet.m _FullBNT/BNT/general/mk_dbn.m _FullBNT/BNT/general/mk_fgraph.m _FullBNT/BNT/general/mk_fgraph_given_ev.m _FullBNT/BNT/general/mk_higher_order_dbn.m _FullBNT/BNT/general/mk_limid.m _FullBNT/BNT/general/mk_mnet.m _FullBNT/BNT/general/mk_mrf2.m _FullBNT/BNT/general/mk_mutilated_samples.m _FullBNT/BNT/general/mk_named_CPT.m _FullBNT/BNT/general/mk_slice_and_half_dbn.m _FullBNT/BNT/general/noisyORtoTable.m _FullBNT/BNT/general/partition_dbn_nodes.m _FullBNT/BNT/general/partition_matrix_vec_3.m _FullBNT/BNT/general/sample_bnet.m _FullBNT/BNT/general/sample_bnet_nocell.m _FullBNT/BNT/general/sample_dbn.m _FullBNT/BNT/general/score_bnet_complete.m _FullBNT/BNT/general/shrink_obs_dims_in_gaussian.m _FullBNT/BNT/general/shrink_obs_dims_in_table.m _FullBNT/BNT/general/solve_limid.m _FullBNT/BNT/general/unroll_dbn_topology.m _FullBNT/BNT/general/unroll_higher_order_topology.m _FullBNT/BNT/general/unroll_set.m _FullBNT/BNT/graph/CVS/.svn/all-wcprops _FullBNT/BNT/graph/CVS/.svn/entries _FullBNT/BNT/graph/CVS/.svn/prop-base/Entries.Log.svn-base _FullBNT/BNT/graph/CVS/.svn/prop-base/Entries.svn-base _FullBNT/BNT/graph/CVS/.svn/prop-base/Repository.svn-base _FullBNT/BNT/graph/CVS/.svn/prop-base/Root.svn-base _FullBNT/BNT/graph/CVS/.svn/text-base/Entries.Log.svn-base _FullBNT/BNT/graph/CVS/.svn/text-base/Entries.svn-base _FullBNT/BNT/graph/CVS/.svn/text-base/Repository.svn-base _FullBNT/BNT/graph/CVS/.svn/text-base/Root.svn-base _FullBNT/BNT/graph/CVS/Entries _FullBNT/BNT/graph/CVS/Entries.Log _FullBNT/BNT/graph/CVS/Repository _FullBNT/BNT/graph/CVS/Root _FullBNT/BNT/graph/Old/.svn/all-wcprops _FullBNT/BNT/graph/Old/.svn/entries _FullBNT/BNT/graph/Old/.svn/prop-base/best_first_elim_order.m.svn-base _FullBNT/BNT/graph/Old/.svn/prop-base/dag_to_jtree.m.svn-base _FullBNT/BNT/graph/Old/.svn/prop-base/dfs.m.svn-base _FullBNT/BNT/graph/Old/.svn/prop-base/dsep_test.m.svn-base _FullBNT/BNT/graph/Old/.svn/prop-base/mk_2D_lattice_slow.m.svn-base _FullBNT/BNT/graph/Old/.svn/text-base/best_first_elim_order.m.svn-base _FullBNT/BNT/graph/Old/.svn/text-base/dag_to_jtree.m.svn-base _FullBNT/BNT/graph/Old/.svn/text-base/dfs.m.svn-base _FullBNT/BNT/graph/Old/.svn/text-base/dsep_test.m.svn-base _FullBNT/BNT/graph/Old/.svn/text-base/mk_2D_lattice_slow.m.svn-base _FullBNT/BNT/graph/Old/CVS/.svn/all-wcprops _FullBNT/BNT/graph/Old/CVS/.svn/entries _FullBNT/BNT/graph/Old/CVS/.svn/prop-base/Entries.svn-base _FullBNT/BNT/graph/Old/CVS/.svn/prop-base/Repository.svn-base _FullBNT/BNT/graph/Old/CVS/.svn/prop-base/Root.svn-base _FullBNT/BNT/graph/Old/CVS/.svn/text-base/Entries.svn-base _FullBNT/BNT/graph/Old/CVS/.svn/text-base/Repository.svn-base _FullBNT/BNT/graph/Old/CVS/.svn/text-base/Root.svn-base _FullBNT/BNT/graph/Old/CVS/Entries _FullBNT/BNT/graph/Old/CVS/Repository _FullBNT/BNT/graph/Old/CVS/Root _FullBNT/BNT/graph/Old/best_first_elim_order.m _FullBNT/BNT/graph/Old/dag_to_jtree.m _FullBNT/BNT/graph/Old/dfs.m _FullBNT/BNT/graph/Old/dsep_test.m _FullBNT/BNT/graph/Old/mk_2D_lattice_slow.m _FullBNT/BNT/graph/README.txt _FullBNT/BNT/graph/acyclic.m _FullBNT/BNT/graph/assignEdgeNums.m _FullBNT/BNT/graph/best_first_elim_order.m _FullBNT/BNT/graph/check_jtree_property.m _FullBNT/BNT/graph/check_triangulated.m _FullBNT/BNT/graph/children.m _FullBNT/BNT/graph/cliques_to_jtree.m _FullBNT/BNT/graph/cliques_to_strong_jtree.m _FullBNT/BNT/graph/connected_graph.m _FullBNT/BNT/graph/dag_to_essential_graph.m _FullBNT/BNT/graph/dfs.m _FullBNT/BNT/graph/dfs_test.m _FullBNT/BNT/graph/dijkstra.m _FullBNT/BNT/graph/family.m _FullBNT/BNT/graph/graph_separated.m _FullBNT/BNT/graph/graph_to_jtree.m _FullBNT/BNT/graph/min_subtree_con_nodes.m _FullBNT/BNT/graph/minimum_spanning_tree.m _FullBNT/BNT/graph/minspan.m _FullBNT/BNT/graph/mk_2D_lattice.m _FullBNT/BNT/graph/mk_2D_lattice_slow.m _FullBNT/BNT/graph/mk_adj_mat.m _FullBNT/BNT/graph/mk_adjmat_chain.m _FullBNT/BNT/graph/mk_all_dags.m _FullBNT/BNT/graph/mk_nbrs_of_dag.m _FullBNT/BNT/graph/mk_nbrs_of_digraph.m _FullBNT/BNT/graph/mk_nbrs_of_digraph_broken.m _FullBNT/BNT/graph/mk_nbrs_of_digraph_not_vectorized.m _FullBNT/BNT/graph/mk_rnd_dag.m _FullBNT/BNT/graph/mk_rnd_dag_given_edge_prob.m _FullBNT/BNT/graph/mk_rooted_tree.m _FullBNT/BNT/graph/mk_undirected.m _FullBNT/BNT/graph/moralize.m _FullBNT/BNT/graph/neighbors.m _FullBNT/BNT/graph/parents.m _FullBNT/BNT/graph/pred2path.m _FullBNT/BNT/graph/reachability_graph.m _FullBNT/BNT/graph/scc.m _FullBNT/BNT/graph/strong_elim_order.m _FullBNT/BNT/graph/test.m _FullBNT/BNT/graph/test_strong_root.m _FullBNT/BNT/graph/topological_sort.m _FullBNT/BNT/graph/trees.txt _FullBNT/BNT/graph/triangulate.c _FullBNT/BNT/graph/triangulate.m _FullBNT/BNT/graph/triangulate_2Dlattice_demo.m _FullBNT/BNT/graph/triangulate_test.m _FullBNT/BNT/inference/@inf_engine/CVS/Entries _FullBNT/BNT/inference/@inf_engine/CVS/Entries.Log _FullBNT/BNT/inference/@inf_engine/CVS/Repository _FullBNT/BNT/inference/@inf_engine/CVS/Root _FullBNT/BNT/inference/@inf_engine/Old/CVS/Entries _FullBNT/BNT/inference/@inf_engine/Old/CVS/Repository _FullBNT/BNT/inference/@inf_engine/Old/CVS/Root _FullBNT/BNT/inference/@inf_engine/Old/marginal_family_pot.m _FullBNT/BNT/inference/@inf_engine/Old/observed_nodes.m _FullBNT/BNT/inference/@inf_engine/bnet_from_engine.m _FullBNT/BNT/inference/@inf_engine/get_field.m _FullBNT/BNT/inference/@inf_engine/inf_engine.m _FullBNT/BNT/inference/@inf_engine/marginal_family.m _FullBNT/BNT/inference/@inf_engine/set_fields.m _FullBNT/BNT/inference/@inf_engine/update_engine.m _FullBNT/BNT/inference/CVS/Entries _FullBNT/BNT/inference/CVS/Entries.Log _FullBNT/BNT/inference/CVS/Repository _FullBNT/BNT/inference/CVS/Root _FullBNT/BNT/inference/dummy _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/CVS/Entries _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/CVS/Entries.Log _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/CVS/Repository _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/CVS/Root _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/bk_ff_hmm_inf_engine.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/dbn_init_bel.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/dbn_marginal_from_bel.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/dbn_predict_bel.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/dbn_update_bel.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/dbn_update_bel1.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/enter_evidence.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/marginal_family.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/CVS/Entries _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/CVS/Repository _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/CVS/Root _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/bk_ff_fb.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/combine_marginals_into_joint.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/dbn_to_hmm.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/mk_hmm_obs_lik_mat.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/mk_hmm_obs_lik_vec.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/mk_hmm_obs_lik_vec1.m _FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/project_joint_onto_marginals.m _FullBNT/BNT/inference/dynamic/@bk_inf_engine/CVS/Entries _FullBNT/BNT/inference/dynamic/@bk_inf_engine/CVS/Repository _FullBNT/BNT/inference/dynamic/@bk_inf_engine/CVS/Root _FullBNT/BNT/inference/dynamic/@bk_inf_engine/bk_inf_engine.m _FullBNT/BNT/inference/dynamic/@bk_inf_engine/dbn_init_bel.m _FullBNT/BNT/inference/dynamic/@bk_inf_engine/dbn_marginal_from_bel.m _FullBNT/BNT/inference/dynamic/@bk_inf_engine/dbn_update_bel.m _FullBNT/BNT/inference/dynamic/@bk_inf_engine/dbn_update_bel1.m _FullBNT/BNT/inference/dynamic/@bk_inf_engine/enter_evidence.m _FullBNT/BNT/inference/dynamic/@bk_inf_engine/enter_soft_evidence.m _FullBNT/BNT/inference/dynamic/@bk_inf_engine/marginal_family.m _FullBNT/BNT/inference/dynamic/@bk_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@bk_inf_engine/update_engine.m _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/CVS/Entries _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/CVS/Repository _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/CVS/Root _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/cbk_inf_engine.m _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/dbn_init_bel.m _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/dbn_marginal_from_bel.m _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/dbn_update_bel.m _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/dbn_update_bel1.m _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/enter_evidence.m _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/enter_soft_evidence.m _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/junk _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/marginal_family.m _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@cbk_inf_engine/update_engine.m _FullBNT/BNT/inference/dynamic/@ff_inf_engine/CVS/Entries _FullBNT/BNT/inference/dynamic/@ff_inf_engine/CVS/Repository _FullBNT/BNT/inference/dynamic/@ff_inf_engine/CVS/Root _FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old/CVS/Entries _FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old/CVS/Repository _FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old/CVS/Root _FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old/enter_soft_evidence.m _FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old/enter_soft_evidence1.m _FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old/marginal_family.m _FullBNT/BNT/inference/dynamic/@ff_inf_engine/enter_evidence.m _FullBNT/BNT/inference/dynamic/@ff_inf_engine/enter_soft_evidence.m _FullBNT/BNT/inference/dynamic/@ff_inf_engine/ff_inf_engine.m _FullBNT/BNT/inference/dynamic/@ff_inf_engine/filter_evidence.m _FullBNT/BNT/inference/dynamic/@ff_inf_engine/marginal_family.m _FullBNT/BNT/inference/dynamic/@ff_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@ff_inf_engine/smooth_evidence.m _FullBNT/BNT/inference/dynamic/@frontier_inf_engine/CVS/Entries _FullBNT/BNT/inference/dynamic/@frontier_inf_engine/CVS/Repository _FullBNT/BNT/inference/dynamic/@frontier_inf_engine/CVS/Root _FullBNT/BNT/inference/dynamic/@frontier_inf_engine/enter_evidence.m _FullBNT/BNT/inference/dynamic/@frontier_inf_engine/enter_soft_evidence.m _FullBNT/BNT/inference/dynamic/@frontier_inf_engine/frontier_inf_engine.m _FullBNT/BNT/inference/dynamic/@frontier_inf_engine/marginal_family.m _FullBNT/BNT/inference/dynamic/@frontier_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@frontier_inf_engine/set_fwdback.m _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/CVS/Entries _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/CVS/Repository _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/CVS/Root _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old/CVS/Entries _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old/CVS/Repository _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old/CVS/Root _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old/dhmm_inf_engine.m _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old/marginal_family.m _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/enter_evidence.m _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/find_mpe.m _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/fwdback_twoslice.m _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/hmm_inf_engine.m _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/marginal_family.m _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/private/CVS/Entries _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/private/CVS/Repository _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/private/CVS/Root _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/private/mk_hmm_obs_lik_matrix.m _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/private/mk_hmm_obs_lik_vec.m _FullBNT/BNT/inference/dynamic/@hmm_inf_engine/update_engine.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Entries _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Repository _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Root _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence1.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence2.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence3.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence4.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Entries _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Entries.Log _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Repository _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Root _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Entries _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Repository _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Root _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/enter_soft_evidence_nonint.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/enter_soft_evidence_trans.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine1.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine2.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/enter_evidence.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/enter_soft_evidence.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/jtree_dbn_inf_engine.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/marginal_family.m _FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/CVS/Entries _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/CVS/Repository _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/CVS/Root _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/Old/CVS/Entries _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/Old/CVS/Repository _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/Old/CVS/Root _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/Old/marginal_family.m _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/Old/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/enter_evidence.m _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/jtree_unrolled_dbn_inf_engine.m _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/marginal_family.m _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/update_engine.m _FullBNT/BNT/inference/dynamic/@kalman_inf_engine/CVS/Entries _FullBNT/BNT/inference/dynamic/@kalman_inf_engine/CVS/Repository _FullBNT/BNT/inference/dynamic/@kalman_inf_engine/CVS/Root _FullBNT/BNT/inference/dynamic/@kalman_inf_engine/enter_evidence.m _FullBNT/BNT/inference/dynamic/@kalman_inf_engine/kalman_inf_engine.m _FullBNT/BNT/inference/dynamic/@kalman_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Entries _FullBNT/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Repository _FullBNT/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Root _FullBNT/BNT/inference/dynamic/@kalman_inf_engine/private/dbn_to_lds.m _FullBNT/BNT/inference/dynamic/@kalman_inf_engine/private/extract_params_from_gbn.m _FullBNT/BNT/inference/dynamic/@kalman_inf_engine/update_engine.m _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/CVS/Entries _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/CVS/Repository _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/CVS/Root _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/CVS/Entries _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/CVS/Repository _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/CVS/Root _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/correct_smooth.m _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/enter_evidence.m _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/filter_evidence.m _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/filter_evidence_obj_oriented.m _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/smooth_evidence.m _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/smooth_evidence_fast.m _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/wrong_smooth.m _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/enter_evidence.m _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/enter_soft_ev.m _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/pearl_dbn_inf_engine.m _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/private/CVS/Entries _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/private/CVS/Repository _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/private/CVS/Root _FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/private/init_pearl_dbn_ev_msgs.m _FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/CVS/Entries _FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/CVS/Repository _FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/CVS/Root _FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/enter_evidence.m _FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/marginal_family.m _FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/pearl_unrolled_dbn_inf_engine.m _FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/update_engine.m _FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/CVS/Entries _FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/CVS/Repository _FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/CVS/Root _FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/enter_evidence.m _FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/marginal_family.m _FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/stable_ho_inf_engine.m _FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/test_ho_inf_enginge.m _FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/update_engine.m _FullBNT/BNT/inference/dynamic/CVS/Entries _FullBNT/BNT/inference/dynamic/CVS/Entries.Log _FullBNT/BNT/inference/dynamic/CVS/Repository _FullBNT/BNT/inference/dynamic/CVS/Root _FullBNT/BNT/inference/dynamic/dummy _FullBNT/BNT/inference/online/@filter_engine/CVS/Entries _FullBNT/BNT/inference/online/@filter_engine/CVS/Repository _FullBNT/BNT/inference/online/@filter_engine/CVS/Root _FullBNT/BNT/inference/online/@filter_engine/bnet_from_engine.m _FullBNT/BNT/inference/online/@filter_engine/enter_evidence.m _FullBNT/BNT/inference/online/@filter_engine/filter_engine.m _FullBNT/BNT/inference/online/@filter_engine/marginal_family.m _FullBNT/BNT/inference/online/@filter_engine/marginal_nodes.m _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Entries _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Entries.Log _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Repository _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Root _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/back.m _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/backT.m _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/fwd.m _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/fwd1.m _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/hmm_2TBN_inf_engine.m _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/marginal_family.m _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Entries _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Repository _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Root _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/private/mk_hmm_obs_lik_vec.m _FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/update_engine.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/CVS/Entries _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/CVS/Entries.Log _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/CVS/Repository _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/CVS/Root _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/Old/CVS/Entries _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/Old/CVS/Repository _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/Old/CVS/Root _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/Old/jtree_2TBN_inf_engine.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/back.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/back1.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/back1_mpe.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/backT.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/backT_mpe.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/back_mpe.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/fwd.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/fwd1.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/fwdMM.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/jtree_2TBN_inf_engine.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/marginal_family.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/set_fields.m _FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/CVS/Entries _FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/CVS/Repository _FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/CVS/Root _FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/back.m _FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/back1.m _FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/backT.m _FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/enter_evidence.m _FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/fwd.m _FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/fwd1.m _FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/jtree_sparse_2TBN_inf_engine.m _FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/marginal_family.m _FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/online/@smoother_engine/CVS/Entries _FullBNT/BNT/inference/online/@smoother_engine/CVS/Repository _FullBNT/BNT/inference/online/@smoother_engine/CVS/Root _FullBNT/BNT/inference/online/@smoother_engine/bnet_from_engine.m _FullBNT/BNT/inference/online/@smoother_engine/enter_evidence.m _FullBNT/BNT/inference/online/@smoother_engine/find_mpe.m _FullBNT/BNT/inference/online/@smoother_engine/find_mpeMM.m _FullBNT/BNT/inference/online/@smoother_engine/marginal_family.m _FullBNT/BNT/inference/online/@smoother_engine/marginal_nodes.m _FullBNT/BNT/inference/online/@smoother_engine/smoother_engine.m _FullBNT/BNT/inference/online/@smoother_engine/update_engine.m _FullBNT/BNT/inference/online/CVS/Entries _FullBNT/BNT/inference/online/CVS/Entries.Log _FullBNT/BNT/inference/online/CVS/Repository _FullBNT/BNT/inference/online/CVS/Root _FullBNT/BNT/inference/online/dummy _FullBNT/BNT/inference/static/@belprop_fg_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@belprop_fg_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@belprop_fg_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@belprop_fg_inf_engine/belprop_fg_inf_engine.m _FullBNT/BNT/inference/static/@belprop_fg_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@belprop_fg_inf_engine/find_mpe.m _FullBNT/BNT/inference/static/@belprop_fg_inf_engine/loopy_converged.m _FullBNT/BNT/inference/static/@belprop_fg_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@belprop_fg_inf_engine/set_params.m _FullBNT/BNT/inference/static/@belprop_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@belprop_inf_engine/CVS/Entries.Log _FullBNT/BNT/inference/static/@belprop_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@belprop_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@belprop_inf_engine/Old/CVS/Entries _FullBNT/BNT/inference/static/@belprop_inf_engine/Old/CVS/Repository _FullBNT/BNT/inference/static/@belprop_inf_engine/Old/CVS/Root _FullBNT/BNT/inference/static/@belprop_inf_engine/Old/belprop_gdl_inf_engine.m _FullBNT/BNT/inference/static/@belprop_inf_engine/Old/belprop_inf_engine_nostr.m _FullBNT/BNT/inference/static/@belprop_inf_engine/Old/enter_evidence.m _FullBNT/BNT/inference/static/@belprop_inf_engine/Old/enter_evidence1.m _FullBNT/BNT/inference/static/@belprop_inf_engine/Old/marginal_domain.m _FullBNT/BNT/inference/static/@belprop_inf_engine/belprop_inf_engine.m _FullBNT/BNT/inference/static/@belprop_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@belprop_inf_engine/find_mpe.m _FullBNT/BNT/inference/static/@belprop_inf_engine/loopy_converged.m _FullBNT/BNT/inference/static/@belprop_inf_engine/marginal_family.m _FullBNT/BNT/inference/static/@belprop_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@belprop_inf_engine/private/CVS/Entries _FullBNT/BNT/inference/static/@belprop_inf_engine/private/CVS/Repository _FullBNT/BNT/inference/static/@belprop_inf_engine/private/CVS/Root _FullBNT/BNT/inference/static/@belprop_inf_engine/private/junk _FullBNT/BNT/inference/static/@belprop_inf_engine/private/parallel_protocol.m _FullBNT/BNT/inference/static/@belprop_inf_engine/private/tree_protocol.m _FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/belprop_mrf2_inf_engine.m _FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/bp_mrf2.m _FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/enter_soft_evidence.m _FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/find_mpe.m _FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/set_params.m _FullBNT/BNT/inference/static/@cond_gauss_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@cond_gauss_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@cond_gauss_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@cond_gauss_inf_engine/cond_gauss_inf_engine.m _FullBNT/BNT/inference/static/@cond_gauss_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@cond_gauss_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@enumerative_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@enumerative_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@enumerative_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@enumerative_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@enumerative_inf_engine/enumerative_inf_engine.m _FullBNT/BNT/inference/static/@enumerative_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@gaussian_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@gaussian_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@gaussian_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@gaussian_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@gaussian_inf_engine/gaussian_inf_engine.m _FullBNT/BNT/inference/static/@gaussian_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@gaussian_inf_engine/private/CVS/Entries _FullBNT/BNT/inference/static/@gaussian_inf_engine/private/CVS/Repository _FullBNT/BNT/inference/static/@gaussian_inf_engine/private/CVS/Root _FullBNT/BNT/inference/static/@gaussian_inf_engine/private/extract_params_from_gbn.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/gibbs_sampling_inf_engine.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/CPT.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Entries _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Repository _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Root _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_children.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_families.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_families_dbn.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_posterior.c _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_posterior.mexmaci _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_posterior_dbn.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_strides.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_cpts.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_slice_dbn.c _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_slice_dbn.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_slice_dbn.mexmaci _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/my_sample_discrete.m _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/sample_single_discrete.c _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/sample_single_discrete.mexmaci _FullBNT/BNT/inference/static/@global_joint_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@global_joint_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@global_joint_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@global_joint_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@global_joint_inf_engine/find_mpe.m _FullBNT/BNT/inference/static/@global_joint_inf_engine/global_joint_inf_engine.m _FullBNT/BNT/inference/static/@global_joint_inf_engine/marginal_family.m _FullBNT/BNT/inference/static/@global_joint_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@jtree_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@jtree_inf_engine/CVS/Entries.Log _FullBNT/BNT/inference/static/@jtree_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@jtree_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@jtree_inf_engine/Old/CVS/Entries _FullBNT/BNT/inference/static/@jtree_inf_engine/Old/CVS/Repository _FullBNT/BNT/inference/static/@jtree_inf_engine/Old/CVS/Root _FullBNT/BNT/inference/static/@jtree_inf_engine/Old/collect_evidence.m _FullBNT/BNT/inference/static/@jtree_inf_engine/Old/distribute_evidence.m _FullBNT/BNT/inference/static/@jtree_inf_engine/Old/enter_evidence.m _FullBNT/BNT/inference/static/@jtree_inf_engine/Old/enter_soft_evidence.m _FullBNT/BNT/inference/static/@jtree_inf_engine/cliques_from_engine.m _FullBNT/BNT/inference/static/@jtree_inf_engine/clq_containing_nodes.m _FullBNT/BNT/inference/static/@jtree_inf_engine/collect_evidence.m _FullBNT/BNT/inference/static/@jtree_inf_engine/distribute_evidence.m _FullBNT/BNT/inference/static/@jtree_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@jtree_inf_engine/enter_soft_evidence.m _FullBNT/BNT/inference/static/@jtree_inf_engine/find_max_config.m _FullBNT/BNT/inference/static/@jtree_inf_engine/find_mpe.m _FullBNT/BNT/inference/static/@jtree_inf_engine/init_pot.m _FullBNT/BNT/inference/static/@jtree_inf_engine/jtree_inf_engine.m _FullBNT/BNT/inference/static/@jtree_inf_engine/marginal_family.m _FullBNT/BNT/inference/static/@jtree_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@jtree_inf_engine/set_fields.m _FullBNT/BNT/inference/static/@jtree_limid_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@jtree_limid_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@jtree_limid_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Entries _FullBNT/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Repository _FullBNT/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Root _FullBNT/BNT/inference/static/@jtree_limid_inf_engine/Old/marginal_family.m _FullBNT/BNT/inference/static/@jtree_limid_inf_engine/Old/marginal_nodes_SS.m _FullBNT/BNT/inference/static/@jtree_limid_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@jtree_limid_inf_engine/jtree_limid_inf_engine.m _FullBNT/BNT/inference/static/@jtree_limid_inf_engine/marginal_family.m _FullBNT/BNT/inference/static/@jtree_limid_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@jtree_mnet_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@jtree_mnet_inf_engine/find_mpe.m _FullBNT/BNT/inference/static/@jtree_mnet_inf_engine/jtree_mnet_inf_engine.m _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Entries.Log _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/cliques_from_engine.m _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/clq_containing_nodes.m _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/collect_evidence.c _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/collect_evidence.mexmaci _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/distribute_evidence.c _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/distribute_evidence.mexmaci _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/enter_soft_evidence.m _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/init_pot.c _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/init_pot.mexmaci _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/jtree_sparse_inf_engine.m _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/marginal_family.m _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Entries _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Repository _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Root _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/collect_evidence.c _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/distribute_evidence.c _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot.c _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot1.c _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot1.m _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/set_fields.m _FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine/likelihood_weighting_inf_engine.m _FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@pearl_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@pearl_inf_engine/CVS/Entries.Log _FullBNT/BNT/inference/static/@pearl_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@pearl_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@pearl_inf_engine/bethe_free_energy.m _FullBNT/BNT/inference/static/@pearl_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@pearl_inf_engine/loopy_converged.m _FullBNT/BNT/inference/static/@pearl_inf_engine/marginal_family.m _FullBNT/BNT/inference/static/@pearl_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@pearl_inf_engine/pearl_inf_engine.m _FullBNT/BNT/inference/static/@pearl_inf_engine/private/CVS/Entries _FullBNT/BNT/inference/static/@pearl_inf_engine/private/CVS/Repository _FullBNT/BNT/inference/static/@pearl_inf_engine/private/CVS/Root _FullBNT/BNT/inference/static/@pearl_inf_engine/private/compute_bel.m _FullBNT/BNT/inference/static/@pearl_inf_engine/private/parallel_protocol.m _FullBNT/BNT/inference/static/@pearl_inf_engine/private/prod_lambda_msgs.m _FullBNT/BNT/inference/static/@pearl_inf_engine/private/tree_protocol.m _FullBNT/BNT/inference/static/@quickscore_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@quickscore_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@quickscore_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@quickscore_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@quickscore_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@quickscore_inf_engine/private/CVS/Entries _FullBNT/BNT/inference/static/@quickscore_inf_engine/private/CVS/Repository _FullBNT/BNT/inference/static/@quickscore_inf_engine/private/CVS/Root _FullBNT/BNT/inference/static/@quickscore_inf_engine/private/C_quickscore.c _FullBNT/BNT/inference/static/@quickscore_inf_engine/private/nr.h _FullBNT/BNT/inference/static/@quickscore_inf_engine/private/nrutil.c _FullBNT/BNT/inference/static/@quickscore_inf_engine/private/nrutil.h _FullBNT/BNT/inference/static/@quickscore_inf_engine/private/quickscore.m _FullBNT/BNT/inference/static/@quickscore_inf_engine/quickscore_inf_engine.m _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Entries.Log _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Entries _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Repository _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Root _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/initialize_engine.m _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/README _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/clq_containing_nodes.m _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_difclq_nodes.m _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_singleclq_nodes.m _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/problems.txt _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/push.m _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/push_pot_toclique.m _FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/stab_cond_gauss_inf_engine.m _FullBNT/BNT/inference/static/@var_elim_inf_engine/CVS/Entries _FullBNT/BNT/inference/static/@var_elim_inf_engine/CVS/Repository _FullBNT/BNT/inference/static/@var_elim_inf_engine/CVS/Root _FullBNT/BNT/inference/static/@var_elim_inf_engine/enter_evidence.m _FullBNT/BNT/inference/static/@var_elim_inf_engine/find_mpe.m _FullBNT/BNT/inference/static/@var_elim_inf_engine/marginal_nodes.m _FullBNT/BNT/inference/static/@var_elim_inf_engine/var_elim_inf_engine.m _FullBNT/BNT/inference/static/CVS/Entries _FullBNT/BNT/inference/static/CVS/Entries.Log _FullBNT/BNT/inference/static/CVS/Repository _FullBNT/BNT/inference/static/CVS/Root _FullBNT/BNT/inference/static/dummy _FullBNT/BNT/installC_BNT.m _FullBNT/BNT/installC_graph.m _FullBNT/BNT/learning/CVS/Entries _FullBNT/BNT/learning/CVS/Repository _FullBNT/BNT/learning/CVS/Root _FullBNT/BNT/learning/CovMat.m _FullBNT/BNT/learning/bayes_update_params.m _FullBNT/BNT/learning/bic_score_family.m _FullBNT/BNT/learning/compute_cooling_schedule.m _FullBNT/BNT/learning/dirichlet_score_family.m _FullBNT/BNT/learning/kpm_learn_struct_mcmc.m _FullBNT/BNT/learning/learn_params.m _FullBNT/BNT/learning/learn_params_dbn.m _FullBNT/BNT/learning/learn_params_dbn_em.m _FullBNT/BNT/learning/learn_params_em.m _FullBNT/BNT/learning/learn_params_em2.m _FullBNT/BNT/learning/learn_struct_K2.m _FullBNT/BNT/learning/learn_struct_dbn_reveal.m _FullBNT/BNT/learning/learn_struct_mcmc.m _FullBNT/BNT/learning/learn_struct_pdag_ic_star.m _FullBNT/BNT/learning/learn_struct_pdag_pc.m _FullBNT/BNT/learning/learn_struct_pdag_pc_constrain.m _FullBNT/BNT/learning/mcmc_sample_to_hist.m _FullBNT/BNT/learning/mk_schedule.m _FullBNT/BNT/learning/mk_tetrad_data_file.m _FullBNT/BNT/learning/score_dags.m _FullBNT/BNT/learning/score_dags_old.m _FullBNT/BNT/learning/score_family.m _FullBNT/BNT/license.gpl.txt _FullBNT/BNT/potentials/@cgpot/CVS/Entries _FullBNT/BNT/potentials/@cgpot/CVS/Entries.Log _FullBNT/BNT/potentials/@cgpot/CVS/Repository _FullBNT/BNT/potentials/@cgpot/CVS/Root _FullBNT/BNT/potentials/@cgpot/Old/CVS/Entries _FullBNT/BNT/potentials/@cgpot/Old/CVS/Repository _FullBNT/BNT/potentials/@cgpot/Old/CVS/Root _FullBNT/BNT/potentials/@cgpot/Old/normalize_pot.m _FullBNT/BNT/potentials/@cgpot/Old/set_domain_pot.m _FullBNT/BNT/potentials/@cgpot/Old/simple_marginalize_pot.m _FullBNT/BNT/potentials/@cgpot/cg_can_to_mom.m _FullBNT/BNT/potentials/@cgpot/cg_mom_to_can.m _FullBNT/BNT/potentials/@cgpot/cgpot.m _FullBNT/BNT/potentials/@cgpot/display.m _FullBNT/BNT/potentials/@cgpot/divide_by_pot.m _FullBNT/BNT/potentials/@cgpot/domain_pot.m _FullBNT/BNT/potentials/@cgpot/enter_cts_evidence_pot.m _FullBNT/BNT/potentials/@cgpot/enter_discrete_evidence_pot.m _FullBNT/BNT/potentials/@cgpot/marginalize_pot.m _FullBNT/BNT/potentials/@cgpot/multiply_by_pot.m _FullBNT/BNT/potentials/@cgpot/multiply_pots.m _FullBNT/BNT/potentials/@cgpot/normalize_pot.m _FullBNT/BNT/potentials/@cgpot/pot_to_marginal.m _FullBNT/BNT/potentials/@cgpot/set_domain_pot.m _FullBNT/BNT/potentials/@cpot/CVS/Entries _FullBNT/BNT/potentials/@cpot/CVS/Entries.Log _FullBNT/BNT/potentials/@cpot/CVS/Repository _FullBNT/BNT/potentials/@cpot/CVS/Root _FullBNT/BNT/potentials/@cpot/Old/CVS/Entries _FullBNT/BNT/potentials/@cpot/Old/CVS/Repository _FullBNT/BNT/potentials/@cpot/Old/CVS/Root _FullBNT/BNT/potentials/@cpot/Old/cpot_to_mpot.m _FullBNT/BNT/potentials/@cpot/Old/normalize_pot.convert.m _FullBNT/BNT/potentials/@cpot/cpot.m _FullBNT/BNT/potentials/@cpot/cpot_to_mpot.m _FullBNT/BNT/potentials/@cpot/display.m _FullBNT/BNT/potentials/@cpot/divide_by_pot.m _FullBNT/BNT/potentials/@cpot/domain_pot.m _FullBNT/BNT/potentials/@cpot/enter_cts_evidence_pot.m _FullBNT/BNT/potentials/@cpot/marginalize_pot.m _FullBNT/BNT/potentials/@cpot/multiply_by_pot.m _FullBNT/BNT/potentials/@cpot/multiply_pots.m _FullBNT/BNT/potentials/@cpot/normalize_pot.m _FullBNT/BNT/potentials/@cpot/pot_to_marginal.m _FullBNT/BNT/potentials/@cpot/rescale_pot.m _FullBNT/BNT/potentials/@cpot/set_domain_pot.m _FullBNT/BNT/potentials/@dpot/CVS/Entries _FullBNT/BNT/potentials/@dpot/CVS/Repository _FullBNT/BNT/potentials/@dpot/CVS/Root _FullBNT/BNT/potentials/@dpot/approxeq_pot.m _FullBNT/BNT/potentials/@dpot/display.m _FullBNT/BNT/potentials/@dpot/divide_by_pot.m _FullBNT/BNT/potentials/@dpot/domain_pot.m _FullBNT/BNT/potentials/@dpot/dpot.m _FullBNT/BNT/potentials/@dpot/dpot_to_table.m _FullBNT/BNT/potentials/@dpot/find_most_prob_entry.m _FullBNT/BNT/potentials/@dpot/get_fields.m _FullBNT/BNT/potentials/@dpot/marginalize_pot.m _FullBNT/BNT/potentials/@dpot/multiply_by_pot.m _FullBNT/BNT/potentials/@dpot/multiply_pots.m _FullBNT/BNT/potentials/@dpot/normalize_pot.m _FullBNT/BNT/potentials/@dpot/pot_to_marginal.m _FullBNT/BNT/potentials/@dpot/set_domain_pot.m _FullBNT/BNT/potentials/@dpot/subsasgn.m _FullBNT/BNT/potentials/@dpot/subsref.m _FullBNT/BNT/potentials/@mpot/CVS/Entries _FullBNT/BNT/potentials/@mpot/CVS/Repository _FullBNT/BNT/potentials/@mpot/CVS/Root _FullBNT/BNT/potentials/@mpot/display.m _FullBNT/BNT/potentials/@mpot/marginalize_pot.m _FullBNT/BNT/potentials/@mpot/mpot.m _FullBNT/BNT/potentials/@mpot/mpot_to_cpot.m _FullBNT/BNT/potentials/@mpot/normalize_pot.m _FullBNT/BNT/potentials/@mpot/pot_to_marginal.m _FullBNT/BNT/potentials/@mpot/rescale_pot.m _FullBNT/BNT/potentials/@mpot/set_domain_pot.m _FullBNT/BNT/potentials/@scgcpot/CVS/Entries _FullBNT/BNT/potentials/@scgcpot/CVS/Repository _FullBNT/BNT/potentials/@scgcpot/CVS/Root _FullBNT/BNT/potentials/@scgcpot/marginalize_pot.m _FullBNT/BNT/potentials/@scgcpot/normalize_pot.m _FullBNT/BNT/potentials/@scgcpot/reduce_pot.m _FullBNT/BNT/potentials/@scgcpot/rescale_pot.m _FullBNT/BNT/potentials/@scgcpot/scgcpot.m _FullBNT/BNT/potentials/@scgpot/CVS/Entries _FullBNT/BNT/potentials/@scgpot/CVS/Repository _FullBNT/BNT/potentials/@scgpot/CVS/Root _FullBNT/BNT/potentials/@scgpot/README _FullBNT/BNT/potentials/@scgpot/combine_pots.m _FullBNT/BNT/potentials/@scgpot/complement_pot.m _FullBNT/BNT/potentials/@scgpot/direct_combine_pots.m _FullBNT/BNT/potentials/@scgpot/extension_pot.m _FullBNT/BNT/potentials/@scgpot/marginalize_pot.m _FullBNT/BNT/potentials/@scgpot/normalize_pot.m _FullBNT/BNT/potentials/@scgpot/pot_to_marginal.m _FullBNT/BNT/potentials/@scgpot/recursive_combine_pots.m _FullBNT/BNT/potentials/@scgpot/reduce_pot.m _FullBNT/BNT/potentials/@scgpot/scgpot.m _FullBNT/BNT/potentials/@upot/CVS/Entries _FullBNT/BNT/potentials/@upot/CVS/Repository _FullBNT/BNT/potentials/@upot/CVS/Root _FullBNT/BNT/potentials/@upot/approxeq_pot.m _FullBNT/BNT/potentials/@upot/display.m _FullBNT/BNT/potentials/@upot/divide_by_pot.m _FullBNT/BNT/potentials/@upot/marginalize_pot.m _FullBNT/BNT/potentials/@upot/multiply_by_pot.m _FullBNT/BNT/potentials/@upot/normalize_pot.m _FullBNT/BNT/potentials/@upot/pot_to_marginal.m _FullBNT/BNT/potentials/@upot/upot.m _FullBNT/BNT/potentials/@upot/upot_to_opt_policy.m _FullBNT/BNT/potentials/CPD_to_pot.m _FullBNT/BNT/potentials/CVS/Entries _FullBNT/BNT/potentials/CVS/Entries.Log _FullBNT/BNT/potentials/CVS/Repository _FullBNT/BNT/potentials/CVS/Root _FullBNT/BNT/potentials/Old/CVS/Entries _FullBNT/BNT/potentials/Old/CVS/Repository _FullBNT/BNT/potentials/Old/CVS/Root _FullBNT/BNT/potentials/Old/comp_eff_node_sizes.m _FullBNT/BNT/potentials/README _FullBNT/BNT/potentials/Tables/CVS/Entries _FullBNT/BNT/potentials/Tables/CVS/Repository _FullBNT/BNT/potentials/Tables/CVS/Root _FullBNT/BNT/potentials/Tables/divide_by_sparse_table.c _FullBNT/BNT/potentials/Tables/divide_by_sparse_table.mexmaci _FullBNT/BNT/potentials/Tables/divide_by_table.c _FullBNT/BNT/potentials/Tables/divide_by_table.m _FullBNT/BNT/potentials/Tables/divide_by_table.mexmaci _FullBNT/BNT/potentials/Tables/extend_domain_table.m _FullBNT/BNT/potentials/Tables/marg_sparse_table.c _FullBNT/BNT/potentials/Tables/marg_sparse_table.mexmaci _FullBNT/BNT/potentials/Tables/marg_table.c _FullBNT/BNT/potentials/Tables/marg_table.m _FullBNT/BNT/potentials/Tables/marg_table.mexmaci _FullBNT/BNT/potentials/Tables/marg_tableC.c _FullBNT/BNT/potentials/Tables/marg_tableM.m _FullBNT/BNT/potentials/Tables/mult_by_sparse_table.c _FullBNT/BNT/potentials/Tables/mult_by_sparse_table.mexmaci _FullBNT/BNT/potentials/Tables/mult_by_table.c _FullBNT/BNT/potentials/Tables/mult_by_table.m _FullBNT/BNT/potentials/Tables/mult_by_table.mexmaci _FullBNT/BNT/potentials/Tables/mult_by_table2.m _FullBNT/BNT/potentials/Tables/mult_by_tableC.c _FullBNT/BNT/potentials/Tables/mult_by_tableM.m _FullBNT/BNT/potentials/Tables/mult_by_table_global.m _FullBNT/BNT/potentials/Tables/rep_mult.c _FullBNT/BNT/potentials/Tables/rep_mult.mexmaci _FullBNT/BNT/potentials/Tables/repmat_and_mult.c _FullBNT/BNT/potentials/check_for_cd_arcs.m _FullBNT/BNT/potentials/determine_pot_type.m _FullBNT/BNT/potentials/genops.c _FullBNT/BNT/potentials/mk_initial_pot.m _FullBNT/BNT/test_BNT.m _FullBNT/BNT/uninstallC_BNT.m _FullBNT/KPMstats/CVS/Entries _FullBNT/KPMstats/CVS/Repository _FullBNT/KPMstats/CVS/Root _FullBNT/KPMstats/KLgauss.m _FullBNT/KPMstats/README.txt _FullBNT/KPMstats/beta_sample.m _FullBNT/KPMstats/chisquared_histo.m _FullBNT/KPMstats/chisquared_prob.m _FullBNT/KPMstats/chisquared_readme.txt _FullBNT/KPMstats/chisquared_table.m _FullBNT/KPMstats/clg_Mstep.m _FullBNT/KPMstats/clg_Mstep_simple.m _FullBNT/KPMstats/clg_prob.m _FullBNT/KPMstats/condGaussToJoint.m _FullBNT/KPMstats/cond_indep_fisher_z.m _FullBNT/KPMstats/condgaussTrainObserved.m _FullBNT/KPMstats/condgauss_sample.m _FullBNT/KPMstats/convertBinaryLabels.m _FullBNT/KPMstats/cwr_demo.m _FullBNT/KPMstats/cwr_em.m _FullBNT/KPMstats/cwr_predict.m _FullBNT/KPMstats/cwr_prob.m _FullBNT/KPMstats/cwr_readme.txt _FullBNT/KPMstats/cwr_test.m _FullBNT/KPMstats/dirichlet_sample.m _FullBNT/KPMstats/dirichletpdf.m _FullBNT/KPMstats/dirichletrnd.m _FullBNT/KPMstats/distchck.m _FullBNT/KPMstats/eigdec.m _FullBNT/KPMstats/est_transmat.m _FullBNT/KPMstats/fit_paritioned_model_testfn.m _FullBNT/KPMstats/fit_partitioned_model.m _FullBNT/KPMstats/gamma_sample.m _FullBNT/KPMstats/gaussian_prob.m _FullBNT/KPMstats/gaussian_sample.m _FullBNT/KPMstats/histCmpChi2.m _FullBNT/KPMstats/linear_regression.m _FullBNT/KPMstats/logist2.m _FullBNT/KPMstats/logist2Apply.m _FullBNT/KPMstats/logist2ApplyRegularized.m _FullBNT/KPMstats/logist2Fit.m _FullBNT/KPMstats/logist2FitRegularized.m _FullBNT/KPMstats/logistK.m _FullBNT/KPMstats/logistK_eval.m _FullBNT/KPMstats/marginalize_gaussian.m _FullBNT/KPMstats/matrix_T_pdf.m _FullBNT/KPMstats/matrix_normal_pdf.m _FullBNT/KPMstats/mc_stat_distrib.m _FullBNT/KPMstats/mixgauss_Mstep.m _FullBNT/KPMstats/mixgauss_classifier_apply.m _FullBNT/KPMstats/mixgauss_classifier_train.m _FullBNT/KPMstats/mixgauss_em.m _FullBNT/KPMstats/mixgauss_init.m _FullBNT/KPMstats/mixgauss_prob.m _FullBNT/KPMstats/mixgauss_prob_test.m _FullBNT/KPMstats/mixgauss_sample.m _FullBNT/KPMstats/mkPolyFvec.m _FullBNT/KPMstats/mk_unit_norm.m _FullBNT/KPMstats/multinomial_prob.m _FullBNT/KPMstats/multinomial_sample.m _FullBNT/KPMstats/multipdf.m _FullBNT/KPMstats/multirnd.m _FullBNT/KPMstats/normal_coef.m _FullBNT/KPMstats/partial_corr_coef.m _FullBNT/KPMstats/parzen.m _FullBNT/KPMstats/parzenC.c _FullBNT/KPMstats/parzenC.dll _FullBNT/KPMstats/parzenC.mexglx _FullBNT/KPMstats/parzenC_test.m _FullBNT/KPMstats/parzen_fit_select_unif.m _FullBNT/KPMstats/pca.m _FullBNT/KPMstats/rndcheck.m _FullBNT/KPMstats/sample.m _FullBNT/KPMstats/sample_discrete.m _FullBNT/KPMstats/sample_gaussian.m _FullBNT/KPMstats/standardize.m _FullBNT/KPMstats/student_t_logprob.m _FullBNT/KPMstats/student_t_prob.m _FullBNT/KPMstats/test_dir.m _FullBNT/KPMstats/unidrndKPM.m _FullBNT/KPMstats/unif_discrete_sample.m _FullBNT/KPMstats/weightedRegression.m _FullBNT/KPMtools/CVS/Entries _FullBNT/KPMtools/CVS/Repository _FullBNT/KPMtools/CVS/Root _FullBNT/KPMtools/README.txt _FullBNT/KPMtools/approx_unique.m _FullBNT/KPMtools/approxeq.m _FullBNT/KPMtools/argmax.m _FullBNT/KPMtools/argmin.m _FullBNT/KPMtools/asdemo.html _FullBNT/KPMtools/asdemo.m _FullBNT/KPMtools/asort.m _FullBNT/KPMtools/assert.m _FullBNT/KPMtools/assignEdgeNums.m _FullBNT/KPMtools/assign_cols.m _FullBNT/KPMtools/axis_pct.m _FullBNT/KPMtools/bipartiteMatchingDemo.m _FullBNT/KPMtools/bipartiteMatchingDemoPlot.m _FullBNT/KPMtools/bipartiteMatchingHungarian.m _FullBNT/KPMtools/bipartiteMatchingIntProg.m _FullBNT/KPMtools/block.m _FullBNT/KPMtools/cell2matPad.m _FullBNT/KPMtools/cell2num.m _FullBNT/KPMtools/centeringMatrix.m _FullBNT/KPMtools/checkpsd.m _FullBNT/KPMtools/chi2inv.m _FullBNT/KPMtools/choose.m _FullBNT/KPMtools/collapse_mog.m _FullBNT/KPMtools/colmult.c _FullBNT/KPMtools/colmult.mexglx _FullBNT/KPMtools/computeROC.m _FullBNT/KPMtools/compute_counts.m _FullBNT/KPMtools/conf2mahal.m _FullBNT/KPMtools/cross_entropy.m _FullBNT/KPMtools/dirKPM.m _FullBNT/KPMtools/div.m _FullBNT/KPMtools/draw_circle.m _FullBNT/KPMtools/draw_ellipse.m _FullBNT/KPMtools/draw_ellipse_axes.m _FullBNT/KPMtools/em_converged.m _FullBNT/KPMtools/entropy.m _FullBNT/KPMtools/exportfig.m _FullBNT/KPMtools/extend_domain_table.m _FullBNT/KPMtools/factorial.m _FullBNT/KPMtools/filepartsLast.m _FullBNT/KPMtools/find_equiv_posns.m _FullBNT/KPMtools/fullfileKPM.m _FullBNT/KPMtools/genpathKPM.m _FullBNT/KPMtools/hash_add.m _FullBNT/KPMtools/hash_del.m _FullBNT/KPMtools/hash_lookup.m _FullBNT/KPMtools/hsvKPM.m _FullBNT/KPMtools/hungarian.m _FullBNT/KPMtools/image_rgb.m _FullBNT/KPMtools/imresizeAspect.m _FullBNT/KPMtools/ind2subv.m _FullBNT/KPMtools/ind2subvKPM.c _FullBNT/KPMtools/ind2subvKPM.m _FullBNT/KPMtools/ind2subvMinka.m _FullBNT/KPMtools/ind2subvTest.m _FullBNT/KPMtools/initFigures.m _FullBNT/KPMtools/installC_KPMtools.m _FullBNT/KPMtools/is_psd.m _FullBNT/KPMtools/is_stochastic.m _FullBNT/KPMtools/isemptycell.m _FullBNT/KPMtools/isequalKPM.m _FullBNT/KPMtools/isposdef.m _FullBNT/KPMtools/isscalar.m _FullBNT/KPMtools/isvector.m _FullBNT/KPMtools/junk.c _FullBNT/KPMtools/loadcell.m _FullBNT/KPMtools/logb.m _FullBNT/KPMtools/logdet.m _FullBNT/KPMtools/logsum.m _FullBNT/KPMtools/logsum_simple.m _FullBNT/KPMtools/logsum_test.m _FullBNT/KPMtools/logsumexp.m _FullBNT/KPMtools/logsumexpv.m _FullBNT/KPMtools/mahal2conf.m _FullBNT/KPMtools/marg_table.m _FullBNT/KPMtools/marginalize_table.m _FullBNT/KPMtools/matprint.m _FullBNT/KPMtools/max_mult.c _FullBNT/KPMtools/max_mult.m _FullBNT/KPMtools/mexutil.c _FullBNT/KPMtools/mexutil.h _FullBNT/KPMtools/mk_multi_index.m _FullBNT/KPMtools/mk_stochastic.m _FullBNT/KPMtools/mkdirKPM.m _FullBNT/KPMtools/montageKPM.m _FullBNT/KPMtools/montageKPM2.m _FullBNT/KPMtools/montageKPM3.m _FullBNT/KPMtools/mult_by_table.m _FullBNT/KPMtools/myintersect.m _FullBNT/KPMtools/myismember.m _FullBNT/KPMtools/myones.m _FullBNT/KPMtools/myplot.m _FullBNT/KPMtools/myrand.m _FullBNT/KPMtools/myrepmat.m _FullBNT/KPMtools/myreshape.m _FullBNT/KPMtools/mysetdiff.m _FullBNT/KPMtools/mysize.m _FullBNT/KPMtools/mysubset.m _FullBNT/KPMtools/mysymsetdiff.m _FullBNT/KPMtools/myunion.m _FullBNT/KPMtools/nchoose2.m _FullBNT/KPMtools/ncols.m _FullBNT/KPMtools/nonmaxsup.m _FullBNT/KPMtools/normalise.m _FullBNT/KPMtools/normaliseC.c _FullBNT/KPMtools/normaliseC.dll _FullBNT/KPMtools/normalize.m _FullBNT/KPMtools/nrows.m _FullBNT/KPMtools/num2strcell.m _FullBNT/KPMtools/optimalMatching.m _FullBNT/KPMtools/optimalMatchingTest.m _FullBNT/KPMtools/partitionData.m _FullBNT/KPMtools/partition_matrix_vec.m _FullBNT/KPMtools/pca_kpm.m _FullBNT/KPMtools/pca_netlab.m _FullBNT/KPMtools/pick.m _FullBNT/KPMtools/plotBox.m _FullBNT/KPMtools/plotColors.m _FullBNT/KPMtools/plotROC.m _FullBNT/KPMtools/plotROCkpm.m _FullBNT/KPMtools/plot_axis_thru_origin.m _FullBNT/KPMtools/plot_ellipse.m _FullBNT/KPMtools/plot_matrix.m _FullBNT/KPMtools/plot_polygon.m _FullBNT/KPMtools/plotcov2.m _FullBNT/KPMtools/plotcov2New.m _FullBNT/KPMtools/plotcov3.m _FullBNT/KPMtools/plotgauss1d.m _FullBNT/KPMtools/plotgauss2d.m _FullBNT/KPMtools/plotgauss2d_old.m _FullBNT/KPMtools/polygon_area.m _FullBNT/KPMtools/polygon_centroid.m _FullBNT/KPMtools/polygon_intersect.m _FullBNT/KPMtools/previewfig.m _FullBNT/KPMtools/process_options.m _FullBNT/KPMtools/rand_psd.m _FullBNT/KPMtools/rectintC.m _FullBNT/KPMtools/rectintLoopC.c _FullBNT/KPMtools/rectintLoopC.dll _FullBNT/KPMtools/rectintLoopC.mexglx _FullBNT/KPMtools/rectintSparse.m _FullBNT/KPMtools/rectintSparseC.m _FullBNT/KPMtools/rectintSparseLoopC.c _FullBNT/KPMtools/rectintSparseLoopC.dll _FullBNT/KPMtools/repmatC.c _FullBNT/KPMtools/repmatC.dll _FullBNT/KPMtools/repmatC.mexglx _FullBNT/KPMtools/rgb2grayKPM.m _FullBNT/KPMtools/rnd_partition.m _FullBNT/KPMtools/rotate_xlabel.m _FullBNT/KPMtools/safeStr.m _FullBNT/KPMtools/sampleUniformInts.m _FullBNT/KPMtools/sample_discrete.m _FullBNT/KPMtools/set_xtick_label.m _FullBNT/KPMtools/set_xtick_label_demo.m _FullBNT/KPMtools/setdiag.m _FullBNT/KPMtools/softeye.m _FullBNT/KPMtools/sort_evec.m _FullBNT/KPMtools/splitLongSeqIntoManyShort.m _FullBNT/KPMtools/sprintf_intvec.m _FullBNT/KPMtools/sqdist.m _FullBNT/KPMtools/strmatch_multi.m _FullBNT/KPMtools/strmatch_substr.m _FullBNT/KPMtools/strsplit.m _FullBNT/KPMtools/subplot2.m _FullBNT/KPMtools/subplot3.m _FullBNT/KPMtools/subsets.m _FullBNT/KPMtools/subsets1.m _FullBNT/KPMtools/subsetsFixedSize.m _FullBNT/KPMtools/subv2ind.m _FullBNT/KPMtools/subv2indKPM.c _FullBNT/KPMtools/subv2indKPM.m _FullBNT/KPMtools/subv2indMinka.m _FullBNT/KPMtools/subv2indTest.m _FullBNT/KPMtools/sumv.m _FullBNT/KPMtools/suptitle.m _FullBNT/KPMtools/unaryEncoding.m _FullBNT/KPMtools/wrap.m _FullBNT/KPMtools/xticklabel_rotate90.m _FullBNT/KPMtools/zipload.m _FullBNT/KPMtools/zipsave.m _beattracker/README _beattracker/adapt_thresh.m _beattracker/bcfm.m _beattracker/bt_parms.m _beattracker/chromaframe.m _beattracker/dojsdiv2.m _beattracker/findmeter.m _beattracker/findmeter_mm.m _beattracker/ftacf.m _beattracker/get_dfs.m _beattracker/getalignment2.m _beattracker/getbcfs2.m _beattracker/getmeasures2.m _beattracker/getmeasures3 _beattracker/getmeasures3.m _beattracker/getmeasures4.m _beattracker/getperiod.m _beattracker/hanningz.m _beattracker/newtt_hmm_dp.m _beattracker/princarg.m _beattracker/refineperiod.m _beattracker/sunity.m _beattracker/tempo_hmm.m _beattracker/viterbi_path.m _chordtools/CVS/Entries _chordtools/CVS/Repository _chordtools/CVS/Root _chordtools/CVS/Template _chordtools/addshort2list.m _chordtools/checklabs.m _chordtools/checklabsyntax.m _chordtools/chord2fifthpositions.m _chordtools/chord2midinotes.m _chordtools/chord2notes.m _chordtools/chord2pitchclasses.m _chordtools/chord2quality.m _chordtools/contents.m _chordtools/degree2note.m _chordtools/degree2semitone.m _chordtools/degrees2notes.m _chordtools/degrees2quality.m _chordtools/degrees2semitones.m _chordtools/getchordinfo.m _chordtools/interval2degree.m _chordtools/interval2semitone.m _chordtools/labread.m _chordtools/labwrite.m _chordtools/mlf2lab.m _chordtools/note2degree.m _chordtools/note2fifthinfo.m _chordtools/note2fifthposition.m _chordtools/note2pitchclass.m _chordtools/notes2fifthpositions.m _chordtools/notes2pitchclasses.m _chordtools/parsechord.m _chordtools/parsedegree.m _chordtools/parsedegreelist.m _chordtools/parsenote.m _chordtools/short2quality.m _chordtools/shorthand2degrees.m _chordtools/syntaxcheck.m _chordtools/transcriptions/01final/01_-_I_Saw_Her_Standing_There.lab _chordtools/transcriptions/01final/02_-_Misery.lab _chordtools/transcriptions/01final/03_-_Anna_(Go_To_Him).lab _chordtools/transcriptions/01final/04_-_Chains.lab _chordtools/transcriptions/01final/05_-_Boys.lab _chordtools/transcriptions/01final/06_-_Ask_Me_Why.lab _chordtools/transcriptions/01final/07_-_Please_Please_Me.lab _chordtools/transcriptions/01final/08_-_Love_Me_Do.lab _chordtools/transcriptions/01final/09_-_P._S._I_Love_You.lab _chordtools/transcriptions/01final/10_-_Baby_It's_You.lab _chordtools/transcriptions/01final/11_-_Do_You_Want_To_Know_A_Secret.lab _chordtools/transcriptions/01final/12_-_A_Taste_Of_Honey.lab _chordtools/transcriptions/01final/13_-_There's_A_Place.lab _chordtools/transcriptions/01final/14_-_Twist_And_Shout.lab _chordtools/transcriptions/01final/CVS/Entries _chordtools/transcriptions/01final/CVS/Repository _chordtools/transcriptions/01final/CVS/Root _chordtools/transcriptions/01final/CVS/Template _chordtools/transcriptions/02final/01_-_It_Won't_Be_Long.lab _chordtools/transcriptions/02final/02_-_All_I've_Got_To_Do.lab _chordtools/transcriptions/02final/03_-_All_My_Loving.lab _chordtools/transcriptions/02final/04_-_Don't_Bother_Me.lab _chordtools/transcriptions/02final/05_-_Little_Child.lab _chordtools/transcriptions/02final/06_-_Till_There_Was_You.lab _chordtools/transcriptions/02final/07_-_Please_Mister_Postman.lab _chordtools/transcriptions/02final/08_-_Roll_Over_Beethoven.lab _chordtools/transcriptions/02final/09_-_Hold_Me_Tight.lab _chordtools/transcriptions/02final/10_-_You_Really_Got_A_Hold_On_Me.lab _chordtools/transcriptions/02final/11_-_I_Wanna_Be_Your_Man.lab _chordtools/transcriptions/02final/12_-_Devil_In_Her_Heart.lab _chordtools/transcriptions/02final/13_-_Not_A_Second_Time.lab _chordtools/transcriptions/02final/14_-_Money.lab _chordtools/transcriptions/02final/CVS/Entries _chordtools/transcriptions/02final/CVS/Repository _chordtools/transcriptions/02final/CVS/Root _chordtools/transcriptions/02final/CVS/Template _chordtools/transcriptions/03final/01_-_A_Hard_Day's_Night.lab _chordtools/transcriptions/03final/02_-_I_Should_Have_Known_Better.lab _chordtools/transcriptions/03final/03_-_If_I_Fell.lab _chordtools/transcriptions/03final/04_-_I'm_Happy_Just_To_Dance_With_You.lab _chordtools/transcriptions/03final/05_-_And_I_Love_Her.lab _chordtools/transcriptions/03final/06_-_Tell_Me_Why.lab _chordtools/transcriptions/03final/07_-_Can't_Buy_Me_Love.lab _chordtools/transcriptions/03final/08_-_Any_Time_At_All.lab _chordtools/transcriptions/03final/09_-_I'll_Cry_Instead.lab _chordtools/transcriptions/03final/10_-_Things_We_Said_Today.lab _chordtools/transcriptions/03final/11_-_When_I_Get_Home.lab _chordtools/transcriptions/03final/12_-_You_Can't_Do_That.lab _chordtools/transcriptions/03final/13_-_I'll_Be_Back.lab _chordtools/transcriptions/03final/CVS/Entries _chordtools/transcriptions/03final/CVS/Repository _chordtools/transcriptions/03final/CVS/Root _chordtools/transcriptions/03final/CVS/Template _chordtools/transcriptions/04final/01_-_No_Reply.lab _chordtools/transcriptions/04final/02_-_I'm_a_Loser.lab _chordtools/transcriptions/04final/03_-_Baby's_In_Black.lab _chordtools/transcriptions/04final/04_-_Rock_and_Roll_Music.lab _chordtools/transcriptions/04final/05_-_I'll_Follow_the_Sun.lab _chordtools/transcriptions/04final/06_-_Mr._Moonlight.lab _chordtools/transcriptions/04final/07_-_Kansas_City-_Hey,_Hey,_Hey,_Hey.lab _chordtools/transcriptions/04final/08_-_Eight_Days_a_Week.lab _chordtools/transcriptions/04final/09_-_Words_of_Love.lab _chordtools/transcriptions/04final/10_-_Honey_Don't.lab _chordtools/transcriptions/04final/11_-_Every_Little_Thing.lab _chordtools/transcriptions/04final/12_-_I_Don't_Want_to_Spoil_the_Party.lab _chordtools/transcriptions/04final/13_-_What_You're_Doing.lab _chordtools/transcriptions/04final/14_-_Everybody's_Trying_to_Be_My_Baby.lab _chordtools/transcriptions/04final/CVS/Entries _chordtools/transcriptions/04final/CVS/Repository _chordtools/transcriptions/04final/CVS/Root _chordtools/transcriptions/04final/CVS/Template _chordtools/transcriptions/05final/01_-_Help!.lab _chordtools/transcriptions/05final/02_-_The_Night_Before.lab _chordtools/transcriptions/05final/03_-_You've_Got_To_Hide_Your_Love_Away.lab _chordtools/transcriptions/05final/04_-_I_Need_You.lab _chordtools/transcriptions/05final/05_-_Another_Girl.lab _chordtools/transcriptions/05final/06_-_You're_Going_to_Lose_That_Girl.lab _chordtools/transcriptions/05final/07_-_Ticket_To_Ride.lab _chordtools/transcriptions/05final/08_-_Act_Naturally.lab _chordtools/transcriptions/05final/09_-_It's_Only_Love.lab _chordtools/transcriptions/05final/10_-_You_Like_Me_Too_Much.lab _chordtools/transcriptions/05final/11_-_Tell_Me_What_You_See.lab _chordtools/transcriptions/05final/12_-_I've_Just_Seen_a_Face.lab _chordtools/transcriptions/05final/13_-_Yesterday.lab _chordtools/transcriptions/05final/14_-_Dizzy_Miss_Lizzie.lab _chordtools/transcriptions/05final/CVS/Entries _chordtools/transcriptions/05final/CVS/Repository _chordtools/transcriptions/05final/CVS/Root _chordtools/transcriptions/05final/CVS/Template _chordtools/transcriptions/06final/01_-_Drive_My_Car.lab _chordtools/transcriptions/06final/02_-_Norwegian_Wood_(This_Bird_Has_Flown).lab _chordtools/transcriptions/06final/03_-_You_Won't_See_Me.lab _chordtools/transcriptions/06final/04_-_Nowhere_Man.lab _chordtools/transcriptions/06final/05_-_Think_For_Yourself.lab _chordtools/transcriptions/06final/06_-_The_Word.lab _chordtools/transcriptions/06final/07_-_Michelle.lab _chordtools/transcriptions/06final/08_-_What_Goes_On.lab _chordtools/transcriptions/06final/09_-_Girl.lab _chordtools/transcriptions/06final/10_-_I'm_Looking_Through_You.lab _chordtools/transcriptions/06final/11_-_In_My_Life.lab _chordtools/transcriptions/06final/12_-_Wait.lab _chordtools/transcriptions/06final/13_-_If_I_Needed_Someone.lab _chordtools/transcriptions/06final/14_-_Run_For_Your_Life.lab _chordtools/transcriptions/06final/CVS/Entries _chordtools/transcriptions/06final/CVS/Repository _chordtools/transcriptions/06final/CVS/Root _chordtools/transcriptions/06final/CVS/Template _chordtools/transcriptions/07final/01_-_Taxman.lab _chordtools/transcriptions/07final/02_-_Eleanor_Rigby.lab _chordtools/transcriptions/07final/03_-_I'm_Only_Sleeping.lab _chordtools/transcriptions/07final/04_-_Love_You_To.lab _chordtools/transcriptions/07final/05_-_Here,_There_And_Everywhere.lab _chordtools/transcriptions/07final/06_-_Yellow_Submarine.lab _chordtools/transcriptions/07final/07_-_She_Said_She_Said.lab _chordtools/transcriptions/07final/08_-_Good_Day_Sunshine.lab _chordtools/transcriptions/07final/09_-_And_Your_Bird_Can_Sing.lab _chordtools/transcriptions/07final/10_-_For_No_One.lab _chordtools/transcriptions/07final/11_-_Doctor_Robert.lab _chordtools/transcriptions/07final/12_-_I_Want_To_Tell_You.lab _chordtools/transcriptions/07final/13_-_Got_To_Get_You_Into_My_Life.lab _chordtools/transcriptions/07final/14_-_Tomorrow_Never_Knows.lab _chordtools/transcriptions/07final/CVS/Entries _chordtools/transcriptions/07final/CVS/Repository _chordtools/transcriptions/07final/CVS/Root _chordtools/transcriptions/07final/CVS/Template _chordtools/transcriptions/08final/01_-_Sgt._Pepper's_Lonely_Hearts_Club_Band.lab _chordtools/transcriptions/08final/02_-_With_A_Little_Help_From_My_Friends.lab _chordtools/transcriptions/08final/03_-_Lucy_In_The_Sky_With_Diamonds.lab _chordtools/transcriptions/08final/04_-_Getting_Better.lab _chordtools/transcriptions/08final/05_-_Fixing_A_Hole.lab _chordtools/transcriptions/08final/06_-_She's_Leaving_Home.lab _chordtools/transcriptions/08final/07_-_Being_For_The_Benefit_Of_Mr._Kite!.lab _chordtools/transcriptions/08final/08_-_Within_You_Without_You.lab _chordtools/transcriptions/08final/09_-_When_I'm_Sixty-Four.lab _chordtools/transcriptions/08final/10_-_Lovely_Rita.lab _chordtools/transcriptions/08final/11_-_Good_Morning_Good_Morning.lab _chordtools/transcriptions/08final/12_-_Sgt._Pepper's_Lonely_Hearts_Club_Band_(Reprise).lab _chordtools/transcriptions/08final/13_-_A_Day_In_The_Life.lab _chordtools/transcriptions/08final/CVS/Entries _chordtools/transcriptions/08final/CVS/Repository _chordtools/transcriptions/08final/CVS/Root _chordtools/transcriptions/08final/CVS/Template _chordtools/transcriptions/09final/01_-_Magical_Mystery_Tour.lab _chordtools/transcriptions/09final/02_-_The_Fool_On_The_Hill.lab _chordtools/transcriptions/09final/03_-_Flying.lab _chordtools/transcriptions/09final/04_-_Blue_Jay_Way.lab _chordtools/transcriptions/09final/05_-_Your_Mother_Should_Know.lab _chordtools/transcriptions/09final/06_-_I_Am_The_Walrus.lab _chordtools/transcriptions/09final/07_-_Hello_Goodbye.lab _chordtools/transcriptions/09final/08_-_Strawberry_Fields_Forever.lab _chordtools/transcriptions/09final/09_-_Penny_Lane.lab _chordtools/transcriptions/09final/10_-_Baby_You're_A_Rich_Man.lab _chordtools/transcriptions/09final/11_-_All_You_Need_Is_Love.lab _chordtools/transcriptions/09final/CVS/Entries _chordtools/transcriptions/09final/CVS/Repository _chordtools/transcriptions/09final/CVS/Root _chordtools/transcriptions/09final/CVS/Template _chordtools/transcriptions/10CD1final/CD1_-_01_-_Back_in_the_USSR.lab _chordtools/transcriptions/10CD1final/CD1_-_02_-_Dear_Prudence.lab _chordtools/transcriptions/10CD1final/CD1_-_03_-_Glass_Onion.lab _chordtools/transcriptions/10CD1final/CD1_-_04_-_Ob-La-Di,_Ob-La-Da.lab _chordtools/transcriptions/10CD1final/CD1_-_05_-_Wild_Honey_Pie.lab _chordtools/transcriptions/10CD1final/CD1_-_06_-The_Continuing_Story_of_Bungalow_Bill.lab _chordtools/transcriptions/10CD1final/CD1_-_07_-_While_My_Guitar_Gently_Weeps.lab _chordtools/transcriptions/10CD1final/CD1_-_08_-_Happiness_is_a_Warm_Gun.lab _chordtools/transcriptions/10CD1final/CD1_-_09_-_Martha_My_Dear.lab _chordtools/transcriptions/10CD1final/CD1_-_10_-_I'm_So_Tired.lab _chordtools/transcriptions/10CD1final/CD1_-_11_-_Black_Bird.lab _chordtools/transcriptions/10CD1final/CD1_-_12_-_Piggies.lab _chordtools/transcriptions/10CD1final/CD1_-_13_-_Rocky_Raccoon.lab _chordtools/transcriptions/10CD1final/CD1_-_14_-_Don't_Pass_Me_By.lab _chordtools/transcriptions/10CD1final/CD1_-_15_-_Why_Don't_We_Do_It_In_The_Road.lab _chordtools/transcriptions/10CD1final/CD1_-_16_-_I_Will.lab _chordtools/transcriptions/10CD1final/CD1_-_17_-_Julia.lab _chordtools/transcriptions/10CD1final/CVS/Entries _chordtools/transcriptions/10CD1final/CVS/Repository _chordtools/transcriptions/10CD1final/CVS/Root _chordtools/transcriptions/10CD1final/CVS/Template _chordtools/transcriptions/10CD2final/CD2_-_01_-_Birthday.lab _chordtools/transcriptions/10CD2final/CD2_-_02_-_Yer_Blues.lab _chordtools/transcriptions/10CD2final/CD2_-_03_-_Mother_Nature's_Son.lab _chordtools/transcriptions/10CD2final/CD2_-_04_-_Everybody's_Got_Something_To_Hide_Except_Me_and_M.lab _chordtools/transcriptions/10CD2final/CD2_-_05_-_Sexy_Sadie.lab _chordtools/transcriptions/10CD2final/CD2_-_06_-_Helter_Skelter.lab _chordtools/transcriptions/10CD2final/CD2_-_07_-_Long_Long_Long.lab _chordtools/transcriptions/10CD2final/CD2_-_08_-_Revolution_1.lab _chordtools/transcriptions/10CD2final/CD2_-_09_-_Honey_Pie.lab _chordtools/transcriptions/10CD2final/CD2_-_10_-_Savoy_Truffle.lab _chordtools/transcriptions/10CD2final/CD2_-_11_-_Cry_Baby_Cry.lab _chordtools/transcriptions/10CD2final/CD2_-_12_-_Revolution_9.lab _chordtools/transcriptions/10CD2final/CD2_-_13_-_Good_Night.lab _chordtools/transcriptions/10CD2final/CVS/Entries _chordtools/transcriptions/10CD2final/CVS/Repository _chordtools/transcriptions/10CD2final/CVS/Root _chordtools/transcriptions/10CD2final/CVS/Template _chordtools/transcriptions/11final/01_-_Come_Together.lab _chordtools/transcriptions/11final/02_-_Something.lab _chordtools/transcriptions/11final/03_-_Maxwell's_Silver_Hammer.lab _chordtools/transcriptions/11final/04_-_Oh!_Darling.lab _chordtools/transcriptions/11final/05_-_Octopus's_Garden.lab _chordtools/transcriptions/11final/06_-_I_Want_You.lab _chordtools/transcriptions/11final/07_-_Here_Comes_The_Sun.lab _chordtools/transcriptions/11final/08_-_Because.lab _chordtools/transcriptions/11final/09_-_You_Never_Give_Me_Your_Money.lab _chordtools/transcriptions/11final/10_-_Sun_King.lab _chordtools/transcriptions/11final/11_-_Mean_Mr_Mustard.lab _chordtools/transcriptions/11final/12_-_Polythene_Pam.lab _chordtools/transcriptions/11final/13_-_She_Came_In_Through_The_Bathroom_Window.lab _chordtools/transcriptions/11final/14_-_Golden_Slumbers.lab _chordtools/transcriptions/11final/15_-_Carry_That_Weight.lab _chordtools/transcriptions/11final/16_-_The_End.lab _chordtools/transcriptions/11final/17_-_Her_Majesty.lab _chordtools/transcriptions/11final/CVS/Entries _chordtools/transcriptions/11final/CVS/Repository _chordtools/transcriptions/11final/CVS/Root _chordtools/transcriptions/11final/CVS/Template _chordtools/transcriptions/12final/01_-_Two_of_Us.lab _chordtools/transcriptions/12final/02_-_Dig_a_Pony.lab _chordtools/transcriptions/12final/03_-_Across_the_Universe.lab _chordtools/transcriptions/12final/04_-_I_Me_Mine.lab _chordtools/transcriptions/12final/05_-_Dig_It.lab _chordtools/transcriptions/12final/06_-_Let_It_Be.lab _chordtools/transcriptions/12final/07_-_Maggie_Mae.lab _chordtools/transcriptions/12final/08_-_I've_Got_A_Feeling.lab _chordtools/transcriptions/12final/09_-_One_After_909.lab _chordtools/transcriptions/12final/10_-_The_Long_and_Winding_Road.lab _chordtools/transcriptions/12final/11_-_For_You_Blue.lab _chordtools/transcriptions/12final/12_-_Get_Back.lab _chordtools/transcriptions/12final/CVS/Entries _chordtools/transcriptions/12final/CVS/Repository _chordtools/transcriptions/12final/CVS/Root _chordtools/transcriptions/12final/CVS/Template _chordtools/transcriptions/CVS/Entries _chordtools/transcriptions/CVS/Entries.Log _chordtools/transcriptions/CVS/Repository _chordtools/transcriptions/CVS/Root _chordtools/transcriptions/CVS/Template _chordtools/tuning/01tuning/01_-_I_Saw_Her_Standing_There.tun _chordtools/tuning/01tuning/02_-_Misery.tun _chordtools/tuning/01tuning/03_-_Anna_(Go_To_Him).tun _chordtools/tuning/01tuning/04_-_Chains.tun _chordtools/tuning/01tuning/05_-_Boys.tun _chordtools/tuning/01tuning/06_-_Ask_Me_Why.tun _chordtools/tuning/01tuning/07_-_Please_Please_Me.tun _chordtools/tuning/01tuning/08_-_Love_Me_Do.tun _chordtools/tuning/01tuning/09_-_P._S._I_Love_You.tun _chordtools/tuning/01tuning/10_-_Baby_It's_You.tun _chordtools/tuning/01tuning/11_-_Do_You_Want_To_Know_A_Secret.tun _chordtools/tuning/01tuning/12_-_A_Taste_Of_Honey.tun _chordtools/tuning/01tuning/13_-_There's_A_Place.tun _chordtools/tuning/01tuning/14_-_Twist_And_Shout.tun _chordtools/tuning/01tuning/CVS/Entries _chordtools/tuning/01tuning/CVS/Repository _chordtools/tuning/01tuning/CVS/Root _chordtools/tuning/01tuning/CVS/Template _chordtools/tuning/02tuning/01_-_It_Won't_Be_Long.tun _chordtools/tuning/02tuning/02_-_All_I've_Got_To_Do.tun _chordtools/tuning/02tuning/03_-_All_My_Loving.tun _chordtools/tuning/02tuning/04_-_Don't_Bother_Me.tun _chordtools/tuning/02tuning/05_-_Little_Child.tun _chordtools/tuning/02tuning/06_-_Till_There_Was_You.tun _chordtools/tuning/02tuning/07_-_Please_Mister_Postman.tun _chordtools/tuning/02tuning/08_-_Roll_Over_Beethoven.tun _chordtools/tuning/02tuning/09_-_Hold_Me_Tight.tun _chordtools/tuning/02tuning/10_-_You_Really_Got_A_Hold_On_Me.tun _chordtools/tuning/02tuning/11_-_I_Wanna_Be_Your_Man.tun _chordtools/tuning/02tuning/12_-_Devil_In_Her_Heart.tun _chordtools/tuning/02tuning/13_-_Not_A_Second_Time.tun _chordtools/tuning/02tuning/14_-_Money.tun _chordtools/tuning/02tuning/CVS/Entries _chordtools/tuning/02tuning/CVS/Repository _chordtools/tuning/02tuning/CVS/Root _chordtools/tuning/02tuning/CVS/Template _chordtools/tuning/03tuning/01_-_A_Hard_Day's_Night.tun _chordtools/tuning/03tuning/02_-_I_Should_Have_Known_Better.tun _chordtools/tuning/03tuning/03_-_If_I_Fell.tun _chordtools/tuning/03tuning/04_-_I'm_Happy_Just_To_Dance_With_You.tun _chordtools/tuning/03tuning/05_-_And_I_Love_Her.tun _chordtools/tuning/03tuning/06_-_Tell_Me_Why.tun _chordtools/tuning/03tuning/07_-_Can't_Buy_Me_Love.tun _chordtools/tuning/03tuning/08_-_Any_Time_At_All.tun _chordtools/tuning/03tuning/09_-_I'll_Cry_Instead.tun _chordtools/tuning/03tuning/10_-_Things_We_Said_Today.tun _chordtools/tuning/03tuning/11_-_When_I_Get_Home.tun _chordtools/tuning/03tuning/12_-_You_Can't_Do_That.tun _chordtools/tuning/03tuning/13_-_I'll_Be_Back.tun _chordtools/tuning/03tuning/CVS/Entries _chordtools/tuning/03tuning/CVS/Repository _chordtools/tuning/03tuning/CVS/Root _chordtools/tuning/03tuning/CVS/Template _chordtools/tuning/04tuning/01_-_No_Reply.tun _chordtools/tuning/04tuning/02_-_I'm_a_Loser.tun _chordtools/tuning/04tuning/03_-_Baby's_In_Black.tun _chordtools/tuning/04tuning/04_-_Rock_and_Roll_Music.tun _chordtools/tuning/04tuning/05_-_I'll_Follow_the_Sun.tun _chordtools/tuning/04tuning/06_-_Mr._Moonlight.tun _chordtools/tuning/04tuning/07_-_Kansas_City-_Hey,_Hey,_Hey,_Hey.tun _chordtools/tuning/04tuning/08_-_Eight_Days_a_Week.tun _chordtools/tuning/04tuning/09_-_Words_of_Love.tun _chordtools/tuning/04tuning/10_-_Honey_Don't.tun _chordtools/tuning/04tuning/11_-_Every_Little_Thing.tun _chordtools/tuning/04tuning/12_-_I_Don't_Want_to_Spoil_the_Party.tun _chordtools/tuning/04tuning/13_-_What_You're_Doing.tun _chordtools/tuning/04tuning/14_-_Everybody's_Trying_to_Be_My_Baby.tun _chordtools/tuning/04tuning/CVS/Entries _chordtools/tuning/04tuning/CVS/Repository _chordtools/tuning/04tuning/CVS/Root _chordtools/tuning/04tuning/CVS/Template _chordtools/tuning/05tuning/01_-_Help!.tun _chordtools/tuning/05tuning/02_-_The_Night_Before.tun _chordtools/tuning/05tuning/03_-_You've_Got_To_Hide_Your_Love_Away.tun _chordtools/tuning/05tuning/04_-_I_Need_You.tun _chordtools/tuning/05tuning/05_-_Another_Girl.tun _chordtools/tuning/05tuning/06_-_You're_Going_to_Lose_That_Girl.tun _chordtools/tuning/05tuning/07_-_Ticket_To_Ride.tun _chordtools/tuning/05tuning/08_-_Act_Naturally.tun _chordtools/tuning/05tuning/09_-_It's_Only_Love.tun _chordtools/tuning/05tuning/10_-_You_Like_Me_Too_Much.tun _chordtools/tuning/05tuning/11_-_Tell_Me_What_You_See.tun _chordtools/tuning/05tuning/12_-_I've_Just_Seen_a_Face.tun _chordtools/tuning/05tuning/13_-_Yesterday.tun _chordtools/tuning/05tuning/14_-_Dizzy_Miss_Lizzie.tun _chordtools/tuning/05tuning/CVS/Entries _chordtools/tuning/05tuning/CVS/Repository _chordtools/tuning/05tuning/CVS/Root _chordtools/tuning/05tuning/CVS/Template _chordtools/tuning/06tuning/01_-_Drive_My_Car.tun _chordtools/tuning/06tuning/02_-_Norwegian_Wood_(This_Bird_Has_Flown).tun _chordtools/tuning/06tuning/03_-_You_Won't_See_Me.tun _chordtools/tuning/06tuning/04_-_Nowhere_Man.tun _chordtools/tuning/06tuning/05_-_Think_For_Yourself.tun _chordtools/tuning/06tuning/06_-_The_Word.tun _chordtools/tuning/06tuning/07_-_Michelle.tun _chordtools/tuning/06tuning/08_-_What_Goes_On.tun _chordtools/tuning/06tuning/09_-_Girl.tun _chordtools/tuning/06tuning/10_-_I'm_Looking_Through_You.tun _chordtools/tuning/06tuning/11_-_In_My_Life.tun _chordtools/tuning/06tuning/12_-_Wait.tun _chordtools/tuning/06tuning/13_-_If_I_Needed_Someone.tun _chordtools/tuning/06tuning/14_-_Run_For_Your_Life.tun _chordtools/tuning/06tuning/CVS/Entries _chordtools/tuning/06tuning/CVS/Repository _chordtools/tuning/06tuning/CVS/Root _chordtools/tuning/06tuning/CVS/Template _chordtools/tuning/07tuning/01_-_Taxman.tun _chordtools/tuning/07tuning/02_-_Eleanor_Rigby.tun _chordtools/tuning/07tuning/03_-_I'm_Only_Sleeping.tun _chordtools/tuning/07tuning/04_-_Love_You_To.tun _chordtools/tuning/07tuning/05_-_Here,_There_And_Everywhere.tun _chordtools/tuning/07tuning/06_-_Yellow_Submarine.tun _chordtools/tuning/07tuning/07_-_She_Said_She_Said.tun _chordtools/tuning/07tuning/08_-_Good_Day_Sunshine.tun _chordtools/tuning/07tuning/09_-_And_Your_Bird_Can_Sing.tun _chordtools/tuning/07tuning/10_-_For_No_One.tun _chordtools/tuning/07tuning/11_-_Doctor_Robert.tun _chordtools/tuning/07tuning/12_-_I_Want_To_Tell_You.tun _chordtools/tuning/07tuning/13_-_Got_To_Get_You_Into_My_Life.tun _chordtools/tuning/07tuning/14_-_Tomorrow_Never_Knows.tun _chordtools/tuning/07tuning/CVS/Entries _chordtools/tuning/07tuning/CVS/Repository _chordtools/tuning/07tuning/CVS/Root _chordtools/tuning/07tuning/CVS/Template _chordtools/tuning/08tuning/01_-_Sgt._Pepper's_Lonely_Hearts_Club_Band.tun _chordtools/tuning/08tuning/02_-_With_A_Little_Help_From_My_Friends.tun _chordtools/tuning/08tuning/03_-_Lucy_In_The_Sky_With_Diamonds.tun _chordtools/tuning/08tuning/04_-_Getting_Better.tun _chordtools/tuning/08tuning/05_-_Fixing_A_Hole.tun _chordtools/tuning/08tuning/06_-_She's_Leaving_Home.tun _chordtools/tuning/08tuning/07_-_Being_For_The_Benefit_Of_Mr._Kite!.tun _chordtools/tuning/08tuning/08_-_Within_You_Without_You.tun _chordtools/tuning/08tuning/09_-_When_I'm_Sixty-Four.tun _chordtools/tuning/08tuning/10_-_Lovely_Rita.tun _chordtools/tuning/08tuning/11_-_Good_Morning_Good_Morning.tun _chordtools/tuning/08tuning/12_-_Sgt._Pepper's_Lonely_Hearts_Club_Band_(Reprise).tun _chordtools/tuning/08tuning/13_-_A_Day_In_The_Life.tun _chordtools/tuning/08tuning/CVS/Entries _chordtools/tuning/08tuning/CVS/Repository _chordtools/tuning/08tuning/CVS/Root _chordtools/tuning/08tuning/CVS/Template _chordtools/tuning/09tuning/01_-_Magical_Mystery_Tour.tun _chordtools/tuning/09tuning/02_-_The_Fool_On_The_Hill.tun _chordtools/tuning/09tuning/03_-_Flying.tun _chordtools/tuning/09tuning/04_-_Blue_Jay_Way.tun _chordtools/tuning/09tuning/05_-_Your_Mother_Should_Know.tun _chordtools/tuning/09tuning/06_-_I_Am_The_Walrus.tun _chordtools/tuning/09tuning/07_-_Hello_Goodbye.tun _chordtools/tuning/09tuning/08_-_Strawberry_Fields_Forever.tun _chordtools/tuning/09tuning/09_-_Penny_Lane.tun _chordtools/tuning/09tuning/10_-_Baby_You're_A_Rich_Man.tun _chordtools/tuning/09tuning/11_-_All_You_Need_Is_Love.tun _chordtools/tuning/09tuning/CVS/Entries _chordtools/tuning/09tuning/CVS/Repository _chordtools/tuning/09tuning/CVS/Root _chordtools/tuning/09tuning/CVS/Template _chordtools/tuning/10CD1tuning/CD1_-_01_-_Back_in_the_USSR.tun _chordtools/tuning/10CD1tuning/CD1_-_02_-_Dear_Prudence.tun _chordtools/tuning/10CD1tuning/CD1_-_03_-_Glass_Onion.tun _chordtools/tuning/10CD1tuning/CD1_-_04_-_Ob-La-Di,_Ob-La-Da.tun _chordtools/tuning/10CD1tuning/CD1_-_05_-_Wild_Honey_Pie.tun _chordtools/tuning/10CD1tuning/CD1_-_06_-The_Continuing_Story_of_Bungalow_Bill.tun _chordtools/tuning/10CD1tuning/CD1_-_07_-_While_My_Guitar_Gently_Weeps.tun _chordtools/tuning/10CD1tuning/CD1_-_08_-_Happiness_is_a_Warm_Gun.tun _chordtools/tuning/10CD1tuning/CD1_-_09_-_Martha_My_Dear.tun _chordtools/tuning/10CD1tuning/CD1_-_10_-_I'm_So_Tired.tun _chordtools/tuning/10CD1tuning/CD1_-_11_-_Black_Bird.tun _chordtools/tuning/10CD1tuning/CD1_-_12_-_Piggies.tun _chordtools/tuning/10CD1tuning/CD1_-_13_-_Rocky_Raccoon.tun _chordtools/tuning/10CD1tuning/CD1_-_14_-_Don't_Pass_Me_By.tun _chordtools/tuning/10CD1tuning/CD1_-_15_-_Why_Don't_We_Do_It_In_The_Road.tun _chordtools/tuning/10CD1tuning/CD1_-_16_-_I_Will.tun _chordtools/tuning/10CD1tuning/CD1_-_17_-_Julia.tun _chordtools/tuning/10CD1tuning/CVS/Entries _chordtools/tuning/10CD1tuning/CVS/Repository _chordtools/tuning/10CD1tuning/CVS/Root _chordtools/tuning/10CD1tuning/CVS/Template _chordtools/tuning/10CD2tuning/CD2_-_01_-_Birthday.tun _chordtools/tuning/10CD2tuning/CD2_-_02_-_Yer_Blues.tun _chordtools/tuning/10CD2tuning/CD2_-_03_-_Mother_Nature's_Son.tun _chordtools/tuning/10CD2tuning/CD2_-_04_-_Everybody's_Got_Something_To_Hide_Except_Me_and_M.tun _chordtools/tuning/10CD2tuning/CD2_-_05_-_Sexy_Sadie.tun _chordtools/tuning/10CD2tuning/CD2_-_06_-_Helter_Skelter.tun _chordtools/tuning/10CD2tuning/CD2_-_07_-_Long_Long_Long.tun _chordtools/tuning/10CD2tuning/CD2_-_08_-_Revolution_1.tun _chordtools/tuning/10CD2tuning/CD2_-_09_-_Honey_Pie.tun _chordtools/tuning/10CD2tuning/CD2_-_10_-_Savoy_Truffle.tun _chordtools/tuning/10CD2tuning/CD2_-_11_-_Cry_Baby_Cry.tun _chordtools/tuning/10CD2tuning/CD2_-_12_-_Revolution_9.tun _chordtools/tuning/10CD2tuning/CD2_-_13_-_Good_Night.tun _chordtools/tuning/10CD2tuning/CVS/Entries _chordtools/tuning/10CD2tuning/CVS/Repository _chordtools/tuning/10CD2tuning/CVS/Root _chordtools/tuning/10CD2tuning/CVS/Template _chordtools/tuning/11tuning/01_-_Come_Together.tun _chordtools/tuning/11tuning/02_-_Something.tun _chordtools/tuning/11tuning/03_-_Maxwell's_Silver_Hammer.tun _chordtools/tuning/11tuning/04_-_Oh!_Darling.tun _chordtools/tuning/11tuning/05_-_Octopus's_Garden.tun _chordtools/tuning/11tuning/06_-_I_Want_You.tun _chordtools/tuning/11tuning/07_-_Here_Comes_The_Sun.tun _chordtools/tuning/11tuning/08_-_Because.tun _chordtools/tuning/11tuning/09_-_You_Never_Give_Me_Your_Money.tun _chordtools/tuning/11tuning/10_-_Sun_King.tun _chordtools/tuning/11tuning/11_-_Mean_Mr_Mustard.tun _chordtools/tuning/11tuning/12_-_Polythene_Pam.tun _chordtools/tuning/11tuning/13_-_She_Came_In_Through_The_Bathroom_Window.tun _chordtools/tuning/11tuning/14_-_Golden_Slumbers.tun _chordtools/tuning/11tuning/15_-_Carry_That_Weight.tun _chordtools/tuning/11tuning/16_-_The_End.tun _chordtools/tuning/11tuning/17_-_Her_Majesty.tun _chordtools/tuning/11tuning/CVS/Entries _chordtools/tuning/11tuning/CVS/Repository _chordtools/tuning/11tuning/CVS/Root _chordtools/tuning/11tuning/CVS/Template _chordtools/tuning/12tuning/01_-_Two_of_Us.tun _chordtools/tuning/12tuning/02_-_Dig_a_Pony.tun _chordtools/tuning/12tuning/03_-_Across_the_Universe.tun _chordtools/tuning/12tuning/04_-_I_Me_Mine.tun _chordtools/tuning/12tuning/05_-_Dig_It.tun _chordtools/tuning/12tuning/06_-_Let_It_Be.tun _chordtools/tuning/12tuning/07_-_Maggie_Mae.tun _chordtools/tuning/12tuning/08_-_I've_Got_A_Feeling.tun _chordtools/tuning/12tuning/09_-_One_After_909.tun _chordtools/tuning/12tuning/10_-_The_Long_and_Winding_Road.tun _chordtools/tuning/12tuning/11_-_For_You_Blue.tun _chordtools/tuning/12tuning/12_-_Get_Back.tun _chordtools/tuning/12tuning/CVS/Entries _chordtools/tuning/12tuning/CVS/Repository _chordtools/tuning/12tuning/CVS/Root _chordtools/tuning/12tuning/CVS/Template _chordtools/tuning/CVS/Entries _chordtools/tuning/CVS/Entries.Log _chordtools/tuning/CVS/Repository _chordtools/tuning/CVS/Root _chordtools/tuning/CVS/Template _chordtools/types.m _chroma/chroma_main.m _chroma/chroma_vampprecalculated.m _chroma/fftbin2frequency.m _chroma/kldiv.m _chroma/logisticlearn.m _chroma/midinote2frequency.m _chroma/newdict.m _chroma/pitch2octave.m _chroma/semitonedistance.m _chroma/sparsePrint.m _chromadata/.csv _dbn/add_chords.m _dbn/add_keys.m _dbn/dbn_ISMIR2010.m _dbn/inference.m _dbn/make_dbn.m _logfiles/03_-_Across_the_Universe.wav.log _logfiles/06_-_Let_It_Be.wav.log _logfiles/Bangles.EternalFlame.wav.log _logfiles/DuranDuran.OrdinaryWorld.wav.log _logfiles/EltonJohn.IslandGirl.wav.log _logfiles/GloriaEstefanAndMiamiSoundMachine.AnythingForYou.wav.log _logfiles/Martika.ToySoldiers.wav.log _logfiles/OtisRedding.TheDockOfTheBay.wav.log _logfiles/RollingStonesRipThisJoint.wav.log _logfiles/U2.WithOrWithoutYou.wav.log _logfiles/friends.wav.log _logfiles/show.wav.log _misc/featureextraction/.svn/all-wcprops _misc/featureextraction/.svn/entries _misc/featureextraction/.svn/prop-base/chunkspectrogram_ISMIR2010.m.svn-base _misc/featureextraction/.svn/text-base/basschroma13.m.svn-base _misc/featureextraction/.svn/text-base/beatchroma.m.svn-base _misc/featureextraction/.svn/text-base/bigframefft.m.svn-base _misc/featureextraction/.svn/text-base/chromagenerator.m.svn-base _misc/featureextraction/.svn/text-base/chromamatthias.m.svn-base _misc/featureextraction/.svn/text-base/chunkspectrogram.m.svn-base _misc/featureextraction/.svn/text-base/chunkspectrogram_ISMIR2010.m.svn-base _misc/featureextraction/.svn/text-base/hpcp2chroma.m.svn-base _misc/featureextraction/.svn/text-base/mmcq2hpcp.m.svn-base _misc/featureextraction/.svn/text-base/mychroma.m.svn-base _misc/featureextraction/.svn/text-base/mychroma.m~.svn-base _misc/featureextraction/.svn/text-base/myframefft.m.svn-base _misc/featureextraction/.svn/text-base/myframefft.m~.svn-base _misc/featureextraction/.svn/text-base/readaudiochunk.m.svn-base _misc/featureextraction/.svn/text-base/shadedplot.m.svn-base _misc/featureextraction/.svn/text-base/synchronisechroma.m.svn-base _misc/featureextraction/.svn/text-base/synchronisechroma.m~.svn-base _misc/featureextraction/basschroma13.m _misc/featureextraction/beatchroma.m _misc/featureextraction/bigframefft.m _misc/featureextraction/chromagenerator.m _misc/featureextraction/chromamatthias.m _misc/featureextraction/chunkspectrogram.m _misc/featureextraction/chunkspectrogram_ISMIR2010.m _misc/featureextraction/hpcp2chroma.m _misc/featureextraction/mmcq2hpcp.m _misc/featureextraction/mychroma.m _misc/featureextraction/mychroma.m~ _misc/featureextraction/myframefft.m _misc/featureextraction/myframefft.m~ _misc/featureextraction/readaudiochunk.m _misc/featureextraction/shadedplot.m _misc/featureextraction/synchronisechroma.m _misc/featureextraction/synchronisechroma.m~ _misc/figures/.svn/all-wcprops _misc/figures/.svn/entries _misc/figures/.svn/prop-base/uimage.m.svn-base _misc/figures/.svn/prop-base/uimagesc.m.svn-base _misc/figures/.svn/text-base/addmax.m.svn-base _misc/figures/.svn/text-base/exportfig.m.svn-base _misc/figures/.svn/text-base/imxy.m.svn-base _misc/figures/.svn/text-base/printme.m.svn-base _misc/figures/.svn/text-base/rotateticklabel.m.svn-base _misc/figures/.svn/text-base/uimage.m.svn-base _misc/figures/.svn/text-base/uimagesc.m.svn-base _misc/figures/addmax.m _misc/figures/exportfig.m _misc/figures/imxy.m _misc/figures/printme.m _misc/figures/rotateticklabel.m _misc/figures/uimage.m _misc/figures/uimagesc.m _misc/general/.svn/all-wcprops _misc/general/.svn/entries _misc/general/.svn/prop-base/dpcore.mexmac.svn-base _misc/general/.svn/prop-base/dpcore.mexmaci.svn-base _misc/general/.svn/text-base/dpcore.c.svn-base _misc/general/.svn/text-base/dpcore.mexmac.svn-base _misc/general/.svn/text-base/dpcore.mexmaci.svn-base _misc/general/.svn/text-base/dpfast.m.svn-base _misc/general/.svn/text-base/filecollection.m.svn-base _misc/general/.svn/text-base/qnorm.m.svn-base _misc/general/.svn/text-base/qnormalise.m.svn-base _misc/general/dpcore.c _misc/general/dpcore.mexmac _misc/general/dpcore.mexmaci _misc/general/dpfast.m _misc/general/filecollection.m _misc/general/qnorm.m _misc/general/qnormalise.m _misc/kde.m _misc/probability/.svn/all-wcprops _misc/probability/.svn/entries _misc/probability/.svn/prop-base/kde.m.svn-base _misc/probability/.svn/text-base/JSDiv.m.svn-base _misc/probability/.svn/text-base/KLDiv.m.svn-base _misc/probability/.svn/text-base/kde.m.svn-base _misc/probability/JSDiv.m _misc/probability/KLDiv.m _misc/probability/kde.m _misc/tools/.svn/all-wcprops _misc/tools/.svn/entries _misc/tools/.svn/prop-base/localmax_logical.m.svn-base _misc/tools/.svn/text-base/getFileDependencies.m.svn-base _misc/tools/.svn/text-base/localmax_logical.m.svn-base _misc/tools/.svn/text-base/localmaxmin.m.svn-base _misc/tools/getFileDependencies.m _misc/tools/localmax_logical.m _misc/tools/localmaxmin.m _parameters/param_mirex.m _parameters/param_segmentation.m _parameters/param_skeleton.m _segmentation/integratesmallparts.m _segmentation/makeparts.m _segmentation/maxfilt1.m _segmentation/mergenulls.m _segmentation/nullpart.m _segmentation/parts2csv.m _segmentation/parts2mirex.m _segmentation/segmentation_auto.m _segmentation/segmentation_main.m _segmentation/segmentation_parts.m _song/song_beat.m _song/song_chroma.m _song/song_segchroma.m _song/song_segment.m _song/song_skeleton.m _song/song_syncchroma.m _song/song_syncchroma_special.m _writetools/chordroot_spelling.m _writetools/keynroot2notetext.m _writetools/spellnote.m _writetools/write_song.m _writetools/write_song2.m
diffstat 2053 files changed, 90024 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/@assocarray/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+/assocarray.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/subsref.m/1.1.1.1/Wed Aug  4 19:36:30 2004//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/@assocarray/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/@assocarray
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/@assocarray/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/@assocarray/assocarray.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function A = assocarray(keys, vals)
+% ASSOCARRAY Make an associative array
+% function A = assocarray(keys, vals)
+%
+% keys{i} is the i'th string, vals{i} is the i'th value.
+% After construction, A('foo') will return the value associated with foo.
+
+A.keys = keys;
+A.vals = vals;
+A = class(A, 'assocarray');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/@assocarray/subsref.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function val = subsref(A, S)
+% SUBSREF Subscript reference for an associative array
+% A('foo') will return the value associated with foo.
+% If there are multiple identicaly keys, the first match is returned.
+% Currently the search is sequential.
+
+i = 1;
+while i <= length(A.keys)
+  if strcmp(S.subs{1}, A.keys{i})
+    val = A.vals{i};
+    return;
+  end
+  i = i + 1;
+end
+error(['can''t find ' S.subs{1}])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@boolean_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/boolean_CPD.m/1.1.1.1/Wed May 29 15:59:52 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@boolean_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@boolean_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@boolean_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@boolean_CPD/boolean_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,179 @@
+function CPD = boolean_CPD(bnet, self, ftype, fname, pfail)
+% BOOLEAN_CPD Make a tabular CPD representing a (noisy) boolean function
+%
+% CPD = boolean_cpd(bnet, self, 'inline', f) uses the inline function f
+% to specify the CPT.
+% e.g., suppose X4 = X2 AND (NOT X3). Then we can write
+%    bnet.CPD{4} = boolean_CPD(bnet, 4, 'inline', inline('(x(1) & ~x(2)'));  
+% Note that x(1) refers pvals(1) = X2, and x(2) refers to pvals(2)=X3.
+%
+% CPD = boolean_cpd(bnet, self, 'named', f) assumes f is a function name.
+% f can be built-in to matlab, or a file.
+% e.g., If X4 = X2 AND X3, we can write
+%    bnet.CPD{4} = boolean_CPD(bnet, 4, 'named', 'and');
+% e.g., If X4 = X2 OR X3, we can write
+%    bnet.CPD{4} = boolean_CPD(bnet, 4, 'named', 'any');
+%
+% CPD = boolean_cpd(bnet, self, 'rnd') makes a random non-redundant bool fn.
+%
+% CPD = boolean_CPD(bnet, self, 'inline'/'named', f, pfail)
+% will put probability mass 1-pfail on f(parents), and put pfail on the other value.
+% This is useful for simulating noisy boolean functions.
+% If pfail is omitted, it is set to 0.
+% (Note that adding noise to a random (non-redundant) boolean function just creates a different
+% (potentially redundant) random boolean function.)
+%
+% Note: This cannot be used to simulate a noisy-OR gate.
+% Example: suppose C has parents A and B, and the
+% link of A->C fails with prob pA and the link B->C fails with pB.
+% Then the noisy-OR gate defines the following distribution
+%
+%  A  B  P(C=0)
+%  0  0  1.0
+%  1  0  pA
+%  0  1  pB
+%  1  1  pA * PB
+% 
+% By contrast, boolean_CPD(bnet, C, 'any', p) would define
+%
+%  A  B  P(C=0) 
+%  0  0  1-p    
+%  1  0  p      
+%  0  1  p
+%  1  1  p
+
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = tabular_CPD(bnet, self);
+  return;
+elseif isa(bnet, 'boolean_CPD')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+
+if nargin < 5, pfail = 0; end
+
+ps = parents(bnet.dag, self);
+ns = bnet.node_sizes;
+psizes = ns(ps);
+self_size = ns(self);
+
+psucc = 1-pfail;
+
+k = length(ps);
+switch ftype
+ case 'inline', f = eval_bool_fn(fname, k);
+ case 'named',  f = eval_bool_fn(fname, k);
+ case 'rnd',    f = mk_rnd_bool_fn(k);
+ otherwise,     error(['unknown function type ' ftype]);
+end
+
+CPT = zeros(prod(psizes), self_size);
+ndx = find(f==0);
+CPT(ndx, 1) = psucc;
+CPT(ndx, 2) = pfail;
+ndx = find(f==1);
+CPT(ndx, 2) = psucc;
+CPT(ndx, 1) = pfail;
+if k > 0
+  CPT = reshape(CPT, [psizes self_size]);  
+end
+
+clamp = 1;
+CPD = tabular_CPD(bnet, self, CPT, [], clamp);
+
+
+
+%%%%%%%%%%%%
+
+function f = eval_bool_fn(fname, n)
+% EVAL_BOOL_FN Evaluate a boolean function on all bit vectors of length n
+% f = eval_bool_fn(fname, n)
+%
+% e.g. f = eval_bool_fn(inline('x(1) & x(3)'), 3)
+% returns   0     0     0     0     0     1     0     1
+
+ns = 2*ones(1, n);
+f = zeros(1, 2^n);
+bits = ind2subv(ns, 1:2^n);
+for i=1:2^n
+  f(i) = feval(fname, bits(i,:)-1);
+end
+
+%%%%%%%%%%%%%%%
+
+function f = mk_rnd_bool_fn(n)
+% MK_RND_BOOL_FN Make a random bit vector of length n that encodes a non-redundant boolean function
+% f = mk_rnd_bool_fn(n)
+
+red = 1;
+while red
+  f = sample_discrete([0.5 0.5], 2^n, 1)-1;
+  red = redundant_bool_fn(f);
+end
+
+%%%%%%%%
+
+
+function red = redundant_bool_fn(f)
+% REDUNDANT_BOOL_FN Does a boolean function depend on all its input values?
+% r = redundant_bool_fn(f)
+%
+% f is a vector of length 2^n, representing the output for each bit vector.
+% An input is redundant if there is no assignment to the other bits
+% which changes the output e.g., input 1 is redundant if u(2:n) s.t.,
+% f([0 u(2:n)]) <> f([1 u(2:n)]). 
+% A function is redundant it it has any redundant inputs.
+
+n = log2(length(f));
+ns = 2*ones(1,n);
+red = 0;
+for i=1:n
+  ens = ns;
+  ens(i) = 1;
+  U = ind2subv(ens, 1:2^(n-1));
+  U(:,i) = 1;
+  f1 = f(subv2ind(ns, U));
+  U(:,i) = 2;
+  f2 = f(subv2ind(ns, U));
+  if isequal(f1, f2)
+    red = 1;
+    return;
+  end
+end
+
+
+%%%%%%%%%%
+
+function [b, iter] = rnd_truth_table(N)
+% RND_TRUTH_TABLE Construct the output of a random truth table s.t. each input is non-redundant
+% b = rnd_truth_table(N)
+%
+% N is the number of inputs. 
+% b is a random bit string of length N, representing the output of the truth table.
+% Non-redundant means that, for each input position k,
+% there are at least two bit patterns, u and v, that differ only in the k'th position,
+% s.t., f(u) ~= f(v), where f is the function represented by b.
+% We use rejection sampling to ensure non-redundancy.
+%
+% Example: b = [0 0 0 1  0 0 0 1] is indep of 3rd input (AND of inputs 1 and 2)
+
+bits = ind2subv(2*ones(1,N), 1:2^N)-1;
+redundant = 1;
+iter = 0;
+while redundant & (iter < 4)
+  iter = iter + 1;
+  b = sample_discrete([0.5 0.5], 1, 2^N)-1;
+  redundant = 0;
+  for i=1:N
+    on = find(bits(:,i)==1);
+    off = find(bits(:,i)==0);
+    if isequal(b(on), b(off))
+      redundant = 1;
+      break;
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@deterministic_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/deterministic_CPD.m/1.1.1.1/Mon Oct  7 13:26:36 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@deterministic_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@deterministic_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@deterministic_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@deterministic_CPD/deterministic_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function CPD = deterministic_CPD(bnet, self, fname, pfail)
+% DETERMINISTIC_CPD Make a tabular CPD representing a (noisy) deterministic function
+%
+% CPD = deterministic_CPD(bnet, self, fname)
+% This calls feval(fname, pvals) for each possible vector of parent values.
+% e.g., suppose there are 2 ternary parents, then pvals = 
+%  [1 1], [2 1], [3 1],   [1 2], [2 2], [3 2],   [1 3], [2 3], [3 3]
+% If v = feval(fname, pvals(i)), then
+%  CPD(x | parents=pvals(i)) = 1 if x==v, and = 0 if x<>v
+% e.g., suppose X4 = X2 AND (NOT X3). Then
+%    bnet.CPD{4} = deterministic_CPD(bnet, 4, inline('((x(1)-1) & ~(x(2)-1)) + 1'));  
+% Note that x(1) refers pvals(1) = X2, and x(2) refers to pvals(2)=X3
+% See also boolean_CPD.
+%
+% CPD = deterministic_CPD(bnet, self, fname, pfail)
+% will put probability mass 1-pfail on f(parents), and distribute pfail over the other values.
+% This is useful for simulating noisy deterministic functions.
+% If pfail is omitted, it is set to 0.
+%
+
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = tabular_CPD(bnet, self);
+  return;
+elseif isa(bnet, 'deterministic_CPD')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+
+if nargin < 4, pfail = 0; end
+
+ps = parents(bnet.dag, self);
+ns = bnet.node_sizes;
+psizes = ns(ps);
+self_size = ns(self);
+
+psucc = 1-pfail;
+
+CPT = zeros(prod(psizes), self_size);
+pvals = zeros(1, length(ps));
+for i=1:prod(psizes)
+  pvals = ind2subv(psizes, i);
+  x = feval(fname, pvals);
+  %fprintf('%d ', [pvals x]); fprintf('\n');
+  if psucc == 1
+    CPT(i, x) = 1;
+  else
+    CPT(i, x) = psucc;
+    rest = mysetdiff(1:self_size, x);
+    CPT(i, rest) = pfail/length(rest);
+  end
+end
+CPT = reshape(CPT, [psizes self_size]);  
+
+CPD = tabular_CPD(bnet, self, 'CPT',CPT, 'clamped',1);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/CPD_to_lambda_msg.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function lam_msg = CPD_to_lambda_msg(CPD, msg_type, n, ps, msg, p, evidence)
+% CPD_TO_LAMBDA_MSG Compute lambda message (discrete)
+% lam_msg = compute_lambda_msg(CPD, msg_type, n, ps, msg, p, evidence)
+% Pearl p183 eq 4.52
+
+switch msg_type
+  case 'd',
+   T = prod_CPT_and_pi_msgs(CPD, n, ps, msg, p);
+   mysize = length(msg{n}.lambda);
+   lambda = dpot(n, mysize, msg{n}.lambda);
+   T = multiply_by_pot(T, lambda);
+   lam_msg = pot_to_marginal(marginalize_pot(T, p));
+   lam_msg = lam_msg.T;           
+ case 'g',
+  error('discrete_CPD can''t create Gaussian msgs')
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/CPD_to_pi.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function pi = CPD_to_pi(CPD, msg_type, n, ps, msg, evidence)
+% COMPUTE_PI Compute pi vector (discrete) 
+% pi = compute_pi(CPD, msg_type, n, ps, msg, evidence)
+% Pearl p183 eq 4.51
+
+switch msg_type
+  case 'd',
+   T = prod_CPT_and_pi_msgs(CPD, n, ps, msg);
+   pi = pot_to_marginal(marginalize_pot(T, n));
+   pi = pi.T(:);                   
+ case 'g', 
+  error('can only convert discrete CPD to Gaussian pi if observed')
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/CPD_to_scgpot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function pot = CPD_to_scgpot(CPD, domain, ns, cnodes, evidence)
+% CPD_TO_SCGPOT Convert a CPD to a CG potential, incorporating any evidence (discrete)
+% pot = CPD_to_scgpot(CPD, domain, ns, cnodes, evidence)
+%
+% domain is the domain of CPD.
+% node_sizes(i) is the size of node i.
+% cnodes
+% evidence{i} is the evidence on the i'th node.
+
+%odom = domain(~isemptycell(evidence(domain)));
+
+%vals = cat(1, evidence{odom});
+%map = find_equiv_posns(odom, domain);
+%index = mk_multi_index(length(domain), map, vals);
+CPT = CPD_to_CPT(CPD);
+%CPT = CPT(index{:});
+CPT = CPT(:);
+%ns(odom) = 1;
+potarray = cell(1, length(CPT));
+for i=1:length(CPT)
+  %p = CPT(i);
+  potarray{i} = scgcpot(0, 0, CPT(i));
+  %scpot{i} = scpot(0, 0);
+end
+pot = scgpot(domain, [], [], ns, potarray);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+/CPD_to_lambda_msg.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/CPD_to_pi.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/CPD_to_scgpot.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/README/1.1.1.1/Wed May 29 15:59:52 2002//
+/convert_CPD_to_table_hidden_ps.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/convert_obs_CPD_to_table.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/convert_to_pot.m/1.1.1.1/Fri Feb 20 22:00:38 2004//
+/convert_to_sparse_table.c/1.1.1.1/Wed May 29 15:59:52 2002//
+/convert_to_table.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/discrete_CPD.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/dom_sizes.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/log_prob_node.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/prob_node.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/sample_node.m/1.1.1.1/Wed May 29 15:59:52 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+A D/Old////
+A D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@discrete_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+/convert_to_pot.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/convert_to_table.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/prob_CPD.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/prob_node.m/1.1.1.1/Wed May 29 15:59:52 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@discrete_CPD/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/Old/convert_to_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,44 @@
+function pot = convert_to_pot(CPD, pot_type, domain, evidence)
+% CONVERT_TO_POT Convert a tabular CPD to one or more potentials
+% pots = convert_to_pot(CPD, pot_type, domain, evidence)
+%
+% pots{i} = CPD evaluated using evidence(domain(:,i))
+% If 'domains' is a single row vector, pots will be an object, not a cell array.
+
+ncases = size(domain,2);
+assert(ncases==1); % not yet vectorized
+
+sz = dom_sizes(CPD);
+ns = zeros(1, max(domain));
+ns(domain) = sz;
+
+local_ev = evidence(domain);
+obs_bitv = ~isemptycell(local_ev);
+odom = domain(obs_bitv);
+T = convert_to_table(CPD, domain, local_ev, obs_bitv);
+
+switch pot_type
+ case 'u',
+  pot = upot(domain, sz, T, 0*myones(sz));  
+ case 'd',
+  ns(odom) = 1;
+  pot = dpot(domain, ns(domain), T);          
+ case {'c','g'},
+  % Since we want the output to be a Gaussian, the whole family must be observed.
+  % In other words, the potential is really just a constant.
+  p = T;
+  %p = prob_node(CPD, evidence(domain(end)), evidence(domain(1:end-1)));
+  ns(domain) = 0;
+  pot = cpot(domain, ns(domain), log(p));       
+ case 'cg',
+  T = T(:);
+  ns(odom) = 1;
+  can = cell(1, length(T));
+  for i=1:length(T)
+    can{i} = cpot([], [], log(T(i)));
+  end
+  pot = cgpot(domain, [], ns, can);   
+ otherwise,
+  error(['unrecognized pot type ' pot_type])
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/Old/convert_to_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+function T = convert_to_table(CPD, domain, local_ev, obs_bitv)
+% CONVERT_TO_TABLE Convert a discrete CPD to a table
+% function T = convert_to_table(CPD, domain, local_ev, obs_bitv)
+%
+% We convert the CPD to a CPT, and then lookup the evidence on the discrete parents.
+% The resulting table can easily be converted to a potential.
+
+
+CPT = CPD_to_CPT(CPD);
+obs_child_only = ~any(obs_bitv(1:end-1)) & obs_bitv(end);
+
+if obs_child_only
+  sz = size(CPT);
+  CPT = reshape(CPT, prod(sz(1:end-1)), sz(end));
+  o = local_ev{end};
+  T = CPT(:, o);
+else
+  odom = domain(obs_bitv);  
+  vals = cat(1, local_ev{find(obs_bitv)}); % undo cell array
+  map = find_equiv_posns(odom, domain);
+  index = mk_multi_index(length(domain), map, vals);
+  T = CPT(index{:});
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/Old/prob_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function p = prob_CPD(CPD, domain, ns, cnodes, evidence)
+% PROB_CPD Compute prob of a node given evidence on the parents (discrete)
+% p = prob_CPD(CPD, domain, ns, cnodes, evidence)
+%
+% domain is the domain of CPD.
+% node_sizes(i) is the size of node i.
+% cnodes = all the cts nodes
+% evidence{i} is the evidence on the i'th node.
+
+ps = domain(1:end-1);
+self = domain(end);
+CPT = CPD_to_CPT(CPD);
+
+if isempty(ps)
+  T = CPT;
+else
+  assert(~any(isemptycell(evidence(ps))));
+  pvals = cat(1, evidence{ps});
+  i = subv2ind(ns(ps), pvals(:)');
+  T = reshape(CPT, [prod(ns(ps)) ns(self)]);
+  T = T(i,:);
+end
+p = T(evidence{self});
+
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/Old/prob_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,51 @@
+function [P, p] = prob_node(CPD, self_ev, pev)
+% PROB_NODE Compute prod_m P(x(i,m)| x(pi_i,m), theta_i) for node i (discrete)
+% [P, p] = prob_node(CPD, self_ev, pev)
+%
+% self_ev(m) is the evidence on this node in case m.
+% pev(i,m) is the evidence on the i'th parent in case m (if there are any parents).
+% (These may also be cell arrays.)
+%
+% p(m) = P(x(i,m)| x(pi_i,m), theta_i) 
+% P = prod p(m)
+
+if iscell(self_ev), usecell = 1; else usecell = 0; end
+
+ncases = length(self_ev);
+sz = dom_sizes(CPD);
+
+nparents = length(sz)-1;
+if nparents == 0
+  assert(isempty(pev));
+else
+  assert(isequal(size(pev), [nparents ncases]));
+end
+
+n = length(sz);
+dom = 1:n;
+p = zeros(1, ncases);
+if nparents == 0
+  for m=1:ncases
+    if usecell
+      evidence = {self_ev{m}};
+    else
+      evidence = num2cell(self_ev(m));
+    end
+    T = convert_to_table(CPD, dom, evidence);
+    p(m) = T;
+  end
+else
+  for m=1:ncases
+    if usecell
+      evidence = cell(1,n);
+      evidence(1:n-1) = pev(:,m);
+      evidence(n) = self_ev(m);
+    else
+      evidence = num2cell([pev(:,m)', self_ev(m)]);
+    end
+    T = convert_to_table(CPD, dom, evidence);
+    p(m) = T;
+  end
+end
+P = prod(p);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/README	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+Any CPD on a discrete child with discrete parents
+can be represented as a table (although this might be quite big).
+discrete_CPD uses this tabular representation to implement various
+functions. Subtypes are free to implement more efficient versions.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/convert_CPD_to_table_hidden_ps.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,20 @@
+function T = convert_CPD_to_table_hidden_ps(CPD, child_obs)
+% CONVERT_CPD_TO_TABLE_HIDDEN_PS Convert a discrete CPD to a table
+% T = convert_CPD_to_table_hidden_ps(CPD, child_obs)
+%
+% This is like convert_to_table, except that we are guaranteed that
+% none of the parents have evidence on them.
+% child_obs may be an integer (1,2,...) or [].
+
+CPT = CPD_to_CPT(CPD);
+if isempty(child_obs)
+  T = CPT(:);
+else
+  sz = dom_sizes(CPD);
+  if length(sz)==1 % no parents
+    T = CPT(child_obs);
+  else
+    CPT = reshape(CPT, prod(sz(1:end-1)), sz(end));
+    T = CPT(:, child_obs);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/convert_obs_CPD_to_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function T = convert_to_table(CPD, domain, evidence)
+% CONVERT_TO_TABLE Convert a discrete CPD to a table
+% T = convert_to_table(CPD, domain, evidence)
+%
+% We convert the CPD to a CPT, and then lookup the evidence on the discrete parents.
+% The resulting table can easily be converted to a potential.
+
+CPT = CPD_to_CPT(CPD);
+odom = domain(~isemptycell(evidence(domain)));
+vals = cat(1, evidence{odom});
+map = find_equiv_posns(odom, domain);
+index = mk_multi_index(length(domain), map, vals);
+T = CPT(index{:});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/convert_to_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,62 @@
+function pot = convert_to_pot(CPD, pot_type, domain, evidence)
+% CONVERT_TO_POT Convert a discrete CPD to a potential
+% pot = convert_to_pot(CPD, pot_type, domain, evidence)
+%
+% pots = CPD evaluated using evidence(domain)
+
+ncases = size(domain,2);
+assert(ncases==1); % not yet vectorized
+
+sz = dom_sizes(CPD);
+ns = zeros(1, max(domain));
+ns(domain) = sz;
+
+CPT1 = CPD_to_CPT(CPD);
+spar = issparse(CPT1);
+odom = domain(~isemptycell(evidence(domain)));
+if spar
+   T = convert_to_sparse_table(CPD, domain, evidence);
+else 
+   T = convert_to_table(CPD, domain, evidence);
+end
+
+switch pot_type
+ case 'u',
+  pot = upot(domain, sz, T, 0*myones(sz));  
+ case 'd',
+  ns(odom) = 1;
+  pot = dpot(domain, ns(domain), T);          
+ case {'c','g'},
+  % Since we want the output to be a Gaussian, the whole family must be observed.
+  % In other words, the potential is really just a constant.
+  p = T;
+  %p = prob_node(CPD, evidence(domain(end)), evidence(domain(1:end-1)));
+  ns(domain) = 0;
+  pot = cpot(domain, ns(domain), log(p));       
+
+ case 'cg',
+  T = T(:);
+  ns(odom) = 1;
+  can = cell(1, length(T));
+  for i=1:length(T)
+    if T(i) == 0 
+      can{i} = cpot([], [], -Inf); % bug fix by Bob Welch 20/2/04
+    else
+      can{i} = cpot([], [], log(T(i)));
+    end;
+  end
+  pot = cgpot(domain, [], ns, can); 
+  
+ case 'scg'
+  T = T(:);
+  ns(odom) = 1;
+  pot_array = cell(1, length(T));
+  for i=1:length(T)
+    pot_array{i} = scgcpot([], [], T(i));
+  end
+  pot = scgpot(domain, [], [], ns, pot_array);   
+
+ otherwise,
+  error(['unrecognized pot type ' pot_type])
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/convert_to_sparse_table.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,154 @@
+/* convert_to_sparse_table.c  convert a sparse discrete CPD with evidence into sparse table */
+/* convert_to_pot.m located in ../CPDs/discrete_CPD call it */
+/* 3 input */
+/* CPD      prhs[0] with 1D sparse CPT */
+/* domain   prhs[1]                    */
+/* evidence prhs[2]                    */
+/* 1 output */
+/* T        plhs[0] sparse table       */
+
+#include <math.h>
+#include "mex.h"
+
+void ind_subv(int index, const int *cumprod, const int n, int *bsubv){
+	int i;
+
+	for (i = n-1; i >= 0; i--) {
+		bsubv[i] = ((int)floor(index / cumprod[i]));
+		index = index % cumprod[i];
+	}
+}
+
+int subv_ind(const int n, const int *cumprod, const int *subv){
+	int i, index=0;
+
+	for(i=0; i<n; i++){
+		index += subv[i] * cumprod[i];
+	}
+	return index;
+}
+
+void reset_nzmax(mxArray *spArray, const int old_nzmax, const int new_nzmax){
+	double *ptr;
+	void   *newptr;
+	int    *ir, *jc;
+	int    nbytes;
+
+	if(new_nzmax == old_nzmax) return;
+	nbytes = new_nzmax * sizeof(*ptr);
+	ptr = mxGetPr(spArray);
+	newptr = mxRealloc(ptr, nbytes);
+	mxSetPr(spArray, newptr);
+	nbytes = new_nzmax * sizeof(*ir);
+	ir = mxGetIr(spArray);
+	newptr = mxRealloc(ir, nbytes);
+	mxSetIr(spArray, newptr);
+	jc = mxGetJc(spArray);
+	jc[0] = 0;
+	jc[1] = new_nzmax;
+	mxSetNzmax(spArray, new_nzmax);
+}
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, j, NS, NZB, count, bdim, match, domain, bindex, sindex, nzCounts=0;
+	int     *observed, *bsubv, *ssubv, *bir, *sir, *bjc, *sjc, *mask, *ssize, *bcumprod, *scumprod;
+	double  *pDomain, *pSize, *bpr, *spr;
+	mxArray *pTemp;
+
+	pTemp = mxGetField(prhs[0], 0, "CPT");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+	pTemp = mxGetField(prhs[0], 0, "sizes");
+	pSize = mxGetPr(pTemp);
+
+	pDomain = mxGetPr(prhs[1]);
+	bdim = mxGetNumberOfElements(prhs[1]);
+
+	mask = malloc(bdim * sizeof(int));
+	ssize = malloc(bdim * sizeof(int));
+	observed = malloc(bdim * sizeof(int));
+
+	for(i=0; i<bdim; i++){
+		ssize[i] = (int)pSize[i];
+	}
+
+	count = 0;
+	for(i=0; i<bdim; i++){
+		domain = (int)pDomain[i] - 1;
+		pTemp = mxGetCell(prhs[2], domain);
+		if(pTemp){
+			mask[count] = i;
+			ssize[i] = 1;
+			observed[count] = (int)mxGetScalar(pTemp) - 1;
+			count++;
+		}
+	}
+
+	if(count == 0){
+		pTemp = mxGetField(prhs[0], 0, "CPT");
+		plhs[0] = mxDuplicateArray(pTemp);
+		free(mask);
+		free(ssize);
+		free(observed);
+		return;
+	}
+
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(count * sizeof(int));
+	bcumprod = malloc(bdim * sizeof(int));
+	scumprod = malloc(bdim * sizeof(int));
+
+	NS = 1;
+	for(i=0; i<bdim; i++){
+		NS *= ssize[i];
+	}
+
+	plhs[0] = mxCreateSparse(NS, 1, NS, mxREAL);
+	spr = mxGetPr(plhs[0]);
+	sir = mxGetIr(plhs[0]);
+	sjc = mxGetJc(plhs[0]);
+	sjc[0] = 0;
+	sjc[1] = NS;
+
+	bcumprod[0] = 1;
+	scumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bcumprod[i+1] = bcumprod[i] * (int)pSize[i];
+		scumprod[i+1] = scumprod[i] * ssize[i];
+	}
+
+	nzCounts = 0;
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bcumprod, bdim, bsubv);
+		for(j=0; j<count; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		match = 1;
+		for(j=0; j<count; j++){
+			if((ssubv[j]) != observed[j]){
+				match = 0;
+				break;
+			}
+		}
+		if(match){
+			spr[nzCounts] = bpr[i];
+			sindex = subv_ind(bdim, scumprod, bsubv);
+			sir[nzCounts] = sindex;
+			nzCounts++;
+		}
+	}
+
+	reset_nzmax(plhs[0], NS, nzCounts);
+	free(mask);
+	free(ssize);
+	free(observed);
+	free(bsubv);
+	free(ssubv);
+	free(bcumprod);
+	free(scumprod);
+}
+
Binary file _FullBNT/BNT/CPDs/@discrete_CPD/convert_to_sparse_table.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/convert_to_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function T = convert_to_table(CPD, domain, evidence)
+% CONVERT_TO_TABLE Convert a discrete CPD to a table
+% T = convert_to_table(CPD, domain, evidence)
+%
+% We convert the CPD to a CPT, and then lookup the evidence on the discrete parents.
+% The resulting table can easily be converted to a potential.
+
+domain = domain(:);
+CPT = CPD_to_CPT(CPD);
+odom = domain(~isemptycell(evidence(domain)));
+vals = cat(1, evidence{odom});
+map = find_equiv_posns(odom, domain);
+index = mk_multi_index(length(domain), map, vals);
+T = CPT(index{:});
+T = T(:);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/discrete_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function CPD = discrete_CPD(clamped, dom_sizes)
+% DISCRETE_CPD Virtual constructor for generic discrete CPD
+% CPD = discrete_CPD(clamped, dom_sizes)
+
+CPD.dom_sizes = dom_sizes;
+CPD = class(CPD, 'discrete_CPD', generic_CPD(clamped));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/dom_sizes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function sz = dom_sizes(CPD)
+% DOM_SIZES Return the size of each node in the domain
+% sz = dom_sizes(CPD)
+
+sz = CPD.dom_sizes;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/log_prob_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function L = log_prob_node(CPD, self_ev, pev)
+% LOG_PROB_NODE Compute sum_m log P(x(i,m)| x(pi_i,m), theta_i) for node i (discrete)
+% L = log_prob_node(CPD, self_ev, pev)
+%
+% self_ev(m) is the evidence on this node in case m.
+% pev(i,m) is the evidence on the i'th parent in case m (if there are any parents).
+% (These may also be cell arrays.)
+
+[P, p] = prob_node(CPD, self_ev, pev); % P may underflow, so we use p
+tiny = exp(-700);
+p = p + (p==0)*tiny; % replace 0s by tiny
+L = sum(log(p));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/prod_CPT_and_pi_msgs.m/1.1.1.1/Wed May 29 15:59:52 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@discrete_CPD/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/private/prod_CPT_and_pi_msgs.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function T = prod_CPT_and_pi_msgs(CPD, n, ps, msgs, except)
+% PROD_CPT_AND_PI_MSGS Multiply the CPD and all the pi messages from parents, perhaps excepting one
+% T = prod_CPY_and_pi_msgs(CPD, n, ps, msgs, except)
+
+if nargin < 5, except = -1; end
+
+dom = [ps n];
+%ns = sparse(1, max(dom));
+ns = zeros(1, max(dom));
+CPT = CPD_to_CPT(CPD);
+ns(dom) = mysize(CPT);
+T = dpot(dom, ns(dom), CPT);
+for i=1:length(ps)
+  p = ps(i);
+  if p ~= except
+    T = multiply_by_pot(T, dpot(p, ns(p), msgs{n}.pi_from_parent{i}));
+  end
+end         
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/prob_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,81 @@
+function [P, p] = prob_node(CPD, self_ev, pev)
+% PROB_NODE Compute prod_m P(x(i,m)| x(pi_i,m), theta_i) for node i (discrete)
+% [P, p] = prob_node(CPD, self_ev, pev)
+%
+% self_ev(m) is the evidence on this node in case m.
+% pev(i,m) is the evidence on the i'th parent in case m (if there are any parents).
+% (These may also be cell arrays.)
+%
+% p(m) = P(x(i,m)| x(pi_i,m), theta_i) 
+% P = prod p(m)
+
+if iscell(self_ev), usecell = 1; else usecell = 0; end
+
+ncases = length(self_ev);
+sz = dom_sizes(CPD);
+
+nparents = length(sz)-1;
+if nparents == 0
+  assert(isempty(pev));
+else
+  assert(isequal(size(pev), [nparents ncases]));
+end
+
+n = length(sz);
+dom = 1:n;
+p = zeros(1, ncases);
+if isa(CPD, 'tabular_CPD')
+  % speed up by looking up CPT using index Zhang Yimin  2001-12-31
+  if usecell
+    if nparents == 0
+      data = [cell2num(self_ev)]; 
+    else
+      data = [cell2num(pev); cell2num(self_ev)]; 
+    end
+  else
+    if nparents == 0
+      data = [self_ev];
+    else
+      data = [pev; self_ev];
+    end
+  end
+  
+  indices = subv2ind(sz, data'); % each row of data' is a case 
+  
+  CPT=CPD_to_CPT(CPD);
+  p = CPT(indices);
+  
+  %get the prob list
+  %cpt_size = prod(sz);
+  %prob_list=reshape(CPT, cpt_size, 1);
+  %for m=1:ncases  %here we assume we get evidence for node and all its parents
+  %  idx=indices(m);
+  %  p(m)=prob_list(idx); 
+  %end
+  
+else % eg. softmax
+  
+  for m=1:ncases
+    if usecell
+      if nparents == 0
+	evidence = {self_ev{m}};
+      else
+	evidence = cell(1,n);
+	evidence(1:n-1) = pev(:,m);
+	evidence(n) = self_ev(m);
+      end
+    else
+      if nparents == 0
+	evidence = num2cell(self_ev(m));
+      else
+	evidence = num2cell([pev(:,m)', self_ev(m)]);
+      end
+    end
+    T = convert_to_table(CPD, dom, evidence);
+    p(m) = T;
+  end
+end
+  
+P = prod(p);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@discrete_CPD/sample_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,34 @@
+function y = sample_node(CPD, pvals)
+% SAMPLE_NODE Draw a random sample from P(Xi | x(pi_i), theta_i)  (discrete)
+% y = sample_node(CPD, parent_evidence)
+%
+% parent_evidence{i} is the value of the i'th parent
+
+if 0
+n = length(pvals)+1;
+dom = 1:n;
+evidence = cell(1,n);
+evidence(1:n-1) = pvals;
+T = convert_to_table(CPD, dom, evidence);
+y = sample_discrete(T);
+end
+
+
+CPT = CPD_to_CPT(CPD);
+sz = mysize(CPT);
+nparents = length(sz)-1;
+switch nparents
+ case 0, T = CPT;
+ case 1, T = CPT(pvals{1}, :);
+ case 2, T = CPT(pvals{1}, pvals{2}, :);
+ case 3, T = CPT(pvals{1}, pvals{2}, pvals{3}, :);
+ case 4, T = CPT(pvals{1}, pvals{2}, pvals{3}, pvals{4}, :);
+ otherwise,
+  pvals = cat(1, pvals{:});
+  psz = sz(1:end-1);
+  ssz = sz(end);
+  i = subv2ind(psz, pvals(:)');
+  T = reshape(CPT, [prod(psz) ssz]);
+  T = T(i,:);
+end
+y = sample_discrete(T);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/CPD_to_lambda_msg.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function lam_msg = CPD_to_lambda_msg(CPD, msg_type, n, ps, msg, p, evidence)
+% CPD_TO_LAMBDA_MSG Compute lambda message (gaussian)
+% lam_msg = compute_lambda_msg(CPD, msg_type, n, ps, msg, p, evidence)
+% Pearl p183 eq 4.52
+
+switch msg_type
+ case 'd',
+  error('gaussian_CPD can''t create discrete msgs')
+ case 'g',
+  cps = ps(CPD.cps);
+  cpsizes = CPD.sizes(CPD.cps);
+  self_size = CPD.sizes(end);
+  i = find_equiv_posns(p, cps); % p is n's i'th cts parent
+  psz = cpsizes(i);
+  if all(msg{n}.lambda.precision == 0) % no info to send on
+    lam_msg.precision = zeros(psz, psz);
+    lam_msg.info_state = zeros(psz, 1);
+    return;
+  end
+  [m, Q, W] = gaussian_CPD_params_given_dps(CPD, [ps n], evidence);
+  Bmu = m;
+  BSigma = Q;
+  for k=1:length(cps) % only get pi msgs from cts parents
+    pk = cps(k);
+    if pk ~= p
+      %bk = block(k, cpsizes);
+      bk = CPD.cps_block_ndx{k};
+      Bk = W(:, bk);
+      m = msg{n}.pi_from_parent{k}; 
+      BSigma = BSigma + Bk * m.Sigma * Bk';
+      Bmu = Bmu + Bk * m.mu;
+    end
+  end
+  % BSigma = Q + sum_{k \neq i} B_k Sigma_k B_k'
+  %bi = block(i, cpsizes);
+  bi = CPD.cps_block_ndx{i};
+  Bi = W(:,bi);
+  P = msg{n}.lambda.precision;
+  if (rcond(P) > 1e-3) | isinf(P)
+    if isinf(P) % Y is observed
+      Sigma_lambda = zeros(self_size, self_size); % infinite precision => 0 variance
+      mu_lambda = msg{n}.lambda.mu; % observed_value;
+    else
+      Sigma_lambda = inv(P);
+      mu_lambda = Sigma_lambda * msg{n}.lambda.info_state;
+    end
+    C = inv(Sigma_lambda + BSigma);
+    lam_msg.precision = Bi' * C * Bi;
+    lam_msg.info_state = Bi' * C * (mu_lambda - Bmu);
+  else
+    % method that uses matrix inversion lemma to avoid inverting P
+    A = inv(P + inv(BSigma));
+    C = P - P*A*P;
+    lam_msg.precision = Bi' * C * Bi;
+    D = eye(self_size) - P*A;
+    z = msg{n}.lambda.info_state;
+    lam_msg.info_state = Bi' * (D*z - D*P*Bmu);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/CPD_to_pi.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function pi = CPD_to_pi(CPD, msg_type, n, ps, msg, evidence)
+% CPD_TO_PI Compute the pi vector (gaussian)
+% function pi = CPD_to_pi(CPD, msg_type, n, ps, msg, evidence)
+
+switch msg_type
+ case 'd',
+  error('gaussian_CPD can''t create discrete msgs')
+ case 'g',
+  [m, Q, W] = gaussian_CPD_params_given_dps(CPD, [ps n], evidence);
+  cps = ps(CPD.cps);
+  cpsizes = CPD.sizes(CPD.cps);
+  pi.mu = m;
+  pi.Sigma = Q;
+  for k=1:length(cps) % only get pi msgs from cts parents
+    %bk = block(k, cpsizes);
+    bk = CPD.cps_block_ndx{k};
+    Bk = W(:, bk);
+    m = msg{n}.pi_from_parent{k}; 
+    pi.Sigma = pi.Sigma + Bk * m.Sigma * Bk';
+    pi.mu = pi.mu + Bk * m.mu; % m.mu = u(k)
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/CPD_to_scgpot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+function pot = CPD_to_scgpot(CPD, domain, ns, cnodes, evidence)
+% CPD_TO_CGPOT Convert a Gaussian CPD to a CG potential, incorporating any evidence   
+% pot = CPD_to_cgpot(CPD, domain, ns, cnodes, evidence)
+
+self = CPD.self;
+dnodes = mysetdiff(1:length(ns), cnodes);
+odom = domain(~isemptycell(evidence(domain)));
+cdom = myintersect(cnodes, domain);
+cheaddom = myintersect(self, domain);
+ctaildom = mysetdiff(cdom,cheaddom);
+ddom = myintersect(dnodes, domain);
+cobs = myintersect(cdom, odom);
+dobs = myintersect(ddom, odom);
+ens = ns; % effective node size
+ens(cobs) = 0;
+ens(dobs) = 1;
+
+% Extract the params compatible with the observations (if any) on the discrete parents (if any)
+% parents are all but the last domain element
+ps = domain(1:end-1);
+dps = myintersect(ps, ddom);
+dops = myintersect(dps, odom);
+
+map = find_equiv_posns(dops, dps);
+dpvals = cat(1, evidence{dops});
+index = mk_multi_index(length(dps), map, dpvals);
+
+dpsize = prod(ens(dps));
+cpsize = size(CPD.weights(:,:,1), 2); % cts parents size
+ss = size(CPD.mean, 1); % self size
+% the reshape acts like a squeeze
+m = reshape(CPD.mean(:, index{:}), [ss dpsize]);
+C = reshape(CPD.cov(:, :, index{:}), [ss ss dpsize]);
+W = reshape(CPD.weights(:, :, index{:}), [ss cpsize dpsize]);
+
+
+% Convert each conditional Gaussian to a canonical potential
+pot = cell(1, dpsize);
+for i=1:dpsize
+  %pot{i} = linear_gaussian_to_scgcpot(m(:,i), C(:,:,i), W(:,:,i), cdom, ns, cnodes, evidence);
+  pot{i} = scgcpot(ss, cpsize, 1, m(:,i), W(:,:,i), C(:,:,i));
+end
+
+pot = scgpot(ddom, cheaddom, ctaildom, ens, pot);
+
+
+function pot = linear_gaussian_to_scgcpot(mu, Sigma, W, domain, ns, cnodes, evidence)
+% LINEAR_GAUSSIAN_TO_CPOT Convert a linear Gaussian CPD  to a stable conditional potential element.
+% pot = linear_gaussian_to_cpot(mu, Sigma, W, domain, ns, cnodes, evidence)
+
+p = 1;
+A = mu;
+B = W;
+C = Sigma;
+ns(odom) = 0;
+%pot = scgcpot(, ns(domain), p, A, B, C);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,20 @@
+/CPD_to_lambda_msg.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/CPD_to_pi.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/CPD_to_scgpot.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/adjustable_CPD.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/convert_CPD_to_table_hidden_ps.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/convert_to_pot.m/1.1.1.1/Sun Mar  9 23:03:16 2003//
+/convert_to_table.m/1.1.1.1/Sun May 11 23:31:54 2003//
+/display.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/gaussian_CPD.m/1.1.1.1/Wed Jun 15 21:13:06 2005//
+/gaussian_CPD_params_given_dps.m/1.1.1.1/Sun May 11 23:13:40 2003//
+/get_field.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/learn_params.m/1.1.1.1/Thu Jun 10 01:28:10 2004//
+/log_prob_node.m/1.1.1.1/Tue Sep 10 17:44:00 2002//
+/maximize_params.m/1.1.1.1/Tue May 20 14:10:06 2003//
+/maximize_params_debug.m/1.1.1.1/Fri Jan 31 00:13:10 2003//
+/reset_ess.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/sample_node.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/set_fields.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/update_ess.m/1.1.1.1/Tue Jul 22 22:55:46 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+A D/Old////
+A D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@gaussian_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/Old/CPD_to_lambda_msg.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+function lam_msg = CPD_to_lambda_msg(CPD, msg_type, n, ps, msg, p)
+% CPD_TO_LAMBDA_MSG Compute lambda message (gaussian)
+% lam_msg = compute_lambda_msg(CPD, msg_type, n, ps, msg, p)
+% Pearl p183 eq 4.52
+
+switch msg_type
+ case 'd',
+  error('gaussian_CPD can''t create discrete msgs')
+ case 'g',
+  self_size = CPD.sizes(end);
+  if all(msg{n}.lambda.precision == 0) % no info to send on
+    lam_msg.precision = zeros(self_size);
+    lam_msg.info_state = zeros(self_size, 1);
+    return;
+  end
+  cpsizes = CPD.sizes(CPD.cps);
+  dpval = 1;
+  Q = CPD.cov(:,:,dpval);
+  Sigmai = Q;
+  wmu = zeros(self_size, 1);
+  for k=1:length(ps)
+    pk = ps(k);
+    if pk ~= p
+      bk = block(k, cpsizes);
+      Bk = CPD.weights(:, bk, dpval);
+      m = msg{n}.pi_from_parent{k};
+      Sigmai = Sigmai + Bk * m.Sigma * Bk';
+      wmu = wmu + Bk * m.mu; % m.mu = u(k)
+    end
+  end
+  % Sigmai = Q + sum_{k \neq i} B_k Sigma_k B_k'
+  i = find_equiv_posns(p, ps);
+  bi = block(i, cpsizes);
+  Bi = CPD.weights(:,bi, dpval);
+  
+  if 0
+  P = msg{n}.lambda.precision;
+  if isinf(P) % inv(P)=Sigma_lambda=0
+    precision_temp = inv(Sigmai);
+    lam_msg.precision = Bi' * precision_temp * Bi;
+    lam_msg.info_state = precision_temp * (msg{n}.lambda.mu - wmu);
+  else
+    A = inv(P + inv(Sigmai));
+    precision_temp = P + P*A*P;
+    lam_msg.precision = Bi' * precision_temp * Bi;
+    self_size = length(P);
+    C = eye(self_size) + P*A;
+    z = msg{n}.lambda.info_state;
+    lam_msg.info_state = C*z - C*P*wmu;
+  end
+  end
+  
+  if isinf(msg{n}.lambda.precision)
+    Sigma_lambda = zeros(self_size, self_size); % infinite precision => 0 variance
+    mu_lambda = msg{n}.lambda.mu; % observed_value;
+  else
+    Sigma_lambda = inv(msg{n}.lambda.precision);
+    mu_lambda = Sigma_lambda * msg{n}.lambda.info_state;
+  end
+  precision_temp = inv(Sigma_lambda + Sigmai);
+  lam_msg.precision = Bi' * precision_temp * Bi;
+  lam_msg.info_state = Bi' * precision_temp * (mu_lambda - wmu);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/CPD_to_lambda_msg.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/gaussian_CPD.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/log_prob_node.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/maximize_params.m/1.1.1.1/Thu Jan 30 22:38:16 2003//
+/update_ess.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/update_tied_ess.m/1.1.1.1/Wed May 29 15:59:52 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@gaussian_CPD/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/Old/gaussian_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,184 @@
+function CPD = gaussian_CPD(varargin)
+% GAUSSIAN_CPD Make a conditional linear Gaussian distrib.
+%
+% To define this CPD precisely, call the continuous (cts) parents (if any) X,
+% the discrete parents (if any) Q, and this node Y. Then the distribution on Y is:
+% - no parents: Y ~ N(mu, Sigma)
+% - cts parents : Y|X=x ~ N(mu + W x, Sigma)
+% - discrete parents: Y|Q=i ~ N(mu(i), Sigma(i))
+% - cts and discrete parents: Y|X=x,Q=i ~ N(mu(i) + W(i) x, Sigma(i))
+%
+% CPD = gaussian_CPD(bnet, node, ...) will create a CPD with random parameters,
+% where node is the number of a node in this equivalence class.
+%
+% The list below gives optional arguments [default value in brackets].
+% (Let ns(i) be the size of node i, X = ns(X), Y = ns(Y) and Q = prod(ns(Q)).)
+%
+% mean       - mu(:,i) is the mean given Q=i [ randn(Y,Q) ]
+% cov        - Sigma(:,:,i) is the covariance given Q=i [ repmat(eye(Y,Y), [1 1 Q]) ]
+% weights    - W(:,:,i) is the regression matrix given Q=i [ randn(Y,X,Q) ]
+% cov_type   - if 'diag', Sigma(:,:,i) is diagonal [ 'full' ]
+% tied_cov   - if 1, we constrain Sigma(:,:,i) to be the same for all i [0]
+% clamp_mean - if 1, we do not adjust mu(:,i) during learning [0]
+% clamp_cov  - if 1, we do not adjust Sigma(:,:,i) during learning [0]
+% clamp_weights - if 1, we do not adjust W(:,:,i) during learning [0]
+% cov_prior_weight - weight given to I prior for estimating Sigma [0.01]
+%
+% e.g., CPD = gaussian_CPD(bnet, i, 'mean', [0; 0], 'clamp_mean', 'yes')
+%
+% For backwards compatibility with BNT2, you can also specify the parameters in the following order
+%   CPD = gaussian_CPD(bnet, self, mu, Sigma, W, cov_type, tied_cov, clamp_mean, clamp_cov, clamp_weight)
+%
+% Sometimes it is useful to create an "isolated" CPD, without needing to pass in a bnet.
+% In this case, you must specify the discrete and cts parents (dps, cps) and the family sizes, followed
+% by the optional arguments above:
+%   CPD = gaussian_CPD('self', i, 'dps', dps, 'cps', cps, 'sz', fam_size, ...)
+
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  clamp = 0;
+  CPD = class(CPD, 'gaussian_CPD', generic_CPD(clamp));
+  return;
+elseif isa(varargin{1}, 'gaussian_CPD')
+  % This might occur if we are copying an object.
+  CPD = varargin{1};
+  return;
+end
+CPD = init_fields;
+ 
+CPD = class(CPD, 'gaussian_CPD', generic_CPD(0));
+
+
+% parse mandatory arguments
+if ~isstr(varargin{1}) % pass in bnet
+  bnet = varargin{1};
+  self = varargin{2};
+  args = varargin(3:end);
+  ns = bnet.node_sizes;
+  ps = parents(bnet.dag, self);
+  dps = myintersect(ps, bnet.dnodes);
+  cps = myintersect(ps, bnet.cnodes);
+  fam_sz = ns([ps self]);
+else
+  disp('parsing new style')
+  for i=1:2:length(varargin)
+    switch varargin{i},
+     case 'self', self = varargin{i+1}; 
+     case 'dps',  dps = varargin{i+1};
+     case 'cps',  cps = varargin{i+1};
+     case 'sz',   fam_sz = varargin{i+1};
+    end
+  end
+  ps = myunion(dps, cps);
+  args = varargin;
+end
+
+CPD.self = self;
+CPD.sizes = fam_sz;
+
+% Figure out which (if any) of the parents are discrete, and which cts, and how big they are
+% dps = discrete parents, cps = cts parents
+CPD.cps = find_equiv_posns(cps, ps); % cts parent index
+CPD.dps = find_equiv_posns(dps, ps);
+ss = fam_sz(end);
+psz = fam_sz(1:end-1);
+dpsz = prod(psz(CPD.dps));
+cpsz = sum(psz(CPD.cps));
+
+% set default params
+CPD.mean = randn(ss, dpsz);
+CPD.cov = 100*repmat(eye(ss), [1 1 dpsz]);    
+CPD.weights = randn(ss, cpsz, dpsz);
+CPD.cov_type = 'full';
+CPD.tied_cov = 0;
+CPD.clamped_mean = 0;
+CPD.clamped_cov = 0;
+CPD.clamped_weights = 0;
+CPD.cov_prior_weight = 0.01;
+
+nargs = length(args);
+if nargs > 0
+  if ~isstr(args{1})
+    % gaussian_CPD(bnet, self, mu, Sigma, W, cov_type, tied_cov, clamp_mean, clamp_cov, clamp_weights)
+    if nargs >= 1 & ~isempty(args{1}), CPD.mean = args{1}; end
+    if nargs >= 2 & ~isempty(args{2}), CPD.cov = args{2}; end
+    if nargs >= 3 & ~isempty(args{3}), CPD.weights = args{3}; end
+    if nargs >= 4 & ~isempty(args{4}), CPD.cov_type = args{4}; end
+    if nargs >= 5 & ~isempty(args{5}) & strcmp(args{5}, 'tied'), CPD.tied_cov = 1; end
+    if nargs >= 6 & ~isempty(args{6}), CPD.clamped_mean = 1; end
+    if nargs >= 7 & ~isempty(args{7}), CPD.clamped_cov = 1; end
+    if nargs >= 8 & ~isempty(args{8}), CPD.clamped_weights = 1; end
+  else
+    CPD = set_fields(CPD, args{:});
+  end
+end
+
+% Make sure the matrices have 1 dimension per discrete parent.
+% Bug fix due to Xuejing Sun 3/6/01
+CPD.mean = myreshape(CPD.mean, [ss ns(dps)]);
+CPD.cov = myreshape(CPD.cov, [ss ss ns(dps)]);
+CPD.weights = myreshape(CPD.weights, [ss cpsz ns(dps)]);
+  
+CPD.init_cov = CPD.cov;  % we reset to this if things go wrong during learning
+
+% expected sufficient statistics 
+CPD.Wsum = zeros(dpsz,1);
+CPD.WYsum = zeros(ss, dpsz);
+CPD.WXsum = zeros(cpsz, dpsz);
+CPD.WYYsum = zeros(ss, ss, dpsz);
+CPD.WXXsum = zeros(cpsz, cpsz, dpsz);
+CPD.WXYsum = zeros(cpsz, ss, dpsz);
+
+% For BIC
+CPD.nsamples = 0;
+switch CPD.cov_type
+  case 'full',
+    ncov_params = ss*(ss-1)/2; % since symmetric (and positive definite)
+  case 'diag',
+    ncov_params = ss;
+  otherwise
+    error(['unrecognized cov_type ' cov_type]);
+end
+% params = weights + mean + cov
+if CPD.tied_cov
+  CPD.nparams = ss*cpsz*dpsz + ss*dpsz + ncov_params;
+else
+  CPD.nparams = ss*cpsz*dpsz + ss*dpsz + dpsz*ncov_params;
+end
+
+
+
+clamped = CPD.clamped_mean & CPD.clamped_cov & CPD.clamped_weights;
+CPD = set_clamped(CPD, clamped);
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.self = [];
+CPD.sizes = [];
+CPD.cps = [];
+CPD.dps = [];
+CPD.mean = [];
+CPD.cov = [];
+CPD.weights = [];
+CPD.clamped_mean = [];
+CPD.clamped_cov = [];
+CPD.clamped_weights = [];
+CPD.init_cov = [];
+CPD.cov_type = [];
+CPD.tied_cov = [];
+CPD.Wsum = [];
+CPD.WYsum = [];
+CPD.WXsum = [];
+CPD.WYYsum = [];
+CPD.WXXsum = [];
+CPD.WXYsum = [];
+CPD.nsamples = [];
+CPD.nparams = [];            
+CPD.cov_prior_weight = [];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/Old/log_prob_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function L = log_prob_node(CPD, self_ev, pev)
+% LOG_PROB_NODE Compute prod_m log P(x(i,m)| x(pi_i,m), theta_i) for node i (gaussian)
+% L = log_prob_node(CPD, self_ev, pev)
+%
+% self_ev(m) is the evidence on this node in case m.
+% pev(i,m) is the evidence on the i'th parent in case m (if there are any parents).
+% (These may also be cell arrays.)
+
+if iscell(self_ev), usecell = 1; else usecell = 0; end
+
+use_log = 1;
+ncases = length(self_ev);
+nparents = length(CPD.sizes)-1;
+assert(ncases == size(pev, 2));
+
+if ncases == 0
+  L = 0;
+  return;
+end
+
+if length(CPD.dps)==0 % no discrete parents, so we can vectorize
+  i = 1;
+  if usecell
+    Y = cell2num(self_ev);
+  else
+    Y = self_ev;
+  end
+  if length(CPD.cps) == 0 
+    L = gaussian_prob(Y, CPD.mean(:,i), CPD.cov(:,:,i), use_log);
+  else
+    if usecell
+      X = cell2num(pev);
+    else
+      X = pev;
+    end
+    L = gaussian_prob(Y, CPD.mean(:,i) + CPD.weights(:,:,i)*X, CPD.cov(:,:,i), use_log);
+  end
+else % each case uses a (potentially) different set of parameters
+  L = 0;
+  for m=1:ncases
+    if usecell
+      dpvals = cat(1, pev{CPD.dps, m});
+    else
+      dpvals = pev(CPD.dps, m);
+    end
+    i = subv2ind(CPD.sizes(CPD.dps), dpvals(:)');
+    y = self_ev{m};
+    if length(CPD.cps) == 0 
+      L = L + gaussian_prob(y, CPD.mean(:,i), CPD.cov(:,:,i), use_log);
+    else
+      if usecell
+	x = cat(1, pev{CPD.cps, m});
+      else
+	x = pev(CPD.cps, m);
+      end
+      L = L + gaussian_prob(y, CPD.mean(:,i) + CPD.weights(:,:,i)*x, CPD.cov(:,:,i), use_log);
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/Old/maximize_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,147 @@
+function CPD = maximize_params(CPD, temp)
+% MAXIMIZE_PARAMS Set the params of a CPD to their ML values (Gaussian)
+% CPD = maximize_params(CPD, temperature)
+%
+% Temperature is currently only used for entropic prior on Sigma
+
+% For details, see "Fitting a Conditional Gaussian Distribution", Kevin Murphy, tech. report,
+% 1998, available at www.cs.berkeley.edu/~murphyk/papers.html
+% Refering to table 2, we use equations 1/2 to estimate the covariance matrix in the untied/tied case,
+% and equation 9 to estimate the weight matrix and mean.
+% We do not implement spherical Gaussians - the code is already pretty complicated!
+
+if ~adjustable_CPD(CPD), return; end
+
+%assert(approxeq(CPD.nsamples, sum(CPD.Wsum)));
+assert(~any(isnan(CPD.WXXsum)))
+assert(~any(isnan(CPD.WXYsum)))
+assert(~any(isnan(CPD.WYYsum)))
+
+[self_size cpsize dpsize] = size(CPD.weights);
+
+% Append 1s to the parents, and derive the corresponding cross products.
+% This is used when estimate the means and weights simultaneosuly,
+% and when estimatting Sigma.
+% Let x2 = [x 1]'
+XY = zeros(cpsize+1, self_size, dpsize); % XY(:,:,i) = sum_l w(l,i) x2(l) y(l)' 
+XX = zeros(cpsize+1, cpsize+1, dpsize); % XX(:,:,i) = sum_l w(l,i) x2(l) x2(l)' 
+YY = zeros(self_size, self_size, dpsize); % YY(:,:,i) = sum_l w(l,i) y(l) y(l)' 
+for i=1:dpsize
+  XY(:,:,i) = [CPD.WXYsum(:,:,i) % X*Y
+	       CPD.WYsum(:,i)']; % 1*Y
+  % [x  * [x' 1]  = [xx' x
+  %  1]              x'  1]
+  XX(:,:,i) = [CPD.WXXsum(:,:,i) CPD.WXsum(:,i);
+	       CPD.WXsum(:,i)'   CPD.Wsum(i)];
+  YY(:,:,i) = CPD.WYYsum(:,:,i);
+end
+
+w = CPD.Wsum(:);
+% Set any zeros to one before dividing
+% This is valid because w(i)=0 => WYsum(:,i)=0, etc
+w = w + (w==0);
+
+if CPD.clamped_mean
+  % Estimating B2 and then setting the last column (the mean) to the clamped mean is *not* equivalent
+  % to estimating B and then adding the clamped_mean to the last column.
+  if ~CPD.clamped_weights
+    B = zeros(self_size, cpsize, dpsize);
+    for i=1:dpsize
+      if det(CPD.WXXsum(:,:,i))==0
+	B(:,:,i) = 0;
+      else
+	% Eqn 9 in table 2 of TR
+	%B(:,:,i) = CPD.WXYsum(:,:,i)' * inv(CPD.WXXsum(:,:,i));
+	B(:,:,i) = (CPD.WXXsum(:,:,i) \ CPD.WXYsum(:,:,i))';
+      end
+    end
+    %CPD.weights = reshape(B, [self_size cpsize dpsize]);
+    CPD.weights = B;
+  end
+elseif CPD.clamped_weights % KPM 1/25/02
+  if ~CPD.clamped_mean % ML estimate is just sample mean of the residuals
+    for i=1:dpsize
+      CPD.mean(:,i) = (CPD.WYsum(:,i) - CPD.weights(:,:,i) * CPD.WXsum(:,i)) / w(i);
+    end
+  end
+else % nothing is clamped, so estimate mean and weights simultaneously
+  B2 = zeros(self_size, cpsize+1, dpsize);
+  for i=1:dpsize
+    if det(XX(:,:,i))==0  % fix by U. Sondhauss 6/27/99
+      B2(:,:,i)=0;          
+    else                    
+      % Eqn 9 in table 2 of TR
+      %B2(:,:,i) = XY(:,:,i)' * inv(XX(:,:,i));
+      B2(:,:,i) = (XX(:,:,i) \ XY(:,:,i))';
+    end                   
+    CPD.mean(:,i) = B2(:,cpsize+1,i);
+    CPD.weights(:,:,i) = B2(:,1:cpsize,i);
+  end
+end
+
+% Let B2 = [W mu]
+if cpsize>0
+  B2(:,1:cpsize,:) = reshape(CPD.weights, [self_size cpsize dpsize]);
+end
+B2(:,cpsize+1,:) = reshape(CPD.mean, [self_size dpsize]);
+
+% To avoid singular covariance matrices,
+% we use the regularization method suggested in "A Quasi-Bayesian approach to estimating
+% parameters for mixtures of normal distributions", Hamilton 91.
+% If the ML estimate is Sigma = M/N, the MAP estimate is (M+gamma*I) / (N+gamma),
+% where gamma >=0 is a smoothing parameter (equivalent sample size of I prior)
+
+gamma = CPD.cov_prior_weight;
+
+if ~CPD.clamped_cov
+  if CPD.cov_prior_entropic % eqn 12 of Brand AI/Stat 99
+    Z = 1-temp;
+    % When temp > 1, Z is negative, so we are dividing by a smaller
+    % number, ie. increasing the variance.
+  else
+    Z = 0;
+  end
+  if CPD.tied_cov
+    S = zeros(self_size, self_size);
+    % Eqn 2 from table 2 in TR
+    for i=1:dpsize
+      S = S + (YY(:,:,i) - B2(:,:,i)*XY(:,:,i));
+    end
+    %denom = max(1, CPD.nsamples + gamma + Z);
+    denom = CPD.nsamples + gamma + Z;
+    S = (S + gamma*eye(self_size)) / denom;
+    if strcmp(CPD.cov_type, 'diag')
+      S = diag(diag(S));
+    end
+    CPD.cov = repmat(S, [1 1 dpsize]);
+  else 
+    for i=1:dpsize      
+      % Eqn 1 from table 2 in TR
+      S = YY(:,:,i) - B2(:,:,i)*XY(:,:,i);
+      %denom = max(1, w(i) + gamma + Z); % gives wrong answers on mhmm1
+      denom = w(i) + gamma + Z;
+      S = (S + gamma*eye(self_size)) / denom;
+      CPD.cov(:,:,i) = S;
+    end
+    if strcmp(CPD.cov_type, 'diag')
+      for i=1:dpsize      
+	CPD.cov(:,:,i) = diag(diag(CPD.cov(:,:,i)));
+      end
+    end
+  end
+end
+
+
+check_covars = 0;
+min_covar = 1e-5;
+if check_covars % prevent collapsing to a point
+  for i=1:dpsize
+    if min(svd(CPD.cov(:,:,i))) < min_covar
+      disp(['resetting singular covariance for node ' num2str(CPD.self)]);
+      CPD.cov(:,:,i) = CPD.init_cov(:,:,i);
+    end
+  end
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/Old/update_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,85 @@
+function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+% UPDATE_ESS Update the Expected Sufficient Statistics of a Gaussian node
+% function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+
+%if nargin < 6
+%  hidden_bitv = zeros(1, max(fmarginal.domain));
+%  hidden_bitv(find(isempty(evidence)))=1;
+%end
+
+dom = fmarginal.domain;
+self = dom(end);
+ps = dom(1:end-1);
+hidden_self = hidden_bitv(self);
+cps = myintersect(ps, cnodes);
+dps = mysetdiff(ps, cps);
+hidden_cps = all(hidden_bitv(cps));
+hidden_dps = all(hidden_bitv(dps));
+
+CPD.nsamples = CPD.nsamples + 1;            
+[ss cpsz dpsz] = size(CPD.weights); % ss = self size
+
+% Let X be the cts parent (if any), Y be the cts child (self).
+
+if ~hidden_self & (isempty(cps) | ~hidden_cps) & hidden_dps % all cts nodes are observed, all discrete nodes are hidden
+  % Since X and Y are observed, SYY = 0, SXX = 0, SXY = 0
+  % Since discrete parents are hidden, we do not need to add evidence to w.
+  w = fmarginal.T(:);
+  CPD.Wsum = CPD.Wsum + w;
+  y = evidence{self};
+  Cyy = y*y';
+  if ~CPD.useC
+     W = repmat(w(:)',ss,1); % W(y,i) = w(i)
+     W2 = repmat(reshape(W, [ss 1 dpsz]), [1 ss 1]); % W2(x,y,i) = w(i)
+     CPD.WYsum = CPD.WYsum +  W .* repmat(y(:), 1, dpsz);
+     CPD.WYYsum = CPD.WYYsum + W2  .* repmat(reshape(Cyy, [ss ss 1]), [1 1 dpsz]);
+  else
+     W = w(:)';
+     W2 = reshape(W, [1 1 dpsz]);
+     CPD.WYsum = CPD.WYsum +  rep_mult(W, y(:), size(CPD.WYsum)); 
+     CPD.WYYsum = CPD.WYYsum + rep_mult(W2, Cyy, size(CPD.WYYsum));
+  end
+  if cpsz > 0 % X exists
+    x = cat(1, evidence{cps}); x = x(:);
+    Cxx = x*x';
+    Cxy = x*y';
+    if ~CPD.useC
+       CPD.WXsum = CPD.WXsum + W .* repmat(x(:), 1, dpsz);
+       CPD.WXXsum = CPD.WXXsum + W2 .* repmat(reshape(Cxx, [cpsz cpsz 1]), [1 1 dpsz]);
+       CPD.WXYsum = CPD.WXYsum + W2 .* repmat(reshape(Cxy, [cpsz ss 1]), [1 1 dpsz]);
+    else
+       CPD.WXsum = CPD.WXsum + rep_mult(W, x(:), size(CPD.WXsum));
+       CPD.WXXsum = CPD.WXXsum + rep_mult(W2, Cxx, size(CPD.WXXsum));
+       CPD.WXYsum = CPD.WXYsum + rep_mult(W2, Cxy, size(CPD.WXYsum));
+    end
+  end
+  return;
+end
+
+% general (non-vectorized) case
+fullm = add_evidence_to_gmarginal(fmarginal, evidence, ns, cnodes); % slow!
+
+if dpsz == 1 % no discrete parents
+  w = 1;
+else
+  w = fullm.T(:);
+end
+
+CPD.Wsum = CPD.Wsum + w;
+xi = 1:cpsz;
+yi = (cpsz+1):(cpsz+ss);
+for i=1:dpsz
+  muY = fullm.mu(yi, i);
+  SYY = fullm.Sigma(yi, yi, i);
+  CPD.WYsum(:,i) = CPD.WYsum(:,i) + w(i)*muY;
+  CPD.WYYsum(:,:,i) = CPD.WYYsum(:,:,i) + w(i)*(SYY + muY*muY'); % E[X Y] = Cov[X,Y] + E[X] E[Y]
+  if cpsz > 0
+    muX = fullm.mu(xi, i);
+    SXX = fullm.Sigma(xi, xi, i);
+    SXY = fullm.Sigma(xi, yi, i);
+    CPD.WXsum(:,i) = CPD.WXsum(:,i) + w(i)*muX;
+    CPD.WXXsum(:,:,i) = CPD.WXXsum(:,:,i) + w(i)*(SXX + muX*muX');
+    CPD.WXYsum(:,:,i) = CPD.WXYsum(:,:,i) + w(i)*(SXY + muX*muY');
+  end
+end                
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/Old/update_tied_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,118 @@
+function CPD = update_tied_ess(CPD, domain, engine, evidence, ns, cnodes)
+
+if ~adjustable_CPD(CPD), return; end
+nCPDs = size(domain, 2);
+fmarginal = cell(1, nCPDs);
+for l=1:nCPDs
+  fmarginal{l} = marginal_family(engine, nodes(l));
+end
+
+[ss cpsz dpsz] = size(CPD.weights);
+if const_evidence_pattern(engine)
+  dom = domain(:,1);
+  dnodes = mysetdiff(1:length(ns), cnodes);
+  ddom = myintersect(dom, dnodes);
+  cdom = myintersect(dom, cnodes);
+  odom = dom(~isemptycell(evidence(dom)));
+  hdom = dom(isemptycell(evidence(dom)));
+  % If all hidden nodes are discrete and all cts nodes are observed 
+  % (e.g., HMM with Gaussian output)
+  % we can add the observed evidence in parallel
+  if mysubset(ddom, hdom) & mysubset(cdom, odom)
+    [mu, Sigma, T] = add_cts_ev_to_marginals(fmarginal, evidence, ns, cnodes);
+  else
+    mu = zeros(ss, dpsz, nCPDs);
+    Sigma = zeros(ss, ss, dpsz, nCPDs);
+    T = zeros(dpsz, nCPDs);
+    for l=1:nCPDs
+      [mu(:,:,l), Sigma(:,:,:,l), T(:,l)] = add_ev_to_marginals(fmarginal{l}, evidence, ns, cnodes);
+    end
+  end
+end
+CPD.nsamples = CPD.nsamples + nCPDs;            
+
+
+if dpsz == 1 % no discrete parents
+  w = 1;
+else
+  w = fullm.T(:);
+end
+CPD.Wsum = CPD.Wsum + w;
+% Let X be the cts parent (if any), Y be the cts child (self).
+xi = 1:cpsz;
+yi = (cpsz+1):(cpsz+ss);
+for i=1:dpsz
+  muY = fullm.mu(yi, i);
+  SYY = fullm.Sigma(yi, yi, i);
+  CPD.WYsum(:,i) = CPD.WYsum(:,i) + w(i)*muY;
+  CPD.WYYsum(:,:,i) = CPD.WYYsum(:,:,i) + w(i)*(SYY + muY*muY'); % E[X Y] = Cov[X,Y] + E[X] E[Y]
+  if cpsz > 0
+    muX = fullm.mu(xi, i);
+    SXX = fullm.Sigma(xi, xi, i);
+    SXY = fullm.Sigma(xi, yi, i);
+    CPD.WXsum(:,i) = CPD.WXsum(:,i) + w(i)*muX;
+    CPD.WXYsum(:,:,i) = CPD.WXYsum(:,:,i) + w(i)*(SXY + muX*muY');
+    CPD.WXXsum(:,:,i) = CPD.WXXsum(:,:,i) + w(i)*(SXX + muX*muX');
+  end
+end                
+
+
+%%%%%%%%%%%%%
+
+function fullm = add_evidence_to_marginal(fmarginal, evidence, ns, cnodes)
+
+
+dom = fmarginal.domain;
+
+% Find out which values of the discrete parents (if any) are compatible with 
+% the discrete evidence (if any).
+dnodes = mysetdiff(1:length(ns), cnodes);
+ddom = myintersect(dom, dnodes);
+cdom = myintersect(dom, cnodes);
+odom = dom(~isemptycell(evidence(dom)));
+hdom = dom(isemptycell(evidence(dom)));
+
+dobs = myintersect(ddom, odom);
+dvals = cat(1, evidence{dobs});
+ens = ns; % effective node sizes
+ens(dobs) = 1;
+S = prod(ens(ddom));
+subs = ind2subv(ens(ddom), 1:S);
+mask = find_equiv_posns(dobs, ddom);
+subs(mask) = dvals;
+supportedQs = subv2ind(ns(ddom), subs);
+
+if isempty(ddom)
+  Qarity = 1;
+else
+  Qarity = prod(ns(ddom));
+end
+fullm.T = zeros(Qarity, 1);
+fullm.T(supportedQs) = fmarginal.T(:);
+
+% Now put the hidden cts parts into their right blocks,
+% leaving the observed cts parts as 0.
+cobs = myintersect(cdom, odom);
+chid = myintersect(cdom, hdom);
+cvals = cat(1, evidence{cobs});
+n = sum(ns(cdom));
+fullm.mu = zeros(n,Qarity);
+fullm.Sigma = zeros(n,n,Qarity);
+
+if ~isempty(chid)
+  chid_blocks = block(find_equiv_posns(chid, cdom), ns(cdom));
+end
+if ~isempty(cobs)
+  cobs_blocks = block(find_equiv_posns(cobs, cdom), ns(cdom));
+end
+
+for i=1:length(supportedQs)
+  Q = supportedQs(i);
+  if ~isempty(chid)
+    fullm.mu(chid_blocks, Q) = fmarginal.mu(:, i);
+    fullm.Sigma(chid_blocks, chid_blocks, Q) = fmarginal.Sigma(:,:,i);
+  end
+  if ~isempty(cobs)
+    fullm.mu(cobs_blocks, Q) = cvals(:);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/adjustable_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function p = adjustable_CPD(CPD)
+% ADJUSTABLE_CPD Does this CPD have any adjustable params? (gaussian)
+% p = adjustable_CPD(CPD)
+
+p = ~CPD.clamped_mean | ~CPD.clamped_cov | ~CPD.clamped_weights;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/convert_CPD_to_table_hidden_ps.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,20 @@
+function T = convert_CPD_to_table_hidden_ps(CPD, self_val)
+% CONVERT_CPD_TO_TABLE_HIDDEN_PS Convert a Gaussian CPD to a table
+% function T = convert_CPD_to_table_hidden_ps(CPD, self_val)
+%
+% self_val must be a non-empty vector.
+% All the parents are hidden.
+%
+% This is used by misc/convert_dbn_CPDs_to_tables
+
+m = CPD.mean;
+C = CPD.cov;
+W = CPD.weights;
+
+[ssz dpsize] = size(m);
+
+T = zeros(dpsize, 1);
+for i=1:dpsize
+  T(i) = gaussian_prob(self_val, m(:,i), C(:,:,i));
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/convert_to_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,71 @@
+function pot = convert_to_pot(CPD, pot_type, domain, evidence)
+% CONVERT_TO_POT Convert a Gaussian CPD to one or more potentials
+% pot = convert_to_pot(CPD, pot_type, domain, evidence)
+
+sz = CPD.sizes;
+ns = zeros(1, max(domain));
+ns(domain) = sz;
+
+odom = domain(~isemptycell(evidence(domain)));
+ps = domain(1:end-1);
+cps = ps(CPD.cps);
+dps = ps(CPD.dps);
+self = domain(end);
+cdom = [cps(:)' self];
+ddom = dps;
+cnodes = cdom;
+  
+switch pot_type
+ case 'u',
+  error('gaussian utility potentials not yet supported');
+ 
+ case 'd',
+  T = convert_to_table(CPD, domain, evidence);
+  ns(odom) = 1;
+  pot = dpot(domain, ns(domain), T);          
+
+ case {'c','g'},
+  [m, C, W] = gaussian_CPD_params_given_dps(CPD, domain, evidence);
+  pot = linear_gaussian_to_cpot(m, C, W, domain, ns, cnodes, evidence);
+
+ case 'cg',
+  [m, C, W] = gaussian_CPD_params_given_dps(CPD, domain, evidence);
+  % Convert each conditional Gaussian to a canonical potential
+  cobs = myintersect(cdom, odom);
+  dobs = myintersect(ddom, odom);
+  ens = ns; % effective node size
+  ens(cobs) = 0;
+  ens(dobs) = 1;
+  dpsize = prod(ens(dps));
+  can = cell(1, dpsize);
+  for i=1:dpsize
+    if isempty(W)
+      can{i} = linear_gaussian_to_cpot(m(:,i), C(:,:,i), [], cdom, ns, cnodes, evidence);
+    else
+      can{i} = linear_gaussian_to_cpot(m(:,i), C(:,:,i), W(:,:,i), cdom, ns, cnodes, evidence);
+    end
+  end
+  pot = cgpot(ddom, cdom, ens, can);
+
+ case 'scg',
+  [m, C, W] = gaussian_CPD_params_given_dps(CPD, domain, evidence);
+  cobs = myintersect(cdom, odom);
+  dobs = myintersect(ddom, odom);
+  ens = ns; % effective node size
+  ens(cobs) = 0;
+  ens(dobs) = 1;
+  dpsize = prod(ens(dps));
+  cpsize = size(W, 2); % cts parents size
+  ss = size(m, 1); % self size
+  cheaddom = self;
+  ctaildom = cps(:)';
+  pot_array = cell(1, dpsize);
+  for i=1:dpsize
+    pot_array{i} = scgcpot(ss, cpsize, 1, m(:,i), W(:,:,i), C(:,:,i));
+  end
+  pot = scgpot(ddom, cheaddom, ctaildom, ens, pot_array);
+
+ otherwise,
+  error(['unrecognized pot_type' pot_type])
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/convert_to_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function T = convert_to_table(CPD, domain, evidence)
+% CONVERT_TO_TABLE Convert a Gaussian CPD to a table
+% T = convert_to_table(CPD, domain, evidence)
+
+
+sz = CPD.sizes;
+ns = zeros(1, max(domain));
+ns(domain) = sz;
+
+odom = domain(~isemptycell(evidence(domain)));
+ps = domain(1:end-1);
+cps = ps(CPD.cps);
+dps = ps(CPD.dps);
+self = domain(end);
+cdom = [cps(:)' self];
+ddom = dps;
+cnodes = cdom;
+
+[m, C, W] = gaussian_CPD_params_given_dps(CPD, domain, evidence);
+
+
+ns(odom) = 1;
+dpsize = prod(ns(dps));
+self = domain(end);
+assert(myismember(self, odom));
+self_val = evidence{self};
+T = zeros(dpsize, 1);
+if length(cps) > 0 
+  assert(~any(isemptycell(evidence(cps))));
+  cps_vals = cat(1, evidence{cps});
+  for i=1:dpsize
+    T(i) = gaussian_prob(self_val, m(:,i) + W(:,:,i)*cps_vals, C(:,:,i));
+  end
+else
+  for i=1:dpsize
+    T(i) = gaussian_prob(self_val, m(:,i), C(:,:,i));
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function display(CPD)
+
+disp('gaussian_CPD object');
+disp(struct(CPD)); 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/gaussian_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,161 @@
+function CPD = gaussian_CPD(bnet, self, varargin)
+% GAUSSIAN_CPD Make a conditional linear Gaussian distrib.
+%
+% CPD = gaussian_CPD(bnet, node, ...) will create a CPD with random parameters,
+% where node is the number of a node in this equivalence class.
+
+% To define this CPD precisely, call the continuous (cts) parents (if any) X,
+% the discrete parents (if any) Q, and this node Y. Then the distribution on Y is:
+% - no parents: Y ~ N(mu, Sigma)
+% - cts parents : Y|X=x ~ N(mu + W x, Sigma)
+% - discrete parents: Y|Q=i ~ N(mu(i), Sigma(i))
+% - cts and discrete parents: Y|X=x,Q=i ~ N(mu(i) + W(i) x, Sigma(i))
+%
+% The list below gives optional arguments [default value in brackets].
+% (Let ns(i) be the size of node i, X = ns(X), Y = ns(Y) and Q = prod(ns(Q)).)
+% Parameters will be reshaped to the right size if necessary.
+%
+% mean       - mu(:,i) is the mean given Q=i [ randn(Y,Q) ]
+% cov        - Sigma(:,:,i) is the covariance given Q=i [ repmat(100*eye(Y,Y), [1 1 Q]) ]
+% weights    - W(:,:,i) is the regression matrix given Q=i [ randn(Y,X,Q) ]
+% cov_type   - if 'diag', Sigma(:,:,i) is diagonal [ 'full' ]
+% tied_cov   - if 1, we constrain Sigma(:,:,i) to be the same for all i [0]
+% clamp_mean - if 1, we do not adjust mu(:,i) during learning [0]
+% clamp_cov  - if 1, we do not adjust Sigma(:,:,i) during learning [0]
+% clamp_weights - if 1, we do not adjust W(:,:,i) during learning [0]
+% cov_prior_weight - weight given to I prior for estimating Sigma [0.01]
+% cov_prior_entropic - if 1, we also use an entropic prior for Sigma [0]
+%
+% e.g., CPD = gaussian_CPD(bnet, i, 'mean', [0; 0], 'clamp_mean', 1)
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  clamp = 0;
+  CPD = class(CPD, 'gaussian_CPD', generic_CPD(clamp));
+  return;
+elseif isa(bnet, 'gaussian_CPD')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+CPD = init_fields;
+ 
+CPD = class(CPD, 'gaussian_CPD', generic_CPD(0));
+
+args = varargin;
+ns = bnet.node_sizes;
+ps = parents(bnet.dag, self);
+dps = myintersect(ps, bnet.dnodes);
+cps = myintersect(ps, bnet.cnodes);
+fam_sz = ns([ps self]);
+
+CPD.self = self;
+CPD.sizes = fam_sz;
+
+% Figure out which (if any) of the parents are discrete, and which cts, and how big they are
+% dps = discrete parents, cps = cts parents
+CPD.cps = find_equiv_posns(cps, ps); % cts parent index
+CPD.dps = find_equiv_posns(dps, ps);
+ss = fam_sz(end);
+psz = fam_sz(1:end-1);
+dpsz = prod(psz(CPD.dps));
+cpsz = sum(psz(CPD.cps));
+
+% set default params
+CPD.mean = randn(ss, dpsz);
+CPD.cov = 100*repmat(eye(ss), [1 1 dpsz]);    
+CPD.weights = randn(ss, cpsz, dpsz);
+CPD.cov_type = 'full';
+CPD.tied_cov = 0;
+CPD.clamped_mean = 0;
+CPD.clamped_cov = 0;
+CPD.clamped_weights = 0;
+CPD.cov_prior_weight = 0.01;
+CPD.cov_prior_entropic = 0;
+nargs = length(args);
+if nargs > 0
+  CPD = set_fields(CPD, args{:});
+end
+
+% Make sure the matrices have 1 dimension per discrete parent.
+% Bug fix due to Xuejing Sun 3/6/01
+CPD.mean = myreshape(CPD.mean, [ss ns(dps)]);
+CPD.cov = myreshape(CPD.cov, [ss ss ns(dps)]);
+CPD.weights = myreshape(CPD.weights, [ss cpsz ns(dps)]);
+
+% Precompute indices into block structured  matrices
+% to speed up CPD_to_lambda_msg and CPD_to_pi
+cpsizes = CPD.sizes(CPD.cps);
+CPD.cps_block_ndx = cell(1, length(cps));
+for i=1:length(cps)
+  CPD.cps_block_ndx{i} = block(i, cpsizes);
+end
+
+%%%%%%%%%%% 
+% Learning stuff
+
+% expected sufficient statistics 
+CPD.Wsum = zeros(dpsz,1);
+CPD.WYsum = zeros(ss, dpsz);
+CPD.WXsum = zeros(cpsz, dpsz);
+CPD.WYYsum = zeros(ss, ss, dpsz);
+CPD.WXXsum = zeros(cpsz, cpsz, dpsz);
+CPD.WXYsum = zeros(cpsz, ss, dpsz);
+
+% For BIC
+CPD.nsamples = 0;
+switch CPD.cov_type
+ case 'full',
+  % since symmetric 
+    %ncov_params = ss*(ss-1)/2; 
+    ncov_params = ss*(ss+1)/2; 
+  case 'diag',
+    ncov_params = ss;
+  otherwise
+    error(['unrecognized cov_type ' cov_type]);
+end
+% params = weights + mean + cov
+if CPD.tied_cov
+  CPD.nparams = ss*cpsz*dpsz + ss*dpsz + ncov_params;
+else
+  CPD.nparams = ss*cpsz*dpsz + ss*dpsz + dpsz*ncov_params;
+end
+
+% for speeding up maximize_params
+CPD.useC = exist('rep_mult');
+
+clamped = CPD.clamped_mean & CPD.clamped_cov & CPD.clamped_weights;
+CPD = set_clamped(CPD, clamped);
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.self = [];
+CPD.sizes = [];
+CPD.cps = [];
+CPD.dps = [];
+CPD.mean = [];
+CPD.cov = [];
+CPD.weights = [];
+CPD.clamped_mean = [];
+CPD.clamped_cov = [];
+CPD.clamped_weights = [];
+CPD.cov_type = [];
+CPD.tied_cov = [];
+CPD.Wsum = [];
+CPD.WYsum = [];
+CPD.WXsum = [];
+CPD.WYYsum = [];
+CPD.WXXsum = [];
+CPD.WXYsum = [];
+CPD.nsamples = [];
+CPD.nparams = [];            
+CPD.cov_prior_weight = [];
+CPD.cov_prior_entropic = [];
+CPD.useC = [];
+CPD.cps_block_ndx = [];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/gaussian_CPD_params_given_dps.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function [m, C, W] = gaussian_CPD_params_given_dps(CPD, domain, evidence)
+% GAUSSIAN_CPD_PARAMS_GIVEN_EV_ON_DPS Extract parameters given evidence on all discrete parents
+% function [m, C, W] = gaussian_CPD_params_given_ev_on_dps(CPD, domain, evidence)
+
+ps = domain(1:end-1);
+dps = ps(CPD.dps);
+if isempty(dps)
+  m = CPD.mean;
+  C = CPD.cov;
+  W = CPD.weights;
+else
+  odom = domain(~isemptycell(evidence(domain)));
+  dops = myintersect(dps, odom);
+  dpvals = cat(1, evidence{dops});
+  if length(dops) == length(dps)
+    dpsizes = CPD.sizes(CPD.dps);
+    dpval = subv2ind(dpsizes, dpvals(:)');
+    m = CPD.mean(:, dpval);
+    C = CPD.cov(:, :, dpval);
+    W = CPD.weights(:, :, dpval);
+  else
+    map = find_equiv_posns(dops, dps);
+    index = mk_multi_index(length(dps), map, dpvals);
+    m = CPD.mean(:, index{:});
+    C = CPD.cov(:, :, index{:});
+    W = CPD.weights(:, :, index{:});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/get_field.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function val = get_params(CPD, name)
+% GET_PARAMS Get the parameters (fields) for a gaussian_CPD object
+% val = get_params(CPD, name)
+%
+% The following fields can be accessed
+%
+% mean       - mu(:,i) is the mean given Q=i
+% cov        - Sigma(:,:,i) is the covariance given Q=i 
+% weights    - W(:,:,i) is the regression matrix given Q=i 
+%
+% e.g., mean = get_params(CPD, 'mean')
+
+switch name
+ case 'mean',      val = CPD.mean;
+ case 'cov',       val = CPD.cov;
+ case 'weights',   val = CPD.weights;
+ otherwise,
+  error(['invalid argument name ' name]);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/learn_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,31 @@
+function CPD = learn_params(CPD, fam, data, ns, cnodes)
+%function CPD = learn_params(CPD, fam, data, ns, cnodes)
+% LEARN_PARAMS Compute the maximum likelihood estimate of the params of a gaussian CPD given complete data
+% CPD = learn_params(CPD, fam, data, ns, cnodes)
+%
+% data(i,m) is the value of node i in case m (can be cell array).
+% We assume this node has a maximize_params method.
+
+ncases = size(data, 2);
+CPD = reset_ess(CPD);
+% make a fully observed joint distribution over the family
+fmarginal.domain = fam;
+fmarginal.T = 1;
+fmarginal.mu = [];
+fmarginal.Sigma = [];
+if ~iscell(data)
+  cases = num2cell(data);
+else
+  cases = data;
+end
+hidden_bitv = zeros(1, max(fam));
+for m=1:ncases
+  % specify (as a bit vector) which elements in the family domain are hidden
+  hidden_bitv = zeros(1, max(fmarginal.domain));
+  ev = cases(:,m);
+  hidden_bitv(find(isempty(ev)))=1;
+  CPD = update_ess(CPD, fmarginal, ev, ns, cnodes, hidden_bitv);
+end
+CPD = maximize_params(CPD);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/log_prob_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,49 @@
+function L = log_prob_node(CPD, self_ev, pev)
+% LOG_PROB_NODE Compute prod_m log P(x(i,m)| x(pi_i,m), theta_i) for node i (gaussian)
+% L = log_prob_node(CPD, self_ev, pev)
+%
+% self_ev(m) is the evidence on this node in case m.
+% pev(i,m) is the evidence on the i'th parent in case m (if there are any parents).
+% (These may also be cell arrays.)
+
+if iscell(self_ev), usecell = 1; else usecell = 0; end
+
+use_log = 1;
+ncases = length(self_ev);
+nparents = length(CPD.sizes)-1;
+assert(ncases == size(pev, 2));
+
+if ncases == 0
+  L = 0;
+  return;
+end
+
+L = 0;
+for m=1:ncases
+  if isempty(CPD.dps)
+    i = 1;
+  else
+    if usecell
+      dpvals = cat(1, pev{CPD.dps, m});
+    else
+      dpvals = pev(CPD.dps, m);
+    end
+    i = subv2ind(CPD.sizes(CPD.dps), dpvals(:)');
+  end
+  if usecell
+    y = self_ev{m};
+  else
+    y = self_ev(m);
+  end
+  if length(CPD.cps) == 0 
+    L = L + gaussian_prob(y, CPD.mean(:,i), CPD.cov(:,:,i), use_log);
+  else
+    if usecell
+      x = cat(1, pev{CPD.cps, m});
+    else
+      x = pev(CPD.cps, m);
+    end
+    L = L + gaussian_prob(y, CPD.mean(:,i) + CPD.weights(:,:,i)*x, CPD.cov(:,:,i), use_log);
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/maximize_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,68 @@
+function CPD = maximize_params(CPD, temp)
+% MAXIMIZE_PARAMS Set the params of a CPD to their ML values (Gaussian)
+% CPD = maximize_params(CPD, temperature)
+%
+% Temperature is currently ignored.
+
+if ~adjustable_CPD(CPD), return; end
+
+
+if CPD.clamped_mean
+  cl_mean = CPD.mean;
+else
+  cl_mean = [];
+end
+
+if CPD.clamped_cov
+  cl_cov = CPD.cov;
+else
+  cl_cov = [];
+end
+
+if CPD.clamped_weights
+  cl_weights = CPD.weights;
+else
+  cl_weights = [];
+end
+
+[ssz psz Q] = size(CPD.weights);
+
+[ss cpsz dpsz] = size(CPD.weights); % ss = self size = ssz
+if cpsz > CPD.nsamples
+  fprintf('gaussian_CPD/maximize_params: warning: input dimension (%d) > nsamples (%d)\n', ...
+	  cpsz, CPD.nsamples);
+end
+
+prior =  repmat(CPD.cov_prior_weight*eye(ssz,ssz), [1 1 Q]);
+
+
+[CPD.mean, CPD.cov, CPD.weights] = ...
+    clg_Mstep(CPD.Wsum, CPD.WYsum, CPD.WYYsum, [], CPD.WXsum, CPD.WXXsum, CPD.WXYsum, ...
+	      'cov_type', CPD.cov_type, 'clamped_mean', cl_mean, ...
+	      'clamped_cov', cl_cov, 'clamped_weights', cl_weights, ...
+	      'tied_cov', CPD.tied_cov, ...
+	      'cov_prior', prior);
+
+if 0
+CPD.mean = reshape(CPD.mean, [ss dpsz]);
+CPD.cov = reshape(CPD.cov, [ss ss dpsz]);
+CPD.weights = reshape(CPD.weights, [ss cpsz dpsz]);
+end
+
+% Bug fix 11 May 2003 KPM
+% clg_Mstep collapses all discrete parents into one mega-node
+% but convert_to_CPT needs access to each parent separately
+sz = CPD.sizes;
+ss = sz(end);
+
+% Bug fix KPM 20 May 2003: 
+cpsz = sum(sz(CPD.cps));
+%if isempty(CPD.cps)
+%  cpsz = 0;
+%else
+%  cpsz = sz(CPD.cps);
+%end
+dpsz = sz(CPD.dps);
+CPD.mean = myreshape(CPD.mean, [ss dpsz]);
+CPD.cov = myreshape(CPD.cov, [ss ss dpsz]);
+CPD.weights = myreshape(CPD.weights, [ss cpsz dpsz]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/maximize_params_debug.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,189 @@
+function CPD = maximize_params(CPD, temp)
+% MAXIMIZE_PARAMS Set the params of a CPD to their ML values (Gaussian)
+% CPD = maximize_params(CPD, temperature)
+%
+% Temperature is currently ignored.
+
+if ~adjustable_CPD(CPD), return; end
+
+CPD1 = struct(new_maximize_params(CPD));
+CPD2 = struct(old_maximize_params(CPD));
+assert(approxeq(CPD1.mean, CPD2.mean))
+assert(approxeq(CPD1.cov, CPD2.cov))
+assert(approxeq(CPD1.weights, CPD2.weights))
+
+CPD = new_maximize_params(CPD);
+
+%%%%%%%
+function CPD = new_maximize_params(CPD)
+
+if CPD.clamped_mean
+  cl_mean = CPD.mean;
+else
+  cl_mean = [];
+end
+
+if CPD.clamped_cov
+  cl_cov = CPD.cov;
+else
+  cl_cov = [];
+end
+
+if CPD.clamped_weights
+  cl_weights = CPD.weights;
+else
+  cl_weights = [];
+end
+
+[ssz psz Q] = size(CPD.weights);
+
+prior =  repmat(CPD.cov_prior_weight*eye(ssz,ssz), [1 1 Q]);
+[CPD.mean, CPD.cov, CPD.weights] = ...
+    Mstep_clg('w', CPD.Wsum, 'YY', CPD.WYYsum, 'Y', CPD.WYsum, 'YTY', [], ...
+	      'XX', CPD.WXXsum, 'XY', CPD.WXYsum, 'X', CPD.WXsum, ...
+	      'cov_type', CPD.cov_type, 'clamped_mean', cl_mean, ...
+	      'clamped_cov', cl_cov, 'clamped_weights', cl_weights, ...
+	      'tied_cov', CPD.tied_cov, ...
+	      'cov_prior', prior);
+
+
+%%%%%%%%%%%
+
+function CPD = old_maximize_params(CPD)
+
+
+if ~adjustable_CPD(CPD), return; end
+
+%assert(approxeq(CPD.nsamples, sum(CPD.Wsum)));
+assert(~any(isnan(CPD.WXXsum)))
+assert(~any(isnan(CPD.WXYsum)))
+assert(~any(isnan(CPD.WYYsum)))
+
+[self_size cpsize dpsize] = size(CPD.weights);
+
+% Append 1s to the parents, and derive the corresponding cross products.
+% This is used when estimate the means and weights simultaneosuly,
+% and when estimatting Sigma.
+% Let x2 = [x 1]'
+XY = zeros(cpsize+1, self_size, dpsize); % XY(:,:,i) = sum_l w(l,i) x2(l) y(l)' 
+XX = zeros(cpsize+1, cpsize+1, dpsize); % XX(:,:,i) = sum_l w(l,i) x2(l) x2(l)' 
+YY = zeros(self_size, self_size, dpsize); % YY(:,:,i) = sum_l w(l,i) y(l) y(l)' 
+for i=1:dpsize
+  XY(:,:,i) = [CPD.WXYsum(:,:,i) % X*Y
+	       CPD.WYsum(:,i)']; % 1*Y
+  % [x  * [x' 1]  = [xx' x
+  %  1]              x'  1]
+  XX(:,:,i) = [CPD.WXXsum(:,:,i) CPD.WXsum(:,i);
+	       CPD.WXsum(:,i)'   CPD.Wsum(i)];
+  YY(:,:,i) = CPD.WYYsum(:,:,i);
+end
+
+w = CPD.Wsum(:);
+% Set any zeros to one before dividing
+% This is valid because w(i)=0 => WYsum(:,i)=0, etc
+w = w + (w==0);
+
+if CPD.clamped_mean
+  % Estimating B2 and then setting the last column (the mean) to the clamped mean is *not* equivalent
+  % to estimating B and then adding the clamped_mean to the last column.
+  if ~CPD.clamped_weights
+    B = zeros(self_size, cpsize, dpsize);
+    for i=1:dpsize
+      if det(CPD.WXXsum(:,:,i))==0
+	B(:,:,i) = 0;
+      else
+	% Eqn 9 in table 2 of TR
+	%B(:,:,i) = CPD.WXYsum(:,:,i)' * inv(CPD.WXXsum(:,:,i));
+	B(:,:,i) = (CPD.WXXsum(:,:,i) \ CPD.WXYsum(:,:,i))';
+      end
+    end
+    %CPD.weights = reshape(B, [self_size cpsize dpsize]);
+    CPD.weights = B;
+  end
+elseif CPD.clamped_weights % KPM 1/25/02
+  if ~CPD.clamped_mean % ML estimate is just sample mean of the residuals
+    for i=1:dpsize
+      CPD.mean(:,i) = (CPD.WYsum(:,i) - CPD.weights(:,:,i) * CPD.WXsum(:,i)) / w(i);
+    end
+  end
+else % nothing is clamped, so estimate mean and weights simultaneously
+  B2 = zeros(self_size, cpsize+1, dpsize);
+  for i=1:dpsize
+    if det(XX(:,:,i))==0  % fix by U. Sondhauss 6/27/99
+      B2(:,:,i)=0;          
+    else                    
+      % Eqn 9 in table 2 of TR
+      %B2(:,:,i) = XY(:,:,i)' * inv(XX(:,:,i));
+      B2(:,:,i) = (XX(:,:,i) \ XY(:,:,i))';
+    end                   
+    CPD.mean(:,i) = B2(:,cpsize+1,i);
+    CPD.weights(:,:,i) = B2(:,1:cpsize,i);
+  end
+end
+
+% Let B2 = [W mu]
+if cpsize>0
+  B2(:,1:cpsize,:) = reshape(CPD.weights, [self_size cpsize dpsize]);
+end
+B2(:,cpsize+1,:) = reshape(CPD.mean, [self_size dpsize]);
+
+% To avoid singular covariance matrices,
+% we use the regularization method suggested in "A Quasi-Bayesian approach to estimating
+% parameters for mixtures of normal distributions", Hamilton 91.
+% If the ML estimate is Sigma = M/N, the MAP estimate is (M+gamma*I) / (N+gamma),
+% where gamma >=0 is a smoothing parameter (equivalent sample size of I prior)
+
+gamma = CPD.cov_prior_weight;
+
+if ~CPD.clamped_cov
+  if CPD.cov_prior_entropic % eqn 12 of Brand AI/Stat 99
+    Z = 1-temp;
+    % When temp > 1, Z is negative, so we are dividing by a smaller
+    % number, ie. increasing the variance.
+  else
+    Z = 0;
+  end
+  if CPD.tied_cov
+    S = zeros(self_size, self_size);
+    % Eqn 2 from table 2 in TR
+    for i=1:dpsize
+      S = S + (YY(:,:,i) - B2(:,:,i)*XY(:,:,i));
+    end
+    %denom = CPD.nsamples + gamma + Z;
+    denom = CPD.nsamples +  Z;
+    S = (S + gamma*eye(self_size)) / denom;
+    if strcmp(CPD.cov_type, 'diag')
+      S = diag(diag(S));
+    end
+    CPD.cov = repmat(S, [1 1 dpsize]);
+  else 
+    for i=1:dpsize      
+      % Eqn 1 from table 2 in TR
+      S = YY(:,:,i) - B2(:,:,i)*XY(:,:,i);
+      %denom = w(i) + gamma + Z;
+      denom = w(i) + Z;
+      S = (S + gamma*eye(self_size)) / denom;
+      CPD.cov(:,:,i) = S;
+    end
+    if strcmp(CPD.cov_type, 'diag')
+      for i=1:dpsize      
+	CPD.cov(:,:,i) = diag(diag(CPD.cov(:,:,i)));
+      end
+    end
+  end
+end
+
+
+check_covars = 0;
+min_covar = 1e-5;
+if check_covars % prevent collapsing to a point
+  for i=1:dpsize
+    if min(svd(CPD.cov(:,:,i))) < min_covar
+      disp(['resetting singular covariance for node ' num2str(CPD.self)]);
+      CPD.cov(:,:,i) = CPD.init_cov(:,:,i);
+    end
+  end
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/private/CPD_to_linear_gaussian.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function [mu, Sigma, W] = CPD_to_linear_gaussian(CPD, domain, ns, cnodes, evidence)
+
+ps = domain(1:end-1);
+dnodes = mysetdiff(1:length(ns), cnodes);
+dps = myintersect(ps, dnodes); % discrete parents
+
+if isempty(dps)
+  Q = 1;
+else
+  assert(~any(isemptycell(evidence(dps))));
+  dpvals = cat(1, evidence{dps});
+  Q = subv2ind(ns(dps), dpvals(:)');
+end
+
+mu = CPD.mean(:,Q);
+Sigma = CPD.cov(:,:,Q);
+W = CPD.weights(:,:,Q);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/CPD_to_linear_gaussian.m/1.1.1.1/Wed May 29 15:59:52 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@gaussian_CPD/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/reset_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function CPD = reset_ess(CPD)
+% RESET_ESS Reset the Expected Sufficient Statistics for a Gaussian CPD.
+% CPD = reset_ess(CPD)
+
+CPD.nsamples = 0;    
+CPD.Wsum = zeros(size(CPD.Wsum));
+CPD.WYsum = zeros(size(CPD.WYsum));
+CPD.WYYsum = zeros(size(CPD.WYYsum));
+CPD.WXsum = zeros(size(CPD.WXsum));
+CPD.WXXsum = zeros(size(CPD.WXXsum));
+CPD.WXYsum = zeros(size(CPD.WXYsum));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/sample_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function y = sample_node(CPD, pev)
+% SAMPLE_NODE Draw a random sample from P(Xi | x(pi_i), theta_i)  (gaussian)
+% y = sample_node(CPD, parent_evidence)
+%
+% pev{i} is the value of the i'th parent (if there are any parents)
+% y is the sampled value (a scalar or vector)
+
+if length(CPD.dps)==0
+  i = 1;
+else
+  dpvals = cat(1, pev{CPD.dps});
+  i = subv2ind(CPD.sizes(CPD.dps), dpvals(:)');
+end
+
+if length(CPD.cps) == 0 
+  y = gsamp(CPD.mean(:,i), CPD.cov(:,:,i), 1);
+else
+  pev = pev(:);
+  x = cat(1, pev{CPD.cps});
+  y = gsamp(CPD.mean(:,i) + CPD.weights(:,:,i)*x(:), CPD.cov(:,:,i), 1);
+end
+y = y(:);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/set_fields.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,43 @@
+function CPD = set_fields(CPD, varargin)
+% SET_PARAMS Set the parameters (fields) for a gaussian_CPD object
+% CPD = set_params(CPD, name/value pairs)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+%
+% mean       - mu(:,i) is the mean given Q=i
+% cov        - Sigma(:,:,i) is the covariance given Q=i 
+% weights    - W(:,:,i) is the regression matrix given Q=i 
+% cov_type   - if 'diag', Sigma(:,:,i) is diagonal 
+% tied_cov   - if 1, we constrain Sigma(:,:,i) to be the same for all i
+% clamp_mean - if 1, we do not adjust mu(:,i) during learning 
+% clamp_cov  - if 1, we do not adjust Sigma(:,:,i) during learning 
+% clamp_weights - if 1, we do not adjust W(:,:,i) during learning
+% clamp      - if 1, we do not adjust any params
+% cov_prior_weight - weight given to I prior for estimating Sigma
+% cov_prior_entropic - if 1, we also use an entropic prior for Sigma [0]
+%
+% e.g., CPD = set_params(CPD, 'mean', [0;0])
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'mean',        CPD.mean = args{i+1}; 
+   case 'cov',         CPD.cov = args{i+1}; 
+   case 'weights',     CPD.weights = args{i+1}; 
+   case 'cov_type',    CPD.cov_type = args{i+1}; 
+   %case 'tied_cov',    CPD.tied_cov = strcmp(args{i+1}, 'yes');
+   case 'tied_cov',    CPD.tied_cov = args{i+1};
+   case 'clamp_mean',  CPD.clamped_mean = args{i+1};
+   case 'clamp_cov',   CPD.clamped_cov = args{i+1};
+   case 'clamp_weights',  CPD.clamped_weights = args{i+1};
+   case 'clamp',  clamp = args{i+1};
+    CPD.clamped_mean = clamp;
+    CPD.clamped_cov = clamp;
+    CPD.clamped_weights = clamp;
+   case 'cov_prior_weight',  CPD.cov_prior_weight = args{i+1};
+   case 'cov_prior_entropic',  CPD.cov_prior_entropic = args{i+1};
+   otherwise,  
+    error(['invalid argument name ' args{i}]);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gaussian_CPD/update_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,88 @@
+function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+% UPDATE_ESS Update the Expected Sufficient Statistics of a Gaussian node
+% function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+
+%if nargin < 6
+%  hidden_bitv = zeros(1, max(fmarginal.domain));
+%  hidden_bitv(find(isempty(evidence)))=1;
+%end
+
+dom = fmarginal.domain;
+self = dom(end);
+ps = dom(1:end-1);
+cps = myintersect(ps, cnodes);
+dps = mysetdiff(ps, cps);
+
+CPD.nsamples = CPD.nsamples + 1;            
+[ss cpsz dpsz] = size(CPD.weights); % ss = self size
+[ss dpsz] = size(CPD.mean);
+
+% Let X be the cts parent (if any), Y be the cts child (self).
+
+if ~hidden_bitv(self) & ~any(hidden_bitv(cps)) & all(hidden_bitv(dps))
+  % Speedup for the common case that all cts nodes are observed, all discrete nodes are hidden
+  % Since X and Y are observed, SYY = 0, SXX = 0, SXY = 0
+  % Since discrete parents are hidden, we do not need to add evidence to w.
+  w = fmarginal.T(:);
+  CPD.Wsum = CPD.Wsum + w;
+  y = evidence{self};
+  Cyy = y*y';
+  if ~CPD.useC
+     WY = repmat(w(:)',ss,1); % WY(y,i) = w(i)
+     WYY = repmat(reshape(WY, [ss 1 dpsz]), [1 ss 1]); % WYY(y,y',i) = w(i)
+     %CPD.WYsum = CPD.WYsum +  WY .* repmat(y(:), 1, dpsz);
+     CPD.WYsum = CPD.WYsum +  y(:) * w(:)';
+     CPD.WYYsum = CPD.WYYsum + WYY  .* repmat(reshape(Cyy, [ss ss 1]), [1 1 dpsz]);
+  else
+     W = w(:)';
+     W2 = reshape(W, [1 1 dpsz]);
+     CPD.WYsum = CPD.WYsum +  rep_mult(W, y(:), size(CPD.WYsum)); 
+     CPD.WYYsum = CPD.WYYsum + rep_mult(W2, Cyy, size(CPD.WYYsum));
+  end
+  if cpsz > 0 % X exists
+    x = cat(1, evidence{cps}); x = x(:);
+    Cxx = x*x';
+    Cxy = x*y';
+    WX = repmat(w(:)',cpsz,1); % WX(x,i) = w(i)
+    WXX = repmat(reshape(WX, [cpsz 1 dpsz]), [1 cpsz 1]); % WXX(x,x',i) = w(i)
+    WXY = repmat(reshape(WX, [cpsz 1 dpsz]), [1 ss 1]); % WXY(x,y,i) = w(i)
+    if ~CPD.useC
+      CPD.WXsum = CPD.WXsum + WX .* repmat(x(:), 1, dpsz);
+      CPD.WXXsum = CPD.WXXsum + WXX .* repmat(reshape(Cxx, [cpsz cpsz 1]), [1 1 dpsz]);
+      CPD.WXYsum = CPD.WXYsum + WXY .* repmat(reshape(Cxy, [cpsz ss 1]), [1 1 dpsz]);
+    else
+      CPD.WXsum = CPD.WXsum + rep_mult(W, x(:), size(CPD.WXsum));
+      CPD.WXXsum = CPD.WXXsum + rep_mult(W2, Cxx, size(CPD.WXXsum));
+      CPD.WXYsum = CPD.WXYsum + rep_mult(W2, Cxy, size(CPD.WXYsum));
+    end
+  end
+  return;
+end
+
+% general (non-vectorized) case
+fullm = add_evidence_to_gmarginal(fmarginal, evidence, ns, cnodes); % slow!
+
+if dpsz == 1 % no discrete parents
+  w = 1;
+else
+  w = fullm.T(:);
+end
+
+CPD.Wsum = CPD.Wsum + w;
+xi = 1:cpsz;
+yi = (cpsz+1):(cpsz+ss);
+for i=1:dpsz
+  muY = fullm.mu(yi, i);
+  SYY = fullm.Sigma(yi, yi, i);
+  CPD.WYsum(:,i) = CPD.WYsum(:,i) + w(i)*muY;
+  CPD.WYYsum(:,:,i) = CPD.WYYsum(:,:,i) + w(i)*(SYY + muY*muY'); % E[X Y] = Cov[X,Y] + E[X] E[Y]
+  if cpsz > 0
+    muX = fullm.mu(xi, i);
+    SXX = fullm.Sigma(xi, xi, i);
+    SXY = fullm.Sigma(xi, yi, i);
+    CPD.WXsum(:,i) = CPD.WXsum(:,i) + w(i)*muX;
+    CPD.WXXsum(:,:,i) = CPD.WXXsum(:,:,i) + w(i)*(SXX + muX*muX');
+    CPD.WXYsum(:,:,i) = CPD.WXYsum(:,:,i) + w(i)*(SXY + muX*muY');
+  end
+end                
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+/README/1.1.1.1/Wed May 29 15:59:52 2002//
+/adjustable_CPD.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/display.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/generic_CPD.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/learn_params.m/1.1.1.1/Thu Jun 10 01:53:20 2004//
+/log_prior.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/set_clamped.m/1.1.1.1/Wed May 29 15:59:52 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@generic_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/Old/BIC_score_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function score = BIC_score_CPD(CPD, fam, data, ns, cnodes)
+% BIC_score_CPD Compute the BIC score of a generic CPD
+% score = BIC_score_CPD(CPD, fam, data, ns, cnodes)
+%
+% We assume this node has a maximize_params method
+
+ncases = size(data, 2);
+CPD = reset_ess(CPD);
+% make a fully observed joint distribution over the family
+fmarginal.domain = fam;
+fmarginal.T = 1;
+fmarginal.mu = [];
+fmarginal.Sigma = [];
+if ~iscell(data)
+  cases = num2cell(data);
+else
+  cases = data;
+end
+for m=1:ncases
+  CPD = update_ess(CPD, fmarginal, cases(:,m), ns, cnodes);
+end
+CPD = maximize_params(CPD);
+self = fam(end);
+ps = fam(1:end-1);
+L = log_prob_node(CPD, cases(self,:), cases(ps,:));
+score = L - 0.5*CPD.nparams*log(ncases);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/Old/CPD_to_dpots.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function pots = CPD_to_dpots(CPD, domain, ns, cnodes, evidence)
+% CPD_TO_DPOTS Convert the CPD to several discrete potentials, for different instantiations (generic)
+% pots = CPD_to_dpots(CPD, domain, ns, cnodes, evidence)
+%
+% domain(:,i) is the domain of the i'th instantiation of CPD.
+% node_sizes(i) is the size of node i.
+% cnodes = all the cts nodes
+% evidence{i} is the evidence on the i'th node.
+%
+% This just calls CPD_to_dpot for each domain.
+    
+nCPDs = size(domain,2);
+pots = cell(1,nCPDs);
+for i=1:nCPDs
+  pots{i} = CPD_to_dpot(CPD, domain(:,i), ns, cnodes, evidence);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+/BIC_score_CPD.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/CPD_to_dpots.m/1.1.1.1/Wed May 29 15:59:52 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@generic_CPD/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/README	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+A generic CPD implements general purpose functions like 'display',
+that subtypes can inherit.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/adjustable_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function p = adjustable_CPD(CPD)
+% ADJUSTABLE_CPD Does this CPD have any adjustable params? (generic)
+% p = adjustable_CPD(CPD)
+   
+p = ~CPD.clamped;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+function display(CPD)
+
+disp(struct(CPD));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/generic_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function CPD = generic_CPD(clamped)
+% GENERIC_CPD Virtual constructor for generic CPD
+% CPD = discrete_CPD(clamped)
+
+if nargin < 1, clamped = 0; end
+
+CPD.clamped = clamped;
+CPD = class(CPD, 'generic_CPD');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/learn_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function CPD = learn_params(CPD, fam, data, ns, cnodes)
+% LEARN_PARAMS Compute the maximum likelihood estimate of the params of a generic CPD given complete data
+% CPD = learn_params(CPD, fam, data, ns, cnodes)
+%
+% data(i,m) is the value of node i in case m (can be cell array).
+% We assume this node has a maximize_params method.
+
+%error('no longer supported') % KPM 1 Feb 03
+
+if 1
+ncases = size(data, 2);
+CPD = reset_ess(CPD);
+% make a fully observed joint distribution over the family
+fmarginal.domain = fam;
+fmarginal.T = 1;
+fmarginal.mu = [];
+fmarginal.Sigma = [];
+if ~iscell(data)
+  cases = num2cell(data);
+else
+  cases = data;
+end
+hidden_bitv = zeros(1, max(fam));
+for m=1:ncases
+  % specify (as a bit vector) which elements in the family domain are hidden
+  hidden_bitv = zeros(1, max(fmarginal.domain));
+  ev = cases(:,m);
+  hidden_bitv(find(isempty(evidence)))=1;
+  CPD = update_ess(CPD, fmarginal, ev, ns, cnodes, hidden_bitv);
+end
+CPD = maximize_params(CPD);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/log_prior.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function L = log_prior(CPD)
+% LOG_PRIOR Return log P(theta) for a generic CPD  - we return 0
+% L = log_prior(CPD)
+
+L = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@generic_CPD/set_clamped.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+function CPD = set_clamped(CPD, bit)
+
+CPD.clamped = bit;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/CPD_to_lambda_msg.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,62 @@
+function lam_msg = CPD_to_lambda_msg(CPD, msg_type, n, ps, msg, p, evidence)
+% CPD_TO_LAMBDA_MSG Compute lambda message (gmux)
+% lam_msg = compute_lambda_msg(CPD, msg_type, n, ps, msg, p, evidence)
+% Pearl p183 eq 4.52
+
+% Let Y be this node, X1..Xn be the cts parents and M the discrete switch node.
+% e.g., for n=3, M=1
+%
+%  X1 X2 X3 M
+%   \
+%    \
+%      Y
+%
+% So the only case in which we send an informative message is if p=1=M.
+% To the other cts parents, we send the "know nothing" message.
+
+switch msg_type
+ case 'd',
+  error('gaussian_CPD can''t create discrete msgs')
+ case 'g',
+  cps = ps(CPD.cps);
+  cpsizes = CPD.sizes(CPD.cps);
+  self_size = CPD.sizes(end);
+  i = find_equiv_posns(p, cps); % p is n's i'th cts parent
+  psz = cpsizes(i);
+  dps = ps(CPD.dps);
+  M = evidence{dps};
+  if isempty(M)
+    error('gmux node must have observed discrete parent')
+  end
+  P = msg{n}.lambda.precision;
+  if all(P == 0) | (cps(M) ~= p) % if we know nothing, or are sending to a disconnected parent
+    lam_msg.precision = zeros(psz, psz);
+    lam_msg.info_state = zeros(psz, 1);
+    return;
+  end
+  % We are sending a message to the only effectively connected parent.
+  % There are no other incoming pi messages.
+  Bmu = CPD.mean(:,M);
+  BSigma = CPD.cov(:,:,M);
+  Bi = CPD.weights(:,:,M);
+  if (det(P) > 0) | isinf(P) 
+    if isinf(P) % Y is observed
+      Sigma_lambda = zeros(self_size, self_size); % infinite precision => 0 variance
+      mu_lambda = msg{n}.lambda.mu; % observed_value;
+    else
+      Sigma_lambda = inv(P);
+      mu_lambda = Sigma_lambda * msg{n}.lambda.info_state;
+    end
+    C = inv(Sigma_lambda + BSigma);
+    lam_msg.precision = Bi' * C * Bi;
+    lam_msg.info_state = Bi' * C * (mu_lambda - Bmu);
+  else
+    % method that uses matrix inversion lemma
+    A = inv(P + inv(BSigma));
+    C = P - P*A*P;
+    lam_msg.precision = Bi' * C * Bi;
+    D = eye(self_size) - P*A;
+    z = msg{n}.lambda.info_state;
+    lam_msg.info_state = Bi' * (D*z - D*P*Bmu);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/CPD_to_pi.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function pi = CPD_to_pi(CPD, msg_type, n, ps, msg, evidence)
+% CPD_TO_PI Compute the pi vector (gaussian)
+% function pi = CPD_to_pi(CPD, msg_type, n, ps, msg, evidence)
+
+switch msg_type
+ case 'd',
+  error('gaussian_CPD can''t create discrete msgs')
+ case 'g',
+  dps = ps(CPD.dps);
+  k = evidence{dps};
+  if isempty(k)
+    error('gmux node must have observed discrete parent')
+  end
+  m = msg{n}.pi_from_parent{k}; 
+  B = CPD.weights(:,:,k);
+  pi.mu = CPD.mean(:,k) + B * m.mu;
+  pi.Sigma = CPD.cov(:,:,k) + B * m.Sigma * B';
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/CPD_to_lambda_msg.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/CPD_to_pi.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/convert_to_pot.m/1.1.1.1/Wed May 29 15:59:52 2002//
+/display.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/gmux_CPD.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/sample_node.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@gmux_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/gmux_CPD.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@gmux_CPD/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/Old/gmux_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,92 @@
+function CPD = gmux_CPD(bnet, self, varargin)
+% GMUX_CPD Make a Gaussian multiplexer node
+%
+% CPD = gmux_CPD(bnet, node, ...) is used similarly to gaussian_CPD,
+% except we assume there is exactly one discrete parent (call it M)
+% which is used to select which cts parent to pass through to the output.
+% i.e., we define P(Y=y|M=m, X1, ..., XK) = N(y | W*x(m) + mu, Sigma)
+% where Y represents this node, and the Xi's are the cts parents.
+% All the Xi must have the same size, and the num values for M must be K.
+%
+% Currently the params for this kind of CPD cannot be learned.
+%
+% Optional arguments [ default in brackets ]
+%
+% mean       - mu  [zeros(Y,1)]
+% cov        - Sigma [eye(Y,Y)]
+% weights    - W [ randn(Y,X) ]
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  clamp = 0;
+  CPD = class(CPD, 'gmux_CPD', generic_CPD(clamp));
+  return;
+elseif isa(bnet, 'gmux_CPD')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+CPD = init_fields;
+ 
+CPD = class(CPD, 'gmux_CPD', generic_CPD(1));
+
+ns = bnet.node_sizes;
+ps = parents(bnet.dag, self);
+dps = myintersect(ps, bnet.dnodes);
+cps = myintersect(ps, bnet.cnodes);
+fam_sz = ns([ps self]);
+
+CPD.self = self;
+CPD.sizes = fam_sz;
+
+% Figure out which (if any) of the parents are discrete, and which cts, and how big they are
+% dps = discrete parents, cps = cts parents
+CPD.cps = find_equiv_posns(cps, ps); % cts parent index
+CPD.dps = find_equiv_posns(dps, ps);
+if length(CPD.dps) ~= 1
+  error('gmux must have exactly 1 discrete parent')
+end
+ss = fam_sz(end);
+cpsz = fam_sz(CPD.cps(1)); % in gaussian_CPD, cpsz = sum(fam_sz(CPD.cps))
+if ~all(fam_sz(CPD.cps) == cpsz)
+  error('all cts parents must have same size')
+end
+dpsz = fam_sz(CPD.dps);
+if dpsz ~= length(cps)
+  error(['the arity of the mux node is ' num2str(dpsz) ...
+	 ' but there are ' num2str(length(cps)) ' cts parents']);
+end
+
+% set default params
+CPD.mean = zeros(ss, 1);
+CPD.cov = eye(ss);
+CPD.weights = randn(ss, cpsz);
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'mean',        CPD.mean = args{i+1}; 
+   case 'cov',         CPD.cov = args{i+1}; 
+   case 'weights',    CPD.weights = args{i+1}; 
+   otherwise,  
+    error(['invalid argument name ' args{i}]);
+  end
+end
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.self = [];
+CPD.sizes = [];
+CPD.cps = [];
+CPD.dps = [];
+CPD.mean = [];
+CPD.cov = [];
+CPD.weights = [];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/convert_to_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,37 @@
+function pot = convert_to_pot(CPD, pot_type, domain, evidence)
+% CONVERT_TO_POT Convert a gmux CPD to a Gaussian potential
+% pot = convert_to_pot(CPD, pot_type, domain, evidence)
+  
+switch pot_type
+ case {'d', 'u', 'cg', 'scg'},
+  error(['can''t convert gmux to potential of type ' pot_type])
+
+ case {'c','g'},
+  % We create a large weight matrix with zeros in all blocks corresponding
+  % to the non-chosen parents, since they are effectively disconnected.
+  % The chosen parent is determined by the value, m,  of the discrete parent.
+  % Thus the potential is as large as the whole family.
+  ps = domain(1:end-1);
+  dps = ps(CPD.dps); % CPD.dps is an index, not a node number (because of param tying)
+  cps = ps(CPD.cps);
+  m = evidence{dps};
+  if isempty(m)
+    error('gmux node must have observed discrete parent')
+  end
+  bs = CPD.sizes(CPD.cps);
+  b = block(m, bs);
+  sum_cpsz = sum(CPD.sizes(CPD.cps));
+  selfsz = CPD.sizes(end);
+  W = zeros(selfsz, sum_cpsz);
+  W(:,b) = CPD.weights(:,:,m);
+
+  ns = zeros(1, max(domain));
+  ns(domain) = CPD.sizes;
+  self = domain(end);
+  cdom = [cps(:)' self];
+  pot = linear_gaussian_to_cpot(CPD.mean(:,m), CPD.cov(:,:,m), W, domain, ns, cdom, evidence);
+  
+ otherwise,
+  error(['unrecognized pot_type' pot_type])
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function display(CPD)
+
+disp('gmux_CPD object');
+disp(struct(CPD));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/gmux_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,95 @@
+function CPD = gmux_CPD(bnet, self, varargin)
+% GMUX_CPD Make a Gaussian multiplexer node
+%
+% CPD = gmux_CPD(bnet, node, ...) is used similarly to gaussian_CPD,
+% except we assume there is exactly one discrete parent (call it M)
+% which is used to select which cts parent to pass through to the output.
+% i.e., we define P(Y=y|M=m, X1, ..., XK) = N(y | W(m)*x(m) + mu(m), Sigma(m))
+% where Y represents this node, and the Xi's are the cts parents.
+% All the Xi must have the same size, and the num values for M must be K.
+%
+% Currently the params for this kind of CPD cannot be learned.
+%
+% Optional arguments [ default in brackets ]
+%
+% mean       - mu(:,i) is the mean given M=i [ zeros(Y,K) ]
+% cov        - Sigma(:,:,i) is the covariance given M=i [ repmat(1*eye(Y,Y), [1 1 K]) ]
+% weights    - W(:,:,i) is the regression matrix given M=i [ randn(Y,X,K) ]
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  clamp = 0;
+  CPD = class(CPD, 'gmux_CPD', generic_CPD(clamp));
+  return;
+elseif isa(bnet, 'gmux_CPD')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+CPD = init_fields;
+ 
+CPD = class(CPD, 'gmux_CPD', generic_CPD(1));
+
+ns = bnet.node_sizes;
+ps = parents(bnet.dag, self);
+dps = myintersect(ps, bnet.dnodes);
+cps = myintersect(ps, bnet.cnodes);
+fam_sz = ns([ps self]);
+
+CPD.self = self;
+CPD.sizes = fam_sz;
+
+% Figure out which (if any) of the parents are discrete, and which cts, and how big they are
+% dps = discrete parents, cps = cts parents
+CPD.cps = find_equiv_posns(cps, ps); % cts parent index
+CPD.dps = find_equiv_posns(dps, ps);
+if length(CPD.dps) ~= 1
+  error('gmux must have exactly 1 discrete parent')
+end
+ss = fam_sz(end);
+cpsz = fam_sz(CPD.cps(1)); % in gaussian_CPD, cpsz = sum(fam_sz(CPD.cps))
+if ~all(fam_sz(CPD.cps) == cpsz)
+  error('all cts parents must have same size')
+end
+dpsz = fam_sz(CPD.dps);
+if dpsz ~= length(cps)
+  error(['the arity of the mux node is ' num2str(dpsz) ...
+	 ' but there are ' num2str(length(cps)) ' cts parents']);
+end
+
+% set default params
+%CPD.mean = zeros(ss, 1);
+%CPD.cov = eye(ss);
+%CPD.weights = randn(ss, cpsz);
+CPD.mean = zeros(ss, dpsz);
+CPD.cov = 1*repmat(eye(ss), [1 1 dpsz]);    
+CPD.weights = randn(ss, cpsz, dpsz);
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'mean',        CPD.mean = args{i+1}; 
+   case 'cov',         CPD.cov = args{i+1}; 
+   case 'weights',    CPD.weights = args{i+1}; 
+   otherwise,  
+    error(['invalid argument name ' args{i}]);
+  end
+end
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.self = [];
+CPD.sizes = [];
+CPD.cps = [];
+CPD.dps = [];
+CPD.mean = [];
+CPD.cov = [];
+CPD.weights = [];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@gmux_CPD/sample_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function y = sample_node(CPD, pev)
+% SAMPLE_NODE Draw a random sample from P(Xi | x(pi_i), theta_i)  (gmux)
+% y = sample_node(CPD, parent_evidence)
+%
+% parent_ev{i} is the value of the i'th parent
+
+dpval = pev{CPD.dps};
+x = pev{CPD.cps(dpval)};
+y = gsamp(CPD.mean(:,dpval) + CPD.weights(:,:,dpval)*x(:), CPD.cov(:,:,dpval), 1);
+y = y(:);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmm2Q_CPD/CPD_to_CPT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,35 @@
+function CPT = CPD_to_CPT(CPD)
+% Compute the big CPT for an HHMM Q node (including F parents)
+% by combining internal transprob and startprob
+% function CPT = CPD_to_CPT(CPD)
+
+Qsz = CPD.Qsz;
+
+if ~isempty(CPD.Fbelow_ndx)
+  if ~isempty(CPD.Fself_ndx) % general case
+    error('not implemented')
+  else % no F from self, hence no startprob (top level)
+    nps = length(CPD.dom_sz)-1; % num parents
+    CPT = 0*myones(CPD.dom_sz);
+    % when Fself=1, the CPT(i,j) = delta(i,j) for all k
+    for k=1:prod(CPD.Qpsizes)
+      Qps_vals = ind2subv(CPD.Qpsizes, k);
+      ndx = mk_multi_index(nps+1, [CPD.Fbelow_ndx CPD.Qps_ndx], [1 Qps_vals]);
+      CPT(ndx{:}) = eye(Qsz); % CPT(:,2,k,:) or CPT(:,k,2,:) etc
+    end
+    ndx = mk_multi_index(nps+1, CPD.Fbelow_ndx, 2);
+    CPT(ndx{:}) = CPD.transprob; % we assume transprob is in topo order
+  end
+else % no F signal from below
+  if ~isempty(CPD.Fself_ndx) % bottom level
+    nps = length(CPD.dom_sz)-1; % num parents
+    CPT = 0*myones(CPD.dom_sz);
+    ndx = mk_multi_index(nps+1, CPD.Fself_ndx, 1);
+    CPT(ndx{:}) = CPD.transprob;
+    ndx = mk_multi_index(nps+1, CPD.Fself_ndx, 2);
+    CPT(ndx{:}) = CPD.startprob;
+  else % no F from self
+    error('An hhmmQ node without any F parents is just a tabular_CPD')
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmm2Q_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/CPD_to_CPT.m/1.1.1.1/Tue Sep 24 12:46:46 2002//
+/hhmm2Q_CPD.m/1.1.1.1/Tue Sep 24 22:34:40 2002//
+/maximize_params.m/1.1.1.1/Tue Sep 24 22:44:36 2002//
+/reset_ess.m/1.1.1.1/Tue Sep 24 22:36:16 2002//
+/update_ess.m/1.1.1.1/Tue Sep 24 22:43:30 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmm2Q_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@hhmm2Q_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmm2Q_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmm2Q_CPD/hhmm2Q_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,65 @@
+function CPD = hhmm2Q_CPD(bnet, self, varargin)
+% HHMMQ_CPD Make the CPD for a Q node in a 2 level hierarchical HMM
+% CPD = hhmmQ_CPD(bnet, self, ...)
+%
+%  Fself(t-1)   Qps
+%           \    |
+%            \   v
+%  Qold(t-1) ->  Q(t)
+%            /
+%           /
+%  Fbelow(t-1) 
+%
+%
+% optional args [defaults]
+%
+% Fself - node number <= ss
+% Fbelow  - node number  <= ss
+% Qps - node numbers (all <= 2*ss) - uses 2TBN indexing
+% transprob - CPT for when Fbelow=2 and Fself=1
+% startprob - CPT for when Fbelow=2 and Fself=2
+% If Fbelow=1, we cannot change state.
+
+ss = bnet.nnodes_per_slice;
+ns = bnet.node_sizes(:);
+
+% set default arguments
+Fself = [];
+Fbelow = [];
+Qps = [];
+startprob = [];
+transprob = [];
+
+for i=1:2:length(varargin)
+  switch varargin{i},
+   case 'Fself', Fself = varargin{i+1};
+   case 'Fbelow', Fbelow = varargin{i+1};
+   case 'Qps', Qps = varargin{i+1};
+   case 'transprob', transprob = varargin{i+1}; 
+   case 'startprob',  startprob = varargin{i+1}; 
+  end
+end
+
+ps = parents(bnet.dag, self);
+old_self = self-ss;
+ndsz = ns(:)';
+CPD.dom_sz = [ndsz(ps) ns(self)];
+CPD.Fself_ndx = find_equiv_posns(Fself, ps);
+CPD.Fbelow_ndx = find_equiv_posns(Fbelow, ps);
+Qps = mysetdiff(ps, [Fself Fbelow old_self]);
+CPD.Qps_ndx = find_equiv_posns(Qps, ps);
+CPD.old_self_ndx = find_equiv_posns(old_self, ps);
+
+Qps = ps(CPD.Qps_ndx);
+CPD.Qsz = ns(self);
+CPD.Qpsizes = ns(Qps);
+
+CPD.transprob = transprob;
+CPD.startprob = startprob;
+CPD.start_counts = [];
+CPD.trans_counts = [];
+
+CPD = class(CPD, 'hhmm2Q_CPD', discrete_CPD(0, CPD.dom_sz));
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmm2Q_CPD/maximize_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function CPD = maximize_params(CPD, temp)
+% MAXIMIZE_PARAMS Set the params of a hhmmQ node to their ML/MAP values.
+% CPD = maximize_params(CPD, temperature)
+
+if sum(CPD.start_counts(:)) > 0
+  CPD.startprob = mk_stochastic(CPD.start_counts);
+end
+if sum(CPD.trans_counts(:)) > 0
+  CPD.transprob = mk_stochastic(CPD.trans_counts);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmm2Q_CPD/reset_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function CPD = reset_ess(CPD)
+% RESET_ESS Reset the Expected Sufficient Statistics of a hhmm2 Q node.
+% CPD = reset_ess(CPD)
+
+domsz = CPD.dom_sz;
+domsz(CPD.Fself_ndx) = 1;
+domsz(CPD.Fbelow_ndx) = 1;
+Qdom_sz = domsz;
+Qdom_sz(Qdom_sz==1)=[]; % get rid of dimensions of size 1
+
+CPD.start_counts = zeros(Qdom_sz);
+CPD.trans_counts = zeros(Qdom_sz);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmm2Q_CPD/update_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+
+marg = add_ev_to_dmarginal(fmarginal, evidence,  ns);
+
+nps = length(CPD.dom_sz)-1; % num parents
+
+if ~isempty(CPD.Fbelow_ndx)
+  if ~isempty(CPD.Fself_ndx) % general case
+    ndx = mk_multi_index(nps+1, [CPD.Fbelow_ndx CPD.Fself_ndx], [2 1]);
+    CPD.trans_counts = CPD.trans_counts + squeeze(marg.T(ndx{:}));
+    ndx = mk_multi_index(nps+1, [CPD.Fbelow_ndx CPD.Fself_ndx], [2 2]);
+    CPD.start_counts = CPD.start_counts + squeeze(marg.T(ndx{:}));
+  else % no F from self, hence no startprob (top level)
+    ndx = mk_multi_index(nps+1, CPD.Fbelow_ndx, 2);
+    CPD.trans_counts = CPD.trans_counts + squeeze(marg.T(ndx{:}));
+  end
+else % no F signal from below
+  if ~isempty(CPD.Fself_ndx) % self F (bottom level)
+    ndx = mk_multi_index(nps+1, CPD.Fself_ndx, 1);
+    CPD.trans_counts = CPD.trans_counts + squeeze(marg.T(ndx{:}));
+    ndx = mk_multi_index(nps+1, CPD.Fself_ndx, 2);
+    CPD.start_counts = CPD.start_counts + squeeze(marg.T(ndx{:}));
+  else % no F from self or below
+    error('no F signal')
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/hhmmF_CPD.m/1.1.1.1/Mon Jun 24 23:38:24 2002//
+/log_prior.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/maximize_params.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/reset_ess.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/update_CPT.m/1.1.1.1/Mon Jun 24 22:45:04 2002//
+/update_ess.m/1.1.1.1/Mon Jun 24 23:54:30 2002//
+D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@hhmmF_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/hhmmF_CPD.m/1.1.1.1/Mon Jun 24 22:35:06 2002//
+/log_prior.m/1.1.1.1/Mon Jun 24 22:35:06 2002//
+/maximize_params.m/1.1.1.1/Mon Jun 24 22:35:06 2002//
+/reset_ess.m/1.1.1.1/Mon Jun 24 22:35:06 2002//
+/update_CPT.m/1.1.1.1/Mon Jun 24 22:35:06 2002//
+/update_ess.m/1.1.1.1/Mon Jun 24 22:35:06 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@hhmmF_CPD/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/Old/hhmmF_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,76 @@
+function CPD = hhmmF_CPD(bnet, self, Qnodes, d, D, varargin)
+% HHMMF_CPD Make the CPD for an F node at depth D of a D-level hierarchical HMM
+% CPD = hhmmF_CPD(bnet, self, Qnodes, d, D, ...)
+%
+%    Q(d-1)
+%          \
+%           \
+%           F(d)
+%         /   |
+%        /    |
+%    Q(d)  F(d+1)
+%
+% We assume nodes are ordered (numbered) as follows:
+% Q(1), ... Q(d), F(d+1), F(d)
+%
+% F(d)=2 means level d has finished. The prob this happens depends on Q(d)
+% and optionally on Q(d-1), Q(d=1), ..., Q(1).
+% Also, level d can only finish if the level below has finished
+% (hence the F(d+1) -> F(d) arc).
+%
+% If d=D, there is no F(d+1), so F(d) is just a regular tabular_CPD.
+% If all models always finish in the same state (e.g., their last),
+% we don't need to condition on the state of parent models (Q(d-1), ...)
+%
+% optional args [defaults]
+%
+% termprob - termprob(k,i,2) = prob finishing given Q(d)=i and Q(1:d-1)=k [ finish in last state ]
+%
+% hhmmF_CPD is a subclass of tabular_CPD so we inherit inference methods like CPD_to_pot, etc.
+%
+% We create an isolated tabular_CPD with no F parent to learn termprob
+% so we can avail of e.g., entropic or Dirichlet priors.
+%
+% For details, see "Linear-time inference in hierarchical HMMs", Murphy and Paskin, NIPS'01.
+
+
+ps = parents(bnet.dag, self);
+Qps = myintersect(ps, Qnodes);
+F = mysetdiff(ps, Qps);
+CPD.Q = Qps(end); % Q(d)
+assert(CPD.Q == Qnodes(d));
+CPD.Qps = Qps(1:end-1); % all Q parents except Q(d), i.e., calling context
+
+ns = bnet.node_sizes(:);
+CPD.Qsizes = ns(Qnodes);
+CPD.d = d;
+CPD.D = D;
+
+Qsz = ns(CPD.Q);
+Qpsz = prod(ns(CPD.Qps));
+
+% set default arguments
+p = 0.9;
+%termprob(k,i,t) Might terminate if i=Qsz; will not terminate if i<Qsz
+termprob = zeros(Qpsz, Qsz, 2);
+termprob(:, Qsz, 2) = p; 
+termprob(:, Qsz, 1) = 1-p; 
+termprob(:, 1:(Qsz-1), 1) = 1; 
+    
+for i=1:2:length(varargin)
+  switch varargin{i},
+   case 'termprob', termprob = varargin{i+1}; 
+   otherwise, error(['unrecognized argument ' varargin{i}])
+  end
+end
+
+ps = [CPD.Qps CPD.Q];
+% ns(self) = 2 since this is an F node
+CPD.sub_CPD_term = mk_isolated_tabular_CPD(ps, ns([ps self]), {'CPT', termprob});
+S = struct(CPD.sub_CPD_term);
+CPD.termprob = S.CPT;
+
+CPD = class(CPD, 'hhmmF_CPD', tabular_CPD(bnet, self));
+
+CPD = update_CPT(CPD);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/Old/log_prior.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function L = log_prior(CPD)
+% LOG_PRIOR Return log P(theta) for a hhmm F CPD 
+% L = log_prior(CPD)
+
+L = log_prior(CPD.sub_CPD_term);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/Old/maximize_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function CPD = maximize_params(CPD, temp)
+% MAXIMIZE_PARAMS Set the params of a hhmmF node to their ML/MAP values.
+% CPD = maximize_params(CPD, temperature)
+
+CPD.sub_CPD_term = maximize_params(CPD.sub_CPD_term, temp);
+S = struct(CPD.sub_CPD_term);
+CPD.termprob = S.CPT;
+
+CPD = update_CPT(CPD);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/Old/reset_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function CPD = reset_ess(CPD)
+% RESET_ESS Reset the Expected Sufficient Statistics of a hhmm F node.
+% CPD = reset_ess(CPD)
+
+CPD.sub_CPD_term = reset_ess(CPD.sub_CPD_term);   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/Old/update_CPT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function CPD = update_CPT(CPD)
+% Compute the big CPT for an HHMM F node given internal termprob
+% function CPD = update_CPT(CPD)
+
+Qsz = CPD.Qsizes(CPD.Q);
+Qpsz = prod(CPD.Qsizes(CPD.Qps));
+
+% P(Q(1:d-1), Q(d), F(d+1), F(d))
+CPT = zeros(Qpsz, Qsz, 2, 2);
+CPT(:,:,1,1) = 1; % if F(d+1)=1, then F(d)=1
+CPT(:,:,2,:) = CPD.termprob;
+
+CPD = set_fields(CPD, 'CPT', CPT);          
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/Old/update_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,61 @@
+function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+% UPDATE_ESS Update the Expected Sufficient Statistics of a hhmmF node.
+% function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+
+% Figure out the node numbers associated with each parent
+% so we extract evidence from the right place
+dom = fmarginal.domain; % Q(1) .. Q(d) F(d+1) F(d)
+Qps = fmarginal.domain(1:end-2);
+Q = Qps(end);
+Qps = Qps(1:end-1);
+
+Qsz = CPD.Qsizes(CPD.Q);
+Qpsz = prod(CPD.Qsizes(CPD.Qps)); % may be 1
+
+% We assume the F node are always hidden, but allow some of the Q nodes
+% to be observed. We do case analysis for speed.
+%We only extract prob from fmarginal.T when F(d+1)=2 i.e., model below has finished.
+% wrong -> % We sum over the possibilities that F(d+1) = 1 or 2
+
+obs_self = ~hidden_bitv(Q);
+if obs_self
+  self_val = evidence{Q};
+end
+
+if isempty(Qps) % independent of parent context
+  counts = zeros(Qsz, 2);
+  %fmarginal.T(Q(d), F(d+1), F(d))
+  if obs_self
+    marg = myreshape(fmarginal.T, [1 2 2]);
+    counts(self_val,:) = marg(1,2,:);
+    %counts(self_val,:) = marg(1,1,:) + marg(1,2,:);
+  else
+    marg = myreshape(fmarginal.T, [Qsz 2 2]);
+    counts = squeeze(marg(:,2,:));
+    %counts = squeeze(marg(:,2,:)) + squeeze(marg(:,1,:));
+  end
+else
+  counts = zeros(Qpsz, Qsz, 2);
+  %fmarginal.T(Q(1:d-1), Q(d), F(d+1), F(d))
+  obs_Qps = ~any(hidden_bitv(Qps));  % we assume that all or none of the Q  parents are observed
+  if obs_Qps
+    Qps_val = subv2ind(Qpsz, cat(1, evidence{Qps}));
+  end
+  if obs_self & obs_Qps
+    marg = myreshape(fmarginal.T, [1 1 2 2]);
+    counts(Qps_val, self_val, :) = squeeze(marg(1,1,2,:));
+    %counts(Qps_val, self_val, :) = squeeze(marg(1,1,2,:)) + squeeze(marg(1,1,1,:));
+  elseif ~obs_self & obs_Qps
+    marg = myreshape(fmarginal.T, [1 Qsz 2 2]);
+    counts(Qps_val, :, :) = squeeze(marg(1,:,2,:));
+    %counts(Qps_val, :, :) = squeeze(marg(1,:,2,:)) + squeeze(marg(1,:,1,:));
+  elseif obs_self & ~obs_Qps
+    error('not yet implemented')
+  else
+    marg = myreshape(fmarginal.T, [Qpsz Qsz 2 2]);
+    counts(:, :, :) = squeeze(marg(:,:,2,:));
+    %counts(:, :, :) = squeeze(marg(:,:,2,:)) + squeeze(marg(:,:,1,:));
+  end    
+end
+
+CPD.sub_CPD_term = update_ess_simple(CPD.sub_CPD_term, counts);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/hhmmF_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,73 @@
+function CPD = hhmmF_CPD(bnet, self, Qself, Fbelow, varargin)
+% HHMMF_CPD Make the CPD for an F node in a hierarchical HMM
+% CPD = hhmmF_CPD(bnet, self, Qself,  Fbelow, ...)
+%
+%        Qps
+%          \
+%           \
+%           Fself
+%         /   |
+%        /    |
+%       Qself Fbelow
+%
+% We assume nodes are ordered (numbered) as follows: Qps, Q, Fbelow, F
+% All nodes numbers should be from slice 1.
+%
+% If Fbelow if missing, this becomes a regular tabular_CPD.
+% Qps may be omitted.
+%
+% optional args [defaults]
+% 
+% Qps - node numbers.
+% termprob - termprob(k,i,2) = prob finishing given Q(d)=i and Q(1:d-1)=k [ finish in last state wp 0.9]
+%
+% hhmmF_CPD is a subclass of tabular_CPD so we inherit inference methods like CPD_to_pot, etc.
+%
+% We create an isolated tabular_CPD with no F parent to learn termprob
+% so we can avail of e.g., entropic or Dirichlet priors.
+%
+% For details, see "Linear-time inference in hierarchical HMMs", Murphy and Paskin, NIPS'01.
+
+
+
+Qps = [];
+% get parents
+for i=1:2:length(varargin)
+  switch varargin{i},
+   case 'Qps', Qps = varargin{i+1}; 
+  end
+end
+
+ns = bnet.node_sizes(:);
+Qsz = ns(Qself);
+Qpsz = prod(ns(Qps));
+CPD.Qsz = Qsz;
+CPD.Qpsz = Qpsz;
+
+ps = parents(bnet.dag, self);
+CPD.Fbelow_ndx = find_equiv_posns(Fbelow, ps);
+CPD.Qps_ndx = find_equiv_posns(Qps, ps);
+CPD.Qself_ndx = find_equiv_posns(Qself, ps);
+
+% set default arguments
+p = 0.9;
+%termprob(k,i,t) Might terminate if i=Qsz; will not terminate if i<Qsz
+termprob = zeros(Qpsz, Qsz, 2);
+termprob(:, Qsz, 2) = p; 
+termprob(:, Qsz, 1) = 1-p; 
+termprob(:, 1:(Qsz-1), 1) = 1; 
+    
+for i=1:2:length(varargin)
+  switch varargin{i},
+   case 'termprob', termprob = varargin{i+1}; 
+  end
+end
+
+CPD.sub_CPD_term = mk_isolated_tabular_CPD([Qpsz Qsz 2], {'CPT', termprob});
+S = struct(CPD.sub_CPD_term);
+CPD.termprob = S.CPT;
+
+CPD = class(CPD, 'hhmmF_CPD', tabular_CPD(bnet, self));
+
+CPD = update_CPT(CPD);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/log_prior.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function L = log_prior(CPD)
+% LOG_PRIOR Return log P(theta) for a hhmm F CPD 
+% L = log_prior(CPD)
+
+L = log_prior(CPD.sub_CPD_term);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/maximize_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function CPD = maximize_params(CPD, temp)
+% MAXIMIZE_PARAMS Set the params of a hhmmF node to their ML/MAP values.
+% CPD = maximize_params(CPD, temperature)
+
+CPD.sub_CPD_term = maximize_params(CPD.sub_CPD_term, temp);
+S = struct(CPD.sub_CPD_term);
+CPD.termprob = S.CPT;
+
+CPD = update_CPT(CPD);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/reset_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function CPD = reset_ess(CPD)
+% RESET_ESS Reset the Expected Sufficient Statistics of a hhmm F node.
+% CPD = reset_ess(CPD)
+
+CPD.sub_CPD_term = reset_ess(CPD.sub_CPD_term);   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/update_CPT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function CPD = update_CPT(CPD)
+% Compute the big CPT for an HHMM F node given internal termprob
+% function CPD = update_CPT(CPD)
+
+Qsz = CPD.Qsz;
+Qpsz = CPD.Qpsz;
+
+% CPT(Qpsz, Q, Fbelow, Fself)
+CPT = zeros(Qpsz, Qsz, 2, 2);
+CPT(:,:,1,1) = 1; % if Fbelow=1 (off), then Fself=1 (off)
+CPT(:,:,2,:) = CPD.termprob;
+
+CPD = set_fields(CPD, 'CPT', CPT);          
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmF_CPD/update_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+% UPDATE_ESS Update the Expected Sufficient Statistics of a hhmmF node.
+% function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+%
+% We assume the F nodes are always hidden
+
+% Figure out the node numbers associated with each parent
+dom = fmarginal.domain;
+%Fself = dom(end); 
+%Fbelow = dom(CPD.Fbelow_ndx);
+Qself = dom(CPD.Qself_ndx);
+Qps = dom(CPD.Qps_ndx);
+
+Qsz = CPD.Qsz;
+Qpsz = CPD.Qpsz;
+
+if all(hidden_bitv(Qps)) % we assume all are hidden or all are observed
+  k_ndx = 1:Qpsz;
+  eff_Qpsz = Qpsz;
+else
+  k_ndx = subv2ind(Qpsz, cat(1, evidence{Qps}));
+  eff_Qpsz = 1;
+end
+
+if hidden_bitv(Qself)
+  j_ndx = 1:Qsz;
+  eff_Qsz = Qsz;
+else
+  j_ndx = evidence{Qself};
+  eff_Qsz = 1;
+end
+
+% Fmarginal(Qps, Q, Fbelow, F)
+fmarg = myreshape(fmarginal.T, [eff_Qpsz eff_Qsz  2 2]);
+
+counts = zeros(Qpsz, Qsz, 2);
+%counts(k_ndx, j_ndx, :) = sum(fmarginal.T(:, :, :, :), 3); % sum over Fbelow
+counts(k_ndx, j_ndx, :) = fmarg(:, :, 2, :); % Fbelow = 2
+
+CPD.sub_CPD_term = update_ess_simple(CPD.sub_CPD_term, counts);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/hhmmQ_CPD.m/1.1.1.1/Tue Sep 24 04:19:26 2002//
+/log_prior.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/maximize_params.m/1.1.1.1/Tue Sep 24 13:10:18 2002//
+/reset_ess.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/update_CPT.m/1.1.1.1/Tue Sep 24 02:58:18 2002//
+/update_ess.m/1.1.1.1/Thu Jul 24 13:41:34 2003//
+D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@hhmmQ_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+/hhmmQ_CPD.m/1.1.1.1/Mon Jun 24 18:19:00 2002//
+/log_prior.m/1.1.1.1/Mon Jun 24 18:19:00 2002//
+/maximize_params.m/1.1.1.1/Mon Jun 24 18:19:00 2002//
+/reset_ess.m/1.1.1.1/Mon Jun 24 18:19:00 2002//
+/update_CPT.m/1.1.1.1/Tue Sep 24 02:30:32 2002//
+/update_ess.m/1.1.1.1/Mon Jun 24 18:19:00 2002//
+/update_ess2.m/1.1.1.1/Mon Jun 24 21:20:52 2002//
+/update_ess3.m/1.1.1.1/Mon Jun 24 22:08:08 2002//
+/update_ess4.m/1.1.1.1/Mon Jun 24 22:23:32 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@hhmmQ_CPD/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/hhmmQ_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,126 @@
+function CPD = hhmmQ_CPD(bnet, self, Qnodes, d, D, varargin)
+% HHMMQ_CPD Make the CPD for a Q node at depth D of a D-level hierarchical HMM
+% CPD = hhmmQ_CPD(bnet, self, Qnodes, d, D, ...)
+%
+%  Fd(t-1) \   Q1:d-1(t)
+%           \  |
+%            \ v
+%  Qd(t-1) -> Qd(t)
+%            /
+%           /
+%  Fd+1(t-1) 
+%
+% We assume parents are ordered (numbered) as follows:
+% Qd(t-1), Fd+1(t-1), Fd(t-1), Q1(t), ..., Qd(t)
+%
+% The parents of Qd(t) can either be just Qd-1(t) or the whole stack Q1:d-1(t) (allQ)
+% In either case, we will call them Qps.
+% If d=1, Qps does not exist. Also, the F1(t-1) -> Q1(t) arc is optional.
+% If the arc is missing, startprob does not need to be specified,
+% since the toplevel is assumed to never reset (F1 does not exist).
+% If d=D, Fd+1(t-1) does not exist (there is no signal from below).
+%
+% optional args [defaults]
+%
+% transprob - transprob(i,k,j) = prob transition from i to j given Qps = k ['leftright']
+% selfprob  - prob of a transition from i to i given Qps=k [0.1]
+% startprob - startprob(k,j) = prob start in j given Qps = k ['leftstart']
+% startargs - other args to be passed to the sub tabular_CPD for learning startprob
+% transargs - other args will be passed to the sub tabular_CPD for learning transprob
+% allQ      - 1 means use all Q nodes above d as parents, 0 means just level d-1 [0]
+% F1toQ1    - 1 means add F1(t-1) -> Q1(t) arc, 0 means level 1 never resets [0]
+%
+% For d=1, startprob(1,j) is only needed if F1toQ1=1
+% Also, transprob(i,j) can be used instead of transprob(i,1,j).
+%
+% hhmmQ_CPD is a subclass of tabular_CPD so we inherit inference methods like CPD_to_pot, etc.
+%
+% We create isolated tabular_CPDs with no F parents to learn transprob/startprob
+% so we can avail of e.g., entropic or Dirichlet priors.
+% In the future, we will be able to represent the transprob using a tree_CPD.
+%
+% For details, see "Linear-time inference in hierarchical HMMs", Murphy and Paskin, NIPS'01.
+
+
+ss = bnet.nnodes_per_slice;
+%assert(self == Qnodes(d)+ss);
+ns = bnet.node_sizes(:);
+CPD.Qsizes = ns(Qnodes);
+CPD.d = d;
+CPD.D = D;
+allQ = 0;
+
+% find out which parents to use, to get right size
+for i=1:2:length(varargin)
+  switch varargin{i},
+   case 'allQ', allQ = varargin{i+1}; 
+  end
+end
+
+if d==1
+  CPD.Qps = [];
+else
+  if allQ
+    CPD.Qps = Qnodes(1:d-1);
+  else
+    CPD.Qps = Qnodes(d-1);
+  end
+end
+
+Qsz = ns(self);
+Qpsz = prod(ns(CPD.Qps));
+
+% set default arguments
+startprob = 'leftstart';
+transprob = 'leftright';
+startargs = {};
+transargs = {};
+CPD.F1toQ1 = 0;
+selfprob = 0.1;
+
+for i=1:2:length(varargin)
+  switch varargin{i},
+   case 'transprob', transprob = varargin{i+1}; 
+   case 'selfprob',  selfprob = varargin{i+1}; 
+   case 'startprob', startprob = varargin{i+1}; 
+   case 'startargs', startargs = varargin{i+1}; 
+   case 'transargs', transargs = varargin{i+1}; 
+   case 'F1toQ1',    CPD.F1toQ1 = varargin{i+1}; 
+  end
+end
+
+Qps = CPD.Qps + ss;
+old_self = self-ss;
+
+if strcmp(transprob, 'leftright')
+  LR = mk_leftright_transmat(Qsz, selfprob);
+  transprob = repmat(reshape(LR, [1 Qsz Qsz]), [Qpsz 1 1]); % transprob(k,i,j)
+  transprob = permute(transprob, [2 1 3]); % now transprob(i,k,j)
+end
+transargs{end+1} = 'CPT';
+transargs{end+1} = transprob;
+CPD.sub_CPD_trans = mk_isolated_tabular_CPD([old_self Qps], ns([old_self Qps self]), transargs);
+S = struct(CPD.sub_CPD_trans);
+CPD.transprob = myreshape(S.CPT, [Qsz Qpsz Qsz]);
+
+
+if strcmp(startprob, 'leftstart')
+  startprob = zeros(Qpsz, Qsz);
+  startprob(:,1) = 1;
+end
+
+if (d==1) & ~CPD.F1toQ1
+  CPD.sub_CPD_start = [];
+  CPD.startprob = [];
+else
+  startargs{end+1} = 'CPT';
+  startargs{end+1} = startprob;
+  CPD.sub_CPD_start = mk_isolated_tabular_CPD(Qps, ns([Qps self]), startargs);
+  S = struct(CPD.sub_CPD_start);
+  CPD.startprob = myreshape(S.CPT, [Qpsz Qsz]);
+end
+
+CPD = class(CPD, 'hhmmQ_CPD', tabular_CPD(bnet, self));
+
+CPD = update_CPT(CPD);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/log_prior.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function L = log_prior(CPD)
+% LOG_PRIOR Return log P(theta) for a hhmm CPD 
+% L = log_prior(CPD)
+
+L = log_prior(CPD.sub_CPD_trans);
+if ~isempty(CPD.sub_CPD_start)
+  L = L + log_prior(CPD.sub_CPD_start);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/maximize_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+function CPD = maximize_params(CPD, temp)
+% MAXIMIZE_PARAMS Set the params of a hhmmQ node to their ML/MAP values.
+% CPD = maximize_params(CPD, temperature)
+
+Qsz = CPD.Qsizes(CPD.d);
+Qpsz = prod(CPD.Qsizes(CPD.Qps));
+
+if ~isempty(CPD.sub_CPD_start)
+  CPD.sub_CPD_start = maximize_params(CPD.sub_CPD_start, temp);
+  S = struct(CPD.sub_CPD_start);
+  CPD.startprob = myreshape(S.CPT, [Qpsz Qsz]);
+  %CPD.startprob = S.CPT;
+end
+
+if 1
+  % If we are in a state that can only go the end state,
+  % we will never see a transition to another (non-end) state,
+  % so counts(i,k,j)=0 (and termprob(k,i)=1).
+  % We set counts(i,k,i)=1 in this case.
+  % This will cause remove_hhmm_end_state to return a
+  % stochastic matrix, but otherwise has no effect on EM.
+  counts = get_field(CPD.sub_CPD_trans, 'counts');
+  counts = reshape(counts, [Qsz Qpsz Qsz]);
+  for k=1:Qpsz
+    for i=1:Qsz
+      if sum(counts(i,k,:))==0 % never witnessed a transition out of i
+	counts(i,k,i)=1; % add self loop 
+	%fprintf('CPDQ d=%d i=%d k=%d\n', CPD.d, i, k);
+      end
+    end
+  end
+  CPD.sub_CPD_trans = set_fields(CPD.sub_CPD_trans, 'counts', counts(:)); 
+end
+ 
+CPD.sub_CPD_trans = maximize_params(CPD.sub_CPD_trans, temp);
+S = struct(CPD.sub_CPD_trans);
+%CPD.transprob = S.CPT;
+CPD.transprob = myreshape(S.CPT, [Qsz Qpsz Qsz]);
+
+CPD = update_CPT(CPD);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/reset_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function CPD = reset_ess(CPD)
+% RESET_ESS Reset the Expected Sufficient Statistics of a hhmm Q node.
+% CPD = reset_ess(CPD)
+
+if ~isempty(CPD.sub_CPD_start)
+  CPD.sub_CPD_start = reset_ess(CPD.sub_CPD_start);
+end
+CPD.sub_CPD_trans = reset_ess(CPD.sub_CPD_trans);   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/update_CPT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,74 @@
+function CPD = update_CPT(CPD)
+% Compute the big CPT for an HHMM Q node (including F parents) given internal transprob and startprob
+% function CPD = update_CPT(CPD)
+
+Qsz = CPD.Qsz;
+Qpsz = CPD.Qpsz;
+
+if ~isempty(CPD.Fbelow_ndx)
+  if ~isempty(CPD.Fself_ndx) % general case
+    % Fb(t-1) Fself(t-1)  P(Q(t)=j| Q(t-1)=i, Qps(t)=k)
+    % ------------------------------------------------------
+    % 1        1         delta(i,j)
+    % 2        1         transprob(i,k,j)
+    % 1        2         impossible
+    % 2        2         startprob(k,j)
+    CPT = zeros(Qsz, 2, 2, Qpsz, Qsz);
+    I = repmat(eye(Qsz), [1 1 Qpsz]); % i,j,k
+    I = permute(I, [1 3 2]); % i,k,j
+    CPT(:, 1, 1, :, :) = I;
+    CPT(:, 2, 1, :, :) = CPD.transprob;
+    CPT(:, 1, 2, :, :) = I;
+    CPT(:, 2, 2, :, :) = repmat(reshape(CPD.startprob, [1 Qpsz Qsz]), [Qsz 1 1]); % replicate over i
+  else % no F from self, hence no startprob
+    % Fb(t-1) P(Q(t)=j| Q(t-1)=i, Qps(t)=k)
+    % ------------------------------------------------------
+    % 1       delta(i,j)
+    % 2       transprob(i,k,j)
+    
+    nps = length(CPD.dom_sz)-1; % num parents
+    CPT = 0*myones(CPD.dom_sz);
+    %CPT = zeros(Qsz, 2, Qpsz, Qsz); % assumes CPT(Q(t-1), F(t-1), Qps, Q(t))
+    % but a member of Qps may preceed Q(t-1) or F(t-1) in the ordering
+    
+    I = repmat(eye(Qsz), [1 1 Qpsz]); % i,j,k
+    I = permute(I, [1 3 2]); % i,k,j
+
+    % the following fails if there is a member of Qps with a lower
+    % number than F
+    %CPT(:, 1, :, :) = I;
+    %CPT(:, 2, :, :) = CPD.transprob;
+
+    ndx = mk_multi_index(nps+1, CPD.Fbelow_ndx, 1);
+    CPT(ndx{:}) = I;
+    ndx = mk_multi_index(nps+1, CPD.Fbelow_ndx, 2);
+    CPT(ndx{:}) = CPD.transprob;
+    keyboard
+  end
+else % no F signal from below
+  if ~isempty(CPD.Fself_ndx)
+    % Q(t-1), Fself(t-1), Qps, Q(t)
+    
+    % if condition start on previous concrete state (as in map learning),
+    % CPT(:, 1, :, :, :) = CPD.transprob(Q(t-1), Qps, Q(t))
+    % CPT(:, 2, :, :, :) = CPD.startprob(Q(t-1), Qps, Q(t))
+    
+    % Fself(t-1)  P(Q(t-1)=i, Qps(t)=k -> Q(t)=j)
+    % ------------------------------------------------------
+    % 1         transprob(i,k,j)
+    % 2         startprob(k,j)
+    CPT = zeros(Qsz, 2, Qpsz, Qsz);
+    I = repmat(eye(Qsz), [1 1 Qpsz]); % i,j,k
+    I = permute(I, [1 3 2]); % i,k,j
+    CPT(:, 1, :, :) = CPD.transprob;
+    if CPD.fullstartprob
+      CPT(:, 2, :, :) = CPD.startprob;
+    else
+      CPT(:, 2, :, :) = repmat(reshape(CPD.startprob, [1 Qpsz Qsz]), [Qsz 1 1]); % replicate over i
+    end
+    else % no F from self
+    error('An hhmmQ node without any F parents is just a tabular_CPD')
+  end
+end
+
+CPD = set_fields(CPD, 'CPT', CPT);          
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/update_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,141 @@
+function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+% UPDATE_ESS Update the Expected Sufficient Statistics of a hhmm Q node.
+% function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, idden_bitv)
+
+% Figure out the node numbers associated with each parent
+% e.g., D=4, d=3, Qps = all Qs above, so dom = [Q3(t-1) F4(t-1) F3(t-1) Q1(t) Q2(t) Q3(t)].
+% so self = Q3(t), old_self = Q3(t-1), CPD.Qps = [1 2], Qps = [Q1(t) Q2(t)]
+dom = fmarginal.domain;
+self = dom(end);
+old_self = dom(1);
+Qps = dom(length(dom)-length(CPD.Qps):end-1);
+
+Qsz = CPD.Qsizes(CPD.d);
+Qpsz = prod(CPD.Qsizes(CPD.Qps));
+
+% If some of the Q nodes are observed (which happens during supervised training)
+% the counts will only be non-zero in positions
+% consistent with the evidence. We put the computed marginal responsibilities
+% into the appropriate slots of the big counts array.
+% (Recall that observed discrete nodes only have a single effective value.)
+% (A more general, but much slower, way is to call add_evidence_to_dmarginal.)
+% We assume the F nodes are never observed.
+
+obs_self = ~hidden_bitv(self);
+obs_Qps = (~isempty(Qps)) & (~any(hidden_bitv(Qps))); % we assume that all or none of the Q parents are observed
+
+if obs_self
+  self_val = evidence{self};
+  oldself_val = evidence{old_self};
+end
+
+if obs_Qps
+  Qps_val = subv2ind(Qpsz, cat(1, evidence{Qps}));
+  if Qps_val == 0
+    keyboard
+  end
+end
+
+if CPD.d==1 % no Qps from above
+  if ~CPD.F1toQ1 % no F from self
+    % marg(Q1(t-1), F2(t-1), Q1(t))                            
+    % F2(t-1) P(Q1(t)=j | Q1(t-1)=i)
+    % 1       delta(i,j)
+    % 2       transprob(i,j)
+    if obs_self
+      hor_counts = zeros(Qsz, Qsz);
+      hor_counts(oldself_val, self_val) = fmarginal.T(2);
+    else
+      marg = reshape(fmarginal.T, [Qsz 2 Qsz]);
+      hor_counts = squeeze(marg(:,2,:));
+    end
+  else
+    % marg(Q1(t-1), F2(t-1), F1(t-1), Q1(t))                            
+    % F2(t-1) F1(t-1)  P(Qd(t)=j| Qd(t-1)=i)
+    % ------------------------------------------------------
+    % 1        1         delta(i,j)
+    % 2        1         transprob(i,j)
+    % 1        2         impossible
+    % 2        2         startprob(j)
+    if obs_self
+      marg = myreshape(fmarginal.T, [1 2 2 1]);
+      hor_counts = zeros(Qsz, Qsz);
+      hor_counts(oldself_val, self_val) = marg(1,2,1,1);
+      ver_counts = zeros(Qsz, 1);
+      %ver_counts(self_val) = marg(1,2,2,1);
+      ver_counts(self_val) = marg(1,2,2,1) + marg(1,1,2,1);
+    else
+      marg = reshape(fmarginal.T, [Qsz 2 2 Qsz]);
+      hor_counts = squeeze(marg(:,2,1,:));
+      %ver_counts = squeeze(sum(marg(:,2,2,:),1)); % sum over i
+      ver_counts = squeeze(sum(marg(:,2,2,:),1)) + squeeze(sum(marg(:,1,2,:),1)); % sum i,b
+    end
+  end % F1toQ1
+else % d ~= 1
+  if CPD.d < CPD.D % general case
+    % marg(Qd(t-1), Fd+1(t-1), Fd(t-1), Qps(t), Qd(t))                            
+    % Fd+1(t-1) Fd(t-1)  P(Qd(t)=j| Qd(t-1)=i, Qps(t)=k)
+    % ------------------------------------------------------
+    % 1        1         delta(i,j)
+    % 2        1         transprob(i,k,j)
+    % 1        2         impossible
+    % 2        2         startprob(k,j)
+    if obs_Qps & obs_self
+      marg = myreshape(fmarginal.T, [1 2 2 1 1]);
+      k = 1;
+      hor_counts = zeros(Qsz, Qpsz, Qsz);
+      hor_counts(oldself_val, Qps_val, self_val) = marg(1, 2,1, k,1);
+      ver_counts = zeros(Qpsz, Qsz);
+      %ver_counts(Qps_val, self_val) = marg(1, 2,2, k,1);
+      ver_counts(Qps_val, self_val) = marg(1, 2,2, k,1) + marg(1, 1,2, k,1);
+    elseif obs_Qps & ~obs_self
+      marg = myreshape(fmarginal.T, [Qsz 2 2 1 Qsz]);
+      k = 1;
+      hor_counts = zeros(Qsz, Qpsz, Qsz);
+      hor_counts(:, Qps_val, :) = marg(:, 2,1, k,:);
+      ver_counts = zeros(Qpsz, Qsz);
+      %ver_counts(Qps_val, :) = sum(marg(:, 2,2, k,:), 1);
+      ver_counts(Qps_val, :) = sum(marg(:, 2,2, k,:), 1) + sum(marg(:, 1,2, k,:), 1);
+    elseif ~obs_Qps & obs_self
+      error('not yet implemented')
+    else % everything is hidden
+      marg = reshape(fmarginal.T, [Qsz 2 2 Qpsz Qsz]);
+      hor_counts = squeeze(marg(:,2,1,:,:)); % i,k,j
+      %ver_counts = squeeze(sum(marg(:,2,2,:,:),1)); % sum over i
+      ver_counts = squeeze(sum(marg(:,2,2,:,:),1)) + squeeze(sum(marg(:,1,2,:,:),1)); % sum over i,b
+    end
+  else % d == D, so no F from below
+    % marg(QD(t-1), FD(t-1), Qps(t), QD(t))                            
+    % FD(t-1) P(QD(t)=j | QD(t-1)=i, Qps(t)=k)
+    % 1      transprob(i,k,j) 
+    % 2      startprob(k,j)
+    if obs_Qps & obs_self
+      marg = myreshape(fmarginal.T, [1 2 1 1]);
+      k = 1;
+      hor_counts = zeros(Qsz, Qpsz, Qsz);
+      hor_counts(oldself_val, Qps_val, self_val) = marg(1, 1, k,1);
+      ver_counts = zeros(Qpsz, Qsz);
+      ver_counts(Qps_val, self_val) = marg(1, 2, k,1);
+    elseif obs_Qps & ~obs_self
+      marg = myreshape(fmarginal.T, [Qsz 2 1 Qsz]);
+      k = 1;
+      hor_counts = zeros(Qsz, Qpsz, Qsz);
+      hor_counts(:, Qps_val, :) = marg(:, 1, k,:);
+      ver_counts = zeros(Qpsz, Qsz);
+      ver_counts(Qps_val, :) = sum(marg(:, 2, k, :), 1);
+    elseif ~obs_Qps & obs_self
+      error('not yet implemented')
+    else % everything is hidden
+      marg = reshape(fmarginal.T, [Qsz 2 Qpsz Qsz]);
+      hor_counts = squeeze(marg(:,1,:,:));
+      ver_counts = squeeze(sum(marg(:,2,:,:),1)); % sum over i
+    end
+  end
+end
+
+CPD.sub_CPD_trans = update_ess_simple(CPD.sub_CPD_trans, hor_counts);
+
+if ~isempty(CPD.sub_CPD_start)
+  CPD.sub_CPD_start = update_ess_simple(CPD.sub_CPD_start, ver_counts);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/update_ess2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,178 @@
+function CPD = update_ess2(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+% UPDATE_ESS Update the Expected Sufficient Statistics of a hhmm Q node.
+% function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, idden_bitv)
+
+% Figure out the node numbers associated with each parent
+dom = fmarginal.domain;
+self = dom(end); % by assumption
+old_self = dom(CPD.old_self_ndx);
+Fself = dom(CPD.Fself_ndx);
+Fbelow = dom(CPD.Fbelow_ndx);
+Qps = dom(CPD.Qps_ndx);
+
+Qsz = CPD.Qsz;
+Qpsz = CPD.Qpsz;
+
+
+fmarg = add_ev_to_dmarginal(fmarginal, evidence, ns);
+
+
+
+% hor_counts(old_self, Qps, self),
+% fmarginal(old_self, Fbelow, Fself, Qps, self)
+% hor_counts(i,k,j) = fmarginal(i,2,1,k,j) % below has finished, self has not
+% ver_counts(i,k,j) = fmarginal(i,2,2,k,j) % below has finished, and so has self (reset)
+% Since any of i,j,k may be observed, we write
+% hor_counts(counts_ndx{:}) = fmarginal(fmarg_ndx{:})
+% where e.g., counts_ndx = {1, ':', 2} if Qps is hidden but we observe old_self=1, self=2.
+% To create this counts_ndx, we write counts_ndx = mk_multi_ndx(3, obs_dim, obs_val)
+% where counts_obs_dim = [1 3], counts_obs_val = [1 2] specifies the values of dimensions 1 and 3.
+
+counts_obs_dim = [];
+fmarg_obs_dim = [];
+obs_val = []; 
+if hidden_bitv(self)
+  effQsz = Qsz;
+else
+  effQsz = 1;
+  counts_obs_dim = [counts_obs_dim 3];
+  fmarg_obs_dim = [fmarg_obs_dim 5];
+  obs_val = [obs_val evidence{self}];
+end
+  
+% e.g., D=4, d=3, Qps = all Qs above, so dom = [Q3(t-1) F4(t-1) F3(t-1) Q1(t) Q2(t) Q3(t)].
+% so self = Q3(t), old_self = Q3(t-1), CPD.Qps = [1 2], Qps = [Q1(t) Q2(t)]
+dom = fmarginal.domain;
+self = dom(end);
+old_self = dom(1);
+Qps = dom(length(dom)-length(CPD.Qps):end-1);
+
+Qsz = CPD.Qsizes(CPD.d);
+Qpsz = prod(CPD.Qsizes(CPD.Qps));
+
+% If some of the Q nodes are observed (which happens during supervised training)
+% the counts will only be non-zero in positions
+% consistent with the evidence. We put the computed marginal responsibilities
+% into the appropriate slots of the big counts array.
+% (Recall that observed discrete nodes only have a single effective value.)
+% (A more general, but much slower, way is to call add_evidence_to_dmarginal.)
+% We assume the F nodes are never observed.
+
+obs_self = ~hidden_bitv(self);
+obs_Qps = (~isempty(Qps)) & (~any(hidden_bitv(Qps))); % we assume that all or none of the Q parents are observed
+
+if obs_self
+  self_val = evidence{self};
+  oldself_val = evidence{old_self};
+end
+
+if obs_Qps
+  Qps_val = subv2ind(Qpsz, cat(1, evidence{Qps}));
+  if Qps_val == 0
+    keyboard
+  end
+end
+
+if CPD.d==1 % no Qps from above
+  if ~CPD.F1toQ1 % no F from self
+    % marg(Q1(t-1), F2(t-1), Q1(t))                            
+    % F2(t-1) P(Q1(t)=j | Q1(t-1)=i)
+    % 1       delta(i,j)
+    % 2       transprob(i,j)
+    if obs_self
+      hor_counts = zeros(Qsz, Qsz);
+      hor_counts(oldself_val, self_val) = fmarginal.T(2);
+    else
+      marg = reshape(fmarginal.T, [Qsz 2 Qsz]);
+      hor_counts = squeeze(marg(:,2,:));
+    end
+  else
+    % marg(Q1(t-1), F2(t-1), F1(t-1), Q1(t))                            
+    % F2(t-1) F1(t-1)  P(Qd(t)=j| Qd(t-1)=i)
+    % ------------------------------------------------------
+    % 1        1         delta(i,j)
+    % 2        1         transprob(i,j)
+    % 1        2         impossible
+    % 2        2         startprob(j)
+    if obs_self
+      marg = myreshape(fmarginal.T, [1 2 2 1]);
+      hor_counts = zeros(Qsz, Qsz);
+      hor_counts(oldself_val, self_val) = marg(1,2,1,1);
+      ver_counts = zeros(Qsz, 1);
+      %ver_counts(self_val) = marg(1,2,2,1);
+      ver_counts(self_val) = marg(1,2,2,1) + marg(1,1,2,1);
+    else
+      marg = reshape(fmarginal.T, [Qsz 2 2 Qsz]);
+      hor_counts = squeeze(marg(:,2,1,:));
+      %ver_counts = squeeze(sum(marg(:,2,2,:),1)); % sum over i
+      ver_counts = squeeze(sum(marg(:,2,2,:),1)) + squeeze(sum(marg(:,1,2,:),1)); % sum i,b
+    end
+  end % F1toQ1
+else % d ~= 1
+  if CPD.d < CPD.D % general case
+    % marg(Qd(t-1), Fd+1(t-1), Fd(t-1), Qps(t), Qd(t))                            
+    % Fd+1(t-1) Fd(t-1)  P(Qd(t)=j| Qd(t-1)=i, Qps(t)=k)
+    % ------------------------------------------------------
+    % 1        1         delta(i,j)
+    % 2        1         transprob(i,k,j)
+    % 1        2         impossible
+    % 2        2         startprob(k,j)
+    if obs_Qps & obs_self
+      marg = myreshape(fmarginal.T, [1 2 2 1 1]);
+      k = 1;
+      hor_counts = zeros(Qsz, Qpsz, Qsz);
+      hor_counts(oldself_val, Qps_val, self_val) = marg(1, 2,1, k,1);
+      ver_counts = zeros(Qpsz, Qsz);
+      %ver_counts(Qps_val, self_val) = marg(1, 2,2, k,1);
+      ver_counts(Qps_val, self_val) = marg(1, 2,2, k,1) + marg(1, 1,2, k,1);
+    elseif obs_Qps & ~obs_self
+      marg = myreshape(fmarginal.T, [Qsz 2 2 1 Qsz]);
+      k = 1;
+      hor_counts = zeros(Qsz, Qpsz, Qsz);
+      hor_counts(:, Qps_val, :) = marg(:, 2,1, k,:);
+      ver_counts = zeros(Qpsz, Qsz);
+      %ver_counts(Qps_val, :) = sum(marg(:, 2,2, k,:), 1);
+      ver_counts(Qps_val, :) = sum(marg(:, 2,2, k,:), 1) + sum(marg(:, 1,2, k,:), 1);
+    elseif ~obs_Qps & obs_self
+      error('not yet implemented')
+    else % everything is hidden
+      marg = reshape(fmarginal.T, [Qsz 2 2 Qpsz Qsz]);
+      hor_counts = squeeze(marg(:,2,1,:,:)); % i,k,j
+      %ver_counts = squeeze(sum(marg(:,2,2,:,:),1)); % sum over i
+      ver_counts = squeeze(sum(marg(:,2,2,:,:),1)) + squeeze(sum(marg(:,1,2,:,:),1)); % sum over i,b
+    end
+  else % d == D, so no F from below
+    % marg(QD(t-1), FD(t-1), Qps(t), QD(t))                            
+    % FD(t-1) P(QD(t)=j | QD(t-1)=i, Qps(t)=k)
+    % 1      transprob(i,k,j) 
+    % 2      startprob(k,j)
+    if obs_Qps & obs_self
+      marg = myreshape(fmarginal.T, [1 2 1 1]);
+      k = 1;
+      hor_counts = zeros(Qsz, Qpsz, Qsz);
+      hor_counts(oldself_val, Qps_val, self_val) = marg(1, 1, k,1);
+      ver_counts = zeros(Qpsz, Qsz);
+      ver_counts(Qps_val, self_val) = marg(1, 2, k,1);
+    elseif obs_Qps & ~obs_self
+      marg = myreshape(fmarginal.T, [Qsz 2 1 Qsz]);
+      k = 1;
+      hor_counts = zeros(Qsz, Qpsz, Qsz);
+      hor_counts(:, Qps_val, :) = marg(:, 1, k,:);
+      ver_counts = zeros(Qpsz, Qsz);
+      ver_counts(Qps_val, :) = sum(marg(:, 2, k, :), 1);
+    elseif ~obs_Qps & obs_self
+      error('not yet implemented')
+    else % everything is hidden
+      marg = reshape(fmarginal.T, [Qsz 2 Qpsz Qsz]);
+      hor_counts = squeeze(marg(:,1,:,:));
+      ver_counts = squeeze(sum(marg(:,2,:,:),1)); % sum over i
+    end
+  end
+end
+
+CPD.sub_CPD_trans = update_ess_simple(CPD.sub_CPD_trans, hor_counts);
+
+if ~isempty(CPD.sub_CPD_start)
+  CPD.sub_CPD_start = update_ess_simple(CPD.sub_CPD_start, ver_counts);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/update_ess3.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,80 @@
+function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+% UPDATE_ESS Update the Expected Sufficient Statistics of a hhmm Q node.
+% function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, idden_bitv)
+%
+% we assume if one of the Qps is observed, all of them are 
+% We assume the F nodes are already hidden 
+
+% Figure out the node numbers associated with each parent
+dom = fmarginal.domain;
+self = dom(CPD.self_ndx);
+old_self = dom(CPD.old_self_ndx);
+%Fself = dom(CPD.Fself_ndx);
+%Fbelow = dom(CPD.Fbelow_ndx);
+Qps = dom(CPD.Qps_ndx);
+
+Qsz = CPD.Qsz;
+Qpsz = CPD.Qpsz;
+
+
+% hor_counts(old_self, Qps, self),
+% fmarginal(old_self, Fbelow, Fself, Qps, self)
+% hor_counts(i,k,j) = fmarginal(i,2,1,k,j) % below has finished, self has not
+% ver_counts(i,k,j) = fmarginal(i,2,2,k,j) % below has finished, and so has self (reset)
+% Since any of i,j,k may be observed, we write
+% hor_counts(ndx{:}) = fmarginal(...)
+% where e.g., ndx = {1, ':', 2} if Qps is hidden but we observe old_self=1, self=2.
+
+% ndx{i,k,j}
+if hidden_bitv(old_self)
+  ndx{1} = ':';
+else
+  ndx{1} = evidence{old_self};
+end
+if hidden_bitv(Qps)
+  ndx{2} = ':';
+else
+  ndx{2} = subv2ind(Qpsz, cat(1, evidence{Qps}));
+end
+if hidden_bitv(self)
+  ndx{3} = ':';
+else
+  ndx{3} = evidence{self};
+end
+
+fmarg = add_ev_to_dmarginal(fmarginal, evidence, ns);
+% marg(Qold(t-1), Fbelow(t-1), Fself(t-1), Qps(t), Qself(t))                            
+hor_counts = zeros(Qsz, Qpsz, Qsz);
+ver_counts = zeros(Qpsz, Qsz);
+    
+if ~isempty(CPD.Fbelow_ndx)
+  if ~isempty(CPD.Fself_ndx) % general case
+    fmarg.T = myreshape(fmarg.T, [Qsz 2 2 Qpsz Qsz]);
+    marg_ndx = {ndx{1}, 2, 1, ndx{2}, ndx{3}};
+    hor_counts(ndx{:}) = fmarg.T(marg_ndx{:});
+    ver_counts(ndx{2:3}) = ... % sum over Fbelow and Qold=i
+	sum(fmarg.T({ndx{1}, 1, 2, ndx{2}, ndx{3}}),1) + ..
+	sum(fmarg.T({ndx{1}, 2, 2, ndx{2}, ndx{3}}),1);
+  else % no F from self, hence no startprob
+    fmarg.T = myreshape(fmarg.T, [Qsz 2 Qpsz Qsz]);
+    hor_counts(ndx{:}) = fmarg.T({ndx{1}, 2, ndx{2}, ndx{3}});
+  end
+else % no F signal from below
+  if ~isempty(CPD.Fself_ndx) % self F
+    fmarg.T = myreshape(fmarg.T, [Qsz 2 Qpsz Qsz]);
+    hor_counts(ndx{:}) = fmarg.T({ndx{1}, 1, ndx{2}, ndx{3}});
+    ver_counts(ndx{2:3}) = ... % sum over Qold=i
+	sum(fmarg.T({ndx{1}, 2, ndx{2}, ndx{3}}),1);
+  else % no F from self
+    error('An hhmmQ node without any F parents is just a tabular_CPD')
+  end
+end
+
+
+CPD.sub_CPD_trans = update_ess_simple(CPD.sub_CPD_trans, hor_counts);
+
+if ~isempty(CPD.sub_CPD_start)
+  CPD.sub_CPD_start = update_ess_simple(CPD.sub_CPD_start, ver_counts);
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/Old/update_ess4.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,95 @@
+function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+% UPDATE_ESS Update the Expected Sufficient Statistics of a hhmm Q node.
+% function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, idden_bitv)
+%
+% we assume if one of the Qps is observed, all of them are 
+% We assume the F nodes are already hidden 
+
+% Figure out the node numbers associated with each parent
+dom = fmarginal.domain;
+self = dom(CPD.self_ndx);
+old_self = dom(CPD.old_self_ndx);
+%Fself = dom(CPD.Fself_ndx);
+%Fbelow = dom(CPD.Fbelow_ndx);
+Qps = dom(CPD.Qps_ndx);
+
+Qsz = CPD.Qsz;
+Qpsz = CPD.Qpsz;
+
+
+% hor_counts(old_self, Qps, self),
+% fmarginal(old_self, Fbelow, Fself, Qps, self)
+% hor_counts(i,k,j) = fmarginal(i,2,1,k,j) % below has finished, self has not
+% ver_counts(i,k,j) = fmarginal(i,2,2,k,j) % below has finished, and so has self (reset)
+% Since any of i,j,k may be observed, we write
+% hor_counts(i_counts_ndx, kndx, jndx) = fmarginal(i_fmarg_ndx...)
+% where i_fmarg_ndx = 1 and i_counts_ndx = i if old_self is observed to have value i,
+% i_fmarg_ndx = 1:Qsz and i_counts_ndx = 1:Qsz if old_self is hidden, etc.
+
+
+if hidden_bitv(old_self)
+  i_counts_ndx = 1:Qsz;
+  i_fmarg_ndx = 1:Qsz;
+  eff_oldQsz = Qsz;
+else
+  i_counts_ndx = evidence{old_self};
+  i_fmarg_ndx = 1;
+  eff_oldQsz = 1;
+end
+
+if all(hidden_bitv(Qps)) % we assume all are hidden or all are observed
+  k_counts_ndx = 1:Qpsz;
+  k_fmarg_ndx = 1:Qpsz;
+  eff_Qpsz = Qpsz;
+else
+  k_counts_ndx = subv2ind(Qpsz, cat(1, evidence{Qps}));
+  k_fmarg_ndx = 1;
+  eff_Qpsz = 1;
+end
+
+if hidden_bitv(self)
+  j_counts_ndx = 1:Qsz;
+  j_fmarg_ndx = 1:Qsz;
+  eff_Qsz = Qsz;
+else
+  j_counts_ndx = evidence{self};
+  j_fmarg_ndx = 1;
+  eff_Qsz = 1;
+end
+
+hor_counts = zeros(Qsz, Qpsz, Qsz);
+ver_counts = zeros(Qpsz, Qsz);
+    
+if ~isempty(CPD.Fbelow_ndx)
+  if ~isempty(CPD.Fself_ndx) % general case
+    fmarg.T = myreshape(fmarg.T, [eff_oldQsz 2 2 eff_Qpsz eff_Qsz]);
+    hor_counts(i_counts_ndx, k_counts_ndx, j_counts_ndx) = ...
+	fmarg.T(:, i_fmarg_ndx, 2, 1, k_fmarg_ndx, j_fmarg_ndx);
+    ver_counts(k_counts_ndx, j_counts_ndx) = ... % sum over Fbelow and Qold
+	sum(fmarg.T(:, 1, 2, k_fmarg_ndx, j_fmarg_ndx), 1) + ...
+	sum(fmarg.T(:, 2, 2, k_fmarg_ndx, j_fmarg_ndx), 1); 
+  else % no F from self, hence no startprob
+    fmarg.T = myreshape(fmarg.T, [eff_oldQsz 2 eff_Qpsz eff_Qsz]);
+    hor_counts(i_counts_ndx, k_counts_ndx, j_counts_ndx) = ...
+	fmarg.T(i_fmarg_ndx, 2, k_fmarg_ndx, j_fmarg_ndx);
+  end
+else % no F signal from below
+  if ~isempty(CPD.Fself_ndx) % self F
+    fmarg.T = myreshape(fmarg.T, [eff_oldQsz 2 eff_Qpsz eff_Qsz]);
+    hor_counts(i_counts_ndx, k_counts_ndx, j_counts_ndx) = ...
+	fmarg.T(i_fmarg_ndx, 1, k_fmarg_ndx, j_fmarg_ndx);
+    ver_counts(k_counts_ndx, j_counts_ndx) = ... % sum over Qold
+	sum(fmarg.T(:, 2, k_fmarg_ndx, j_fmarg_ndx), 1);
+  else % no F from self
+    error('An hhmmQ node without any F parents is just a tabular_CPD')
+  end
+end
+
+
+CPD.sub_CPD_trans = update_ess_simple(CPD.sub_CPD_trans, hor_counts);
+
+if ~isempty(CPD.sub_CPD_start)
+  CPD.sub_CPD_start = update_ess_simple(CPD.sub_CPD_start, ver_counts);
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/hhmmQ_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,132 @@
+function CPD = hhmmQ_CPD(bnet, self, varargin)
+% HHMMQ_CPD Make the CPD for a Q node in a hierarchical HMM
+% CPD = hhmmQ_CPD(bnet, self, ...)
+%
+%  Fself(t-1)   Qps(t)
+%           \    |
+%            \   v
+%  Qold(t-1) ->  Q(t)
+%            /
+%           /
+%  Fbelow(t-1) 
+%
+% Let ss = slice size = num. nodes per slice.
+% This node is Q(t), and has mandatory parents Qold(t-1) (assumed to be numbered Q(t)-ss)
+% and optional parents Fbelow, Fself, Qps.
+% We require parents to be ordered (numbered) as follows:
+% Qold, Fbelow, Fself, Qps, Q.
+%
+% If Fself=2, we use the transition matrix, else we use the prior matrix.
+% If Fself node is omitted (eg. top level), we always use the transition matrix.
+% If Fbelow=2, we may change state, otherwise we must stay in the same state.
+% If Fbelow node is omitted (eg., bottom level), we may change state at every step.
+% If Qps (Q parents) are specified, all parameters are conditioned on their joint value.
+% We may choose any subset of nodes to condition on, as long as they as numbered lower than self.
+%
+% optional args [defaults]
+%
+% Fself - node number <= ss
+% Fbelow  - node number  <= ss
+% Qps - node numbers (all <= 2*ss) - uses 2TBN indexing
+% transprob - transprob(i,k,j) = prob transition from i to j given Qps = k ['leftright']
+% selfprob  - prob of a transition from i to i given Qps=k [0.1]
+% startprob - startprob(k,j) = prob start in j given Qps = k ['leftstart']
+% startargs - other args to be passed to the sub tabular_CPD for learning startprob
+% transargs - other args will be passed to the sub tabular_CPD for learning transprob
+% fullstartprob - 1 means startprob depends on Q(t-1) [0]
+% hhmmQ_CPD is a subclass of tabular_CPD so we inherit inference methods like CPD_to_pot, etc.
+%
+% We create isolated tabular_CPDs with no F parents to learn transprob/startprob
+% so we can avail of e.g., entropic or Dirichlet priors.
+% In the future, we will be able to represent the transprob using a tree_CPD.
+%
+% For details, see "Linear-time inference in hierarchical HMMs", Murphy and Paskin, NIPS'01.
+
+
+ss = bnet.nnodes_per_slice;
+ns = bnet.node_sizes(:);
+
+% set default arguments
+Fself = [];
+Fbelow = [];
+Qps = [];
+startprob = 'leftstart';
+transprob = 'leftright';
+startargs = {};
+transargs = {};
+selfprob = 0.1;
+fullstartprob = 0;
+
+for i=1:2:length(varargin)
+  switch varargin{i},
+   case 'Fself', Fself = varargin{i+1};
+   case 'Fbelow', Fbelow = varargin{i+1};
+   case 'Qps', Qps = varargin{i+1};
+   case 'transprob', transprob = varargin{i+1}; 
+   case 'selfprob',  selfprob = varargin{i+1}; 
+   case 'startprob', startprob = varargin{i+1}; 
+   case 'startargs', startargs = varargin{i+1}; 
+   case 'transargs', transargs = varargin{i+1}; 
+   case 'fullstartprob', fullstartprob = varargin{i+1}; 
+  end
+end
+
+CPD.fullstartprob = fullstartprob;
+
+ps = parents(bnet.dag, self);
+ndsz = ns(:)';
+CPD.dom_sz = [ndsz(ps) ns(self)];
+CPD.Fself_ndx = find_equiv_posns(Fself, ps);
+CPD.Fbelow_ndx = find_equiv_posns(Fbelow, ps);
+%CPD.Qps_ndx = find_equiv_posns(Qps+ss, ps);
+CPD.Qps_ndx = find_equiv_posns(Qps, ps);
+old_self = self-ss;
+CPD.old_self_ndx = find_equiv_posns(old_self, ps);
+
+Qps = ps(CPD.Qps_ndx);
+CPD.Qsz = ns(self);
+CPD.Qpsz = prod(ns(Qps));
+CPD.Qpsizes = ns(Qps);
+Qsz = CPD.Qsz;
+Qpsz = CPD.Qpsz;
+
+if strcmp(transprob, 'leftright')
+  LR = mk_leftright_transmat(Qsz, selfprob);
+  transprob = repmat(reshape(LR, [1 Qsz Qsz]), [Qpsz 1 1]); % transprob(k,i,j)
+  transprob = permute(transprob, [2 1 3]); % now transprob(i,k,j)
+end
+transargs{end+1} = 'CPT';
+transargs{end+1} = transprob;
+CPD.sub_CPD_trans = mk_isolated_tabular_CPD(ns([old_self Qps self]), transargs);
+S = struct(CPD.sub_CPD_trans);
+%CPD.transprob = myreshape(S.CPT, [Qsz Qpsz Qsz]);
+CPD.transprob = S.CPT;
+
+
+if strcmp(startprob, 'leftstart')
+  startprob = zeros(Qpsz, Qsz);
+  startprob(:,1) = 1;
+end
+if isempty(CPD.Fself_ndx)
+  CPD.sub_CPD_start = [];
+  CPD.startprob = [];
+else
+  startargs{end+1} = 'CPT';
+  startargs{end+1} = startprob;
+  if CPD.fullstartprob
+    CPD.sub_CPD_start = mk_isolated_tabular_CPD(ns([self Qps self]), startargs);
+    S = struct(CPD.sub_CPD_start);
+    %CPD.startprob = myreshape(S.CPT, [Qsz Qpsz Qsz]);
+    CPD.startprob = S.CPT;
+  else
+    CPD.sub_CPD_start = mk_isolated_tabular_CPD(ns([Qps self]), startargs);
+    S = struct(CPD.sub_CPD_start);
+    %CPD.startprob = myreshape(S.CPT, [CPD.Qpsizes Qsz]);
+    CPD.startprob = S.CPT;
+  end
+end
+
+CPD = class(CPD, 'hhmmQ_CPD', tabular_CPD(bnet, self));
+
+CPD = update_CPT(CPD);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/log_prior.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function L = log_prior(CPD)
+% LOG_PRIOR Return log P(theta) for a hhmm CPD 
+% L = log_prior(CPD)
+
+L = log_prior(CPD.sub_CPD_trans);
+if ~isempty(CPD.sub_CPD_start)
+  L = L + log_prior(CPD.sub_CPD_start);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/maximize_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+function CPD = maximize_params(CPD, temp)
+% MAXIMIZE_PARAMS Set the params of a hhmmQ node to their ML/MAP values.
+% CPD = maximize_params(CPD, temperature)
+
+Qsz = CPD.Qsz;
+Qpsz = CPD.Qpsz;
+
+if ~isempty(CPD.sub_CPD_start)
+  CPD.sub_CPD_start = maximize_params(CPD.sub_CPD_start, temp);
+  S = struct(CPD.sub_CPD_start);
+  CPD.startprob = myreshape(S.CPT, [Qpsz Qsz]);
+  %CPD.startprob = S.CPT;
+end
+
+if 1
+  % If we are in a state that can only go the end state,
+  % we will never see a transition to another (non-end) state,
+  % so counts(i,k,j)=0 (and termprob(k,i)=1).
+  % We set counts(i,k,i)=1 in this case.
+  % This will cause remove_hhmm_end_state to return a
+  % stochastic matrix, but otherwise has no effect on EM.
+  counts = get_field(CPD.sub_CPD_trans, 'counts');
+  counts = reshape(counts, [Qsz Qpsz Qsz]);
+  for k=1:Qpsz
+    for i=1:Qsz
+      if sum(counts(i,k,:))==0 % never witnessed a transition out of i
+	counts(i,k,i)=1; % add self loop 
+	%fprintf('CPDQ d=%d i=%d k=%d\n', CPD.d, i, k);
+      end
+    end
+  end
+  CPD.sub_CPD_trans = set_fields(CPD.sub_CPD_trans, 'counts', counts(:)); 
+end
+ 
+CPD.sub_CPD_trans = maximize_params(CPD.sub_CPD_trans, temp);
+S = struct(CPD.sub_CPD_trans);
+%CPD.transprob = S.CPT;
+CPD.transprob = myreshape(S.CPT, [Qsz Qpsz Qsz]);
+
+CPD = update_CPT(CPD);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/reset_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function CPD = reset_ess(CPD)
+% RESET_ESS Reset the Expected Sufficient Statistics of a hhmm Q node.
+% CPD = reset_ess(CPD)
+
+if ~isempty(CPD.sub_CPD_start)
+  CPD.sub_CPD_start = reset_ess(CPD.sub_CPD_start);
+end
+CPD.sub_CPD_trans = reset_ess(CPD.sub_CPD_trans);   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/update_CPT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,70 @@
+function CPD = update_CPT(CPD)
+% Compute the big CPT for an HHMM Q node (including F parents) given internal transprob and startprob
+% function CPD = update_CPT(CPD)
+
+Qsz = CPD.Qsz;
+Qpsz = CPD.Qpsz;
+
+if ~isempty(CPD.Fbelow_ndx)
+  if ~isempty(CPD.Fself_ndx) % general case
+    % Fb(t-1) Fself(t-1)  P(Q(t)=j| Q(t-1)=i, Qps(t)=k)
+    % ------------------------------------------------------
+    % 1        1         delta(i,j)
+    % 2        1         transprob(i,k,j)
+    % 1        2         impossible
+    % 2        2         startprob(k,j)
+    CPT = zeros(Qsz, 2, 2, Qpsz, Qsz);
+    I = repmat(eye(Qsz), [1 1 Qpsz]); % i,j,k
+    I = permute(I, [1 3 2]); % i,k,j
+    CPT(:, 1, 1, :, :) = I;
+    CPT(:, 2, 1, :, :) = CPD.transprob;
+    CPT(:, 1, 2, :, :) = I;
+    CPT(:, 2, 2, :, :) = repmat(reshape(CPD.startprob, [1 Qpsz Qsz]), ...
+				[Qsz 1 1]); % replicate  over i 
+  else % no F from self, hence no startprob
+    % Fb(t-1) P(Q(t)=j| Q(t-1)=i, Qps(t)=k)
+    % ------------------------------------------------------
+    % 1       delta(i,j)
+    % 2       transprob(i,k,j)
+    
+    nps = length(CPD.dom_sz)-1; % num parents
+    CPT = 0*myones(CPD.dom_sz);
+    %CPT = zeros(Qsz, 2, Qpsz, Qsz); % assumes CPT(Q(t-1), F(t-1), Qps, Q(t))
+    % but a member of Qps may preceed Q(t-1) or F(t-1) in the ordering
+
+    for k=1:CPD.Qpsz
+      Qps_vals = ind2subv(CPD.Qpsizes, k);
+      ndx = mk_multi_index(nps+1, [CPD.Fbelow_ndx CPD.Qps_ndx], [1 Qps_vals]);
+      CPT(ndx{:}) = eye(Qsz); % CPT(:,2,k,:) or CPT(:,k,2,:) etc
+    end
+    ndx = mk_multi_index(nps+1, CPD.Fbelow_ndx, 2);
+    CPT(ndx{:}) = CPD.transprob; % we assume transprob is in topo order
+  end
+else % no F signal from below
+  if ~isempty(CPD.Fself_ndx)
+    % Q(t-1), Fself(t-1), Qps, Q(t)
+    
+    % Fself(t-1)  P(Q(t-1)=i, Qps(t)=k -> Q(t)=j)
+    % ------------------------------------------------------
+    % 1         transprob(i,k,j)
+    % 2         startprob(k,j)
+    
+    nps = length(CPD.dom_sz)-1; % num parents
+    CPT = 0*myones(CPD.dom_sz);
+    ndx = mk_multi_index(nps+1, CPD.Fself_ndx, 1);
+    CPT(ndx{:}) = CPD.transprob;
+    if CPD.fullstartprob
+      ndx = mk_multi_index(nps+1, CPD.Fself_ndx, 2);
+      CPT(ndx{:}) = CPD.startprob;
+    else
+      for i=1:CPD.Qsz
+	ndx = mk_multi_index(nps+1, [CPD.Fself_ndx CPD.old_self_ndx], [2 i]);
+	CPT(ndx{:}) = CPD.startprob;
+      end
+    end
+  else % no F from self
+    error('An hhmmQ node without any F parents is just a tabular_CPD')
+  end
+end
+
+CPD = set_fields(CPD, 'CPT', CPT);          
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@hhmmQ_CPD/update_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,86 @@
+function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+% UPDATE_ESS Update the Expected Sufficient Statistics of a hhmm Q node.
+% function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, idden_bitv)
+%
+% we assume if one of the Qps is observed, all of them are 
+% We assume the F nodes are already hidden 
+
+% Figure out the node numbers associated with each parent
+dom = fmarginal.domain;
+self = dom(end);
+old_self = dom(CPD.old_self_ndx);
+%Fself = dom(CPD.Fself_ndx);
+%Fbelow = dom(CPD.Fbelow_ndx);
+Qps = dom(CPD.Qps_ndx);
+
+Qsz = CPD.Qsz;
+Qpsz = CPD.Qpsz;
+
+
+% hor_counts(old_self, Qps, self),
+% fmarginal(old_self, Fbelow, Fself, Qps, self)
+% hor_counts(i,k,j) = fmarginal(i,2,1,k,j) % below has finished, self has not
+% ver_counts(i,k,j) = fmarginal(i,2,2,k,j) % below has finished, and so has self (reset)
+% Since any of i,j,k may be observed, we write
+% hor_counts(i_counts_ndx, kndx, jndx) = fmarginal(i_fmarg_ndx...)
+% where i_fmarg_ndx = 1 and i_counts_ndx = i if old_self is observed to have value i,
+% i_fmarg_ndx = 1:Qsz and i_counts_ndx = 1:Qsz if old_self is hidden, etc.
+
+
+if hidden_bitv(old_self)
+  i_counts_ndx = 1:Qsz;
+  eff_oldQsz = Qsz;
+else
+  i_counts_ndx = evidence{old_self};
+  eff_oldQsz = 1;
+end
+
+if all(hidden_bitv(Qps)) % we assume all are hidden or all are observed
+  k_counts_ndx = 1:Qpsz;
+  eff_Qpsz = Qpsz;
+else
+  k_counts_ndx = subv2ind(Qpsz, cat(1, evidence{Qps}));
+  eff_Qpsz = 1;
+end
+
+if hidden_bitv(self)
+  j_counts_ndx = 1:Qsz;
+  eff_Qsz = Qsz;
+else
+  j_counts_ndx = evidence{self};
+  eff_Qsz = 1;
+end
+
+hor_counts = zeros(Qsz, Qpsz, Qsz);
+ver_counts = zeros(Qpsz, Qsz);
+    
+if ~isempty(CPD.Fbelow_ndx)
+  if ~isempty(CPD.Fself_ndx) % general case
+    fmarg = myreshape(fmarginal.T, [eff_oldQsz 2 2 eff_Qpsz eff_Qsz]);
+    hor_counts(i_counts_ndx, k_counts_ndx, j_counts_ndx) =  fmarg(:, 2, 1, :, :);
+    ver_counts(k_counts_ndx, j_counts_ndx) = ... % sum over Fbelow and Qold
+	sumv(fmarg(:, :,  2, :, :), [1 2]); % require Fself=2
+  else % no F from self, hence no startprob
+    fmarg = myreshape(fmarginal.T, [eff_oldQsz 2 eff_Qpsz eff_Qsz]);
+    hor_counts(i_counts_ndx, k_counts_ndx, j_counts_ndx) = ...
+	fmarg(:, 2, :, :); % require Fbelow = 2
+  end
+else % no F signal from below
+  if ~isempty(CPD.Fself_ndx) % self F
+    fmarg = myreshape(fmarginal.T, [eff_oldQsz 2 eff_Qpsz eff_Qsz]);
+    hor_counts(i_counts_ndx, k_counts_ndx, j_counts_ndx) =  fmarg(:, 1, :, :);
+    ver_counts(k_counts_ndx, j_counts_ndx) = ... % sum over Qold
+	squeeze(sum(fmarg(:, 2, :, :), 1)); % Fself=2
+  else % no F from self
+    error('An hhmmQ node without any F parents is just a tabular_CPD')
+  end
+end
+
+
+CPD.sub_CPD_trans = update_ess_simple(CPD.sub_CPD_trans, hor_counts);
+
+if ~isempty(CPD.sub_CPD_start)
+  CPD.sub_CPD_start = update_ess_simple(CPD.sub_CPD_start, ver_counts);
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@mlp_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/convert_to_table.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/maximize_params.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/mlp_CPD.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/reset_ess.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/update_ess.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@mlp_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@mlp_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@mlp_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@mlp_CPD/convert_to_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,80 @@
+function T = convert_to_table(CPD, domain, evidence)
+% CONVERT_TO_TABLE Convert a mlp CPD to a table, incorporating any evidence 
+% T = convert_to_table(CPD, domain, evidence)
+
+self = domain(end);                    
+ps = domain(1:end-1);                               % self' parents                                       
+%cps = myintersect(ps, cnodes);                      % self' continous parents      
+cnodes     = domain(CPD.cpndx);
+cps        = myintersect(ps, cnodes);
+odom = domain(~isemptycell(evidence(domain)));      % obs nodes in the net
+assert(myismember(cps, odom));                      % !ALL the CTS parents must be observed!
+ns(cps)=1;
+dps = mysetdiff(ps, cps);                           % self' discrete parents                                                    
+dobs = myintersect(dps, odom);                      % discrete obs parents
+
+% Extract the params compatible with the observations (if any) on the discrete parents (if any)
+
+if ~isempty(dobs),
+    dvals = cat(1, evidence{dobs});             
+    ns_eff= CPD.sizes;                               % effective node sizes              
+    ens=ns_eff;
+    ens(dobs) = 1;                              
+    S=prod(ens(dps));
+    subs = ind2subv(ens(dps), 1:S);
+    mask = find_equiv_posns(dobs, dps);        
+    for i=1:length(mask),
+        subs(:,mask(i)) = dvals(i);
+    end     
+    support = subv2ind(ns_eff(dps), subs)';
+else 
+    ns_eff= CPD.sizes;
+    support=[1:prod(ns_eff(dps))];
+end
+
+W1=[]; b1=[]; W2=[]; b2=[];
+
+W1 = CPD.W1(:,:,support);
+b1= CPD.b1(support,:);
+W2 = CPD.W2(:,:,support);
+b2= CPD.b2(support,:);
+ns(odom) = 1;
+dpsize = prod(ns(dps));                             % overall size of the self' discrete parents  
+
+x = cat(1, evidence{cps});    
+ndata=size(x,2);
+
+if ~isempty(evidence{self})                         %
+    app=struct(CPD);                                %
+    ns(self)=app.mlp{1}.nout;                       % pump up self to the original dimension if observed
+    clear app;                                      %
+end                                                 %
+
+T =zeros(dpsize, ns(self));                         %
+for i=1:dpsize                                      %                 
+    W1app = W1(:,:,i);                              % 
+    b1app = b1(i,:);                                % 
+    W2app = W2(:,:,i);                              % 
+    b2app = b2(i,:);                                % for each of the dpsize combinations of self'parents values 
+    z = tanh(x(:)'*W1app + ones(ndata, 1)*b1app);   % we tabulate the corrisponding glm model
+    a = z*W2app + ones(ndata, 1)*b2app;             % (element of the cell array CPD.glim)
+    appoggio = normalise(exp(a));                   %
+    T(i,:)=appoggio;                                %
+    W1app=[]; W2app=[]; b1app=[]; b2app=[];         %
+    z=[]; a=[]; appoggio=[];                        %
+end                                                 %                
+
+if ~isempty(evidence{self})
+    appoggio=[];                            %
+    appoggio=zeros(1,ns(self));             %
+    r = evidence{self};                     %...if self is observed => in output there's only the probability of the 'true' class
+    for i=1:dpsize                          % 
+          appoggio(i)=T(i,r);               % 
+    end
+    T=zeros(dpsize,1);
+    for i=1:dpsize
+        T(i,1)=appoggio(i);                        
+    end
+    clear appoggio;
+    ns(self) = 1;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@mlp_CPD/maximize_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,34 @@
+function CPD = maximize_params(CPD, temp)
+% MAXIMIZE_PARAMS Find ML params of an MLP using Scaled Conjugated Gradient (SCG)
+% CPD = maximize_params(CPD, temperature)
+% temperature parameter is ignored
+
+if ~adjustable_CPD(CPD), return; end
+options = foptions;
+
+% options(1) >= 0 means print an annoying message when the max. num. iter. is reached
+if CPD.verbose
+  options(1) = 1;
+else
+  options(1) = -1;
+end
+%options(1) = CPD.verbose;
+
+options(2) = CPD.wthresh;
+options(3) = CPD.llthresh;
+options(14) = CPD.max_iter;
+
+dpsz=length(CPD.mlp);
+
+for i=1:dpsz
+    mask=[];
+    mask=find(CPD.eso_weights(:,:,i)>0);    % for adapting the parameters we use only positive weighted example
+    if  ~isempty(mask),
+        CPD.mlp{i} = netopt_weighted(CPD.mlp{i}, options, CPD.parent_vals(mask',:), CPD.self_vals(mask',:,i), CPD.eso_weights(mask',:,i), 'scg');
+        
+        CPD.W1(:,:,i)=CPD.mlp{i}.w1;        % update the parameters matrix
+        CPD.b1(i,:)=CPD.mlp{i}.b1;          %
+        CPD.W2(:,:,i)=CPD.mlp{i}.w2;        % update the parameters matrix
+        CPD.b2(i,:)=CPD.mlp{i}.b2;          %
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@mlp_CPD/mlp_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,139 @@
+function CPD = mlp_CPD(bnet, self, nhidden, w1, b1, w2, b2, clamped, max_iter, verbose, wthresh,  llthresh)
+% MLP_CPD Make a CPD from a Multi Layer Perceptron (i.e., feedforward neural network)
+%
+% We use a different MLP for each discrete parent combination (if there are any discrete parents).
+% We currently assume this node (the child) is discrete.
+%
+% CPD = mlp_CPD(bnet, self, nhidden)
+% will create a CPD with random parameters, where self is the number of this node and nhidden the number of the hidden nodes.
+% The params are drawn from N(0, s*I), where s = 1/sqrt(n+1), n = length(X).
+%
+% CPD = mlp_CPD(bnet, self, nhidden, w1, b1, w2, b2) allows you to specify the params, where
+%  w1 = first-layer weight matrix
+%  b1 = first-layer bias vector
+%  w2 = second-layer weight matrix
+%  b2 = second-layer bias vector
+% These are assumed to be the same for each discrete parent combination.
+% If any of these are [], random values will be created.
+%
+% CPD = mlp_CPD(bnet, self, nhidden, w1, b1, w2, b2, clamped) allows you to prevent the params from being
+% updated during learning (if clamped = 1). Default: clamped = 0.
+%
+% CPD = mlp_CPD(bnet, self, nhidden, w1, b1, w2, b2, clamped, max_iter, verbose, wthresh,  llthresh)
+% alllows you to specify params that control the M step:
+%  max_iter - the maximum number of steps to take (default: 10)
+%  verbose - controls whether to print (default: 0 means silent).
+%  wthresh - a measure of the precision required for the value of
+%     the weights W at the solution. Default: 1e-2.
+%  llthresh - a measure of the precision required of the objective
+%     function (log-likelihood) at the solution.  Both this and the previous condition must
+%     be satisfied for termination. Default: 1e-2.
+%
+% For learning, we use a weighted version of scaled conjugated gradient in the M step.
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  CPD = class(CPD, 'mlp_CPD', discrete_CPD(0,[]));
+  return;
+elseif isa(bnet, 'mlp_CPD')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+CPD = init_fields;
+
+assert(myismember(self, bnet.dnodes));
+ns = bnet.node_sizes;
+
+ps = parents(bnet.dag, self);
+dnodes = mysetdiff(1:length(bnet.dag), bnet.cnodes);
+dps = myintersect(ps, dnodes);
+cps = myintersect(ps, bnet.cnodes);
+dpsz = prod(ns(dps));
+cpsz = sum(ns(cps));
+self_size = ns(self);
+
+% discrete/cts parent index - which ones of my parents are discrete/cts?
+CPD.dpndx = find_equiv_posns(dps, ps); 
+CPD.cpndx = find_equiv_posns(cps, ps);
+
+CPD.mlp = cell(1,dpsz);
+for i=1:dpsz
+    CPD.mlp{i} = mlp(cpsz, nhidden, self_size, 'softmax');
+    if nargin >=4 & ~isempty(w1)
+        CPD.mlp{i}.w1 = w1;
+    end
+    if nargin >=5 & ~isempty(b1)
+        CPD.mlp{i}.b1 = b1; 
+    end
+    if nargin >=6 & ~isempty(w2)
+        CPD.mlp{i}.w2 = w2; 
+    end
+    if nargin >=7 & ~isempty(b2)
+        CPD.mlp{i}.b2 = b2; 
+    end
+    W1app(:,:,i)=CPD.mlp{i}.w1;
+    W2app(:,:,i)=CPD.mlp{i}.w2;
+    b1app(i,:)=CPD.mlp{i}.b1;
+    b2app(i,:)=CPD.mlp{i}.b2;
+end
+if nargin < 8, clamped = 0; end
+if nargin < 9, max_iter = 10; end
+if nargin < 10, verbose = 0; end
+if nargin < 11, wthresh = 1e-2; end
+if nargin < 12, llthresh = 1e-2; end
+
+CPD.self = self;
+CPD.max_iter = max_iter;
+CPD.verbose = verbose;
+CPD.wthresh = wthresh;
+CPD.llthresh = llthresh;
+
+% sufficient statistics 
+% Since MLP is not in the exponential family, we must store all the raw data.
+%
+CPD.W1=W1app;                     % Extract all the parameters of the node for handling discrete obs parents
+CPD.W2=W2app;                     %
+nparaW=[size(W1app) size(W2app)]; %
+CPD.b1=b1app;                     %
+CPD.b2=b2app;                     %
+nparab=[size(b1app) size(b2app)]; %
+
+CPD.sizes=bnet.node_sizes(:);   % used in CPD_to_table to pump up the node sizes
+
+CPD.parent_vals = [];        % X(l,:) = value of cts parents in l'th example
+
+CPD.eso_weights=[];          % weights used by the SCG algorithm 
+
+CPD.self_vals = [];          % Y(l,:) = value of self in l'th example
+
+% For BIC
+CPD.nsamples = 0;   
+CPD.nparams=prod(nparaW)+prod(nparab);
+CPD = class(CPD, 'mlp_CPD', discrete_CPD(clamped, ns([ps self])));
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.mlp = {};
+CPD.self = [];
+CPD.max_iter = [];
+CPD.verbose = [];
+CPD.wthresh = [];
+CPD.llthresh = [];
+CPD.approx_hess = [];
+CPD.W1 = [];
+CPD.W2 = [];
+CPD.b1 = [];
+CPD.b2 = [];
+CPD.sizes = [];
+CPD.parent_vals = [];
+CPD.eso_weights=[];
+CPD.self_vals = [];
+CPD.nsamples = [];
+CPD.nparams = [];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@mlp_CPD/reset_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function CPD = reset_ess(CPD)
+% RESET_ESS Reset the Expected Sufficient Statistics for a CPD (mlp)
+% CPD = reset_ess(CPD)
+
+CPD.W1 = [];
+CPD.W2 = [];
+CPD.b1 = [];
+CPD.b2 = [];
+CPD.parent_vals = [];
+CPD.eso_weights=[];
+CPD.self_vals = [];
+CPD.nsamples = 0;  
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@mlp_CPD/update_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,131 @@
+function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+% UPDATE_ESS Update the Expected Sufficient Statistics of a CPD (MLP)
+% CPD = update_ess(CPD, family_marginal, evidence, node_sizes, cnodes, hidden_bitv)
+%
+% fmarginal = overall posterior distribution of self and its parents
+% fmarginal(i1,i2...,ik,s)=prob(Pa1=i1,...,Pak=ik, self=s| X)
+% 
+% => 1) prob(self|Pa1,...,Pak)=fmarginal/prob(Pa1,...,Pak) with prob(Pa1,...,Pak)=sum{s,fmarginal}
+%       [self estimation -> CPD.self_vals]
+% 	  2) prob(Pa1,...,Pak) [SCG weights -> CPD.eso_weights]
+%
+% Hidden_bitv is ignored
+
+% Written by Pierpaolo Brutti
+
+if ~adjustable_CPD(CPD), return; end
+
+dom = fmarginal.domain;                              
+cdom = myintersect(dom, cnodes);                     
+assert(~any(isemptycell(evidence(cdom))));           
+ns(cdom)=1;
+
+self = dom(end);                                  
+ps=dom(1:end-1);                                     
+dpdom=mysetdiff(ps,cdom);                            
+
+dnodes = mysetdiff(1:length(ns), cnodes);            
+
+ddom = myintersect(ps, dnodes);                      %
+if isempty(evidence{self}),                          % if self is hidden in what follow we must 
+    ddom = myintersect(dom, dnodes);                 % consider its dimension
+end                                                  % 
+
+odom = dom(~isemptycell(evidence(dom)));    
+hdom = dom(isemptycell(evidence(dom)));              % hidden parents in domain
+ 
+dobs = myintersect(ddom, odom);             
+dvals = cat(1, evidence{dobs});             
+ens = ns;                                            % effective node sizes              
+ens(dobs) = 1;                              
+                                            
+dpsz=prod(ns(dpdom));
+S=prod(ens(ddom));
+subs = ind2subv(ens(ddom), 1:S);
+mask = find_equiv_posns(dobs, ddom);
+for i=1:length(mask),
+    subs(:,mask(i)) = dvals(i);
+end
+supportedQs = subv2ind(ns(ddom), subs);
+
+Qarity = prod(ns(ddom));
+if isempty(ddom),                      
+  Qarity = 1;                         
+end                                
+fullm.T = zeros(Qarity, 1);
+fullm.T(supportedQs) = fmarginal.T(:);
+
+% For dynamic (recurrent) net-------------------------------------------------------------
+% ----------------------------------------------------------------------------------------
+high=size(evidence,1);                                  % slice height
+ss_ns=ns(1:high);                                       % single slice nodes sizes
+pos=self;                                               %
+slice_num=0;                                            %
+while pos>high,                                         % 
+    slice_num=slice_num+1;                              % find active slice
+    pos=pos-high;                                       % pos=self posistion into a single slice
+end                                                     %
+
+last_dim=pos-1;                                         % 
+if isempty(evidence{self}),                             % 
+    last_dim=pos;                                       %
+end                                                     % last_dim=last reshaping dimension      
+reg=dom-slice_num*high;
+dex=myintersect(reg(find(reg>=0)), [1:last_dim]);       %           
+rs_dim=ss_ns(dex);                                      % reshaping dimensions
+
+if slice_num>0,
+    act_slice=[]; past_ancest=[];                       %
+    act_slice=slice_num*high+[1:high];                  % recover the active slice nodes
+    % past_ancest=mysetdiff(ddom, act_slice);
+    past_ancest=mysetdiff(ps, act_slice);               % recover ancestors contained into past slices
+    app=ns(past_ancest);
+    rs_dim=[app(:)' rs_dim(:)'];                        %
+end                                                     %
+if length(rs_dim)==1, rs_dim=[1 rs_dim]; end            %
+if size(rs_dim,1)~=1, rs_dim=rs_dim';    end            %
+
+fullm.T=reshape(fullm.T, rs_dim);                       % reshaping the marginal
+
+% ----------------------------------------------------------------------------------------
+% ----------------------------------------------------------------------------------------
+
+% X = cts parent, R = discrete self
+
+% 1) observations vector -> CPD.parents_vals -------------------------------------------------
+x = cat(1, evidence{cdom});
+
+% 2) weights vector -> CPD.eso_weights -------------------------------------------------------
+if isempty(evidence{self}) % R is hidden
+    sum_over=length(rs_dim);
+    app=sum(fullm.T, sum_over);    
+    pesi=reshape(app,[dpsz,1]);
+    clear app;
+else
+    pesi=reshape(fullm.T,[dpsz,1]);
+end
+
+assert(approxeq(sum(pesi),1));
+
+% 3) estimate (if R is hidden) or recover (if R is obs) self'value----------------------------
+if isempty(evidence{self})              % R is hidden    
+    app=mk_stochastic(fullm.T);         % P(self|Pa1,...,Pak)=fmarginal/prob(Pa1,...,Pak)
+    app=reshape(app,[dpsz ns(self)]);   % matrix size: prod{j,ns(Paj)} x ns(self)      
+    r=app;
+    clear app;
+else
+    r = zeros(dpsz,ns(self));
+    for i=1:dpsz
+        if pesi(i)~=0, r(i,evidence{self}) = 1; end
+    end
+end
+for i=1:dpsz
+    if pesi(i) ~=0, assert(approxeq(sum(r(i,:)),1)); end
+end
+
+CPD.nsamples = CPD.nsamples + 1;            
+CPD.parent_vals(CPD.nsamples,:) = x(:)';
+for i=1:dpsz
+    CPD.eso_weights(CPD.nsamples,:,i)=pesi(i);
+    CPD.self_vals(CPD.nsamples,:,i) = r(i,:); 
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@noisyor_CPD/CPD_to_CPT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,34 @@
+function CPT = CPD_to_CPT(CPD)
+% CPD_TO_CPT Convert the discrete CPD to tabular form (noisyor)
+% CPT = CPD_to_CPT(CPD)
+%
+% CPT(U1,...,Un, X) = Pr(X|U1,...,Un) where the Us are the parents (excluding leak).
+
+if ~isempty(CPD.CPT)
+  CPT = CPD.CPT; % remember to flush cache if params change (e.g., during learning)
+  return;
+end
+
+q = [CPD.leak_inhibit CPD.inhibit(:)'];
+% q(i) is the prob. that the i'th parent will be inhibited (flipped from 1 to 0).
+% q(1) is the leak inhibition probability, and length(q) = n + 1.
+
+if length(q)==1
+  CPT = [q  1-q];
+  return;
+end
+
+n = length(q);
+Bn = ind2subv(2*ones(1,n), 1:(2^n))-1;  % all n bit vectors, with the left most column toggling fastest (LSB)
+CPT = zeros(2^n, 2);
+% Pr(X=0 | U_1 .. U_n) = prod_{i: U_i = on} q_i =  prod_i q_i ^ U_i = exp(u' * log(q_i))
+% This method is problematic when q contains zeros
+
+Q = repmat(q(:)', 2^n, 1);
+Q(logical(~Bn)) = 1;
+CPT(:,1) = prod(Q,2);
+CPT(:,2) = 1-CPT(:,1);
+
+CPT = reshape(CPT(2:2:end), 2*ones(1,n)); % skip cases in which the leak is off       
+
+CPD.CPT = CPT;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@noisyor_CPD/CPD_to_lambda_msg.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function lam_msg = CPD_to_lambda_msg(CPD, msg_type, n, ps, msg, p, evidence)
+% CPD_TO_LAMBDA_MSG Compute lambda message (noisyor)
+% lam_msg = CPD_to_lambda_msg(CPD, msg_type, n, ps, msg, p)
+% Pearl p190 top eqn
+
+switch msg_type
+  case 'd', 
+   l0 = msg{n}.lambda(1);
+   l1 = msg{n}.lambda(2);
+   Pi = sum_prod_CPD_and_pi_msgs(CPD, n, ps, msg, p);
+   i = find(p==ps); % p is n's i'th parent
+   q = CPD.inhibit(i);
+   lam_msg = zeros(2,1);
+   for u=0:1
+     lam_msg(u+1) = l1 - (q^u)*(l1 - l0)*Pi;
+   end       
+ case 'g',
+  error('noisyor_CPD can''t create Gaussian msgs')
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@noisyor_CPD/CPD_to_pi.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function pi = CPD_to_pi(CPD, msg_type, n, ps, msg, evidence)
+% CPD_TO_PI Compute pi vector (noisyor)
+% pi = CPD_to_pi(CPD, msg_type, n, ps, msg)
+% Pearl p188 eqn 4.57
+  
+switch msg_type
+ case 'd',
+   pi = sum_prod_CPD_and_pi_msgs(CPD, n, ps, msg);
+   pi = [pi 1-pi]';
+ case 'g', 
+  error('can''t convert noisy-or CPD to Gaussian pi')
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@noisyor_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+/CPD_to_CPT.m/1.1.1.1/Mon Aug  2 22:23:32 2004//
+/CPD_to_lambda_msg.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/CPD_to_pi.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/noisyor_CPD.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@noisyor_CPD/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@noisyor_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@noisyor_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@noisyor_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@noisyor_CPD/noisyor_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,79 @@
+function CPD = noisyor_CPD(bnet, self, leak_inhibit, inhibit)
+% NOISYOR_CPD Make a noisy-or CPD
+% CPD = NOISYOR_CPD(BNET, NODE_NUM, LEAK_INHIBIT, INHIBIT)
+%
+% A noisy-or node turns on if any of its parents are on, provided they are not inhibited.
+% The prob. that the i'th parent gets inhibited (flipped from 1 to 0) is inhibit(i).
+% The prob that the leak node (a dummy parent that is always on) gets inhibit is leak_inhibit.
+% These params default to random values if omitted.
+%
+% Example: suppose C has parents A and B, and the
+% link of A->C fails with prob pA and the link B->C fails with pB.
+% Then the noisy-OR gate defines the following distribution
+%
+%  A  B  P(C=0)
+%  0  0  1.0
+%  1  0  pA
+%  0  1  pB
+%  1  1  pA * PB
+%
+% Currently, learning is not supported for noisy-or nodes
+% (since the M step is somewhat complicated).
+%
+% For simple generalizations of the noisy-OR model, see e.g.,
+% - Srinivas, "A generalization of the noisy-OR model", UAI 93
+% - Meek and Heckerman, "Learning Causal interaction models", UAI 97.
+  
+
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  CPD = class(CPD, 'noisyor_CPD', discrete_CPD(1, []));
+  return;
+elseif isa(bnet, 'noisyor_CPD')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+CPD = init_fields;
+
+
+ps = parents(bnet.dag, self);
+fam = [ps self];
+ns = bnet.node_sizes;
+assert(all(ns(fam)==2));
+assert(isempty(myintersect(fam, bnet.cnodes)));
+
+if nargin < 3, leak_inhibit = rand(1, 1); end
+if nargin < 4, inhibit = rand(1, length(ps)); end
+
+CPD.self = self;
+CPD.inhibit = inhibit;
+CPD.leak_inhibit = leak_inhibit;
+
+
+% For BIC
+CPD.nparams = 0;
+CPD.nsamples = 0;
+
+CPD.CPT = []; % cached copy, to speed up CPD_to_CPT
+
+clamped = 1;
+CPD = class(CPD, 'noisyor_CPD', discrete_CPD(clamped, ns([ps self])));
+
+
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.self = [];
+CPD.inhibit = [];
+CPD.leak_inhibit = [];
+CPD.nparams = [];
+CPD.nsamples = [];
+CPD.CPT = [];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@noisyor_CPD/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/sum_prod_CPD_and_pi_msgs.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@noisyor_CPD/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@noisyor_CPD/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@noisyor_CPD/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@noisyor_CPD/private/sum_prod_CPD_and_pi_msgs.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function pi = sum_prod_CPD_and_pi_msgs(CPD, n, ps, msg, except)
+% SUM_PROD_CPD_AND_PI_MSGS Compute pi = sum_{u\p} P(n|u) prod_{ui in ps\p} pi_msg(ui->n)
+% pi = sum_prod_CPD_and_pi_msgs(CPD, n, ps, msg, p)
+%
+% pi  = prod_i (qi pi_msg(ui->n) + 1 - pi_msg(ui->n)) = prod_i (1 - ci pi_msg(ui->n))
+% is the product of the endorsement withheld (Pearl p188 eqn 4.56)
+% We skip p from this product, if specified.
+
+if nargin < 5, except = -1; end
+pi = 1;
+for i=1:length(ps)
+  p = ps(i);
+  if p ~= except
+    pi_from_parent = msg{n}.pi_from_parent{i};
+    q = CPD.inhibit(i);
+    c = 1-q;
+    pi = pi * (1 - c*pi_from_parent(2));
+  end
+end
+% The pi msg that a leak node sends to its child is [0 1]
+% since its own pi is [0 1] and its lambda to self is [0 1].
+q = CPD.leak_inhibit;
+% 1 - c*pi_from_parent = 1-c*1 = q
+pi = pi * q;
+                 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/CPD_to_pi.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function pi = CPD_to_pi(CPD, msg_type, n, ps, msg, evidence)
+% CPD_TO_PI Compute the pi vector (root)
+% function pi = CPD_to_pi(CPD, msg_type, n, ps, msg, evidence)
+
+self_ev = evidence{n};
+switch msg_type
+ case 'd',
+  error('root_CPD can''t create discrete msgs')
+ case 'g',
+  pi.mu = self_ev;
+  pi.Sigma = zeros(size(self_ev));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/CPD_to_pi.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/convert_to_pot.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/log_marg_prob_node.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/log_prob_node.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/root_CPD.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/sample_node.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@root_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/Old/CPD_to_CPT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function CPT = CPD_to_CPT(CPD)
+% CPD_TO_CPT Convert the CPD to tabular form (root)
+% CPT = CPD_to_CPT(CPD)
+
+CPT = 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/CPD_to_CPT.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@root_CPD/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/convert_to_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function pot = convert_to_pot(CPD, pot_type, domain, evidence)
+% CONVERT_TO_POT Convert a root CPD to one or more potentials
+% pots = convert_to_pot(CPD, pot_type, domain, evidence)
+
+assert(length(domain)==1);
+assert(~isempty(evidence(domain)));
+T = 1;   
+
+sz = CPD.sizes;
+ns = zeros(1, max(domain));
+ns(domain) = sz;
+
+switch pot_type
+ case 'u',
+  pot = upot(domain, 1, T, 0);
+ case 'd',
+  ns(domain) = 1;
+  pot = dpot(domain, ns(domain), T);          
+ case {'c','g'},
+  ns(domain) = 0;
+  pot = cpot(domain, ns(domain), 0);
+ case 'cg',
+  ddom = [];
+  cdom = domain; % we assume the root node is cts
+  %pot = cgpot(ddom, cdom, ns, {cpot([],[],0)});
+  pot = cgpot(ddom, cdom, ns);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/log_marg_prob_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function L = log_marg_prob_node(CPD, self_ev, pev)
+% LOG_MARG_PROB_NODE Compute prod_m log int_{theta_i} P(x(i,m)| x(pi_i,m), theta_i) for node i (root)
+% L = log_marg_prob_node(CPD, self_ev, pev)
+%
+% self_ev{m} is the evidence on this node in case m
+% pev{i,m} is the evidence on the i'th parent in case m (ignored)
+% We always return L = 0.
+
+L = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/log_prob_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function L = log_prob_node(CPD, self_ev, pev)
+% LOG_PROB_NODE Compute prod_m log P(x(i,m)| x(pi_i,m), theta_i) for node i (root)
+% L = log_prob_node(CPD, self_ev, pev)
+%
+% self_ev{m} is the evidence on this node in case m
+% pev{i,m} is the evidence on the i'th parent in case m (ignored)
+% We always return L = 0.
+
+L = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/root_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,48 @@
+function CPD = root_CPD(bnet, self, val)
+% ROOT_CPD Make a conditional prob. distrib. which has no parameters.
+% CPD = ROOT_CPD(BNET, NODE_NUM, VAL)
+%
+% The node must not have any parents and is assumed to always be observed.
+% It is a way of modelling exogenous inputs to a model.
+% VAL is the value to which the root is clamped (default: [])
+
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  CPD = class(CPD, 'root_CPD', generic_CPD(1));
+  return;
+elseif isa(bnet, 'root_CPD')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+CPD = init_fields;
+
+
+if nargin < 3, val = []; end
+
+ns = bnet.node_sizes;
+ps = parents(bnet.dag, self);
+if ~isempty(ps)
+  error('root CPDs should have no parents')
+end
+
+CPD.self = self;
+CPD.val = val;
+CPD.sizes = ns(self);
+
+clamped = 1;
+CPD = class(CPD, 'root_CPD', generic_CPD(clamped));
+
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.self = [];
+CPD.val = [];
+CPD.sizes = [];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@root_CPD/sample_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function y = sample_node(CPD, pev)
+% SAMPLE_NODE Draw a random sample from P(Y|pa(y), theta)  (root)
+% Y = SAMPLE_NODE(CPD, PEV)
+%
+% pev{i} is the evidence on the i'th parent.
+% Since a root has no parents, we ignore pev,
+% and return the value the root was clamped to when it was created.
+
+y = CPD.val;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+/convert_to_pot.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/convert_to_table.m/1.1.1.1/Tue Mar 30 17:19:22 2004//
+/display.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/get_field.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/maximize_params.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/reset_ess.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/sample_node.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/set_fields.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/softmax_CPD.m/1.1.1.1/Tue Jan  7 16:25:14 2003//
+/update_ess.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@softmax_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/convert_to_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+function pot = convert_to_pot(CPD, pot_type, domain, evidence)
+% CONVERT_TO_POT Convert a softmax CPD to a potential
+% pots = convert_to_pot(CPD, pot_type, domain, evidence)
+%
+% pots = CPD evaluated using evidence(domain)
+
+ncases = size(domain,2);
+assert(ncases==1); % not yet vectorized
+
+sz = dom_sizes(CPD);
+ns = zeros(1, max(domain));
+ns(domain) = sz;
+
+odom = domain(~isemptycell(evidence(domain)));
+T = convert_to_table(CPD, domain, evidence);
+
+switch pot_type
+ case 'u',
+  pot = upot(domain, sz, T, 0*myones(sz));  
+ case 'd',
+  ns(odom) = 1;
+  pot = dpot(domain, ns(domain), T);          
+ 
+ case {'c','g'},
+  % Since we want the output to be a Gaussian, the whole family must be observed.
+  % In other words, the potential is really just a constant.
+  p = T;
+  %p = prob_node(CPD, evidence(domain(end)), evidence(domain(1:end-1)));
+  ns(domain) = 0;
+  pot = cpot(domain, ns(domain), log(p));       
+ 
+ case 'cg',
+  T = T(:);
+  ns(odom) = 1;
+  can = cell(1, length(T));
+  for i=1:length(T)
+    can{i} = cpot([], [], log(T(i)));
+  end
+  ps = domain(1:end-1);
+  dps = ps(CPD.dpndx);
+  cps = ps(CPD.cpndx);
+  ddom = [dps CPD.self];
+  cdom = cps;
+  pot = cgpot(ddom, cdom, ns, can);   
+  
+ case 'scg'
+  T = T(:);
+  ns(odom) = 1;
+  pot_array = cell(1, length(T));
+  for i=1:length(T)
+    pot_array{i} = scgcpot([], [], T(i));
+  end
+  pot = scgpot(domain, [], [], ns, pot_array);   
+
+ otherwise,
+  error(['unrecognized pot type ' pot_type])
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/convert_to_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+function T = convert_to_table(CPD, domain, evidence)
+% CONVERT_TO_TABLE Convert a softmax CPD to a table, incorporating any evidence 
+% T = convert_to_table(CPD, domain, evidence)
+
+self       = domain(end);             
+ps         = domain(1:end-1);                            
+cnodes     = domain(CPD.cpndx);
+cps        = myintersect(ps, cnodes);
+dps        = domain(CPD.dpndx); 
+dps_as_cps = domain(CPD.dps_as_cps.ndx);
+all_dps    = union(dps,dps_as_cps);
+odom       = domain(~isemptycell(evidence(domain))); 
+if ~isempty(cps), assert(myismember(cps, odom)); end % all cts parents must be observed
+
+ns         = zeros(1, max(domain));
+ns(domain) = CPD.sizes;
+ens        = ns; % effective node sizes
+ens(odom)  = 1;
+
+% dpsize >= glimsz because the glm parameters are tied across the dps_as_cps parents
+dpsize       = prod(ens(all_dps)); % size of ALL self'discrete parents
+dpvals       = cat(1, evidence{myintersect(all_dps, odom)});
+cpvals       = cat(1, evidence{cps});
+if ~isempty(dps_as_cps),
+  separator          = CPD.dps_as_cps.separator;
+  dp_as_cpmap        = find_equiv_posns(dps_as_cps, all_dps);
+  dops_map           = find_equiv_posns(myintersect(all_dps, odom), all_dps);
+  puredp_map         = find_equiv_posns(dps, all_dps);
+  subs               = ind2subv(ens(all_dps), 1:prod(ens(all_dps)));
+  if ~isempty(dops_map), subs(:,dops_map) = subs(:,dops_map)+repmat(dpvals(:)',[size(subs,1) 1])-1; end
+end
+
+[w,b] = extract_params(CPD);
+T = zeros(dpsize, ns(self));                                       
+for i=1:dpsize,    
+  active_glm  = i;
+  dp_as_cpvals=zeros(1,sum(ns(dps_as_cps)));                                                                  
+  if ~isempty(dps_as_cps),                          
+    active_glm = max([1,subv2ind(ns(dps), subs(i,puredp_map))]);
+    % Extract the params compatible with the observations (if any) on the 'pure' discrete parents (if any)
+    where_one = separator + subs(i,dp_as_cpmap);
+    % and get in the dp_as_cp parents...
+    dp_as_cpvals(where_one)=1;                    
+  end                                               
+  T(i,:) = normalise(exp([dp_as_cpvals(:); cpvals(:)]'*w(:,:,active_glm) + b(:,active_glm)'));
+end
+if myismember(self, odom)
+  r = evidence{self};
+  T = T(:,r);
+end
+
+T = myreshape(T, ens(domain));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function display(CPD)
+
+disp('softmax_CPD object');
+disp(struct(CPD)); 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/get_field.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function val = get_params(CPD, name)
+% GET_PARAMS Get the parameters (fields) for a softmax_CPD object
+% val = get_params(CPD, name)
+%
+% The following fields can be accessed
+%
+% weights - W(X,Y,Q)
+% offset  - b(Y,Q)
+%
+% e.g., W = get_params(CPD, 'weights')
+
+[W, b] = extract_params(CPD);
+switch name
+ case 'weights',   val = W;
+ case 'offset',    val = b;
+ otherwise,
+  error(['invalid argument name ' name]);
+end                
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/maximize_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,41 @@
+function CPD = maximize_params(CPD, temp)
+% MAXIMIZE_PARAMS Set the params of a CPD to their ML values (dsoftmax) using IRLS
+% CPD = maximize_params(CPD, temperature)
+% temperature parameter is ignored
+
+% Written by Pierpaolo Brutti
+
+if ~adjustable_CPD(CPD), return; end
+options = foptions;
+
+if CPD.verbose
+  options(1) = 1;
+else
+  options(1) = -1;
+end
+%options(1) = CPD.verbose;
+
+options(2) = CPD.wthresh;
+options(3) = CPD.llthresh;
+options(5) = CPD.approx_hess;
+options(14) = CPD.max_iter;
+
+dpsize = size(CPD.self_vals,3);
+for i=1:dpsize,
+  mask=find(CPD.eso_weights(:,:,i)>0); % for adapting the parameters we use only positive weighted example
+  if  ~isempty(mask),
+    if ~isempty(CPD.dps_as_cps.ndx),
+        puredp_map = find_equiv_posns(CPD.dpndx, union(CPD.dpndx, CPD.dps_as_cps.ndx)); % find the glm  structure
+        subs       = ind2subv(CPD.sizes(union(CPD.dpndx, CPD.dps_as_cps.ndx)),i);       % that corrisponds to the
+        active_glm = max([1,subv2ind(CPD.sizes(CPD.dpndx), subs(puredp_map))]);         % i-th 'fictitious' example
+        
+        CPD.glim{active_glm} = netopt_weighted(CPD.glim{active_glm}, options, CPD.parent_vals(mask',:,i),...
+            CPD.self_vals(mask',:,i), CPD.eso_weights(mask',:,i), 'scg');
+    else
+        alfa = 0.4; if CPD.solo, alfa = 1; end % learning step = 1 <=> self is all alone in the net
+        CPD.glim{i} = glmtrain_weighted(CPD.glim{i}, options, CPD.parent_vals(mask',:),...
+            CPD.self_vals(mask',:,i), CPD.eso_weights(mask',:,i), alfa);
+    end               
+  end
+  mask=[];
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/extract_params.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@softmax_CPD/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/private/extract_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function [W, b] = extract_params(CPD)
+
+% W(X,Y,Q), b(Y,Q)  where Y = ns(self), X = ns(cps), Q = prod(ns(dps))
+
+glimsz = prod(CPD.sizes(CPD.dpndx));
+ss = CPD.sizes(end);
+cpsz       = sum(CPD.sizes(CPD.cpndx));
+dp_as_cpsz = sum(CPD.sizes(CPD.dps_as_cps.ndx));
+W = zeros(dp_as_cpsz + cpsz, ss, glimsz);
+b = zeros(ss, glimsz);
+
+for i=1:glimsz
+  W(:,:,i) = CPD.glim{i}.w1;
+  b(:,i) = CPD.glim{i}.b1(:);
+end
+
+W = myreshape(W, [dp_as_cpsz + cpsz ss CPD.sizes(CPD.dpndx)]);
+b = myreshape(b, [ss CPD.sizes(CPD.dpndx)]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/reset_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function CPD = reset_ess(CPD)
+% RESET_ESS Reset the Expected Sufficient Statistics for a CPD (dsoftmax)
+% CPD = reset_ess(CPD)
+
+CPD.parent_vals = [];
+CPD.eso_weights=[];
+CPD.self_vals = [];
+CPD.nsamples = 0;  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/sample_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+function y = sample_node(CPD, pvals)
+% SAMPLE_NODE Draw a random sample from P(Xi | x(pi_i), theta_i)  (discrete)
+% y = sample_node(CPD, parent_evidence)
+%
+% parent_evidence{i} is the value of the i'th parent
+
+n = length(pvals)+1;
+dom = 1:n;
+%evidence = cell(1,n);
+%evidence(1:n-1) = pvals(:)';
+evidence = pvals;
+evidence{end+1} = [];
+T = convert_to_table(CPD, dom, evidence);
+y = sample_discrete(T);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/set_fields.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+function CPD = set_params(CPD, varargin)
+% SET_PARAMS Set the parameters (fields) for a softmax_CPD object
+% CPD = set_params(CPD, name/value pairs)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% (Let ns(i) be the size of node i, X = ns(X), Y = ns(Y), Q1=ns(dps(1)), Q2=ns(dps(2)), ...
+%   where dps are the discrete parents; if there are no discrete parents, we set Q1=1.)
+%
+% weights - (W(:,j,a,b,...) - W(:,j',a,b,...)) is ppn to dec. boundary
+%           between j,j' given Q1=a,Q2=b,... [ randn(X,Y,Q1,Q2,...) ]
+% offset  - (offset(j,a,b,...) - offset(j',a,b,...)) is the offset to dec. boundary
+%           between j,j' given Q1=a,Q2=b,... [ randn(Y,Q1,Q2,...) ]
+% clamped     - 'yes' means don't adjust params during learning ['no']
+% max_iter    - the maximum number of steps to take [10]
+% verbose     - 'yes' means print the LL at each step of IRLS ['no']
+% wthresh     - convergence threshold for weights [1e-2]
+% llthresh    - convergence threshold for log likelihood [1e-2]
+% approx_hess - 'yes' means approximate the Hessian for speed ['no']
+%
+% e.g., CPD = set_params(CPD,'offset', zeros(ns(i),1));
+
+args = varargin;
+nargs = length(args);
+glimsz = prod(CPD.sizes(CPD.dpndx));
+for i=1:2:nargs
+  switch args{i},
+   case 'discrete',     str='nothing to do';   
+   case 'clamped',      CPD = set_clamped(CPD, strcmp(args{i+1}, 'yes'));
+   case 'max_iter',     CPD.max_iter = args{i+1};
+   case 'verbose',      CPD.verbose = strcmp(args{i+1}, 'yes');
+   case 'max_iter',     CPD.max_iter = args{i+1};
+   case 'wthresh',      CPD.wthresh = args{i+1};
+   case 'llthresh',     CPD.llthresh = args{i+1};
+   case 'approx_hess',  CPD.approx_hess = strcmp(args{i+1}, 'yes');
+   case 'weights',      for q=1:glimsz, CPD.glim{q}.w1 = args{i+1}(:,:,q); end; 
+   case 'offset',
+    if glimsz == 1
+      CPD.glim{1}.b1 = args{i+1};
+    else
+      for q=1:glimsz, CPD.glim{q}.b1 = args{i+1}(:,q); end; 
+    end
+   otherwise,  
+    error(['invalid argument name ' args{i}]);       
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/softmax_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,187 @@
+function CPD = softmax_CPD(bnet, self, varargin)
+% SOFTMAX_CPD Make a softmax (multinomial logit) CPD
+%
+% To define this CPD precisely, let W be an (m x n) matrix with W(i,:) = {i-th row of B} 
+% => we can define the following vectorial function:
+%    
+%                                   softmax: R^n |--> R^m  
+%                  softmax(z,i-th)=exp(W(i,:)*z)/sum_k(exp(W(k,:)*z))      
+%
+% (this constructor augments z with a one at the beginning to introduce an offset term (=bias, intercept))                                   
+% Now call the continuous (cts) and always observed (obs) parents X,
+% the discrete parents (if any) Q, and this node Y then we use the discrete parent(s) just  to index
+% the parameter vectors (c.f., conditional Gaussian nodes); that is:
+%                 prob(Y=i | X=x, Q=j) = softmax(x,i-th|j)
+% where '|j' means that we are using the j-th (m x n) parameters matrix W(:,:,j).
+% If there are no discrete parents, this is a regular softmax node.
+% If Y is binary, this is a logistic (sigmoid) function.
+%
+% CPD = softmax_CPD(bnet, node_num, ...) will create a softmax CPD with random parameters,
+% where node is the number of a node in this equivalence class.
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+% (Let ns(i) be the size of node i, X = ns(X), Y = ns(Y), Q1=ns(dps(1)), Q2=ns(dps(2)), ...
+% where dps are the discrete parents; if there are no discrete parents, we set Q1=1.)
+%
+% discrete - the discrete parents that we want to treat like the cts ones [ [] ]. 
+%            This can be used to define sigmoid belief network - see below the reference.             
+%            For example suppose that Y has one cts parents X and two discrete ones: Q, C1 where:
+%            -> Q is binary (1/2) and used just to index the parameters of 'self'
+%            -> C1 is ternary (1/2/3) and treated as a cts node <=> its values appear into the linear 
+%               part of the softmax function
+%            then:
+%                     prob(Y|X=x, Q=q, C1=c1)= softmax(W(:,:,q)' * y)
+%            where y = [1 | delta(C1,1) delta(C1,2) delta(C1,3) | x(:)']' and delta(Y,a)=indicator(Y=a).
+% weights - (w(:,j,a,b,...) - w(:,j',a,b,...)) is ppn to dec. boundary
+%           between j,j' given Q1=a,Q2=b,... [ randn(X,Y,Q1,Q2,...) ]
+% offset  - (b(j,a,b,...) - b(j',a,b,...)) is the offset to dec. boundary
+%           between j,j' given Q1=a,Q2=b,... [ randn(Y,Q1,Q2,...) ]
+%
+% e.g., CPD = softmax_CPD(bnet, i, 'offset', zeros(ns(i),1));
+%
+% The following fields control the behavior of the M step, which uses 
+% a weighted version of the Iteratively Reweighted Least Squares (WIRLS) if dps_as_cps=[]; or
+% a weighted SCG otherwise, as implemented in Netlab, and modified by Pierpaolo Brutti.
+%
+% clamped     - 'yes' means don't adjust params during learning ['no']
+% max_iter    - the maximum number of steps to take [10]
+% verbose     - 'yes' means print the LL at each step of IRLS ['no']
+% wthresh     - convergence threshold for weights [1e-2]
+% llthresh    - convergence threshold for log likelihood [1e-2]
+% approx_hess - 'yes' means approximate the Hessian for speed ['no']
+%
+% For backwards compatibility with BNT2, you can also specify the parameters in the following order
+%   softmax_CPD(bnet, self, w, b, clamped, max_iter, verbose, wthresh, llthresh, approx_hess)
+%
+% REFERENCE
+% For details on the sigmoid belief nets, see:
+% - Neal (1992). Connectionist learning of belief networks, Artificial Intelligence, 56, 71-113.
+% - Saul, Jakkola, Jordan (1996). Mean field theory for sigmoid belief networks, Journal of Artificial Intelligence Reseach (4), pagg. 61-76.
+%
+% For details on the M step, see:
+% - K. Chen, L. Xu, H. Chi (1999). Improved learning algorithms for mixtures of experts in multiclass 
+%       classification. Neural Networks 12, pp. 1229-1252.
+% - M.I. Jordan, R.A. Jacobs (1994). Hierarchical Mixtures of Experts and the EM algorithm. 
+%       Neural Computation 6, pp. 181-214.
+% - S.R. Waterhouse, A.J. Robinson (1994). Classification Using Hierarchical Mixtures of Experts. In Proc. IEEE
+%       Workshop on Neural Network for Signal Processing IV, pp. 177-186
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  CPD = class(CPD, 'softmax_CPD', discrete_CPD(0, []));
+  return;
+elseif isa(bnet, 'softmax_CPD')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+CPD = init_fields;
+
+assert(myismember(self, bnet.dnodes));
+ns = bnet.node_sizes;
+ps = parents(bnet.dag, self);
+dps = myintersect(ps, bnet.dnodes);
+cps = myintersect(ps, bnet.cnodes);
+
+clamped = 0;
+CPD = class(CPD, 'softmax_CPD', discrete_CPD(clamped, ns([ps self])));
+
+dps_as_cpssz = 0;
+dps_as_cps = [];
+% determine if any discrete parents are to be treated as cts
+if nargin >= 3 & isstr(varargin{1}) % might have passed in 'discrete'
+  for i=1:2:length(varargin)
+    if strcmp(varargin{i}, 'discrete')
+      dps_as_cps = varargin{i+1};
+      assert(myismember(dps_as_cps, dps));
+      dps = mysetdiff(dps, dps_as_cps);         % put out the dps treated as cts
+      CPD.dps_as_cps.ndx = find_equiv_posns(dps_as_cps, ps);
+      CPD.dps_as_cps.separator = [0 cumsum(ns(dps_as_cps(1:end-1)))]; % concatenated dps_as_cps dims separators
+      dps_as_cpssz = sum(ns(dps_as_cps));
+      break;
+    end
+  end
+end
+assert(~isempty(union(cps, dps_as_cps)));   % It have to be at least a cts or a dps_as_cps parents
+self_size = ns(self); 
+cpsz = sum(ns(cps));  
+glimsz = prod(ns(dps));
+CPD.dpndx = find_equiv_posns(dps, ps);  % it contains only the indeces of the 'pure' dps
+CPD.cpndx = find_equiv_posns(cps, ps);
+
+CPD.self  = self;
+CPD.solo  = (length(ns)<=2);
+CPD.sizes = bnet.node_sizes([ps self]);
+
+% set default params
+CPD.max_iter = 10;
+CPD.verbose = 0;
+CPD.wthresh = 1e-2;
+CPD.llthresh = 1e-2;
+CPD.approx_hess = 0;
+CPD.glim = cell(1,glimsz);
+for i=1:glimsz
+  CPD.glim{i} = glm(dps_as_cpssz + cpsz, self_size, 'softmax');
+end
+
+if nargin >= 3
+  args = varargin;
+  nargs = length(args);
+  if ~isstr(args{1})
+    %   softmax_CPD(bnet, self, w, b, clamped, max_iter, verbose, wthresh, llthresh, approx_hess)
+    if nargs >= 1 & ~isempty(args{1}), CPD = set_fields(CPD, 'weights', args{1}); end
+    if nargs >= 2 & ~isempty(args{2}), CPD = set_fields(CPD, 'offset', args{2});  end
+    if nargs >= 3 & ~isempty(args{3}), CPD = set_clamped(CPD, args{3});           end
+    if nargs >= 4 & ~isempty(args{4}), CPD.max_iter    = args{4}; end
+    if nargs >= 5 & ~isempty(args{5}), CPD.verbose     = args{5}; end
+    if nargs >= 6 & ~isempty(args{6}), CPD.wthresh     = args{6}; end
+    if nargs >= 7 & ~isempty(args{7}), CPD.llthresh   = args{7}; end
+    if nargs >= 8 & ~isempty(args{8}), CPD.approx_hess = args{8}; end
+  else
+    CPD = set_fields(CPD, args{:});
+  end
+end
+
+% sufficient statistics 
+% Since dsoftmax is not in the exponential family, we must store all the raw data.
+CPD.parent_vals = [];         % X(l,:) = value of cts parents in l'th example
+CPD.self_vals = [];           % Y(l,:) = value of self in l'th example
+
+CPD.eso_weights=[];           % weights used by the WIRLS algorithm
+
+% For BIC
+CPD.nsamples = 0;   
+if ~adjustable_CPD(CPD),
+   CPD.nparams=0;
+else
+   [W, b] = extract_params(CPD);
+   CPD.nparams= prod(size(W)) + prod(size(b));
+end
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.glim = {};
+CPD.self = [];
+CPD.solo = [];
+CPD.max_iter = [];
+CPD.verbose = [];
+CPD.wthresh = [];
+CPD.llthresh = [];
+CPD.approx_hess = [];
+CPD.sizes = [];
+CPD.parent_vals = [];
+CPD.eso_weights=[];
+CPD.self_vals = [];
+CPD.nsamples = [];
+CPD.nparams = [];
+CPD.dpndx = [];
+CPD.cpndx = [];
+CPD.dps_as_cps.ndx = [];
+CPD.dps_as_cps.separator = [];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@softmax_CPD/update_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,97 @@
+function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+% UPDATE_ESS Update the Expected Sufficient Statistics of a softmax node
+% function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+%
+% fmarginal = overall posterior distribution of self and its parents
+% fmarginal(i1,i2...,ik,s)=prob(Pa1=i1,...,Pak=ik, self=s| X)
+% 
+% => 1) prob(self|Pa1,...,Pak)=fmarginal/prob(Pa1,...,Pak) with prob(Pa1,...,Pak)=sum{s,fmarginal}
+%       [self estimation -> CPD.self_vals]
+% 	  2) prob(Pa1,...,Pak) [WIRLS weights -> CPD.eso_weights]
+%
+% Hidden_bitv is ignored
+
+% Written by Pierpaolo Brutti
+
+if ~adjustable_CPD(CPD), return; end
+
+domain     = fmarginal.domain;                              
+self       = domain(end);          
+ps         = domain(1:end-1);                                     
+cnodes     = domain(CPD.cpndx);
+cps        = myintersect(domain, cnodes);                     
+dps        = mysetdiff(ps, cps);                            
+dn_use     = dps;
+if isempty(evidence{self}) dn_use = [dn_use self]; end % if self is hidden we must consider its dimension  
+dps_as_cps = domain(CPD.dps_as_cps.ndx);
+odom       = domain(~isemptycell(evidence(domain))); 
+
+ns = zeros(1, max(domain));
+ns(domain) = CPD.sizes;     % CPD.sizes = bnet.node_sizes([ps self]);
+ens = ns;                   % effective node sizes
+ens(odom) = 1;              
+dpsize = prod(ns(dps));
+
+% Extract the params compatible with the observations (if any) on the discrete parents (if any)
+dops = myintersect(dps, odom);
+dpvals = cat(1, evidence{dops});
+
+subs = ind2subv(ens(dn_use), 1:prod(ens(dn_use)));
+dpmap = find_equiv_posns(dops, dn_use);
+if ~isempty(dpmap), subs(:,dpmap) = subs(:,dpmap)+repmat(dpvals(:)',[size(subs,1) 1])-1; end
+supportedQs = subv2ind(ns(dn_use), subs); subs=subs(1:prod(ens(dps)),1:length(dps));
+Qarity = prod(ns(dn_use));
+if isempty(dn_use), Qarity = 1; end   
+
+fullm.T              = zeros(Qarity, 1);
+fullm.T(supportedQs) = fmarginal.T(:);
+rs_dim = CPD.sizes;    rs_dim(CPD.cpndx) = 1;           %
+if ~isempty(evidence{self}), rs_dim(end)=1; end         % reshaping the marginal
+fullm.T              = reshape(fullm.T, rs_dim);        %
+
+% --------------------------------------------------------------------------------UPDATE--
+
+CPD.nsamples = CPD.nsamples + 1;
+
+% 1) observations vector -> CPD.parents_vals ---------------------------------------------
+cpvals = cat(1, evidence{cps});
+
+if ~isempty(dps_as_cps),   % ...get in the dp_as_cp parents... 
+    separator          = CPD.dps_as_cps.separator;
+    dp_as_cpmap        = find_equiv_posns(dps_as_cps, dps);       
+    for i=1:dpsize,
+        dp_as_cpvals=zeros(1,sum(ns(dps_as_cps)));
+        possible_vals = ind2subv(ns(dps),i);
+        ll=find(ismember(subs(:,dp_as_cpmap), possible_vals(dp_as_cpmap), 'rows')==1);   
+        if ~isempty(ll),
+            where_one = separator + possible_vals(dp_as_cpmap);
+            dp_as_cpvals(where_one)=1;                            
+        end
+        CPD.parent_vals(CPD.nsamples,:,i) = [dp_as_cpvals(:); cpvals(:)]';
+    end
+else
+    CPD.parent_vals(CPD.nsamples,:) = cpvals(:)';
+end
+
+% 2) weights vector -> CPD.eso_weights ----------------------------------------------------
+if isempty(evidence{self}),             % self is hidden
+    pesi=reshape(sum(fullm.T, length(rs_dim)),[dpsize,1]);
+else
+    pesi=reshape(fullm.T,[dpsize,1]);
+end
+assert(approxeq(sum(pesi),1));          % check
+
+% 3) estimate (if R is hidden) or recover (if R is obs) self'value-------------------------
+if isempty(evidence{self})                                  % P(self|Pa1,...,Pak)=fmarginal/prob(Pa1,...,Pak)
+    r=reshape(mk_stochastic(fullm.T), [dpsize ns(self)]);   % matrix size: prod{j,ns(Paj)} x ns(self)      
+else
+    r = zeros(dpsize,ns(self));
+    for i=1:dpsize, if pesi(i)~=0, r(i,evidence{self}) = 1; end; end
+end
+for i=1:dpsize, if pesi(i)~=0, assert(approxeq(sum(r(i,:)),1)); end; end     % check
+
+% 4) save the previous values --------------------------------------------------------------
+for i=1:dpsize
+    CPD.eso_weights(CPD.nsamples,:,i)=pesi(i);
+    CPD.self_vals(CPD.nsamples,:,i) = r(i,:); 
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/CPD_to_CPT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function CPT = CPD_to_CPT(CPD)
+% CPD_TO_CPT Convert the discrete CPD to tabular form (tabular)
+% CPT = CPD_to_CPT(CPD)
+
+CPT = CPD.CPT;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+/CPD_to_CPT.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/bayes_update_params.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/display.m/1.1.1.1/Tue Apr 22 21:00:02 2003//
+/get_field.m/1.1.1.1/Sun Jan 16 02:27:30 2005//
+/learn_params.m/1.1.1.1/Thu Jun 10 01:25:02 2004//
+/log_marg_prob_node.m/1.1.1.1/Fri Jun 11 21:16:00 2004//
+/log_nextcase_prob_node.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/log_prior.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/maximize_params.m/1.1.1.1/Sun Mar  9 22:44:40 2003//
+/reset_ess.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/set_fields.m/1.1.1.1/Sun Jan 16 02:27:30 2005//
+/tabular_CPD.m/1.1.1.1/Sun Jan 16 02:27:32 2005//
+/update_ess.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/update_ess_simple.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@tabular_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/BIC_score_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function score = BIC_score_CPD(CPD, fam, data, ns, cnodes)
+% BIC_score_CPD Compute the BIC score of a tabular CPD
+% score = BIC_score_CPD(CPD, fam, data, ns, cnodes)
+
+if iscell(data)
+  local_data = cell2num(data(fam,:));
+else
+  local_data = data(fam, :);
+end
+counts = compute_counts(local_data, CPD.sizes);
+CPT = mk_stochastic(counts); % MLE
+tiny = exp(-700); 
+CPT = CPT + (CPT==0)*tiny;  % replace 0s by tiny
+LL = sum(log(CPT(:)) .* counts(:));
+N = size(data, 2);
+score = LL - 0.5*CPD.nparams*log(N);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+/BIC_score_CPD.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/bayesian_score_CPD.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/log_marg_prob_node_case.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/mult_CPD_and_pi_msgs.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/prob_CPT.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/prob_node.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/sample_node.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/sample_node_single_case.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/tabular_CPD.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/update_params.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@tabular_CPD/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/bayesian_score_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function score = bayesian_score_CPD(CPD, local_ev)
+% bayesian_score_CPD Compute the Bayesian score of a tabular CPD using uniform Dirichlet prior
+% score = bayesian_score_CPD(CPD, local_ev)
+%
+% The Bayesian score is the log marginal likelihood
+
+if iscell(local_ev)
+ data = num2cell(local_ev);
+else
+ data =	local_ev;
+end
+
+score = dirichlet_score_family(compute_counts(data, CPD.sizes));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/log_marg_prob_node_case.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function L = log_marg_prob_node_case(CPD, y, x)
+% LOG_MARG_PROB_NODE_CASE Compute prod_m log P(x(i,m)| x(pi_i,m)) for node i (tabular)
+% L = log_marg_prob_node_case(CPD, self_ev, parent_ev)
+% 
+% This is a slightly optimised version of log_marg_prob_node.
+% We assume we have exactly 1 case, i.e., y is a scalar and x is a vector (not a cell array).
+
+sz = CPD.sizes;
+nparents = length(sz)-1;
+
+% We assume the CPTs are already set to the mean of the posterior (due to update_params)
+
+switch nparents
+ case 0, p = CPD.CPT(y);
+ case 1, p = CPD.CPT(x(1), y);
+ case 2, p = CPD.CPT(x(1), x(2), y);
+ case 3, p = CPD.CPT(x(1), x(2), x(3), y);
+ otherwise,
+  ind = subv2ind(sz, [x y]);
+  p = CPD.CPT(ind);
+end
+L = log(p);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/mult_CPD_and_pi_msgs.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function T = mult_CPD_and_pi_msgs(CPD, n, ps, msgs, except)
+% MULT_CPD_AND_PI_MSGS Multiply the CPD and all the pi messages from parents, perhaps excepting one
+% T = mult_CPD_and_pi_msgs(CPD, n, ps, msgs, except)
+
+if nargin < 5, except = -1; end
+
+dom = [ps n];
+%ns = sparse(1, max(dom));
+ns = zeros(1, max(dom));
+ns(dom) = mysize(CPD.CPT);
+T = dpot(dom, ns(dom), CPD.CPT);
+for i=1:length(ps)
+  p = ps(i);
+  if p ~= except
+    T = multiply_by_pot(T, dpot(p, ns(p), msgs{n}.pi_from_parent{i}.T)); 
+  end
+end         
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/prob_CPT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function p = prob_CPT(CPD, x)
+% PROB_CPT Lookup the prob. of a family value in a tabular CPD
+% p = prob_CPT(CPD, x)
+%
+% This is a version of prob_CPD optimized for tables.
+
+switch length(x)
+ case 1, p = CPD.CPT(x);
+ case 2, p = CPD.CPT(x(1), x(2));
+ case 3, p = CPD.CPT(x(1), x(2), x(3));
+ case 4, p = CPD.CPT(x(1), x(2), x(3), x(4));
+ otherwise,
+  ind = subv2ind(mysize(CPD.CPT), x);
+  p = CPD.CPT(ind);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/prob_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+function p = prob_node(CPD, self_ev, pev)
+% PROB_NODE Compute P(y|pa(y), theta) (tabular)
+% p = prob_node(CPD, self_ev, pev)
+%
+% self_ev{m} is the evidence on this node in case m
+% pev{i,m} is the evidence on the i'th parent in case m
+% If there is a single case, self_ev can be a scalar instead of a cell array
+
+ncases = size(pev, 2);
+
+%assert(~any(isemptycell(pev))); % slow
+%assert(~any(isemptycell(self_ev))); % slow
+
+CPT = CPD_to_CPT(CPD);  
+sz = mysize(CPT);
+nparents = length(sz)-1;
+assert(nparents == size(pev, 1));
+
+if ncases==1 
+  x = cat(1, pev{:});
+  if iscell(y)
+    y = self_ev{1};
+  else
+    y = self_ev;
+  end
+  switch nparents
+   case 0, p = CPT(y);
+   case 1, p = CPT(x(1), y);
+   case 2, p = CPT(x(1), x(2), y);
+   case 3, p = CPT(x(1), x(2), x(3), y);
+   otherwise,
+    ind = subv2ind(CPD.sizes, [x y]);
+    p = CPT(ind);
+  end
+else
+  x = num2cell(pev)'; % each row is a case
+  y = cat(1, self_ev{:})';
+  ind = subv2ind(CPD.sizes, [x y]);
+  p = CPT(ind);
+end     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/sample_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,53 @@
+function y = sample_node(CPD, pev, nsamples)
+% SAMPLE_NODE Draw a random sample from P(Xi | x(pi_i), theta_i)  (tabular)
+% Y = SAMPLE_NODE(CPD, PEV, NSAMPLES)
+%
+% pev(i,m) is the value of the i'th parent in sample m (if there are any parents).
+% y(m) is the m'th sampled value (a row vector).
+% (If pev is a cell array, so is y.)
+% nsamples defaults to 1.
+
+if nargin < 3, nsamples = 1; end
+
+%if nargin < 4, usecell = 0; end
+if iscell(pev), usecell = 1; else usecell = 0; end
+
+if nsamples == 1, pev = pev(:); end
+
+sz = CPD.sizes; 
+nparents = length(sz)-1;
+if nparents==0
+  y = sample_discrete(CPD.CPT, 1, nsamples);
+  if usecell
+    y = num2cell(y);
+  end
+  return;
+end
+
+sz = CPD.sizes; 
+[nparents nsamples] = size(pev);
+
+if usecell
+  pvals = cell2num(pev)'; % each row is a case
+else
+  pvals = pev';
+end
+
+psz = sz(1:end-1);
+ssz = sz(end);
+ndx = subv2ind(psz, pvals);
+T = reshape(CPD.CPT, [prod(psz) ssz]);
+T2 = T(ndx,:); % each row is a distribution selected by the parents
+C = cumsum(T2, 2); % sum across columns
+R = rand(nsamples, 1);
+y = ones(nsamples, 1);
+for i=1:ssz-1
+  y = y + (R > C(:,i));
+end
+y = y(:)';
+if usecell
+  y = num2cell(y);
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/sample_node_single_case.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,39 @@
+function y = sample_node(CPD, pev)
+% SAMPLE_NODE Draw a random sample from P(Xi | x(pi_i), theta_i)  (tabular)
+% y = sample_node(CPD, pev)
+%
+% pev{i} is the value of the i'th parent (if any)
+
+%assert(~any(isemptycell(pev)));
+
+%CPT = CPD_to_CPT(CPD);
+%sz = mysize(CPT);
+sz = CPD.sizes; 
+nparents = length(sz)-1;
+if nparents > 0
+  pvals = cat(1, pev{:});
+end
+switch nparents
+ case 0, T = CPD.CPT;
+ case 1, T = CPD.CPT(pvals(1), :);
+ case 2, T = CPD.CPT(pvals(1), pvals(2), :);
+ case 3, T = CPD.CPT(pvals(1), pvals(2), pvals(3), :);
+ case 4, T = CPD.CPT(pvals(1), pvals(2), pvals(3), pvals(4), :);
+ otherwise,
+  psz = sz(1:end-1);
+  ssz = sz(end);
+  i = subv2ind(psz, pvals(:)');
+  T = reshape(CPD.CPT, [prod(psz) ssz]);
+  T = T(i,:);
+end
+
+if sz(end)==2
+  r = rand(1,1);
+  if r > T(1)
+    y = 2;
+  else
+    y = 1;
+  end
+else
+  y = sample_discrete(T);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/tabular_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,186 @@
+function CPD = tabular_CPD(bnet, self, varargin)
+% TABULAR_CPD Make a multinomial conditional prob. distrib. (CPT)
+%
+% CPD = tabular_CPD(bnet, node) creates a random CPT.
+%
+% The following arguments can be specified [default in brackets]
+%
+% CPT - specifies the params ['rnd']
+%   - T means use table T; it will be reshaped to the size of node's family.
+%   - 'rnd' creates rnd params (drawn from uniform)
+%   - 'unif' creates a uniform distribution
+%   - 'leftright' only transitions from i to i/i+1 are allowed, for each non-self parent context.
+%       The non-self parents are all parents except oldself.
+% selfprob - The prob of transition from i to i if CPT = 'leftright' [0.1]
+% old_self - id of the node corresponding to self in the previous slice [self-ss]
+% adjustable - 0 means don't adjust the parameters during learning [1]
+% prior_type - defines type of prior ['none']
+%  - 'none' means do ML estimation
+%  - 'dirichlet' means add pseudo-counts to every cell
+%  - 'entropic' means use a prior P(theta) propto exp(-H(theta)) (see Brand)
+% dirichlet_weight - equivalent sample size (ess) of the dirichlet prior [1]
+% dirichlet_type - defines the type of Dirichlet prior ['BDeu']
+%  - 'unif' means put dirichlet_weight in every cell
+%  - 'BDeu' means we put 'dirichlet_weight/(r q)' in every cell
+%    where r = self_sz and q = prod(parent_sz) (see Heckerman)
+% trim - 1 means trim redundant params (rows in CPT) when using entropic prior [0]
+%
+% e.g., tabular_CPD(bnet, i, 'CPT', T)
+% e.g., tabular_CPD(bnet, i, 'CPT', 'unif', 'dirichlet_weight', 2, 'dirichlet_type', 'unif')
+%
+% REFERENCES
+% M. Brand - "Structure learning in conditional probability models via an entropic  prior
+%   and parameter extinction", Neural Computation 11 (1999): 1155--1182
+% M. Brand - "Pattern discovery via entropy minimization" [covers annealing]
+%   AI & Statistics 1999. Equation numbers refer to this paper, which is available from
+%   www.merl.com/reports/docs/TR98-21.pdf
+% D. Heckerman, D. Geiger and M. Chickering, 
+%   "Learning Bayesian networks: the combination of knowledge and statistical data",
+%   Microsoft Research Tech Report, 1994
+
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  CPD = class(CPD, 'tabular_CPD', discrete_CPD(0, []));
+  return;
+elseif isa(bnet, 'tabular_CPD')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+CPD = init_fields;
+
+ns = bnet.node_sizes;
+ps = parents(bnet.dag, self);
+fam_sz = ns([ps self]);
+CPD.sizes = fam_sz;
+CPD.leftright = 0;
+
+% set defaults
+CPD.CPT = mk_stochastic(myrand(fam_sz));
+CPD.adjustable = 1;
+CPD.prior_type = 'none';
+dirichlet_type = 'BDeu';
+dirichlet_weight = 1;
+CPD.trim = 0;
+selfprob = 0.1;
+
+% extract optional args
+args = varargin;
+% check for old syntax CPD(bnet, i, CPT) as opposed to CPD(bnet, i, 'CPT', CPT)
+if ~isempty(args) & ~isstr(args{1})
+  CPD.CPT = myreshape(args{1}, fam_sz);
+  args = [];
+end
+
+% if old_self is specified, read in the value before CPT is created
+old_self = []; 
+for i=1:2:length(args)
+  switch args{i},
+   case 'old_self', old_self = args{i+1};
+  end
+end
+
+for i=1:2:length(args)
+  switch args{i},
+   case 'CPT',
+    T = args{i+1};
+    if ischar(T)
+      switch T
+       case 'unif', CPD.CPT = mk_stochastic(myones(fam_sz));
+       case 'rnd',  CPD.CPT = mk_stochastic(myrand(fam_sz));
+       case 'leftright', 
+	% we just initialise the CPT to leftright - this structure will
+	% be maintained by EM, assuming we don't use a prior...
+	CPD.leftright = 1;
+	if isempty(old_self) % we assume the network is a DBN
+	  ss = bnet.nnodes_per_slice;
+	  old_self = self-ss;
+	end
+	other_ps = mysetdiff(ps, old_self);
+	Qps = prod(ns(other_ps));
+	Q = ns(self);
+	p = selfprob;
+	LR = mk_leftright_transmat(Q, p);
+	transprob = repmat(reshape(LR, [1 Q Q]), [Qps 1 1]); % transprob(k,i,j)
+	transprob = permute(transprob, [2 1 3]); % now transprob(i,k,j)
+	CPD.CPT = myreshape(transprob, fam_sz);
+       otherwise,   error(['invalid CPT ' T]);       
+      end
+    else
+      CPD.CPT = myreshape(T, fam_sz);
+    end
+    
+   case 'prior_type', CPD.prior_type = args{i+1};
+   case 'dirichlet_type', dirichlet_type = args{i+1};
+   case 'dirichlet_weight', dirichlet_weight = args{i+1};
+   case 'adjustable', CPD.adjustable = args{i+1};
+   case 'clamped', CPD.adjustable = ~args{i+1};
+   case 'trim', CPD.trim = args{i+1};
+   case 'old_self', noop = 1; % already read in
+   otherwise, error(['invalid argument name: ' args{i}]);       
+  end
+end
+
+switch CPD.prior_type
+ case 'dirichlet',
+  switch dirichlet_type
+   case 'unif', CPD.dirichlet = dirichlet_weight * myones(fam_sz);
+   case 'BDeu',  CPD.dirichlet = dirichlet_weight * mk_stochastic(myones(fam_sz));
+   otherwise, error(['invalid dirichlet_type ' dirichlet_type])
+  end
+ case {'entropic', 'none'}
+  CPD.dirichlet = [];
+ otherwise, error(['invalid prior_type ' prior_type])
+end
+
+  
+
+% fields to do with learning
+if ~CPD.adjustable
+  CPD.counts = [];
+  CPD.nparams = 0;
+  CPD.nsamples = [];
+else
+  CPD.counts = zeros(size(CPD.CPT));
+  psz = fam_sz(1:end-1);
+  ss = fam_sz(end);
+  if CPD.leftright
+    % For each of the Qps contexts, we specify Q elements on the diagoanl
+    CPD.nparams = Qps * Q;
+  else
+    % sum-to-1 constraint reduces the effective arity of the node by 1
+    CPD.nparams = prod([psz ss-1]);
+  end
+  CPD.nsamples = 0;
+end
+
+fam_sz = CPD.sizes;
+psz = prod(fam_sz(1:end-1));
+ssz = fam_sz(end);
+CPD.trimmed_trans = zeros(psz, ssz); % must declare before reading
+
+CPD = class(CPD, 'tabular_CPD', discrete_CPD(~CPD.adjustable, fam_sz));
+
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.CPT = [];
+CPD.sizes = [];
+CPD.prior_type = [];
+CPD.dirichlet = [];
+CPD.adjustable = [];
+CPD.counts = [];
+CPD.nparams = [];
+CPD.nsamples = [];
+CPD.trim = [];
+CPD.trimmed_trans = [];
+CPD.leftright = [];
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/Old/update_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function CPD = update_params(CPD, ev, counts)
+% UPDATE_PARAMS Update the Dirichlet pseudo counts and compute the new MAP param estimates (tabular)
+%
+% CPD = update_params(CPD, ev) uses the evidence on the family from a single case.
+%
+% CPD = update_params(CPD, [], counts) does a batch update using the specified suff. stats.
+
+if nargin < 3
+  n = length(ev);
+  data = cat(1, ev{:}); % convert to a vector of scalars
+  counts = compute_counts(data(:)', 1:n, mysize(CPD.CPT));
+end
+  
+CPD.prior = CPD.prior + counts;
+CPD.CPT = mk_stochastic(CPD.prior);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/bayes_update_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,55 @@
+function CPD = bayes_update_params(CPD, self_ev, pev)
+% UPDATE_PARAMS_COMPLETE Bayesian parameter updating given completely observed data (tabular)
+% CPD = update_params_complete(CPD, self_ev, pev)
+%
+% self_ev(m) is the evidence on this node in case m.
+% pev(i,m) is the evidence on the i'th parent in case m (if there are any parents).
+% These can be arrays or cell arrays.
+%
+% We update the Dirichlet pseudo counts and set the CPT to the mean of the posterior.
+
+if iscell(self_ev), usecell = 1; else usecell = 0; end
+
+ncases = length(self_ev);
+sz = CPD.sizes;
+nparents = length(sz)-1;
+assert(nparents == size(pev,1));
+
+if ncases == 0 | ~adjustable_CPD(CPD)
+  return;
+elseif ncases == 1 % speedup the sequential learning case by avoiding normalization of the whole array
+  if usecell
+    x = cat(1, pev{:})';
+    y = self_ev{1};
+  else
+    x = pev(:)';
+    y = self_ev;
+  end
+  switch nparents
+   case 0,
+    CPD.dirichlet(y) = CPD.dirichlet(y)+1;
+    CPD.CPT = CPD.dirichlet / sum(CPD.dirichlet);
+   case 1,
+    CPD.dirichlet(x(1), y) = CPD.dirichlet(x(1), y)+1;
+    CPD.CPT(x(1), :) = CPD.dirichlet(x(1), :) ./ sum(CPD.dirichlet(x(1), :));
+   case 2,
+    CPD.dirichlet(x(1), x(2), y) = CPD.dirichlet(x(1), x(2), y)+1;
+    CPD.CPT(x(1), x(2), :) = CPD.dirichlet(x(1), x(2), :) ./ sum(CPD.dirichlet(x(1), x(2), :));
+   case 3,
+    CPD.dirichlet(x(1), x(2), x(3), y) = CPD.dirichlet(x(1), x(2), x(3), y)+1;
+    CPD.CPT(x(1), x(2), x(3), :) = CPD.dirichlet(x(1), x(2), x(3), :) ./ sum(CPD.dirichlet(x(1), x(2), x(3), :));
+   otherwise,
+    ind = subv2ind(sz, [x y]);
+    CPD.dirichlet(ind) = CPD.dirichlet(ind) + 1;
+    CPD.CPT = mk_stochastic(CPD.dirichlet);
+  end
+else  
+  if usecell
+    data = [cell2num(pev); cell2num(self_ev)]; 
+  else
+    data = [pev; self_ev];
+  end
+  counts = compute_counts(data, sz);
+  CPD.dirichlet = CPD.dirichlet + counts;
+  CPD.CPT = mk_stochastic(CPD.dirichlet);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function display(CPD)
+
+disp('tabular_CPD object');
+disp(struct(CPD)); 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/get_field.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function val = get_field(CPD, name)
+% GET_PARAMS Get the parameters (fields) for a tabular_CPD object
+% val = get_params(CPD, name)
+%
+% The following fields can be accessed
+%
+% cpt, counts
+%
+% e.g., CPT = get_params(CPD, 'cpt')
+
+switch name
+ case 'cpt',      val = CPD.CPT;
+ case 'counts',      val = CPD.counts;
+ otherwise,
+  error(['invalid argument name ' name]);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/learn_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function CPD = learn_params(CPD, fam, data, ns, cnodes)
+%function CPD = learn_params(CPD, local_data)
+% LEARN_PARAMS Compute the ML/MAP estimate of the params of a tabular CPD given complete data
+% CPD = learn_params(CPD, local_data)
+%
+% local_data(i,m) is the value of i'th family member in case m (can be cell array).
+
+local_data = data(fam, :); 
+if iscell(local_data)
+  local_data = cell2num(local_data);
+end
+counts = compute_counts(local_data, CPD.sizes);
+switch CPD.prior_type
+ case 'none', CPD.CPT = mk_stochastic(counts); 
+ case 'dirichlet', CPD.CPT = mk_stochastic(counts + CPD.dirichlet); 
+ otherwise, error(['unrecognized prior ' CPD.prior_type])
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/log_marg_prob_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,69 @@
+function L = log_marg_prob_node(CPD, self_ev, pev, usecell)
+% LOG_MARG_PROB_NODE Compute sum_m log P(x(i,m)| x(pi_i,m)) for node i (tabular)
+% L = log_marg_prob_node(CPD, self_ev, pev)
+%
+% This differs from log_prob_node because we integrate out the parameters.
+% self_ev(m) is the evidence on this node in case m.
+% pev(i,m) is the evidence on the i'th parent in case m (if there are any parents).
+% (These may also be cell arrays.)
+
+ncases = length(self_ev);
+sz = CPD.sizes;
+nparents = length(sz)-1;
+assert(ncases == size(pev, 2)); 
+
+if nargin < 4
+  %usecell = 0;
+  if iscell(self_ev)
+    usecell = 1;
+  else
+    usecell = 0;
+  end
+end
+
+
+if ncases==0
+  L = 0;
+  return;
+elseif ncases==1  % speedup the sequential learning case
+  CPT = CPD.CPT;
+  % We assume the CPTs are already set to the mean of the posterior (due to bayes_update_params)
+  if usecell
+    x = cat(1, pev{:})';
+    y = self_ev{1};
+  else
+    %x = pev(:)';
+    x = pev;
+    y = self_ev;
+  end
+  switch nparents
+   case 0, p = CPT(y);
+   case 1, p = CPT(x(1), y);
+   case 2, p = CPT(x(1), x(2), y);
+   case 3, p = CPT(x(1), x(2), x(3), y);
+   otherwise,
+    ind = subv2ind(sz, [x y]);
+    p = CPT(ind);
+  end
+  L = log(p);
+else
+  % We ignore the CPTs here and assume the prior has not been changed
+  
+  % We arrange the data as in the following example.
+  % Let there be 2 parents and 3 cases. Let p(i,m) be parent i in case m,
+  % and y(m) be the child in case m. Then we create the data matrix
+  % 
+  % p(1,1) p(1,2) p(1,3)
+  % p(2,1) p(2,2) p(2,3)
+  % y(1)   y(2)   y(3)
+  if usecell
+    data = [cell2num(pev); cell2num(self_ev)]; 
+  else
+    data = [pev; self_ev];
+  end
+  %S = struct(CPD); fprintf('log marg prob node %d, ps\n', S.self); disp(S.parents)
+  counts = compute_counts(data, sz);
+  L = dirichlet_score_family(counts, CPD.dirichlet);
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/log_nextcase_prob_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,72 @@
+function L = log_nextcase_prob_node(CPD, self_ev, pev, test_self_ev, test_pev)
+% LOG_NEXTCASE_PROB_NODE compute the joint distribution of a node (tabular) of a new case given
+% completely observed data.
+%
+% The input arguments are mainly similar with log_marg_prob_node(CPD, self_ev, pev, usecell),
+% but add test_self_ev, test_pev, and without usecell
+% test_self_ev(m) is the evidence on this node in a test case.
+% test_pev(i) is the evidence on the i'th parent in the test case (if there are any parents).
+%
+% Written by qian.diao@intel.com
+
+ncases = length(self_ev);
+sz = CPD.sizes;
+nparents = length(sz)-1;
+assert(ncases == size(pev, 2)); 
+
+if nargin < 6
+  %usecell = 0;
+  if iscell(self_ev)
+    usecell = 1;
+  else
+    usecell = 0;
+  end
+end
+
+
+if ncases==0
+  L = 0;
+  return;
+elseif ncases==1  % speedup the sequential learning case; here need correction!!!
+  CPT = CPD.CPT;
+  % We assume the CPTs are already set to the mean of the posterior (due to bayes_update_params)
+  if usecell
+    x = cat(1, pev{:})';
+    y = self_ev{1};
+  else
+    %x = pev(:)';
+    x = pev;
+    y = self_ev;
+  end
+  switch nparents
+   case 0, p = CPT(y);
+   case 1, p = CPT(x(1), y);
+   case 2, p = CPT(x(1), x(2), y);
+   case 3, p = CPT(x(1), x(2), x(3), y);
+   otherwise,
+    ind = subv2ind(sz, [x y]);
+    p = CPT(ind);
+  end
+  L = log(p);
+else
+  % We ignore the CPTs here and assume the prior has not been changed
+  
+  % We arrange the data as in the following example.
+  % Let there be 2 parents and 3 cases. Let p(i,m) be parent i in case m,
+  % and y(m) be the child in case m. Then we create the data matrix
+  % 
+  % p(1,1) p(1,2) p(1,3)
+  % p(2,1) p(2,2) p(2,3)
+  % y(1)   y(2)   y(3)
+  if usecell
+    data = [cell2num(pev); cell2num(self_ev)]; 
+  else
+    data = [pev; self_ev];
+  end
+  counts = compute_counts(data, sz);
+  
+  % compute the (N_ijk'+ N_ijk)/(N_ij' + N_ij) under the condition of 1_m+1,ijk = 1 
+  L = predict_family(counts, CPD.prior, test_self_ev, test_pev);
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/log_prior.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function L = log_prior(CPD)
+% LOG_PRIOR Return log P(theta) for a tabular CPD 
+% L = log_prior(CPD)
+
+switch CPD.prior_type
+ case 'none',
+  L = 0;
+ case 'dirichlet',
+  D = CPD.dirichlet(:);
+  L = sum(log(D + (D==0)));
+ case 'entropic',
+  % log-prior = log exp(-H(theta)) = sum_i theta_i log (theta_i)
+  fam_sz = CPD.sizes;
+  psz = prod(fam_sz(1:end-1));
+  ssz = fam_sz(end);
+  C = reshape(CPD.CPT, psz, ssz);
+  L = sum(sum(C .* log(C + (C==0))));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/maximize_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+function CPD = maximize_params(CPD, temp)
+% MAXIMIZE_PARAMS Set the params of a tabular node to their ML/MAP values.
+% CPD = maximize_params(CPD, temp)
+
+if ~adjustable_CPD(CPD), return; end
+
+%assert(approxeq(sum(CPD.counts(:)), CPD.nsamples)); % false!
+switch CPD.prior_type
+ case 'none',
+  counts = reshape(CPD.counts, size(CPD.CPT));
+  CPD.CPT = mk_stochastic(counts);
+ case 'dirichlet',
+  counts = reshape(CPD.counts, size(CPD.CPT));
+  CPD.CPT = mk_stochastic(counts + CPD.dirichlet);
+ 
+ % case 'entropic',
+%   % For an HMM,
+%   % CPT(i,j) = pr(X(t)=j | X(t-1)=i) = transprob(i,j)
+%   % counts(i,j) = E #(X(t-1)=i, X(t)=j) = exp_num_trans(i,j)
+%   Z = 1-temp;
+%   fam_sz = CPD.sizes;
+%   psz = prod(fam_sz(1:end-1));
+%   ssz = fam_sz(end);
+%   counts = reshape(CPD.counts, psz, ssz);
+%   CPT = zeros(psz, ssz);
+%   for i=CPD.entropic_pcases(:)'
+%     [CPT(i,:), logpost] = entropic_map_estimate(counts(i,:), Z);
+%   end
+%   non_entropic_pcases = mysetdiff(1:psz, CPD.entropic_pcases);
+%   for i=non_entropic_pcases(:)'
+%     CPT(i,:) = mk_stochastic(counts(i,:));
+%   end
+%   %for i=1:psz
+%   %  [CPT(i,:), logpost] = entropic_map(counts(i,:), Z);
+%   %end
+%   if CPD.trim & (temp < 2) % at high temps, we would trim everything!
+%     % grad(j) = d log lik / d theta(i ->j)
+%     % CPT(i,j) = 0 => counts(i,j) = 0
+%     % so we can safely replace 0s by 1s in the denominator
+%     denom = CPT(i,:) + (CPT(i,:)==0);
+%     grad = counts(i,:) ./ denom;
+%     trim = find(CPT(i,:) <= exp(-(1/Z)*grad)); % eqn 32
+%     if ~isempty(trim)
+%       CPT(i,trim) = 0;
+%       if all(CPD.trimmed_trans(i,trim)==0) % trimming for 1st time
+% 	disp(['trimming CPT(' num2str(i) ',' num2str(trim) ')']) 
+%       end
+%       CPD.trimmed_trans(i,trim) = 1;
+%     end
+%   end
+%   CPD.CPT = myreshape(CPT, CPD.sizes);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/reset_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function CPD = reset_ess(CPD)
+% RESET_ESS Reset the Expected Sufficient Statistics of a tabular node.
+% CPD = reset_ess(CPD)
+
+%CPD.counts = zeros(size(CPD.CPT));
+CPD.counts = zeros(prod(size(CPD.CPT)), 1);
+CPD.nsamples = 0;    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/set_fields.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+function CPD = set_fields(CPD, varargin)
+% SET_PARAMS Set the parameters (fields) for a tabular_CPD object
+% CPD = set_params(CPD, name/value pairs)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+%
+% CPT, prior, clamped, counts
+%
+% e.g., CPD = set_params(CPD, 'CPT', 'rnd')
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'CPT', 
+    if ischar(args{i+1})
+      switch args{i+1}
+       case 'unif', CPD.CPT = mk_stochastic(myones(CPD.sizes));
+       case 'rnd',  CPD.CPT = mk_stochastic(myrand(CPD.sizes));
+       otherwise,   error(['invalid type ' args{i+1}]);       
+      end
+    elseif isscalar(args{i+1})
+      p = args{i+1};
+      k = CPD.sizes(end);
+      % Bug fix by Hervé Boutrouille 10/1/01
+      CPD.CPT = myreshape(sample_dirichlet(p*ones(1,k), prod(CPD.sizes(1:end-1)), CPD.sizes));   
+      %CPD.CPT = myreshape(sample_dirichlet(p*ones(1,k), prod(CPD.sizes(1:end-1))), CPD.sizes);
+    else
+      CPD.CPT = myreshape(args{i+1}, CPD.sizes);
+    end
+   
+   case 'prior',       
+    if ischar(args{i+1}) & strcmp(args{i+1}, 'unif')
+      CPD.prior = myones(CPD.sizes);
+    elseif isscalar(args{i+1})
+      CPD.prior = args{i+1} * normalise(myones(CPD.sizes));
+    else
+      CPD.prior = myreshape(args{i+1}, CPD.sizes);
+    end
+    
+   %case 'clamped',      CPD.clamped = strcmp(args{i+1}, 'yes');
+   %case 'clamped',      CPD = set_clamped(CPD, strcmp(args{i+1}, 'yes'));
+   case 'clamped',      CPD = set_clamped(CPD, args{i+1});
+    
+   case 'counts',      CPD.counts = args{i+1};
+   
+   otherwise,  
+    %error(['invalid argument name ' args{i}]);       
+  end
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/tabular_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,173 @@
+function CPD = tabular_CPD(bnet, self, varargin)
+% TABULAR_CPD Make a multinomial conditional prob. distrib. (CPT)
+%
+% CPD = tabular_CPD(bnet, node) creates a random CPT.
+%
+% The following arguments can be specified [default in brackets]
+%
+% CPT - specifies the params ['rnd']
+%   - T means use table T; it will be reshaped to the size of node's family.
+%   - 'rnd' creates rnd params (drawn from uniform)
+%   - 'unif' creates a uniform distribution
+% adjustable - 0 means don't adjust the parameters during learning [1]
+% prior_type - defines type of prior ['none']
+%  - 'none' means do ML estimation
+%  - 'dirichlet' means add pseudo-counts to every cell
+%  - 'entropic' means use a prior P(theta) propto exp(-H(theta)) (see Brand)
+% dirichlet_weight - equivalent sample size (ess) of the dirichlet prior [1]
+% dirichlet_type - defines the type of Dirichlet prior ['BDeu']
+%  - 'unif' means put dirichlet_weight in every cell
+%  - 'BDeu' means we put 'dirichlet_weight/(r q)' in every cell
+%    where r = self_sz and q = prod(parent_sz) (see Heckerman)
+% trim - 1 means trim redundant params (rows in CPT) when using entropic prior [0]
+% entropic_pcases - list of assignments to the parents nodes when we should use 
+%      the entropic prior; all other cases will be estimated using ML [1:psz]
+% sparse - 1 means use 1D sparse array to represent CPT [0]
+%
+% e.g., tabular_CPD(bnet, i, 'CPT', T)
+% e.g., tabular_CPD(bnet, i, 'CPT', 'unif', 'dirichlet_weight', 2, 'dirichlet_type', 'unif')
+%
+% REFERENCES
+% M. Brand - "Structure learning in conditional probability models via an entropic  prior
+%   and parameter extinction", Neural Computation 11 (1999): 1155--1182
+% M. Brand - "Pattern discovery via entropy minimization" [covers annealing]
+%   AI & Statistics 1999. Equation numbers refer to this paper, which is available from
+%   www.merl.com/reports/docs/TR98-21.pdf
+% D. Heckerman, D. Geiger and M. Chickering, 
+%   "Learning Bayesian networks: the combination of knowledge and statistical data",
+%   Microsoft Research Tech Report, 1994
+
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  CPD = class(CPD, 'tabular_CPD', discrete_CPD(0, []));
+  return;
+elseif isa(bnet, 'tabular_CPD')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+CPD = init_fields;
+
+ns = bnet.node_sizes;
+ps = parents(bnet.dag, self);
+fam_sz = ns([ps self]);
+psz = prod(ns(ps));
+CPD.sizes = fam_sz;
+CPD.leftright = 0;
+CPD.sparse = 0;
+
+% set defaults
+CPD.CPT = mk_stochastic(myrand(fam_sz));
+CPD.adjustable = 1;
+CPD.prior_type = 'none';
+dirichlet_type = 'BDeu';
+dirichlet_weight = 1;
+CPD.trim = 0;
+selfprob = 0.1;
+CPD.entropic_pcases = 1:psz;
+
+% extract optional args
+args = varargin;
+% check for old syntax CPD(bnet, i, CPT) as opposed to CPD(bnet, i, 'CPT', CPT)
+if ~isempty(args) & ~isstr(args{1})
+  CPD.CPT = myreshape(args{1}, fam_sz);
+  args = [];
+end
+
+for i=1:2:length(args)
+  switch args{i},
+   case 'CPT',
+    T = args{i+1};
+    if ischar(T)
+      switch T
+       case 'unif', CPD.CPT = mk_stochastic(myones(fam_sz));
+       case 'rnd',  CPD.CPT = mk_stochastic(myrand(fam_sz));
+       otherwise,   error(['invalid CPT ' T]);       
+      end
+    else
+      CPD.CPT = myreshape(T, fam_sz);
+    end
+   case 'prior_type', CPD.prior_type = args{i+1};
+   case 'dirichlet_type', dirichlet_type = args{i+1};
+   case 'dirichlet_weight', dirichlet_weight = args{i+1};
+   case 'adjustable', CPD.adjustable = args{i+1};
+   case 'clamped', CPD.adjustable = ~args{i+1};
+   case 'trim', CPD.trim = args{i+1};
+   case 'entropic_pcases', CPD.entropic_pcases = args{i+1};
+   case 'sparse', CPD.sparse = args{i+1};
+   otherwise, error(['invalid argument name: ' args{i}]);       
+  end
+end
+
+switch CPD.prior_type
+ case 'dirichlet',
+  switch dirichlet_type
+   case 'unif', CPD.dirichlet = dirichlet_weight * myones(fam_sz);
+   case 'BDeu',  CPD.dirichlet = (dirichlet_weight/psz) * mk_stochastic(myones(fam_sz));
+   otherwise, error(['invalid dirichlet_type ' dirichlet_type])
+  end
+ case {'entropic', 'none'}
+  CPD.dirichlet = [];
+ otherwise, error(['invalid prior_type ' prior_type])
+end
+
+  
+
+% fields to do with learning
+if ~CPD.adjustable
+  CPD.counts = [];
+  CPD.nparams = 0;
+  CPD.nsamples = [];
+else
+  %CPD.counts = zeros(size(CPD.CPT));
+  CPD.counts = zeros(prod(size(CPD.CPT)), 1);
+  psz = fam_sz(1:end-1);
+  ss = fam_sz(end);
+  if CPD.leftright
+    % For each of the Qps contexts, we specify Q elements on the diagoanl
+    CPD.nparams = Qps * Q;
+  else
+    % sum-to-1 constraint reduces the effective arity of the node by 1
+    CPD.nparams = prod([psz ss-1]);
+  end
+  CPD.nsamples = 0;
+end
+
+CPD.trimmed_trans = [];
+fam_sz = CPD.sizes;
+
+%psz = prod(fam_sz(1:end-1));
+%ssz = fam_sz(end);
+%CPD.trimmed_trans = zeros(psz, ssz); % must declare before reading
+
+%sparse CPT
+if CPD.sparse
+   CPD.CPT = sparse(CPD.CPT(:));
+end
+
+CPD = class(CPD, 'tabular_CPD', discrete_CPD(~CPD.adjustable, fam_sz));
+
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.CPT = [];
+CPD.sizes = [];
+CPD.prior_type = [];
+CPD.dirichlet = [];
+CPD.adjustable = [];
+CPD.counts = [];
+CPD.nparams = [];
+CPD.nsamples = [];
+CPD.trim = [];
+CPD.trimmed_trans = [];
+CPD.leftright = [];
+CPD.entropic_pcases = [];
+CPD.sparse = [];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/update_ess.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+% UPDATE_ESS Update the Expected Sufficient Statistics of a tabular node.
+% function CPD = update_ess(CPD, fmarginal, evidence, ns, cnodes, hidden_bitv)
+
+dom = fmarginal.domain;
+
+if all(hidden_bitv(dom))
+  CPD = update_ess_simple(CPD, fmarginal.T);
+  %fullm = add_ev_to_dmarginal(fmarginal, evidence, ns);
+  %assert(approxeq(fullm.T(:), fmarginal.T(:)))
+else
+  fullm = add_ev_to_dmarginal(fmarginal, evidence, ns);
+  CPD = update_ess_simple(CPD, fullm.T);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_CPD/update_ess_simple.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function CPD = update_ess_simple(CPD, counts)
+% UPDATE_ESS_SIMPLE Update the Expected Sufficient Statistics of a tabular node.
+% function CPD = update_ess_simple(CPD, counts)
+
+CPD.nsamples = CPD.nsamples + 1;            
+CPD.counts = CPD.counts + counts(:);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/CPD_to_CPT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function CPT = CPD_to_CPT(CPD)
+% CPD_TO_CPT Convert the tabular_decision_node to a CPT
+% CPT = CPD_to_CPT(CPD)
+
+CPT = CPD.CPT;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/CPD_to_CPT.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/display.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/get_field.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/set_fields.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/tabular_decision_node.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@tabular_decision_node
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/tabular_decision_node.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@tabular_decision_node/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/Old/tabular_decision_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,39 @@
+function CPD = tabular_decision_node(sz, CPT)
+% TABULAR_DECISION_NODE Represent the randomized policy over a discrete decision/action node as a table
+% CPD = tabular_decision_node(sz, CPT)
+%
+% sz(1:end-1) is the sizes of the parents, sz(end) is the size of this node
+% By default, CPT is set to the uniform random policy
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  CPD = class(CPD, 'tabular_decision_node');
+  return;
+elseif isa(sz, 'tabular_decision_node')
+  % This might occur if we are copying an object.
+  CPD = sz;
+  return;
+end
+CPD = init_fields;
+
+if nargin < 2
+  CPT = mk_stochastic(myones(sz)); 
+else
+  CPT = myreshape(CPT, sz);
+end
+
+CPD.CPT = CPT;
+CPD.size = sz;
+
+CPD = class(CPD, 'tabular_decision_node');
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.CPT = [];
+CPD.size = [];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function display(CPD)
+
+disp('tabular decision node object');
+disp(struct(CPD)); 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/get_field.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function vals = get_field(CPD, name)
+% GET_PARAMS Get the parameters (fields) for a tabular_decision_node object
+% vals = get_params(CPD, name)
+%
+% The following fields can be accessed
+%
+% policy - the table containing the policy
+%
+% e.g., policy = get_params(CPD, 'policy')
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'policy',  vals =  CPD.CPT;
+   otherwise,
+    error(['invalid argument name ' args{i}]);
+  end
+end               
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/set_fields.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function CPD = set_params(CPD, varargin)
+% SET_PARAMS Set the parameters (fields) for a tabular_decision_node object
+% CPD = set_params(CPD, name/value pairs)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+%
+% policy - the table containing the policy
+%
+% e.g., CPD = set_params(CPD, 'policy', T)
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'policy',   CPD.CPT = args{i+1};
+   otherwise,
+    error(['invalid argument name ' args{i}]);
+  end
+end               
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_decision_node/tabular_decision_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+function CPD = tabular_decision_node(bnet, self, CPT)
+% TABULAR_DECISION_NODE Represent a stochastic policy over a discrete decision/action node as a table
+% CPD = tabular_decision_node(bnet, self, CPT)
+%
+% node is the number of a node in this equivalence class.
+% CPT is an optional argument (see tabular_CPD for details); by default, it is the uniform policy.
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  CPD = class(CPD, 'tabular_decision_node', discrete_CPD(1, []));
+  return;
+elseif isa(bnet, 'tabular_decision_node')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+CPD = init_fields;
+
+ns = bnet.node_sizes;
+fam = family(bnet.dag, self);
+ps = parents(bnet.dag, self);
+sz = ns(fam);
+
+if nargin < 3
+  CPT = mk_stochastic(myones(sz)); 
+else
+  CPT = myreshape(CPT, sz);
+end
+
+CPD.CPT = CPT;
+CPD.sizes = sz; 
+
+clamped = 1; % don't update using EM
+CPD = class(CPD, 'tabular_decision_node', discrete_CPD(clamped, ns([ps self])));
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.CPT = [];
+CPD.sizes = [];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/convert_to_pot.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/convert_to_table.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/get_field.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/set_fields.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/tabular_kernel.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@tabular_kernel
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/tabular_kernel.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@tabular_kernel/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/Old/tabular_kernel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+function K = tabular_kernel(fg, self)
+% TABULAR_KERNEL Make a table-based local kernel (discrete potential)
+% K = tabular_kernel(fg, self)
+%
+% fg is a factor graph
+% self is the number of a representative domain
+%
+% Use 'set_params_kernel' to adjust the following fields
+%   table - a q[1]xq[2]x... array, where q[i] is the number of values for i'th node
+%       in this domain [default: random values from [0,1], which need not sum to 1]
+
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  K = init_fields;
+  K = class(K, 'tabular_kernel');
+  return;
+elseif isa(fg, 'tabular_kernel')
+  % This might occur if we are copying an object.
+  K = fg;
+  return;
+end
+K = init_fields;
+
+ns = fg.node_sizes;
+dom = fg.doms{self};
+% we don't store the actual domain since it may vary due to parameter tieing
+K.sz = ns(dom);
+K.table = myrand(K.sz);
+
+K = class(K, 'tabular_kernel');
+
+
+%%%%%%%
+
+
+function K = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+K.table = [];
+K.sz = [];
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/convert_to_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,37 @@
+function pot = convert_to_pot(CPD, pot_type, domain, evidence)
+% CONVERT_TO_POT Convert a tabular CPD to one or more potentials
+% pot = convert_to_pot(CPD, pot_type, domain, evidence)
+
+% This is the same as discrete_CPD/convert_to_pot,
+% except we didn't want to the kernel to inherit methods like sample_node etc.
+
+sz = CPD.sz;
+ns = zeros(1, max(domain));
+ns(domain) = sz;
+
+odom = domain(~isemptycell(evidence(domain)));
+T = convert_to_table(CPD, domain, evidence);
+
+switch pot_type
+ case 'u',
+  pot = upot(domain, sz, T, 0*myones(sz));  
+ case 'd',
+  ns(odom) = 1;
+  pot = dpot(domain, ns(domain), T);          
+ case 'c',
+  % Since we want the output to be a Gaussian, the whole family must be observed.
+  % In other words, the potential is really just a constant.
+  p = T.p;
+  %p = prob_node(CPD, evidence(domain(end)), evidence(domain(1:end-1)));
+  ns(domain) = 0;
+  pot = cpot(domain, ns(domain), log(p));       
+ case 'cg',
+  T = T(:);
+  ns(odom) = 1;
+  can = cell(1, length(T));
+  for i=1:length(T)
+    can{i} = cpot([], [], log(T(i)));
+  end
+  pot = cgpot(domain, [], ns, can);   
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/convert_to_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function T = convert_to_table(CPD, domain, evidence)
+% CONVERT_TO_TABLE Convert a discrete CPD to a table
+% T = convert_to_table(CPD, domain, evidence)
+%
+% We convert the CPD to a CPT, and then lookup the evidence on the discrete parents.
+% The resulting table can easily be converted to a potential.
+
+CPT = CPD.table;
+odom = domain(~isemptycell(evidence(domain)));
+vals = cat(1, evidence{odom});
+map = find_equiv_posns(odom, domain);
+index = mk_multi_index(length(domain), map, vals);
+T = CPT(index{:});               
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/get_field.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function val = get_params_kernel(K, name)
+% GET_PARAMS_KERNEL Accessor function for a field (tabular_kernel)
+% val = get_params_kernel(K, name)
+%
+% e.g., get_params_kernel(K, 'table')
+
+switch name
+ case 'table', val = K.table;
+ otherwise,
+  error(['invalid field name ' name]);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/set_fields.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function K = set_params_kernel(K, name, val)
+% SET_PARAMS_KERNEL Accessor function for a field (table_kernel)
+% K = set_params_kernel(K, name, val)
+%
+% e.g., K = set_params_kernel(K, 'table', rand(2,3,2)) for a kernel on 3 nodes with 2,3,2 values each
+
+% We should check if the arguments are valid...
+
+switch name
+ case 'table', K.table = val;
+ otherwise,
+  error(['invalid field name ' name]);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_kernel/tabular_kernel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+function K = tabular_kernel(sz, table)
+% TABULAR_KERNEL Make a table-based local kernel (discrete potential)
+% K = tabular_kernel(sz, table)
+%
+% sz(i) is the number of values the i'th member of this kernel can have
+% table is an optional array of size sz[1] x sz[2] x... [default: random]
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  K = init_fields;
+  K = class(K, 'tabular_kernel');
+  return;
+elseif isa(sz, 'tabular_kernel')
+  % This might occur if we are copying an object.
+  K = sz;
+  return;
+end
+K = init_fields;
+
+if nargin < 2, table = myrand(sz); end
+
+K.sz = sz;
+K.table = table;
+
+K = class(K, 'tabular_kernel');
+
+
+%%%%%%%
+
+
+function K = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+K.sz = [];
+K.table = [];
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_utility_node/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+/convert_to_pot.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/display.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/tabular_utility_node.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_utility_node/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@tabular_utility_node
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_utility_node/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_utility_node/convert_to_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function pot = convert_to_pot(CPD, pot_type, domain, evidence)
+% CONVERT_TO_POT Convert a tabular utility node to one or more potentials
+% pot = convert_to_pot(CPD, pot_type, domain, evidence)
+
+switch pot_type
+ case 'u',
+  sz = [CPD.sizes 1]; % the utility node itself has size 1
+  pot = upot(domain, sz, 1*myones(sz), myreshape(CPD.T, sz));   
+ otherwise,
+  error(['can''t convert a utility node to a ' pot_type ' potential']);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_utility_node/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function display(CPD)
+
+disp('tabular utility node object');
+disp(struct(CPD)); 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tabular_utility_node/tabular_utility_node.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,46 @@
+function CPD = tabular_utility_node(bnet, node, T)
+% TABULAR_UTILITY_NODE Represent a utility function as a table
+% CPD = tabular_utility_node(bnet, node, T)
+%
+% node is the number of a node in this equivalence class.
+% T is an optional argument (same shape as the CPT in tabular_CPD, but missing the last (child)
+% dimension). By default, entries in T are chosen u.a.r. from 0:1 (using 'rand').
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  clamp = 0;
+  CPD = class(CPD, 'tabular_utility_node');
+  return;
+elseif isa(bnet, 'tabular_utility_node')
+  % This might occur if we are copying an object.
+  CPD = bnet;
+  return;
+end
+CPD = init_fields;
+
+
+ns = bnet.node_sizes;
+ps = parents(bnet.dag, node);
+sz = ns(ps);
+
+if nargin < 3
+  T = myrand(sz);
+else
+  T = myreshape(T, sz);
+end
+
+CPD.T = T;
+CPD.sizes = sz;
+
+CPD = class(CPD, 'tabular_utility_node');
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+CPD.T = [];
+CPD.sizes = [];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tree_CPD/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+/display.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/evaluate_tree_performance.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/get_field.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/learn_params.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/readme.txt/1.1.1.1/Wed May 29 15:59:54 2002//
+/set_fields.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/tree_CPD.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tree_CPD/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs/@tree_CPD
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tree_CPD/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tree_CPD/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function display(CPD)
+
+disp('dtree_CPD object');
+disp(struct(CPD)); 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tree_CPD/evaluate_tree_performance.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,82 @@
+function [score,outputs] = evaluate(CPD, fam, data, ns, cnodes)
+% Evaluate evaluate the performance of the classification/regression tree on given complete data
+% score = evaluate(CPD, fam, data, ns, cnodes)
+%
+% fam(i) is the node id of the i-th node in the family of nodes, self node is the last one
+% data(i,m) is the value of node i in case m (can be cell array).
+% ns(i) is the node size for the i-th node in the whold bnet
+% cnodes(i) is the node id for the i-th continuous node in the whole bnet
+%  
+% Output
+% score is the classification accuracy (for classification) 
+%          or mean square deviation (for regression)
+%            here for every case we use the mean value at the tree leaf node as its predicted value
+% outputs(i) is the predicted output value for case i
+%
+% Author: yimin.zhang@intel.com
+% Last updated: Jan. 19, 2002
+
+
+if iscell(data)
+  local_data = cell2num(data(fam,:));
+else
+  local_data = data(fam, :);
+end
+
+%get local node sizes and node types
+node_sizes = ns(fam);
+node_types = zeros(1,size(ns,2)); %all nodes are disrete
+node_types(cnodes)=1;
+node_types=node_types(fam);
+
+fam_size=size(fam,2);
+output_type = node_types(fam_size);
+
+num_cases=size(local_data,2);
+total_error=0;
+
+outputs=zeros(1,num_cases);
+for i=1:num_cases
+  %class one case using the tree
+  cur_node=CPD.tree.root;  % at the root node of the tree
+  while (1)
+    if (CPD.tree.nodes(cur_node).is_leaf==1)
+      if (output_type==0) %output is discrete
+        %use the class with max probability as the output  
+        [maxvalue,class_id]=max(CPD.tree.nodes(cur_node).probs);
+        outputs(i)=class_id;
+        if (class_id~=local_data(fam_size,i))
+          total_error=total_error+1;
+        end
+      else   %output is continuous
+        %use the mean as the value
+        outputs(i)=CPD.tree.nodes(cur_node).mean;
+        cur_deviation = CPD.tree.nodes(cur_node).mean-local_data(fam_size,i);
+        total_error=total_error+cur_deviation*cur_deviation;
+      end
+      break;
+    end
+    cur_attr = CPD.tree.nodes(cur_node).split_id; 
+    attr_val = local_data(cur_attr,i);
+    if (node_types(cur_attr)==0)  %discrete attribute
+        % goto the attr_val -th child
+        cur_node = CPD.tree.nodes(cur_node).children(attr_val);
+    else
+        if (attr_val <= CPD.tree.nodes(cur_node).split_threshhold)
+          cur_node = CPD.tree.nodes(cur_node).children(1);
+        else
+          cur_node = CPD.tree.nodes(cur_node).children(2);  
+        end
+    end
+    if (cur_node > CPD.tree.num_node)
+      fprintf('Fatal error: Tree structure corrupted.\n');
+      return;
+    end
+  end
+  %update the classification error number
+end
+if (output_type==0)
+  score=1-total_error/num_cases;
+else
+  score=total_error/num_cases;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tree_CPD/get_field.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function val = get_params(CPD, name)
+% GET_PARAMS Get the parameters (fields) for a tabular_CPD object
+% val = get_params(CPD, name)
+%
+% The following fields can be accessed
+%
+% cpt       - the CPT
+%
+% e.g., CPT = get_params(CPD, 'cpt')
+
+switch name
+ case 'cpt',      val = CPD.CPT;
+ case 'tree',     val = CPD.tree;
+ otherwise,
+  error(['invalid argument name ' name]);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tree_CPD/learn_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,642 @@
+function CPD = learn_params(CPD, fam, data, ns, cnodes, varargin)
+% LEARN_PARAMS Construct classification/regression tree given complete data
+% CPD = learn_params(CPD, fam, data, ns, cnodes)
+%
+% fam(i) is the node id of the i-th node in the family of nodes, self node is the last one
+% data(i,m) is the value of node i in case m (can be cell array).
+% ns(i) is the node size for the i-th node in the whold bnet
+% cnodes(i) is the node id for the i-th continuous node in the whole bnet
+%  
+% The following optional arguments can be specified in the form of name/value pairs:
+% stop_cases: for early stop (pruning). A node is not split if it has less than k cases. default is 0.
+% min_gain: for early stop (pruning). 
+%     For discrete output: A node is not split when the gain of best split is less than min_gain. default is 0.  
+%     For continuous (cts) outpt: A node is not split when the gain of best split is less than min_gain*score(root) 
+%                                 (we denote it cts_min_gain). default is 0.006
+% %%%%%%%%%%%%%%%%%%%Struction definition of dtree_CPD.tree%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% tree.num_node               the last position in tree.nodes array for adding new nodes,
+%                             it is not always same to number of nodes in a tree, because some position in the 
+%                             tree.nodes array can be set to unused (e.g. in tree pruning)  
+% tree.nodes is the array of nodes in the tree plus some unused nodes.
+% tree.nodes(1) is the root for the tree.
+%
+% Below is the attributes for each node
+% tree.nodes(i).used;     % flag this node is used (0 means node not used, it can be removed from tree to save memory)
+% tree.nodes(i).is_leaf;  % if 1 means this node is a leaf, if 0 not a leaf.
+% tree.nodes(i).children; % children(i) is the node number in tree.nodes array for the i-th child node
+% tree.nodes(i).split_id; % the attribute id used to split this node
+% tree.nodes(i).split_threshhold; % the threshhold for continuous attribute to split this node
+% %%%%%attributes specially for classification tree (discrete output)
+% tree.nodes(i).probs     % probs(i) is the prob for i-th value of class node 
+%                         % For three output class, the probs = [0.9 0.1 0.0] means the probability of 
+%                         % class 1 is 0.9, for class 2 is 0.1, for class 3 is 0.0.
+% %%%%%attributes specially for regression tree (continuous output)                          
+% tree.nodes(i).mean      % mean output value for this node
+% tree.nodes(i).std       % standard deviation for output values in this node
+%
+% Author: yimin.zhang@intel.com
+% Last updated: Jan. 19, 2002
+
+% Want list:
+% (1) more efficient for cts attributes: get the values of cts attributes at first (the begining of build_tree function), then doing bi_search in finding threshhold
+% (2) pruning classification tree using Pessimistic Error Pruning
+% (3) bi_search for strings (used for transform data to BNT format)
+
+global tree %tree must be global so that it can be accessed in recursive slitting function
+global cts_min_gain
+tree=[]; % clear the tree
+tree.num_node=0;
+cts_min_gain=0;
+
+stop_cases=0;
+min_gain=0;
+
+args = varargin;
+nargs = length(args);
+if (nargs>0)
+  if isstr(args{1})
+    for i=1:2:nargs
+      switch args{i},
+        case 'stop_cases', stop_cases = args{i+1};   
+        case 'min_gain', min_gain = args{i+1};
+      end
+    end
+  else
+    error(['error in input parameters']);
+  end
+end
+
+if iscell(data)
+  local_data = cell2num(data(fam,:));
+else
+  local_data = data(fam, :);
+end
+%counts = compute_counts(local_data, CPD.sizes);
+%CPD.CPT = mk_stochastic(counts + CPD.prior); % bug fix 11/5/01
+node_types = zeros(1,size(ns,2)); %all nodes are disrete
+node_types(cnodes)=1;
+%make the data be BNT compliant (values for discrete nodes are from 1-n, here n is the node size)
+%trans_data=transform_data(local_data,'tmp.dat',[]); %here no cts nodes
+
+build_dtree (CPD, local_data, ns(fam), node_types(fam),stop_cases,min_gain);
+%CPD.tree=copy_tree(tree);
+CPD.tree=tree; %copy the tree constructed to CPD
+
+
+function new_tree = copy_tree(tree)
+% copy the tree to new_tree
+new_tree.num_node=tree.num_node;
+new_tree.root = tree.root;
+for i=1:tree.num_node
+  new_tree.nodes(i)=tree.nodes(i);
+end
+
+
+function build_dtree (CPD, fam_ev, node_sizes, node_types,stop_cases,min_gain)
+global tree
+global cts_min_gain
+
+tree.num_node=0; %the current number of nodes in the tree
+tree.root=1;
+
+T = 1:size(fam_ev,2) ; %all cases
+candidate_attrs = 1:(size(node_sizes,2)-1); %all attributes
+node_id=1;  %the root node
+lastnode=size(node_sizes,2); %the last element in all nodes is the dependent variable (category node)
+num_cat=node_sizes(lastnode);
+
+% get minimum gain for cts output (used in stop splitting)
+if (node_types(size(fam_ev,1))==1) %cts output
+  N = size(fam_ev,2);
+  output_id = size(fam_ev,1);
+  cases_T = fam_ev(output_id,:); %get all the output value for cases T
+  std_T = std(cases_T);
+  avg_y_T = mean(cases_T);
+  sqr_T = cases_T - avg_y_T;
+  cts_min_gain = min_gain*(sum(sqr_T.*sqr_T)/N);  % min_gain * (R(root) = 1/N * SUM(y-avg_y)^2)
+end  
+
+split_dtree (CPD, fam_ev, node_sizes, node_types, stop_cases,min_gain, T, candidate_attrs, num_cat);
+  
+
+
+% pruning method
+% (1) Restrictions on minimum node size: A node is not split if it has smaller than k cases.
+% (2) Threshholds on impurity: a threshhold is imposed on the splitting test score. Threshhold can be 
+% imposed on local goodness measure (the gain_ratio of a node) or global goodness.
+% (3) Mininum Error Pruning (MEP), (no need pruning set)
+%     Prune if static error<=backed-up error
+%      Static error at node v: e(v) = (Nc + 1)/(N+k) (laplace estimate, prior for each class equal) 
+%        here N is # of all examples, Nc is # of majority class examples, k is number of classes 
+%      Backed-up error at node v: (Ti is the i-th subtree root)
+%         E(T) = Sum_1_to_n(pi*e(Ti))
+% (4) Pessimistic Error Pruning (PEP), used in Quilan C4.5 (no need pruning set, efficient because of pruning top-down)
+%       Probability of error (apparent error rate)
+%           q = (N-Nc+0.5)/N
+%         where N=#examples, Nc=#examples in majority class
+%     Error of a node v (if pruned)  q(v)= (Nv- Nc,v + 0.5)/Nv
+%     Error of a subtree   q(T)= Sum_of_l_leaves(Nl - Nc,l + 0.5)/Sum_of_l_leaves(Nl)
+%     Prune if q(v)<=q(T)
+% 
+% Implementation statuts:
+% (1)(2) has been implemented as the input parameters of learn_params.
+% (4) is implemented in this function
+function pruning(fam_ev,node_sizes,node_types)
+% PRUNING prune the constructed tree using PEP
+% pruning(fam_ev,node_sizes,node_types)
+%
+% fam_ev(i,j)  is the value of attribute i in j-th training cases (for whole tree), the last row is for the class label (self_ev)
+% node_sizes(i) is the node size for the i-th node in the family
+% node_types(i) is the node type for the i-th node in the family, 0 for disrete node, 1 for continous node
+% the global parameter 'tree' is for storing the input tree and the pruned tree
+
+
+function split_T = split_cases(fam_ev,node_sizes,node_types,T,node_i, threshhold)
+% SPLIT_CASES split the cases T according to values of node_i in the family
+% split_T = split_cases(fam_ev,node_sizes,node_types,T,node_i)
+%
+% fam_ev(i,j)  is the value of attribute i in j-th training cases (for whole tree), the last row is for the class label (self_ev)
+% node_sizes(i) is the node size for the i-th node in the family
+% node_types(i) is the node type for the i-th node in the family, 0 for disrete node, 1 for continous node
+% node_i is the attribute we need to split
+
+if (node_types(node_i)==0) %discrete attribute
+  %init the subsets of T
+  split_T = cell(1,node_sizes(node_i)); %T will be separated into |node_size of i| subsets according to different values of node i
+  for i=1:node_sizes(node_i)   % here we assume that the value of an attribute is 1:node_size
+    split_T{i}=zeros(1,0);
+  end
+
+  size_t = size(T,2);
+  for i=1:size_t
+    case_id = T(i);
+    %put this case into one subset of split_T according to its value for node_i
+    value = fam_ev(node_i,case_id); 
+    pos = size(split_T{value},2)+1;
+    split_T{value}(pos)=case_id;  % here assumes the value of an attribute is 1:node_size 
+  end
+else %continuous attribute
+  %init the subsets of T
+  split_T = cell(1,2); %T will be separated into 2 subsets (<=threshhold) (>threshhold)
+  for i=1:2   
+    split_T{i}=zeros(1,0);
+  end
+
+  size_t = size(T,2);
+  for i=1:size_t
+    case_id = T(i);
+    %put this case into one subset of split_T according to its value for node_i
+    value = fam_ev(node_i,case_id); 
+    subset_num=1;
+    if (value>threshhold)
+      subset_num=2;
+    end  
+    pos = size(split_T{subset_num},2)+1;
+    split_T{subset_num}(pos)=case_id;  
+  end
+end
+
+
+  
+function new_node = split_dtree (CPD, fam_ev, node_sizes, node_types, stop_cases, min_gain, T, candidate_attrs, num_cat)
+% SPLIT_TREE Split the tree at node node_id with cases T (actually it is just indexes to family evidences).
+% new_node = split_dtree (fam_ev, node_sizes, node_types, T, node_id, num_cat, method)
+%
+% fam_ev(i,j)  is the value of attribute i in j-th training cases (for whole tree), the last row is for the class label (self_ev)
+% node_sizes{i} is the node size for the i-th node in the family
+% node_types{i} is the node type for the i-th node in the family, 0 for disrete node, 1 for continous node
+% stop_cases is the threshold of number of cases to stop slitting
+% min_gain is the minimum gain need to split a node
+% T(i) is the index of i-th cases in current decision tree node, we need split it further
+% candidate_attrs(i) the node id for the i-th attribute that still need to be considered as split attribute 
+%%%%% node_id is the index of current node considered for a split
+% num_cat is the number of output categories for the decision tree
+% output:
+% new_node is the new node created
+global tree
+global cts_min_gain
+
+size_fam = size(fam_ev,1);            %number of family size
+output_type = node_types(size_fam);   %the type of output for the tree (0 is discrete, 1 is continuous)
+size_attrs = size(candidate_attrs,2); %number of candidate attributes
+size_t = size(T,2);                   %number of training cases in this tree node
+
+%(1)computeFrequenceyForEachClass(T)
+if (output_type==0) %discrete output
+  class_freqs = zeros(1,num_cat);
+  for i=1:size_t
+    case_id = T(i);
+    case_class = fam_ev(size_fam,case_id); %get the class label for this case
+    class_freqs(case_class)=class_freqs(case_class)+1;
+  end
+else  %cts output
+  N = size(fam_ev,2);
+  cases_T = fam_ev(size(fam_ev,1),T); %get the output value for cases T
+  std_T = std(cases_T);
+end
+
+%(2) if OneClass (for discrete output) or same output value (for cts output) or Class With #examples < stop_cases
+%         return a leaf;
+%    create a decision node N;
+
+% get majority class in this node
+if (output_type == 0)
+  top1_class = 0;       %the class with the largest number of cases
+  top1_class_cases = 0; %the number of cases in top1_class
+  [top1_class_cases,top1_class]=max(class_freqs);
+end
+  
+if (size_t==0)     %impossble
+  new_node=-1;
+  fprintf('Fatal error: please contact the author. \n');
+  return;
+end
+
+% stop splitting if needed
+  %for discrete output: one class 
+  %for cts output, all output value in cases are same
+  %cases too little
+if ( (output_type==0 & top1_class_cases == size_t) | (output_type==1 & std_T == 0) | (size_t < stop_cases))             
+  %create one new leaf node
+  tree.num_node=tree.num_node+1;
+  tree.nodes(tree.num_node).used=1; %flag this node is used (0 means node not used, it will be removed from tree at last to save memory)
+  tree.nodes(tree.num_node).is_leaf=1;
+  tree.nodes(tree.num_node).children=[];
+  tree.nodes(tree.num_node).split_id=0;  %the attribute(parent) id to split this tree node
+  tree.nodes(tree.num_node).split_threshhold=0;  
+  if (output_type==0)
+    tree.nodes(tree.num_node).probs=class_freqs/size_t; %the prob for each value of class node 
+
+    %  tree.nodes(tree.num_node).probs=zeros(1,num_cat); %the prob for each value of class node 
+    %  tree.nodes(tree.num_node).probs(top1_class)=1; %use the majority class of parent node, like for binary class, 
+                                                   %and majority is class 2, then the CPT is [0 1]
+                                                   %we may need to use prior to do smoothing, to get [0.001 0.999]
+    tree.nodes(tree.num_node).error.self_error=1-top1_class_cases/size_t; %the classfication error in this tree node when use default class
+    tree.nodes(tree.num_node).error.all_error=1-top1_class_cases/size_t;  %no total classfication error in this tree node and its subtree
+    tree.nodes(tree.num_node).error.all_error_num=size_t - top1_class_cases;
+    fprintf('Create leaf node(onecla) %d. Class %d Cases %d Error %d \n',tree.num_node, top1_class, size_t, size_t - top1_class_cases );
+  else
+    avg_y_T = mean(cases_T);
+    tree.nodes(tree.num_node).mean = avg_y_T; 
+    tree.nodes(tree.num_node).std = std_T;
+    fprintf('Create leaf node(samevalue) %d. Mean %8.4f Std %8.4f Cases %d \n',tree.num_node, avg_y_T, std_T, size_t);
+  end  
+  new_node = tree.num_node;
+  return;
+end
+    
+%create one new node
+tree.num_node=tree.num_node+1;
+tree.nodes(tree.num_node).used=1; %flag this node is used (0 means node not used, it will be removed from tree at last to save memory)
+tree.nodes(tree.num_node).is_leaf=1;
+tree.nodes(tree.num_node).children=[];
+tree.nodes(tree.num_node).split_id=0;
+tree.nodes(tree.num_node).split_threshhold=0;  
+if (output_type==0)
+  tree.nodes(tree.num_node).error.self_error=1-top1_class_cases/size_t; 
+  tree.nodes(tree.num_node).error.all_error=0;
+  tree.nodes(tree.num_node).error.all_error_num=0;
+else
+  avg_y_T = mean(cases_T);
+  tree.nodes(tree.num_node).mean = avg_y_T; 
+  tree.nodes(tree.num_node).std = std_T;
+end
+new_node = tree.num_node;
+
+%Stop splitting if no attributes left in this node
+if (size_attrs==0) 
+  if (output_type==0)
+    tree.nodes(tree.num_node).probs=class_freqs/size_t; %the prob for each value of class node 
+    tree.nodes(tree.num_node).error.all_error=1-top1_class_cases/size_t;  
+    tree.nodes(tree.num_node).error.all_error_num=size_t - top1_class_cases;
+    fprintf('Create leaf node(noattr) %d. Class %d Cases %d Error %d \n',tree.num_node, top1_class, size_t, size_t - top1_class_cases );
+  else
+    fprintf('Create leaf node(noattr) %d. Mean %8.4f Std %8.4f Cases %d \n',tree.num_node, avg_y_T, std_T, size_t);
+  end
+  return;
+end
+      
+  
+%(3) for each attribute A
+%        ComputeGain(A);
+max_gain=0;  %the max gain score (for discrete information gain or gain ration, for cts node the R(T))
+best_attr=0;  %the attribute with the max_gain
+best_split = []; %the split of T according to the value of best_attr
+cur_best_threshhold = 0; %the threshhold for split continuous attribute
+best_threshhold=0;
+
+% compute Info(T) (for discrete output)
+if (output_type == 0)
+  class_split_T = split_cases(fam_ev,node_sizes,node_types,T,size(fam_ev,1),0); %split cases according to class
+  info_T = compute_info (fam_ev, T, class_split_T);
+else % compute R(T) (for cts output)
+%  N = size(fam_ev,2);
+%  cases_T = fam_ev(size(fam_ev,1),T); %get the output value for cases T
+%  std_T = std(cases_T);
+%  avg_y_T = mean(cases_T);
+  sqr_T = cases_T - avg_y_T;
+  R_T = sum(sqr_T.*sqr_T)/N;  % get R(T) = 1/N * SUM(y-avg_y)^2
+  info_T = R_T;
+end
+
+for i=1:(size_fam-1)
+  if (myismember(i,candidate_attrs))  %if this attribute still in the candidate attribute set
+    if (node_types(i)==0) %discrete attibute
+      split_T = split_cases(fam_ev,node_sizes,node_types,T,i,0); %split cases according to value of attribute i
+      % For cts output, we compute the least square gain.
+      % For discrete output, we compute gain ratio
+      cur_gain = compute_gain(fam_ev,node_sizes,node_types,T,info_T,i,split_T,0,output_type); %gain ratio
+    else %cts attribute
+      %get the values of this attribute
+      ev = fam_ev(:,T);
+      values = ev(i,:);
+      sort_v = sort(values); 
+        %remove the duplicate values in sort_v
+      v_set = unique(sort_v);  
+      best_gain = 0;
+      best_threshhold = 0;
+      best_split1 = [];
+      
+      %find the best split for this cts attribute
+      % see "Quilan 96: Improved Use of Continuous Attributes in C4.5"
+      for j=1:(size(v_set,2)-1)
+        mid_v = (v_set(j)+v_set(j+1))/2; 
+        split_T = split_cases(fam_ev,node_sizes,node_types,T,i,mid_v); %split cases according to value of attribute i (<=mid_v)
+        % For cts output, we compute the least square gain.
+        % For discrete output, we use Quilan 96: use information gain instead of gain ratio to select threshhold
+        cur_gain = compute_gain(fam_ev,node_sizes,node_types,T,info_T,i,split_T,1,output_type); 
+        %if (i==6)
+        %  fprintf('gain %8.5f threshhold %6.3f spliting %d\n', cur_gain, mid_v, size(split_T{1},2));
+        %end
+
+        if (best_gain < cur_gain)
+          best_gain = cur_gain;
+          best_threshhold = mid_v;
+          %best_split1 = split_T;     %here we need to copy array, not good!!! (maybe we can compute after we get best_attr
+        end
+      end
+      %recalculate the gain_ratio of the best_threshhold
+      split_T = split_cases(fam_ev,node_sizes,node_types,T,i,best_threshhold);
+      best_gain = compute_gain(fam_ev,node_sizes,node_types,T,info_T,i,split_T,0,output_type); %gain_ratio
+      if (output_type==0) %for discrete output
+        cur_gain = best_gain-log2(size(v_set,2)-1)/size_t; % Quilan 96: use the gain_ratio-log2(N-1)/|D| as the gain of this attr
+      else                %for cts output
+        cur_gain = best_gain;
+      end
+    end
+    
+    if (max_gain < cur_gain)
+      max_gain = cur_gain;
+      best_attr = i;
+      cur_best_threshhold=best_threshhold;  %save the threshhold
+      %best_split = split_T;        %here we need to copy array, not good!!! So we will recalculate in below line 313
+    end
+  end
+end
+
+% stop splitting if gain is too small
+if (max_gain==0 | (output_type==0 & max_gain < min_gain) | (output_type==1 & max_gain < cts_min_gain)) 
+  if (output_type==0)
+    tree.nodes(tree.num_node).probs=class_freqs/size_t; %the prob for each value of class node 
+    tree.nodes(tree.num_node).error.all_error=1-top1_class_cases/size_t;  
+    tree.nodes(tree.num_node).error.all_error_num=size_t - top1_class_cases;
+    fprintf('Create leaf node(nogain) %d. Class %d Cases %d Error %d \n',tree.num_node, top1_class, size_t, size_t - top1_class_cases );
+  else
+    fprintf('Create leaf node(nogain) %d. Mean %8.4f Std %8.4f Cases %d \n',tree.num_node, avg_y_T, std_T, size_t);
+  end
+  return;
+end
+
+%get the split of cases according to the best split attribute
+if (node_types(best_attr)==0) %discrete attibute
+  best_split = split_cases(fam_ev,node_sizes,node_types,T,best_attr,0);  
+else  
+  best_split = split_cases(fam_ev,node_sizes,node_types,T,best_attr,cur_best_threshhold);
+end
+  
+%(4) best_attr = AttributeWithBestGain;
+%(5) if best_attr is continuous             ???? why need this? maybe the value in the decision tree must appeared in data
+%       find threshhold in all cases that <= max_V
+%    change the split of T
+tree.nodes(tree.num_node).split_id=best_attr;
+tree.nodes(tree.num_node).split_threshhold=cur_best_threshhold; %for cts attribute only
+
+%note: below threshhold rejust is linera search, so it is slow. A better method is described in paper "Efficient C4.5"
+%if (output_type==0)
+if (node_types(best_attr)==1)  %is a continuous attribute
+  %find the value that approximate best_threshhold from below (the largest that <= best_threshhold)
+  best_value=0;
+  for i=1:size(fam_ev,2)  %note: need to search in all cases for all tree, not just in cases for this node
+    val = fam_ev(best_attr,i);
+    if (val <= cur_best_threshhold & val > best_value) %val is more clear to best_threshhold
+      best_value=val;
+    end
+  end
+  tree.nodes(tree.num_node).split_threshhold=best_value; %for cts attribute only
+end
+%end
+  
+if (output_type == 0)
+  fprintf('Create node %d split at %d gain %8.4f Th %d. Class %d Cases %d Error %d \n',tree.num_node, best_attr, max_gain, tree.nodes(tree.num_node).split_threshhold, top1_class, size_t, size_t - top1_class_cases );
+else
+  fprintf('Create node %d split at %d gain %8.4f Th %d. Mean %8.4f Cases %d\n',tree.num_node, best_attr, max_gain, tree.nodes(tree.num_node).split_threshhold, avg_y_T, size_t );
+end
+  
+%(6) Foreach T' in the split_T
+%        if T' is Empty
+%            Child of node_id is a leaf
+%        else
+%            Child of node_id = split_tree (T')
+tree.nodes(new_node).is_leaf=0; %because this node will be split, it is not leaf now
+for i=1:size(best_split,2)
+  if (size(best_split{i},2)==0) %T(i) is empty
+    %create one new leaf node
+    tree.num_node=tree.num_node+1;
+    tree.nodes(tree.num_node).used=1; %flag this node is used (0 means node not used, it will be removed from tree at last to save memory)
+    tree.nodes(tree.num_node).is_leaf=1;
+    tree.nodes(tree.num_node).children=[];
+    tree.nodes(tree.num_node).split_id=0;
+    tree.nodes(tree.num_node).split_threshhold=0;  
+    if (output_type == 0)
+      tree.nodes(tree.num_node).probs=zeros(1,num_cat); %the prob for each value of class node 
+      tree.nodes(tree.num_node).probs(top1_class)=1; %use the majority class of parent node, like for binary class, 
+                                                   %and majority is class 2, then the CPT is [0 1]
+                                                   %we may need to use prior to do smoothing, to get [0.001 0.999]
+      tree.nodes(tree.num_node).error.self_error=0; 
+      tree.nodes(tree.num_node).error.all_error=0;  
+      tree.nodes(tree.num_node).error.all_error_num=0;
+    else
+      tree.nodes(tree.num_node).mean = avg_y_T; %just use parent node's mean value
+      tree.nodes(tree.num_node).std = std_T;
+    end
+    %add the new leaf node to parents
+    num_children=size(tree.nodes(new_node).children,2);
+    tree.nodes(new_node).children(num_children+1)=tree.num_node;
+    if (output_type==0)
+      fprintf('Create leaf node(nullset) %d. %d-th child of Father %d Class %d\n',tree.num_node, i, new_node, top1_class );
+    else
+      fprintf('Create leaf node(nullset) %d. %d-th child of Father %d \n',tree.num_node, i, new_node );
+    end
+
+  else
+    if (node_types(best_attr)==0)  % if attr is discrete, it should be removed from the candidate set  
+      new_candidate_attrs = mysetdiff(candidate_attrs,[best_attr]);
+    else
+      new_candidate_attrs = candidate_attrs;
+    end
+    new_sub_node = split_dtree (CPD, fam_ev, node_sizes, node_types, stop_cases, min_gain, best_split{i}, new_candidate_attrs, num_cat);  
+    %tree.nodes(parent_id).error.all_error += tree.nodes(new_sub_node).error.all_error;
+    fprintf('Add subtree node %d to %d. #nodes %d\n',new_sub_node,new_node, tree.num_node );
+
+%   tree.nodes(new_node).error.all_error_num = tree.nodes(new_node).error.all_error_num + tree.nodes(new_sub_node).error.all_error_num;
+    %add the new leaf node to parents
+    num_children=size(tree.nodes(new_node).children,2);
+    tree.nodes(new_node).children(num_children+1)=new_sub_node;
+  end
+end   
+  
+%(7) Compute errors of N; for doing pruning
+%    get the total error for the subtree
+if (output_type==0)
+  tree.nodes(new_node).error.all_error=tree.nodes(new_node).error.all_error_num/size_t;
+end
+%doing pruning, but doing here is not so efficient, because it is bottom up.
+%if tree.nodes()
+%after doing pruning, need to update the all_error to self_error
+
+%(8) Return N
+  
+
+
+
+%(1) For discrete output, we use GainRatio defined as below
+%  			         Gain(X,T)
+% 	GainRatio(X,T) = ----------
+% 			         SplitInfo(X,T)
+%   where
+%   Gain(X,T) = Info(T) - Info(X,T)
+%    				                       |Ti|
+% 	Info(X,T) = Sum for i from 1 to n of ( ---- * Info(Ti))
+%                                          |T|
+ 			 
+%   SplitInfo(D,T) is the information due to the split of T on the basis
+%    of the value of the categorical attribute D. Thus SplitInfo(D,T) is
+%  		 I(|T1|/|T|, |T2|/|T|, .., |Tm|/|T|)
+%    where {T1, T2, .. Tm} is the partition of T induced by the value of D.
+
+%   Definition of Info(Ti)
+%     If a set T of records is partitioned into disjoint exhaustive classes C1, C2, .., Ck on the basis of the 
+%     value of the categorical attribute, then the information needed to identify the class of an element of T 
+%     is Info(T) = I(P), where P is the probability distribution of the partition (C1, C2, .., Ck): 
+%     	P = (|C1|/|T|, |C2|/|T|, ..., |Ck|/|T|)
+%     Here I(P) is defined as
+%       I(P) = -(p1*log(p1) + p2*log(p2) + .. + pn*log(pn))
+% 
+%(2) For continuous output (regression tree), we use least squares score (adapted from Leo Breiman's book "Classification and regression trees", page 231
+%    The original support only binary split, we further extend it to permit multiple-child split
+%                                        
+%     Delta_R = R(T) - Sum for all childe nodes Ti (R(Ti))
+%     Where R(Ti)= 1/N * Sum for all cases i in node Ti ((yi - avg_y(Ti))^2)
+%     here N is the number of all training cases for construct the regression tree
+%          avg_y(Ti) is the average value for output variable for the cases in node Ti
+
+function gain_score = compute_gain (fam_ev, node_sizes, node_types, T, info_T, attr_id, split_T, score_type, output_type)
+% COMPUTE_GAIN Compute the score for the split of cases T using attribute attr_id
+% gain_score = compute_gain (fam_ev, T, attr_id, node_size, method)
+%
+% fam_ev(i,j)  is the value of attribute i in j-th training cases, the last row is for the class label (self_ev)
+% T(i) is the index of i-th cases in current decision tree node, we need split it further
+% attr_id is the index of current node considered for a split
+% split_T{i} is the i_th subset in partition of cases T according to the value of attribute attr_id
+% score_type if 0, is gain ratio, 1 is information gain (only apply to discrete output)
+% node_size(i) the node size of i-th node in the family
+% output_type: 0 means discrete output, 1 means continuous output.
+gain_score=0;
+% ***********for DISCRETE output*******************************************************
+if (output_type == 0)
+  % compute Info(T)
+  total_cnt = size(T,2);
+  if (total_cnt==0)
+    return;
+  end;
+  %class_split_T = split_cases(fam_ev,node_sizes,node_types,T,size(fam_ev,1),0); %split cases according to class
+  %info_T = compute_info (fam_ev, T, class_split_T);
+
+  % compute Info(X,T)
+  num_class = size(split_T,2); 
+  subset_sizes = zeros(1,num_class);
+  info_ti = zeros(1,num_class);
+  for i=1:num_class
+    subset_sizes(i)=size(split_T{i},2);
+    if (subset_sizes(i)~=0)
+      class_split_Ti = split_cases(fam_ev,node_sizes,node_types,split_T{i},size(fam_ev,1),0); %split cases according to class
+      info_ti(i) = compute_info(fam_ev, split_T{i}, class_split_Ti);
+    end
+  end    
+  ti_ratios = subset_sizes/total_cnt;  %get the |Ti|/|T|
+  info_X_T = sum(ti_ratios.*info_ti);
+
+  %get Gain(X,T)
+  gain_X_T = info_T - info_X_T;
+
+  if (score_type == 1) %information gain
+    gain_score=gain_X_T;
+    return;
+  end
+  %compute the SplitInfo(X,T)   //is this also for cts attr, only split into two subsets
+  splitinfo_T = compute_info (fam_ev, T, split_T);
+  if (splitinfo_T~=0)
+    gain_score = gain_X_T/splitinfo_T;
+  end
+
+% ************for continuous output**************************************************
+else 
+  N = size(fam_ev,2);
+
+  % compute R(Ti)
+  num_class = size(split_T,2); 
+  R_Ti = zeros(1,num_class);
+  for i=1:num_class
+    if (size(split_T{i},2)~=0)
+      cases_T = fam_ev(size(fam_ev,1),split_T{i});
+      avg_y_T = mean(cases_T);
+      sqr_T = cases_T - avg_y_T;
+      R_Ti(i) = sum(sqr_T.*sqr_T)/N;  % get R(Ti) = 1/N * SUM(y-avg_y)^2
+    end
+  end
+  %delta_R = R(T) - SUM(R(Ti))
+  gain_score = info_T - sum(R_Ti);
+
+end
+
+
+%   Definition of Info(Ti)
+%     If a set T of records is partitioned into disjoint exhaustive classes C1, C2, .., Ck on the basis of the 
+%     value of the categorical attribute, then the information needed to identify the class of an element of T 
+%     is Info(T) = I(P), where P is the probability distribution of the partition (C1, C2, .., Ck): 
+%     	P = (|C1|/|T|, |C2|/|T|, ..., |Ck|/|T|)
+%     Here I(P) is defined as
+%       I(P) = -(p1*log(p1) + p2*log(p2) + .. + pn*log(pn))
+function info = compute_info (fam_ev, T, split_T)
+% COMPUTE_INFO compute the information for the split of T into split_T
+% info = compute_info (fam_ev, T, split_T)
+
+total_cnt = size(T,2);
+num_class = size(split_T,2);
+subset_sizes = zeros(1,num_class);
+probs = zeros(1,num_class);
+log_probs = zeros(1,num_class);
+for i=1:num_class
+  subset_sizes(i)=size(split_T{i},2);
+end    
+
+probs = subset_sizes/total_cnt;
+%log_probs = log2(probs);  % if probs(i)=0, the log2(probs(i)) will be Inf
+for i=1:size(probs,2)
+  if (probs(i)~=0)
+    log_probs(i)=log2(probs(i));
+  end
+end
+
+info = sum(-(probs.*log_probs));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tree_CPD/readme.txt	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+Decision/regression tree CPD
+Author: Yimin Zhang yimin.zhang@intel.com
+21 Jan 2002
+
+
+See also Paul Bradley's Multisurface Method-Tree matlab code
+ http://www.cs.wisc.edu/~paulb/msmt/
+http://www.cs.wisc.edu/~olvi/uwmp/msmt.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tree_CPD/set_fields.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+function CPD = set_fields(CPD, varargin)
+% SET_PARAMS Set the parameters (fields) for a tabular_CPD object
+% CPD = set_params(CPD, name/value pairs)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+%
+% CPT     - the CPT
+% prior   - the prior
+% clamped - 1 means don't adjust during EM
+%
+% e.g., CPD = set_params(CPD, 'CPT', 'rnd')
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'CPT', 
+    if ischar(args{i+1})
+      switch args{i+1}
+       case 'unif', CPD.CPT = mk_stochastic(myones(CPD.sizes));
+       case 'rnd',  CPD.CPT = mk_stochastic(myrand(CPD.sizes));
+       otherwise,   error(['invalid type ' args{i+1}]);       
+      end
+    elseif isscalar(args{i+1})
+      p = args{i+1};
+      k = CPD.sizes(end);
+      % Bug fix by Hervé BOUTROUILLE 10/1/01
+      CPD.CPT = myreshape(sample_dirichlet(p*ones(1,k), prod(CPD.sizes(1:end-1)), CPD.sizes));   
+      %CPD.CPT = myreshape(sample_dirichlet(p*ones(1,k), prod(CPD.sizes(1:end-1))), CPD.sizes);
+    else
+      CPD.CPT = myreshape(args{i+1}, CPD.sizes);
+    end
+   
+   case 'prior',       
+    if ischar(args{i+1}) & strcmp(args{i+1}, 'unif')
+      CPD.prior = myones(CPD.sizes);
+    elseif isscalar(args{i+1})
+      CPD.prior = args{i+1} * normalise(myones(CPD.sizes));
+    else
+      CPD.prior = myreshape(args{i+1}, CPD.sizes);
+    end
+    
+   %case 'clamped',      CPD.clamped = strcmp(args{i+1}, 'yes');
+   %case 'clamped',      CPD = set_clamped(CPD, strcmp(args{i+1}, 'yes'));
+   case 'clamped',      CPD = set_clamped(CPD, args{i+1});
+   
+   otherwise,  
+    %error(['invalid argument name ' args{i}]);       
+  end
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/@tree_CPD/tree_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,37 @@
+function CPD = tree_CPD(varargin)
+%DTREE_CPD Make a conditional prob. distrib. which is a decision/regression tree.
+%
+% CPD =dtree_CPD() will create an empty tree.
+
+if nargin==0
+  % This occurs if we are trying to load an object from a file.
+  CPD = init_fields;
+  clamp = 0;
+  CPD = class(CPD, 'tree_CPD', discrete_CPD(clamp, []));
+  return;
+elseif isa(varargin{1}, 'tree_CPD')
+  % This might occur if we are copying an object.
+  CPD = varargin{1};
+  return;
+end
+
+CPD = init_fields;
+
+
+clamped = 0;
+fam_sz = [];
+CPD = class(CPD, 'tree_CPD', discrete_CPD(clamped, fam_sz));
+
+
+%%%%%%%%%%%
+
+function CPD = init_fields()
+% This ensures we define the fields in the same order 
+% no matter whether we load an object from a file,
+% or create it from scratch. (Matlab requires this.)
+
+%init the decision tree set the root to null
+CPD.tree.num_node = 0;
+CPD.tree.root=1;
+CPD.tree.nodes=[];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/mk_isolated_tabular_CPD.m/1.1.1.1/Mon Jun 24 18:58:32 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+A D/@boolean_CPD////
+A D/@deterministic_CPD////
+A D/@discrete_CPD////
+A D/@gaussian_CPD////
+A D/@generic_CPD////
+A D/@gmux_CPD////
+A D/@hhmm2Q_CPD////
+A D/@hhmmF_CPD////
+A D/@hhmmQ_CPD////
+A D/@mlp_CPD////
+A D/@noisyor_CPD////
+A D/@root_CPD////
+A D/@softmax_CPD////
+A D/@tabular_CPD////
+A D/@tabular_decision_node////
+A D/@tabular_kernel////
+A D/@tabular_utility_node////
+A D/@tree_CPD////
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/CPDs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CPDs/mk_isolated_tabular_CPD.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+function CPD = mk_isolated_tabular_CPD(fam_sz, args)
+% function CPD = mk_isolated_tabular_CPD(fam_sz, args)
+% function CPD = mk_isolated_tabular_CPD(fam_sz, args)
+% Make a single CPD by creating a mini-bnet containing just this one family.
+% This is necessary because the CPD constructor requires a bnet.
+
+n = length(fam_sz);
+dag = zeros(n,n);
+ps = 1:(n-1);
+if ~isempty(ps)
+  dag(ps,n) = 1;
+end
+bnet = mk_bnet(dag, fam_sz);
+CPD = tabular_CPD(bnet, n, args{:});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+/README.txt/1.1.1.1/Thu Jun 10 01:56:50 2004//
+/add_BNT_to_path.m/1.2/Sat Sep 17 16:58:43 2005//
+/copyright.txt/1.1.1.1/Sat Jan 18 23:00:58 2003//
+/installC_BNT.m/1.1.1.1/Thu Mar 31 19:20:56 2005//
+/installC_graph.m/1.1.1.1/Tue May 18 14:50:12 2004//
+/license.gpl.txt/1.1.1.1/Wed May 29 15:59:56 2002//
+/test_BNT.m/1.3/Sat Sep 17 16:56:27 2005//
+/uninstallC_BNT.m/1.1.1.1/Sun May  4 22:31:38 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+A D/@assocarray////
+A D/CPDs////
+A D/examples////
+A D/general////
+A D/inference////
+A D/learning////
+A D/potentials////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/README.txt	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+The Bayes Net Toolbox for Matlab was written by Kevin Patrick Murphy et al.
+This version was last updated on 17 Oct 2007..
+To download the latest version, and to get documentation, please go to
+   http://www.cs.ubc.ca/~murphyk/Software/BNT/bnt.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/copyright.txt	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+Written by Kevin Murphy (murphyk@ai.mit.edu), 1997-2003
+Distributed under the GNU Library GPL - see license.gpl for details.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,50 @@
+/add_ev_to_dmarginal.m/1.1.1.1/Thu Jun 27 20:34:32 2002//
+/add_evidence_to_gmarginal.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/bnet_to_fgraph.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/compute_fwd_interface.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/compute_interface_nodes.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/compute_joint_pot.m/1.1.1.1/Mon Jun  7 15:50:34 2004//
+/compute_minimal_interface.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/convert_dbn_CPDs_to_pots.m/1.1.1.1/Fri Nov 22 22:35:00 2002//
+/convert_dbn_CPDs_to_tables.m/1.1.1.1/Thu Jan 23 18:44:50 2003//
+/convert_dbn_CPDs_to_tables1.m/1.1.1.1/Thu Jan 23 18:49:48 2003//
+/convert_dbn_CPDs_to_tables_slow.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/dbn_to_bnet.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/dbn_to_hmm.m/1.1.1.1/Sun Feb  2 00:23:38 2003//
+/determine_elim_constraints.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/dispcpt.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/do_intervention.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/dsep.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/dsep_test.m/1.1.1.1/Sat Jan 18 23:10:16 2003//
+/enumerate_scenarios.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/fgraph_to_bnet.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/hodbn_to_bnet.m/1.1.1.1/Wed Jul 24 14:48:06 2002//
+/is_mnet.m/1.1.1.1/Sun Jun 16 20:01:22 2002//
+/linear_gaussian_to_cpot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/log_lik_complete.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/log_marg_lik_complete.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/mk_bnet.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/mk_dbn.m/1.1.1.1/Sat Feb  1 19:42:14 2003//
+/mk_fgraph.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/mk_fgraph_given_ev.m/1.1.1.1/Mon Jun 24 18:56:26 2002//
+/mk_higher_order_dbn.m/1.1.1.1/Tue Jul 23 13:17:04 2002//
+/mk_limid.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/mk_mnet.m/1.1.1.1/Sun Jun 16 19:52:12 2002//
+/mk_mrf2.m/1.1.1.1/Tue Dec 31 22:06:48 2002//
+/mk_mutilated_samples.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/mk_named_CPT.m/1.1.1.1/Tue Mar 30 17:18:54 2004//
+/mk_slice_and_half_dbn.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/noisyORtoTable.m/1.1.1.1/Mon Aug  2 22:05:58 2004//
+/partition_dbn_nodes.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/partition_matrix_vec_3.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/sample_bnet.m/1.1.1.1/Thu Jun 10 01:17:46 2004//
+/sample_bnet_nocell.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/sample_dbn.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/score_bnet_complete.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/shrink_obs_dims_in_gaussian.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/shrink_obs_dims_in_table.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/solve_limid.m/1.1.1.1/Mon Jun  7 15:48:02 2004//
+/unroll_dbn_topology.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/unroll_higher_order_topology.m/1.1.1.1/Fri May 31 10:25:58 2002//
+/unroll_set.m/1.1.1.1/Mon Dec 16 17:57:14 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/general
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+/bnet_to_gdl_graph.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/calc_mpe.m/1.1.1.1/Mon Jun 17 21:58:38 2002//
+/calc_mpe_bucket.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/calc_mpe_dbn.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/calc_mpe_given_inf_engine.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/calc_mpe_global.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/compute_interface_nodes.m/1.1.1.1/Wed May 29 15:59:54 2002//
+/mk_gdl_graph.m/1.1.1.1/Wed May 29 15:59:54 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/general/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/Old/bnet_to_gdl_graph.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function gdl = bnet_to_gdl_graph(bnet)
+% BNET_TO_GDL_GRAPH Convert a Bayesian network to a GDL graph
+% gdl = bnet_to_gdl_graph(bnet)
+%
+% Each node in the BN gets converted to a single node in the GDL graph,
+% representing its family; its kernel function is the corresponding CPD.
+
+N = length(bnet.dag);
+doms = cell(1,N);
+for i=1:N
+  doms{i} = family(bnet.dag, i);
+end
+
+U = mk_undirected(bnet.dag);
+gdl = mk_gdl_graph(U, doms, bnet.node_sizes, bnet.CPD, 'equiv_class', bnet.equiv_class, ...
+		   'discrete', bnet.dnodes, 'chance', bnet.chance_nodes, ...
+		   'decision', bnet.decision_nodes, 'utility', bnet.utility_nodes);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/Old/calc_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+function [mpe, ll] = calc_mpe(engine, evidence, break_ties)
+% CALC_MPE Computes the most probable explanation of the evidence
+% [mpe, ll] = calc_mpe_given_inf_engine(engine, evidence, break_ties)
+%
+% INPUT
+% engine must support max-propagation
+% evidence{i} is the observed value of node i, or [] if hidden
+% break_ties is optional. If 1, we will force ties to be broken consistently
+%  by calling enter_evidence N times.
+%
+% OUTPUT
+% mpe{i} is the most likely value of node i (cell array!)
+% ll is the log-likelihood of the globally best assignment
+%
+% This currently only works when all hidden nodes are discrete
+
+if nargin < 3, break_ties = 0; end
+
+
+[engine, ll] = enter_evidence(engine, evidence, 'maximize', 1);
+
+observed = ~isemptycell(evidence);
+
+if 0 % fgraphs don't support bnet_from_engine
+onodes = find(observed);
+bnet = bnet_from_engine(engine);
+pot_type = determine_pot_type(bnet, onodes);
+assert(pot_type == 'd');
+end
+
+scalar = 1;
+evidence = evidence(:); % hack to handle unrolled DBNs
+N = length(evidence);
+mpe = cell(1,N);
+for i=1:N
+  m = marginal_nodes(engine, i);
+  % observed nodes are all set to 1 inside the inference engine, so we must undo this
+  if observed(i)
+    mpe{i} = evidence{i};
+  else
+    mpe{i} = argmax(m.T);
+    % Bug fix by Ron Zohar, 8/15/01
+    % If there are ties, we must break them as follows (see Jensen96, p106)
+    if break_ties
+      evidence{i} = mpe{i};                             
+      [engine, ll] = enter_evidence(engine, evidence, 'maximize', 1);  
+    end
+  end
+  if length(mpe{i}) > 1, scalar = 0; end
+end
+
+if nargout >= 2
+  bnet = bnet_from_engine(engine);
+  ll = log_lik_complete(bnet, mpe(:));
+end
+if 0 % scalar
+  mpe = cell2num(mpe);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/Old/calc_mpe_bucket.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,160 @@
+function [mpe, ll] = calc_mpe_bucket(bnet, new_evidence, max_over)
+%
+% PURPOSE:
+%       CALC_MPE Computes the most probable explanation to the network nodes
+%       given the evidence.
+%       
+%       [mpe, ll] = calc_mpe(engine, new_evidence, max_over)
+%
+% INPUT:
+%       bnet  - the bayesian network
+%       new_evidence - optional, if specified - evidence to be incorporated [cell(1,n)]
+%       max_over - optional, if specified determines the variable elimination order [1:n]
+%
+% OUTPUT:
+%       mpe - the MPE assignmet for the net variables (or [] if no satisfying assignment)
+%       ll - log assignment probability.
+%
+% Notes:
+% 1. Adapted from '@var_elim_inf_engine\marginal_nodes' for MPE by Ron Zohar, 8/7/01
+% 2. Only discrete potentials are supported at this time.
+% 3. Complexity: O(nw*) where n is the number of nodes and w* is the induced tree width.
+% 4. Implementation based on:
+%  - R. Dechter, "Bucket Elimination: A Unifying Framework for Probabilistic Inference", 
+%                 UA1 96, pp. 211-219.
+
+
+ns = bnet.node_sizes;
+n = length(bnet.dag);
+evidence = cell(1,n);
+if (nargin<2)
+    new_evidence = evidence;
+end
+
+onodes = find(~isemptycell(new_evidence));  % observed nodes
+hnodes = find(isemptycell(new_evidence));  % hidden nodes
+pot_type = determine_pot_type(bnet, onodes);
+
+if pot_type ~= 'd'
+  error('only disrete potentials supported at this time')    
+end
+
+for i=1:n
+  fam = family(bnet.dag, i);
+  CPT{i} = convert_to_pot(bnet.CPD{bnet.equiv_class(i)}, pot_type, fam(:), evidence);        
+end 
+
+% handle observed nodes: set impossible cases' probability to zero
+% rather than prun matrix (this makes backtracking easier)
+
+for ii=onodes
+  lIdx = 1:ns(ii);
+  lIdx = setdiff(lIdx, new_evidence{ii});
+  
+  sCPT=struct(CPT{ii});  % violate object privacy
+  
+  sargs = '';
+  for jj=1:(length(sCPT.domain)-1)
+    sargs = [sargs, ':,']; 
+  end        
+  for jj=lIdx
+    eval(['sCPT.T(', sargs, num2str(jj), ')=0;']);
+  end
+  CPT{ii}=dpot(sCPT.domain, sCPT.sizes, sCPT.T);        
+end
+
+B = cell(1,n); 
+for b=1:n
+  B{b} = mk_initial_pot(pot_type, [], [], [], []);
+end
+
+if (nargin<3)
+  max_over = (1:n);
+end   
+order = max_over; % no attempt to optimize this
+
+
+% Initialize the buckets with the CPDs assigned to them
+for i=1:n
+  b = bucket_num(domain_pot(CPT{i}), order);
+  B{b} = multiply_pots(B{b}, CPT{i});
+end
+
+% Do backward phase
+max_over = max_over(length(max_over):-1:1); % reverse
+for i=max_over(1:end-1)        
+  % max-ing over variable i which occurs in bucket j
+  j = bucket_num(i, order);
+  rest = mysetdiff(domain_pot(B{j}), i);
+  %temp = marginalize_pot_max(B{j}, rest);
+  temp = marginalize_pot(B{j}, rest, 1);
+  b = bucket_num(domain_pot(temp), order);
+  %        fprintf('maxing over bucket %d (var %d), putting result into bucket %d\n', j, i, b);
+  sB=struct(B{b});  % violate object privacy
+  if ~isempty(sB.domain)
+    B{b} = multiply_pots(B{b}, temp);
+  else
+    B{b} = temp;
+  end
+end
+result = B{1};
+marginal = pot_to_marginal(result);
+[prob, mpe] = max(marginal.T);
+
+% handle impossible cases
+if ~(prob>0)
+  mpe = [];    
+  ll = -inf;
+  %warning('evidence has zero probability')
+  return
+end
+
+ll = log(prob);
+
+% Do forward phase    
+for ii=2:n
+  marginal = pot_to_marginal(B{ii});
+  mpeidx = [];
+  for jj=order(1:length(mpe))
+    assert(ismember(jj, marginal.domain)) %%% bug
+    temp = find_equiv_posns(jj, marginal.domain);
+    mpeidx = [mpeidx, temp] ;
+    if isempty(temp)
+      mpeidx = [mpeidx, Inf] ;
+    end
+  end
+  [mpeidxsorted sortedtompe] = sort(mpeidx) ;
+  
+  % maximize the matrix obtained from assigning values from previous buckets.
+  % this is done by building a string and using eval.
+  
+  kk=1;
+  sargs = '(';
+  for jj=1:length(marginal.domain)
+    if (jj~=1)
+      sargs = [sargs, ','];
+    end
+    if (mpeidxsorted(kk)==jj)
+      sargs = [sargs, num2str(mpe(sortedtompe(kk)))];
+      if (kk<length(mpe))
+	kk = kk+1 ;
+      end
+    else
+      sargs = [sargs, ':'];
+    end
+  end
+  sargs = [sargs, ')'] ;   
+  eval(['[val, loc] = max(marginal.T', sargs, ');'])        
+  mpe = [mpe loc];
+end     
+[I,J] = sort(order);
+mpe = mpe(J);
+
+
+
+%%%%%%%%%
+
+function b = bucket_num(domain, order)
+
+b = max(find_equiv_posns(domain, order));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/Old/calc_mpe_dbn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,41 @@
+function [mpe, ll] = calc_mpe_dbn(engine, evidence, break_ties)
+% CALC_MPE Computes the most probable explanation of the evidence
+% [mpe, ll] = calc_mpe_dbn(engine, evidence, break_ties)
+%
+% INPUT
+% engine must support max-propagation
+% evidence{i,t} is the observed value of node i in slice t, or [] if hidden
+%
+% OUTPUT
+% mpe{i,t} is the most likely value of node i (cell array!)
+% ll is the log-likelihood of the globally best assignment
+%
+% This currently only works when all hidden nodes are discrete
+
+if nargin < 3, break_ties = 0; end
+
+if break_ties
+  disp('warning: break ties is ignored')
+end
+
+[engine, ll] = enter_evidence(engine, evidence, 'maximize', 1);
+
+observed = ~isemptycell(evidence);
+[ss T] = size(evidence);
+scalar = 1;
+N = length(evidence);
+mpe = cell(ss,T);
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes;
+for t=1:T
+  for i=1:ss
+    m = marginal_nodes(engine, i, t);
+    % observed nodes are all set to 1 inside the inference engine, so we must undo this
+    if observed(i,t)
+      mpe{i,t} = evidence{i,t};
+    else
+      assert(length(m.T) == ns(i));
+      mpe{i,t} = argmax(m.T);
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/Old/calc_mpe_given_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function [mpe, prob] = calc_mpe_given_inf_engine(engine, evidence)
+% CALC_MPE_GIVEN_ENGINE Computes the most probable explanation of the evidence
+% [mpe, prob] = calc_mpe_given_inf_engine(engine, evidence)
+%
+% INPUT
+% engine must support max-propagation
+% evidence{i} is the obsevred value of node i, or [] if hidden
+%
+% OUTPUT
+% mpe(i) is the most likely value of node i
+% prob is the likelihood of the globally best assignment
+%
+% This currently only works when all nodes are discrete
+
+[engine, ll] = enter_evidence(engine, evidence);
+
+observed = ~isemptycell(evidence);
+N = length(evidence);
+mpe = zeros(1,N);
+for i=1:N
+  m = marginal_nodes(engine, i);
+  % discrete observed nodes are all set to 1 inside the inference engine, so we must undo this
+  if observed(i)
+    mpe(i) = evidence{i};
+  else
+    mpe(i) = argmax(m.T);
+  end
+end
+
+bnet = bnet_from_engine(engine);
+ll = log_lik_complete(bnet, num2cell(mpe(:)));
+prob = exp(ll);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/Old/calc_mpe_global.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function [mpe, ll] = calc_mpe_global(bnet, evidence)
+% CALC_MPE_GLOBAL Compute the most probable explanation(s) from the global joint
+% [mpe, ll] = calc_mpe_global(bnet, evidence)
+%
+% mpe(k,i) is the most probable value of node i in the k'th global mode 
+% ll is the log likelihood
+%
+% We assume all nodes are discrete
+
+engine = global_joint_inf_engine(bnet);
+engine = enter_evidence(engine, evidence);
+S1 = struct(engine); % violate object privacy
+S2 = struct(S1.jpot); % joint potential
+prob = max(S2.T(:));
+modes = find(S2.T(:) == prob);
+
+ens = bnet.node_sizes;
+onodes = find(~isemptycell(evidence));
+ens(onodes) = 1;
+mpe = ind2subv(ens, modes);
+for k=1:length(modes)
+  for i=onodes(:)'
+    mpe(k,i) = evidence{i};
+  end
+end
+ll = log(prob);
+
+mpe = num2cell(mpe);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/Old/compute_interface_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,31 @@
+function [int, persist, transient] = compute_interface_nodes(intra, inter)
+% COMPUTE_INTERFACE_NODES Find the nodes in a DBN that represent a sufficient statistic
+% [int, persist, transient] = compute_interface_nodes(intra, inter)
+%
+% The interface nodes are all those that has an incoming temporal arc,
+% or which have a child which has an incoming temporal arc,
+% where a temporal arc means one coming from the previous slice.
+% (The parents of nodes with incoming temporal arcs are needed
+% because moralization will bring them into the clique.)
+%
+% The persisent nodes are all those that have one or more incoming temporal arc.
+% The transient nodes are all the non-persistent.
+%
+% See U. Kjaerulff, "dHugin: A computational system for dynamic
+% time-sliced Bayesian networks", Intl. J. Forecasting (11) 89-111, 1995
+
+n = length(intra);
+int = [];
+persist = [];
+for u=1:n
+  if any(inter(:,u))
+    int = [int u];
+    persist = [persist u];
+  end
+  if any(inter(:, children(intra, u)))
+    int = [int u];
+  end
+end
+int = unique(int);
+persist = unique(persist);
+transient = mysetdiff(1:n, persist);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/Old/mk_gdl_graph.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,86 @@
+function gdl = mk_gdl_graph(G, domains, node_sizes, kernels, varargin)
+% MK_GDL_GRAPH Make a GDL (generalized distributed law) graph
+% gdl = mk_gdl_graph(G, domains, node_sizes, kernels, ...)
+%
+% A GDL graph is like a moralized, but untriangulated, Bayes net:
+% each "node" represents a domain with a corresponding kernel function.
+% For details, see "The Generalized Distributive Law", Aji and McEliece,
+% IEEE Trans. Info. Theory, 46(2): 325--343, 2000
+% 
+% G(i,j) = 1 if there is an (undirected) edge between domains i,j
+%
+% domains{i} is the domain of node i
+%
+% node_sizes(i) is the number of values node i can take on,
+%   or the length of node i if i is a continuous-valued vector.
+% node_sizes(i) = 1 if i is a utility node.
+%
+% kernels is the list of kernel functions
+%
+% The list below gives optional arguments [default value in brackets].
+% 
+% equiv_class - equiv_class(i)=j  means factor node i gets its params from factors{j} [1:F]
+% discrete - the list of nodes which are discrete random variables [1:N]
+% chance   - the list of nodes which are random variables [1:N]
+% decision - the list of nodes which are decision nodes [ [] ]
+% utility  - the list of nodes which are utility nodes [ [] ]
+
+
+ns = node_sizes;
+N = length(domains);
+vars = [];
+for i=1:N
+  vars = myunion(vars, domains{i});
+end
+Nvars  = length(vars);
+
+gdl.equiv_class = 1:length(kernels);
+gdl.chance_nodes = 1:Nvars;
+gdl.utility_nodes = [];
+gdl.decision_nodes = [];
+gdl.dnodes = 1:Nvars;
+
+if nargin >= 5
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'equiv_class', bnet.equiv_class = args{i+1}; 
+     case 'chance',      bnet.chance_nodes = args{i+1}; 
+     case 'utility',     bnet.utility_nodes = args{i+1}; 
+     case 'decision',    bnet.decision_nodes = args{i+1}; 
+     case 'discrete',    bnet.dnodes = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+
+gdl.G = G;
+gdl.vars = vars;
+gdl.doms = domains;
+gdl.node_sizes = node_sizes;
+gdl.cnodes = mysetdiff(vars, gdl.dnodes);
+gdl.kernels = kernels;
+gdl.type = 'gdl';
+
+% Compute a bit vector representation of the set of domains
+% dom_bitv(i,j) = 1 iff variable j occurs in domain i
+gdl.dom_bitv = zeros(N, length(vars));
+for i=1:N
+  gdl.dom_bitv(i, domains{i}) = 1;
+end
+
+% compute the interesection of the domains on either side of each edge (separating set)
+gdl.sepset = cell(N, N);
+gdl.nbrs = cell(1,N);
+for i=1:N
+  nbrs = neighbors(G, i);
+  gdl.nbrs{i} = nbrs;
+  for j = nbrs(:)'
+    gdl.sepset{i,j} = myintersect(domains{i}, domains{j});
+  end
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/add_ev_to_dmarginal.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function fmarginal = add_ev_to_dmarginal(fmarginal, evidence, ns)
+% ADD_EV_TO_DMARGINAL 'pump up' observed nodes back to their original size.
+% fmarginal = add_ev_to_dmarginal(fmarginal, evidence, ns)
+%
+% We introduce 0s into the array in positions which are incompatible with the evidence.
+
+dom = fmarginal.domain;
+odom = dom(~isemptycell(evidence(dom)));
+vals = cat(1, evidence{odom});
+index = mk_multi_index(length(dom), find_equiv_posns(odom, dom), vals);
+T = 0*myones(ns(dom));
+ens = ns(:)';
+ens(odom) = 1;
+T(index{:}) = myreshape(fmarginal.T, ens(dom));
+fmarginal.T = T;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/add_evidence_to_gmarginal.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,78 @@
+function fullm = add_evidence_to_gmarginal(fmarginal, evidence, ns, cnodes)
+% ADD_EVIDENCE_TO_GMARGINAL 'pump up' observed nodes back to their original size.
+% function fullm = add_evidence_to_gmarginal(fmarginal, evidence, ns, cnodes)
+%
+% We introduce 0s into the array in positions which are incompatible with the evidence.
+% for both discrete and continuous nodes.
+%
+% See also add_ev_to_dmarginal
+
+dom = fmarginal.domain;
+fullm.domain = fmarginal.domain;
+
+% Find out which values of the discrete parents (if any) are compatible with 
+% the discrete evidence (if any).
+dnodes = mysetdiff(1:length(ns), cnodes);
+ddom = myintersect(dom, dnodes);
+cdom = myintersect(dom, cnodes);
+odom = dom(~isemptycell(evidence(dom)));
+hdom = dom(isemptycell(evidence(dom)));
+
+% Find the entries in the big table that are compatible with the discrete evidence.
+% (We will put the probabilities from the small inferred table into these positions.)
+% We could use add_ev_to_dmarginal to do this.
+dobs = myintersect(ddom, odom);
+dvals = cat(1, evidence{dobs});
+ens = ns; % effective node sizes
+ens(dobs) = 1;
+S = prod(ens(ddom));
+subs = ind2subv(ens(ddom), 1:S);
+mask = find_equiv_posns(dobs, ddom);
+%subs(mask) = dvals; % bug fix by P. Brutti
+for i=1:length(mask),
+  subs(:,mask(i)) = dvals(i);
+end       
+supportedQs = subv2ind(ns(ddom), subs);
+
+if isempty(ddom)
+  Qarity = 1;
+else
+  Qarity = prod(ns(ddom));
+end
+fullm.T = zeros(Qarity, 1);
+fullm.T(supportedQs) = fmarginal.T(:);
+fullm.T = myreshape(fullm.T, ns(ddom));
+
+
+if isempty(cdom)
+  fullm.mu = [];
+  fullm.sigma = [];
+  return;
+end
+
+% Now put the hidden cts parts into their right blocks,
+% leaving the observed cts parts as 0.
+cobs = myintersect(cdom, odom);
+chid = myintersect(cdom, hdom);
+cvals = cat(1, evidence{cobs});
+n = sum(ns(cdom));
+fullm.mu = zeros(n,Qarity);
+fullm.Sigma = zeros(n,n,Qarity);
+
+if ~isempty(chid)
+  chid_blocks = block(find_equiv_posns(chid, cdom), ns(cdom));
+end
+if ~isempty(cobs)
+  cobs_blocks = block(find_equiv_posns(cobs, cdom), ns(cdom));
+end
+
+for i=1:length(supportedQs)
+  Q = supportedQs(i);
+  if ~isempty(chid)
+    fullm.mu(chid_blocks, Q) = fmarginal.mu(:, i);
+    fullm.Sigma(chid_blocks, chid_blocks, Q) = fmarginal.Sigma(:,:,i);
+  end
+  if ~isempty(cobs)
+    fullm.mu(cobs_blocks, Q) = cvals(:);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/bnet_to_fgraph.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function fg = bnet_to_fgraph(bnet)
+% BNET_TO_FGRAPH Convert a Bayes net to a factor graph
+% fg = bnet_to_fgraph(bnet)
+%
+% We create one factor per family, whose kernel is the CPD
+
+nnodes = length(bnet.dag);
+G = zeros(nnodes, nnodes);
+for i=1:nnodes
+  G(family(bnet.dag, i), i) = 1;
+end
+
+fg = mk_fgraph(G, bnet.node_sizes, bnet.CPD, 'equiv_class', bnet.equiv_class, 'discrete', bnet.dnodes);
+
+	       
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/compute_fwd_interface.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function int = compute_fwd_interface(intra, inter)
+% COMPUTE_FWD_INTERFACE Compute nodes with children in the next slice
+% function int = compute_fwd_interface(intra, inter)
+
+int = [];
+ss = length(intra);
+for u=1:ss
+  if any(inter(u,:))
+    int = [int u];
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/compute_interface_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,42 @@
+function [interface, persist, transient] = compute_interface_nodes(intra, inter)
+% COMPUTE_INTERFACE_NODES Find the nodes in a DBN that represent a sufficient statistic
+% [interface, persist, transient] = compute_interface_nodes(intra, inter)
+%
+% The interface nodes are all those that has an incoming temporal arc,
+% or which are parents of such nodes.
+% If the parents are in the previous slice, this just means they have an
+% outgoing temporal arc.
+% (The parents of nodes with incoming temporal arcs are needed
+% because moralization will bring them into the clique.)
+%
+% The persisent nodes are all those that have one or more incoming temporal arc.
+% The transient nodes are all the non-persistent.
+%
+% See U. Kjaerulff, "dHugin: A computational system for dynamic
+% time-sliced Bayesian networks", Intl. J. Forecasting (11) 89-111, 1995
+
+n = length(intra);
+interface = [];
+persist = [];
+% any nodes with incoming arcs
+for u=1:n
+  if any(inter(:,u))
+    interface = [interface u];
+    persist = [persist u];
+  end
+end
+% Any nodes which are parents of nodes with incoming arcs
+for u=1:n
+  cs = children(intra, u);
+  if any(inter(:, cs))
+    interface = [interface u];
+  end
+  %cs = children(inter, u);
+  % if ~isempty(myintersect(cs, persist))
+  %  interface = [interface u];
+  %end
+end
+interface = unique(interface);
+persist = unique(persist);
+transient = mysetdiff(1:n, persist);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/compute_joint_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function [jpot, loglik] = compute_joint_pot(bnet, nodes, evidence, domain)
+% COMPUTE_JOINT_POT Compute the global joint potential of a Bayes net
+% function jpot = compute_joint_pot(bnet, nodes, evidence, domain)
+
+if nargin < 4, domain = nodes; end
+
+onodes = find(~isemptycell(evidence));
+pot_type = determine_pot_type(bnet, onodes, domain);
+
+jpot = mk_initial_pot(pot_type, domain, bnet.node_sizes, bnet.cnodes, onodes);
+for i=nodes(:)'
+  e = bnet.equiv_class(i);
+  fam = family(bnet.dag, i);
+  pot = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence);
+  jpot = multiply_by_pot(jpot, pot);
+end                                                  
+%[jpot, loglik] = normalize_pot(jpot); % causes errors in asia_dt1 etc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/compute_minimal_interface.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function clqs = compute_minimal_interface(intra, inter)
+
+int = compute_fwd_interface(intra, inter);
+ss  = length(intra);
+Z = zeros(ss);
+dag = [intra inter;
+       Z     intra];
+G = moralize(dag);
+intra2 = G(1:ss,1:ss);
+inter2 = G(1:ss,(1:ss)+ss);
+G = unroll_dbn_topology(intra2, inter2, ss);
+T = ss;
+last_slice = (1:ss) + (T-1)*ss;
+G = (G + G')/2; % mk symmetric
+G2 = (expm(full(G)) > 0); % closure of graph
+G3 = G2(last_slice, last_slice);
+[c,v] = scc(G3); % connected components
+ncomp = size(v,1);
+clqs = cell(1,ncomp);
+for i=1:ncomp
+  ndx = find(v(i,:)>0);
+  clqs{i} = v(i,ndx);
+  clqs{i} = myintersect(clqs{i}, int);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/convert_dbn_CPDs_to_pots.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function CPDpot = convert_dbn_CPDs_to_pots(bnet, evidence, pot_type, softCPDpot)
+% CONVERT_DBN_CPDS_TO_POTS Convert CPDs of (possibly instantiated) DBN nodes to potentials
+% CPDpot = convert_dbn_CPDs_to_pots(bnet, evidence, pot_type, softCPDpot)
+%
+% CPDpot{n,t} is a potential containing P(n,t|pa(n,t), ev)
+% softCPDpot{n,t} is a potential containing P(n,t|pa(n,t), ev) insted of using n's CPD
+
+[ss T] = size(evidence);
+
+if nargin < 4, softCPDpot = cell(ss,T); end
+CPDpot = softCPDpot;
+
+% Convert CPDs of instantiated nodes to potential form
+t = 1;
+for n=1:ss
+  fam = family(bnet.dag, n);
+  e = bnet.equiv_class(n, 1);
+  if isempty(softCPDpot{n,t})
+    CPDpot{n,t} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence(:,1));
+  end
+end
+for n=1:ss
+  fam = family(bnet.dag, n, 2);
+  e = bnet.equiv_class(n, 2);
+  for t=2:T
+    if isempty(softCPDpot{n,t})
+      CPDpot{n,t} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence(:,t-1:t));
+    end
+  end       
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/convert_dbn_CPDs_to_tables.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,201 @@
+function CPDpot = convert_dbn_CPDs_to_tables(bnet, evidence)
+% CONVERT_DBN_CPDS_TO_TABLES Convert CPDs of (possibly instantiated) DBN nodes to tables
+% CPDpot = convert_dbn_CPDs_to_tables(bnet, evidence)
+%
+% CPDpot{n,t} is a table containing P(n,t|pa(n,t), ev)
+% All hidden nodes are assumed to be discrete.
+% We assume the observed nodes are the same in every slice.
+%
+% Evaluating the conditional likelihood of long evidence sequences can be very slow,
+% so we take pains to vectorize where possible.
+
+[ss T] = size(evidence);
+%obs_bitv = ~isemptycell(evidence(:));
+obs_bitv = zeros(1, 2*ss);
+obs_bitv(bnet.observed) = 1;
+obs_bitv(bnet.observed+ss) = 1;
+
+ns = bnet.node_sizes(:);
+CPDpot = cell(ss,T); 
+
+for n=1:ss
+  % slice 1
+  t = 1;
+  ps = parents(bnet.dag, n);
+  e = bnet.equiv_class(n, 1);
+  if ~any(obs_bitv(ps))
+    CPDpot{n,t} = convert_CPD_to_table_hidden_ps(bnet.CPD{e}, evidence{n,t});
+  else
+    CPDpot{n,t} = convert_to_table(bnet.CPD{e}, [ps n], evidence(:,1));
+  end
+
+% special cases: c=child, p=parents, d=discrete, h=hidden, 1sl=1slice
+% if c=h=1 then c=d=1, since hidden nodes must be discrete
+% c=h c=d p=h p=d 1sl method
+% ---------------------------
+% 1   1   1   1   -   replicate CPT
+% -   1   -   1   -   evaluate CPT on evidence *
+% 0   1   1   1   1   dhmm
+% 0   0   1   1   1   ghmm
+% other               loop
+%
+% * = any subset of the domain may be observed
+
+% Example where all of the special cases occur - a hierarchical HMM
+% where the top layer (G) and leaves (Y) are observed and
+% all nodes are discrete except Y.
+% (O turns on if Y is an outlier)
+
+% G ---------> G 
+% |            |
+% v            v
+% S  --------> S
+% |            |
+% v            v
+% Y            Y
+% ^            ^
+% |            |
+% O            O
+
+% Evaluating P(yt|St,Ot) is the ghmm case
+% Evaluating P(St|S(t-1),gt) is the eval CPT case
+% Evaluating P(gt|g(t-1) is the eval CPT case (hdom = [])
+% Evaluating P(Ot) is the replicated CPT case
+
+% Cts parents (e.g., inputs) would require an additional special case for speed
+
+
+  % slices 2..T
+  [ss T] = size(evidence);
+  self = n+ss;
+  ps = parents(bnet.dag, self);
+  e = bnet.equiv_class(n, 2);
+
+  if 1
+  debug = 0;
+  hidden_child = ~obs_bitv(n);
+  discrete_child = myismember(n, bnet.dnodes);
+  hidden_ps = all(~obs_bitv(ps));
+  discrete_ps = mysubset(ps, bnet.dnodes);
+  parents_in_same_slice = all(ps > ss);
+  
+  if hidden_child & discrete_child & hidden_ps & discrete_ps
+    CPDpot = helper_repl(bnet, evidence, n, CPDpot, obs_bitv, debug);
+  elseif discrete_child & discrete_ps
+    CPDpot = helper_eval(bnet, evidence, n, CPDpot, obs_bitv, debug);
+  elseif discrete_child & hidden_ps & discrete_ps & parents_in_same_slice
+    CPDpot = helper_dhmm(bnet, evidence, n, CPDpot, obs_bitv, debug);
+  elseif ~discrete_child & hidden_ps & discrete_ps & parents_in_same_slice
+    CPDpot = helper_ghmm(bnet, evidence, n, CPDpot, obs_bitv, debug);
+  else
+    if debug, fprintf('node %d, slow\n', n); end
+    for t=2:T
+      CPDpot{n,t} = convert_to_table(bnet.CPD{e}, [ps self], evidence(:,t-1:t));
+    end
+  end
+  end
+  
+  if 0
+  for t=2:T
+    CPDpot2{n,t} = convert_to_table(bnet.CPD{e}, [ps self], evidence(:,t-1:t));
+    if ~approxeq(CPDpot{n,t}, CPDpot2{n,t})
+      fprintf('CPDpot n=%d, t=%d\n',n,t);
+      keyboard
+    end
+  end
+  end
+
+  
+end
+
+
+
+
+%%%%%%%
+function CPDpot = helper_repl(bnet, evidence, n, CPDpot, obs_bitv, debug)
+
+[ss T] = size(evidence);
+if debug, fprintf('node %d, repl\n', n); end
+e = bnet.equiv_class(n, 2);
+CPT = convert_CPD_to_table_hidden_ps(bnet.CPD{e}, []);
+CPDpot(n,2:T) = num2cell(repmat(CPT, [1 1 T-1]), [1 2]);
+
+
+
+%%%%%%%
+function CPDpot = helper_eval(bnet, evidence, n, CPDpot, obs_bitv, debug)
+
+[ss T] = size(evidence);
+self = n+ss;
+ps = parents(bnet.dag, self);
+e = bnet.equiv_class(n, 2);
+ns = bnet.node_sizes(:);
+% Example: given CPT(p1, p2, p3, p4, c), where p1,p3 are observed
+% we create CPT([p2 p4 c], [p1 p3]).
+% We then convert all observed p1,p3 into indices ndx
+% and return CPT(:, ndx)
+CPT = CPD_to_CPT(bnet.CPD{e});
+domain = [ps self];
+% if dom is [3 7 8] and 3,8 are observed, odom_rel = [1 3], hdom_rel = 2,
+% odom = [3 8], hdom = 7
+odom_rel = find(obs_bitv(domain));
+hdom_rel = find(~obs_bitv(domain));
+odom = domain(odom_rel);
+hdom = domain(hdom_rel);
+if isempty(hdom)
+  CPT = CPT(:);
+else
+  CPT = permute(CPT, [hdom_rel odom_rel]);
+  CPT = reshape(CPT, prod(ns(hdom)), prod(ns(odom)));
+end
+parents_in_same_slice = all(ps > ss);
+if parents_in_same_slice
+  if debug, fprintf('node %d eval 1 slice\n', n); end
+  data = cell2num(evidence(odom-ss,2:T)); %data(i,t) = val of i'th obs parent at t+1
+else
+  if debug, fprintf('node %d eval 2 slice\n', n); end
+  % there's probably a way of vectorizing this...
+  data = zeros(length(odom), T-1);
+  for t=2:T
+    ev = evidence(:,t-1:t);
+    ev = ev(:);
+    ev2 = ev(odom);
+    data(:,t-1) = cat(1, ev2{:});
+    %data(:,t-1) = cell2num(ev2);
+  end
+end
+ndx = subv2ind(ns(odom), data'); % ndx(t) encodes data(:,t)
+if isempty(hdom)
+  CPDpot(n,2:T) = num2cell(CPT(ndx)); % a cell array of floats
+else
+  CPDpot(n,2:T) = num2cell(CPT(:, ndx), 1); % a cell array of column vectors
+end
+
+%%%%%%%
+function CPDpot = helper_dhmm(bnet, evidence, n, CPDpot, obs_bitv, debug)
+
+if debug, fprintf('node %d, dhmm\n', n); end
+[ss T] = size(evidence);
+self = n+ss;
+ps = parents(bnet.dag, self);
+e = bnet.equiv_class(n, 2);
+ns = bnet.node_sizes(:);
+CPT = CPD_to_CPT(bnet.CPD{e});
+CPT = reshape(CPT, [prod(ns(ps)) ns(self)]); % what if no parents?
+%obslik = mk_dhmm_obs_lik(cell2num(evidence(n,2:T)), CPT);
+obslik = eval_pdf_cond_multinomial(cell2num(evidence(n,2:T)), CPT);
+CPDpot(n,2:T) = num2cell(obslik, 1);
+
+
+%%%%%%%
+function CPDpot = helper_ghmm(bnet, evidence, n, CPDpot, obs_bitv, debug)
+
+if debug, fprintf('node %d, ghmm\n', n); end
+[ss T] = size(evidence);
+e = bnet.equiv_class(n, 2);
+S = struct(bnet.CPD{e}); 
+ev2 = cell2num(evidence(n,2:T));
+%obslik = mk_ghmm_obs_lik(ev2, S.mean, S.cov);
+obslik = eval_pdf_cond_gauss(ev2, S.mean, S.cov);
+CPDpot(n,2:T) = num2cell(obslik, 1);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/convert_dbn_CPDs_to_tables1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,162 @@
+function CPDpot = convert_dbn_CPDs_to_tables1(bnet, evidence)
+% CONVERT_DBN_CPDS_TO_TABLES Convert CPDs of (possibly instantiated) DBN nodes to tables
+% CPDpot = convert_dbn_CPDs_to_tables(bnet, evidence)
+%
+% CPDpot{n,t} is a table containing P(n,t|pa(n,t), ev)
+% All hidden nodes are assumed to be discrete
+% We assume the observed nodes are the same in every slice
+%
+% Evaluating the conditional likelihood of the evidence can be very slow,
+% so we take pains to vectorize where possible, i.e., we try to avoid
+% calling convert_to_table
+
+[ss T] = size(evidence);
+%obs_bitv = ~isemptycell(evidence(:));
+obs_bitv = zeros(1, 2*ss);
+obs_bitv(bnet.observed) = 1;
+obs_bitv(bnet.observed+ss) = 1;
+
+ns = bnet.node_sizes(:);
+CPDpot = cell(ss,T); 
+
+for n=1:ss
+  % slice 1
+  t = 1;
+  ps = parents(bnet.dag, n);
+  e = bnet.equiv_class(n, 1);
+  if ~any(obs_bitv(ps))
+    CPDpot{n,t} = convert_CPD_to_table_hidden_ps(bnet.CPD{e}, evidence{n,t});
+  else
+    CPDpot{n,t} = convert_to_table(bnet.CPD{e}, [ps n], evidence(:,1));
+  end
+  
+  % slices 2..T
+  debug = 1;
+  if ~obs_bitv(n)
+    CPDpot = helper_hidden_child(bnet, evidence, n, CPDpot, obs_bitv, debug);
+  else
+    CPDpot = helper_obs_child(bnet, evidence, n, CPDpot, obs_bitv, debug);
+  end
+end
+
+if 0
+CPDpot2 = convert_dbn_CPDs_to_tables_slow(bnet, evidence);
+for t=1:T
+  for n=1:ss
+    if ~approxeq(CPDpot{n,t}, CPDpot2{n,t})
+      fprintf('CPDpot n=%d, t=%d\n',n,t);
+      keyboard
+    end
+  end
+end
+end
+
+
+% special cases: c=child, p=parents, d=discrete, h=hidden, 1=1slice
+% if c=h=1 then c=d=1, since hidden nodes must be discrete
+% c=h c=d p=h p=d p=1 method
+% ---------------------------
+% 1   1   1   1   -   replicate CPT
+% 0   1   1   1   1   dhmm
+% 0   0   1   1   1   ghmm
+% -   1   -   1   -   evaluate CPT on evidence
+% other               loop
+
+%%%%%%%
+function CPDpot = helper_hidden_child(bnet, evidence, n, CPDpot, obs_bitv, debug)
+
+[ss T] = size(evidence);
+self = n+ss;
+ps = parents(bnet.dag, self);
+e = bnet.equiv_class(n, 2);
+ns = bnet.node_sizes(:);
+if ~any(obs_bitv(ps)) % all parents are hidden (hence discrete)
+  if debug, fprintf('node %d is hidden, all ps are hidden\n', n); end
+  if myismember(n, bnet.dnodes) 
+    %CPT = CPD_to_CPT(bnet.CPD{e});
+    %CPT = reshape(CPT, [prod(ns(ps)) ns(self)]);
+    CPT = convert_CPD_to_table_hidden_ps(bnet.CPD{e}, []);
+    CPDpot(n,2:T) = num2cell(repmat(CPT, [1 1 T-1]), [1 2]);
+  else
+    error(['hidden cts node disallowed'])
+  end
+else % some parents are observed - slow
+  if mysubset(ps, bnet.dnodes) % all parents are discrete
+    % given CPT(p1, p2, p3, p4, c), where p1,p3 are observed
+    % we create CPT([p2 p4 c], [p1 p3]).
+    % We then convert all observed p1,p3 into indices ndx
+    % and return CPT(:, ndx)
+    CPT = CPD_to_CPT(bnet.CPD{e});
+    domain = [ps self];
+    % if dom is [3 7 8] and 3,8 are observed, odom_rel = [1 3], hdom_rel = 2,
+    % odom = [3 8], hdom = 7
+    odom_rel = find(obs_bitv(domain));
+    hdom_rel = find(~obs_bitv(domain));
+    odom = domain(odom_rel);
+    hdom = domain(hdom_rel);
+    CPT = permute(CPT, [hdom_rel odom_rel]);
+    CPT = reshape(CPT, prod(ns(hdom)), prod(ns(odom)));
+    parents_in_same_slice = all(ps > ss);
+    if parents_in_same_slice
+      if debug, fprintf('node %d is hidden, some ps are obs, all ps discrete, 1 slice\n', n); end
+      data = cell2num(evidence(odom-ss,2:T)); %data(i,t) = val of i'th obs parent at t+1
+    else
+      if debug, fprintf('node %d is hidden, some ps are obs, all ps discrete, 2 slice\n', n); end
+      data = zeros(length(odom), T-1);
+      for t=2:T
+	ev = evidence(:,t-1:t);
+	data(:,t-1) = cell2num(ev(odom));
+      end
+    end
+    ndx = subv2ind(ns(odom), data'); % ndx(t) encodes data(:,t)
+    CPDpot(n,2:T) = num2cell(CPT(:, ndx), [1 2]);
+  else % some parents are cts - v slow
+    if debug, fprintf('node %d is hidden, some ps are obs, some ps cts\n', n); end
+    for t=2:T
+      CPDpot{n,t} = convert_to_table(bnet.CPD{e}, [ps self], evidence(:,t-1:t));
+    end
+  end
+end
+  
+%%%%%%%
+function CPDpot = helper_obs_child(bnet, evidence, n, CPDpot, obs_bitv, debug)
+
+[ss T] = size(evidence);
+self = n+ss;
+ps = parents(bnet.dag, self);
+e = bnet.equiv_class(n, 2);
+ns = bnet.node_sizes(:);
+if ~any(obs_bitv(ps)) % all parents are hidden
+  parents_in_same_slice = all(ps > ss);
+  if parents_in_same_slice
+    if debug, fprintf('node %d is obs, all ps are hidden, 1 slice\n', n); end
+    ps1 = ps - ss;
+    if myismember(n, bnet.dnodes) 
+      CPT = CPD_to_CPT(bnet.CPD{e});
+      CPT = reshape(CPT, [prod(ns(ps)) ns(self)]); % what if no parents?
+      obslik = eval_pdf_cond_multinomial(cell2num(evidence(n,2:T)), CPT);
+      CPDpot(n,2:T) = num2cell(obslik, 1);
+    else
+      S = struct(bnet.CPD{e}); 
+      obslik = eval_pdf_cond_gauss(cell2num(evidence(n,2:T)), S.mean, S.cov);
+      CPDpot(n,2:T) = num2cell(obslik, 1);
+    end
+  else % parents span 2 slices - slow
+    if debug, fprintf('node %d is obs, all ps are hidden , 2 slice\n', n); end
+    for t=2:T
+      CPDpot{n,t} = convert_to_table(bnet.CPD{e}, [ps self], evidence(:,t-1:t));
+    end
+  end
+else 
+  if isempty(ps) % observed root
+    if debug, fprintf('node %d is obs, no ps\n', n); end
+    CPT = CPD_to_CPT(bnet.CPD{e});
+    data = cell2num(evidence(n,2:T));
+    CPDpot(n,2:T) = CPT(data);
+  else  % some parents are observed  - slow
+    if debug, fprintf('node %d is obs, some ps are obs\n', n); end
+    for t=2:T
+      CPDpot{n,t} = convert_to_table(bnet.CPD{e}, [ps self], evidence(:,t-1:t));
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/convert_dbn_CPDs_to_tables_slow.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,41 @@
+function CPDpot = convert_dbn_CPDs_to_tables_slow(bnet, evidence)
+% CONVERT_DBN_CPDS_TO_TABLES_SLOW Convert CPDs of (possibly instantiated) DBN nodes to tables
+% CPDpot = convert_dbn_CPDs_to_tables_slow(bnet, evidence)
+%
+% CPDpot{n,t} is a table containing P(n,t|pa(n,t), ev)
+% All hidden nodes are assumed to be discrete
+%
+% Non-vectorized method; this is less efficient for long sequences of observed Gaussian
+% nodes, because of the (unnecessary) repeated matrix inversion.
+
+obs_bitv = ~isemptycell(evidence(:));
+[ss T] = size(evidence);
+ns = bnet.node_sizes(:);
+
+CPDpot = cell(ss,T); 
+
+t = 1;
+for n=1:ss
+  %ps = engine.bnet_parents{n};
+  ps = parents(bnet.dag, n);
+  e = bnet.equiv_class(n, 1);
+  if ~any(obs_bitv(ps))
+    CPDpot{n,t} = convert_CPD_to_table_hidden_ps(bnet.CPD{e}, evidence{n,t});
+  else
+    CPDpot{n,t} = convert_to_table(bnet.CPD{e}, [ps n], evidence(:,1));
+  end
+end
+for t=2:T
+  for n=1:ss
+    self = n+ss;
+    ps = parents(bnet.dag, self);
+    e = bnet.equiv_class(n, 2);
+    if ~any(obs_bitv(ps))
+      CPDpot{n,t} = convert_CPD_to_table_hidden_ps(bnet.CPD{e}, evidence{n,t});
+    else
+      CPDpot{n,t} = convert_to_table(bnet.CPD{e}, [ps self], evidence(:,t-1:t));
+    end
+  end
+end       
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/dbn_to_bnet.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function bnet = dbn_to_bnet(dbn, T)
+% DBN_TO_BNET Convert a DBN to a static network by unroll for T slices
+% bnet = dbn_to_bnet(dbn, T)
+
+ss = length(dbn.intra);
+eclass = [dbn.equiv_class(:,1) repmat(dbn.equiv_class(:,2), 1, T-1)];
+dnodes = unroll_set(dbn.dnodes_slice, ss, T);
+ns = repmat(dbn.node_sizes_slice(:), 1, T);
+dag = unroll_dbn_topology(dbn.intra, dbn.inter, T, dbn.intra1);
+onodes = unroll_set(dbn.observed(:), ss, T);
+bnet = mk_bnet(dag, ns(:), 'discrete', dnodes(:), 'equiv_class', eclass(:), 'observed', onodes(:));
+bnet.CPD = dbn.CPD;
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/dbn_to_hmm.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,81 @@
+function [startprob, transprob, obsprob] = dbn_to_hmm(bnet)
+% DBN_TO_HMM % Convert DBN params to HMM params
+% [startprob, transprob, obsprob] = dbn_to_hmm(bnet, onodes)
+% startprob(i)
+% transprob(i,j)
+% obsprob{k}.big_CPT(i,o) if k'th observed node is discrete
+% obsprob{k}.big_mu(:,i), .big_Sigma(:,:,i) if k'th observed node is Gaussian
+% Big means the domain contains all the hidden discrete nodes, not just the parents.
+
+% Called by constructor and by update_engine
+
+ss = length(bnet.intra);
+onodes = bnet.observed;
+hnodes = mysetdiff(1:ss, onodes);
+evidence = cell(ss, 2);
+ns = bnet.node_sizes(:);
+Qh = prod(ns(hnodes));
+tmp = dpot_to_table(compute_joint_pot(bnet, hnodes, evidence));
+startprob = reshape(tmp, Qh, 1);
+
+tmp = dpot_to_table(compute_joint_pot(bnet, hnodes+ss, evidence, [hnodes hnodes+ss]));
+transprob = mk_stochastic(reshape(tmp, Qh, Qh));
+
+% P(o|ps) is used by mk_hmm_obs_lik_vec for a single time slice
+% P(o|h) (the big version), where h = all hidden nodes, is used by enter_evidence
+
+obsprob = cell(1, length(onodes));
+for i=1:length(onodes)
+  o = onodes(i);
+  if bnet.auto_regressive(o)
+    % We assume the parents of this node are all the hidden nodes in the slice,
+    % so the params already are "big". Also, we assume we regress only on our old selves.
+    % slice 1
+    e = bnet.equiv_class(o);
+    CPD = struct(bnet.CPD{e});
+    O = ns(o);
+    ps = bnet.parents{o};
+    Qps = prod(ns(ps));
+    obsprob{i}.big_mu0 = reshape(CPD.mean, [O Qps]);
+    obsprob{i}.big_Sigma0 = reshape(CPD.cov, [O O Qps]);
+
+    % slice t>1
+    e = bnet.equiv_class(o+ss);
+    CPD = struct(bnet.CPD{e});
+    O = ns(o);
+    dps = mysetdiff(bnet.parents{o+ss}, o);
+    Qdps = prod(ns(dps));
+    obsprob{i}.big_mu = reshape(CPD.mean, [O Qdps]);
+    obsprob{i}.big_Sigma = reshape(CPD.cov, [O O Qdps]);
+    obsprob{i}.big_W = reshape(CPD.weights, [O O Qdps]);
+  else
+    e = bnet.equiv_class(o+ss);
+    CPD = struct(bnet.CPD{e});
+    O = ns(o);
+    ps = bnet.parents{o};
+    Qps = prod(ns(ps));
+    % We make a big potential, replicating the params if necessary
+    % e.g., for a 2 chain coupled HMM, mu(:,Q1) becomes mu(:,Q1,Q2)
+    bigpot = pot_to_marginal(compute_joint_pot(bnet, onodes(i), evidence, [hnodes onodes(i)]));
+
+    if myismember(o, bnet.dnodes)
+      obsprob{i}.CPT = reshape(CPD.CPT, [Qps O]);
+      obsprob{i}.big_CPT = reshape(bigpot.T, Qh, O); 
+    else
+      obsprob{i}.big_mu = bigpot.mu;
+      obsprob{i}.big_Sigma = bigpot.Sigma;
+      
+      if 1
+      obsprob{i}.mu = reshape(CPD.mean, [O Qps]);
+      C = reshape(CPD.cov, [O O Qps]);
+      obsprob{i}.Sigma = C;
+      d = size(obsprob{i}.mu, 1);
+      for j=1:Qps
+	obsprob{i}.inv_Sigma(:,:,j) = inv(C(:,:,j));
+	obsprob{i}.denom(j) = (2*pi)^(d/2)*sqrt(abs(det(C(:,:,j))));
+      end
+      end
+      
+    end % if discrete
+  end % if ar
+end % for
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/determine_elim_constraints.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,43 @@
+function partial_order = determine_elim_constraints(bnet, onodes)
+% DETERMINE_ELIM_CONSTRAINTS Determine what the constraints are (if any) on the elimination ordering.
+% partial_order = determine_elim_constraints(bnet, onodes)
+%
+% A graph with different kinds of nodes (e.g., discrete and cts, or decision and rnd) is called marked. 
+% A strong root is guaranteed to exist if the marked graph is triangulated and does not have any paths of
+% the form discrete -> cts -> discrete. In general we need to add extra edges to
+% the moral graph to ensure this (see example in Lauritzen (1992) fig 3b).
+% However, a simpler sufficient condition is to eliminate all the cts nodes before the discrete ones,
+% because then, as we move from the leaves to the root, the cts nodes get marginalized away
+% and we are left with purely discrete cliques.
+%
+% partial_order(i,j)=1 if we must marginalize j *before* i
+% (so i will be nearer the strong root).
+% If the hidden nodes are either all discrete or all cts, we set partial_order = [].
+%
+% For details, see
+% - Jensen, Jensen and Dittmer, "From influence diagrams to junction trees", UAI 94.
+% - Lauritzen, "Propgation of probabilities, means, and variances in mixed graphical
+%   association models", JASA 87(420):1098--1108, 1992.
+% - K. Olesen, "Causal probabilistic networks with both discrete and continuous variables",
+%      IEEE Pami 15(3), 1993
+
+
+n = length(bnet.dag);
+pot_type = determine_pot_type(bnet, onodes);
+if (pot_type == 'd') | (pot_type == 'g')
+  partial_order = [];
+  return;
+end
+
+
+partial_order = sparse(n,n);
+partial_order(bnet.dnodes, bnet.cnodes) = 1;
+
+% Integrate out cts nodes before their discrete parents - see Olesen (1993) p9
+% This method gives the wrong results on cg1.m!
+if 0
+for i=bnet.cnodes(:)'
+  dps = myintersect(parents(bnet.dag, i), bnet.dnodes);
+  partial_order(dps, i)=1;
+end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/dispcpt.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function display_CPT(CPT)
+
+n = ndims(CPT);
+parents_size = size(CPT);
+parents_size = parents_size(1:end-1);
+child_size = size(CPT,n);
+c = 1;
+for i=1:prod(parents_size)
+  parent_inst = ind2subv(parents_size, i);
+  fprintf(1, '%d ', parent_inst);
+  fprintf(1, ': ');
+  index = num2cell([parent_inst 1]);
+  index{n} = ':';
+  fprintf(1, '%6.4f ', CPT(index{:}));
+  fprintf(1, '\n');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/do_intervention.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function bnet = mutilate_bnet(bnet, nodes, vals)
+% MUTILATE_BNET Clamp nodes to specific values (perform a surgical intervention)
+% bnet = mutilate_bnet(bnet, nodes, vals)
+%
+% We make all the clamped nodes roots.
+
+ns = bnet.node_sizes;
+for i=1:length(nodes)
+  X = nodes(i);
+  x = vals(i);
+  bnet.dag(:,X) = 0;
+  bnet.CPD{X} = root_CPD(bnet, X, x);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/dsep.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function sep = dsep(X, Y, S, G)
+% DSEP Is X indep Y given S wrt DAG G?
+% sep = dsep(X, Y, S, G)
+%
+% Instead of using the Bayes-Ball criterion, we see if S separates X and Y
+% in the moralized ancestral graph.
+
+conn = reachability_graph(G);
+M = myunion(myunion(X, Y), S);
+[A,junk] = find(conn(:, M));
+A = unique(A);
+A = myunion(A, M);
+GM = moralize(G(A,A));
+%sep = graph_separated(GM, X, Y, S);
+sep = graph_separated(GM, find_equiv_posns(X,A), find_equiv_posns(Y,A), find_equiv_posns(S,A));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/dsep_test.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+
+% Cowell et al p72
+G = zeros(10);
+G(1,2)=1;
+G(2,3)=1;
+G(3,7)=1;
+G(4,[5 8])=1;
+G(5,6)=1;
+G(6,7)=1;
+G(7,[9 10])=1;
+G(8,9)=1;
+
+dsep(1, 4, [5 7], G)
+dsep(1, 4, [7], G)
+dsep(1, 4, [10 5], G)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/enumerate_scenarios.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function [scenarios, log_probs] = enumerate_scenarios(bnet, evidence)
+% ENUMERATE_SCENARIOS Enumerate all assignments, and return the prob. of the non-zeros ones
+% function [scenarios, log_probs] = enumerate_scenarios(bnet, evidence)
+
+assert(isempty(bnet.cnodes));
+n = length(bnet.dag);
+observed = ~isemptycell(evidence);
+vals = cat(1,evidence{observed});
+vals = vals(:)';
+ns = bnet.node_sizes;
+
+log_probs = [];
+scenarios = [];
+for i=1:prod(ns)
+  inst = ind2subv(ns, i); % i'th instantiation
+  if isempty(vals) | inst(observed) == vals % agrees with evidence
+    ll = log_lik_complete(bnet, num2cell(inst(:)));
+    log_probs = [log_probs ll];
+    scenarios = [scenarios(:)' inst];
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/fgraph_to_bnet.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function bnet = fgraph_to_bnet(fg)
+% FGRAPH_TO_BNET Convert a factor graph to a Bayes net
+% bnet = fgraph_to_bnet(fg)
+%
+% We assume all factors are tabular_CPD.
+% We create 1 dummy observed node for every factor.
+
+N = fg.nvars + fg.nfactors;
+vnodes = 1:fg.nvars;
+fnodes = fg.nvars+1:N;
+dag = zeros(N);
+for x=1:fg.nvars
+  dag(x, fnodes(fg.dep{x})) = 1;
+end
+ns = [fg.node_sizes ones(1, fg.nfactors)];
+discrete = [fg.dnodes fnodes];
+bnet = mk_bnet(dag, ns, 'discrete', discrete);
+for x=1:fg.nvars
+  bnet.CPD{x} = tabular_CPD(bnet, x, 'CPT', 'unif');
+end
+ev = cell(1, fg.nvars); % no evidence
+for i=1:fg.nfactors
+  f = fnodes(i);
+  e = fg.equiv_class(i);
+  pot = convert_to_pot(fg.factors{e}, 'd', fg.dom{i}, ev);
+  m = pot_to_marginal(pot);
+  bnet.CPD{f} = tabular_CPD(bnet, f, 'CPT', m.T);
+end
+  
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/hodbn_to_bnet.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function bnet = hodbn_to_bnet(dbn, T)
+% DBN_TO_BNET Convert a DBN to a static network by unroll for T slices
+% bnet = dbn_to_bnet(dbn, T)
+ss = length(dbn.intra);
+[row,order] = size(dbn.equiv_class);
+eclass = [];
+for i = 1:min(order,T)
+     eclass = [eclass ; dbn.equiv_class(:,i)];
+end
+if T > order
+    eclass = [eclass ; repmat(dbn.equiv_class(:,order),T-order,1)]; 
+end
+
+dnodes = unroll_set(dbn.dnodes_slice, ss, T);
+ns = repmat(dbn.node_sizes_slice(:), 1, T);
+dag = unroll_higher_order_topology(dbn.intra, dbn.inter, T, dbn.intra1);
+onodes = unroll_set(dbn.observed(:), ss, T);
+bnet = mk_bnet(dag, ns(:), 'discrete', dnodes(:), 'equiv_class', eclass(:), 'observed', onodes(:));
+bnet.CPD = dbn.CPD;
+ 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/is_mnet.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+function m = is_mnet(model)
+
+m = isfield(model, 'markov_net');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/linear_gaussian_to_cpot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,43 @@
+function pot = linear_gaussian_to_cpot(mu, Sigma, W, domain, ns, cnodes, evidence)
+% LINEAR_GAUSSIAN_TO_CPOT Convert a linear Gaussian CPD  to a canonical potential.
+% pot = linear_gaussian_to_cpot(mu, Sigma, W, domain, ns, cnodes, evidence)
+%
+% We include any cts evidence, but ignore any discrete evidence.
+% (Use gaussian_CPD_params_given_dps to use discrete evidence to select mu, Sigma, W.)
+
+odom = domain(~isemptycell(evidence(domain)));
+hdom = domain(isemptycell(evidence(domain)));
+cobs = myintersect(cnodes, odom);
+chid = myintersect(cnodes, hdom);
+cvals = cat(1, evidence{cobs});
+
+%[g,h,K] = gaussian_to_canonical(mu, Sigma, W);
+Sinv = inv(Sigma);
+g = -0.5*mu'*Sinv*mu + log(normal_coef(Sigma));
+if isempty(W) | (size(W,2)==0)  % no cts parents
+  h = Sinv*mu;
+  K = Sinv;
+else
+  h = [-W'*Sinv*mu; Sinv*mu];
+  K = [W'*Sinv*W  -W'*Sinv';
+       -Sinv*W     Sinv]; 
+end
+
+if ~isempty(cvals)
+  %[g, h, K] = enter_evidence_canonical(g, h, K, chid, cobs, cvals(:), ns);  
+  [hx, hy, KXX, KXY, KYX, KYY] = partition_matrix_vec(h, K, chid, cobs, ns);
+  y = cvals(:);
+  g = g + hy'*y - 0.5*y'*KYY*y;
+  if length(hx)==0 % isempty(X) % i.e., we have instantiated everything away
+    h = [];
+    K = [];
+  else
+    h = hx - KXY*y;
+    K = KXX;
+  end
+end
+
+ns(odom) = 0;
+pot = cpot(domain, ns(domain), g, h, K);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/log_lik_complete.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function L = log_lik_complete(bnet, cases, clamped)
+% LOG_LIK_COMPLETE Compute sum_m sum_i log P(x(i,m)| x(pi_i,m), theta_i) for a completely observed data set
+% L = log_lik_complete(bnet, cases, clamped)
+%
+% If there is a missing data, you must use an inference engine.
+% cases(i,m) is the value assigned to node i in case m.
+% (If there are vector-valued nodes, cases should be a cell array.)
+% clamped(i,m) = 1 if node i was set by intervention in case m (default: clamped = zeros)
+% Clamped nodes contribute a factor of 1.0 to the likelihood.
+
+if iscell(cases), usecell = 1; else usecell = 0; end
+
+n = length(bnet.dag);
+ncases = size(cases, 2);
+if n ~= size(cases, 1)
+  error('data should be of size nnodes * ncases');
+end
+
+if nargin < 3, clamped = zeros(n,ncases); end
+
+L = 0;
+for i=1:n
+  ps = parents(bnet.dag, i);
+  e = bnet.equiv_class(i);
+  u = find(clamped(i,:)==0);
+  ll = log_prob_node(bnet.CPD{e}, cases(i,u), cases(ps,u));
+  if approxeq(exp(ll), 0),  fprintf('node %d has very low likelihood\n'); end
+  L = L + ll;
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/log_marg_lik_complete.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+function L = log_marg_lik_complete(bnet, cases, clamped)
+% LOG_MARG_LIK_COMPLETE Compute sum_m sum_i log P(x(i,m)| x(pi_i,m)) for a completely observed data set
+% L = log_marg_lik_complete(bnet, cases, clamped)
+%
+% This differs from log_lik_complete because we integrate out the parameters.   
+% If there is a missing data, you must use an inference engine.
+% cases(i,m) is the value assigned to node i in case m.
+% (If there are vector-valued nodes, cases should be a cell array.)
+% clamped(i,m) = 1 if node i was set by intervention in case m (default: clamped = zeros)
+% Clamped nodes contribute a factor of 1.0 to the likelihood.
+%
+% If there is a single case, clamped is a list of the clamped nodes, not a bit vector.
+
+if iscell(cases), usecell = 1; else usecell = 0; end
+
+n = length(bnet.dag);
+ncases = size(cases, 2);
+if n ~= size(cases, 1)
+  error('data should be of size nnodes * ncases');
+end
+
+if ncases == 1
+  if nargin < 3, clamped = []; end
+  clamp_set = clamped;
+  clamped = zeros(n,1);
+  clamped(clamp_set) = 1;
+else
+  if nargin < 3, clamped = zeros(n,ncases); end
+end
+
+L = 0;
+for i=1:n
+  ps = parents(bnet.dag, i);
+  e = bnet.equiv_class(i);
+  u = find(clamped(i,:)==0);
+  L = L + log_marg_prob_node(bnet.CPD{e}, cases(i,u), cases(ps,u));
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/mk_bnet.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,93 @@
+function bnet = mk_bnet(dag, node_sizes, varargin)
+% MK_BNET Make a Bayesian network.
+%
+% BNET = MK_BNET(DAG, NODE_SIZES, ...) makes a graphical model with an arc from i to j iff DAG(i,j) = 1.
+% Thus DAG is the adjacency matrix for a directed acyclic graph.
+% The nodes are assumed to be in topological order. Use TOPOLOGICAL_SORT if necessary.
+%
+% node_sizes(i) is the number of values node i can take on,
+%   or the length of node i if i is a continuous-valued vector.
+% node_sizes(i) = 1 if i is a utility node.
+% 
+% Below are the names of optional arguments [and their default value in brackets].
+% Pass as 'PropertyName1', PropertyValue1, 'PropertyName2', PropertyValue2, ...
+% 
+% discrete - the list of nodes which are discrete random variables [1:N]
+% equiv_class - equiv_class(i)=j  means node i gets its params from CPD{j} [1:N]
+% observed - the list of nodes which will definitely be observed in every case [ [] ]
+% 'names' - a cell array of strings to be associated with nodes 1:n [{}]
+%    This creates an associative array, so you write e.g.
+%     'evidence(bnet.names{'bar'}) = 42' instead of  'evidence(2} = 42' 
+%     assuming names = { 'foo', 'bar', ...}.
+%
+% e.g., bnet = mk_bnet(dag, ns, 'discrete', [1 3])
+%
+% For backwards compatibility with BNT2, you can also specify the parameters in the following order
+%   bnet = mk_bnet(dag, node_sizes, discrete_nodes, equiv_class)
+
+n = length(dag);
+
+% default values for parameters
+bnet.equiv_class = 1:n;
+bnet.dnodes = 1:n; % discrete 
+bnet.observed = [];
+bnet.names = {};
+
+if nargin >= 3
+  args = varargin;
+  nargs = length(args);
+  if ~isstr(args{1})
+    if nargs >= 1, bnet.dnodes = args{1}; end
+    if nargs >= 2, bnet.equiv_class = args{2}; end
+  else    
+    for i=1:2:nargs
+      switch args{i},
+       case 'equiv_class', bnet.equiv_class = args{i+1}; 
+       case 'discrete',    bnet.dnodes = args{i+1}; 
+       case 'observed',    bnet.observed = args{i+1}; 
+       case 'names',  bnet.names = assocarray(args{i+1}, num2cell(1:n)); 
+       otherwise,  
+	error(['invalid argument name ' args{i}]);       
+      end
+    end
+  end
+end
+
+bnet.observed = sort(bnet.observed); % for comparing sets
+bnet.hidden = mysetdiff(1:n, bnet.observed(:)');
+bnet.hidden_bitv = zeros(1,n);
+bnet.hidden_bitv(bnet.hidden) = 1;
+bnet.dag = dag;
+bnet.node_sizes = node_sizes(:)';
+
+bnet.cnodes = mysetdiff(1:n, bnet.dnodes);
+% too many functions refer to cnodes to rename it to cts_nodes - 
+% We hope it won't be confused with chance nodes!
+
+bnet.parents = cell(1,n);
+for i=1:n
+  bnet.parents{i} = parents(dag, i);
+end
+
+E = max(bnet.equiv_class);
+mem = cell(1,E);
+for i=1:n
+  e = bnet.equiv_class(i);
+  mem{e} = [mem{e} i];
+end
+bnet.members_of_equiv_class = mem;
+
+bnet.CPD = cell(1, E);
+
+bnet.rep_of_eclass = zeros(1,E);
+for e=1:E
+  mems = bnet.members_of_equiv_class{e};
+  bnet.rep_of_eclass(e) = mems(1);
+end
+
+directed = 1;
+if ~acyclic(dag,directed)
+  error('graph must be acyclic')
+end
+
+bnet.order = topological_sort(bnet.dag);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/mk_dbn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,133 @@
+function bnet = mk_dbn(intra, inter, node_sizes, varargin)
+% MK_DBN Make a Dynamic Bayesian Network.
+%
+% BNET = MK_DBN(INTRA, INTER, NODE_SIZES, ...) makes a DBN with arcs
+% from i in slice t to j in slice t iff intra(i,j) = 1, and 
+% from i in slice t to j in slice t+1 iff inter(i,j) = 1,
+% for i,j in {1, 2, ..., n}, where n = num. nodes per slice, and t >= 1.
+% node_sizes(i) is the number of values node i can take on.
+% The nodes are assumed to be in topological order. Use TOPOLOGICAL_SORT if necessary.
+% See also mk_bnet.
+%
+% Optional arguments [default in brackets]
+% 'discrete' - list of discrete nodes [1:n]
+% 'observed' - the list of nodes which will definitely be observed in every slice of every case [ [] ]
+% 'eclass1' - equiv class for slice 1 [1:n]
+% 'eclass2' - equiv class for slice 2 [tie nodes with equivalent parents to slice 1]
+%    equiv_class1(i) = j means node i in slice 1 gets its parameters from bnet.CPD{j},
+%    i.e., nodes i and j have tied parameters.
+% 'intra1' - topology of first slice, if different from others
+% 'names' - a cell array of strings to be associated with nodes 1:n [{}]
+%    This creates an associative array, so you write e.g.
+%     'evidence(bnet.names{'bar'}) = 42' instead of  'evidence(2} = 42' 
+%     assuming names = { 'foo', 'bar', ...}.
+%    
+% For backwards compatibility with BNT2, arguments can also be specified as follows
+%   bnet = mk_dbn(intra, inter, node_sizes, dnodes, eclass1, eclass2, intra1)
+%
+% After calling this function, you must specify the parameters (conditional probability
+% distributions) using bnet.CPD{i} = gaussian_CPD(...) or tabular_CPD(...) etc.
+
+
+n = length(intra);
+ss = n;
+bnet.nnodes_per_slice = ss;
+bnet.intra = intra;
+bnet.inter = inter;
+bnet.intra1 = intra;
+dag = zeros(2*n);
+dag(1:n,1:n) = bnet.intra1;
+dag(1:n,(1:n)+n) = bnet.inter;
+dag((1:n)+n,(1:n)+n) = bnet.intra;
+bnet.dag = dag;
+bnet.names = {};
+
+directed = 1;
+if ~acyclic(dag,directed)
+  error('graph must be acyclic')
+end
+
+
+bnet.eclass1 = 1:n;
+%bnet.eclass2 = (1:n)+n;
+bnet.eclass2 = bnet.eclass1;
+for i=1:ss
+  if isequal(parents(dag, i+ss), parents(dag, i)+ss)
+    %fprintf('%d has isomorphic parents, eclass %d\n', i, bnet.eclass2(i))
+  else
+    bnet.eclass2(i) = max(bnet.eclass2) + 1;
+    %fprintf('%d has non isomorphic parents, eclass %d\n', i, bnet.eclass2(i))
+  end
+end
+
+dnodes = 1:n;
+bnet.observed = [];
+
+if nargin >= 4
+  args = varargin;
+  nargs = length(args);
+  if ~isstr(args{1})
+    if nargs >= 1, dnodes = args{1}; end
+    if nargs >= 2, bnet.eclass1 = args{2}; end
+    if nargs >= 3, bnet.eclass2 = args{3}; end
+    if nargs >= 4, bnet.intra1 = args{4}; end
+  else
+    for i=1:2:nargs
+      switch args{i},
+       case 'discrete', dnodes = args{i+1}; 
+       case 'observed', bnet.observed = args{i+1}; 
+       case 'eclass1',  bnet.eclass1 = args{i+1}; 
+       case 'eclass2',  bnet.eclass2 = args{i+1}; 
+       case 'intra1',  bnet.intra1 = args{i+1}; 
+       %case 'ar_hmm',  bnet.ar_hmm = args{i+1};  % should check topology
+       case 'names',  bnet.names = assocarray(args{i+1}, num2cell(1:n)); 
+       otherwise,  
+	error(['invalid argument name ' args{i}]);       
+      end
+    end
+  end
+end
+
+
+bnet.observed = sort(bnet.observed); % for comparing sets
+ns = node_sizes;
+bnet.node_sizes_slice = ns(:)';
+bnet.node_sizes = [ns(:) ns(:)];
+
+cnodes = mysetdiff(1:n, dnodes);
+bnet.dnodes_slice = dnodes;
+bnet.cnodes_slice = cnodes;
+bnet.dnodes = [dnodes dnodes+n];
+bnet.cnodes = [cnodes cnodes+n];
+
+bnet.equiv_class = [bnet.eclass1(:) bnet.eclass2(:)];
+bnet.CPD = cell(1,max(bnet.equiv_class(:)));
+eclass = bnet.equiv_class(:);
+E = max(eclass);
+bnet.rep_of_eclass = zeros(1,E);
+for e=1:E
+  mems = find(eclass==e);
+  bnet.rep_of_eclass(e) = mems(1);
+end
+
+ss = n;
+onodes = bnet.observed;
+hnodes = mysetdiff(1:ss, onodes);
+bnet.hidden_bitv = zeros(1,2*ss);
+bnet.hidden_bitv(hnodes) = 1;
+bnet.hidden_bitv(hnodes+ss) = 1;
+
+bnet.parents = cell(1, 2*ss);
+for i=1:ss
+  bnet.parents{i} = parents(bnet.dag, i);
+  bnet.parents{i+ss} = parents(bnet.dag, i+ss);
+end
+
+bnet.auto_regressive = zeros(1,ss);
+% ar(i)=1 means (observed) node i depends on i in the  previous slice
+for o=bnet.observed(:)'
+  if any(bnet.parents{o+ss} <= ss)
+    bnet.auto_regressive(o) = 1;
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/mk_fgraph.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,60 @@
+function fg = mk_fgraph(G, node_sizes, factors, varargin)
+% MK_FGRAPH Make a factor graph
+% fg = mk_fgraph(G, node_sizes, factors, ...)
+%
+% A factor graph is a bipartite graph, with one side containing variables,
+% and the other containing functions of (subsets of) these variables.
+% For details, see "Factor Graphs and the Sum-Product Algorithm",
+%  F. Kschischang and B. Frey and H-A. Loeliger,
+%  IEEE Trans. Info. Theory, 2001
+%
+% G(i,j) = 1 if there is an arc from variable i to factor j
+%
+% node_sizes(i) is the number of values node i can take on,
+%   or the length of node i if i is a continuous-valued vector.
+%
+% 'factors' is the list of factors (kernel functions)
+%
+% The list below gives optional arguments [default value in brackets].
+% 
+% equiv_class - equiv_class(i)=j  means factor node i gets its params from factors{j} [1:F]
+% discrete - the list of nodes which are discrete random variables [1:N]
+%
+% e.g., fg = mk_fgraph(G, [2 2], {bnet.CPD{1},bnet.CPD{2}}, 'discrete', [1 2])
+
+fg.G = G;
+fg.node_sizes = node_sizes;
+fg.factors = factors;
+[fg.nvars fg.nfactors] = size(G);
+
+% default values for parameters
+fg.equiv_class = 1:fg.nfactors;
+fg.dnodes = 1:fg.nvars;
+
+if nargin >= 4
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'equiv_class', fg.equiv_class = args{i+1}; 
+     case 'discrete',    fg.dnodes = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+% so that determine_pot_type will work...
+fg.utility_nodes = [];
+%fg.decision_nodes = [];
+%fg.chance_nodes = fg.nvars;
+
+fg.dom = cell(1, fg.nfactors);
+for f=1:fg.nfactors
+  fg.dom{f} = find(G(:,f));
+end
+fg.dep = cell(1, fg.nvars);
+for x=1:fg.nvars
+  fg.dep{x} = find(G(x,:));
+end
+fg.cnodes = mysetdiff(1:fg.nvars, fg.dnodes);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/mk_fgraph_given_ev.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,48 @@
+function fg = mk_fgraph_given_ev(G, node_sizes, factors, ev_CPD, evidence, varargin)
+% MK_FGRAPH_GIVEN_EV Make a factor graph where each node has its own private evidence term
+% fg = mk_fgraph(G, node_sizes, factors, ev_CPD, evidence, ...)
+%
+% G, node_sizes and factors are as in mk_fgraph, but they refer to the hidden nodes.
+% ev_CPD{i} is a CPD for the i'th hidden node; this will be converted into a factor
+% for node i using evidence{i}.
+% We currently assume all hidden nodes are discrete, for simplicity.
+%
+% The list below gives optional arguments [default value in brackets].
+% 
+% equiv_class - equiv_class(i)=j  means factor node i gets its params from factors{j} [1:F]
+% ev_equiv_class - ev_equiv_class(i)=j  means evidence node i gets its params from ev_CPD{j} [1:N]
+
+
+N = length(node_sizes);
+nfactors = length(factors);
+
+% default values for parameters
+eclass = 1:nfactors;
+ev_eclass = 1:N;
+
+if nargin >= 6
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'equiv_class', eclass = args{i+1}; 
+     case 'ev_equiv_class', ev_eclass = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+pot_type = 'd';
+for x=1:N
+  ev = cell(1,2); % cell 1 is the hidden parent, cell 2 is the observed child
+  ev(2) = evidence(x); 
+  dom = 1:2;
+  F = convert_to_pot(ev_CPD{ev_eclass(x)}, pot_type, dom(:), ev);
+  M = pot_to_marginal(F);
+  %factors{end+1} = tabular_CPD('self', 1, 'ps', [], 'sz', node_sizes(x), 'CPT', M.T);
+  factors{end+1} = mk_isolated_tabular_CPD(node_sizes(x), {'CPT', M.T});
+end
+
+E = max(eclass);
+fg = mk_fgraph([G eye(N)], node_sizes, factors, 'equiv_class', [eclass E+1:E+N]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/mk_higher_order_dbn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,181 @@
+function bnet = mk_higher_order_dbn(intra, inter, node_sizes, varargin)
+% MK_DBN Make a Dynamic Bayesian Network.
+%
+% BNET = MK_DBN(INTRA, INTER, NODE_SIZES, ...) makes a DBN with arcs
+% from i in slice t to j in slice t iff intra(i,j) = 1, and 
+% from i in slice t to j in slice t+1 iff inter(i,j) = 1,
+% for i,j in {1, 2, ..., n}, where n = num. nodes per slice, and t >= 1.
+% node_sizes(i) is the number of values node i can take on.
+% The nodes are assumed to be in topological order. Use TOPOLOGICAL_SORT if necessary.
+% See also mk_bnet.
+%
+% Optional arguments [default in brackets]
+% 'discrete' - list of discrete nodes [1:n]
+% 'observed' - the list of nodes which will definitely be observed in every slice of every case [ [] ]
+% 'eclass1' - equiv class for slice 1 [1:n]
+% 'eclass2' - equiv class for slice 2 [tie nodes with equivalent parents to slice 1]
+%    equiv_class1(i) = j means node i in slice 1 gets its parameters from bnet.CPD{j},
+%    i.e., nodes i and j have tied parameters.
+% 'intra1' - topology of first slice, if different from others
+% 'names' - a cell array of strings to be associated with nodes 1:n [{}]
+%    This creates an associative array, so you write e.g.
+%     'evidence(bnet.names{'bar'}) = 42' instead of  'evidence(2} = 42' 
+%     assuming names = { 'foo', 'bar', ...}.
+%    
+% For backwards compatibility with BNT2, arguments can also be specified as follows
+%   bnet = mk_dbn(intra, inter, node_sizes, dnodes, eclass1, eclass2, intra1)
+%
+% After calling this function, you must specify the parameters (conditional probability
+% distributions) using bnet.CPD{i} = gaussian_CPD(...) or tabular_CPD(...) etc.
+
+
+n = length(intra);
+ss = n;
+bnet.nnodes_per_slice = ss;
+bnet.intra = intra;
+bnet.inter = inter;
+bnet.intra1 = intra;
+
+% As this method is used to generate a higher order Markov Model
+% also connect from time slice t - i -> t with i > 1 has to be 
+% taken into account.
+
+%inter should be a three dimensional array where inter(:,:,i)
+%describes the connections from time-slice t - i to t.  
+[rows,columns,order] = size(inter);
+assert(rows    == n);
+assert(columns == n);
+dag = zeros((order + 1)*n);
+
+i = 0;
+while i <= order
+    j = i;
+    while j <= order
+        if j == i
+            dag(1 + i*n:(i+1)*n,1+i*n:(i+1)*n) = intra;
+        else
+            dag(1+i*n:(i+1)*n,1+j*n:(j+1)*n) = inter(:,:,j - i);
+        end
+        j = j + 1;
+    end;
+    i = i + 1;
+end;
+
+bnet.dag = dag;
+bnet.names = {};
+
+directed = 1;
+if ~acyclic(dag,directed)
+  error('graph must be acyclic')
+end
+
+% Calculation of the equivalence classes
+bnet.eclass1 = 1:n;
+bnet.eclass = zeros(order + 1,ss);
+bnet.eclass(1,:) = 1:n;
+for i = 1:order
+    bnet.eclass(i+1,:) = bnet.eclass(i,:);
+    for j = 1:ss 
+        if(isequal(parents(dag,(i-1)*n+j)+ss,parents(dag,(i*n + j))))
+	   %fprintf('%d has isomorphic parents, eclass %d \n',j,bnet.eclass(i,j))
+        else
+	   bnet.eclass(i + 1,j) = max(bnet.eclass(i+1,:))+1;
+	   %fprintf('%d has non isomorphic parents, eclass %d \n',j,bnet.eclass(i,j))  
+	end;
+    end;
+end;
+bnet.eclass1 = 1:n;
+
+% To be compatible with whe rest of the code 
+bnet.eclass2 = bnet.eclass(2,:);
+
+dnodes = 1:n;
+bnet.observed = [];
+
+if nargin >= 4
+  args = varargin;
+  nargs = length(args);
+  if ~isstr(args{1})
+    if nargs >= 1 dnodes = args{1}; end
+    if nargs >= 2 bnet.eclass1 = args{2}; bnet.eclass(1,:) = args{2}; end
+    if nargs >= 3 bnet.eclass2 = args{3}; bnet.eclass(2,:) = args{2}; end
+    if nargs >= 4 bnet.intra1 = args{4}; end
+  else
+    for i=1:2:nargs
+      switch args{i},
+       case 'discrete', dnodes = args{i+1}; 
+       case 'observed', bnet.observed = args{i+1}; 
+       case 'eclass1',  bnet.eclass1 = args{i+1}; bnet.eclass(1,:) = args{i+1}; 
+       case 'eclass2',  bnet.eclass2 = args{i+1}; bnet.eclass(2,:) = args{i+1};
+       case 'eclass',   bnet.eclass = args{i+1};  
+       case 'intra1',  bnet.intra1 = args{i+1}; 
+       %case 'ar_hmm',  bnet.ar_hmm = args{i+1};  % should check topology
+       case 'names',  bnet.names = assocarray(args{i+1}, num2cell(1:n)); 
+       otherwise,  
+	error(['invalid argument name ' args{i}]);       
+      end
+    end
+  end
+end
+
+bnet.observed = sort(bnet.observed); % for comparing sets
+ns = node_sizes;
+bnet.node_sizes_slice = ns(:)';
+bnet.node_sizes = repmat(ns(:),1,order + 1);
+
+cnodes = mysetdiff(1:n, dnodes);
+bnet.dnodes_slice = dnodes;
+bnet.cnodes_slice = cnodes;
+bnet.dnodes = dnodes;
+bnet.cnodes = cnodes;
+% To adapt the function to higher order Markov models include dnodes for more 
+% time slices
+for i = 1:order
+    bnet.dnodes = [bnet.dnodes dnodes+i*n];
+    bnet.cnodes = [bnet.cnodes cnodes+i*n];
+end
+
+% Generieren einer Matrix, deren i-te Spalte die Aequivalenzklassen
+% der i-ten Zeitscheibe enthaelt. 
+bnet.equiv_class = [bnet.eclass(1,:)]';
+for i = 2:(order + 1)
+    bnet.equiv_class = [bnet.equiv_class   bnet.eclass(i,:)'];
+end
+
+bnet.CPD = cell(1,max(bnet.equiv_class(:)));
+
+ss = n;
+onodes = bnet.observed;
+hnodes = mysetdiff(1:ss, onodes);
+bnet.hidden_bitv = zeros(1,(order + 1)*ss);
+for i = 0:order
+    bnet.hidden_bitv(hnodes +i*ss) = 1;
+end;
+
+bnet.parents = cell(1, (order + 1)*ss);
+for i=1:(order + 1)*ss
+  bnet.parents{i} = parents(bnet.dag, i);
+end
+
+bnet.auto_regressive = zeros(1,ss);
+% ar(i)=1 means (observed) node i depends on i in the  previous slice
+for o=bnet.observed(:)'
+  if any(bnet.parents{o+ss} <= ss)
+    bnet.auto_regressive(o) = 1;
+  end
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/mk_limid.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,93 @@
+function bnet = mk_limid(dag, node_sizes, varargin)
+% MK_LIMID Make a limited information influence diagram
+%
+% BNET = MK_LIMID(DAG, NODE_SIZES, ...) 
+% DAG is the adjacency matrix for a directed acyclic graph.
+% The nodes are assumed to be in topological order. Use TOPOLOGICAL_SORT if necessary.
+% For decision nodes, the parents must explicitely include all nodes
+% on which it can depends, in contrast to the implicit no-forgetting assumption of influence diagrams.
+% (For details, see "Representing and solving decision problems with limited information",
+%    Lauritzen and Nilsson, Management Science, 2001.)
+%
+% node_sizes(i) is the number of values node i can take on,
+%   or the length of node i if i is a continuous-valued vector.
+% node_sizes(i) = 1 if i is a utility node.
+% 
+% The list below gives optional arguments [default value in brackets].
+% 
+% chance   - the list of nodes which are random variables [1:N]
+% decision - the list of nodes which are decision nodes [ [] ]
+% utility  - the list of nodes which are utility nodes [ [] ]
+% equiv_class - equiv_class(i)=j  means node i gets its params from CPD{j} [1:N]
+%
+% e.g., limid = mk_limid(dag, ns, 'chance', [1 3], 'utility', [2])
+
+n = length(dag);
+
+% default values for parameters
+bnet.chance_nodes = 1:n;
+bnet.equiv_class = 1:n;
+bnet.utility_nodes = [];
+bnet.decision_nodes = [];
+bnet.dnodes = 1:n; % discrete 
+
+if nargin >= 3
+  args = varargin;
+  nargs = length(args);
+  if ~isstr(args{1})
+    if nargs >= 1, bnet.dnodes = args{1}; end
+    if nargs >= 2, bnet.equiv_class = args{2}; end
+  else    
+    for i=1:2:nargs
+      switch args{i},
+       case 'equiv_class', bnet.equiv_class = args{i+1}; 
+       case 'chance',      bnet.chance_nodes = args{i+1}; 
+       case 'utility',     bnet.utility_nodes = args{i+1}; 
+       case 'decision',    bnet.decision_nodes = args{i+1}; 
+       case 'discrete',    bnet.dnodes = args{i+1}; 
+        otherwise,  
+	error(['invalid argument name ' args{i}]);       
+      end
+    end
+  end
+end
+ 
+bnet.limid = 1;
+
+bnet.dag = dag;
+bnet.node_sizes = node_sizes(:)';
+
+bnet.cnodes = mysetdiff(1:n, bnet.dnodes);
+% too many functions refer to cnodes to rename it to cts_nodes - 
+% We hope it won't be confused with chance nodes!
+
+bnet.parents = cell(1,n);
+for i=1:n
+  bnet.parents{i} = parents(dag, i);
+end
+
+E = max(bnet.equiv_class);
+mem = cell(1,E);
+for i=1:n
+  e = bnet.equiv_class(i);
+  mem{e} = [mem{e} i];
+end
+bnet.members_of_equiv_class = mem;
+
+bnet.CPD = cell(1, E);
+
+% for e=1:E
+%   i = bnet.members_of_equiv_class{e}(1); % pick arbitrary member
+%   switch type{e}
+%     case 'tabular',  bnet.CPD{e} = tabular_CPD(bnet, i);
+%     case 'gaussian', bnet.CPD{e} = gaussian_CPD(bnet, i);
+%     otherwise, error(['unrecognized CPD type ' type{e}]);
+%   end
+% end
+
+directed = 1;
+if ~acyclic(dag,directed)
+  error('graph must be acyclic')
+end
+
+bnet.order = topological_sort(bnet.dag);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/mk_mnet.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+function mnet = mk_mnet(graph, node_sizes, cliques, potentials)
+% MK_MNET Make a Markov network (Markov Random Field)
+%
+% mnet = mk_mnet(adj_mat, node_sizes, cliques, potentials)
+%
+% cliques{i} is a list of the nodes in clq i
+% potentials{i} is a dpot object corresponding to the potential for clique i
+%
+
+mnet.markov_net = 1;
+mnet.graph = graph;
+mnet.node_sizes = node_sizes;
+mnet.user_cliques = cliques;
+mnet.user_potentials = potentials;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/mk_mrf2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function mrf2 = mk_mrf2(adj_mat, pot)
+% MK_MRF2 Make a Markov random field with pairwise potentials
+% function mrf2 = mk_mrf2(adj_mat, pot)
+%
+% pot{i,j}(k1,k2)
+
+mrf2.adj_mat = adj_mat;
+mrf2.pot = pot;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/mk_mutilated_samples.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function [data, clamped] = mk_mutilated_samples(bnet, ncases, max_clamp, usecell)
+% GEN_MUTILATED_SAMPLES Do random interventions and then draw random samples
+% [data, clamped] = gen_mutilated_samples(bnet, ncases, max_clamp, usecell)
+%
+% At each step, we pick a random subset of size 0 .. max_clamp, and 
+% clamp these nodes to random values.
+%
+% data(i,m) is the value of node i in case m.
+% clamped(i,m) = 1 if node i in case m was set by intervention.
+
+if nargin < 4, usecell = 1; end
+
+ns = bnet.node_sizes;
+n = length(bnet.dag);
+if usecell
+  data = cell(n, ncases);
+else
+  data = zeros(n, ncases);
+end
+clamped = zeros(n, ncases);
+
+csubsets = subsets(1:n, max_clamp, 0); % includes the empty set
+distrib_cset = normalise(ones(1, length(csubsets)));
+
+for m=1:ncases
+  cset = csubsets{sample_discrete(distrib_cset)};
+  nvals = prod(ns(cset));
+  distrib_cvals = normalise(ones(1, nvals));
+  cvals = ind2subv(ns(cset), sample_discrete(distrib_cvals));
+  mutilated_bnet = do_intervention(bnet, cset, cvals);
+  ev = sample_bnet(mutilated_bnet);
+  if usecell
+    data(:,m) = ev;
+  else
+    data(:,m) = cell2num(ev);
+  end
+  clamped(cset,m) = 1;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/mk_named_CPT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+function CPT2 = mk_named_CPT(family_names, names, dag, CPT1)
+% MK_NAMED_CPT Permute the dimensions of a CPT so they agree with the internal numbering convention
+% CPT2 = mk_named_CPT(family_names, names, dag, CPT1)
+%
+% This is best explained by example.
+% Consider the following directed acyclic graph
+%
+%     C
+%   /   \
+%  R     S
+%   \   /
+%     W
+%
+% where all arcs point down.
+% When we create the CPT for node W, we consider S as its first parent, and R as its
+% second, and hence write
+%
+%      S R W
+% CPT1(1,1,:) = [1.0 0.0];
+% CPT1(2,1,:) = [0.2 0.8];  % P(W=1 | R=1, S=2) = 0.2
+% CPT1(1,2,:) = [0.1 0.9]; 
+% CPT1(2,2,:) = [0.01 0.99];
+%
+% However, when we create the dag using mk_adj_mat, the nodes get topologically sorted,
+% and by chance, node R preceeds node S in this ordering.
+% Hence we should have written
+%
+%      R S W
+% CPT2(1,1,:) = [1.0 0.0];
+% CPT2(2,1,:) = [0.1 0.9];
+% CPT2(1,2,:) = [0.2 0.8]; % P(W=1 | R=1, S=2) = 0.2
+% CPT2(2,2,:) = [0.01 0.99];
+%
+% Since we do not know the order of the nodes in advance, we can write
+%   CPT2 = mk_named_CPT({'S', 'R', 'W'}, names, dag, CPT1)
+% where 'S', 'R', 'W' are the order of the dimensions we assumed (the child node must be last in this list),
+% and names{i} is the name of the i'th node.
+
+n = length(family_names);
+family_nums = zeros(1,n);
+for i=1:n
+  family_nums(i) = stringmatch(family_names{i}, names); % was strmatch
+end
+
+fam = family(dag, family_nums(end));
+perm = zeros(1,n);
+for i=1:n
+  %  perm(i) = find(family_nums(i) == fam);
+  perm(i) = find(fam(i) == family_nums);
+end
+
+CPT2 = permute(CPT1, perm);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/mk_slice_and_half_dbn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function bnet15 = mk_slice_and_half_dbn(bnet, int)
+% function bnet = mk_slice_and_half_dbn(bnet, int)
+% function bnet = mk_slice_and_half_dbn(bnet, int)
+%
+% Create a "1.5 slice" jtree, containing the interface nodes of slice 1
+% and all the nodes of slice 2
+% To keep the node numbering the same, we simply disconnect the non-interface nodes
+% from slice 1, and set their size to 1.
+% We do this to speed things up, and so that the likelihood is computed correctly.
+% We do not need to do
+% this if we just want to compute marginals (i.e., we can include nodes whose potentials will
+% be left as all 1s).
+
+intra15 = bnet.intra;
+ss = length(bnet.intra);
+nonint = mysetdiff(1:ss, int);
+for i=nonint(:)'
+  intra15(:,i) = 0;
+  intra15(i,:) = 0;
+  %assert(~any(bnet.inter(i,:)))
+end
+dag15 = [intra15      bnet.inter;
+	 zeros(ss)    bnet.intra];
+ns = bnet.node_sizes(:);
+ns(nonint) = 1; % disconnected nodes get size 1
+obs_nodes = [bnet.observed(:) bnet.observed(:)+ss];
+bnet15 = mk_bnet(dag15, ns, 'discrete', bnet.dnodes, 'equiv_class', bnet.equiv_class(:), ...
+		 'observed', obs_nodes(:));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/noisyORtoTable.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function CPT = noisyORtoTable(inhibit, leak_inhibit)
+% NOISYORTOTABLE Convert noisyOR distribution to CPT
+% function CPT = noisyORtoTable(inhibit, leak_inhibit)
+%
+% inhibit(i) = prob i'th parent will be inhibited (flipped from 1 to 0)
+% leak_inhibit - optional suppression of leak
+% CPT(U1,...,Un, X) = Pr(X|U1,...,Un) where the Us are the parents (excluding leak).
+% State 1 = off, 2 = on
+
+if nargin < 2, leak_inhibit = 1; end
+
+q = [leak_inhibit inhibit(:)'];
+
+if length(q)==1
+  CPT = [q  1-q];
+  return;
+end
+
+n = length(q);
+Bn = ind2subv(2*ones(1,n), 1:(2^n))-1;  % all n bit vectors, with the left most column toggling fastest (LSB)
+CPT = zeros(2^n, 2);
+% Pr(X=0 | U_1 .. U_n) = prod_{i: U_i = on} q_i =  prod_i q_i ^ U_i = exp(u' * log(q_i))
+% This method is problematic when q contains zeros
+
+Q = repmat(q(:)', 2^n, 1);
+Q(logical(~Bn)) = 1;
+CPT(:,1) = prod(Q,2);
+CPT(:,2) = 1-CPT(:,1);
+
+CPT = reshape(CPT(2:2:end), 2*ones(1,n)); % skip cases in which the leak is off       
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/partition_dbn_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function [pnodes, tnodes] = partition_dbn_nodes(intra, inter)
+% PARTITION_DBN_NODES Divide the nodes into a DBN into persistent and transient.
+% [pnodes, tnodes] = partition_dbn_nodes(intra, inter)
+% Persistent nodes have children in the next time slice, transient nodes do not.
+ 
+ss = length(intra);
+pnodes = []; 
+tnodes = [];
+for i=1:ss
+  cs = children(inter, i);
+  if isempty(cs)
+    tnodes = [tnodes i];
+  else
+    pnodes = [pnodes i];
+  end
+end
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/partition_matrix_vec_3.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function [A1, A2, B1, B2, C11, C12, C21, C22] = partition_matrix_vec_3(A, B, C, n1, n2, bs)
+
+dom = myunion(n1, n2);
+n1i = block(find_equiv_posns(n1, dom), bs(dom));
+n2i = block(find_equiv_posns(n2, dom), bs(dom));
+
+
+    A1 = A(n1i);
+    A2 = A(n2i);
+    if isempty(B)
+        B1 = zeros(size(n1i, 2),size(B, 2));
+        B2 = zeros(size(n2i, 2),size(B, 2));
+    else
+        B1 = B(n1i, :);
+        B2 = B(n2i, :);
+    end
+    
+    
+    C11 = C(n1i, n1i);
+    C12 = C(n1i, n2i);
+    C21 = C(n2i, n1i);
+    C22 = C(n2i, n2i);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/sample_bnet.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,34 @@
+function sample = sample_bnet(bnet, varargin)
+% SAMPLE_BNET Generate a random sample from a Bayes net.
+% SAMPLE = SAMPLE_BNET(BNET, ...)
+%
+% sample{i} contains the value of the i'th node.
+% i.e., the result is an Nx1 cell array.
+% Nodes are sampled in the order given by bnet.order.
+%
+% Optional arguments:
+%
+% evidence - initial evidence; if evidence{i} is non-empty, node i won't be sampled.
+
+% set defauly params
+n = length(bnet.dag);
+sample = cell(n,1);
+
+% get optional params
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'evidence',    sample = args{i+1}(:);
+   otherwise, error(['unrecognized argument ' args{i}])
+  end
+end
+
+for j=bnet.order(:)'
+  if isempty(sample{j})
+    %ps = parents(bnet.dag, j);
+    ps = bnet.parents{j};
+    e = bnet.equiv_class(j);
+    sample{j} = sample_node(bnet.CPD{e}, sample(ps));
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/sample_dbn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,73 @@
+function seq = sample_dbn(bnet, varargin)
+% SAMPLE_DBN Generate a random sequence from a DBN.
+% seq = sample_dbn(bnet, ...)
+%
+% seq{i,t} contains the values of the i'th node in the t'th slice.
+%
+% Optional arguments:
+%
+% length - length of sequence  to be generated (can also just use sample_dbn(bnet,T))
+% stop_test - name of a function which is used to decide when to stop;
+%   This will be called as feval(stop_test, seq(:,t))
+%   i.e., stop_test is passed a cell array containing all the nodes in the current slice.   
+% evidence - initial evidence; if evidence{i,t} is non-empty, this node won't be sampled.
+
+args = varargin;
+nargs = length(args);
+
+if (nargs == 1) & ~isstr(args{1})
+  % Old syntax: sample_dbn(bnet, T)
+  T = args{1};
+else
+  % get length
+  T = 1;
+  for i=1:2:nargs
+    switch args{i},
+     case 'length',      T = args{i+1}; 
+     case 'evidence',    T = size(args{i+1}, 2);
+    end
+  end
+end
+
+ss = length(bnet.intra);
+% set default arguments
+seq = cell(ss, T);
+stop_test = [];
+for i=1:2:nargs
+  switch args{i},
+   case 'evidence',    seq = args{i+1}; % initialise observed nodes
+   case 'stop_test',  stop_test = args{i+1};
+  end
+end
+
+t = 1;
+for i=1:ss
+  if ~isempty(stop_test) | isempty(seq{i,t})
+    ps = parents(bnet.dag, i);
+    e = bnet.equiv_class(i,1);
+    pvals = seq(ps);
+    seq{i,t} = sample_node(bnet.CPD{e}, pvals);
+    %fprintf('sample i=%d,t=%d,val=%d,ps\n', i, t, seq(i,t)); pvals(:)'
+  end
+end
+t = 2;
+done = 0;
+while ~done
+  for i=1:ss
+    if ~isempty(stop_test) | isempty(seq{i,t})
+      ps = parents(bnet.dag, i+ss) + (t-2)*ss;
+      e = bnet.equiv_class(i,2);
+      pvals = seq(ps);
+      seq{i,t} = sample_node(bnet.CPD{e}, pvals);
+      %fprintf('sample i=%d,t=%d,val=%d,ps\n', i, t, seq(i,t)); pvals(:)'
+    end
+  end
+  if ~isempty(stop_test)
+    done = feval(stop_test, seq(:,t));
+  else
+    if t==T
+      done = 1;
+    end
+  end
+  t = t + 1;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/score_bnet_complete.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function L = log_lik_complete(bnet, cases, clamped)
+% LOG_LIK_COMPLETE Compute sum_m sum_i log P(x(i,m)| x(pi_i,m), theta_i) for a completely observed data set
+% L = log_lik_complete(bnet, cases, clamped)
+%
+% If there is a missing data, you must use an inference engine.
+% cases(i,m) is the value assigned to node i in case m.
+% (If there are vector-valued nodes, cases should be a cell array.)
+% clamped(i,m) = 1 if node i was set by intervention in case m (default: clamped = zeros)
+% Clamped nodes contribute a factor of 1.0 to the likelihood.
+
+if iscell(cases), usecell = 1; else usecell = 0; end
+
+n = length(bnet.dag);
+ncases = size(cases, 2);
+if n ~= size(cases, 1)
+  error('data should be of size nnodes * ncases');
+end
+
+if nargin < 3, clamped = zeros(n,ncases); end
+
+L = 0;
+for i=1:n
+  ps = parents(bnet.dag, i);
+  e = bnet.equiv_class(i);
+  u = find(clamped(i,:)==0);
+  L = L + log_prob_node(bnet.CPD{e}, cases(i,u), cases(ps,u));
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/shrink_obs_dims_in_gaussian.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function marg2 = shrink_obs_dims_in_gaussian(marg1, dom, evidence, ns)
+% SHRINK_OBS_DIMS_IN_GAUSSIAN Remove observed dimensions from mu/Sigma
+% function marg2 = shrink_obs_dims_in_gaussian(marg1, dom, evidence, ns)
+
+% This is used by loopy
+
+hdom = dom(isemptycell(evidence(dom)));
+ndx = find_equiv_posns(hdom, dom);
+b = block(ndx, ns(dom));
+marg2.mu = marg1.mu(b);
+marg2.Sigma = marg1.Sigma(b,b);
+marg2.domain = marg1.domain;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/shrink_obs_dims_in_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function T2 = shrink_obs_dims_in_table(T1, dom, evidence)
+% SHRINK_OBS_DIMS_IN_TABLE Set observed dimensions to size 1
+% T2 = shrink_obs_dims_in_table(T1, dom, evidence)
+%
+% If 'T1' contains observed nodes, it will have 0s in the positions that are
+% inconsistent with the evidence. We now remove these 0s and set the corresponding dimensions to
+% size 1, to be consistent with the way most inference engines handle evidence, which is to
+% shrink observed nodes before doing inference.
+
+% This is used by pearl and enumerative inf. engines.
+
+odom = dom(~isemptycell(evidence(dom)));
+vals = cat(1,evidence{odom});
+ndx = mk_multi_index(length(dom), find_equiv_posns(odom, dom), vals(:));
+T2 = T1(ndx{:});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/solve_limid.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,68 @@
+function [strategy, MEU, niter] = solve_limid(engine, varargin)
+% SOLVE_LIMID Find the (locally) optimal strategy for a LIMID
+% [strategy, MEU, niter] = solve_limid(inf_engine, ...)
+%
+% strategy{d} = stochastic policy for node d (a decision node)
+% MEU = maximum expected utility
+% niter = num iterations used
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default in brackets]
+%
+% max_iter - max. num. iterations [ 1 ]
+% tol - tolerance required of consecutive MEU values, used to assess convergence [1e-3]
+% order - order in which decision nodes are optimized [ reverse numerical order ]
+%
+% e.g., solve_limid(engine, 'tol', 1e-2, 'max_iter', 10)
+
+bnet = bnet_from_engine(engine);
+
+% default values
+max_iter = 1;
+tol = 1e-3;
+D = bnet.decision_nodes;
+order = D(end:-1:1);
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'max_iter', max_iter  = args{i+1}; 
+   case 'tol',      tol = args{i+1}; 
+   case 'order',    order = args{i+1}; 
+   otherwise,  
+    error(['invalid argument name ' args{i}]);       
+  end
+end
+
+CPDs = bnet.CPD;
+ns = bnet.node_sizes;
+N = length(ns);
+evidence = cell(1,N);
+strategy = cell(1, N);
+
+iter = 1;
+converged = 0;
+oldMEU = 0;
+while ~converged & (iter <= max_iter)
+  for d=order(:)'
+    engine = enter_evidence(engine, evidence, 'exclude', d);
+    [m, pot] = marginal_family(engine, d);
+    %pot = marginal_family_pot(engine, d);
+    [policy, score] = upot_to_opt_policy(pot);    
+    e = bnet.equiv_class(d);
+    CPDs{e} = set_fields(CPDs{e}, 'policy', policy);
+    engine = update_engine(engine, CPDs);
+    strategy{d} = policy;
+  end  
+  engine = enter_evidence(engine, evidence);
+  [m, pot] = marginal_nodes(engine, []);
+  %pot = marginal_family_pot(engine, []);
+  [dummy, MEU] = upot_to_opt_policy(pot);    
+  if approxeq(MEU, oldMEU, tol)
+    converged = 1;
+  end
+  oldMEU = MEU;
+  iter = iter + 1;
+end
+niter = iter - 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/unroll_dbn_topology.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function M = unroll_dbn_topology(intra, inter, T, intra1)
+% UNROLL_DBN_TOPOLOGY Make the block diagonal adjacency matrix for a DBN consisting of T slices
+% M = unroll_dbn_topology(intra, inter, T, intra1)
+%
+% intra is the connectivity within a slice, inter between two slices.
+% M will have intra along the diagonal, and inter one above the diagonal.
+% intra1 is an optional argumnet, in case the intra is different for the first slice.
+
+if nargin < 4, intra1 = intra; end
+
+ss = length(intra); % slice size
+M = sparse(ss*T, ss*T);
+
+b = 1:ss;
+M(b,b) = intra1;
+M(b,b+ss) = inter;
+
+for t=2:T-1
+  b = (1:ss) + (t-1)*ss;
+  M(b,b) = intra;
+  M(b,b+ss) = inter;
+end
+
+t = T;
+b = (1:ss) + (t-1)*ss;
+M(b,b) = intra;
+
+   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/unroll_higher_order_topology.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function M = unroll_higher_order_topology(intra, inter, T, intra1)
+% UNROLL_DBN_TOPOLOGY Make the block diagonal adjacency matrix for a DBN consisting of T slices
+% M = unroll_dbn_topology(intra, inter, T, intra1)
+%
+% intra is the connectivity within a slice, inter between two slices.
+% M will have intra along the diagonal, and inter one above the diagonal.
+% intra1 is an optional argumnet, in case the intra is different for the first slice.
+
+if nargin < 4 
+    intra1 = intra; 
+end;
+
+
+ss = length(intra); % slice size
+M = sparse(ss*T, ss*T);
+[rows,columns,order] = size(inter);
+for t1 = 1:T
+  b = 1 + (t1 - 1)*ss : t1*ss;
+  if t1 == 1
+      M(b,b) = intra1;
+  else
+      M(b,b) = intra;
+  end
+  for t2 = 1:order
+    if t1 + t2 <= T
+      M(b,b+t2*ss) = inter(:,:,t2);
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/general/unroll_set.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function U = unroll_set(S, ss, T)
+% UNROLL_SET Make T shifted copies of the set of nodes S in a slice of size ss.
+% U = unroll_set(S, ss, T)
+
+offset = repmat(0:ss:(T-1)*ss, [length(S) 1]);
+U = repmat(S(:), [1 T]) + offset;
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/.svn/all-wcprops	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/CVS
+END
+Repository
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/CVS/Repository
+END
+Root
+K 25
+svn:wc:ra_dav:version-url
+V 67
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/CVS/Root
+END
+Entries
+K 25
+svn:wc:ra_dav:version-url
+V 70
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/CVS/Entries
+END
+Entries.Log
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/CVS/Entries.Log
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/.svn/entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,164 @@
+10
+
+dir
+7329
+https://parrot.dcs.qmul.ac.uk/svnroot/matlabtoolboxes/FullBNT-1.0.4/graph/CVS
+https://parrot.dcs.qmul.ac.uk/svnroot
+
+
+
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+214cd2a9-030a-0410-b9a1-da4e402363b6
+
+Repository
+file
+
+
+
+
+2010-04-08T01:08:23.000000Z
+5547e28254023e278f909952604e906e
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+14
+
+Root
+file
+
+
+
+
+2010-04-08T01:08:23.000000Z
+a49432e9bea5bbd5666443ab187b4558
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+51
+
+Entries
+file
+
+
+
+
+2010-04-08T01:08:23.000000Z
+409b7f319e28ba20e594a8c1c77bf619
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2547
+
+Entries.Log
+file
+
+
+
+
+2010-04-08T01:08:23.000000Z
+ef0b99de88eda8653a20a0f7a9f177c0
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/.svn/prop-base/Entries.Log.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/.svn/prop-base/Entries.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/.svn/prop-base/Repository.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/.svn/prop-base/Root.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/.svn/text-base/Entries.Log.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/.svn/text-base/Entries.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,49 @@
+/README.txt/1.1.1.1/Mon Aug 29 17:44:02 2005//
+/acyclic.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/assignEdgeNums.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/best_first_elim_order.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/check_jtree_property.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/check_triangulated.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/children.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/cliques_to_jtree.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/cliques_to_strong_jtree.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/connected_graph.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/dag_to_essential_graph.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/dfs.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/dfs_test.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/dijkstra.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/family.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/graph_separated.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/graph_to_jtree.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/min_subtree_con_nodes.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/minimum_spanning_tree.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/minspan.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_2D_lattice.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_2D_lattice_slow.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_adj_mat.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_adjmat_chain.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_all_dags.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_nbrs_of_dag.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_nbrs_of_digraph.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_nbrs_of_digraph_broken.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_nbrs_of_digraph_not_vectorized.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_rnd_dag.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_rnd_dag_given_edge_prob.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_rooted_tree.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_undirected.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/moralize.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/neighbors.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/parents.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/pred2path.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/reachability_graph.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/scc.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/strong_elim_order.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/test.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/test_strong_root.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/topological_sort.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/trees.txt/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/triangulate.c/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/triangulate.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/triangulate_2Dlattice_demo.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/triangulate_test.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/.svn/text-base/Repository.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/graph
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/.svn/text-base/Root.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,49 @@
+/README.txt/1.1.1.1/Mon Aug 29 17:44:02 2005//
+/acyclic.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/assignEdgeNums.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/best_first_elim_order.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/check_jtree_property.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/check_triangulated.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/children.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/cliques_to_jtree.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/cliques_to_strong_jtree.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/connected_graph.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/dag_to_essential_graph.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/dfs.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/dfs_test.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/dijkstra.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/family.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/graph_separated.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/graph_to_jtree.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/min_subtree_con_nodes.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/minimum_spanning_tree.m/1.1.1.1/Mon Aug 29 17:44:04 2005//
+/minspan.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_2D_lattice.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_2D_lattice_slow.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_adj_mat.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_adjmat_chain.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_all_dags.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_nbrs_of_dag.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_nbrs_of_digraph.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_nbrs_of_digraph_broken.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_nbrs_of_digraph_not_vectorized.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_rnd_dag.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_rnd_dag_given_edge_prob.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_rooted_tree.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/mk_undirected.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/moralize.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/neighbors.m/1.1.1.1/Mon Aug 29 17:44:06 2005//
+/parents.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/pred2path.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/reachability_graph.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/scc.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/strong_elim_order.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/test.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/test_strong_root.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/topological_sort.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/trees.txt/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/triangulate.c/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/triangulate.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/triangulate_2Dlattice_demo.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+/triangulate_test.m/1.1.1.1/Mon Aug 29 17:44:08 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/graph
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/.svn/all-wcprops	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,35 @@
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/Old
+END
+best_first_elim_order.m
+K 25
+svn:wc:ra_dav:version-url
+V 86
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/Old/best_first_elim_order.m
+END
+mk_2D_lattice_slow.m
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/Old/mk_2D_lattice_slow.m
+END
+dag_to_jtree.m
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/Old/dag_to_jtree.m
+END
+dsep_test.m
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/Old/dsep_test.m
+END
+dfs.m
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/Old/dfs.m
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/.svn/entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,201 @@
+10
+
+dir
+7329
+https://parrot.dcs.qmul.ac.uk/svnroot/matlabtoolboxes/FullBNT-1.0.4/graph/Old
+https://parrot.dcs.qmul.ac.uk/svnroot
+
+
+
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+214cd2a9-030a-0410-b9a1-da4e402363b6
+
+best_first_elim_order.m
+file
+
+
+
+
+2010-04-08T01:08:23.000000Z
+181b4fccdaf1791e1c7f710c26aeaa09
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2607
+
+mk_2D_lattice_slow.m
+file
+
+
+
+
+2010-04-08T01:08:23.000000Z
+259c93a5a0170329b60f3d5b3d1be31d
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2974
+
+dag_to_jtree.m
+file
+
+
+
+
+2010-04-08T01:08:23.000000Z
+f1284e4c382c299b49e64ee7449d4d12
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1819
+
+dsep_test.m
+file
+
+
+
+
+2010-04-08T01:08:23.000000Z
+e9c530ff844accff52a321ebe6fa88be
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+202
+
+dfs.m
+file
+
+
+
+
+2010-04-08T01:08:23.000000Z
+da9bdaa08aac3ad2eda9556949b6e46b
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2826
+
+CVS
+dir
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/.svn/prop-base/best_first_elim_order.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/.svn/prop-base/dag_to_jtree.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/.svn/prop-base/dfs.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/.svn/prop-base/dsep_test.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/.svn/prop-base/mk_2D_lattice_slow.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/.svn/text-base/best_first_elim_order.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+function order = best_first_elim_order(G, node_sizes, stage)
+% BEST_FIRST_ELIM_ORDER Greedily search for an optimal elimination order.
+% order = best_first_elim_order(moral_graph, node_sizes)
+%
+% Find an order in which to eliminate nodes from the graph in such a way as to try and minimize the
+% weight of the resulting triangulated graph.  The weight of a graph is the sum of the weights of each
+% of its cliques; the weight of a clique is the product of the weights of each of its members; the
+% weight of a node is the number of values it can take on.
+%
+% Since this is an NP-hard problem, we use the following greedy heuristic:
+% at each step, eliminate that node which will result in the addition of the least
+% number of fill-in edges, breaking ties by choosing the node that induces the lighest clique.
+% For details, see
+% - Kjaerulff, "Triangulation of graphs -- algorithms giving small total state space",
+%      Univ. Aalborg tech report, 1990 (www.cs.auc.dk/~uk)
+% - C. Huang and A. Darwiche, "Inference in Belief Networks: A procedural guide",
+%      Intl. J. Approx. Reasoning, 11, 1994
+%
+
+% Warning: This code is pretty old and could probably be made faster.
+
+n = length(G);
+if nargin < 3, stage = { 1:n }; end % no constraints
+
+% For long DBNs, it may be useful to eliminate all the nodes in slice t before slice t+1.
+% This will ensure that the jtree has a repeating structure (at least away from both edges).
+% This is why we have stages.
+% See the discussion of splicing jtrees on p68 of
+% Geoff Zweig's PhD thesis, Dept. Comp. Sci., UC Berkeley, 1998.
+% This constraint can increase the clique size significantly.
+
+MG = G; % copy the original graph
+uneliminated = ones(1,n);
+order = zeros(1,n);
+t = 1;  % Counts which time slice we are on        
+for i=1:n
+  U = find(uneliminated);
+  valid = myintersect(U, stage{t});
+  % Choose the best node from the set of valid candidates
+  score1 = zeros(1,length(valid));
+  score2 = zeros(1,length(valid));
+  for j=1:length(valid)
+    k = valid(j);
+    ns = myintersect(neighbors(G, k), U);
+    l = length(ns);
+    M = MG(ns,ns);
+    score1(j) = l^2 - sum(M(:)); % num. added edges
+    score2(j) = prod(node_sizes([k ns])); % weight of clique
+  end
+  j1s = find(score1==min(score1));
+  j = j1s(argmin(score2(j1s)));
+  k = valid(j);
+  uneliminated(k) = 0;
+  order(i) = k;
+  ns = myintersect(neighbors(G, k), U);
+  if ~isempty(ns)
+    G(ns,ns) = 1;
+    G = setdiag(G,0);
+  end
+  if ~any(logical(uneliminated(stage{t}))) % are we allowed to the next slice?
+    t = t + 1;
+  end   
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/.svn/text-base/dag_to_jtree.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,55 @@
+function [jtree, root, cliques, B, w, elim_order, moral_edges, fill_in_edges, strong] = ...
+    dag_to_jtree(dag, node_sizes, partial_order, stages, clusters)
+% DAG_TO_JTREE Moralize and triangulate a DAG, and make a junction tree from its cliques.
+% [jtree, root, cliques, B, w, elim_order, moral_edges, fill_in_edges, strong] = ...
+%    dag_to_jtree(dag, node_sizes, partial_order, stages, clusters)
+%
+% Input:
+% dag(i,j) 
+% jtree(i,j) = 1 iff there is an arc between clique i and clique j 
+% root = the root clique
+% cliques{i} = the nodes in clique i
+% B(i,j) = 1 iff node j occurs in clique i
+% w(i) = weight of clique i
+
+N = length(bnet.dag);
+if nargin < 2, obs_nodes = []; end
+if nargin < 3, stages = { 1:N }; end
+if nargin < 4, clusters = {}; end
+
+[MG, moral_edges]  = moralize(bnet.dag);
+
+% Add extra arcs between nodes in each cluster to ensure they occur in the same clique
+for i=1:length(clusters)
+  c = clusters{i};
+  MG(c,c) = 1;
+end
+MG = setdiag(MG, 0);
+
+% Find an optimal elimination ordering (NP-hard problem!)
+ns = bnet.node_sizes(:);
+ns(obs_nodes) = 1; % observed nodes have only 1 possible value
+partial_order = determine_elim_constraints(bnet, obs_nodes);
+
+if isempty(partial_order)
+  strong = 0;
+  elim_order = best_first_elim_order(MG, ns, stages);
+else
+  strong = 1;
+  elim_order = strong_elim_order(MG, ns, partial_order);
+end
+
+[MTG, cliques, fill_in_edges]  = triangulate(MG, elim_order);
+
+% Connect the cliques up into a jtree,
+[jtree, root, B, w] = cliques_to_jtree(cliques, ns);
+
+if 0
+  disp('testing dag to jtree');
+  % Find the cliques containing each node, and check they form a connected subtree
+  clqs_con_node = cell(1,N);
+  for i=1:N
+    clqs_con_node{i} = find(B(:,i))';
+  end
+  check_jtree_property(clqs_con_node, jtree);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/.svn/text-base/dfs.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,84 @@
+function [d, pre, post, height, cycle, pred] = dfs(adj_mat, start, directed)
+% DFS Perform a depth-first search of the graph starting from 'start'.
+% [d, pre, post, height, cycle, pred] = dfs(adj_mat, start, directed)
+%
+% d(i) is the time at which node i is first discovered.
+% pre is a listing of the nodes in the order in which they are first encountered (opened).
+% post is a listing of the nodes in the order in which they are last encountered (closed).
+% A node is last encountered once we have explored all of its neighbors.
+% If the graph is directed, i's neighbors are its children.
+% If the graph is a tree, preorder is parents before children, and
+% postorder is children before parents.
+% For a DAG, topological order = reverse(postorder).
+% height(i) is the height (distance) of node i from the start.
+% 'cycle' is true iff a (directed) cycle is found.
+% pred(i) is the parent of i in the dfs tree rooted at start.
+% See Cormen, Leiserson and Rivest, "An intro. to algorithms" 1994, p478.
+
+% We can detect undirected cycles by checking if we are about to visit a node n which we have
+% already visited. To detect *directed* cycles, we need to know if n has been closed or is still open.
+% For example (where arcs are directed down)
+%   1    2
+%   \   /
+%     3
+% Assume we visit 1, 3 and then 2 in order. The fact that a child of 2 (namely, 3) has
+% already been visited is okay, because 3 has been closed.
+% The algorithms in Aho, Hopcroft and Ullman, and Sedgewick, do not detect directed cycles.
+
+n = length(adj_mat);
+
+global white gray black
+white = 0; gray = 1; black = 2;
+
+color = white*ones(1,n);
+d = zeros(1,n);
+height = zeros(1,n);
+pred = zeros(1,n);
+pre = [];
+post = [];
+cycle = 0;
+global count
+count = 0;
+h = 0;
+[d, pre, post, height, cycle, color, pred] = ...
+    dfs2(adj_mat, start, directed, h, d, pre, post, height, cycle, color, pred);
+
+
+
+%%%%%%%%%%
+
+function [d, pre, post, height, cycle, color, pred] = ...
+    dfs2(adj_mat, i, directed, h, d, pre, post, height, cycle, color, pred)
+
+global count
+global white gray black
+
+color(i) = gray;
+count = count + 1;
+d(i) = count;
+pre = [pre i];
+height(i) = h;
+if directed
+  ns = children(adj_mat, i);
+else
+  ns = neighbors(adj_mat, i);
+end
+for j=1:length(ns)
+  n=ns(j);
+  if ~directed & n==pred(i) % don't go back up the edge you just came down
+    % continue
+  else
+    if color(n) == gray % going back to a non-closed vertex via a new edge
+      %fprintf(1, 'cycle from %d to %d\n', i, n);
+      cycle = 1;
+    end
+    if color(n) == white % not visited n before
+      pred(n)=i;
+      [d, pre, post, height, cycle, color, pred] = ...
+	  dfs2(adj_mat, n, directed, h+1, d, pre, post, height, cycle, color, pred);
+    end
+  end
+end
+color(i) = black;
+post = [post i];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/.svn/text-base/dsep_test.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+
+% Cowell et al p72
+G = zeros(10);
+G(1,2)=1;
+G(2,3)=1;
+G(3,7)=1;
+G(4,[5 8])=1;
+G(5,6)=1;
+G(6,7)=1;
+G(7,[9 10])=1;
+G(8,9)=1;
+
+dsep(1, 4, [5 7], G)
+dsep(1, 4, [7], G)
+dsep(1, 4, [10 5], G)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/.svn/text-base/mk_2D_lattice_slow.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,121 @@
+function G = mk_2D_lattice(nrows, ncols, wrap_around) 
+% MK_2D_LATTICE Return adjacency matrix for 4-nearest neighbor connected 2D lattice
+% G = mk_2D_lattice(nrows, ncols, wrap_around)
+% G(k1, k2) = 1 iff k1=(i1,j1) is connected to k2=(i2,j2)
+%
+% If wrap_around = 1, we use toroidal boundary conditions (default = 0)
+%
+% Nodes are assumed numbered as in the following 3x3 lattice
+%   1 4 7
+%   2 5 8 
+%   3 6 9
+%
+% e.g., G = mk_2D_lattice(3, 3, 0) returns
+%   0 1 0 1 0 0 0 0 0 
+%   1 0 1 0 1 0 0 0 0 
+%   0 1 0 0 0 1 0 0 0 
+%   1 0 0 0 1 0 1 0 0 
+%   0 1 0 1 0 1 0 1 0 
+%   0 0 1 0 1 0 0 0 1 
+%   0 0 0 1 0 0 0 1 0 
+%   0 0 0 0 1 0 1 0 1 
+%   0 0 0 0 0 1 0 1 0 
+% so find(G(5,:)) = [2 4 6 8] 
+% but find(G(1,:)) = [2 4]
+%
+% Using wrap around, G = mk_2D_lattice(3, 3, 1), we get
+%   0 1 1 1 0 0 1 0 0 
+%   1 0 1 0 1 0 0 1 0 
+%   1 1 0 0 0 1 0 0 1 
+%   1 0 0 0 1 1 1 0 0 
+%   0 1 0 1 0 1 0 1 0 
+%   0 0 1 1 1 0 0 0 1 
+%   1 0 0 1 0 0 0 1 1 
+%   0 1 0 0 1 0 1 0 1 
+%   0 0 1 0 0 1 1 1 0 
+% so find(G(5,:)) = [2 4 6 8] 
+% and find(G(1,:)) = [2 3 4 7]
+
+if nargin < 3, wrap_around = 0; end
+
+% M contains the number of each cell e.g.
+%   1 4 7
+%   2 5 8 
+%   3 6 9
+% North neighbors (assuming wrap around) are
+%   3 6 9
+%   1 4 7
+%   2 5 8
+% Without wrap around, they are
+%   1 4 7
+%   1 4 7
+%   2 5 8
+% The first row is arbitrary, since pixels at the top have no north neighbor.
+
+npixels = nrows*ncols;
+
+N = 1; E = 2; S = 3; W = 4;
+if wrap_around
+  rows{N} = [nrows 1:nrows-1]; cols{N} = 1:ncols;
+  rows{E} = 1:nrows; cols{E} = [2:ncols 1];
+  rows{S} = [2:nrows 1]; cols{S} = 1:ncols;
+  rows{W} = 1:nrows; cols{W} = [ncols 1:ncols-1];
+else
+  rows{N} = [1 1:nrows-1]; cols{N} = 1:ncols;
+  rows{E} = 1:nrows; cols{E} = [2:ncols 2];
+  rows{S} = [2:nrows 2]; cols{S} = 1:ncols;
+  rows{W} = 1:nrows; cols{W} = [1 1:ncols-1];
+end
+
+M = reshape(1:npixels, [nrows ncols]);
+nbrs = cell(1, 4);
+for i=1:4
+  nbrs{i} = M(rows{i}, cols{i});
+end
+
+
+G = zeros(npixels, npixels);
+if wrap_around
+  for i=1:4
+    if 0
+      % naive
+      for p=1:npixels
+	G(p, nbrs{i}(p)) = 1;
+      end
+    else
+      % vectorized
+      ndx2 = sub2ind([npixels npixels], 1:npixels, nbrs{i}(:)');
+      G(ndx2) = 1;
+    end
+  end
+else
+  i = N;
+  mask = ones(nrows, ncols);
+  mask(1,:) = 0; % pixels in row 1 have no nbr to the north
+  ndx = find(mask);
+  ndx2 = sub2ind([npixels npixels], ndx, nbrs{i}(ndx));
+  G(ndx2) = 1;
+
+  i = E;
+  mask = ones(nrows, ncols);
+  mask(:,ncols) = 0;
+  ndx = find(mask);
+  ndx2 = sub2ind([npixels npixels], ndx, nbrs{i}(ndx));
+  G(ndx2) = 1;
+
+  i = S;
+  mask = ones(nrows, ncols);
+  mask(nrows,:)=0;
+  ndx = find(mask);
+  ndx2 = sub2ind([npixels npixels], ndx, nbrs{i}(ndx));
+  G(ndx2) = 1;
+  
+  i = W;
+  mask = ones(nrows, ncols);
+  mask(:,1)=0;
+  ndx = find(mask);
+  ndx2 = sub2ind([npixels npixels], ndx, nbrs{i}(ndx));
+  G(ndx2) = 1;
+end
+
+G = setdiag(G, 0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/CVS/.svn/all-wcprops	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/Old/CVS
+END
+Repository
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/Old/CVS/Repository
+END
+Root
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/Old/CVS/Root
+END
+Entries
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svnroot/!svn/ver/1127/matlabtoolboxes/FullBNT-1.0.4/graph/Old/CVS/Entries
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/CVS/.svn/entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,130 @@
+10
+
+dir
+7329
+https://parrot.dcs.qmul.ac.uk/svnroot/matlabtoolboxes/FullBNT-1.0.4/graph/Old/CVS
+https://parrot.dcs.qmul.ac.uk/svnroot
+
+
+
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+214cd2a9-030a-0410-b9a1-da4e402363b6
+
+Repository
+file
+
+
+
+
+2010-04-08T01:08:23.000000Z
+aab97ca5bf8f143ca69f54882751ca4c
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+18
+
+Root
+file
+
+
+
+
+2010-04-08T01:08:23.000000Z
+a49432e9bea5bbd5666443ab187b4558
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+51
+
+Entries
+file
+
+
+
+
+2010-04-08T01:08:23.000000Z
+d4180170bdf4e29332494da6ad177c67
+2008-11-18T12:42:45.431389Z
+1127
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+260
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/CVS/.svn/prop-base/Entries.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/CVS/.svn/prop-base/Repository.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/CVS/.svn/prop-base/Root.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/CVS/.svn/text-base/Entries.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/best_first_elim_order.m/1.1.1.1/Mon Aug 29 17:44:02 2005//
+/dag_to_jtree.m/1.1.1.1/Mon Aug 29 17:44:02 2005//
+/dfs.m/1.1.1.1/Mon Aug 29 17:44:02 2005//
+/dsep_test.m/1.1.1.1/Mon Aug 29 17:44:02 2005//
+/mk_2D_lattice_slow.m/1.1.1.1/Mon Aug 29 17:44:02 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/CVS/.svn/text-base/Repository.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/graph/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/CVS/.svn/text-base/Root.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/best_first_elim_order.m/1.1.1.1/Mon Aug 29 17:44:02 2005//
+/dag_to_jtree.m/1.1.1.1/Mon Aug 29 17:44:02 2005//
+/dfs.m/1.1.1.1/Mon Aug 29 17:44:02 2005//
+/dsep_test.m/1.1.1.1/Mon Aug 29 17:44:02 2005//
+/mk_2D_lattice_slow.m/1.1.1.1/Mon Aug 29 17:44:02 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/graph/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/best_first_elim_order.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+function order = best_first_elim_order(G, node_sizes, stage)
+% BEST_FIRST_ELIM_ORDER Greedily search for an optimal elimination order.
+% order = best_first_elim_order(moral_graph, node_sizes)
+%
+% Find an order in which to eliminate nodes from the graph in such a way as to try and minimize the
+% weight of the resulting triangulated graph.  The weight of a graph is the sum of the weights of each
+% of its cliques; the weight of a clique is the product of the weights of each of its members; the
+% weight of a node is the number of values it can take on.
+%
+% Since this is an NP-hard problem, we use the following greedy heuristic:
+% at each step, eliminate that node which will result in the addition of the least
+% number of fill-in edges, breaking ties by choosing the node that induces the lighest clique.
+% For details, see
+% - Kjaerulff, "Triangulation of graphs -- algorithms giving small total state space",
+%      Univ. Aalborg tech report, 1990 (www.cs.auc.dk/~uk)
+% - C. Huang and A. Darwiche, "Inference in Belief Networks: A procedural guide",
+%      Intl. J. Approx. Reasoning, 11, 1994
+%
+
+% Warning: This code is pretty old and could probably be made faster.
+
+n = length(G);
+if nargin < 3, stage = { 1:n }; end % no constraints
+
+% For long DBNs, it may be useful to eliminate all the nodes in slice t before slice t+1.
+% This will ensure that the jtree has a repeating structure (at least away from both edges).
+% This is why we have stages.
+% See the discussion of splicing jtrees on p68 of
+% Geoff Zweig's PhD thesis, Dept. Comp. Sci., UC Berkeley, 1998.
+% This constraint can increase the clique size significantly.
+
+MG = G; % copy the original graph
+uneliminated = ones(1,n);
+order = zeros(1,n);
+t = 1;  % Counts which time slice we are on        
+for i=1:n
+  U = find(uneliminated);
+  valid = myintersect(U, stage{t});
+  % Choose the best node from the set of valid candidates
+  score1 = zeros(1,length(valid));
+  score2 = zeros(1,length(valid));
+  for j=1:length(valid)
+    k = valid(j);
+    ns = myintersect(neighbors(G, k), U);
+    l = length(ns);
+    M = MG(ns,ns);
+    score1(j) = l^2 - sum(M(:)); % num. added edges
+    score2(j) = prod(node_sizes([k ns])); % weight of clique
+  end
+  j1s = find(score1==min(score1));
+  j = j1s(argmin(score2(j1s)));
+  k = valid(j);
+  uneliminated(k) = 0;
+  order(i) = k;
+  ns = myintersect(neighbors(G, k), U);
+  if ~isempty(ns)
+    G(ns,ns) = 1;
+    G = setdiag(G,0);
+  end
+  if ~any(logical(uneliminated(stage{t}))) % are we allowed to the next slice?
+    t = t + 1;
+  end   
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/dag_to_jtree.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,55 @@
+function [jtree, root, cliques, B, w, elim_order, moral_edges, fill_in_edges, strong] = ...
+    dag_to_jtree(dag, node_sizes, partial_order, stages, clusters)
+% DAG_TO_JTREE Moralize and triangulate a DAG, and make a junction tree from its cliques.
+% [jtree, root, cliques, B, w, elim_order, moral_edges, fill_in_edges, strong] = ...
+%    dag_to_jtree(dag, node_sizes, partial_order, stages, clusters)
+%
+% Input:
+% dag(i,j) 
+% jtree(i,j) = 1 iff there is an arc between clique i and clique j 
+% root = the root clique
+% cliques{i} = the nodes in clique i
+% B(i,j) = 1 iff node j occurs in clique i
+% w(i) = weight of clique i
+
+N = length(bnet.dag);
+if nargin < 2, obs_nodes = []; end
+if nargin < 3, stages = { 1:N }; end
+if nargin < 4, clusters = {}; end
+
+[MG, moral_edges]  = moralize(bnet.dag);
+
+% Add extra arcs between nodes in each cluster to ensure they occur in the same clique
+for i=1:length(clusters)
+  c = clusters{i};
+  MG(c,c) = 1;
+end
+MG = setdiag(MG, 0);
+
+% Find an optimal elimination ordering (NP-hard problem!)
+ns = bnet.node_sizes(:);
+ns(obs_nodes) = 1; % observed nodes have only 1 possible value
+partial_order = determine_elim_constraints(bnet, obs_nodes);
+
+if isempty(partial_order)
+  strong = 0;
+  elim_order = best_first_elim_order(MG, ns, stages);
+else
+  strong = 1;
+  elim_order = strong_elim_order(MG, ns, partial_order);
+end
+
+[MTG, cliques, fill_in_edges]  = triangulate(MG, elim_order);
+
+% Connect the cliques up into a jtree,
+[jtree, root, B, w] = cliques_to_jtree(cliques, ns);
+
+if 0
+  disp('testing dag to jtree');
+  % Find the cliques containing each node, and check they form a connected subtree
+  clqs_con_node = cell(1,N);
+  for i=1:N
+    clqs_con_node{i} = find(B(:,i))';
+  end
+  check_jtree_property(clqs_con_node, jtree);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/dfs.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,84 @@
+function [d, pre, post, height, cycle, pred] = dfs(adj_mat, start, directed)
+% DFS Perform a depth-first search of the graph starting from 'start'.
+% [d, pre, post, height, cycle, pred] = dfs(adj_mat, start, directed)
+%
+% d(i) is the time at which node i is first discovered.
+% pre is a listing of the nodes in the order in which they are first encountered (opened).
+% post is a listing of the nodes in the order in which they are last encountered (closed).
+% A node is last encountered once we have explored all of its neighbors.
+% If the graph is directed, i's neighbors are its children.
+% If the graph is a tree, preorder is parents before children, and
+% postorder is children before parents.
+% For a DAG, topological order = reverse(postorder).
+% height(i) is the height (distance) of node i from the start.
+% 'cycle' is true iff a (directed) cycle is found.
+% pred(i) is the parent of i in the dfs tree rooted at start.
+% See Cormen, Leiserson and Rivest, "An intro. to algorithms" 1994, p478.
+
+% We can detect undirected cycles by checking if we are about to visit a node n which we have
+% already visited. To detect *directed* cycles, we need to know if n has been closed or is still open.
+% For example (where arcs are directed down)
+%   1    2
+%   \   /
+%     3
+% Assume we visit 1, 3 and then 2 in order. The fact that a child of 2 (namely, 3) has
+% already been visited is okay, because 3 has been closed.
+% The algorithms in Aho, Hopcroft and Ullman, and Sedgewick, do not detect directed cycles.
+
+n = length(adj_mat);
+
+global white gray black
+white = 0; gray = 1; black = 2;
+
+color = white*ones(1,n);
+d = zeros(1,n);
+height = zeros(1,n);
+pred = zeros(1,n);
+pre = [];
+post = [];
+cycle = 0;
+global count
+count = 0;
+h = 0;
+[d, pre, post, height, cycle, color, pred] = ...
+    dfs2(adj_mat, start, directed, h, d, pre, post, height, cycle, color, pred);
+
+
+
+%%%%%%%%%%
+
+function [d, pre, post, height, cycle, color, pred] = ...
+    dfs2(adj_mat, i, directed, h, d, pre, post, height, cycle, color, pred)
+
+global count
+global white gray black
+
+color(i) = gray;
+count = count + 1;
+d(i) = count;
+pre = [pre i];
+height(i) = h;
+if directed
+  ns = children(adj_mat, i);
+else
+  ns = neighbors(adj_mat, i);
+end
+for j=1:length(ns)
+  n=ns(j);
+  if ~directed & n==pred(i) % don't go back up the edge you just came down
+    % continue
+  else
+    if color(n) == gray % going back to a non-closed vertex via a new edge
+      %fprintf(1, 'cycle from %d to %d\n', i, n);
+      cycle = 1;
+    end
+    if color(n) == white % not visited n before
+      pred(n)=i;
+      [d, pre, post, height, cycle, color, pred] = ...
+	  dfs2(adj_mat, n, directed, h+1, d, pre, post, height, cycle, color, pred);
+    end
+  end
+end
+color(i) = black;
+post = [post i];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/dsep_test.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+
+% Cowell et al p72
+G = zeros(10);
+G(1,2)=1;
+G(2,3)=1;
+G(3,7)=1;
+G(4,[5 8])=1;
+G(5,6)=1;
+G(6,7)=1;
+G(7,[9 10])=1;
+G(8,9)=1;
+
+dsep(1, 4, [5 7], G)
+dsep(1, 4, [7], G)
+dsep(1, 4, [10 5], G)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/Old/mk_2D_lattice_slow.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,121 @@
+function G = mk_2D_lattice(nrows, ncols, wrap_around) 
+% MK_2D_LATTICE Return adjacency matrix for 4-nearest neighbor connected 2D lattice
+% G = mk_2D_lattice(nrows, ncols, wrap_around)
+% G(k1, k2) = 1 iff k1=(i1,j1) is connected to k2=(i2,j2)
+%
+% If wrap_around = 1, we use toroidal boundary conditions (default = 0)
+%
+% Nodes are assumed numbered as in the following 3x3 lattice
+%   1 4 7
+%   2 5 8 
+%   3 6 9
+%
+% e.g., G = mk_2D_lattice(3, 3, 0) returns
+%   0 1 0 1 0 0 0 0 0 
+%   1 0 1 0 1 0 0 0 0 
+%   0 1 0 0 0 1 0 0 0 
+%   1 0 0 0 1 0 1 0 0 
+%   0 1 0 1 0 1 0 1 0 
+%   0 0 1 0 1 0 0 0 1 
+%   0 0 0 1 0 0 0 1 0 
+%   0 0 0 0 1 0 1 0 1 
+%   0 0 0 0 0 1 0 1 0 
+% so find(G(5,:)) = [2 4 6 8] 
+% but find(G(1,:)) = [2 4]
+%
+% Using wrap around, G = mk_2D_lattice(3, 3, 1), we get
+%   0 1 1 1 0 0 1 0 0 
+%   1 0 1 0 1 0 0 1 0 
+%   1 1 0 0 0 1 0 0 1 
+%   1 0 0 0 1 1 1 0 0 
+%   0 1 0 1 0 1 0 1 0 
+%   0 0 1 1 1 0 0 0 1 
+%   1 0 0 1 0 0 0 1 1 
+%   0 1 0 0 1 0 1 0 1 
+%   0 0 1 0 0 1 1 1 0 
+% so find(G(5,:)) = [2 4 6 8] 
+% and find(G(1,:)) = [2 3 4 7]
+
+if nargin < 3, wrap_around = 0; end
+
+% M contains the number of each cell e.g.
+%   1 4 7
+%   2 5 8 
+%   3 6 9
+% North neighbors (assuming wrap around) are
+%   3 6 9
+%   1 4 7
+%   2 5 8
+% Without wrap around, they are
+%   1 4 7
+%   1 4 7
+%   2 5 8
+% The first row is arbitrary, since pixels at the top have no north neighbor.
+
+npixels = nrows*ncols;
+
+N = 1; E = 2; S = 3; W = 4;
+if wrap_around
+  rows{N} = [nrows 1:nrows-1]; cols{N} = 1:ncols;
+  rows{E} = 1:nrows; cols{E} = [2:ncols 1];
+  rows{S} = [2:nrows 1]; cols{S} = 1:ncols;
+  rows{W} = 1:nrows; cols{W} = [ncols 1:ncols-1];
+else
+  rows{N} = [1 1:nrows-1]; cols{N} = 1:ncols;
+  rows{E} = 1:nrows; cols{E} = [2:ncols 2];
+  rows{S} = [2:nrows 2]; cols{S} = 1:ncols;
+  rows{W} = 1:nrows; cols{W} = [1 1:ncols-1];
+end
+
+M = reshape(1:npixels, [nrows ncols]);
+nbrs = cell(1, 4);
+for i=1:4
+  nbrs{i} = M(rows{i}, cols{i});
+end
+
+
+G = zeros(npixels, npixels);
+if wrap_around
+  for i=1:4
+    if 0
+      % naive
+      for p=1:npixels
+	G(p, nbrs{i}(p)) = 1;
+      end
+    else
+      % vectorized
+      ndx2 = sub2ind([npixels npixels], 1:npixels, nbrs{i}(:)');
+      G(ndx2) = 1;
+    end
+  end
+else
+  i = N;
+  mask = ones(nrows, ncols);
+  mask(1,:) = 0; % pixels in row 1 have no nbr to the north
+  ndx = find(mask);
+  ndx2 = sub2ind([npixels npixels], ndx, nbrs{i}(ndx));
+  G(ndx2) = 1;
+
+  i = E;
+  mask = ones(nrows, ncols);
+  mask(:,ncols) = 0;
+  ndx = find(mask);
+  ndx2 = sub2ind([npixels npixels], ndx, nbrs{i}(ndx));
+  G(ndx2) = 1;
+
+  i = S;
+  mask = ones(nrows, ncols);
+  mask(nrows,:)=0;
+  ndx = find(mask);
+  ndx2 = sub2ind([npixels npixels], ndx, nbrs{i}(ndx));
+  G(ndx2) = 1;
+  
+  i = W;
+  mask = ones(nrows, ncols);
+  mask(:,1)=0;
+  ndx = find(mask);
+  ndx2 = sub2ind([npixels npixels], ndx, nbrs{i}(ndx));
+  G(ndx2) = 1;
+end
+
+G = setdiag(G, 0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/README.txt	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+Graph theory toolbox.
+All functions written by Kevin Murphy (1998) unless otherwise noted.
+The latest version is available from http://www.ai.mit.edu/~murphyk/Software/index.html
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/acyclic.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+function b = acyclic(adj_mat, directed)
+% ACYCLIC Returns true iff the graph has no (directed) cycles.
+% b = acyclic(adj_mat, directed)
+
+adj_mat = double(adj_mat);
+if nargin < 2, directed = 1; end
+
+% e.g., G =
+% 1 -> 3
+%      |
+%      v
+% 2 <- 4   
+% In this case, 1->2 in the transitive closure, but 1 cannot get to itself.
+% If G was undirected, 1 could get to itself, but this graph is not cyclic.
+% So we cannot use the closure test in the undirected case.
+
+if directed
+  R = reachability_graph(adj_mat);
+  b = ~any(diag(R)==1);
+else
+  [d, pre, post, cycle] = dfs(adj_mat,[],directed);
+  b = ~cycle;    
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/assignEdgeNums.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function [edge_id, nedges] = assignEdgeNums(adj_mat)
+% give each edge a unique number
+% we number (i,j) for j>i first, in row, column order.
+% Then we number the reverse links
+
+nnodes = length(adj_mat);
+edge_id = zeros(nnodes);
+e = 1;
+for i=1:nnodes
+  for j=i+1:nnodes
+    if adj_mat(i,j)
+      edge_id(i,j) = e;
+      e = e+1;
+    end
+  end
+end
+
+nedges = e-1;
+tmp = edge_id;
+ndx = find(tmp);
+tmp(ndx) = tmp(ndx)+nedges;
+edge_id = edge_id + triu(tmp)';
+
+
+if 0
+ndx = find(adj_mat);
+nedges = length(ndx);
+nnodes = length(adj_mat);
+edge_id = zeros(1, nnodes*nnodes);
+edge_id(ndx) = 1:nedges; 
+edge_id = reshape(edge_id, nnodes, nnodes);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/best_first_elim_order.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,68 @@
+function order = best_first_elim_order(G, node_sizes, stage)
+% BEST_FIRST_ELIM_ORDER Greedily search for an optimal elimination order.
+% order = best_first_elim_order(moral_graph, node_sizes)
+%
+% Find an order in which to eliminate nodes from the graph in such a way as to try and minimize the
+% weight of the resulting triangulated graph.  The weight of a graph is the sum of the weights of each
+% of its cliques; the weight of a clique is the product of the weights of each of its members; the
+% weight of a node is the number of values it can take on.
+%
+% Since this is an NP-hard problem, we use the following greedy heuristic:
+% at each step, eliminate that node which will result in the addition of the least
+% number of fill-in edges, breaking ties by choosing the node that induces the lighest clique.
+% For details, see
+% - Kjaerulff, "Triangulation of graphs -- algorithms giving small total state space",
+%      Univ. Aalborg tech report, 1990 (www.cs.auc.dk/~uk)
+% - C. Huang and A. Darwiche, "Inference in Belief Networks: A procedural guide",
+%      Intl. J. Approx. Reasoning, 11, 1994
+%
+
+% Warning: This code is pretty old and could probably be made faster.
+
+n = length(G);
+if nargin < 3, stage = { 1:n }; end % no constraints
+
+% For long DBNs, it may be useful to eliminate all the nodes in slice t before slice t+1.
+% This will ensure that the jtree has a repeating structure (at least away from both edges).
+% This is why we have stages.
+% See the discussion of splicing jtrees on p68 of
+% Geoff Zweig's PhD thesis, Dept. Comp. Sci., UC Berkeley, 1998.
+% This constraint can increase the clique size significantly.
+
+MG = G; % copy the original graph
+uneliminated = ones(1,n);
+order = zeros(1,n);
+t = 1;  % Counts which time slice we are on        
+for i=1:n
+  U = find(uneliminated);
+  valid = myintersect(U, stage{t});
+  % Choose the best node from the set of valid candidates
+  min_fill = zeros(1,length(valid));
+  min_weight = zeros(1,length(valid));
+  for j=1:length(valid)
+    k = valid(j);
+    nbrs = myintersect(neighbors(G, k), U);
+    l = length(nbrs);
+    M = MG(nbrs,nbrs);
+    min_fill(j) = l^2 - sum(M(:)); % num. added edges
+    min_weight(j) = prod(node_sizes([k nbrs])); % weight of clique
+  end
+  lightest_nbrs = find(min_weight==min(min_weight));
+  % break ties using min-fill heuristic
+  best_nbr_ndx = argmin(min_fill(lightest_nbrs));
+  j = lightest_nbrs(best_nbr_ndx); % we will eliminate the j'th element of valid
+  %j1s = find(score1==min(score1));
+  %j = j1s(argmin(score2(j1s)));
+  k = valid(j);
+  uneliminated(k) = 0;
+  order(i) = k;
+  ns = myintersect(neighbors(G, k), U);
+  if ~isempty(ns)
+    G(ns,ns) = 1;
+    G = setdiag(G,0);
+  end
+  if ~any(logical(uneliminated(stage{t}))) % are we allowed to the next slice?
+    t = t + 1;
+  end   
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/check_jtree_property.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function check_jtree_property(cliques_containing_node, jtree)
+% CHECK_JTREE_PROPERTY Raise an error if the graph does not satisfy the join tree property.
+% check_jtree_property(cliques_containing_node, jtree_adj_mat)
+%
+% The join tree property says:
+% For each node n in the dag, compute the node-induced subgraph G by looking at all the cliques
+% that contain n, and make sure G forms a connected graph. 
+% This ensures that local propagation leads to global consistency.
+
+num_bn_nodes = length(cliques_containing_node);
+directed = 0;
+for i=1:num_bn_nodes
+  cs = cliques_containing_node{i};
+  G = jtree(cs,cs);
+  if ~connected_graph(G, directed)
+    error(['node ' num2str(i) ' violates jtree property']);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/check_triangulated.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,34 @@
+function [triangulated, order] = check_triangulated(G)
+% CHECK_TRIANGULATED Return 1 if G is a triangulated (chordal) graph, 0 otherwise.
+% [triangulated, order] = check_triangulated(G)
+% 
+% A numbering alpha is perfect if Nbrs(alpha(i)) intersect {alpha(1)...alpha(i-1)} is complete.
+% A graph is triangulated iff it has a perfect numbering.
+% The Maximum Cardinality Search algorithm will create such a perfect numbering if possible.
+% See Golumbic, "Algorithmic Graph Theory and Perfect Graphs", Cambridge Univ. Press, 1985, p85.
+% or Castillo, Gutierrez and Hadi, "Expert systems and probabilistic network models", Springer 1997, p134.
+
+
+G = setdiag(G, 1);
+n = length(G);
+order = zeros(1,n);
+triangulated = 1;
+numbered = [1];
+order(1) = 1;
+for i=2:n
+  U = mysetdiff(1:n, numbered); % unnumbered nodes
+  score = zeros(1, length(U));
+  for ui=1:length(U)
+    u = U(ui);
+    score(ui) = length(myintersect(neighbors(G, u), numbered));
+  end
+  u = U(argmax(score));
+  numbered = [numbered u];
+  order(i) = u;
+  nns = myintersect(neighbors(G,u), order(1:i-1)); % numbered neighbors
+  if ~isequal(G(nns,nns), ones(length(nns))) % ~complete(G(nns,nns))
+    triangulated = 0;
+    break;
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/children.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function cs = children(adj_mat, i, t)
+% CHILDREN Return the indices of a node's children in sorted order
+% c = children(adj_mat, i, t)
+%
+% t is an optional argument: if present, dag is assumed to be a 2-slice DBN
+
+if nargin < 3 
+  cs = find(adj_mat(i,:));
+else
+  if t==1
+    cs = find(adj_mat(i,:));
+  else
+    ss = length(adj_mat)/2;
+    j = i+ss;
+    cs = find(adj_mat(j,:)) + (t-2)*ss;
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/cliques_to_jtree.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+function [jtree, root, B, w] = cliques_to_jtree(cliques, ns)
+% MK_JTREE Make an optimal junction tree.
+% [jtree, root, B, w] = mk_jtree(cliques, ns)
+% 
+% A junction tree is a tree that satisfies the jtree property, which says:
+% for each pair of cliques U,V with intersection S, all cliques on the path between U and V
+% contain S. (This ensures that local propagation leads to global consistency.)
+%
+% We can create a junction tree by computing the maximal spanning tree of the junction graph.
+% (The junction graph connects all cliques, and the weight of an edge (i,j) is
+% |C(i) intersect C(j)|, where C(i) is the i'th clique.)
+%
+% The best jtree is the maximal spanning tree which minimizes the sum of the costs on each edge,
+% where cost(i,j) = w(C(i)) + w(C(j)), and w(C) is the weight of clique C,
+% which is the total number of values C can take on.
+%
+% For details, see
+%  - Jensen and Jensen, "Optimal Junction Trees", UAI 94.
+%
+% Input:
+%  cliques{i} = nodes in clique i
+%  ns(i) = number of values node i can take on
+% Output:
+%  jtree(i,j) = 1 iff cliques i and j aer connected
+%  root = the clique that should be used as root
+%  B(i,j) = 1 iff node j occurs in clique i
+%  w(i) = weight of clique i
+
+
+
+num_cliques = length(cliques);
+w = zeros(num_cliques, 1); 
+B = sparse(num_cliques, 1);
+for i=1:num_cliques
+  B(i, cliques{i}) = 1;
+  w(i) = prod(ns(cliques{i}));
+end
+
+
+% C1(i,j) = length(intersect(cliques{i}, cliques{j})); 
+% The length of the intersection of two sets is the dot product of their bit vector representation.
+C1 = B*B';
+C1 = setdiag(C1, 0);
+
+% C2(i,j) = w(i) + w(j)
+num_cliques = length(w);
+W = repmat(w, 1, num_cliques);
+C2 = W + W';
+C2 = setdiag(C2, 0);
+
+jtree = sparse(minimum_spanning_tree(-C1, C2)); % Using -C1 gives *maximum* spanning tree
+
+% The root is arbitrary, but since the first pass is towards the root,
+% we would like this to correspond to going forward in time in a DBN.
+root = num_cliques;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/cliques_to_strong_jtree.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,114 @@
+function [jtree, root, cliques, B, w] = mk_strong_jtree(cliques, ns, elim_order, MTG)
+% MK_SRONG_JTREE Make a strong junction tree.
+% [jtree, root, cliques, B, w] = mk_strong_jtree(cliques, ns, elim_order, MTG)
+%
+% Here is a definition of a strong jtree from Jensen et al. 1994:
+% "A junction tree is said to be strong if it has at least one distinguished clique R,
+% called a strong root, s.t. for each pair (C1,C2) of adjacent cliques in the tree,
+% with C1 closer to R than C2, there exists and ordering of [the nodes below] C2
+% that respects [the partial order] and with the vertices of the separator C1 intersect C2
+% preceeding the vertices [below C2] of C2 \ C1."
+%          
+% For details, see
+% - Jensen, Jensen and Dittmer, "From influence diagrams to junction trees", UAI 94.
+%
+% MTG is the moralized, triangulated graph.
+% elim_order is the elimination ordering used to compute MTG.
+
+
+% Warning: this is a very naive implementation of the algorithm in Jensen et al.
+
+n = length(elim_order);
+alpha(elim_order) = n:-1:1;
+% alpha(u) = i if we eliminate u at step n-i+1
+% i.e., vertices with higher alpha numbers are eliminated before vertices with lower numbers.
+% e.g., from the Jensen et al paper
+% node a=1 eliminated at step 6, so alpha(a)=16-6+1=11.
+% alpha = [11 1 2 10 9 3 4 7 5 8 13 12 6 16 15 14]
+
+
+% We sort the cliques in order of increasing index. The index of a clique C is defined as follows.
+% Let lower = {u | alpha(u) < alpha(v)}, and
+% let v in C be the highest-numbered vertex s.t. the vertices in W = lower intersect C
+% have a common neighbor u in U, where U = lower \ C.
+% If such a v exists, define index(C) = alpha(v), otherwise, index(C) = 1.
+% Intuitively, index(C) is the step in the elimination process at which C disappears.
+
+num_cliques = length(cliques);
+index = zeros(1, num_cliques);
+for c = 1:num_cliques
+  C = cliques{c};
+  highest_num = -inf;
+  for vi = 1:length(C)
+    v = C(vi);
+    lower = find(alpha < alpha(v));
+    W = myintersect(lower, C);
+    U = mysetdiff(lower, C);
+    found = 0;
+    for ui=1:length(U)
+      u = U(ui);
+      if mysubset(W, neighbors(MTG, u))
+	found = 1;
+	break;
+      end
+    end
+    if found
+      if alpha(v) > highest_num
+	highest_num = alpha(v);
+      end
+    end
+  end
+  if highest_num == -inf
+    index(c) = 1;
+  else
+    index(c) = highest_num;
+  end
+end
+
+
+% Permute the cliques so that they are ordered according to index
+[dummy, clique_order] = sort(index);
+cliques = cliques(clique_order);
+
+w = zeros(num_cliques, 1); 
+B = sparse(num_cliques, 1);
+for i=1:num_cliques
+  B(i, cliques{i}) = 1;
+  w(i) = prod(ns(cliques{i}));
+end
+
+% Pearl p113 suggests ordering the cliques by rank of the highest vertex in each clique.
+% However, this will only work if we use maximum cardinality search.
+
+
+% Join up the cliques so that they satisfy the Running Intersection Property.
+% This states that, for all k > 1, S(k) subseteq C(j) for some j < k, where
+% S(k) = C(k) intersect (union_{i=1}^{k-1} C(i))
+jtree = sparse(num_cliques, num_cliques);
+for k=2:num_cliques
+  S = [];
+  for i=1:k-1
+    S = myunion(S, cliques{i});
+  end
+  S = myintersect(S, cliques{k});
+  found = 0;
+  for j=1:k-1
+    if mysubset(S, cliques{j})
+      found = 1;
+      break;
+    end
+  end
+  if ~found
+    disp(['RIP is violated for clique ' num2str(k)]);
+  end
+  jtree(k,j)=1;
+  jtree(j,k)=1;
+end
+
+% Pearl p113 suggests connecting Ci to a predecessor Cj (j < i) sharing
+% the highest number of vertices with Ci (i.e., the heaviest i-j edge
+% in the jgraph). However, this will only work if we use maximum cardinality search.
+
+root = 1;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/connected_graph.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function b = connected(adj_mat, directed)
+%
+% b = connected(adj_mat).
+% Returns true iff the graph is connected.
+
+n = length(adj_mat);
+start = 1;
+[d, pre] = dfs(adj_mat, start, directed);
+b = (length(pre) == n);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/dag_to_essential_graph.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,112 @@
+
+function [eg] = dag_to_essential_graph(dag)
+cpdag = dag_to_cpdag(dag);
+eg = dag + dag .* (cpdag + cpdag');
+
+return;
+
+
+
+
+% Coverts a DAG into Essential Graph where edges are coded by 2 and 3, 2 is
+% directed edge and 3 is bidirected edge and is at one (the same as the original DAG) of the two
+% symetrical places. 
+
+% Is implemented by the algorithm of Max Chickering in D.M.Chickering (1995). 
+% A transformational characterization of equivalent Bayesian network structures. 
+% In Proceedings of Eleventh Conference on Uncertainty in Artificial Intelligence, Montreal, QU,
+% pages 87-98. Morgan Kaufmann 
+% http://research.microsoft.com/~dmax/publications/uai95.pdf 
+
+% Implemented by Tomas Kocka, AAU.
+
+function [eg] = dag_to_essential_graph(dagx)
+
+%print_dag(dagx); % Just checking input
+
+order = topological_sort(dagx); % get the topological order of nodes and their number
+
+% fprintf('the topological order is: %d',order);
+% fprintf('\n');
+
+[nx,ny] = size(dagx); % gets the number of nodes, note that nx == ny
+[I,J] = find(dagx); % finds all nonzero elements in the adjacency matrix, i.e. arcs in the DAG - however we will overwrite it in a special order
+% we will sort the arcs from lowest possible y and highest possible x, arcs are x->y
+e = 1;
+for y = 1:ny
+    for x = nx:-1:1
+        %fprintf('x %d ',order(x)); fprintf('y %d ',order(y));
+        if dagx(order(x),order(y)) == 1 
+            I(e) = order(x);
+            J(e) = order(y);
+            e = e + 1;
+            %fprintf('x order %d',x);
+            %fprintf('y order %d',y);
+            %fprintf('\n');
+        end
+    end
+end
+
+
+% fprintf('the arcs are: %d',I);
+% fprintf('\n');
+% fprintf('the arcs are: %d',J);
+% fprintf('\n');
+
+
+% Now we have to decide which arcs are part of the essential graph and
+% which are undirected edges in the essential graph.
+% Undecided arc in the DAG are 1, directed in EG are 2 and undirected in EG
+% are 3.
+
+
+for e = 1:length(I)
+    if dagx(I(e),J(e)) == 1
+        cont = true;
+        for w = 1:nx 
+            if dagx(w,I(e)) == 2
+                if dagx(w,J(e)) ~= 0
+                    dagx(w,J(e)) = 2;
+                else
+                    for ww = 1:nx
+                        if dagx(ww,J(e)) ~= 0
+                           dagx(ww,J(e)) = 2;
+                        end
+                    end % and now skip the rest and start with another arc from the list
+                    w = nx;
+                    cont = false;
+                end
+            end
+        end
+        if cont
+           exists = false;
+           for z = 1:nx
+               %fprintf('test %d',dagx(z,J(e)));
+               if dagx(z,J(e)) ~= 0 & z ~= I(e) & dagx(z,I(e)) == 0
+                  exists = true; 
+                  for ww = 1:nx
+                        if dagx(ww,J(e)) == 1
+                           dagx(ww,J(e)) = 2;
+                        end 
+                  end
+               end
+           end
+           if ~ exists
+               for ww = 1:nx
+                   if dagx(ww,J(e)) == 1
+                      dagx(ww,J(e)) = 3;
+                   end 
+               end  
+           end
+        end
+    end            
+end
+
+%print_dag(dagx); % Just checking output
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/dfs.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,91 @@
+function [d, pre, post, cycle, f, pred] = dfs(adj_mat, start, directed)
+% DFS Perform a depth-first search of the graph starting from 'start'.
+% [d, pre, post, cycle, f, pred] = dfs(adj_mat, start, directed)
+%
+% Input:
+% adj_mat(i,j)=1 iff i is connected to j.
+% start is the root vertex of the dfs tree; if [], all nodes are searched
+% directed = 1 if the graph is directed
+%
+% Output:
+% d(i) is the time at which node i is first discovered.
+% pre is a list of the nodes in the order in which they are first encountered (opened).
+% post is a list of the nodes in the order in which they are last encountered (closed).
+% 'cycle' is true iff a (directed) cycle is found.
+% f(i) is the time at which node i is finished.
+% pred(i) is the predecessor of i in the dfs tree.
+%
+% If the graph is a tree, preorder is parents before children,
+% and postorder is children before parents.
+% For a DAG, topological order = reverse(postorder).
+%
+% See Cormen, Leiserson and Rivest, "An intro. to algorithms" 1994, p478.
+
+n = length(adj_mat);
+
+global white gray black color
+white = 0; gray = 1; black = 2;
+color = white*ones(1,n);
+
+global time_stamp
+time_stamp = 0;
+
+global d f
+d = zeros(1,n);
+f = zeros(1,n);
+
+global pred
+pred = zeros(1,n);
+
+global cycle
+cycle = 0;
+
+global pre post
+pre = [];
+post = [];
+
+if ~isempty(start)
+  dfs_visit(start, adj_mat, directed);
+end
+for u=1:n
+  if color(u)==white
+    dfs_visit(u, adj_mat, directed);
+  end
+end
+
+
+%%%%%%%%%%
+
+function dfs_visit(u, adj_mat, directed)
+
+global white gray black color time_stamp d f pred cycle  pre post
+
+pre = [pre u];
+color(u) = gray;
+time_stamp = time_stamp + 1;
+d(u) = time_stamp;
+if directed
+  ns = children(adj_mat, u);
+else
+  ns = neighbors(adj_mat, u);
+  ns = setdiff(ns, pred(u)); % don't go back to visit the guy who called you!
+end
+for v=ns(:)'
+  %fprintf('u=%d, v=%d, color(v)=%d\n', u, v, color(v))
+  switch color(v)
+    case white, % not visited v before (tree edge)
+     pred(v)=u;
+     dfs_visit(v, adj_mat, directed);
+   case gray, % back edge - v has been visited, but is still open
+    cycle = 1;
+    %fprintf('cycle: back edge from v=%d to u=%d\n', v, u);
+   case black, % v has been visited, but is closed
+    % no-op
+  end
+end
+color(u) = black;
+post = [post u];
+time_stamp = time_stamp + 1;
+f(u) = time_stamp;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/dfs_test.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+% Do the example in fig 23.4 p479 of Cormen, Leiserson and Rivest (1994)
+
+u = 1; v = 2; w = 3; x = 4; y = 5; z = 6;
+n = 6;
+dag=zeros(n,n);
+dag(u,[v x])=1;
+dag(v,y)=1;
+dag(w,[y z])=1;
+dag(x,v)=1;
+dag(y,x)=1;
+dag(z,z)=1;
+
+[d, pre, post, cycle, f, pred] = dfs(dag, [], 1);
+assert(isequal(d, [1 2 9 4 3 10]))
+assert(isequal(f, [8 7 12 5 6 11])
+assert(cycle)
+
+% Now give it an undirected cyclic graph
+G = mk_2D_lattice(2,2,0);
+% 1 - 3
+% |   |
+% 2 - 4
+[d, pre, post, cycle, f, pred] = dfs(G, [], 0);
+% d = [1 2 4 3]
+assert(cycle)
+
+% Now break the cycle
+G(1,2)=0; G(2,1)=0;
+[d, pre, post, cycle, f, pred] = dfs(G, [], 0);
+assert(~cycle)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/dijkstra.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,112 @@
+function [D,P] = dijk(A,s,t)
+%DIJK Shortest paths from nodes 's' to nodes 't' using Dijkstra algorithm.
+% [D,p] = dijk(A,s,t)
+%     A = n x n node-node weighted adjacency matrix of arc lengths
+%         (Note: A(i,j) = 0   => Arc (i,j) does not exist;
+%                A(i,j) = NaN => Arc (i,j) exists with 0 weight)
+%     s = FROM node indices
+%       = [] (default), paths from all nodes
+%     t = TO node indices
+%       = [] (default), paths to all nodes
+%     D = |s| x |t| matrix of shortest path distances from 's' to 't'
+%       = [D(i,j)], where D(i,j) = distance from node 'i' to node 'j' 
+%     P = |s| x n matrix of predecessor indices, where P(i,j) is the
+%         index of the predecessor to node 'j' on the path from 's(i)' to 'j'
+%         (use PRED2PATH to convert P to paths)
+%       = path from 's' to 't', if |s| = |t| = 1
+%
+%  (If A is a triangular matrix, then computationally intensive node
+%   selection step not needed since graph is acyclic (triangularity is a 
+%   sufficient, but not a necessary, condition for a graph to be acyclic)
+%   and A can have non-negative elements)
+%
+%  (If |s| >> |t|, then DIJK is faster if DIJK(A',t,s) used, where D is now
+%   transposed and P now represents successor indices)
+%
+%  (Based on Fig. 4.6 in Ahuja, Magnanti, and Orlin, Network Flows,
+%   Prentice-Hall, 1993, p. 109.)
+
+% Copyright (c) 1998-2001 by Michael G. Kay
+% Matlog Version 5 22-Aug-2001
+
+% Input Error Checking ******************************************************
+error(nargchk(1,3,nargin));
+
+[n,cA] = size(A);
+
+if nargin < 2 | isempty(s), s = (1:n)'; else s = s(:); end
+if nargin < 3 | isempty(t), t = (1:n)'; else t = t(:); end
+
+if ~any(any(tril(A) ~= 0))       % A is upper triangular
+   isAcyclic = 1;
+elseif ~any(any(triu(A) ~= 0))   % A is lower triangular
+   isAcyclic = 2;
+else                             % Graph may not be acyclic
+   isAcyclic = 0;
+end
+
+if n ~= cA
+   error('A must be a square matrix');
+elseif ~isAcyclic & any(any(A < 0))
+   error('A must be non-negative');
+elseif any(s < 1 | s > n)
+   error(['''s'' must be an integer between 1 and ',num2str(n)]);
+elseif any(t < 1 | t > n)
+   error(['''t'' must be an integer between 1 and ',num2str(n)]);
+end
+% End (Input Error Checking) ************************************************
+
+A = A';    % Use transpose to speed-up FIND for sparse A
+
+D = zeros(length(s),length(t));
+if nargout > 1, P = zeros(length(s),n); end
+
+for i = 1:length(s)
+   j = s(i);
+   
+   Di = Inf*ones(n,1); Di(j) = 0;
+   
+   isLab = logical(zeros(length(t),1));
+   if isAcyclic ==  1
+      nLab = j - 1;
+   elseif isAcyclic == 2
+      nLab = n - j;
+   else
+      nLab = 0;
+      UnLab = 1:n;
+      isUnLab = logical(ones(n,1));
+   end
+   
+   while nLab < n & ~all(isLab)
+      if isAcyclic
+         Dj = Di(j);
+      else	% Node selection
+         [Dj,jj] = min(Di(isUnLab));
+         j = UnLab(jj);
+         UnLab(jj) = [];
+         isUnLab(j) = 0;
+      end
+      
+      nLab = nLab + 1;
+      if length(t) < n, isLab = isLab | (j == t); end
+      
+      [jA,kA,Aj] = find(A(:,j));
+      Aj(isnan(Aj)) = 0;
+            
+      if isempty(Aj), Dk = Inf; else Dk = Dj + Aj; end
+      
+      if nargout > 1, P(i,jA(Dk < Di(jA))) = j; end
+      Di(jA) = min(Di(jA),Dk);
+      
+      if isAcyclic == 1       % Increment node index for upper triangular A
+         j = j + 1;
+      elseif isAcyclic == 2   % Decrement node index for lower triangular A
+         j = j - 1;
+      end
+   end
+   D(i,:) = Di(t)';
+end
+
+if nargout > 1 & length(s) == 1 & length(t) == 1
+   P = pred2path(P,s,t);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function f = family(A,i,t)
+% FAMILY Return the indices of parents and self in sorted order
+% f = family(dag,i,t)
+%
+% t is an optional argument: if present, dag is assumed to be a 2-slice DBN
+
+if nargin < 3 
+  f = [parents(A,i) i];
+else
+  if t == 1
+    f = [parents(A,i) i];
+  else
+    ss = length(A)/2;
+    j = i+ss;
+    f = [parents(A,j) j] + (t-2)*ss;
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/graph_separated.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function sep = graph_separated(G, X, Y, S)
+
+G2 = G;
+G2(S,:) = 0;
+G2(:,S) = 0;
+conn = reachability_graph(G2);
+conn2 = conn(X,Y);
+sep = all(conn2(:)==0);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/graph_to_jtree.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function [jtree, root, cliques, B, w, elim_order] = graph_to_jtree(MG, ns, partial_order, stages, clusters)
+% GRAPH_TO_JTREE Triangulate a graph and make a junction tree from its cliques.
+% [jtree, root, cliques, B, w, elim_order] = ...
+%    graph_to_jtree(graph, node_sizes, partial_order, stages, clusters)
+%
+% INPUT:
+% graph(i,j) = 1 iff there is an edge between i,j
+% node_weights(i) = num discrete values node i can take on [1 if observed]
+% partial_order = {} if no constraints on elimination ordering
+% stages{i} = nodes that must be eliminated at i'th stage (if porder is empty)
+% clusters{i} = list of nodes that must get connected together in the moral graph
+%
+% OUTPUT:
+% jtree(i,j) = 1 iff there is an arc between clique i and clique j 
+% root = the root clique
+% cliques{i} = the nodes in clique i
+% B(i,j) = 1 iff node j occurs in clique i
+% w(i) = weight of clique i
+
+N = length(MG);
+
+if nargin >= 5
+  % Add extra arcs between nodes in each cluster to ensure they occur in the same clique
+  for i=1:length(clusters)
+    c = clusters{i};
+    MG(c,c) = 1;
+  end
+end
+MG = setdiag(MG, 0);
+
+% Find an optimal elimination ordering (NP-hard problem!)
+if nargin < 4
+  stages = {1:N};
+end
+if nargin < 3
+  partial_order = {};
+end
+if isempty(partial_order)
+  strong = 0;
+  elim_order = best_first_elim_order(MG, ns, stages);
+else
+  strong = 1;
+  elim_order = strong_elim_order(MG, ns, partial_order);
+end
+
+[MTG, cliques, fill_in_edges]  = triangulate(MG, elim_order);
+
+% Connect the cliques up into a jtree,
+[jtree, root, B, w] = cliques_to_jtree(cliques, ns);
+
+if 0
+  disp('testing dag to jtree');
+  % Find the cliques containing each node, and check they form a connected subtree
+  clqs_con_node = cell(1,N);
+  for i=1:N
+    clqs_con_node{i} = find(B(:,i))';
+  end
+  check_jtree_property(clqs_con_node, jtree);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/min_subtree_con_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,60 @@
+function [subtree, nroot_node] = min_subtree_con_nodes(jtree, root, nodes)
+%min_subtree_con_nodes get the minimum subtree of tree which contains the nodes
+
+if isempty(jtree) | isempty(nodes)
+    subtree = [];
+    nroot_node = [];
+    return;
+end
+
+rnodes = min_subtree_nodes(jtree, nodes);
+nea_node = nearest_node(jtree, root, nodes);
+node_num = length(jtree);
+subtree = zeros(node_num);
+subtree(rnodes, rnodes) = jtree(rnodes, rnodes);
+nroot_node = nea_node;
+
+
+function rnodes = min_subtree_nodes(tree, nodes)
+rnodes = [];
+if isempty(tree) | isempty(nodes)
+    return
+end
+
+rnodes = nodes(1);
+newnodes = neighbors(tree, nodes(1));
+while ~mysubset(nodes, rnodes)
+    swapnodes = newnodes;
+    newnodes = [];
+    added = 0;
+    for i=1:length(swapnodes)
+        inode = swapnodes(i);
+        tnodes = myunion(inode, rnodes);
+        if mysubset(nodes, tnodes)
+            added = 1;
+            break;
+        end
+        nns = neighbors(tree, inode);
+        add_nodes = mysetdiff(nns, tnodes);
+        newnodes = myunion(newnodes, add_nodes);
+    end
+    if added
+        rnodes = tnodes;
+    else
+        rnodes = myunion(rnodes, newnodes);
+    end
+end
+
+function nea_node = nearest_node(tree, inode, nodes)
+if myismember(inode, nodes)
+    nea_node = inode;
+    return;
+end
+cs = children(tree, inode);
+for i = 1:length(cs)
+    n = cs(i);
+    nea_node = nearest_node(tree, n, nodes);
+end
+    
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/minimum_spanning_tree.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,51 @@
+function A = minimum_spanning_tree(C1, C2)
+%
+% Find the minimum spanning tree using Prim's algorithm.
+% C1(i,j) is the primary cost of connecting i to j.
+% C2(i,j) is the (optional) secondary cost of connecting i to j, used to break ties.
+% We assume that absent edges have 0 cost.
+% To find the maximum spanning tree, used -1*C.
+% See Aho, Hopcroft & Ullman 1983, "Data structures and algorithms", p 237.
+
+% Prim's is O(V^2). Kruskal's algorithm is O(E log E) and hence is more efficient
+% for sparse graphs, but is implemented in terms of a priority queue.
+
+% We partition the nodes into those in U and those not in U.
+% closest(i) is the vertex in U that is closest to i in V-U.
+% lowcost(i) is the cost of the edge (i, closest(i)), or infinity is i has been used.
+% In Aho, they say C(i,j) should be "some appropriate large value" if the edge is missing.
+% We set it to infinity.
+% However, since lowcost is initialized from C, we must distinguish absent edges from used nodes.
+
+n = length(C1);
+if nargin==1, C2 = zeros(n); end
+A = zeros(n);
+
+closest = ones(1,n);
+used = zeros(1,n); % contains the members of U
+used(1) = 1; % start with node 1
+C1(find(C1==0))=inf;
+C2(find(C2==0))=inf;
+lowcost1 = C1(1,:);
+lowcost2 = C2(1,:);
+
+for i=2:n
+  ks = find(lowcost1==min(lowcost1));
+  k = ks(argmin(lowcost2(ks)));
+  A(k, closest(k)) = 1;
+  A(closest(k), k) = 1;
+  lowcost1(k) = inf;
+  lowcost2(k) = inf;
+  used(k) = 1;
+  NU = find(used==0);
+  for ji=1:length(NU)
+    for j=NU(ji)
+      if C1(k,j) < lowcost1(j)
+	lowcost1(j) = C1(k,j);
+	lowcost2(j) = C2(k,j);
+	closest(j) = k;
+      end
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/minspan.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,56 @@
+function [t,nk] = minspan(IJC)
+%MINSPAN Minimum weight spanning tree using Kruskal algorithm.
+%[t,nk] = minspan(IJC)
+%   IJC = n x 3 matrix arc list [i j c] of arc heads, tails, and costs
+%     t = n-element logical vector, where 
+%         t(i) = 1, if IJC(i,:) arc in spanning tree
+%         t(i) = k, if IJC(i,:) arc in component k of forest
+%    nk = number of components
+
+% Copyright (c) 1998-2001 by Michael G. Kay
+% Matlog Version 5 22-Aug-2001
+
+% Input Error Checking ******************************************************
+[n,cIJC] = size(IJC);
+if cIJC ~= 3
+   error('''IJC'' must be a 3-column matrix.')
+elseif n < 1
+   error('''IJC'' must have at least one row.')
+elseif any(IJC(:,1) < 1) | any(any(~isint(IJC(:,[1 2]))))
+   error('Invalid arc index in IJC.')
+end
+% End (Input Error Checking) ************************************************
+
+i = IJC(:,1); j = abs(IJC(:,2));
+m = max(max([i j]));
+
+sidxIJ = argsort(IJC(:,3));
+i = i(sidxIJ); j = j(sidxIJ);
+
+t = logical(zeros(n,1));
+k = 1;            % Current arc
+nt = 0;           % Number of arcs in spanning tree
+v = (1:m)';       % Arc labels
+
+while nt < m - 1 & k <= n
+   if (v(i(k)) ~= v(j(k)))
+      v(v==v(j(k))) = v(i(k));
+      t(k) = 1;
+      nt = nt + 1;
+   end
+   k = k + 1;
+end
+
+idxIJ = invperm(sidxIJ);
+t = t(idxIJ); i = i(idxIJ); j = j(idxIJ);
+
+c = unique(v(unique([i; j])));   % Unique labels of arc vertices
+nk = length(c);
+if ~any(t), nk = 0; end          % Self-loop not a component
+
+if nk > 1
+   for k = 1:nk
+      t(t~=0 & v(i)==c(k)) = k;  % Relabel to consecutive component numbers
+   end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_2D_lattice.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function G = mk_2D_lattice(nrows, ncols, con)
+% MK_2D_LATTICE Return adjacency matrix for nearest neighbor connected 2D lattice
+% G = mk_2D_lattice(nrows, ncols, con)
+% G(k1, k2) = 1 iff k1=(i1,j1) is a neighbor of k2=(i2,j2) 
+% (Two pixels are neighbors if their Euclidean distance is less than r.)
+% Default connectivity = 4.
+%
+% WE ASSUME NO WRAP AROUND. 
+%
+% This is the neighborhood as a function of con:
+%
+%  con=4,r=1  con=8,r=sqrt(2)   con=12,r=2   con=24,r=sqrt(8)
+%  nn            2nd order        4th order
+%                                  x         x x x x x
+%    x          x x x            x x x       x x x x x
+%  x o x        x o x          x x o x x     x x o x x
+%    x          x x x            x x x       x x x x x
+%                                  x         x x x x x
+%
+% Examples:
+% Consider a 3x4 grid
+%  1  4  7  10
+%  2  5  8  11
+%  3  6  9  12
+%  
+% 4-connected:
+% G=mk_2D_lattice(3,4,4);
+% find(G(1,:)) = [2 4]
+% find(G(5,:)) = [2 4 6 8]
+%
+% 8-connected:
+% G=mk_2D_lattice(3,4,8);
+% find(G(1,:)) = [2 4 5]
+% find(G(5,:)) = [1 2 3 4 6 7 8 9]
+
+% meshgrid trick due to Temu Gautama (temu@neuro.kuleuven.ac.be)
+
+if nargin < 3, con = 4; end
+
+switch con,
+ case 4, r = 1;
+ case 8, r = sqrt(2);
+ case 12, r = 2;
+ case 24, r = sqrt(8);
+ otherwise, error(['unrecognized connectivity ' num2str(con)])
+end
+
+
+npixels = nrows*ncols;
+
+[x y]=meshgrid(1:ncols, 1:nrows);
+M = [x(:) y(:)];
+M1 = repmat(reshape(M',[1 2 npixels]),[npixels 1 1]);
+M2 = repmat(M,[1 1 npixels]);
+%D = squeeze(sum(abs(M1-M2),2)); % Manhattan distance
+M3 = M1-M2;
+D = sqrt(squeeze(M3(:,1,:)) .^2 + squeeze(M3(:,2,:)) .^2); % Euclidean distance
+G = reshape(D <= r,npixels,npixels);
+G = setdiag(G, 0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_2D_lattice_slow.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,135 @@
+function G = mk_2D_lattice_slow(nrows, ncols, wrap_around) 
+% MK_2D_LATTICE Return adjacency matrix for 4-nearest neighbor connected 2D lattice
+% G = mk_2D_lattice(nrows, ncols, wrap_around)
+% G(k1, k2) = 1 iff k1=(i1,j1) is connected to k2=(i2,j2)
+%
+% If wrap_around = 1, we use toroidal boundary conditions (default = 0)
+%
+% Nodes are assumed numbered as in the following 3x3 lattice
+%   1 4 7
+%   2 5 8 
+%   3 6 9
+%
+% e.g., G = mk_2D_lattice(3, 3, 0) returns
+%   0 1 0 1 0 0 0 0 0 
+%   1 0 1 0 1 0 0 0 0 
+%   0 1 0 0 0 1 0 0 0 
+%   1 0 0 0 1 0 1 0 0 
+%   0 1 0 1 0 1 0 1 0 
+%   0 0 1 0 1 0 0 0 1 
+%   0 0 0 1 0 0 0 1 0 
+%   0 0 0 0 1 0 1 0 1 
+%   0 0 0 0 0 1 0 1 0 
+% so find(G(5,:)) = [2 4 6 8] 
+% but find(G(1,:)) = [2 4]
+%
+% Using wrap around, G = mk_2D_lattice(3, 3, 1), we get
+%   0 1 1 1 0 0 1 0 0 
+%   1 0 1 0 1 0 0 1 0 
+%   1 1 0 0 0 1 0 0 1 
+%   1 0 0 0 1 1 1 0 0 
+%   0 1 0 1 0 1 0 1 0 
+%   0 0 1 1 1 0 0 0 1 
+%   1 0 0 1 0 0 0 1 1 
+%   0 1 0 0 1 0 1 0 1 
+%   0 0 1 0 0 1 1 1 0 
+% so find(G(5,:)) = [2 4 6 8] 
+% and find(G(1,:)) = [2 3 4 7]
+
+if nargin < 3, wrap_around = 0; end
+
+% M contains the number of each cell e.g.
+%   1 4 7
+%   2 5 8 
+%   3 6 9
+% North neighbors (assuming wrap around) are
+%   3 6 9
+%   1 4 7
+%   2 5 8
+% Without wrap around, they are
+%   1 4 7
+%   1 4 7
+%   2 5 8
+% The first row is arbitrary, since pixels at the top have no north neighbor.
+
+if nrows==1
+  G = zeros(1, ncols);
+  for i=1:ncols-1
+    G(i,i+1) = 1;
+    G(i+1,i) = 1;
+  end
+  if wrap_around
+    G(1,ncols) = 1;
+    G(ncols,1) = 1;
+  end
+  return;
+end
+
+  
+npixels = nrows*ncols;
+
+N = 1; E = 2; S = 3; W = 4;
+if wrap_around
+  rows{N} = [nrows 1:nrows-1]; cols{N} = 1:ncols;
+  rows{E} = 1:nrows; cols{E} = [2:ncols 1];
+  rows{S} = [2:nrows 1]; cols{S} = 1:ncols;
+  rows{W} = 1:nrows; cols{W} = [ncols 1:ncols-1];
+else
+  rows{N} = [1 1:nrows-1]; cols{N} = 1:ncols;
+  rows{E} = 1:nrows; cols{E} = [1 1:ncols-1];
+  rows{S} = [2:nrows nrows]; cols{S} = 1:ncols;
+  rows{W} = 1:nrows; cols{W} = [2:ncols ncols];
+end
+
+M = reshape(1:npixels, [nrows ncols]);
+nbrs = cell(1, 4);
+for i=1:4
+  nbrs{i} = M(rows{i}, cols{i});
+end
+
+
+G = zeros(npixels, npixels);
+if wrap_around
+  for i=1:4
+    if 0
+      % naive
+      for p=1:npixels
+	G(p, nbrs{i}(p)) = 1;
+      end
+    else
+      % vectorized
+      ndx2 = sub2ind([npixels npixels], 1:npixels, nbrs{i}(:)');
+      G(ndx2) = 1;
+    end
+  end
+else
+  i = N;
+  mask = ones(nrows, ncols);
+  mask(1,:) = 0; % pixels in row 1 have no nbr to the north
+  ndx = find(mask);
+  ndx2 = sub2ind([npixels npixels], ndx, nbrs{i}(ndx));
+  G(ndx2) = 1;
+
+  i = E;
+  mask = ones(nrows, ncols);
+  mask(:,ncols) = 0;
+  ndx = find(mask);
+  ndx2 = sub2ind([npixels npixels], ndx, nbrs{i}(ndx));
+  G(ndx2) = 1;
+
+  i = S;
+  mask = ones(nrows, ncols);
+  mask(nrows,:)=0;
+  ndx = find(mask);
+  ndx2 = sub2ind([npixels npixels], ndx, nbrs{i}(ndx));
+  G(ndx2) = 1;
+  
+  i = W;
+  mask = ones(nrows, ncols);
+  mask(:,1)=0;
+  ndx = find(mask);
+  ndx2 = sub2ind([npixels npixels], ndx, nbrs{i}(ndx));
+  G(ndx2) = 1;
+end
+
+G = setdiag(G, 0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_adj_mat.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+function [A, names] = mk_adj_mat(connections, names, topological)
+% MK_ADJ_MAT Make a directed adjacency matrix from a list of connections between named nodes.
+%
+% A = mk_adj_mat(connections, name)
+% This is best explaine by an example:
+%   names = {'WetGrass', 'Sprinkler', 'Cloudy', 'Rain'}; 
+%   connections = {'Cloudy', 'Sprinkler'; 'Cloudy', 'Rain'; 'Sprinkler', 'WetGrass'; 'Rain', 'WetGrass'}; 
+% adds the arcs C -> S, C -> R, S -> W, R -> W. Node 1 is W, 2 is S, 3 is C, 4 is R.
+%
+% [A, names] = mk_adj_mat(connections, name, 1)
+% The last argument of 1 indicates that we should topologically sort the nodes (parents before children).
+% In the example, the numbering becomes: node 1 is C, 2 is R, 3 is S, 4 is W
+% and the return value of names gets permuted to {'Cloudy', 'Rain', 'Sprinkler', 'WetGrass'}.
+% Note that topological sorting the graph is only possible if it has no directed cycles.
+
+if nargin < 3, topological = 0; end
+  
+n=length(names);
+A=zeros(n);
+[nr nc] = size(connections);
+for r=1:nr
+  from = strmatch(connections{r,1}, names, 'exact');
+  assert(~isempty(from));
+  to = strmatch(connections{r,2}, names, 'exact');
+  assert(~isempty(to));
+  %fprintf(1, 'from %s %d to %s %d\n', connections{r,1}, from, connections{r,2}, to);
+  A(from,to) = 1;
+end
+
+if topological
+  order = topological_sort(A); 
+  A = A(order, order); 
+  names = names(order); 
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_adjmat_chain.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function G = mk_adjmat_chain(T)
+% MK_DAG_CHAIN Make adjacency matrix for bi-directional Markov chain of  T nodes
+% function G = mk_dag_chain(T)
+%
+% G(t,t+1) = 1 for all t<T
+
+G = diag(ones(1,T-1),1) + diag(ones(1,T-1),-1);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_all_dags.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+function Gs = mk_all_dags(N, order)
+% MK_ALL_DAGS generate all DAGs on N variables
+% G = mk_all_dags(N)
+%
+% G = mk_all_dags(N, order) only generates DAGs in which node i has parents from 
+% nodes in order(1:i-1). Default: order=[] (no constraints).
+%
+% G{i} is the i'th dag
+%
+% Note: the number of DAGs is super-exponential in N, so don't call this with N > 4.
+
+if nargin < 2, order = []; end
+
+use_file = 0;
+
+global BNT_HOME
+fname = sprintf('%s/DAGS%d.mat', BNT_HOME, N);
+if use_file & exist(fname, 'file')
+  S = load(fname, '-mat');
+  fprintf('loading %s\n', fname);
+  Gs = S.Gs;
+  return;
+end
+
+m = 2^(N*N);
+ind = ind2subv(2*ones(1,N^2), 1:m);
+Gs = {};
+j = 1;
+directed = 1;
+for i=1:m
+  dag = reshape(ind(i,:)-1, N, N);
+  if acyclic(dag, directed)
+    out_of_order = 0;
+    if ~isempty(order)
+      for k=1:N-1
+	if any(dag(order(k+1:end), k))
+	  out_of_order = 1;
+	  break;
+	end
+      end
+    end
+    if ~out_of_order
+      Gs{j} = dag;
+      j = j + 1;
+    end
+  end
+end
+
+if use_file
+  disp(['mk_all_dags: saving to ' fname '!']);
+  save(fname, 'Gs');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_nbrs_of_dag.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+function [Gs, op, nodes] = mk_nbrs_of_dag(G0)
+% MK_NBRS_OF_DAG Make all DAGs that differ from G0 by a single edge deletion, addition or reversal
+% [Gs, op, nodes] = mk_nbrs_of_dag(G0)
+%
+% Gs{i} is the i'th neighbor.
+% op{i} = 'add', 'del', or 'rev' is the operation used to create the i'th neighbor.
+% nodes(i,1:2) are the head and tail of the operated-on arc.
+
+Gs = {};
+op = {};
+nodes = [];
+
+[I,J] = find(G0);
+nnbrs = 1;
+% all single edge deletions
+for e=1:length(I)
+  i = I(e); j = J(e);
+  G = G0;
+  G(i,j) = 0;
+  Gs{nnbrs} = G;
+  op{nnbrs} = 'del';
+  nodes(nnbrs, :) = [i j];
+  nnbrs = nnbrs + 1;
+end
+
+% all single edge reversals
+for e=1:length(I)
+  i = I(e); j = J(e);
+  G = G0;
+  G(i,j) = 0;
+  G(j,i) = 1;
+  if acyclic(G)
+    Gs{nnbrs} = G;
+    op{nnbrs} = 'rev';
+    nodes(nnbrs, :) = [i j];
+    nnbrs = nnbrs + 1;
+  end
+end
+
+[I,J] = find(~G0);
+% all single edge additions
+for e=1:length(I)
+  i = I(e); j = J(e);
+  if i ~= j % don't add self arcs
+    G = G0;
+    G(i,j) = 1;
+    if G(j,i)==0 % don't add i->j if j->i exists already
+      if acyclic(G)
+	Gs{nnbrs} = G;
+	op{nnbrs} = 'add';
+	nodes(nnbrs, :) = [i j];
+	nnbrs = nnbrs + 1;
+      end
+    end
+  end
+end
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_nbrs_of_digraph.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,132 @@
+function [Gs, op, nodes, A] = my_mk_nbs_of_digraph(G0,A)
+% MY_MK_NBRS_OF_DIGRAPH Make all digraphs that differ from G0 by a single edge deletion, addition or reversal, subject to acyclicity
+% [Gs, op, nodes, A] = my_mk_nbrs_of_digraph(G0,<A>)
+%
+% G0 is an adj matrix s.t. G0(i,j)=1 iff i->j in graph
+% A is the ancestor matrix for G0  (opt, creates if necessary)
+%
+% Gs(:,:,i) is the i'th neighbor
+% op{i} = 'add', 'del', or 'rev' is the operation used to create the i'th neighbor. 
+% nodes(i,1:2) are the head and tail of the operated-on arc.
+% Modified from mk_nbrs_of_digraph by Sonia Leach
+%
+% Modified by Sonia Leach Feb 02
+
+if nargin ==1, A = reachability_graph(G0');, end
+
+n = length(G0);
+[I,J] = find(G0); % I(k), J(k) is the k'th edge
+E = length(I);    % num edges present in G0
+
+
+% SINGLE EDGE DELETIONS
+% all deletions are valid wrt acyclity
+
+Grep = repmat(G0(:), 1, E); % each column is a copy of G0
+% edge_ndx(k) is the scalar location of the k'th edge 
+edge_ndx = find(G0);
+
+% edge_ndx = subv2ind([n n], [I J]); % equivalent
+% We set (ndx(k), k) to 0 for k=1:E in Grep
+ndx = subv2ind(size(Grep), [edge_ndx(:) (1:E)']);
+G1 = Grep;
+G1(ndx) = 0;
+Gdel = reshape(G1, [n n E]);
+
+
+% SINGLE EDGE REVERSALS
+
+% SML: previously Kevin had that legal structure was if
+% A(P,i)=1 for any P = { p | p in parents(j), p~=i}
+% specifically he said 
+%  "if any(A(ps,i)) then there is a path i -> parent of j -> j
+%   so reversing i->j would create a cycle"
+% Thus put in another way:
+%    for each i,j if sum(G0(:,j)' * A(:,i)) > 0, reversing i->j
+% is not legal.
+%
+% Ex. Suppose we want to check if 2->4 can be reversed in the 
+% following graph: 
+% G0 =                               A =
+%     0     0     1     0               0     0     0     0
+%     0     0     1     1               0     0     0     0
+%     0     0     0     1               1     1     0     0
+%     0     0     0     0               1     1     1     0
+% 
+% Then parents(4) = G0(:,4) = [0 1 1 0]'
+% and A(:,2) = [0 0 1 1]. Thus G0(:,4)'*A(:,2) = 1 b/c 3 is
+% an ancestor of 4 and a child of 2. Note that this works b/c
+% matrix multiplication has the effect of ANDing the two vectors 
+% and summing up the result (equiv. to the any(A(ps,i)) in kevin's code)
+%
+% So, we vectorize and check for all i,j pairs by looking for
+% 1's in L = (G0'*A)' which has L(i,j)=1 if rev(i,j) not legal
+% Note that this will give 1's where there are none in the G0
+% so we do a L=max(0, G0-L) to cancel out only the existing edges that 
+% aren't legal (subtracting where both are 1 and setting where
+% G0=0 and A=1 back to 0).
+
+L = max(0, G0-(G0'*A)');
+[IL, JL] = find(L);  % I(k), J(k) is the k'th legal edge to rev.
+EL = length(IL);
+
+
+% SML: First we have to DELETE THE EDGES WE ARE REVERSING
+% We can't use G1 w/ reversed edges already deleted (as
+% Kevin did) b/c the space of possible deletions are different 
+% now (some reverses aren't legal)
+
+Grep = repmat(G0(:), 1, EL); % each column is a copy of G0
+% edge_ndx(k) is the scalar location of the k'th edge 
+edge_ndx = subv2ind([n n], [IL JL]); 
+% We set (ndx(k), k) to 0 for k=1:E in Grep
+ndx = subv2ind(size(Grep), [edge_ndx(:) (1:EL)']);
+G1 = Grep;
+G1(ndx) = 0;
+
+% SML: Now we add in our REVERSED EDGES
+% rev_edge_ndx(k) is the scalar location of the k'th legal reversed edge
+rev_edge_ndx = subv2ind([n n], [JL IL]);
+
+% We set (rev_edge_ndx(k), k) to 1 for k=1:EL in G1
+% We have already deleted i->j in the previous step
+ndx = subv2ind(size(Grep), [rev_edge_ndx(:) (1:EL)']);
+G1(ndx) = 1;
+Grev = reshape(G1, [n n EL]);
+
+% SINGLE EDGE ADDITIONS
+
+% SML: previously Kevin had that any addition was legal if A(i,j)=0
+% however, you can not add i->j  if j is a descendent of i.
+% Thus, we create all possible additions in Gbar and then
+% subtract the descendants of each edge as possible parents
+% This means the potential parents of i (i.e. Gbar(:,i))
+% can not also be descendants if i i.e. (A(:,i)) which is accomplished
+% by subtracting (Gbar-A == 1 iff Gbar=1 & A=0)
+
+Gbar = ~G0;  % Gbar(i,j)=1 iff there is no i->j edge in G0
+Gbar = setdiag(Gbar, 0); % turn off self loops
+
+GbarL = Gbar-A;
+[IbarL, JbarL] = find(GbarL);  % I(k), J(k) is the k'th legal edge to add
+EbarL = length(IbarL);
+
+bar_edge_ndx = find(GbarL);
+
+Grep = repmat(G0(:), 1, EbarL); % each column is a copy of G0
+ndx = subv2ind(size(Grep), [bar_edge_ndx(:) (1:EbarL)']);
+Grep(ndx) = 1;
+Gadd = reshape(Grep, [n n EbarL]);
+
+
+Gs = cat(3, Gdel, Grev, Gadd);
+
+nodes = [I J;
+     IL JL;
+   IbarL JbarL];
+
+op = cell(1, E+EL+EbarL);
+op(1:E) = {'del'};
+op(E+(1:EL)) = {'rev'};
+op((E+EL+1):end) = {'add'};
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_nbrs_of_digraph_broken.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,111 @@
+function [Gs, op, nodes] = mk_nbrs_of_digraph(G0)
+% MK_NBRS_OF_DIGRAPH Make all digraphs that differ from G0 by a single edge deletion, addition or reversal
+% [Gs, op, nodes] = mk_nbrs_of_digraph(G0)
+%
+% Gs(:,:,i) is the i'th neighbor
+% op{i} = 'add', 'del', or 'rev' is the operation used to create the i'th neighbor. 
+% nodes(i,1:2) are the head and tail of the operated-on arc.
+
+debug = 0; % the vectorized version is about 3 to 10 times faster
+
+n = length(G0);
+[I,J] = find(G0); % I(k), J(k) is the k'th edge
+E = length(I); % num edges present in G0
+
+% SINGLE EDGE DELETIONS
+
+Grep = repmat(G0(:), 1, E); % each column is a copy of G0
+% edge_ndx(k) is the scalar location of the k'th edge 
+edge_ndx = find(G0);
+% edge_ndx = subv2ind([n n], [I J]); % equivalent
+% We set (ndx(k), k) to 0 for k=1:E in Grep
+ndx = subv2ind(size(Grep), [edge_ndx(:) (1:E)']);
+G1 = Grep;
+G1(ndx) = 0;
+Gdel = reshape(G1, [n n E]);
+
+
+% if debug
+% % Non-vectorized version
+% ctr = 1;
+% for e=1:E
+%   i = I(e); j = J(e);
+%   Gdel2(:,:,ctr) = G0;
+%   Gdel2(i,j,ctr) = 0;
+%   ctr = ctr + 1;
+% end
+% assert(isequal(Gdel, Gdel2));
+% end
+
+
+% SINGLE EDGE REVERSALS
+
+% rev_edge_ndx(k) is the scalar location of the k'th reversed edge
+%rev_edge_ndx = find(G0'); % different order to edge_ndx, which is bad
+rev_edge_ndx = subv2ind([n n], [J I]);
+% We set (rev_edge_ndx(k), k) to 1 for k=1:E in G1
+% We have already deleted i->j in the previous step
+ndx = subv2ind(size(Grep), [rev_edge_ndx(:) (1:E)']);
+G1(ndx) = 1;
+Grev = reshape(G1, [n n E]);
+
+% if debug
+% % Non-vectorized version
+% ctr = 1;
+% for e=1:E
+%   i = I(e); j = J(e);
+%   Grev2(:,:,ctr) = G0;
+%   Grev2(i,j,ctr) = 0;
+%   Grev2(j,i,ctr) = 1;
+%   ctr = ctr + 1;
+% end
+% assert(isequal(Grev, Grev2));
+% end
+
+
+% SINGLE EDGE ADDITIONS
+
+Gbar = ~G0; % Gbar(i,j)=1 iff there is no i->j edge in G0
+Gbar = setdiag(Gbar, 0); % turn off self loops
+[Ibar,Jbar] = find(Gbar); 
+
+bar_edge_ndx = find(Gbar);
+Ebar = length(Ibar); % num edges present in Gbar
+Grep = repmat(G0(:), 1, Ebar); % each column is a copy of G0
+ndx = subv2ind(size(Grep), [bar_edge_ndx(:) (1:Ebar)']);
+Grep(ndx) = 1;
+Gadd = reshape(Grep, [n n Ebar]);
+
+% if debug
+% % Non-vectorized version
+% ctr = 1;
+% for e=1:length(Ibar)
+%   i = Ibar(e); j = Jbar(e);
+%   Gadd2(:,:,ctr) = G0;
+%   Gadd2(i,j,ctr) = 1;
+%   ctr = ctr + 1;
+% end
+% assert(isequal(Gadd, Gadd2));
+% end
+
+
+Gs = cat(3, Gdel, Grev, Gadd);
+
+nodes = [I J;
+	 I J;
+	 Ibar Jbar];
+
+op = cell(1, E+E+Ebar);
+op(1:E) = {'del'};
+op(E+1:2*E) = {'rev'};
+op(2*E+1:end) = {'add'};
+
+
+% numeric output:
+% op(i) = 1, 2, or 3, if the i'th neighbor was created by adding, deleting or reversing an arc.
+
+ADD = 1;
+DEL = 2;
+REV = 3;
+
+%op = [repmat(DEL, 1, E) repmat(REV, 1, E) repmat(ADD, 1, Ebar)];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_nbrs_of_digraph_not_vectorized.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,53 @@
+function [Gs, op, nodes] = mk_nbrs_of_digraph2(G0)
+% MK_NBRS_OF_DIGRAPH Make all digraphs that differ from G0 by a single edge deletion, addition or reversal
+% [Gs, op, nodes] = mk_nbrs_of_digraph(G0)
+% op{i} = 'add', 'del', or 'rev' is the operation used to create the i'th neighbor.
+% nodes(i,1:2) are the head and tail of the operated-on arc.
+
+[I,J] = find(G0);
+G0bar = setdiag(~G0, 0); % exclude self loops in graph complement
+[Ibar,Jbar] = find(G0bar);
+nnbrs = 2*length(I) + length(Ibar);
+Gs = cell(1, nnbrs);
+op = cell(1, nnbrs);
+nodes = zeros(nnbrs, 2);
+
+nbr = 1;
+% all single edge deletions
+for e=1:length(I)
+  i = I(e); j = J(e);
+  G = G0;
+  G(i,j) = 0;
+  Gs{nbr} = G;
+  op{nbr} = 'del';
+  nodes(nbr, :) = [i j];
+  nbr = nbr + 1;
+end
+
+% all single edge reversals
+for e=1:length(I)
+  i = I(e); j = J(e);
+  G = G0;
+  G(i,j) = 0;
+  G(j,i) = 1;
+  Gs{nbr} = G;
+  op{nbr} = 'rev';
+  nodes(nbr, :) = [i j];
+  nbr = nbr + 1;
+end
+
+[I,J] = find(~G0);
+% all single edge additions
+for e=1:length(I)
+  i = I(e); j = J(e);
+  G = G0;
+  if i ~= j % don't add self loops
+    G(i,j) = 1;
+    Gs{nbr} = G;
+    op{nbr} = 'add';
+    nodes(nbr, :) = [i j];
+    nbr = nbr + 1;
+  end
+end
+
+assert(nnbrs == nbr-1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_rnd_dag.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,27 @@
+function [dag, order] = mk_rnd_dag(N, max_fan_in)
+% MY_MK_RND_DAG  Create a random directed acyclic graph
+%
+% [dag, order] = my_mk_rnd_dag(N, max_fan_in)
+%  max_fan_in defaults to N.
+%  order is the random topological order that was chosen
+
+% Modified by Sonia Leach 2/25/02
+
+if nargin < 2, max_fan_in = N; end
+
+order = randperm(N);
+dag = zeros(N,N);
+for i=2:N
+  j = order(i);
+  %k = sample_discrete(normalise(ones(1, min(i-1, max_fan_in))));
+  k = sample_discrete(normalise(ones(1, min(i-1, max_fan_in)+1))) - 1; % min = 0 (bug fix due to
+                                                                       % Pedrito, 7/28/04)
+  SS = order(1:i-1);          % get Set of possible parentS
+  p  = randperm(length(SS));  % permute order of set
+  dag(SS(p(1:k)),j) = 1;      % take first k in permuted order
+
+  % Kevin had:
+  %SS = subsets(order(1:i-1), k, k);
+  %p = sample_discrete(normalise(ones(1, length(SS))));
+  %dag(SS{p}, j) = 1;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_rnd_dag_given_edge_prob.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function dag = sample_dag(P)
+% SAMPLE_DAG Create a random directed acyclic graph with edge probabilities P(i,j)
+% dag = sample_dag(P)
+%
+% This uses rejection sampling to reject graphs with directed cycles.
+
+done = 0;
+directed = 1;
+iter = 1;
+while ~done
+  dag = binornd(1, P); % each edge is an indep Bernoulli (0/1) random variable
+  dag = setdiag(dag, 0);
+  done = acyclic(dag, directed);
+  iter = iter + 1
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_rooted_tree.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function [T, pre, post, cycle] = mk_rooted_tree(G, root)
+% MK_ROOTED_TREE Make a directed tree pointing away from root
+% [T, pre, post, cycle] = mk_rooted_tree(G, root)
+
+n = length(G);
+T = sparse(n,n); % not the same as T = sparse(n) !
+directed = 0;
+[d, pre, post, cycle, f, pred] = dfs(G, root, directed);
+[junk, pre2] = sort(d);
+assert(isequal(pre, pre2))
+[junk, post2] = sort(f);
+assert(isequal(post, post2));
+%[d, pre, post, cycle, f, pred] = dfs(G, [], directed);
+for i=1:length(pred)
+  if pred(i)>0
+    T(pred(i),i)=1;
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/mk_undirected.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function U = mk_undirected(G)
+
+[nr nc] = size(G);
+U = G;
+for i=1:nr
+  for j=1:nc
+    if U(i,j)==1
+      U(j,i) = 1;
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/moralize.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function [M, moral_edges] = moralize(G)
+% MORALIZE Ensure that for every child, all its parents are married, and drop directionality of edges.
+% [M, moral_edges] = moralize(G)
+
+M = G;
+n = length(M);
+for i=1:n
+  fam = family(G,i);
+  M(fam,fam)=1;
+end
+M = setdiag(M,0);
+moral_edges = sparse(triu(max(0,M-G),1));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/neighbors.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function ns = neighbors(adj_mat, i)
+% NEIGHBORS Find the parents and children of a node in a graph.
+% ns = neighbors(adj_mat, i)
+
+%ns = myunion(children(adj_mat, i), parents(adj_mat, i));
+ns = [find(adj_mat(i,:)) find(adj_mat(:,i))'];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/parents.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function ps = parents(adj_mat, i)
+% PARENTS Return the list of parents of node i
+% ps = parents(adj_mat, i)
+
+ps = find(adj_mat(:,i))';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/pred2path.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,78 @@
+function rte = pred2path(P,s,t)
+%PRED2PATH Convert predecessor indices to shortest paths from node 's' to 't'.
+%   rte = pred2path(P,s,t)
+%     P = |s| x n matrix of predecessor indices (from DIJK)
+%     s = FROM node indices
+%       = [] (default), paths from all nodes
+%     t = TO node indices
+%       = [] (default), paths to all nodes
+%   rte = |s| x |t| cell array of paths (or routes) from 's' to 't', where
+%         rte{i,j} = path from s(i) to t(j)
+%                  = [], if no path exists from s(i) to t(j)
+%
+% (Used with output of DIJK)
+
+% Copyright (c) 1998-2001 by Michael G. Kay
+% Matlog Version 5 22-Aug-2001
+
+% Input Error Checking ******************************************************
+error(nargchk(1,3,nargin));
+
+[rP,n] = size(P);
+
+if nargin < 2 | isempty(s), s = (1:n)'; else s = s(:); end
+if nargin < 3 | isempty(t), t = (1:n)'; else t = t(:); end
+
+if any(P < 0 | P > n)
+   error(['Elements of P must be integers between 1 and ',num2str(n)]);
+elseif any(s < 1 | s > n)
+   error(['''s'' must be an integer between 1 and ',num2str(n)]);
+elseif any(t < 1 | t > n)
+   error(['''t'' must be an integer between 1 and ',num2str(n)]);
+end
+% End (Input Error Checking) ************************************************
+
+rte = cell(length(s),length(t));
+
+for i = 1:length(s)
+   if rP == 1
+      si = 1;
+   else
+      si = s(i);
+      if si < 1 | si > rP
+         error('Invalid P matrix.')
+      end
+   end
+   for j = 1:length(t)
+      tj = t(j);
+      if tj == s(i)
+         r = tj;
+      elseif P(si,tj) == 0
+         r = [];
+      else
+         r = tj;
+         while tj ~= s(i)
+            if tj < 1 | tj > n
+               error('Invalid element of P matrix found.')
+            end
+            r = [P(si,tj) r];
+            tj = P(si,tj);
+         end
+      end
+      rte{i,j} = r;
+   end
+end
+
+if length(s) == 1 & length(t) == 1
+   rte = rte{:};
+end
+
+%rte = t;
+while 0%t ~= s
+   if t < 1 | t > n | round(t) ~= t
+      error('Invalid ''pred'' element found prior to reaching ''s''');
+   end
+   rte = [P(t) rte];
+   t = P(t);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/reachability_graph.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function C = reachability_graph(G)
+% REACHABILITY_GRAPH C(i,j) = 1 iff there is a path from i to j in DAG G
+% C = reachability_graph(G)
+
+if 1
+  % expm(G) = I + G + G^2 / 2! + G^3 / 3! + ...
+  M = expm(double(full(G))) - eye(length(G));
+  C = (M>0);
+else
+  % This computes C = G + G^2 + ... + G^{n-1}
+  n = length(G);
+  A = G;
+  C = zeros(n);
+  for i=1:n-1
+    C = C + A;
+    A = A * G;
+  end
+  C = (C > 0);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/scc.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+function [c,v] = scc(a,tol)
+
+%       Finds the strongly connected sets of vertices
+%                in the DI-rected G-raph of A
+%          c = 0-1 matrix displaying accessibility
+%          v = displays the equivalent classes
+%
+% v(i,j) is the j'th member of the i'th equiv class (0 padded)
+%
+% http://www.math.wsu.edu/math/faculty/tsat/matlab.html
+
+[m,n] = size(a);
+if m~=n 'Not a Square Matrix', break, end
+b=abs(a); o=ones(size(a)); x=zeros(1,n);
+msg='The Matrix is Irreducible !'; v='Connected Directed Graph !';
+if (nargin==1) tol=n*eps*norm(a,'inf'); end
+
+% Create a companion matrix
+c = b>tol*o;
+if (c==o)
+  %  msg, break
+  v = 1:length(a);
+  return
+end
+
+
+% Compute accessibility in at most n-step paths
+for k=1:n
+  for j=1:n
+    for i=1:n
+      % If index i accesses j, where can you go ?
+      if c(i,j) > 0  c(i,:) = c(i,:)+c(j,:); end
+    end
+  end
+end
+% Create a 0-1 matrix with the above information
+c>zeros(size(a)); c=ans; if (c==o) msg, break, end
+
+% Identify equivalence classes
+d=c.*c'+eye(size(a)); d>zeros(size(a)); d=ans;
+v=zeros(size(a));
+for i=1:n find(d(i,:)); ans(n)=0; v(i,:)=ans; end
+
+% Eliminate displaying of identical rows
+i=1;
+while(i<n)
+  for k=i+1:n
+    if v(k,1) == v(i,1)
+      v(k,:)=x;
+    end
+  end
+  i=i+1;
+end
+j=1;
+for i=1:n
+  if v(i,1)>0
+    h(j,:)=v(i,:);
+    j=j+1;
+  end
+end
+v=h;
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/strong_elim_order.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,75 @@
+function order = strong_elim_order(G, node_sizes, partial_order)
+% STRONG_ELIM_ORDER Find an elimination order to produce a strongly triangulated graph.
+% order = strong_elim_order(moral_graph, node_sizes, partial_order)
+% 
+% partial_order(i,j)=1 if we must marginalize i *after* j
+% (so i will be nearer the strong root).
+% e.g., if j is a decision node and i is its information set:
+%   we cannot maximize j if we have marginalized out some of i
+% e.g., if j is a continuous child and i is its discrete parent:
+%   we want to integrate out the cts nodes before the discrete ones,
+%   so that the marginal is strong.
+%
+% For details, see
+% - Jensen, Jensen and Dittmer, "From influence diagrams to junction trees", UAI 94.
+% - Lauritzen, "Propgation of probabilities, means, and variances in mixed graphical
+%   association models", JASA 87(420):1098--1108, 1992.
+%
+% On p369 of the Jensen paper, they state "the reverse of the elimination order must be some
+% extension of [the partial order] to a total order".
+% We make no attempt to find the best such total ordering, in the sense of minimizing the weight
+% of the resulting cliques.
+
+% Example from the Jensen paper:
+% Let us number the nodes in Fig 1 from top to bottom, left to right,
+% so a=1,b=2,D1=3,c=4,...,l=14,j=15,k=16.
+% The elimination ordering they propose on p370 is [14 15 16 11 12 1 4 5 10 8 13 9 7 6 3 2];
+
+if 0
+  total_order = topological_sort(partial_order);
+  order = total_order(end:-1:1); % no attempt to find an optimal constrained ordering!
+  return;
+end
+
+% The following implementation is due to Ilya Shpitser and seems to give wrong
+% results on cg1
+
+n = length(G);
+MG = G; % copy the original graph
+uneliminated = ones(1,n);
+order = zeros(1,n);
+
+for i=1:n
+  roots = [];
+  k = 1;
+  for j=1:n
+    if sum(partial_order(j,:)) == 0
+      roots(k) = j;
+      k = k + 1;
+    end
+  end
+  U = find(uneliminated);
+  valid = myintersect(U, roots);
+  % Choose the best node from the set of valid candidates
+  score1 = zeros(1,length(valid));
+  score2 = zeros(1,length(valid));
+  for j=1:length(valid)
+    k = valid(j);
+    ns = myintersect(neighbors(G, k), U);
+    l = length(ns);
+    M = MG(ns,ns);
+    score1(j) = l^2 - sum(M(:)); % num. added edges
+    score2(j) = prod(node_sizes([k ns])); % weight of clique
+  end
+  j1s = find(score1==min(score1));
+  j = j1s(argmin(score2(j1s)));
+  k = valid(j);
+  uneliminated(k) = 0;
+  order(i) = k;
+  ns = myintersect(neighbors(G, k), U);
+  if ~isempty(ns)
+    G(ns,ns) = 1;
+    G = setdiag(G,0);
+  end
+  partial_order(:,k) = 0;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/test.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+% A - B
+%     |
+% D - C - E
+
+A=1;B=2;C=3;D=4;E=5;
+dag = zeros(5,5);
+dag(A,B)=1;
+%dag(A,D)=1;
+dag(B,C)=1;
+dag(C,D)=1;
+dag(E,C)=1;
+[d, pre, post, cycle, f, pred] = dfs(dag, A, 0)
+
+[T, pre, post, cycle] = mk_rooted_tree(dag, A)
+
+%[T, pre, post, cycle] = mkRootedTree(dag, A)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/test_strong_root.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,34 @@
+function strong = test_strong_root(jtree,cliques,dnodes,root)
+% This function tests, whether root is a strong root of jtree. 
+% The following parameters are used
+% Input:
+% jtree   An matrix with two colums. jtree(i,j) == jtree(j,i) is 1 if node 
+%         i is connected with node j
+% cliques Cells which contain the nodes in each clique
+% dnodes  An array with the discrete nodes of the juntion tree.
+% root    It is tested whether root is the strong root of the junction tree
+% Output:
+% strong  The output is 1 if root is the strong root of the junction tree jtree.
+%         Please note, that the running intersection property is not tested. 
+if isempty(dnodes)
+     strong = 1;
+     return;
+end
+
+children = find(jtree(root,:)==1);
+i = 1;
+strong = 1;
+while (i <= length(children)) & (strong==1)
+     child = children(i);
+     jtree(child,root) = 0;
+     jtree(root,child) = 0;
+     sep = myintersect(cliques{child},cliques{root});
+     diff = mysetdiff(cliques{child},cliques{root});
+     if (mysubset(sep,dnodes) | isempty(myintersect(diff,dnodes)))
+         strong = test_strong_root(jtree,cliques,dnodes,child);
+     else
+         strong = 0;
+     end;
+     i = i+1;
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/topological_sort.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function order = topological_sort(A)
+% TOPOLOGICAL_SORT Return the nodes in topological order (parents before children).
+% order = topological_sort(adj_mat)
+
+n = length(A);
+indeg = zeros(1,n);
+zero_indeg = []; % a stack of nodes with no parents
+for i=1:n
+  indeg(i) = length(parents(A,i));
+  if indeg(i)==0
+    zero_indeg = [i zero_indeg];
+  end
+end
+
+t=1;
+order = zeros(1,n);
+while ~isempty(zero_indeg)
+  v = zero_indeg(1); % pop v
+  zero_indeg = zero_indeg(2:end);
+  order(t) = v;
+  t = t + 1;
+  cs = children(A, v);
+  for j=1:length(cs)
+    c = cs(j);
+    indeg(c) = indeg(c) - 1;
+    if indeg(c) == 0
+      zero_indeg = [c zero_indeg]; % push c 
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/trees.txt	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,168 @@
+
+% make undirected adjacency matrix of graph/tree
+% e.g.,
+%  1 
+% / \
+% 2  3
+T = zeros(3,3);
+T(1,2) = 1; T(2,1)=1;
+T(1,3)=1; T(3,1) = 1;
+
+root = 1;
+[T, preorder, postorder] =  mk_rooted_tree(T, root);
+
+% bottom up message passing leaves to root
+for n=postorder(:)'
+  for p	= parents(T, n)
+     % p is parent of n
+   end
+end
+
+% top down, root to leaves
+for n=preorder(:)'
+  for c= children(T,n)
+    % c is child of n
+  end
+end
+
+
+%%%%%%%%%%%%%
+
+function ps = parents(adj_mat, i)
+% PARENTS Return the list of parents of node i
+% ps = parents(adj_mat, i)
+
+ps = find(adj_mat(:,i))';
+
+
+%%%%%%%%%%%%
+
+function cs = children(adj_mat, i, t)
+% CHILDREN Return the indices of a node's children in sorted order
+% c = children(adj_mat, i, t)
+%
+% t is an optional argument: if present, dag is assumed to be a 2-slice DBN
+
+if nargin < 3 
+  cs = find(adj_mat(i,:));
+else
+  if t==1
+    cs = find(adj_mat(i,:));
+  else
+    ss = length(adj_mat)/2;
+    j = i+ss;
+    cs = find(adj_mat(j,:)) + (t-2)*ss;
+  end
+end
+
+%%%%%%%%%%%
+
+function [T, pre, post, cycle] = mk_rooted_tree(G, root)
+% MK_ROOTED_TREE Make a directed, rooted tree out of an undirected tree.
+% [T, pre, post, cycle] = mk_rooted_tree(G, root)
+
+n = length(G);
+T = sparse(n,n); % not the same as T = sparse(n) !
+directed = 0;
+[d, pre, post, cycle, f, pred] = dfs(G, root, directed);
+for i=1:length(pred)
+  if pred(i)>0
+    T(pred(i),i)=1;
+  end
+end
+
+
+%%%%%%%%%%%
+
+function [d, pre, post, cycle, f, pred] = dfs(adj_mat, start, directed)
+% DFS Perform a depth-first search of the graph starting from 'start'.
+% [d, pre, post, cycle, f, pred] = dfs(adj_mat, start, directed)
+%
+% Input:
+% adj_mat(i,j)=1 iff i is connected to j.
+% start is the root vertex of the dfs tree; if [], all nodes are searched
+% directed = 1 if the graph is directed
+%
+% Output:
+% d(i) is the time at which node i is first discovered.
+% pre is a list of the nodes in the order in which they are first encountered (opened).
+% post is a list of the nodes in the order in which they are last encountered (closed).
+% 'cycle' is true iff a (directed) cycle is found.
+% f(i) is the time at which node i is finished.
+% pred(i) is the predecessor of i in the dfs tree.
+%
+% If the graph is a tree, preorder is parents before children,
+% and postorder is children before parents.
+% For a DAG, topological order = reverse(postorder).
+%
+% See Cormen, Leiserson and Rivest, "An intro. to algorithms" 1994, p478.
+
+n = length(adj_mat);
+
+global white gray black color
+white = 0; gray = 1; black = 2;
+color = white*ones(1,n);
+
+global time_stamp
+time_stamp = 0;
+
+global d f
+d = zeros(1,n);
+f = zeros(1,n);
+
+global pred
+pred = zeros(1,n);
+
+global cycle
+cycle = 0;
+
+global pre post
+pre = [];
+post = [];
+
+if ~isempty(start)
+  dfs_visit(start, adj_mat, directed);
+else
+  for u=1:n
+    if color(u)==white
+      dfs_visit(u, adj_mat, directed);
+    end
+  end
+end
+
+
+%%%%%%%%%%
+
+function dfs_visit(u, adj_mat, directed)
+
+global white gray black color time_stamp d f pred cycle  pre post
+
+pre = [pre u];
+color(u) = gray;
+time_stamp = time_stamp + 1;
+d(u) = time_stamp;
+if directed
+  ns = children(adj_mat, u);
+else
+  ns = neighbors(adj_mat, u);
+  ns = mysetdiff(ns, pred(u)); % don't go back to visit the guy who called you!
+end
+for v=ns(:)'
+  %fprintf('u=%d, v=%d, color(v)=%d\n', u, v, color(v))
+  switch color(v)
+    case white, % not visited v before (tree edge)
+     pred(v)=u;
+     dfs_visit(v, adj_mat, directed);
+   case gray, % back edge - v has been visited, but is still open
+    cycle = 1;
+    %fprintf('cycle: back edge from v=%d to u=%d\n', v, u);
+   case black, % v has been visited, but is closed
+    % no-op
+  end
+end
+color(u) = black;
+post = [post u];
+time_stamp = time_stamp + 1;
+f(u) = time_stamp;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/triangulate.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,159 @@
+/* triangulate.c written by Ilya Shpitser  */
+
+#include <stdlib.h>
+
+#ifdef UNIX
+#include "matlab.h"
+#endif
+
+#include "matrix.h"
+#include "mex.h"
+
+#include "elim.h"
+#include "map.h"
+#include "misc.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+
+  int dims [2];
+  int i, j, k, m, n;
+  long index;
+  double * G_pr;
+  double * stage_pr;
+  double * answer_G_pr, * fill_ins_pr;
+  double * matlab_clique_pr;
+  mxArray * matlab_clique;
+  Elimination e;
+  float ** adj_mat;
+  int ** order = (int **) NULL;
+  Iterator iter, iter2;
+  word w, w2;
+  int ** fill_ins;
+  Map cliques;
+  Map clique;
+  mxArray * fill_ins_mat;
+  int * nodes;
+  mxArray * full;
+
+// (original)  full = mlfFull((mxArray *) prhs[0]);
+  full = (mxArray *) mlfFull((mxArray *) prhs[0]);  // added typecasting
+  /* Obtain graph matrix information. */
+  m = mxGetM(full);
+  n = mxGetN(full);
+  G_pr = mxGetPr(full);
+
+  if(n < 1 || m < 1){
+    return;
+  }
+
+  /* Allocate and populate the log weight adjacency matrix corresponding
+     to the input graph. */
+  adj_mat = (float **) malloc(sizeof(float *) * m);
+  adj_mat[0] = (float *) malloc(sizeof(float) * m * n);
+  for(i = 1; i < m; i++){
+    adj_mat[i] = adj_mat[i - 1] + n;
+  }
+  /* We no longer have log weight info, but we have a (total) ordering on
+     the nodes already, so we do not need this information. */
+  for(i = 0; i < m; i++){
+    for(j = 0; j < n; j++){
+      index = j * m + i;
+      if(G_pr[index] > 0){
+        adj_mat[i][j] = 1;
+      } else {
+        adj_mat[i][j] = 0;
+      }
+    }
+  }
+
+  /* Convert the total elimination ordering into a partial order argument
+     for the elimination routine.  The elimination routine's purpose in this
+     mode of operation is to return cliques and fill-in edges. */
+  if(nrhs > 1){
+    order = (int **) malloc(sizeof(int *) * m);
+    order[0] = (int *) malloc(sizeof(int) * m * n);
+    for(i = 1; i < m; i++){
+      order[i] = order[i - 1] + n;
+    }
+    for(i = 0; i < m; i++){
+      for(j = 0; j < n; j++){
+        order[i][j] = 0;
+      }
+    }
+    stage_pr = mxGetPr(prhs[1]);
+    for(i = 0; i < mxGetN(prhs[1]) - 1; i++){
+      order[(int) stage_pr[i] - 1][(int) stage_pr[i + 1] - 1] = 1;
+    }
+  }
+
+  /* Find the elimination ordering. */
+  e = find_elim(n, adj_mat, order, -1);
+
+  /* Allocate memory for the answer, and set the answer. */
+  plhs[0] = mxCreateDoubleMatrix(m, n, mxREAL);
+  answer_G_pr = mxGetPr(plhs[0]);
+  cliques = get_cliques(e);
+/* 
+  dims[0] = 1;
+  dims[1] = get_size_Map(cliques);
+  plhs[1] = mxCreateCellArray(2, (const int *) dims);*/
+  plhs[1] = mxCreateCellMatrix(get_size_Map(cliques), 1);
+  fill_ins = get_fill_ins(e);
+  fill_ins_mat = mxCreateDoubleMatrix(m, n, mxREAL);
+  fill_ins_pr = mxGetPr(fill_ins_mat);
+
+  for(i = 0; i < n; i++){
+    for(j = 0; j < m; j++){
+      index = j * m + i;
+      answer_G_pr[index] = G_pr[index];
+      if(fill_ins[i][j] > 0){
+        answer_G_pr[index] = 1;
+        fill_ins_pr[index] = 1;
+      }
+    }
+  }
+  mxDestroyArray(full);
+// (original)  plhs[2] = mlfSparse(fill_ins_mat, NULL, NULL, NULL, NULL, NULL);
+  plhs[2] = (mxArray *) mlfSparse(fill_ins_mat, NULL, NULL, NULL, NULL, NULL); // added typecasting
+  mxDestroyArray(fill_ins_mat);
+  nodes = (int *) malloc(sizeof(int) * n);
+  k = 0;
+  iter = get_Iterator(cliques);
+  while(!is_empty(iter)){
+    w = next_key(iter);
+    clique = (Map) w.v;
+    matlab_clique = mxCreateDoubleMatrix(1, get_size_Map(clique), mxREAL);
+    matlab_clique_pr = mxGetPr(matlab_clique);
+    for(i = 0; i < n; i++){
+      nodes[i] = 0;
+    }
+    iter2 = get_Iterator(clique);
+    while(!is_empty(iter2)){
+      w2 = next_key(iter2);
+      nodes[w2.i] = w2.i + 1;
+    }
+    j = 0;
+    for(i = 0; i < n; i++){
+      if(nodes[i] > 0){
+        matlab_clique_pr[j++] = nodes[i];
+      }
+    }
+    mxSetCell(plhs[1], k++, matlab_clique);
+  }
+  free(nodes);
+
+  /* Finally, free the allocated memory. */
+  destroy_Elimination(e);
+  if(adj_mat){
+    if(adj_mat[0]){
+      free(adj_mat[0]);
+    }
+    free(adj_mat);
+  }
+  if(order){
+    if(order[0]){
+      free(order[0]);
+    }
+    free(order);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/triangulate.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,42 @@
+function [G, cliques, fill_ins] = triangulate(G, order)
+% TRIANGULATE Ensure G is triangulated (chordal), i.e., every cycle of length > 3 has a chord.
+% [G, cliques, fill_ins, cliques_containing_node] = triangulate(G, order)
+% 
+% cliques{i} is the i'th maximal complete subgraph of the triangulated graph.
+% fill_ins(i,j) = 1 iff we add a fill-in arc between i and j.
+%
+% To find the maximal cliques, we save each induced cluster (created by adding connecting
+% neighbors) that is not a subset of any previously saved cluster. (A cluster is a complete,
+% but not necessarily maximal, set of nodes.)
+
+MG = G;
+n = length(G);
+eliminated = zeros(1,n);
+cliques = {};
+for i=1:n
+  u = order(i);
+  U = find(~eliminated); % uneliminated
+  nodes = myintersect(neighbors(G,u), U); % look up neighbors in the partially filled-in graph
+  nodes = myunion(nodes, u); % the clique will always contain at least u
+  G(nodes,nodes) = 1; % make them all connected to each other
+  G = setdiag(G,0);  
+  eliminated(u) = 1;
+  
+  exclude = 0;
+  for c=1:length(cliques)
+    if mysubset(nodes,cliques{c}) % not maximal
+      exclude = 1;
+      break;
+    end
+  end
+  if ~exclude
+    cnum = length(cliques)+1;
+    cliques{cnum} = nodes;
+  end
+end
+
+fill_ins = sparse(triu(max(0, G - MG), 1));
+
+%assert(check_triangulated(G)); % takes 72% of the time!
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/triangulate_2Dlattice_demo.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,131 @@
+% Consider a 3x3 lattice with 4-nearest neighbor connectivity
+
+% 1 - 2 - 3
+% |   |   |
+% 4 - 5 - 6
+% |   |   |
+% 7 - 8 - 9
+
+N = 3;
+G = mk_2D_lattice(N,N,4);
+G0 = G;
+
+% Now add in the diagonal edges
+
+if 0
+% 1 - 2 - 3
+% | x | x |
+% 4 - 5 - 6
+% | x | x |
+% 7 - 8 - 9
+
+G(1,5)=1; G(5,1)=1;
+G(2,6)=1; G(6,2)=1;
+G(4,2)=1; G(2,4)=1;
+G(5,3)=1; G(3,5)=1;
+
+G(4,8)=1; G(8,4)=1;
+G(5,9)=1; G(9,5)=1;
+G(7,5)=1; G(5,7)=1;
+G(8,6)=1; G(6,8)=1;
+end
+
+% 1 - 2 - 3
+% | / | \ |
+% 4 - 5 - 6
+% | \ | / |
+% 7 - 8 - 9
+
+G(2,6)=1; G(6,2)=1;
+G(4,2)=1; G(2,4)=1;
+G(4,8)=1; G(8,4)=1;
+G(8,6)=1; G(6,8)=1;
+
+% Is this a chordal (triangulated) graph? No!
+
+assert(~check_triangulated(G))
+
+% The reason is that there is a chordless cycle around the outside nodes.
+% To see this, imagine "picking up" node 5, leaving the rest on the plane
+% (like a hoop skirt, or a tent), as shown below
+
+% 1 - 2 - 3
+% | /   \ |
+% 4       6
+% | \   / |
+% 7 - 8 - 9
+
+
+% However, if we add in the 4-6 arc, it will be chordal.
+
+G2 = G;
+G2(4,6)=1; G2(6,4)=1;
+assert(check_triangulated(G2))
+
+% Or we can add in the 2-8 arc
+G2 = G;
+G2(2,8)=1; G2(8,2)=1;
+assert(check_triangulated(G2))
+
+
+if 0
+% 4x4 lattice with cross arcs
+N=4;G0 = mk_2D_lattice(N,N,4);
+vs = [1 6;  2 5;   2 7;   3 6;   3 8;   4 7; ...
+      5 10; 6 9;   6 11;  7 10;  7 12;  8 11;...
+      9 14; 10 13; 10 15; 11 14; 11 16; 12 15];
+for i=1:size(vs,1)
+  u = vs(i,1); v= vs(i,2);
+  G0(u,v) = 1; G0(v,u) = 1;
+end
+end
+
+% Here is how we can discover which edges to fill in automatically 
+% (although possibly sub-optimally)
+weights = 2*ones(1,N*N); % all nodes are binar
+
+% fill-ins = 2-4, 2-6,  4-8, 6-8 and 4-6
+% cliques = 124, etc  and 2456  4568
+greedy_order = best_first_elim_order(G0, weights);
+[GT, cliques, fill_ins] = triangulate(G0, greedy_order)
+assert(check_triangulated(GT))
+
+
+
+greedy_order = best_first_elim_order(G, weights);
+[GT, cliques, fill_ins] = triangulate(G, greedy_order)
+assert(check_triangulated(GT))
+
+% fill-ins = [4 6]
+
+% Cliques are the overlapping squares  [1,2,4,5], [2 3 5 6], [4 5 7 8], [5 6 8 9]
+% and the following caused by the fill-in: [2 4 5 6], [4 5 6 8]
+
+% Connect the maximal cliques of the triangulate graph into a junction tree
+[jtree, root, B, clq_weights] = cliques_to_jtree(cliques, weights);
+
+% In this case, all cliques have weight 2^4 = 16
+
+
+% Now consider size of max clique as a function of grid size
+% Note: this is not necessarily the optimal triangulation
+
+% N  5  10 15 16 17 18
+% m  6  15 23 25 28 28
+Ns = [5 10 15 16 17 18]; 
+for i=1:length(Ns)
+  N = Ns(i)
+  G = mk_2D_lattice(N,N,4);
+  weights = 2*ones(1,N*N); % all nodes are binary
+  greedy_order = best_first_elim_order(G, weights); % slow!
+  [GT, cliques, fill_ins] = triangulate(G, greedy_order);
+  %assert(check_triangulated(GT))
+  [jtree, root, B, clq_weights] = cliques_to_jtree(cliques, weights);
+  m(i) = log2(max(clq_weights));
+end
+
+% plot distribution of clique sizes for fixed N
+for c=1:length(cliques)
+  l(c) = length(cliques{c});
+end
+hist(l)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/graph/triangulate_test.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+% Test the code using the dag in Fig 1 of Jensen, Jensen, Dittmer, 
+% "From influence diagrams to junction trees", UAI 94
+
+% By reverse enginering Fig 2, we infer that the following arcs should
+% be absent from the original dag:  b->d1, e->d2, f->d2, g->d4
+a=1; b=2; d1=3; c=4; d=5; e=6; f=7; g=8; d2=9; d4=10; i=11; h=12; d3=13; l=14; j=15; k=16;
+dag=zeros(16);
+dag(a,c)=1;
+%dag(b,[c d d1])=1;
+dag(b,[c d])=1;
+dag(d1,d)=1;
+dag(c,e)=1;
+dag(d,[e f])=1;
+%dag(e,[g d2])=1;
+dag(e,[g])=1;
+%dag(f,[d2 h])=1;
+dag(f,[h])=1;
+%dag(g,[d4 i])=1;
+dag(g,[i])=1;
+dag(d2,i)=1;
+dag(d4,l)=1;
+dag(i,l)=1;
+dag(h,[j k])=1;
+dag(d3,k)=1;
+
+
+[MG, moral_edges] = moralize(dag);
+MG(j,k)=1; MG(k,j)=1;  % simulate having a common utility child
+% MG now equals fig 2
+order = [l j k i h a c d d4 g d3 d2 f e d1 b];
+[MTG, cliques, fill_ins] = triangulate(MG, order);
+% MTG equals fig 3
+ns = 2*ones(1,16);
+[jtree, root, cliques2] = mk_strong_jtree(cliques, ns, order, MTG);
+jtree2 = mk_rooted_tree(jtree, root);
+% jtree2 equals fig 4, with their arrows reversed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/bnet_from_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/get_field.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/set_fields.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/update_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/@inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+/marginal_family_pot.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/observed_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/@inf_engine/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/Old/marginal_family_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+function pot = marginal_family_pot(engine, i)
+% MARGINAL_FAMILY_POT Compute the marginal on i's family and return as a potentila (inf_engine)
+% function pot = marginal_family_pot(engine,i)
+
+% This function is only called by solve_limid.
+% It requires that engine's marginal_family function return a potential.
+% This is true for jtree_inf_engine, but not for, say, jtree_ndx_inf_engine.
+% All limids must be solved using potentials,
+% but this is not true for bnets.
+
+%[m, pot] = marginal_family(engine, i);
+
+bnet = bnet_from_engine(engine);
+[m, pot] = marginal_nodes(engine, family(bnet.dag, i));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/Old/observed_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function onodes = observed_nodes(engine)
+% OBSERVED_NODES  Return nodes that are guaranteed to be observed, indep of evidence (generic inf_engine)
+% onodes = observed_nodes(engine)
+
+onodes = [];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/bnet_from_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function bnet = bnet_from_engine(engine)
+% BNET_FROM_ENGINE Return the bnet structure stored inside the engine (inf_engine)
+% bnet = bnet_from_engine(engine)
+
+bnet = engine.bnet;
+
+% We cannot write 'engine.bnet' without writing a 'subsref' function,
+% since engine is an object with private parts.
+% The bnet field should be the only thing external users of the engine should need access to.
+% We do not pass bnet as a separate argument, since it could get out of synch with the one
+% encoded inside the engine.
+       
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/get_field.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function val = get_field(engine, name)
+% GET_FIELD Get the value of a named field from a generic engine
+% val = get_field(engine, name)
+%
+% The following fields can be accessed
+%
+% bnet
+%
+% e.g., bnet = get_field(engine, 'bnet')
+
+switch name
+ case 'bnet',      val = engine.bnet;
+ otherwise,
+  error(['invalid argument name ' name]);
+end                                  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function engine = inf_engine(bnet)
+
+engine.bnet = bnet;
+engine = class(engine, 'inf_engine');
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function m = marginal_family(engine, i, t)
+% MARGINAL_FAMILY Compute the marginal on i's family (inf_engine)
+% m = marginal_family(engine, i, t)
+%
+% t defaults to 1.
+
+if nargin < 3, t = 1; end
+
+bnet = bnet_from_engine(engine);
+if t==1
+  m = marginal_nodes(engine, family(bnet.dag, i));
+else
+  ss = length(bnet.intra);
+  fam = family(bnet.dag, i+ss);
+  if any(fam<=ss)
+    % i has a parent in the preceeding slice
+    % Hence the lowest numbered slice containing the family is t-1
+    m = marginal_nodes(engine, fam, t-1);
+  else
+    % The family all fits inside slice t
+    % Hence shift the indexes back to slice 1
+    m = marginal_nodes(engine, fam-ss, t);
+  end
+end     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/set_fields.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function engine = set_fields(engine, varargin)
+% SET_FIELDS Set the fields for a generic engine
+% engine = set_fields(engine, name/value pairs)
+%
+% e.g., engine = set_fields(engine, 'maximize', 1)
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'maximize', engine.maximize = args{i+1};
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/@inf_engine/update_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function engine = update_engine(engine, newCPDs)
+% UPDATE_ENGINE Update the engine to take into account the new parameters (inf_engine).
+% engine = update_engine(engine, newCPDs)
+%
+% This generic method is suitable for engines that do not process the parameters until 'enter_evidence'.
+
+engine.bnet.CPD = newCPDs;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/dummy/1.1.1.1/Sat Jan 18 22:22:22 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+A D/@inf_engine////
+A D/dynamic////
+A D/online////
+A D/static////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+/bk_ff_hmm_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/dbn_init_bel.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/dbn_marginal_from_bel.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/dbn_predict_bel.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/dbn_update_bel.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/dbn_update_bel1.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/bk_ff_hmm_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function engine = bk_ff_hmm_inf_engine(bnet)
+% BK_FF_HMM_INF_ENGINE Naive (HMM-based) implementation of fully factored form of Boyen-Koller 
+% engine = bk_ff_hmm_inf_engine(bnet)
+%
+% This is implemented on top of the forwards-backwards algo for HMMs,
+% so it is *less* efficient than exact inference! However, it is good for educational purposes,
+% because it illustrates the BK algorithm very clearly.
+
+[persistent_nodes, transient_nodes] = partition_dbn_nodes(bnet.intra, bnet.inter);
+assert(isequal(sort(bnet.observed), transient_nodes));
+[engine.prior, engine.transmat] = dbn_to_hmm(bnet);
+
+ss = length(bnet.intra);
+
+engine.bel = [];
+engine.bel_marginals = [];
+engine.marginals = [];
+
+
+engine = class(engine, 'bk_ff_hmm_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/dbn_init_bel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function engine = dbn_init_bel(engine)
+% DBN_INIT_BEL Compute the initial belief state (bk_ff_hmm)
+% engine = dbn_init_bel(engine)
+
+engine.bel = engine.prior(:);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/dbn_marginal_from_bel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function marginal = dbn_marginal_from_bel(engine, i)
+% DBN_MARGINAL_FROM_BEL Compute the marginal on a node given the current belief state (bk_ff_hmm)
+% marginal = dbn_marginal_from_bel(engine, i)
+
+marginal = pot_to_marginal(engine.bel_marginals{i});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/dbn_predict_bel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function engine = dbn_predict_bel(engine, lag)
+% DBN_PREDICT_BEL Predict the belief state 'lag' steps into the future (bk_ff_hmm)
+% engine = dbn_predict_bel(engine, lag)
+% 'lag' defaults to 1
+
+if nargin < 2, lag = 1; end
+
+for d=1:lag
+  %newbel = engine.transmat' * engine.bel;
+  newbel = normalise(engine.transmat' * engine.bel); 
+  
+  hnodes = engine.hnodes;
+  bnet = bnet_from_engine(engine);
+  ns = bnet.node_sizes;
+  [marginals, marginalsT] = project_joint_onto_marginals(newbel, hnodes, ns);
+  newbel = combine_marginals_into_joint(marginalsT, hnodes, ns);          
+  engine.bel_marginals = marginalsT;
+  engine.bel = newbel;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/dbn_update_bel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function [engine, loglik] = dbn_update_bel(engine, evidence)
+% DBN_UPDATE_BEL Update the belief state (bk_ff_hmm)
+% [engine, loglik] = dbn_update_bel(engine, evidence)
+%
+% evidence{i,1} contains the evidence on node i in slice t-1
+% evidence{i,2} contains the evidence on node i in slice t
+
+oldbel = engine.bel;
+bnet = bnet_from_engine(engine);
+obslik = mk_hmm_obs_lik_vec(bnet, evidence);
+[newbel, lik] = normalise((engine.transmat' * oldbel) .* obslik);
+loglik = log(lik);
+
+hnodes = engine.hnodes;
+ns = bnet.node_sizes;
+[marginals, marginalsT] = project_joint_onto_marginals(newbel, hnodes, ns);
+newbel = combine_marginals_into_joint(marginalsT, hnodes, ns);          
+engine.bel_marginals = marginalsT;
+engine.bel = newbel;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/dbn_update_bel1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function [engine, loglik] = dbn_update_bel1(engine, evidence)
+% DBN_UPDATE_BEL Update the initial belief state (bk_ff_hmm)
+% [engine, loglik] = dbn_update_bel(engine, evidence)
+%
+%  evidence{i} contains the evidence on node i in slice 1
+
+oldbel = engine.bel;
+bnet = bnet_from_engine(engine);
+obslik = mk_hmm_obs_lik_vec1(bnet, evidence);
+[newbel, lik] = normalise(oldbel .* obslik);
+loglik = log(lik);
+
+hnodes = engine.hnodes;
+ns = bnet.node_sizes;
+[marginals, marginalsT] = project_joint_onto_marginals(newbel, hnodes, ns);
+newbel = combine_marginals_into_joint(marginalsT, hnodes, ns);          
+engine.bel_marginals = marginalsT;
+engine.bel = newbel;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,60 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (bk_ff_hmm)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product (not yet supported), else sum-product [0]
+% filter -   if 1, do filtering, else smoothing [0]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+maximize = 0;
+filter = 0;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1}; 
+     case 'filter', filter = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+assert(~maximize);
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+onodes = bnet.observed;
+hnodes = mysetdiff(1:ss, onodes);
+T = size(evidence, 2);
+assert(~any(isemptycell(evidence(onodes,:))));
+
+obslik = mk_hmm_obs_lik_mat(bnet, onodes, evidence);
+
+ns = bnet.node_sizes_slice;
+ns(onodes) = 1;
+
+[gamma, loglik, marginals, marginalsT] = bk_ff_fb(engine.prior, engine.transmat, obslik, filter, hnodes, ns);
+  
+for t=1:T
+  for i=hnodes(:)'
+    engine.marginals{i,t} = pot_to_marginal(marginalsT{i,t});
+  end
+  for i=onodes(:)'
+    m.domain = i + (t-1)*ss;
+    m.T = 1;
+    engine.marginals{i,t} = m;
+  end
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function m = marginal_family(engine, i, t)
+% MARGINAL_FAMILY Compute the marginal on the specified family (bk_ff_hmm)
+% marginal = marginal_family(engine, i, t)
+
+error('bk_ff_hmm doesn''t support marginal_family');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function marginal = marginal_nodes(engine, nodes, t)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (bk_ff_hmm)
+% marginal = marginal_nodes(engine, i, t)
+
+assert(length(nodes)==1);
+i = nodes(end);
+%assert(myismember(i, engine.hnodes));
+marginal = engine.marginals{i,t};
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+marginal.domain = i + (t-1)*ss;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+/bk_ff_fb.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/combine_marginals_into_joint.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/dbn_to_hmm.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/mk_hmm_obs_lik_mat.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/mk_hmm_obs_lik_vec.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/mk_hmm_obs_lik_vec1.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/project_joint_onto_marginals.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/bk_ff_fb.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function [gamma, loglik, marginals, marginalsT] = bk_ff_fb(prior, transmat, obslik, filter_only, hnodes, ns)
+% BK_FF_FB Fully factored Boyen-Koller version of forwards-backwards
+% [gamma, loglik, marginals, marginalsT] = bk_ff_hmm(prior, transmat, obslik, filter_only, hnodes, ns)
+
+ss  = length(ns);
+S = length(prior);
+T = size(obslik, 2);
+marginals = cell(ss,T);
+marginalsT = cell(ss,T);
+scale = zeros(1,T);
+alpha = zeros(S, T);
+
+transmat2 = transmat';
+for t=1:T
+  if t==1
+    [alpha(:,t), scale(t)] = normalise(prior(:) .* obslik(:,t));
+  else
+    [alpha(:,t), scale(t)] = normalise((transmat2 * alpha(:,t-1)) .* obslik(:,t));
+  end
+  [marginals(:,t), marginalsT(:,t)] = project_joint_onto_marginals(alpha(:,t), hnodes, ns);
+  alpha(:,t) = combine_marginals_into_joint(marginalsT(:,t), hnodes, ns);
+  %fprintf('alpha t=%d\n', t);
+  %celldisp(marginals(1:8,t))
+end
+loglik = sum(log(scale));
+
+if filter_only
+  gamma = alpha;
+  return;
+end
+
+beta = zeros(S,T);
+gamma = zeros(S,T);
+t = T;
+beta(:,t) = ones(S,1);
+gamma(:,t) = normalise(alpha(:,t) .* beta(:,t));
+[marginals(:,t), marginalsT(:,t)] = project_joint_onto_marginals(gamma(:,t), hnodes, ns);
+
+for t=T-1:-1:1
+  b = beta(:,t+1) .* obslik(:,t+1); 
+  beta(:,t) = normalise((transmat * b));
+  [junk, tempT] = project_joint_onto_marginals(beta(:,t), hnodes, ns);
+  beta(:,t) = combine_marginals_into_joint(tempT, hnodes, ns);
+  %gamma(:,t) = normalise(alpha(:,t) .* beta(:,t));
+  %[marginals(:,t), marginalsT(:,t)] = project_joint_onto_marginals(gamma(:,t), hnodes, ns);
+end
+
+gamma2 = zeros(S,T);
+for t=T-1:-1:1
+  b = beta(:,t+1) .* obslik(:,t+1); 
+  xi(:,:,t) = normalise((transmat .* (alpha(:,t) * b')));      
+  if t==T-1
+    gamma2(:,T) = sum(xi(:,:,T-1), 1)';
+  end
+  gamma2(:,t) = sum(xi(:,:,t), 2);
+  [marginals(:,t), marginalsT(:,t)] = project_joint_onto_marginals(gamma2(:,t), hnodes, ns);
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/combine_marginals_into_joint.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function joint = combine_marginals_into_joint(marginalsT, hnodes, ns)
+
+jointT = dpot(hnodes, ns(hnodes));
+for i=hnodes(:)'
+  jointT = multiply_by_pot(jointT, marginalsT{i});
+end
+m = pot_to_marginal(jointT);
+joint = m.T(:);           
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/dbn_to_hmm.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,41 @@
+function [prior, transmat] = dbn_to_hmm(bnet)
+% DBN_TO_HMM Compute the discrete HMM matrices from a simple DBN
+% [prior, transmat] = dbn_to_hmm(bnet)
+
+onodes = bnet.observed;
+ss = length(bnet.intra);
+evidence = cell(1,2*ss);
+hnodes = mysetdiff(1:ss, onodes);
+prior = multiply_CPTs(bnet, [], hnodes, evidence);
+transmat = multiply_CPTs(bnet, hnodes, hnodes+ss, evidence);
+%obsmat1 = multiply_CPTs(bnet, hnodes, onodes, evidence);
+%obsmat = multiply_CPTs(bnet, hnodes+ss, onodes+ss, evidence);
+%obsmat1 = obsmat if the observation matrices are tied across slices
+
+
+
+%%%%%%%%%%%%
+
+function mat = multiply_CPTs(bnet, pdom, cdom, evidence)
+
+% MULTIPLY_CPTS Make a matrix Pr(Y|X), where X represents all the parents, and Y all the children
+% We assume the children have no intra-connections.
+%
+% e.g., Consider the DBN with interconnectivity i->i', j->j',k', k->i',k'
+% Then transition matrix = Pr(i,j,k -> i',j',k') = Pr(i,k->i') Pr(j->j') Pr(j,k->k')
+
+dom = [pdom cdom];
+ns = bnet.node_sizes;
+bigpot = dpot(dom, ns(dom));
+for j=cdom(:)'
+  e = bnet.equiv_class(j);
+  fam = family(bnet.dag, j);
+  pot = convert_to_pot(bnet.CPD{e}, 'd', fam(:), evidence);
+  bigpot = multiply_by_pot(bigpot, pot);
+end
+psize = prod(ns(pdom));
+csize = prod(ns(cdom));
+T = pot_to_marginal(bigpot);
+mat = reshape(T.T, [psize csize]);
+
+          
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/mk_hmm_obs_lik_mat.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,34 @@
+function obslik = mk_hmm_obs_lik_mat(bnet, onodes, evidence)
+% MK_HMM_OBS_LIK_MAT Make the observation likelihood matrix for all slices
+% obslik = mk_hmm_obs_lik_mat(bnet, onodes, evidence)
+%
+% obslik(i,t) = Pr(Y(t) | X(t)=i)
+
+[ss T] = size(evidence);
+
+hnodes = mysetdiff(1:ss, onodes);
+ns = bnet.node_sizes_slice;
+ns(onodes) = 1;
+Q = prod(ns(hnodes));
+obslik = zeros(Q,T);
+
+dom = 1:ss;
+for t=1:T
+  bigpot = dpot(dom, ns(dom));
+  for i=onodes(:)'
+    if t==1
+      e = bnet.equiv_class(i,1);
+      fam = family(bnet.dag, i);
+    else
+      e = bnet.equiv_class(i,2);
+      fam = family(bnet.dag, i, 2) + ss*(t-2);
+    end
+    pot = convert_to_pot(bnet.CPD{e}, 'd', fam(:), evidence);
+    pot = set_domain_pot(pot, family(bnet.dag, i));
+    bigpot = multiply_by_pot(bigpot, pot);
+  end
+  m = pot_to_marginal(bigpot);
+  obslik(:,t) = m.T(:);
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/mk_hmm_obs_lik_vec.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,27 @@
+function obslik = mk_hmm_obs_lik_vec(bnet, evidence)
+% MK_HMM_OBS_LIK_VEC Make the observation likelihood vector for one slice
+% obslik = mk_obs_lik(bnet, evidence)
+%
+% obslik(i) = Pr(y(t) | X(t)=i)
+% evidence{i,1} contains the evidence on node i in slice t-1
+% evidence{i,2} contains the evidence on node i in slice t
+
+ns = bnet.node_sizes;
+ss = length(bnet.intra);
+onodes = find(~isemptycell(evidence(:)));
+hnodes = find(isemptycell(evidence(:)));
+ens = ns;
+ens(onodes) = 1;
+Q = prod(ens(hnodes));
+obslik = zeros(1,Q);
+dom = (1:ss)+ss;
+bigpot = dpot(dom, ens(dom));
+onodes1 = find(~isemptycell(evidence(:,1)));
+for i=onodes1(:)'
+  e = bnet.equiv_class(i,2);
+  fam = family(bnet.dag, i, 2);
+  pot = convert_to_pot(bnet.CPD{e}, 'd', fam, evidence);
+  bigpot = multiply_by_pot(bigpot, pot);
+end
+m = pot_to_marginal(bigpot);
+obslik = m.T(:);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/mk_hmm_obs_lik_vec1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function obslik = mk_hmm_obs_lik_vec1(bnet, evidence)
+% MK_HMM_OBS_LIK_VEC1 Make the observation likelihood vector for the first slice
+% obslik = mk_hmm_obs_lik_vec1(engine, evidence)
+%
+% obslik(i) = Pr(y(1) | X(1)=i)
+% evidence{i} contains the evidence on node i in slice 1
+
+ns = bnet.node_sizes;
+ss = length(ns);
+onodes = find(~isemptycell(evidence(:)));
+hnodes = find(isemptycell(evidence(:)));
+ens = ns;
+ens(onodes) = 1;
+Q = prod(ens(hnodes));
+obslik = zeros(1,Q);
+dom = (1:ss);
+bigpot = dpot(dom, ens(dom));
+for i=onodes(:)'
+  e = bnet.equiv_class(i,1);
+  fam = family(bnet.dag, i);
+  pot = convert_to_pot(bnet.CPD{e}, 'd', fam(:), evidence);
+  bigpot = multiply_by_pot(bigpot, pot);
+end
+m = pot_to_marginal(bigpot);
+obslik = m.T(:);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_ff_hmm_inf_engine/private/project_joint_onto_marginals.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function [marginals, marginalsT] = project_joint_onto_marginals(joint, hnodes, ns)
+
+ss = length(ns);
+jointT = dpot(hnodes, ns(hnodes), joint);
+marginalsT = cell(1, ss);
+marginals = cell(1,ss);
+for i=hnodes(:)'
+  marginalsT{i} = marginalize_pot(jointT, i);
+  m = pot_to_marginal(marginalsT{i});
+  marginals{i} = m.T(:);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+/bk_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/dbn_init_bel.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/dbn_marginal_from_bel.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/dbn_update_bel.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/dbn_update_bel1.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_soft_evidence.m/1.1.1.1/Sat Jan 11 18:13:50 2003//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/update_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@bk_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/bk_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,107 @@
+function engine = bk_inf_engine(bnet, varargin)
+% BK_INF_ENGINE Boyen-Koller approximate inference algorithm for DBNs.
+%
+% In the BK algorithm, the belief state is represented as a product of marginals,
+% even though the factors may not be independent.
+%
+% engine = bk_inf_engine(bnet, ...)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+% 
+% clusters - if a cell array, clusters{i} specifies the terms in the i'th factor.
+%          - 'exact' means create one cluster that contains all the nodes in a slice [exact]
+%          - 'ff' means create one cluster per node (ff = fully factorised).
+%
+%
+% For details, see
+% - "Tractable Inference for Complex Stochastic Processes", X. Boyen and D. Koller, UAI 98.
+% - "Approximate learning of dynamic models",  X. Boyen and D. Koller, NIPS 98.
+% (The UAI98 paper discusses filtering and theory, and the NIPS98 paper discusses smoothing.)
+
+ss = length(bnet.intra);
+% set default params
+clusters = 'exact';
+
+
+if nargin >= 2
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'clusters',  clusters = args{i+1};
+     otherwise, error(['unrecognized argument ' args{i}])
+    end
+  end
+end
+
+if strcmp(clusters, 'exact')
+  %clusters = { compute_interface_nodes(bnet.intra, bnet.inter) };
+  clusters = { 1:ss }; 
+elseif strcmp(clusters, 'ff')
+  clusters = num2cell(1:ss);
+end
+
+
+% We need to insert the prior on the clusters in slice 1,
+% and extract the posterior on the clusters in slice 2.
+C = length(clusters);
+clusters2 = cell(1,2*C);
+clusters2(1:C) = clusters;
+for c=1:C
+  clusters2{c+C} = clusters{c} + ss;
+end
+
+onodes = bnet.observed;
+obs_nodes = [onodes(:) onodes(:)+ss];
+engine.sub_engine = jtree_inf_engine(bnet, 'clusters', clusters2);
+
+engine.clq_ass_to_cluster = zeros(C, 2);
+for c=1:C
+  engine.clq_ass_to_cluster(c,1) = clq_containing_nodes(engine.sub_engine, clusters{c});
+  engine.clq_ass_to_cluster(c,2) = clq_containing_nodes(engine.sub_engine, clusters{c}+ss);
+end
+engine.clusters = clusters;
+
+engine.clq_ass_to_node = zeros(ss, 2);
+for i=1:ss
+  engine.clq_ass_to_node(i, 1) = clq_containing_nodes(engine.sub_engine, i);
+  engine.clq_ass_to_node(i, 2) = clq_containing_nodes(engine.sub_engine, i+ss);
+end
+
+
+
+% Also create an engine just for slice 1
+bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, 'discrete', myintersect(bnet.dnodes, 1:ss), ...
+		'equiv_class', bnet.equiv_class(:,1), 'observed', onodes);
+for i=1:max(bnet1.equiv_class)
+  bnet1.CPD{i} = bnet.CPD{i};
+end
+
+engine.sub_engine1 = jtree_inf_engine(bnet1, 'clusters', clusters);
+
+engine.clq_ass_to_cluster1 = zeros(1,C);
+for c=1:C
+  engine.clq_ass_to_cluster1(c) = clq_containing_nodes(engine.sub_engine1, clusters{c});
+end
+
+engine.clq_ass_to_node1 = zeros(1, ss);
+for i=1:ss
+  engine.clq_ass_to_node1(i) = clq_containing_nodes(engine.sub_engine1, i);
+end
+
+engine.clpot = []; % this is where we store the results between enter_evidence and marginal_nodes
+engine.filter = [];
+engine.maximize = [];
+engine.T = [];
+
+engine.bel = [];
+engine.bel_clpot = [];
+engine.slice1 = [];
+%engine.pot_type = 'cg';
+% hack for online inference so we can cope with hidden Gaussians and discrete
+% it will not affect the pot type used in enter_evidence
+engine.pot_type = determine_pot_type(bnet, onodes);
+
+engine = class(engine, 'bk_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/dbn_init_bel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function engine = dbn_init_bel(engine)
+% DBN_INIT_BEL Compute the initial belief state (bk)
+% engine = dbn_init_bel(engine))
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+evidence = cell(1,ss);
+engine = dbn_update_bel1(engine, evidence);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/dbn_marginal_from_bel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function marginal = dbn_marginal_from_bel(engine, i)
+% DBN_MARGINAL_FROM_BEL Compute the marginal on a node given the current belief state (bk)
+% marginal = dbn_marginal_from_bel(engine, i)
+  
+if engine.slice1
+  j = i;
+  c = clq_containing_nodes(engine.sub_engine1, j);
+else
+  bnet = bnet_from_engine(engine);
+  ss = length(bnet.intra);
+  j = i+ss;
+  c = clq_containing_nodes(engine.sub_engine, j);
+end
+assert(c >= 1);
+bigpot = engine.bel_clpot{c};
+
+pot = marginalize_pot(bigpot, j);
+marginal = pot_to_marginal(pot);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/dbn_update_bel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,37 @@
+function [engine, loglik] = dbn_update_bel(engine, evidence)
+% DBN_UPDATE_BEL Update the belief state (bk)
+% [engine, loglik] = dbn_update_bel(engine, evidence)
+%
+% evidence{i,1} contains the evidence on node i in slice t-1
+% evidence{i,2} contains the evidence on node i in slice t
+
+oldbel = engine.bel;
+
+ss = size(evidence, 1);
+bnet = bnet_from_engine(engine);
+CPDpot = cell(1, ss);
+for n=1:ss
+  fam = family(bnet.dag, n, 2);
+  e = bnet.equiv_class(n, 2);
+  CPDpot{n} = convert_to_pot(bnet.CPD{e}, engine.pot_type, fam(:), evidence);
+end
+
+observed = ~isemptycell(evidence);
+onodes2 = find(observed(:));
+clqs = [engine.clq_ass_to_cluster(:,1); engine.clq_ass_to_node(:,2)];
+pots = [oldbel(:); CPDpot(:)];
+
+[clpot, loglik] = enter_soft_evidence(engine.sub_engine, clqs, pots, onodes2(:), engine.pot_type);
+
+C = length(engine.clusters);
+newbel = cell(1,C);
+for c=1:C
+  k = engine.clq_ass_to_cluster(c,2);
+  cl = engine.clusters{c};
+  newbel{c} = marginalize_pot(clpot{k}, cl+ss); % extract slice 2 posterior
+  newbel{c} = set_domain_pot(newbel{c}, cl); % shift back to slice 1 for re-use as prior
+end
+
+engine.bel = newbel;
+engine.bel_clpot = clpot;
+engine.slice1 = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/dbn_update_bel1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function [engine, loglik] = dbn_update_bel1(engine, evidence)
+% DBN_UPDATE_BEL1 Update  the initial belief state (bk)
+% engine = dbn_update_bel1(engine, evidence)
+%
+% evidence{i} has the evidence on node i for slice 1
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+CPDpot = cell(1,ss);      
+t = 1;
+for n=1:ss
+  fam = family(bnet.dag, n);
+  e = bnet.equiv_class(n, 1);
+  CPDpot{n} = convert_to_pot(bnet.CPD{e}, engine.pot_type, fam(:), evidence);
+end
+
+onodes = find(~isemptycell(evidence));
+
+[clpot, loglik] = enter_soft_evidence(engine.sub_engine1, engine.clq_ass_to_node1, CPDpot, onodes, engine.pot_type);
+
+C  = length(engine.clusters);
+newbel = cell(1,C);
+for c=1:C
+  k = engine.clq_ass_to_cluster1(c);
+  newbel{c} = marginalize_pot(clpot{k}, engine.clusters{c});
+end
+
+engine.bel = newbel;
+engine.bel_clpot = clpot;
+engine.slice1 = 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,48 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (bk)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product instead of sum-product [0]
+% filter -   if 1, do filtering, else smoothing [0]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+maximize = 0;
+filter = 0;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1}; 
+     case 'filter', filter = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+[ss T] = size(evidence);
+engine.filter = filter;
+engine.maximize = maximize;
+engine.T = T;
+
+if maximize
+  error('BK does not yet support max propagation')
+  % because it calls enter_soft_evidence, not enter_evidence
+end
+
+observed_bitv = ~isemptycell(evidence);
+onodes = find(observed_bitv);
+bnet = bnet_from_engine(engine);
+pot_type = determine_pot_type(bnet, onodes); 
+CPDpot = convert_dbn_CPDs_to_pots(bnet, evidence, pot_type);
+[engine.clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed_bitv, pot_type, filter);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/enter_soft_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,88 @@
+function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (bk)
+% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+
+[ss T] = size(CPDpot);
+C = length(engine.clusters);
+Q = length(cliques_from_engine(engine.sub_engine));
+Q1 = length(cliques_from_engine(engine.sub_engine1));
+clpot = cell(Q,T);
+alpha = cell(C,T);
+
+% Forwards
+% The method is a generalization of the following HMM equation:
+% alpha(j,t) = normalise( (sum_i alpha(i,t-1) * transmat(i,j)) * obsmat(j,t) )
+% where alpha(j,t) = Pr(Q(t)=j | y(1:t))
+t = 1;
+[clpot(1:Q1,t), logscale(t)] = enter_soft_evidence(engine.sub_engine1, engine.clq_ass_to_node1(:), ...
+					   CPDpot(:,1), find(observed(:,1)), pot_type);
+for c=1:C
+  k = engine.clq_ass_to_cluster1(c);
+  alpha{c,t} = marginalize_pot(clpot{k,t}, engine.clusters{c});
+end
+% For filtering, clpot{1} contains evidence on slice 1 only
+
+%fprintf('alphas t=%d\n', t);
+%for c=1:8
+%  temp = pot_to_marginal(alpha{c,t});
+%  temp.T
+%end
+
+% clpot{t} contains evidence from slices t-1, t for t > 1
+clqs = [engine.clq_ass_to_cluster(:,1); engine.clq_ass_to_node(:,2)];
+for t=2:T
+  pots = [alpha(:,t-1); CPDpot(:,t)];
+  [clpot(:,t), logscale(t)] = enter_soft_evidence(engine.sub_engine, clqs, pots, find(observed(:,t-1:t)),  pot_type);
+  for c=1:C
+    k = engine.clq_ass_to_cluster(c,2);
+    cl = engine.clusters{c};
+    alpha{c,t} = marginalize_pot(clpot{k,t}, cl+ss); % extract slice 2 posterior
+    alpha{c,t} = set_domain_pot(alpha{c,t}, cl); % shift back to slice 1 for re-use as prior
+  end
+
+end
+
+loglik = sum(logscale);
+
+if filter
+  return;
+end
+
+% Backwards
+% The method is a generalization of the following HMM equation:
+% beta(i,t) = (sum_j transmat(i,j) * obsmat(j,t+1) * beta(j,t+1))
+% where beta(i,t) = Pr(y(t+1:T) | Q(t)=i)
+t = T;
+bnet = bnet_from_engine(engine);
+beta = cell(C,T);
+for c=1:C
+  beta{c,t} = mk_initial_pot(pot_type, engine.clusters{c} + ss, bnet.node_sizes(:), bnet.cnodes(:), ...
+			     find(observed(:,t-1:t)));
+end
+for t=T-1:-1:1
+  clqs = [engine.clq_ass_to_cluster(:,2); engine.clq_ass_to_node(:,2)];
+  pots = [beta(:,t+1); CPDpot(:,t+1)];
+  temp = enter_soft_evidence(engine.sub_engine, clqs, pots, find(observed(:,t:t+1)),  pot_type);
+  for c=1:C
+    k = engine.clq_ass_to_cluster(c,1);
+    cl = engine.clusters{c};
+    beta{c,t} = marginalize_pot(temp{k}, cl); % extract slice 1
+    beta{c,t} = set_domain_pot(beta{c,t}, cl + ss); % shift fwd to slice 2
+  end
+end
+
+% Combine
+% The method is a generalization of the following HMM equation:
+% xi(i,j,t) = normalise( alpha(i,t) * transmat(i,j) * obsmat(j,t+1) * beta(j,t+1) )
+% where xi(i,j,t) = Pr(Q(t)=i, Q(t+1)=j | y(1:T))
+for t=1:T-1
+  clqs = [engine.clq_ass_to_cluster(:); engine.clq_ass_to_node(:,2)];
+  pots = [alpha(:,t); beta(:,t+1); CPDpot(:,t+1)];
+  clpot(:,t+1) = enter_soft_evidence(engine.sub_engine, clqs, pots, find(observed(:,t:t+1)),  pot_type);
+end
+% for smoothing, clpot{1} is undefined
+for k=1:Q1
+  clpot{k,1} = []; 
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function m = marginal_family(engine, i, t)
+% MARGINAL_FAMILY Compute the marginal on the specified family (bk)
+% marginal = marginal_family(engine, i, t)
+
+% This is just like inf_engine/marginal_family, except when we call
+% marginal_nodes, we provide a 4th argument, to tell it's a family.
+
+if nargin < 3, t = 1; end
+
+bnet = bnet_from_engine(engine);
+if t==1
+  m = marginal_nodes(engine, family(bnet.dag, i), t, 1);
+else
+  ss = length(bnet.intra);
+  fam = family(bnet.dag, i+ss);
+  if any(fam<=ss)
+    % i has a parent in the preceeding slice
+    % Hence the lowest numbered slice containing the family is t-1
+    m = marginal_nodes(engine, fam, t-1, 1);
+  else
+    % The family all fits inside slice t
+    % Hence shift the indexes back to slice 1
+    m = marginal_nodes(engine, fam-ss, t, 1);
+  end
+end     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,67 @@
+function marginal = marginal_nodes(engine, nodes, t, fam)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (bk)
+%
+%   marginal = marginal_nodes(engine, i, t)
+% returns Pr(X(i,t) | Y(1:T)), where X(i,t) is the i'th node in the t'th slice.
+% If enter_evidence used filtering instead of smoothing, this will return  Pr(X(i,t) | Y(1:t)).
+%
+%   marginal = marginal_nodes(engine, query, t)
+% returns Pr(X(query(1),t), ... X(query(end),t) | Y(1:T)),
+% where X(q,t) is the q'th node in the t'th slice. If q > ss (slice size), this is equal
+% to X(q mod ss, t+1). That is, 't' specifies the time slice of the earliest node.
+% 'query' cannot span more than 2 time slices.
+% Example:
+% Consider a DBN with 2 nodes per slice.
+% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3.
+
+if nargin < 3, t = 1; end
+if nargin < 4, fam = 0; else fam = 1; end
+
+
+% clpot{t} contains slice t-1 and t
+% Example
+% clpot #: 1    2    3
+% slices:  1  1,2  2,3
+% For filtering, we must take care not to take future evidence into account.
+% For smoothing, clpot{1} does not exist.
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+
+nodes2 = nodes;
+if ~engine.filter
+  if t < engine.T
+    slice = t+1;
+  else % earliest t is T, so all nodes fit in one slice
+    slice = engine.T;
+    nodes2 = nodes + ss;
+  end
+else
+  if t == 1
+   slice = 1;
+  else
+    if all(nodes<=ss)
+      slice = t;
+      nodes2 = nodes + ss;
+    elseif t == engine.T
+      slice = t;
+    else
+      slice = t + 1;
+    end
+  end
+end
+  
+if engine.filter & t==1
+  c = clq_containing_nodes(engine.sub_engine1, nodes2, fam);
+else
+  c = clq_containing_nodes(engine.sub_engine, nodes2, fam);
+end
+assert(c >= 1);
+bigpot = engine.clpot{c, slice};
+
+pot = marginalize_pot(bigpot, nodes2);
+marginal = pot_to_marginal(pot);
+
+% we convert the domain to the unrolled numbering system
+% so that update_ess extracts the right evidence.
+marginal.domain = nodes+(t-1)*ss;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@bk_inf_engine/update_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function engine = update_engine(engine, newCPDs)
+% UPDATE_ENGINE Update the engine to take into account the new parameters (bk)
+% engine = update_engine(engine, newCPDs)
+
+engine.inf_engine = update_engine(engine.inf_engine, newCPDs);
+engine.sub_engine = update_engine(engine.sub_engine, newCPDs);
+
+bnet = bnet_from_engine(engine);
+eclass1 = bnet.equiv_class(:,1);
+engine.sub_engine1 = update_engine(engine.sub_engine1, newCPDs(1:max(eclass1)));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+/cbk_inf_engine.m/1.1.1.1/Mon Nov 22 22:15:34 2004//
+/dbn_init_bel.m/1.1.1.1/Tue Jul 29 02:44:58 2003//
+/dbn_marginal_from_bel.m/1.1.1.1/Tue Jul 29 02:44:58 2003//
+/dbn_update_bel.m/1.1.1.1/Tue Jul 29 02:44:58 2003//
+/dbn_update_bel1.m/1.1.1.1/Tue Jul 29 02:44:58 2003//
+/enter_evidence.m/1.1.1.1/Mon Jan 12 20:53:54 2004//
+/enter_soft_evidence.m/1.1.1.1/Wed Feb  4 07:42:38 2004//
+/junk/1.1.1.1/Wed Nov 24 20:12:38 2004//
+/marginal_family.m/1.1.1.1/Tue Jul 29 02:44:58 2003//
+/marginal_nodes.m/1.1.1.1/Tue Dec 16 06:17:18 2003//
+/update_engine.m/1.1.1.1/Tue Jul 29 02:44:58 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@cbk_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/cbk_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,175 @@
+function engine = cbk_inf_engine(bnet, varargin)
+% Just the same as bk_inf_engine, but you can specify overlapping clusters.
+
+ss = length(bnet.intra);
+% set default params
+clusters = 'exact';
+
+if nargin >= 2
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'clusters',  clusters = args{i+1};
+     otherwise, error(['unrecognized argument ' args{i}])
+    end
+  end
+end
+
+if strcmp(clusters, 'exact')
+  %clusters = { compute_interface_nodes(bnet.intra, bnet.inter) };
+  clusters = { 1:ss };
+elseif strcmp(clusters, 'ff')
+  clusters = num2cell(1:ss);
+end
+
+
+% We need to insert the prior on the clusters in slice 1,
+% and extract the posterior on the clusters in slice 2.
+% We don't need to care about the separators, b/c they're subsets of the clusters.
+C = length(clusters);
+clusters2 = cell(1,2*C);
+clusters2(1:C) = clusters;
+for c=1:C
+  clusters2{c+C} = clusters{c} + ss;
+end
+
+onodes = bnet.observed;
+obs_nodes = [onodes(:) onodes(:)+ss];
+engine.sub_engine = jtree_inf_engine(bnet, 'clusters', clusters2);
+
+%FH >>>
+%Compute separators. 
+ns = bnet.node_sizes(:,1);
+ns(onodes) = 1;
+[clusters, separators] = build_jt(clusters, 1:length(ns), ns);
+S = length(separators);
+engine.separators = separators;
+
+%Compute size of clusters.
+cl_sizes = zeros(1,C);
+for c=1:C
+    cl_sizes(c) = prod(ns(clusters{c}));
+end
+
+%Assign separators to the smallest cluster subsuming them.
+engine.cluster_ass_to_separator = zeros(S, 1);
+for s=1:S
+    subsuming_clusters = [];
+    %find smallest cluster containing s
+    for c=1:C
+        if mysubset(separators{s}, clusters{c}) 
+            subsuming_clusters(end+1) = c;
+        end
+    end
+    c = argmin(cl_sizes(subsuming_clusters));
+    engine.cluster_ass_to_separator(s) = subsuming_clusters(c);
+end
+
+%<<< FH
+
+engine.clq_ass_to_cluster = zeros(C, 2);
+for c=1:C
+  engine.clq_ass_to_cluster(c,1) = clq_containing_nodes(engine.sub_engine, clusters{c});
+  engine.clq_ass_to_cluster(c,2) = clq_containing_nodes(engine.sub_engine, clusters{c}+ss);
+end
+engine.clusters = clusters;
+
+engine.clq_ass_to_node = zeros(ss, 2);
+for i=1:ss
+  engine.clq_ass_to_node(i, 1) = clq_containing_nodes(engine.sub_engine, i);
+  engine.clq_ass_to_node(i, 2) = clq_containing_nodes(engine.sub_engine, i+ss);
+end
+
+
+
+% Also create an engine just for slice 1
+bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, 'discrete', myintersect(bnet.dnodes, 1:ss), ...
+		'equiv_class', bnet.equiv_class(:,1), 'observed', onodes);
+for i=1:max(bnet1.equiv_class)
+  bnet1.CPD{i} = bnet.CPD{i};
+end
+
+engine.sub_engine1 = jtree_inf_engine(bnet1, 'clusters', clusters);
+
+engine.clq_ass_to_cluster1 = zeros(1,C);
+for c=1:C
+  engine.clq_ass_to_cluster1(c) = clq_containing_nodes(engine.sub_engine1, clusters{c});
+end
+
+engine.clq_ass_to_node1 = zeros(1, ss);
+for i=1:ss
+  engine.clq_ass_to_node1(i) = clq_containing_nodes(engine.sub_engine1, i);
+end
+
+engine.clpot = []; % this is where we store the results between enter_evidence and marginal_nodes
+engine.filter = [];
+engine.maximize = [];
+engine.T = [];
+
+engine.bel = [];
+engine.bel_clpot = [];
+engine.slice1 = [];
+%engine.pot_type = 'cg';
+% hack for online inference so we can cope with hidden Gaussians and discrete
+% it will not affect the pot type used in enter_evidence
+engine.pot_type = determine_pot_type(bnet, onodes);
+
+engine = class(engine, 'cbk_inf_engine', inf_engine(bnet));
+
+
+
+
+function [cliques, seps, jt_size] = build_jt(cliques, vars, ns)
+% BUILD_JT connects the cliques into a jtree, computes the respective 
+% separators and the size of the resulting jtree.
+%
+% [cliques, seps, jt_size] = build_jt(cliques, vars, ns)
+% ns(i) has to hold the size of vars(i)
+% vars has to be a superset of the union of cliques.
+
+%======== Compute the jtree with tool from BNT. This wants the vars to be 1:N.
+%==== Map from nodes to their indices.
+%disp('Computing jtree for cliques with vars and ns:');
+%cliques
+%vars
+%ns'
+
+inv_nodes = sparse(1,max(vars));
+N = length(vars);
+for i=1:N
+    inv_nodes(vars(i)) = i;
+end
+
+tmp_cliques = cell(1,length(cliques));
+%==== Temporarily map clique vars to their indices.
+for i=1:length(cliques)
+    tmp_cliques{i} = inv_nodes(cliques{i});
+end
+
+%=== Compute the jtree, using BNT.
+[jtree, root, B, w] = cliques_to_jtree(tmp_cliques, ns);
+
+
+%======== Now, compute the separators between connected cliques and their weights.
+seps = {};
+s_w = [];
+[is,js] = find(jtree > 0);
+for k=1:length(is)
+  i = is(k); j = js(k);
+  sep = vars(find(B(i,:) & B(j,:))); % intersect(cliques{i}, cliques{j});
+  if i>j | length(sep) == 0, continue; end;
+  seps{end+1} = sep;
+  s_w(end+1) = prod(ns(inv_nodes(seps{end})));
+end
+
+cl_w = sum(w);
+sep_w = sum(s_w);
+assert(cl_w > sep_w, 'Weight of cliques must be bigger than weight of separators');
+
+jt_size = cl_w + sep_w;
+% jt.cliques = cliques;
+% jt.seps = seps;
+% jt.size = jt_size;
+% jt.ns = ns';
+% jt;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/dbn_init_bel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function engine = dbn_init_bel(engine)
+% DBN_INIT_BEL Compute the initial belief state (bk)
+% engine = dbn_init_bel(engine))
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+evidence = cell(1,ss);
+engine = dbn_update_bel1(engine, evidence);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/dbn_marginal_from_bel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function marginal = dbn_marginal_from_bel(engine, i)
+% DBN_MARGINAL_FROM_BEL Compute the marginal on a node given the current belief state (bk)
+% marginal = dbn_marginal_from_bel(engine, i)
+  
+if engine.slice1
+  j = i;
+  c = clq_containing_nodes(engine.sub_engine1, j);
+else
+  bnet = bnet_from_engine(engine);
+  ss = length(bnet.intra);
+  j = i+ss;
+  c = clq_containing_nodes(engine.sub_engine, j);
+end
+assert(c >= 1);
+bigpot = engine.bel_clpot{c};
+
+pot = marginalize_pot(bigpot, j);
+marginal = pot_to_marginal(pot);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/dbn_update_bel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,37 @@
+function [engine, loglik] = dbn_update_bel(engine, evidence)
+% DBN_UPDATE_BEL Update the belief state (bk)
+% [engine, loglik] = dbn_update_bel(engine, evidence)
+%
+% evidence{i,1} contains the evidence on node i in slice t-1
+% evidence{i,2} contains the evidence on node i in slice t
+
+oldbel = engine.bel;
+
+ss = size(evidence, 1);
+bnet = bnet_from_engine(engine);
+CPDpot = cell(1, ss);
+for n=1:ss
+  fam = family(bnet.dag, n, 2);
+  e = bnet.equiv_class(n, 2);
+  CPDpot{n} = convert_to_pot(bnet.CPD{e}, engine.pot_type, fam(:), evidence);
+end
+
+observed = ~isemptycell(evidence);
+onodes2 = find(observed(:));
+clqs = [engine.clq_ass_to_cluster(:,1); engine.clq_ass_to_node(:,2)];
+pots = [oldbel(:); CPDpot(:)];
+
+[clpot, loglik] = enter_soft_evidence(engine.sub_engine, clqs, pots, onodes2(:), engine.pot_type);
+
+C = length(engine.clusters);
+newbel = cell(1,C);
+for c=1:C
+  k = engine.clq_ass_to_cluster(c,2);
+  cl = engine.clusters{c};
+  newbel{c} = marginalize_pot(clpot{k}, cl+ss); % extract slice 2 posterior
+  newbel{c} = set_domain_pot(newbel{c}, cl); % shift back to slice 1 for re-use as prior
+end
+
+engine.bel = newbel;
+engine.bel_clpot = clpot;
+engine.slice1 = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/dbn_update_bel1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function [engine, loglik] = dbn_update_bel1(engine, evidence)
+% DBN_UPDATE_BEL1 Update  the initial belief state (bk)
+% engine = dbn_update_bel1(engine, evidence)
+%
+% evidence{i} has the evidence on node i for slice 1
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+CPDpot = cell(1,ss);      
+t = 1;
+for n=1:ss
+  fam = family(bnet.dag, n);
+  e = bnet.equiv_class(n, 1);
+  CPDpot{n} = convert_to_pot(bnet.CPD{e}, engine.pot_type, fam(:), evidence);
+end
+
+onodes = find(~isemptycell(evidence));
+
+[clpot, loglik] = enter_soft_evidence(engine.sub_engine1, engine.clq_ass_to_node1, CPDpot, onodes, engine.pot_type);
+
+C  = length(engine.clusters);
+newbel = cell(1,C);
+for c=1:C
+  k = engine.clq_ass_to_cluster1(c);
+  newbel{c} = marginalize_pot(clpot{k}, engine.clusters{c});
+end
+
+engine.bel = newbel;
+engine.bel_clpot = clpot;
+engine.slice1 = 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,48 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% this is unchanged from bk_inf_engine.
+% ENTER_EVIDENCE Add the specified evidence to the network (bk)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product instead of sum-product [0]
+% filter -   if 1, do filtering, else smoothing [0]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+maximize = 0;
+filter = 0;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1}; 
+     case 'filter', filter = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+[ss T] = size(evidence);
+engine.filter = filter;
+engine.maximize = maximize;
+engine.T = T;
+
+if maximize
+  error('BK does not yet support max propagation')
+  % because it calls enter_soft_evidence, not enter_evidence
+end
+
+observed_bitv = ~isemptycell(evidence);
+onodes = find(observed_bitv);
+bnet = bnet_from_engine(engine);
+pot_type = determine_pot_type(bnet, onodes); 
+CPDpot = convert_dbn_CPDs_to_pots(bnet, evidence, pot_type);
+[engine.clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed_bitv, pot_type, filter);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/enter_soft_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,115 @@
+function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (bk)
+% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+
+[ss T] = size(CPDpot);
+C = length(engine.clusters);
+S = length(engine.separators);
+Q = length(cliques_from_engine(engine.sub_engine));
+Q1 = length(cliques_from_engine(engine.sub_engine1));
+clpot = cell(Q,T);
+alpha = cell(C,T);
+
+% Forwards
+% The method is a generalization of the following HMM equation:
+% alpha(j,t) = normalise( (sum_i alpha(i,t-1) * transmat(i,j)) * obsmat(j,t) )
+% where alpha(j,t) = Pr(Q(t)=j | y(1:t))
+t = 1;
+[clpot(1:Q1,t), logscale(t)] = enter_soft_evidence(engine.sub_engine1, engine.clq_ass_to_node1(:), ...
+					   CPDpot(:,1), find(observed(:,1)), pot_type);
+for c=1:C
+  k = engine.clq_ass_to_cluster1(c);
+  alpha{c,t} = marginalize_pot(clpot{k,t}, engine.clusters{c});
+end
+
+%=== FH: For each separator s, divide some cluster potential by s's potential
+alpha_orig = alpha(:,t);
+for s=1:S
+  c = engine.cluster_ass_to_separator(s);
+  alpha{c,t} = divide_by_pot(alpha{c,t}, marginalize_pot(alpha_orig{c}, engine.separators{s}));
+end
+
+% For filtering, clpot{1} contains evidence on slice 1 only
+
+%fprintf('alphas t=%d\n', t);
+%for c=1:8
+%  temp = pot_to_marginal(alpha{c,t});
+%  temp.T
+%end
+
+% clpot{t} contains evidence from slices t-1, t for t > 1
+clqs = [engine.clq_ass_to_cluster(:,1); engine.clq_ass_to_node(:,2)];
+for t=2:T
+  pots = [alpha(:,t-1); CPDpot(:,t)];
+  [clpot(:,t), logscale(t)] = enter_soft_evidence(engine.sub_engine, clqs, pots, find(observed(:,t-1:t)),  pot_type);
+  for c=1:C
+    k = engine.clq_ass_to_cluster(c,2);
+    cl = engine.clusters{c};
+    alpha{c,t} = marginalize_pot(clpot{k,t}, cl+ss); % extract slice 2 posterior
+    alpha{c,t} = set_domain_pot(alpha{c,t}, cl); % shift back to slice 1 for re-use as prior
+  end
+  %=== FH: For each separator s, divide some cluster potential by s's potential
+  alpha_orig = alpha(:,t);
+  for s=1:S
+    c = engine.cluster_ass_to_separator(s);
+    alpha{c,t} = divide_by_pot(alpha{c,t}, marginalize_pot(alpha_orig{c}, engine.separators{s}));
+  end
+end
+
+loglik = sum(logscale); 
+
+if filter
+  return;
+end
+
+% Backwards
+% The method is a generalization of the following HMM equation:
+% beta(i,t) = (sum_j transmat(i,j) * obsmat(j,t+1) * beta(j,t+1))
+% where beta(i,t) = Pr(y(t+1:T) | Q(t)=i)
+t = T;
+bnet = bnet_from_engine(engine);
+beta = cell(C,T);
+for c=1:C
+  beta{c,t} = mk_initial_pot(pot_type, engine.clusters{c} + ss, bnet.node_sizes(:), bnet.cnodes(:), ...
+			     find(observed(:,t-1:t)));
+end
+%=== FH: For each separator s, divide some cluster potential by s's potential
+beta_orig = beta(:,t);
+for s=1:S
+  c = engine.cluster_ass_to_separator(s);
+  beta{c,t} = divide_by_pot(beta{c,t}, marginalize_pot(beta_orig{c}, engine.separators{s}+ss));
+end
+
+for t=T-1:-1:1
+  clqs = [engine.clq_ass_to_cluster(:,2); engine.clq_ass_to_node(:,2)];
+  pots = [beta(:,t+1); CPDpot(:,t+1)];
+  temp = enter_soft_evidence(engine.sub_engine, clqs, pots, find(observed(:,t:t+1)),  pot_type);
+  for c=1:C
+    k = engine.clq_ass_to_cluster(c,1);
+    cl = engine.clusters{c};
+    beta{c,t} = marginalize_pot(temp{k}, cl); % extract slice 1
+    beta{c,t} = set_domain_pot(beta{c,t}, cl + ss); % shift fwd to slice 2
+  end
+  %=== FH: For each separator s, divide some cluster potential by s's potential
+  beta_orig = beta(:,t);
+  for s=1:S
+    c = engine.cluster_ass_to_separator(s);
+    beta{c,t} = divide_by_pot(beta{c,t}, marginalize_pot(beta_orig{c}, engine.separators{s}+ss));
+  end
+end
+
+% Combine
+% The method is a generalization of the following HMM equation:
+% xi(i,j,t) = normalise( alpha(i,t) * transmat(i,j) * obsmat(j,t+1) * beta(j,t+1) )
+% where xi(i,j,t) = Pr(Q(t)=i, Q(t+1)=j | y(1:T))
+for t=1:T-1
+  clqs = [engine.clq_ass_to_cluster(:); engine.clq_ass_to_node(:,2)];
+  pots = [alpha(:,t); beta(:,t+1); CPDpot(:,t+1)];
+  clpot(:,t+1) = enter_soft_evidence(engine.sub_engine, clqs, pots, find(observed(:,t:t+1)),  pot_type);
+end
+% for smoothing, clpot{1} is undefined
+for k=1:Q1
+  clpot{k,1} = []; 
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/junk	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,176 @@
+function engine = cbk_inf_engine(bnet, varargin)
+% Just the same as bk_inf_engine, but you can specify overlapping clusters.
+
+ss = length(bnet.intra);
+% set default params
+clusters = 'exact';
+
+if nargin >= 2
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'clusters',  clusters = args{i+1};
+     otherwise, error(['unrecognized argument ' args{i}])
+    end
+  end
+end
+
+if strcmp(clusters, 'exact')
+  %clusters = { compute_interface_nodes(bnet.intra, bnet.inter) };
+  clusters = { 1:ss };
+elseif strcmp(clusters, 'ff')
+  clusters = num2cell(1:ss);
+end
+
+
+% We need to insert the prior on the clusters in slice 1,
+% and extract the posterior on the clusters in slice 2.
+% We don't need to care about the separators, b/c they're subsets of the clusters.
+C = length(clusters);
+clusters2 = cell(1,2*C);
+clusters2(1:C) = clusters;
+for c=1:C
+  clusters2{c+C} = clusters{c} + ss;
+end
+
+onodes = bnet.observed;
+obs_nodes = [onodes(:) onodes(:)+ss];
+engine.sub_engine = jtree_inf_engine(bnet, 'clusters', clusters2);
+
+%FH >>>
+%Compute separators. 
+ns = bnet.node_sizes(:,1);
+ns(onodes) = 1;
+[clusters, separators] = build_jt(clusters, 1:length(ns), ns);
+S = length(separators);
+engine.separators = separators;
+
+%Compute size of clusters.
+cl_sizes = zeros(1,C);
+for c=1:C
+    cl_sizes(c) = prod(ns(clusters{c}));
+end
+
+%Assign separators to the smallest cluster subsuming them.
+engine.cluster_ass_to_separator = zeros(S, 1);
+for s=1:S
+    subsuming_clusters = [];
+    %find smaunk
+    
+    for c=1:C
+        if mysubset(separators{s}, clusters{c}) 
+            subsuming_clusters(end+1) = c;
+        end
+    end
+    c = argmin(cl_sizes(subsuming_clusters));
+    engine.cluster_ass_to_separator(s) = subsuming_clusters(c);
+end
+
+%<<< FH
+
+engine.clq_ass_to_cluster = zeros(C, 2);
+for c=1:C
+  engine.clq_ass_to_cluster(c,1) = clq_containing_nodes(engine.sub_engine, clusters{c});
+  engine.clq_ass_to_cluster(c,2) = clq_containing_nodes(engine.sub_engine, clusters{c}+ss);
+end
+engine.clusters = clusters;
+
+engine.clq_ass_to_node = zeros(ss, 2);
+for i=1:ss
+  engine.clq_ass_to_node(i, 1) = clq_containing_nodes(engine.sub_engine, i);
+  engine.clq_ass_to_node(i, 2) = clq_containing_nodes(engine.sub_engine, i+ss);
+end
+
+
+
+% Also create an engine just for slice 1
+bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, 'discrete', myintersect(bnet.dnodes, 1:ss), ...
+		'equiv_class', bnet.equiv_class(:,1), 'observed', onodes);
+for i=1:max(bnet1.equiv_class)
+  bnet1.CPD{i} = bnet.CPD{i};
+end
+
+engine.sub_engine1 = jtree_inf_engine(bnet1, 'clusters', clusters);
+
+engine.clq_ass_to_cluster1 = zeros(1,C);
+for c=1:C
+  engine.clq_ass_to_cluster1(c) = clq_containing_nodes(engine.sub_engine1, clusters{c});
+end
+
+engine.clq_ass_to_node1 = zeros(1, ss);
+for i=1:ss
+  engine.clq_ass_to_node1(i) = clq_containing_nodes(engine.sub_engine1, i);
+end
+
+engine.clpot = []; % this is where we store the results between enter_evidence and marginal_nodes
+engine.filter = [];
+engine.maximize = [];
+engine.T = [];
+
+engine.bel = [];
+engine.bel_clpot = [];
+engine.slice1 = [];
+%engine.pot_type = 'cg';
+% hack for online inference so we can cope with hidden Gaussians and discrete
+% it will not affect the pot type used in enter_evidence
+engine.pot_type = determine_pot_type(bnet, onodes);
+
+engine = class(engine, 'cbk_inf_engine', inf_engine(bnet));
+
+
+
+
+function [cliques, seps, jt_size] = build_jt(cliques, vars, ns)
+% BUILD_JT connects the cliques into a jtree, computes the respective 
+% separators and the size of the resulting jtree.
+%
+% [cliques, seps, jt_size] = build_jt(cliques, vars, ns)
+% ns(i) has to hold the size of vars(i)
+% vars has to be a superset of the union of cliques.
+
+%======== Compute the jtree with tool from BNT. This wants the vars to be 1:N.
+%==== Map from nodes to their indices.
+%disp('Computing jtree for cliques with vars and ns:');
+%cliques
+%vars
+%ns'
+
+inv_nodes = sparse(1,max(vars));
+N = length(vars);
+for i=1:N
+    inv_nodes(vars(i)) = i;
+end
+
+tmp_cliques = cell(1,length(cliques));
+%==== Temporarily map clique vars to their indices.
+for i=1:length(cliques)
+    tmp_cliques{i} = inv_nodes(cliques{i});
+end
+
+%=== Compute the jtree, using BNT.
+[jtree, root, B, w] = cliques_to_jtree(tmp_cliques, ns);
+
+
+%======== Now, compute the separators between connected cliques and their weights.
+seps = {};
+s_w = [];
+[is,js] = find(jtree > 0);
+for k=1:length(is)
+  i = is(k); j = js(k);
+  sep = vars(find(B(i,:) & B(j,:))); % intersect(cliques{i}, cliques{j});
+  if i>j | length(sep) == 0, continue; end;
+  seps{end+1} = sep;
+  s_w(end+1) = prod(ns(inv_nodes(seps{end})));
+end
+
+cl_w = sum(w);
+sep_w = sum(s_w);
+assert(cl_w > sep_w, 'Weight of cliques must be bigger than weight of separators');
+
+jt_size = cl_w + sep_w;
+% jt.cliques = cliques;
+% jt.seps = seps;
+% jt.size = jt_size;
+% jt.ns = ns';
+% jt;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function m = marginal_family(engine, i, t)
+% MARGINAL_FAMILY Compute the marginal on the specified family (bk)
+% marginal = marginal_family(engine, i, t)
+
+% This is just like inf_engine/marginal_family, except when we call
+% marginal_nodes, we provide a 4th argument, to tell it's a family.
+
+if nargin < 3, t = 1; end
+
+bnet = bnet_from_engine(engine);
+if t==1
+  m = marginal_nodes(engine, family(bnet.dag, i), t, 1);
+else
+  ss = length(bnet.intra);
+  fam = family(bnet.dag, i+ss);
+  if any(fam<=ss)
+    % i has a parent in the preceeding slice
+    % Hence the lowest numbered slice containing the family is t-1
+    m = marginal_nodes(engine, fam, t-1, 1);
+  else
+    % The family all fits inside slice t
+    % Hence shift the indexes back to slice 1
+    m = marginal_nodes(engine, fam-ss, t, 1);
+  end
+end     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,67 @@
+function marginal = marginal_nodes(engine, nodes, t, fam)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (bk)
+%
+%   marginal = marginal_nodes(engine, i, t)
+% returns Pr(X(i,t) | Y(1:T)), where X(i,t) is the i'th node in the t'th slice.
+% If enter_evidence used filtering instead of smoothing, this will return  Pr(X(i,t) | Y(1:t)).
+%
+%   marginal = marginal_nodes(engine, query, t)
+% returns Pr(X(query(1),t), ... X(query(end),t) | Y(1:T)),
+% where X(q,t) is the q'th node in the t'th slice. If q > ss (slice size), this is equal
+% to X(q mod ss, t+1). That is, 't' specifies the time slice of the earliest node.
+% 'query' cannot span more than 2 time slices.
+% Example:
+% Consider a DBN with 2 nodes per slice.
+% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3.
+
+if nargin < 3, t = 1; end
+if nargin < 4, fam = 0; else fam = 1; end
+
+
+% clpot{t} contains slice t-1 and t
+% Example
+% clpot #: 1    2    3
+% slices:  1  1,2  2,3
+% For filtering, we must take care not to take future evidence into account.
+% For smoothing, clpot{1} does not exist.
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+
+nodes2 = nodes;
+if ~engine.filter
+  if t < engine.T
+    slice = t+1;
+  else % earliest t is T, so all nodes fit in one slice
+    slice = engine.T;
+    nodes2 = nodes + ss;
+  end
+else
+  if t == 1
+   slice = 1;
+  else
+    if all(nodes<=ss)
+      slice = t;
+      nodes2 = nodes + ss;
+    elseif t == engine.T
+      slice = t;
+    else
+      slice = t + 1;
+    end
+  end
+end
+  
+if engine.filter & t==1
+  c = clq_containing_nodes(engine.sub_engine1, nodes2, fam);
+else
+  c = clq_containing_nodes(engine.sub_engine, nodes2, fam);
+end
+assert(c >= 1);
+bigpot = engine.clpot{c, slice};
+
+pot = marginalize_pot(bigpot, nodes2);
+marginal = pot_to_marginal(pot);
+
+% we convert the domain to the unrolled numbering system
+% so that update_ess extracts the right evidence.
+marginal.domain = nodes+(t-1)*ss;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@cbk_inf_engine/update_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function engine = update_engine(engine, newCPDs)
+% UPDATE_ENGINE Update the engine to take into account the new parameters (bk)
+% engine = update_engine(engine, newCPDs)
+
+engine.inf_engine = update_engine(engine.inf_engine, newCPDs);
+engine.sub_engine = update_engine(engine.sub_engine, newCPDs);
+
+bnet = bnet_from_engine(engine);
+eclass1 = bnet.equiv_class(:,1);
+engine.sub_engine1 = update_engine(engine.sub_engine1, newCPDs(1:max(eclass1)));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_soft_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/ff_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/filter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/smooth_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@ff_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+/enter_soft_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_soft_evidence1.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old/enter_soft_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function [marginals, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (bk_ff)
+% [marginals, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+
+assert(pot_type == 'd');
+[ss T] = size(CPDpot);
+fwd = cell(ss,T);
+hnodes = engine.hnodes(:)';
+onodes = engine.onodes(:)';
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes;
+onodes2 = [onodes onodes+ss];
+ns(onodes2) = 1;
+
+logscale = zeros(1,T);
+local_logscale = zeros(1,length(hnodes));
+
+t = 1;
+for i=hnodes
+  fwd{i,t} = CPDpot{i,t};
+end
+for i=onodes
+  p = parents(bnet.dag, i);
+  assert(length(p)==1);
+  ev = marginalize_pot(CPDpot{i,t}, p);
+  fwd{p,t} = multiply_by_pot(fwd{p,t}, ev);
+end
+for i=hnodes
+  [fwd{i,t}, local_logscale(i)] = normalize_pot(fwd{i,t});
+end
+logscale(t) = sum(local_logscale);
+
+for t=2:T
+  for i=hnodes
+    ps = parents(bnet.dag, i+ss);
+    assert(all(ps<=ss)); % in previous slice
+    prior = CPDpot{i,t};
+    for p=ps(:)'
+      prior = multiply_by_pot(prior, fwd{p,t-1});
+    end
+    fwd{i,t} = marginalize_pot(prior, i+ss);
+    fwd{i,t} = set_domain_pot(fwd{i,t}, i);
+  end
+  for i=onodes
+    p = parents(bnet.dag, i);
+    assert(length(p)==1);
+    temp = pot_to_marginal(CPDpot{i,t}); 
+    ev = dpot(p, ns(p), temp.T);
+    fwd{p,t} = multiply_by_pot(fwd{p,t}, ev);
+  end
+  
+  for i=hnodes
+    [fwd{i,t}, local_logscale(i)] = normalize_pot(fwd{i,t});
+  end
+  logscale(t) = sum(local_logscale);
+end
+
+marginals = fwd;
+loglik = sum(logscale);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old/enter_soft_evidence1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,94 @@
+function [marginals, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (ff)
+% [marginals, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+
+assert(pot_type == 'd');
+[ss T] = size(CPDpot);
+fwd = cell(ss,T);
+hnodes = engine.hnodes(:)';
+onodes = engine.onodes(:)';
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes;
+onodes2 = [onodes onodes+ss];
+ns(onodes2) = 1;
+
+logscale = zeros(1,T);
+H = length(hnodes);
+local_logscale = zeros(1,ss);
+
+obschild = zeros(1,ss);
+for i=hnodes
+  ocs = myintersect(children(bnet.dag, i), onodes);
+  assert(length(ocs)==1);
+  obschild(i) = ocs(1);
+end  
+  
+t = 1;
+for i=hnodes
+  fwd{i,t} = CPDpot{i,t};
+  c = obschild(i);
+  temp = pot_to_marginal(CPDpot{c,t}); 
+  ev = dpot(i, ns(i), temp.T);
+  fwd{i,t} = multiply_by_pot(fwd{i,t}, ev);
+  [fwd{i,t}, local_logscale(i)] = normalize_pot(fwd{i,t});
+end
+logscale(t) = sum(local_logscale);
+
+for t=2:T
+  for i=hnodes
+    ps = parents(bnet.dag, i+ss);
+    assert(all(ps<=ss)); % in previous slice
+    prior = CPDpot{i,t};
+    for p=ps(:)'
+      prior = multiply_by_pot(prior, fwd{p,t-1});
+    end
+    fwd{i,t} = marginalize_pot(prior, i+ss);
+    fwd{i,t} = set_domain_pot(fwd{i,t}, i);
+    c = obschild(i);
+    temp = pot_to_marginal(CPDpot{c,t});
+    ev = dpot(i, ns(i), temp.T);
+    fwd{i,t} = multiply_by_pot(fwd{i,t}, ev);
+    [fwd{i,t}, local_logscale(i)] = normalize_pot(fwd{i,t});
+  end
+  logscale(t) = sum(local_logscale);
+end
+
+loglik = sum(logscale);
+
+
+if filter
+  marginals = fwd;
+  return;
+end
+
+back = cell(ss,T);
+t = T;
+for i=hnodes
+  back{i,t} = dpot(i, ns(i));
+  back{i,t} = set_domain_pot(back{i,t}, i+ss);
+end
+for t=T-1:-1:1
+  for i=hnodes
+    pot = CPDpot{i,t+1};
+    pot = multiply_by_pot(pot, back{i,t+1});
+    c = obschild(i);
+    temp = pot_to_marginal(CPDpot{c,t+1});
+    ev = dpot(i, ns(i), temp.T);
+    pot = multiply_by_pot(pot, ev);
+    back{i,t} = marginalize_pot(pot, i);
+    back{i,t} = normalize_pot(back{i,t});
+    back{i,t} = set_domain_pot(back{i,t}, i+ss);
+  end
+end
+
+
+
+% COMBINE
+for t=1:T
+  for i=hnodes
+    back{i,t} = set_domain_pot(back{i,t}, i);
+    fwd{i,t} = multiply_by_pot(fwd{i,t}, back{i,t});
+    marginals{i,t} = normalize_pot(fwd{i,t});
+    %fwdback{i,t} = normalize_pot(multiply_pots(fwd{i,t}, back{i,t}));
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/Old/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function marginal = marginal_family(engine, i, t)
+% MARGINAL_FAMILY Compute the marginal on the specified family (ff)
+% marginal = marginal_family(engine, i, t)
+
+if nargin < 3, t = 1; end
+
+% The method is similar to the following HMM equation:
+% xi(i,j,t) = normalise( alpha(i,t) * transmat(i,j) * obsmat(j,t+1) * beta(j,t+1) )
+% where xi(i,j,t) = Pr(Q(t)=i, Q(t+1)=j | y(1:T))
+
+bnet = bnet_from_engine(engine);
+
+if myismember(i, engine.onodes)
+  ps = parents(bnet.dag, i);
+  p = ps(1);
+  marginal = pot_to_marginal(engine.marginals{p,t});
+  marginal.domain = [p i];
+  return;
+end
+
+if t==1
+  marginal = pot_to_marginal(engine.marginals{i,t});
+  return;
+end
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+pot = engine.CPDpot{i,t};
+c = engine.obschild(i);
+pot = multiply_by_pot(pot, engine.CPDpot{c,t});
+pot = multiply_by_pot(pot, engine.back{i,t});
+ps = parents(bnet.dag, i+ss);
+for p=ps(:)'
+  pot = multiply_by_pot(pot, engine.fwd{p,t-1});
+end
+marginal = pot_to_marginal(normalize_pot(pot));
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,62 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (ff)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or
+% column vector)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product (not yet supported), else sum-product [0]
+% filter -   if 1, do filtering, else smoothing [0]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+maximize = 0;
+filter = 0;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1}; 
+     case 'filter', filter = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+assert(~maximize);
+
+
+[ss T] = size(evidence);
+observed = ~isemptycell(evidence);
+bnet = bnet_from_engine(engine);
+%pot_type = determine_pot_type(find(observed(:,1)), bnet.cnodes_slice, bnet.intra);
+pot_type = determine_pot_type(bnet, observed);
+% we assume we can use the same pot_type in all slices
+
+CPDpot = convert_dbn_CPDs_to_pots(bnet, evidence, pot_type);
+
+% Now convert CPDs on observed nodes to be potentials just on their parents
+assert(pot_type == 'd');
+onodes = bnet.observed(:);
+ns = bnet.node_sizes_slice;
+ns(onodes) = 1;
+for t=1:T
+  for i=onodes
+    p = parents(bnet.dag, i);
+    %CPDpot{i,t} = set_domain_pot(CPDpot{i,t}, p); % leaves size too long
+    temp = pot_to_marginal(CPDpot{i,t});
+    CPDpot{i,t} = dpot(p, ns(p), temp.T); % assumes pot_type = d
+  end
+end
+
+[engine.marginals, engine.fwd, engine.back, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter);
+
+engine.CPDpot = CPDpot;
+engine.filter = filter;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/enter_soft_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function [marginals, fwd, back, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (ff)
+% [marginals, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+
+if filter
+  [fwd, loglik] = filter_evidence(engine, CPDpot, observed, pot_type);
+  marginals = fwd;
+  back = [];
+else
+  [marginals, fwd, back, loglik] = smooth_evidence(engine, CPDpot, observed, pot_type);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/ff_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,44 @@
+function engine = ff_inf_engine(bnet)
+% FF_INF_ENGINE Factored frontier inference engine for DBNs
+% engine = ff_inf_engine(bnet)
+%
+% The model must be topologically isomorphic to an HMM.
+% In addition, each hidden node is assumed to have at most one observed child,
+% and each observed child is assumed to have exactly one hidden parent.
+%
+% For details of this algorithm, see
+%  "The Factored Frontier Algorithm for Approximate Inference in DBNs",
+%   Kevin Murphy and Yair Weiss, UAI 2001.
+%
+% THIS IS HIGHLY EXPERIMENTAL CODE!
+
+ss = length(bnet.intra);
+onodes = bnet.observed;
+hnodes = mysetdiff(1:ss, onodes);
+
+[persistent_nodes, transient_nodes] = partition_dbn_nodes(bnet.intra, bnet.inter);
+assert(isequal(onodes, transient_nodes));
+assert(isequal(hnodes, persistent_nodes));
+
+engine.onodes = onodes;
+engine.hnodes = hnodes;
+engine.marginals = [];
+engine.fwd = [];
+engine.back = [];
+engine.CPDpot = [];
+engine.filter = [];
+
+obschild = zeros(1,ss);
+for i=engine.hnodes(:)'
+  %ocs = myintersect(children(bnet.dag, i), onodes);
+  ocs = children(bnet.intra, i);
+  assert(length(ocs) <= 1);
+  if length(ocs)==1
+    obschild(i) = ocs(1);
+  end
+end  
+engine.obschild = obschild;
+
+
+engine = class(engine, 'ff_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/filter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,48 @@
+function [fwd, loglik] = filter_evidence(engine, CPDpot, observed, pot_type)
+% [fwd, loglik] = filter_evidence(engine, CPDpot, observed, pot_type) (ff)
+
+[ss T] = size(CPDpot);
+fwd = cell(ss,T);
+hnodes = engine.hnodes(:)';
+onodes = engine.onodes(:)';
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes;
+onodes2 = [onodes onodes+ss];
+ns(onodes2) = 1;
+
+logscale = zeros(1,T);
+H = length(hnodes);
+local_logscale = zeros(1,ss);
+  
+t = 1;
+for i=hnodes
+  fwd{i,t} = CPDpot{i,t};
+  c = engine.obschild(i);
+  if c > 0
+    fwd{i,t} = multiply_by_pot(fwd{i,t}, CPDpot{c, t});
+  end
+  [fwd{i,t}, local_logscale(i)] = normalize_pot(fwd{i,t});
+end
+logscale(t) = sum(local_logscale);
+
+for t=2:T
+  for i=hnodes
+    ps = parents(bnet.dag, i+ss);
+    assert(all(ps<=ss)); % in previous slice
+    prior = CPDpot{i,t};
+    for p=ps(:)'
+      prior = multiply_by_pot(prior, fwd{p,t-1});
+    end
+    fwd{i,t} = marginalize_pot(prior, i+ss);
+    fwd{i,t} = set_domain_pot(fwd{i,t}, i);
+    c = engine.obschild(i);
+    if c > 0
+      fwd{i,t} = multiply_by_pot(fwd{i,t}, CPDpot{c,t});
+    end
+    [fwd{i,t}, local_logscale(i)] = normalize_pot(fwd{i,t});
+  end
+  logscale(t) = sum(local_logscale);
+end
+
+loglik = sum(logscale);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,44 @@
+function marginal = marginal_family(engine, i, t)
+% MARGINAL_FAMILY Compute the marginal on the specified family (ff)
+% marginal = marginal_family(engine, i, t)
+
+
+if engine.filter
+  error('can''t currently use marginal_family when filtering with ff');
+end
+
+if nargin < 3, t = 1; end
+
+% The method is similar to the following HMM equation:
+% xi(i,j,t) = normalise( alpha(i,t) * transmat(i,j) * obsmat(j,t+1) * beta(j,t+1) )
+% where xi(i,j,t) = Pr(Q(t)=i, Q(t+1)=j | y(1:T))
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+
+if myismember(i, engine.onodes)
+  ps = parents(bnet.dag, i);
+  p = ps(1);
+  marginal = pot_to_marginal(engine.marginals{ps(1),t});
+  fam = ([ps i]) + (t-1)*ss;
+elseif t==1
+  marginal = pot_to_marginal(engine.marginals{i,t});
+  fam = i + (t-1)*ss;
+else
+  pot = engine.CPDpot{i,t};
+  c = engine.obschild(i);
+  if c>0
+    pot = multiply_by_pot(pot, engine.CPDpot{c,t});
+  end
+  pot = multiply_by_pot(pot, engine.back{i,t});
+  ps = parents(bnet.dag, i+ss);
+  for p=ps(:)'
+    pot = multiply_by_pot(pot, engine.fwd{p,t-1});
+  end
+  marginal = pot_to_marginal(normalize_pot(pot));
+  fam = ([ps i+ss]) + (t-2)*ss;
+end
+
+% we convert the domain to the unrolled numbering system
+% so that update_ess extracts the right evidence.
+marginal.domain = fam;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,20 @@
+function marginal = marginal_nodes(engine, nodes, t)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (ff)
+% marginal = marginal_nodes(engine, i, t)
+% returns Pr(X(i,t) | Y(1:T)), where X(i,t) is the i'th node in the t'th slice.
+% If enter_evidence used filtering instead of smoothing, this will return  Pr(X(i,t) | Y(1:t)).
+
+if nargin < 3, t = 1; end
+assert(length(nodes)==1);
+i = nodes(end);
+if myismember(i, engine.hnodes)
+  marginal = pot_to_marginal(engine.marginals{i,t});
+else
+  marginal = pot_to_marginal(dpot(i, 1, 1)); % observed
+end
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+% we convert the domain to the unrolled numbering system
+% so that update_ess extracts the right evidence.
+marginal.domain = nodes+(t-1)*ss;   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@ff_inf_engine/smooth_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,89 @@
+function [marginals, fwd, back, loglik] = smooth_evidence(engine, CPDpot, observed, pot_type)
+% [marginals, fwd, back, loglik] = smooth_evidence(engine, CPDpot, observed, pot_type) (ff)
+
+error('ff smoothing is broken');
+
+[ss T] = size(CPDpot);
+fwd = cell(ss,T);
+hnodes = engine.hnodes(:)';
+onodes = engine.onodes(:)';
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes;
+onodes2 = [onodes onodes+ss];
+ns(onodes2) = 1;
+
+logscale = zeros(1,T);
+H = length(hnodes);
+local_logscale = zeros(1,ss);
+  
+t = 1;
+for i=hnodes
+  fwd{i,t} = CPDpot{i,t};
+  c = engine.obschild(i);
+  if 0 %  c > 0
+    fwd{i,t} = multiply_by_pot(fwd{i,t}, CPDpot{c, t});
+  end
+  [fwd{i,t}, local_logscale(i)] = normalize_pot(fwd{i,t});
+end
+logscale(t) = sum(local_logscale);
+
+for t=2:T
+  for i=hnodes
+    ps = parents(bnet.dag, i+ss);
+    assert(all(ps<=ss)); % in previous slice
+    prior = CPDpot{i,t};
+    for p=ps(:)'
+      prior = multiply_by_pot(prior, fwd{p,t-1});
+    end
+    fwd{i,t} = marginalize_pot(prior, i+ss);
+    fwd{i,t} = set_domain_pot(fwd{i,t}, i);
+    c = engine.obschild(i);
+    if 0 % c > 0
+      fwd{i,t} = multiply_by_pot(fwd{i,t}, CPDpot{c,t});
+    end
+    [fwd{i,t}, local_logscale(i)] = normalize_pot(fwd{i,t});
+  end
+  logscale(t) = sum(local_logscale);
+end
+
+loglik = sum(logscale);
+
+back = cell(ss,T);
+t = T;
+for i=hnodes
+  pot = dpot(i, ns(i));
+  cs = children(bnet.intra, i);
+  for c=cs(:)'
+    pot = multiply_pots(pot, CPDpot{c,t});
+  end
+  back{i,t} = marginalize_pot(pot, i);
+  back{i,t} = normalize_pot(back{i,t});
+  back{i,t} = set_domain_pot(back{i,t}, i+ss);
+end
+for t=T-1:-1:1
+  for i=hnodes
+    pot = dpot(i, ns(i));
+    cs = children(bnet.inter, i);
+    for c=cs(:)'
+      pot = multiply_pots(pot, back{c,t+1});
+      pot = multiply_pots(pot, CPDpot{c,t+1});
+    end
+    cs = children(bnet.intra, i);
+    for c=cs(:)'
+      pot = multiply_pots(pot, CPDpot{c,t});
+    end
+    back{i,t} = marginalize_pot(pot, i);
+    back{i,t} = normalize_pot(back{i,t});
+    back{i,t} = set_domain_pot(back{i,t}, i+ss);
+  end
+end
+
+
+% COMBINE
+for t=1:T
+  for i=hnodes
+    back{i,t} = set_domain_pot(back{i,t}, i);
+    fwd{i,t} = multiply_by_pot(fwd{i,t}, back{i,t});
+    marginals{i,t} = normalize_pot(fwd{i,t});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@frontier_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_soft_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/frontier_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/set_fwdback.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@frontier_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@frontier_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@frontier_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@frontier_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,44 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (frontier)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product (not yet supported), else sum-product [0]
+% filter -   if 1, do filtering, else smoothing [0]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+maximize = 0;
+filter = 0;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1}; 
+     case 'filter', filter = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+assert(~maximize);
+
+[ss T] = size(evidence);
+bnet = bnet_from_engine(engine);
+onodes = find(~isemptycell(evidence));
+cnodes = unroll_set(bnet.cnodes(:), ss, T);
+pot_type = determine_pot_type(bnet, onodes);
+
+CPDpot = convert_dbn_CPDs_to_pots(bnet, evidence, pot_type);
+
+[engine.fwdback, loglik, engine.fwd_frontier, engine.back_frontier] = ...
+    enter_soft_evidence(engine, CPDpot, onodes, pot_type, filter);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@frontier_inf_engine/enter_soft_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,142 @@
+function [fwdback, loglik, fwd_frontier, back_frontier] = enter_soft_evidence(engine, CPD, onodes, pot_type, filter)
+% ENTER_SOFT_EVIDENCE Add soft evidence to network (frontier)
+% [fwdback, loglik] = enter_soft_evidence(engine, CPDpot, onodes, filter)
+
+if nargin < 3, filter = 0; end
+
+[ss T] = size(CPD);
+bnet = bnet_from_engine(engine);
+ns = repmat(bnet.node_sizes_slice(:), 1, T);
+cnodes = unroll_set(bnet.cnodes(:), ss, T);
+
+% FORWARDS
+fwd = cell(ss,T);
+ll = zeros(1,T);
+S = 2*ss; % num. intermediate frontiers to get from t to t+1
+frontier = cell(S,T);
+
+% Start with empty frontier, and add each node in slice 1
+init = mk_initial_pot(pot_type, [], ns, cnodes, onodes);  
+t = 1;
+s = 1;
+j = 1;
+frontier{s,t} = update(init, j, 1, CPD{j}, engine.fdom1{s}, pot_type, ns, cnodes, onodes);
+fwd{j} = frontier{s,t};
+for s=2:ss
+  j = s; % add node j at step s
+  frontier{s,t} = update(frontier{s-1,t}, j, 1, CPD{j}, engine.fdom1{s}, pot_type, ns, cnodes, onodes);
+  fwd{j} = frontier{s,t};
+end
+frontier{S,t} = frontier{ss,t};
+[frontier{S,t}, ll(1)] = normalize_pot(frontier{S,t});
+
+% Now move frontier from slice to slice
+OPS = engine.ops;
+add = OPS>0;
+nodes = [zeros(S,1) unroll_set(abs(OPS(:)), ss, T-1)];
+for t=2:T
+  offset = (t-2)*ss;
+  for s=1:S
+    if s==1
+      prev_ndx = (t-2)*S + S; % S,t-1
+    else
+      prev_ndx = (t-1)*S + s-1; % s-1,t
+    end
+    j = nodes(s,t);
+    frontier{s,t} = update(frontier{prev_ndx}, j, add(s), CPD{j}, engine.fdom{s}+offset, pot_type, ns, cnodes, onodes);
+    if add(s)
+      fwd{j} = frontier{s,t};
+    end
+  end
+  [frontier{S,t}, ll(t)] = normalize_pot(frontier{S,t});
+end
+loglik = sum(ll);
+
+
+fwd_frontier = frontier;
+
+if filter
+  fwdback = fwd;
+  return;
+end
+
+
+% BACKWARDS
+back = cell(ss,T);
+add = ~add; % forwards add = backwards remove 
+frontier = cell(S,T+1);
+t = T;
+dom = (1:ss) + (t-1)*ss;
+frontier{1,T+1} = mk_initial_pot(pot_type, dom, ns, cnodes, onodes); % all 1s for last slice
+for t=T:-1:2
+  offset = (t-2)*ss;
+  for s=S:-1:1 % reverse order
+    if s==S
+      prev_ndx = t*S + 1; % 1,t+1
+    else
+      prev_ndx = (t-1)*S + (s+1); % s+1,t
+    end
+    j = nodes(s,t);
+    if ~add(s)
+      back{j} = frontier{prev_ndx}; % save frontier before removing
+    end
+    frontier{s,t} = rev_update(frontier{prev_ndx}, t, s, j, add(s), CPD{j}, engine.fdom{s}+offset, pot_type, ns, cnodes, onodes);
+  end
+  frontier{1,t} = normalize_pot(frontier{1,t});
+end
+% Remove each node in first slice until left with empty set
+t = 1;
+frontier{ss+1,t} = frontier{1,2};
+add = 0;
+for s=ss:-1:1
+  j = s; % remove node j at step s
+  back{j} = frontier{s+1,t};
+  frontier{s,t} = rev_update(frontier{s+1,t}, t, s, j, add, CPD{j}, 1:s, pot_type, ns, cnodes, onodes);
+end
+
+% COMBINE
+for t=1:T
+  for i=1:ss
+    %fwd{i,t} = multiply_by_pot(fwd{i,t}, back{i,t});
+    %fwdback{i,t} = normalize_pot(fwd{i,t});
+    fwdback{i,t} = normalize_pot(multiply_pots(fwd{i,t}, back{i,t}));
+  end
+end
+
+back_frontier = frontier;
+
+%%%%%%%%%%
+function new_frontier = update(old_frontier, j, add, CPD, newdom, pot_type, ns, cnodes, onodes)
+
+if add
+  new_frontier = mk_initial_pot(pot_type, newdom, ns, cnodes, onodes);      
+  new_frontier = multiply_by_pot(new_frontier, old_frontier);
+  new_frontier = multiply_by_pot(new_frontier, CPD);
+else
+  new_frontier = marginalize_pot(old_frontier, mysetdiff(domain_pot(old_frontier), j));    
+end
+
+
+%%%%%%
+function new_frontier = rev_update(old_frontier, t, s, j, add, CPD, junk, pot_type, ns, cnodes, onodes)
+
+olddom = domain_pot(old_frontier);
+assert(isequal(junk, olddom));
+
+if add
+  % add: extend domain to include j by multiplying by 1
+  newdom = myunion(olddom, j);
+  new_frontier = mk_initial_pot(pot_type, newdom, ns, cnodes, onodes);      
+  new_frontier = multiply_by_pot(new_frontier, old_frontier);
+  %fprintf('t=%d, s=%d, add %d to %s to make %s\n', t, s, j, num2str(olddom), num2str(newdom));
+else 
+  % remove: multiply in CPT and then marginalize out j
+  % parents of j are guaranteed to be in old_frontier, else couldn't have added j on fwds pass
+  old_frontier = multiply_by_pot(old_frontier, CPD);
+  newdom = mysetdiff(olddom, j);
+  new_frontier = marginalize_pot(old_frontier, newdom);
+  %newdom2 = domain_pot(new_frontier);
+  %fprintf('t=%d, s=%d, rem %d from %s to make %s\n', t, s, j, num2str(olddom), num2str(newdom2));
+end
+
+       
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@frontier_inf_engine/frontier_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,121 @@
+function engine = frontier_inf_engine(bnet)
+% FRONTIER_INF_ENGINE Inference engine for DBNs which which uses the frontier algorithm.
+% engine = frontier_inf_engine(bnet)
+%
+% The frontier algorithm extends the forwards-backwards algorithm to DBNs in the obvious way,
+% maintaining a joint distribution (frontier) over all the nodes in a time slice.
+% When all the hidden nodes in the DBN are persistent (have children in the next time slice),
+% its theoretical running time is often similar to that of the junction tree algorithm,
+% although in practice, this algorithm seems to very slow (at least in matlab).
+% However, it is extremely simple to describe and implement.
+%
+% Suppose there are n binary nodes per slice, so the frontier takes O(2^n) space.
+% Each time step takes between O(n 2^{n+1}) and O(n 2^{2n}) operations, depending on the graph structure.
+% The lower bound is achieved by a set of n independent chains, as in a factorial HMM.
+% The upper bound is achieved by a set of n fully interconnected chains, as in an HMM.
+%
+% The factor of n arises because we need to multiply in each CPD from slice t+1.
+% The second factor depends on the size of the frontier to which we add the new node.
+% In an FHMM, once we have added X(i,t+1), we can marginalize out X(i,t) from the frontier, since
+% no other nodes depend on it; hence the frontier never contains more than n+1 nodes.
+% In a fully coupled HMM, we must leave X(i,t) in the frontier until all X(j,t+1) have been
+% added; hence the frontier will contain 2*n nodes at its peak.
+%
+% For details, see
+%   "The Factored Frontier Algorithm for Approximate Inference in DBNs",
+%   Kevin Murphy and Yair Weiss, UAI 01.
+
+ns = bnet.node_sizes_slice;
+onodes = bnet.observed;
+ns(onodes) = 1;
+ss = length(bnet.intra);
+
+[engine.ops, engine.fdom] = best_first_frontier_seq(ns, bnet.dag);
+engine.ops1 = 1:ss;
+
+engine.fwdback = [];
+engine.fwd_frontier = [];
+engine.back_frontier = [];
+
+engine.fdom1 = cell(1,ss);
+for s=1:ss
+  engine.fdom1{s} = 1:s;
+end
+
+engine = class(engine, 'frontier_inf_engine', inf_engine(bnet));
+
+
+%%%%%%%%%
+
+function [ops, frontier_set] = best_first_frontier_seq(ns, dag)
+% BEST_FIRST_FRONTIER_SEQ Do a greedy search for the sequence of additions/removals to the frontier.
+% [ops, frontier_set] = best_first_frontier_seq(ns, dag)
+%
+% We maintain 3 sets: the frontier (F), the right set (R), and the left set (L).
+% The invariant is that the nodes in R are d-separated from L given F.
+% We start with slice 1 in F and slice 2 in R.
+% The goal is to move slice 1 from F to L, and slice 2 from R to F, so as to minimize the size
+% of the frontier at each step, where the size(F) = product of the node-sizes of nodes in F.
+% A node may be removed (from F to L) if it has no children in R.
+% A node may be added (from R to F) if its parents are in F.
+%
+% ns(i) = num. discrete values node i can take on (i=1..ss, where ss = slice size)
+% dag is the (2*ss) x (2*ss) adjacency matrix for the 2-slice DBN.
+
+% Example:
+%
+% 4    9
+% ^    ^
+% |    |
+% 2 -> 7
+% ^    ^
+% |    |
+% 1 -> 6
+% |    |
+% v    v
+% 3 -> 8
+% |    |
+% v    V
+% 5    10
+%
+% ops = -4, -5, 6, -1, 7, -2, 8, -3, 9, 10
+
+ss = length(ns);
+ns = [ns(:)' ns(:)'];
+ops = zeros(1,ss);
+L = []; F = 1:ss; R = (1:ss)+ss;
+frontier_set = cell(1,2*ss);
+for s=1:2*ss
+  remcost = inf*ones(1,2*ss);
+  %disp(['L: ' num2str(L) ', F: ' num2str(F) ', R: ' num2str(R)]);
+  maybe_removable = myintersect(F, 1:ss);
+  for n=maybe_removable(:)'
+    cs = children(dag, n);
+    if isempty(myintersect(cs, R))
+      remcost(n) = prod(ns(mysetdiff(F, n)));
+    end
+  end
+  %remcost
+  if any(remcost < inf)
+    n = argmin(remcost);
+    ops(s) = -n;
+    L = myunion(L, n);
+    F = mysetdiff(F, n);
+  else
+    addcost = inf*ones(1,2*ss);
+    for n=R(:)'
+      ps = parents(dag, n);
+      if mysubset(ps, F)
+	addcost(n) = prod(ns(myunion(F, [ps n])));
+      end
+    end
+    %addcost
+    assert(any(addcost < inf));
+    n = argmin(addcost);
+    ops(s) = n;
+    R  = mysetdiff(R, n);
+    F = myunion(F, n);
+  end
+  %fprintf('op at step %d = %d\n\n', s, ops(s));
+  frontier_set{s} = F;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@frontier_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function marginal = marginal_family(engine, i, t)
+% MARGINAL_FAMILY Compute the marginal on node i in slice t and its parents  (frontier)
+% marginal = marginal_family(engine, i, t)
+
+bnet = bnet_from_engine(engine);    
+fam = family(bnet.dag, i, t);
+marginal = pot_to_marginal(normalize_pot(marginalize_pot(engine.fwdback{i,t}, fam)));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@frontier_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function marginal = marginal_nodes(engine, nodes, t)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (frontier)
+% marginal = marginal_nodes(engine, nodes, t)
+%
+% 't' specifies the time slice of the earliest node in 'nodes'.
+% 'nodes' cannot span more than 2 time slices.
+%
+% Example:
+% Consider a DBN with 2 nodes per slice.
+% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3,
+% i.e., nodes 3 and 5 in the unrolled network,
+
+if nargin < 3, t = 1; end
+assert(length(nodes)==1);
+i = nodes(1);
+bigpot = engine.fwdback{i,t};
+bnet = bnet_from_engine(engine);
+ss  = length(bnet.intra);
+nodes = nodes + (t-1)*ss;
+%if t > 1, nodes = nodes + ss; end
+marginal = pot_to_marginal(marginalize_pot(bigpot, nodes));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@frontier_inf_engine/set_fwdback.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function engine = set_fwdback(engine, fb)
+% SET_FWDBACK Set the field 'fwdback', which contains the frontiers after propagation
+% engine = set_fwdback(engine, fb)
+%
+% This is used by frontier_fast_inf_engine/enter_evidence
+% as a workaround for Matlab's annoying privacy control
+    
+engine.fwdback = fb;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+/enter_evidence.m/1.2/Sat Sep 17 17:00:30 2005//
+/find_mpe.m/1.1.1.1/Thu Jun 20 00:18:24 2002//
+/fwdback_twoslice.m/1.1/Sat Nov 26 01:24:09 2005//
+/hmm_inf_engine.m/1.1.1.1/Thu Nov 14 20:05:36 2002//
+/marginal_family.m/1.1.1.1/Thu Nov 14 20:05:36 2002//
+/marginal_nodes.m/1.1.1.1/Thu Nov 14 20:03:28 2002//
+/update_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D/Old////
+D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@hmm_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+/dhmm_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old/dhmm_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,34 @@
+function engine = dhmm_inf_engine(bnet, onodes)
+% DHMM_INF_ENGINE Inference engine for discrete DBNs which uses the forwards-backwards algorithm.
+% engine = dhmm_inf_engine(bnet, onodes)
+%
+% 'onodes' specifies which nodes are observed; these must be leaves, and can be discrete or continuous.
+% The remaining nodes are all hidden, and must be discrete.
+% The DBN is converted to an HMM, with a single meganode, but which may have factored obs.
+
+ss = length(bnet.intra);
+hnodes = mysetdiff(1:ss, onodes);
+evidence = cell(ss, 2);
+ns = bnet.node_sizes;
+Q = prod(ns(hnodes));
+tmp = dpot_to_table(compute_joint_pot(bnet, hnodes, evidence));
+engine.startprob = reshape(tmp, Q, 1);
+tmp = dpot_to_table(compute_joint_pot(bnet, [hnodes hnodes+ss], evidence));
+engine.transprob = mk_stochastic(reshape(tmp, Q, Q));
+engine.obsprob = cell(1, length(onodes));
+for i=1:length(onodes)
+  tmp = dpot_to_table(compute_joint_pot(bnet, [hnodes onodes(i)], evidence));
+  O = ns(onodes(i));
+  engine.obsprob{i} = mk_stochastic(reshape(tmp, Q, O));
+end
+
+% This is where we will store the results between enter_evidence and marginal_nodes
+engine.gamma = [];
+engine.xi = [];
+
+engine.onodes = onodes;
+engine.hnodes = hnodes;
+engine.maximize = [];
+
+engine = class(engine, 'dhmm_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,31 @@
+function marginal = marginal_family(engine, i, t, add_ev)
+% MARGINAL_FAMILY Compute the marginal on the specified family  (hmm)
+% marginal = marginal_nodes(engine, i, t, add_ev)
+%
+
+if nargin < 3, t = 1; end
+if nargin < 4, add_ev = 0; end
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+if t==1
+ fam = family(bnet.dag, i);
+ bigpot = engine.one_slice_marginal{t};
+ nodes = fam;
+else
+  fam = family(bnet.dag, i+ss);
+  if any(fam <= ss) % family spans 2 slices
+    bigpot = engine.two_slice_marginal{t-1}; % t-1 and t
+    nodes = fam + (t-2)*ss;
+  else
+    bigpot = engine.one_slice_marginal{t};
+    nodes = fam-ss + (t-1)*ss;
+  end
+end
+
+marginal = pot_to_marginal(marginalize_pot(bigpot, nodes, engine.maximize));
+
+if add_ev
+  marginal = add_ev_to_dmarginal(marginal, engine.evidence, engine.node_sizes);
+end    
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/Old/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function marginal = marginal_nodes(engine, nodes, t, add_ev)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (hmm)
+% marginal = marginal_nodes(engine, nodes, t, add_ev)
+%
+% 't' specifies the time slice of the earliest node in 'nodes'.
+% 'nodes' cannot span more than 2 time slices.
+%
+% Example:
+% Consider a DBN with 2 nodes per slice.
+% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3,
+% i.e., nodes 3 and 5 in the unrolled network,
+
+if nargin < 3, t = 1; end
+if nargin < 4, add_ev = 0; end
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+if all(nodes <= ss)
+  bigpot = engine.one_slice_marginal{t};
+else
+  bigpot = engine.two_slice_marginal{t};
+end
+
+nodes = nodes + (t-1)*ss;
+marginal = pot_to_marginal(marginalize_pot(bigpot, nodes, engine.maximize));
+
+if add_ev
+  marginal = add_ev_to_dmarginal(marginal, engine.evidence, engine.node_sizes);
+end    
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (hmm)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product (not yet supported), else sum-product [0]
+% filter   - if 1, does filtering, else smoothing [0]
+% oneslice - 1 means only compute marginals on nodes within a single slice [0]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+maximize = 0;
+filter = 0;
+oneslice = 0;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1}; 
+     case 'filter',  filter = args{i+1}; 
+     case 'oneslice', oneslice = args{i+1};
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+[ss T] = size(evidence);
+engine.maximize = maximize;
+engine.evidence = evidence;
+bnet = bnet_from_engine(engine);
+engine.node_sizes = repmat(bnet.node_sizes_slice(:), [1 T]);
+
+obs_bitv = ~isemptycell(evidence(:));
+bitv = reshape(obs_bitv, ss, T);
+for t=1:T
+  onodes = find(bitv(:,t));
+  if ~isequal(onodes, bnet.observed(:))
+    error(['dbn was created assuming observed nodes per slice were '...
+	   num2str(bnet.observed(:)')  ' but the evidence in slice ' num2str(t) ...
+	   ' has observed nodes ' num2str(onodes(:)')]);
+  end
+end
+
+obslik = mk_hmm_obs_lik_matrix(engine, evidence);
+
+%[alpha, beta, gamma, loglik, xi] = fwdback(engine.startprob, engine.transprob, obslik, ...
+[alpha, beta, gamma, loglik, xi] = fwdback_twoslice(engine, engine.startprob,...
+                                                    engine.transprob, obslik, ...
+                                                    'maximize', maximize, 'fwd_only', filter, ...
+                                                    'compute_xi', ~oneslice);
+
+engine.one_slice_marginal = gamma; % gamma(:,t) for t=1:T
+if ~oneslice
+  Q = size(gamma,1);
+  engine.two_slice_marginal = reshape(xi, [Q*Q T-1]); % xi(:,t) for t=1:T-1
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/find_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function mpe = find_mpe(engine, evidence)
+% FIND_MPE Find the most probable explanation (Viterbi)
+% mpe = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+
+obslik = mk_hmm_obs_lik_matrix(engine, evidence);
+path = viterbi_path(engine.startprob, engine.transprob, obslik);
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes_slice;
+ns(bnet.observed) = 1;
+ass = ind2subv(ns, path);
+mpe = num2cell(ass');
+mpe(bnet.observed,:) = evidence(bnet.observed,:);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/fwdback_twoslice.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,198 @@
+function [alpha, beta, gamma, loglik, xi, gamma2] = fwdback_twoslice(engine, init_state_distrib, transmat, obslik, varargin)
+% FWDBACK Compute the posterior probs. in an HMM using the forwards backwards algo.
+%
+% [alpha, beta, gamma, loglik, xi, gamma2] = fwdback(init_state_distrib, transmat, obslik, ...)
+%
+% Notation:
+% Y(t) = observation, Q(t) = hidden state, M(t) = mixture variable (for MOG outputs)
+% A(t) = discrete input (action) (for POMDP models)
+%
+% INPUT:
+% init_state_distrib(i) = Pr(Q(1) = i)
+% transmat(i,j) = Pr(Q(t) = j | Q(t-1)=i)
+%  or transmat{a}(i,j) = Pr(Q(t) = j | Q(t-1)=i, A(t-1)=a) if there are discrete inputs
+% obslik(i,t) = Pr(Y(t)| Q(t)=i)
+%   (Compute obslik using eval_pdf_xxx on your data sequence first.)
+%
+% Optional parameters may be passed as 'param_name', param_value pairs.
+% Parameter names are shown below; default values in [] - if none, argument is mandatory.
+%
+% For HMMs with MOG outputs: if you want to compute gamma2, you must specify
+% 'obslik2' - obslik(i,j,t) = Pr(Y(t)| Q(t)=i,M(t)=j)  []
+% 'mixmat' - mixmat(i,j) = Pr(M(t) = j | Q(t)=i)  []
+%
+% For HMMs with discrete inputs:
+% 'act' - act(t) = action performed at step t
+%
+% Optional arguments:
+% 'fwd_only' - if 1, only do a forwards pass and set beta=[], gamma2=[]  [0]
+% 'scaled' - if 1,  normalize alphas and betas to prevent underflow [1]
+% 'maximize' - if 1, use max-product instead of sum-product [0]
+%
+% OUTPUTS:
+% alpha(i,t) = p(Q(t)=i | y(1:t)) (or p(Q(t)=i, y(1:t)) if scaled=0)
+% beta(i,t) = p(y(t+1:T) | Q(t)=i)*p(y(t+1:T)|y(1:t)) (or p(y(t+1:T) | Q(t)=i) if scaled=0)
+% gamma(i,t) = p(Q(t)=i | y(1:T))
+% loglik = log p(y(1:T))
+% xi(i,j,t-1)  = p(Q(t-1)=i, Q(t)=j | y(1:T))
+% gamma2(j,k,t) = p(Q(t)=j, M(t)=k | y(1:T)) (only for MOG  outputs)
+%
+% If fwd_only = 1, these become
+% alpha(i,t) = p(Q(t)=i | y(1:t))
+% beta = []
+% gamma(i,t) = p(Q(t)=i | y(1:t))
+% xi(i,j,t-1)  = p(Q(t-1)=i, Q(t)=j | y(1:t))
+% gamma2 = []
+%
+% Note: we only compute xi if it is requested as a return argument, since it can be very large.
+% Similarly, we only compute gamma2 on request (and if using MOG outputs).
+%
+% Examples:
+%
+% [alpha, beta, gamma, loglik] = fwdback(pi, A, multinomial_prob(sequence, B));
+%
+% [B, B2] = mixgauss_prob(data, mu, Sigma, mixmat);
+% [alpha, beta, gamma, loglik, xi, gamma2] = fwdback(pi, A, B, 'obslik2', B2, 'mixmat', mixmat);
+
+
+if nargout >= 5, compute_xi = 1; else compute_xi = 0; end
+if nargout >= 6, compute_gamma2 = 1; else compute_gamma2 = 0; end
+
+[obslik2, mixmat, fwd_only, scaled, act, maximize, compute_xi, compute_gamma2] = process_options(varargin, 'obslik2', [], 'mixmat', [], 'fwd_only', 0, 'scaled', 1, 'act', [], 'maximize', 0, 'compute_xi', compute_xi, 'compute_gamma2', compute_gamma2);
+
+
+[Q T] = size(obslik);
+
+if isempty(obslik2)
+  compute_gamma2 = 0;
+end
+
+if isempty(act)
+  act = ones(1,T);
+  transmat = { transmat } ;
+end
+
+scale = ones(1,T);
+
+% scale(t) = Pr(O(t) | O(1:t-1)) = 1/c(t) as defined by Rabiner (1989).
+% Hence prod_t scale(t) = Pr(O(1)) Pr(O(2)|O(1)) Pr(O(3) | O(1:2)) = Pr(O(1), ... ,O(T))
+% or log P = sum_t log scale(t).
+% Rabiner suggests multiplying beta(t) by scale(t), but we can instead
+% normalise beta(t) - the constants will cancel when we compute gamma.
+
+loglik = 0;
+
+alpha = zeros(Q,T);
+gamma = zeros(Q,T);
+if compute_xi
+  xi = zeros(Q,Q,T-1);
+else
+  xi = [];
+end
+
+
+%%%%%%%%% Forwards %%%%%%%%%%
+
+t = 1;
+alpha(:,1) = init_state_distrib(:) .* obslik(:,t);
+if scaled
+  %[alpha(:,t), scale(t)] = normaliseC(alpha(:,t));
+  [alpha(:,t), scale(t)] = normalise(alpha(:,t));
+end
+if scaled, assert(approxeq(sum(alpha(:,t)),1)), end
+for t=2:T
+  %trans = transmat(:,:,act(t-1))';
+  trans = transmat{act(t-1)};
+  if maximize
+    m = max_mult(trans', alpha(:,t-1));
+    %A = repmat(alpha(:,t-1), [1 Q]);
+    %m = max(trans .* A, [], 1);
+  else
+    m = trans' * alpha(:,t-1);
+  end
+  alpha(:,t) = m(:) .* obslik(:,t);
+  if scaled
+    %[alpha(:,t), scale(t)] = normaliseC(alpha(:,t));
+    [alpha(:,t), scale(t)] = normalise(alpha(:,t));
+  end
+  if compute_xi & fwd_only  % useful for online EM
+    %xi(:,:,t-1) = normaliseC((alpha(:,t-1) * obslik(:,t)') .* trans);
+    xi(:,:,t-1) = normalise((alpha(:,t-1) * obslik(:,t)') .* trans);
+  end
+  if scaled, assert(approxeq(sum(alpha(:,t)),1)), end
+end
+if scaled
+  if any(scale==0)
+    loglik = -inf;
+  else
+    loglik = sum(log(scale));
+  end
+else
+  loglik = log(sum(alpha(:,T)));
+end
+
+if fwd_only
+  gamma = alpha;
+  beta = [];
+  gamma2 = [];
+  return;
+end
+
+
+%%%%%%%%% Backwards %%%%%%%%%%
+
+beta = zeros(Q,T);
+if compute_gamma2
+  M = size(mixmat, 2);
+  gamma2 = zeros(Q,M,T);
+else
+  gamma2 = [];
+end
+
+beta(:,T) = ones(Q,1);
+%gamma(:,T) = normaliseC(alpha(:,T) .* beta(:,T));
+gamma(:,T) = normalise(alpha(:,T) .* beta(:,T));
+t=T;
+if compute_gamma2
+  denom = obslik(:,t) + (obslik(:,t)==0); % replace 0s with 1s before dividing
+  gamma2(:,:,t) = obslik2(:,:,t) .* mixmat .* repmat(gamma(:,t), [1 M]) ./ repmat(denom, [1 M]);
+  %gamma2(:,:,t) = normaliseC(obslik2(:,:,t) .* mixmat .* repmat(gamma(:,t), [1 M])); % wrong!
+end
+for t=T-1:-1:1
+  b = beta(:,t+1) .* obslik(:,t+1);
+  %trans = transmat(:,:,act(t));
+  trans = transmat{act(t)};
+  if maximize
+    B = repmat(b(:)', Q, 1);
+    beta(:,t) = max(trans .* B, [], 2);
+  else
+    beta(:,t) = trans * b;
+  end
+  if scaled
+    %beta(:,t) = normaliseC(beta(:,t));
+    beta(:,t) = normalise(beta(:,t));
+  end
+  %gamma(:,t) = normaliseC(alpha(:,t) .* beta(:,t));
+  gamma(:,t) = normalise(alpha(:,t) .* beta(:,t));
+  if compute_xi
+    %xi(:,:,t) = normaliseC((trans .* (alpha(:,t) * b')));
+    xi(:,:,t) = normalise((trans .* (alpha(:,t) * b')));
+    %xi(:,:,t) = (trans .* (alpha(:,t) * b'));
+  end
+  if compute_gamma2
+    denom = obslik(:,t) + (obslik(:,t)==0); % replace 0s with 1s before dividing
+    gamma2(:,:,t) = obslik2(:,:,t) .* mixmat .* repmat(gamma(:,t), [1 M]) ./ repmat(denom, [1 M]);
+    %gamma2(:,:,t) = normaliseC(obslik2(:,:,t) .* mixmat .* repmat(gamma(:,t), [1 M]));
+  end
+end
+
+
+% We now explain the equation for gamma2
+% Let zt=y(1:t-1,t+1:T) be all observations except y(t)
+% gamma2(Q,M,t) = P(Qt,Mt|yt,zt) = P(yt|Qt,Mt,zt) P(Qt,Mt|zt) / P(yt|zt)
+%                = P(yt|Qt,Mt) P(Mt|Qt) P(Qt|zt) / P(yt|zt)
+% Now gamma(Q,t) = P(Qt|yt,zt) = P(yt|Qt) P(Qt|zt) / P(yt|zt)
+% hence
+% P(Qt,Mt|yt,zt) = P(yt|Qt,Mt) P(Mt|Qt) [P(Qt|yt,zt) P(yt|zt) / P(yt|Qt)] / P(yt|zt)
+%                = P(yt|Qt,Mt) P(Mt|Qt) P(Qt|yt,zt) / P(yt|Qt)
+%
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/hmm_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,71 @@
+function engine = hmm_inf_engine(bnet, varargin)
+% HMM_INF_ENGINE Inference engine for DBNs which uses the forwards-backwards algorithm.
+% engine = hmm_inf_engine(bnet, ...)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - 1 means max-product, 0 means sum-product [0]
+%
+% The DBN is converted to an HMM with a single meganode, but the observed nodes remain factored.
+% This can be faster than jtree if the num. hidden nodes is low, because of lower constant factors.
+%
+% All hidden nodes must be discrete.
+% All observed nodes are assumed to be leaves, i.e., they cannot be parents of anything.
+% The parents of each observed leaf are assumed to be a subset of the hidden nodes within the same slice.
+% The only exception is if bnet is an AR-HMM, where the parents are assumed to be self in the
+% previous slice (continuous), plus all the discrete nodes in the current slice.
+
+ss = bnet.nnodes_per_slice;
+
+engine.maximize = 0;
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', engine.maximize = args{i+1};
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+% Stuff to do with speeding up marginal_family
+[int, engine.persist, engine.transient] = compute_interface_nodes(bnet.intra, bnet.inter);
+engine.persist_bitv = zeros(1, ss);
+engine.persist_bitv(engine.persist) = 1;
+
+
+ns = bnet.node_sizes(:);
+ns(bnet.observed) = 1;
+ns(bnet.observed+ss) = 1;
+engine.eff_node_sizes = ns;
+
+for o=bnet.observed(:)'
+  %if bnet.equiv_class(o,1) ~= bnet.equiv_class(o,2)
+  %  error(['observed node ' num2str(o) ' is not tied'])
+  %end
+  cs = children(bnet.dag, o);
+  if ~isempty(cs)
+    error(['observed node ' num2str(o) ' is not allowed children'])
+  end
+end
+
+[engine.startprob, engine.transprob, engine.obsprob] = dbn_to_hmm(bnet);
+
+% This is where we will store the results between enter_evidence and marginal_nodes
+engine.one_slice_marginal = [];
+engine.two_slice_marginal = [];
+
+ss = length(bnet.intra);
+engine.evidence = [];
+engine.node_sizes = [];
+
+% avoid the need to do bnet_from_engine, which is slow
+engine.slice_size = ss;
+engine.parents = bnet.parents;
+
+engine = class(engine, 'hmm_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,35 @@
+function marginal = marginal_family(engine, i, t, add_ev)
+% MARGINAL_FAMILY Compute the marginal on the specified family (hmm)
+% marginal = marginal_family(engine, i, t, add_ev)
+
+if nargin < 3, t = 1; end
+if nargin < 4, add_ev = 0; end
+
+ns = engine.eff_node_sizes(:);
+ss = engine.slice_size;
+
+if t==1 | ~engine.persist_bitv(i)
+  bigT = engine.one_slice_marginal(:,t);
+  ps = engine.parents{i};
+  dom = [ps i] + (t-1)*ss;
+  bigdom = 1:ss;
+  bigsz = ns(bigdom);
+  bigdom = bigdom + (t-1)*ss;
+else % some parents are in previous slice
+  bigT = engine.two_slice_marginal(:,t-1); % t-1 and t
+  ps = engine.parents{i+ss};
+  dom = [ps i+ss] + (t-2)*ss; 
+  bigdom = 1:(2*ss); % domain of xi(:,:,t)
+  bigsz = ns(bigdom);
+  bigdom = bigdom + (t-2)*ss;
+end
+marginal.domain = dom;
+
+marginal.T = marg_table(bigT, bigdom, bigsz, dom, engine.maximize); 
+marginal.mu = []; 
+marginal.Sigma = [];
+
+if add_ev
+  marginal = add_ev_to_dmarginal(marginal, engine.evidence, engine.node_sizes);
+end    
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+function marginal = marginal_nodes(engine, nodes, t, add_ev)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (hmm)
+% marginal = marginal_nodes(engine, nodes, t, add_ev)
+%
+% 'nodes' must be a single node.
+% t is the time slice.
+
+if nargin < 3, t = 1; end
+if nargin < 4, add_ev = 0; end
+
+assert(length(nodes)==1)
+ss = engine.slice_size;
+
+i = nodes(1);
+bigT = engine.one_slice_marginal(:,t);
+dom = i + (t-1)*ss;
+
+ns = engine.eff_node_sizes(:);
+bigdom = 1:ss;
+marginal.T = marg_table(bigT, bigdom + (t-1)*ss, ns(bigdom), dom, engine.maximize);
+
+marginal.domain = dom;
+marginal.mu = [];
+marginal.Sigma = [];
+
+if add_ev
+  marginal = add_ev_to_dmarginal(marginal, engine.evidence, engine.node_sizes);
+end    
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+/mk_hmm_obs_lik_matrix.m/1.1.1.1/Sun May  4 21:42:26 2003//
+/mk_hmm_obs_lik_vec.m/1.1.1.1/Thu Jan 23 18:50:10 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@hmm_inf_engine/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/private/mk_hmm_obs_lik_matrix.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function obslik = mk_hmm_obs_lik_matrix(engine, evidence)
+
+T  = size(evidence,2);
+Q = length(engine.startprob);
+obslik = ones(Q, T);
+bnet = bnet_from_engine(engine);
+% P(o1,o2| Q1,Q2) = P(o1|Q1,Q2) * P(o2|Q1,Q2)
+onodes = bnet.observed;
+for i=1:length(onodes)
+  data = cell2num(evidence(onodes(i),:));
+  if bnet.auto_regressive(onodes(i))
+    params = engine.obsprob{i};
+    mu = params.big_mu;
+    Sigma = params.big_Sigma,
+    W = params.big_W;
+    mu0 = params.big_mu0;
+    Sigma0 = params.big_Sigma0;
+    %obslik_i = mk_arhmm_obs_lik(data, mu, Sigma, W, mu0, Sigma0
+    obslik_i = clg_prob(data(:,1:T-1), data(:,2:T), mu, Sigma, W);
+    obslik_i = [mixgauss_prob(data(:,1), mu0, Sigma0) obslik_i];
+  elseif myismember(onodes(i), bnet.dnodes)
+    %obslik_i = eval_pdf_cond_multinomial(data, engine.obsprob{i}.big_CPT);
+    obslik_i = multinomial_prob(data, engine.obsprob{i}.big_CPT);
+  else
+    %obslik_i = eval_pdf_cond_gauss(data, engine.obsprob{i}.big_mu, engine.obsprob{i}.big_Sigma);
+    obslik_i = mixgauss_prob(data, engine.obsprob{i}.big_mu, engine.obsprob{i}.big_Sigma);
+  end
+  obslik = obslik .* obslik_i;
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/private/mk_hmm_obs_lik_vec.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+function obslik = mk_hmm_obs_lik_vec(engine, evidence)
+
+% P(o1,o2| h) = P(o1|h) * P(o2|h) where h = Q1,Q2,...
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+onodes = bnet.observed;
+hnodes = mysetdiff(1:ss, onodes);
+ns = bnet.node_sizes(:);
+ns(onodes) = 1;
+
+Q = length(engine.startprob);
+obslik = ones(Q, 1);
+
+for i=1:length(onodes)
+  o = onodes(i);
+  %data = cell2num(evidence(o,1));
+  data = evidence{o,1};
+  if myismember(o, bnet.dnodes)
+    obslik_i = eval_pdf_cond_multinomial(data, engine.obsprob{i}.CPT);
+  else
+    if bnet.auto_regressive(o)
+      error('can''t handle AR nodes')
+    end
+    %% calling mk_ghmm_obs_lik, which calls gaussian_prob, is slow, so we inline it
+    %% and use the pre-computed  inverse matrix
+    %obslik_i = mk_ghmm_obs_lik(data, engine.obsprob{i}.mu, engine.obsprob{i}.Sigma);
+    x = data(:);
+    m = engine.obsprob{i}.mu;
+    Qi = size(m, 2);
+    obslik_i = size(Qi, 1);
+    invC = engine.obsprob{i}.inv_Sigma;
+    denom = engine.obsprob{i}.denom;
+    for j=1:Qi
+      numer = exp(-0.5 * (x-m(:,j))' * invC(:,:,j) * (x-m(:,j)));
+      obslik_i(j) = numer / denom(j);
+    end
+  end
+  % convert P(o|ps) into P(o|h) by multiplying onto a (h,o) potential of all 1s
+  ps = bnet.parents{o};
+  dom = [ps o];
+  obspot_i = dpot(dom, ns(dom), obslik_i);
+  dom = [hnodes o];
+  obspot = dpot(dom, ns(dom));
+  obspot = multiply_by_pot(obspot, obspot_i);
+  % compute p(oi|h) * p(oj|h)
+  S = struct(obspot);
+  obslik = obslik .* S.T(:);
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@hmm_inf_engine/update_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function engine = update_engine(engine, newCPDs)
+% UPDATE_ENGINE Update the engine to take into account the new parameters (hmm)
+% engine = update_engine(engine, newCPDs)
+
+%engine.inf_engine.bnet.CPD = newCPDs;
+engine.inf_engine = update_engine(engine.inf_engine, newCPDs);
+[engine.startprob, engine.transprob, engine.obsprob] = dbn_to_hmm(bnet_from_engine(engine));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/enter_soft_evidence1.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_soft_evidence2.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_soft_evidence3.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_soft_evidence4.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,119 @@
+function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type)
+% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn)
+% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+
+[ss T] = size(CPDpot);
+Q = length(engine.jtree_struct.cliques);
+clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) 
+seppot = cell(Q,Q,T);
+ll = zeros(1,Q);
+logscale = zeros(1,T);
+bnet = bnet_from_engine(engine);
+
+% Forwards pass.
+% Compute distribution on clq C,
+% where C is the out interface to (t-1,t).
+% Then pass this to clq D, where D is the in inferface to (t+1,t).
+% Then propagate from D to later slices.
+
+C = engine.out_clq;
+assert(C==engine.jtree_struct.root_clq);
+D = engine.in_clq;
+slice1 = 1:ss;
+slice2 = slice1 + ss;
+for t=2:T
+  if t==2
+    clqs = engine.jtree_struct.clq_ass_to_node([slice1 slice2]);
+    pots = CPDpot(:,t-1:t);
+  else
+    %clqs = [D; engine.clq_ass_to_node(:,2)];
+    clqs = [D engine.jtree_struct.clq_ass_to_node(slice2)];
+    phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1
+    pots = [ {phiC}; CPDpot(:,t)]; % CPDpot domains are always slice 2
+  end
+  [clpot(:,t), seppot(:,:,t)] =  init_pot(engine.jtree_struct.cliques, clqs, pots, pot_type, ...
+					 find(observed(:,t-1:t)), bnet.node_sizes(:), bnet.cnodes);
+  [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.postorder, ...
+						    engine.jtree_struct.postorder_parents,...
+						    engine.jtree_struct.separator);
+
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  logscale(t) = ll(C);
+
+  phiC = marginalize_pot(clpot{C,t}, engine.interface+ss, engine.maximize);
+end
+
+
+
+% Backwards pass.
+% Pass evidence from clq C to clq D,
+% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t)
+% Then propagate evidence from D to earlier slices.
+C = engine.in_clq;
+D = engine.out_clq;
+for t=T:-1:2
+  [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.preorder, ...
+						    engine.jtree_struct.preorder_children, ...
+						    engine.jtree_struct.separator);
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  logscale(t) = ll(C);
+  
+  if t >= 3
+    phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize);
+    phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2
+    phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize);
+    ratio = divide_by_pot(phiC, phiD);
+    clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio);
+  end
+end
+
+loglik = sum(logscale);
+
+
+%%%%%%%
+function [clpot, seppot] = init_pot(cliques, clqs, pots, pot_type, onodes, ns, cnodes);
+
+% Set the clique potentials to all 1s
+C = length(cliques);
+clpot = cell(1,C);
+for i=1:C
+  clpot{i} = mk_initial_pot(pot_type, cliques{i}, ns, cnodes, onodes);
+end
+
+% Multiply on specified potentials
+for i=1:length(clqs)
+  c = clqs(i);
+  clpot{c} = multiply_by_pot(clpot{c}, pots{i});
+end
+
+seppot = cell(C,C); % implicitely initialized to 1
+
+
+%%%%
+function [clpot, seppot] = collect_evidence(clpot, seppot, maximize, postorder, postorder_parents,...
+					    separator)
+for n=postorder %postorder(1:end-1)
+  for p=postorder_parents{n}
+    %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant
+    seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n}, maximize);
+    clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n});
+  end
+end
+
+
+%%%%
+function [clpot, seppot] = distribute_evidence(clpot, seppot, maximize, preorder, preorder_children,...
+					       separator)
+for n=preorder
+  for c=preorder_children{n}
+    clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); 
+    seppot{n,c} = marginalize_pot(clpot{n}, separator{n,c}, maximize);
+    clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,143 @@
+function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type)
+% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn)
+% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+
+[ss T] = size(CPDpot);
+Q = length(engine.jtree_struct.cliques);
+clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) 
+seppot = cell(Q,Q,T);
+ll = zeros(1,Q);
+logscale = ones(1,T); % log(logscale(1)) = 0
+bnet = bnet_from_engine(engine);
+
+slice1 = 1:ss;
+slice2 = slice1+ss;
+
+% calibrate each 2-slice jtree in isolation
+for t=2:T
+  if t==2
+    clqs = engine.jtree_struct.clq_ass_to_node([slice1 slice2]);
+    pots = CPDpot(:,t-1:t);
+  else
+    clqs = engine.jtree_struct.clq_ass_to_node(slice2);
+    pots = CPDpot(:,t); % CPDpot domains are always slice 2
+  end
+  [clpot(:,t), sepot(:,:,t)] =  init_pot(engine.jtree_struct.cliques, clqs, pots, pot_type, ...
+					 find(observed(:,t-1:t)), bnet.node_sizes(:), bnet.cnodes);
+  [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.postorder, ...
+						    engine.jtree_struct.postorder_parents,...
+						    engine.jtree_struct.separator);
+  [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.preorder, ...
+						    engine.jtree_struct.preorder_children, ...
+						    engine.jtree_struct.separator);
+end
+
+% Forwards pass.
+% Compute distribution on clq C,
+% where C is the out interface to (t-1,t).
+% Then pass this to clq D, where D is the in inferface to (t+1,t).
+% Then propagate from D to later slices.
+
+C = engine.out_clq;
+D = engine.in_clq;
+for t=2:T-1
+  phiC = marginalize_pot(clpot{C,t}, engine.interface+ss, engine.maximize);
+  phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1
+  phiD = marginalize_pot(clpot{D,t+1}, engine.interface, engine.maximize);
+  ratio = divide_by_pot(phiC, phiD);
+  clpot{D,t+1} = multiply_by_pot(clpot{D,t+1}, ratio);
+
+  [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.preorder, ...
+						    engine.jtree_struct.preorder_children, ...
+						    engine.jtree_struct.separator);
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  logscale(t) = ll(1);
+end
+
+% Backwards pass.
+% Pass evidence from clq C to clq D,
+% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t)
+% Then propagate evidence from D to earlier slices.
+C = engine.in_clq;
+D = engine.out_clq;
+for t=T:-1:2
+  [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						 engine.jtree_struct.postorder, ...
+						 engine.jtree_struct.postorder_parents,...
+						 engine.jtree_struct.separator);
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  logscale(t) = ll(1);
+
+  if t >= 3
+    phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize);
+    phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2
+    phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize);
+    ratio = divide_by_pot(phiC, phiD);
+    clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio);
+  end
+end
+
+loglik = sum(logscale);
+
+%%%%%%%%%%
+
+function [clpot, seppot] = calibrate(engine, clpot, seppot)
+
+  [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.postorder, ...
+						    engine.jtree_struct.postorder_parents,...
+						    engine.jtree_struct.separator);
+  [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.preorder, ...
+						    engine.jtree_struct.preorder_children, ...
+						    engine.jtree_struct.separator);
+
+
+%%%%%%%
+function [clpot, seppot] = init_pot(cliques, clqs, pots, pot_type, onodes, ns, cnodes);
+
+% Set the clique potentials to all 1s
+C = length(cliques);
+clpot = cell(1,C);
+for i=1:C
+  clpot{i} = mk_initial_pot(pot_type, cliques{i}, ns, cnodes, onodes);
+end
+
+% Multiply on specified potentials
+for i=1:length(clqs)
+  c = clqs(i);
+  clpot{c} = multiply_by_pot(clpot{c}, pots{i});
+end
+
+seppot = cell(C,C); % implicitely initialized to 1
+
+
+%%%%
+function [clpot, seppot] = collect_evidence(clpot, seppot, maximize, postorder, postorder_parents,...
+					    separator)
+for n=postorder %postorder(1:end-1)
+  for p=postorder_parents{n}
+    %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant
+    seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n}, maximize);
+    clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n});
+  end
+end
+
+
+%%%%
+function [clpot, seppot] = distribute_evidence(clpot, seppot, maximize, preorder, preorder_children,...
+					       separator)
+for n=preorder
+  for c=preorder_children{n}
+    clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); 
+    seppot{n,c} = marginalize_pot(clpot{n}, separator{n,c}, maximize);
+    clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence3.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,125 @@
+function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type)
+% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn)
+% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+
+[ss T] = size(CPDpot);
+Q = length(engine.jtree_struct.cliques);
+clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) 
+seppot = cell(Q,Q,T);
+ll = zeros(1,Q);
+logscale = zeros(1,T);
+bnet = bnet_from_engine(engine);
+
+% Forwards pass.
+% Compute distribution on clq C,
+% where C is the out interface to (t-1,t).
+% Then pass this to clq D, where D is the in inferface to (t+1,t).
+% Then propagate from D to later slices.
+
+C = engine.out_clq;
+assert(C==engine.jtree_struct.root_clq);
+D = engine.in_clq;
+slice1 = 1:ss;
+slice2 = slice1 + ss;
+Ntransient = length(engine.transient);
+trans = cell(Ntransient,1);
+for t=2:T
+  if t==2
+    clqs = engine.jtree_struct.clq_ass_to_node([slice1 slice2]);
+    pots = CPDpot(:,t-1:t);
+  else
+    %clqs = [D; engine.clq_ass_to_node(:,2)];
+    clqs = [D engine.jtree_struct.clq_ass_to_node([engine.transient slice2])];
+    phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1
+    for i=1:Ntransient
+      trans{i} = CPDpot{engine.transient(i), t-1};
+      trans{i} = set_domain_pot(trans{i}, domain_pot(trans{i})-ss); % shift back to slice 1
+    end
+    pots = [ {phiC}; trans; CPDpot(:,t)]; 
+  end
+  [clpot(:,t), seppot(:,:,t)] =  init_pot(engine.jtree_struct.cliques, clqs, pots, pot_type, ...
+					 find(observed(:,t-1:t)), bnet.node_sizes(:), bnet.cnodes);
+  [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.postorder, ...
+						    engine.jtree_struct.postorder_parents,...
+						    engine.jtree_struct.separator);
+
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  logscale(t) = ll(C);
+
+  phiC = marginalize_pot(clpot{C,t}, engine.interface+ss, engine.maximize);
+end
+
+
+
+% Backwards pass.
+% Pass evidence from clq C to clq D,
+% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t)
+% Then propagate evidence from D to earlier slices.
+C = engine.in_clq;
+D = engine.out_clq;
+for t=T:-1:2
+  [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.preorder, ...
+						    engine.jtree_struct.preorder_children, ...
+						    engine.jtree_struct.separator);
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  logscale(t) = ll(C);
+  
+  if t >= 3
+    phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize);
+    phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2
+    phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize);
+    ratio = divide_by_pot(phiC, phiD);
+    clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio);
+  end
+end
+
+loglik = sum(logscale);
+
+
+%%%%%%%
+function [clpot, seppot] = init_pot(cliques, clqs, pots, pot_type, onodes, ns, cnodes);
+
+% Set the clique potentials to all 1s
+C = length(cliques);
+clpot = cell(1,C);
+for i=1:C
+  clpot{i} = mk_initial_pot(pot_type, cliques{i}, ns, cnodes, onodes);
+end
+
+% Multiply on specified potentials
+for i=1:length(clqs)
+  c = clqs(i);
+  clpot{c} = multiply_by_pot(clpot{c}, pots{i});
+end
+
+seppot = cell(C,C); % implicitely initialized to 1
+
+
+%%%%
+function [clpot, seppot] = collect_evidence(clpot, seppot, maximize, postorder, postorder_parents,...
+					    separator)
+for n=postorder %postorder(1:end-1)
+  for p=postorder_parents{n}
+    %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant
+    seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n}, maximize);
+    clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n});
+  end
+end
+
+
+%%%%
+function [clpot, seppot] = distribute_evidence(clpot, seppot, maximize, preorder, preorder_children,...
+					       separator)
+for n=preorder
+  for c=preorder_children{n}
+    clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); 
+    seppot{n,c} = marginalize_pot(clpot{n}, separator{n,c}, maximize);
+    clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/enter_soft_evidence4.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,149 @@
+function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type)
+% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn)
+% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+
+[ss T] = size(CPDpot);
+Q = length(engine.jtree_struct.cliques);
+clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) 
+seppot = cell(Q,Q,T);
+ll = zeros(1,Q);
+logscale = ones(1,T); % log(logscale(1)) = 0
+bnet = bnet_from_engine(engine);
+
+slice1 = 1:ss;
+slice2 = slice1+ss;
+Ntransient = length(engine.transient);
+trans = cell(Ntransient,1);
+
+% calibrate each 2-slice jtree in isolation
+for t=2:T
+  if t==2
+    clqs = engine.jtree_struct.clq_ass_to_node([slice1 slice2]);
+    pots = CPDpot(:,t-1:t);
+  else
+    clqs = engine.jtree_struct.clq_ass_to_node([engine.transient slice2]);
+    for i=1:Ntransient
+      trans{i} = CPDpot{engine.transient(i), t-1};
+      trans{i} = set_domain_pot(trans{i}, domain_pot(trans{i})-ss); % shift back to slice 1
+    end
+    pots = [ trans; CPDpot(:,t)]; 
+  end
+  [clpot(:,t), sepot(:,:,t)] =  init_pot(engine.jtree_struct.cliques, clqs, pots, pot_type, ...
+					 find(observed(:,t-1:t)), bnet.node_sizes(:), bnet.cnodes);
+  [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.postorder, ...
+						    engine.jtree_struct.postorder_parents,...
+						    engine.jtree_struct.separator);
+  [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.preorder, ...
+						    engine.jtree_struct.preorder_children, ...
+						    engine.jtree_struct.separator);
+end
+
+% Forwards pass.
+% Compute distribution on clq C,
+% where C is the out interface to (t-1,t).
+% Then pass this to clq D, where D is the in inferface to (t+1,t).
+% Then propagate from D to later slices.
+
+C = engine.out_clq;
+D = engine.in_clq;
+for t=2:T-1
+  phiC = marginalize_pot(clpot{C,t}, engine.interface+ss, engine.maximize);
+  phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1
+  phiD = marginalize_pot(clpot{D,t+1}, engine.interface, engine.maximize);
+  ratio = divide_by_pot(phiC, phiD);
+  clpot{D,t+1} = multiply_by_pot(clpot{D,t+1}, ratio);
+
+  [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.preorder, ...
+						    engine.jtree_struct.preorder_children, ...
+						    engine.jtree_struct.separator);
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  logscale(t) = ll(1);
+end
+
+% Backwards pass.
+% Pass evidence from clq C to clq D,
+% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t)
+% Then propagate evidence from D to earlier slices.
+C = engine.in_clq;
+D = engine.out_clq;
+for t=T:-1:2
+  [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						 engine.jtree_struct.postorder, ...
+						 engine.jtree_struct.postorder_parents,...
+						 engine.jtree_struct.separator);
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  logscale(t) = ll(1);
+
+  if t >= 3
+    phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize);
+    phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2
+    phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize);
+    ratio = divide_by_pot(phiC, phiD);
+    clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio);
+  end
+end
+
+loglik = sum(logscale);
+
+%%%%%%%%%%
+
+function [clpot, seppot] = calibrate(engine, clpot, seppot)
+
+  [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.postorder, ...
+						    engine.jtree_struct.postorder_parents,...
+						    engine.jtree_struct.separator);
+  [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.preorder, ...
+						    engine.jtree_struct.preorder_children, ...
+						    engine.jtree_struct.separator);
+
+
+%%%%%%%
+function [clpot, seppot] = init_pot(cliques, clqs, pots, pot_type, onodes, ns, cnodes);
+
+% Set the clique potentials to all 1s
+C = length(cliques);
+clpot = cell(1,C);
+for i=1:C
+  clpot{i} = mk_initial_pot(pot_type, cliques{i}, ns, cnodes, onodes);
+end
+
+% Multiply on specified potentials
+for i=1:length(clqs)
+  c = clqs(i);
+  clpot{c} = multiply_by_pot(clpot{c}, pots{i});
+end
+
+seppot = cell(C,C); % implicitely initialized to 1
+
+
+%%%%
+function [clpot, seppot] = collect_evidence(clpot, seppot, maximize, postorder, postorder_parents,...
+					    separator)
+for n=postorder %postorder(1:end-1)
+  for p=postorder_parents{n}
+    %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant
+    seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n}, maximize);
+    clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n});
+  end
+end
+
+
+%%%%
+function [clpot, seppot] = distribute_evidence(clpot, seppot, maximize, preorder, preorder_children,...
+					       separator)
+for n=preorder
+  for c=preorder_children{n}
+    clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); 
+    seppot{n,c} = marginalize_pot(clpot{n}, separator{n,c}, maximize);
+    clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Broken/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,51 @@
+function marginal = marginal_nodes(engine, nodes, t, fam)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (bk)
+%
+%   marginal = marginal_nodes(engine, i, t)
+% returns Pr(X(i,t) | Y(1:T)), where X(i,t) is the i'th node in the t'th slice.
+%
+%   marginal = marginal_nodes(engine, query, t)
+% returns Pr(X(query(1),t), ... X(query(end),t) | Y(1:T)),
+% where 't' specifies the time slice of the earliest node in the query.
+% 'query' cannot span more than 2 time slices.
+%
+% Example:
+% Consider a DBN with 2 nodes per slice.
+% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3.
+
+if nargin < 3, t = 1; end
+if nargin < 4, fam = 0; else fam = 1; end
+
+
+% clpot{t} contains slice t-1 and t
+% Example
+% clpot #: 1    2    3
+% slices:  1  1,2  2,3
+% For filtering, we must take care not to take future evidence into account.
+% For smoothing, clpot{1} does not exist.
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+
+if t < engine.T
+  slice = t+1;
+  nodes2 = nodes;
+else % earliest t is T, so all nodes fit in one slice
+  slice = engine.T;
+  nodes2 = nodes + ss;
+end
+  
+c = clq_containing_nodes(engine.jtree_engine, nodes2, fam);
+assert(c >= 1);
+
+%disp(['computing marginal on ' num2str(nodes) ' t = ' num2str(t)]);
+%disp(['using ' num2str(nodes2) ' slice = ' num2str(slice) 'clq = ' num2str(c)]);
+
+bigpot = engine.clpot{c, slice};
+
+pot = marginalize_pot(bigpot, nodes2, engine.maximize);
+marginal = pot_to_marginal(pot);
+
+% we convert the domain to the unrolled numbering system
+% so that update_ess extracts the right evidence.
+marginal.domain = nodes+(t-1)*ss;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/enter_evidence.m/1.1.1.1/Sat Jan 11 18:41:30 2003//
+/enter_soft_evidence.m/1.1.1.1/Thu Feb 19 01:12:08 2004//
+/jtree_dbn_inf_engine.m/1.1.1.1/Thu Nov 14 16:32:00 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Fri Nov 22 23:51:58 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+A D/Broken////
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/enter_soft_evidence_nonint.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_soft_evidence_trans.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/jtree_dbn_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/jtree_dbn_inf_engine1.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/jtree_dbn_inf_engine2.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/enter_soft_evidence_nonint.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,135 @@
+function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type)
+% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn)
+% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+
+[ss T] = size(CPDpot);
+Q = length(engine.jtree_struct.cliques);
+clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) 
+seppot = cell(Q,Q,T);
+ll = zeros(1,Q);
+logscale = zeros(1,T);
+bnet = bnet_from_engine(engine);
+
+% Forwards pass.
+% Compute distribution on clq C,
+% where C is the out interface to (t-1,t).
+% Then pass this to clq D, where D is the in inferface to (t+1,t).
+% Then propagate from D to later slices.
+
+C = engine.out_clq;
+assert(C==engine.jtree_struct.root_clq);
+D = engine.in_clq;
+slice1 = 1:ss;
+slice2 = slice1 + ss;
+Nnonint = length(engine.nonint);
+nonint = cell(Nnonint, 1);
+for t=1:T
+  if t==1
+    pots = [CPDpot(:,1); CPDpot(engine.interface, 2)];
+    clqs = engine.jtree_struct.clq_ass_to_node([slice1 engine.interface+ss]);
+    obs = find(observed(:,1:2));
+  elseif t==T
+    clqs = [D engine.jtree_struct.clq_ass_to_node(engine.nonint)];
+    phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1
+    for i=1:Nnonint
+      nonint{i} = CPDpot{engine.nonint(i), t};
+      nonint{i} = set_domain_pot(nonint{i}, domain_pot(nonint{i})-ss); % shift back to slice 1
+    end
+    pots = [ {phiC}; nonint]; 
+    obs = find(observed(:,T));
+  else
+    clqs = [D engine.jtree_struct.clq_ass_to_node([engine.nonint engine.interface+ss])];
+    phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1
+    for i=1:Nnonint
+      nonint{i} = CPDpot{engine.nonint(i), t};
+      nonint{i} = set_domain_pot(nonint{i}, domain_pot(nonint{i})-ss); % shift back to slice 1
+    end
+    pots = [ {phiC}; nonint; CPDpot(engine.interface, t+1)]; 
+    obs = find(observed(:,t:t+1));
+  end
+  [clpot(:,t), seppot(:,:,t)] =  init_pot(engine.jtree_struct.cliques, clqs, pots, pot_type, ...
+					 obs, bnet.node_sizes(:), bnet.cnodes);
+  [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.postorder, ...
+						    engine.jtree_struct.postorder_parents,...
+						    engine.jtree_struct.separator);
+
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  logscale(t) = ll(C);
+
+  phiC = marginalize_pot(clpot{C,t}, engine.interface+ss, engine.maximize);
+end
+
+
+
+% Backwards pass.
+% Pass evidence from clq C to clq D,
+% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t)
+% Then propagate evidence from D to earlier slices.
+C = engine.in_clq;
+D = engine.out_clq;
+for t=T:-1:1
+  [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.preorder, ...
+						    engine.jtree_struct.preorder_children, ...
+						    engine.jtree_struct.separator);
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  %logscale(t) = ll(C);
+  
+  if t >= 2
+    phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize);
+    phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2
+    phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize);
+    ratio = divide_by_pot(phiC, phiD);
+    clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio);
+  end
+end
+
+loglik = sum(logscale);
+
+
+%%%%%%%
+function [clpot, seppot] = init_pot(cliques, clqs, pots, pot_type, onodes, ns, cnodes);
+
+% Set the clique potentials to all 1s
+C = length(cliques);
+clpot = cell(1,C);
+for i=1:C
+  clpot{i} = mk_initial_pot(pot_type, cliques{i}, ns, cnodes, onodes);
+end
+
+% Multiply on specified potentials
+for i=1:length(clqs)
+  c = clqs(i);
+  clpot{c} = multiply_by_pot(clpot{c}, pots{i});
+end
+
+seppot = cell(C,C); % implicitely initialized to 1
+
+
+%%%%
+function [clpot, seppot] = collect_evidence(clpot, seppot, maximize, postorder, postorder_parents,...
+					    separator)
+for n=postorder %postorder(1:end-1)
+  for p=postorder_parents{n}
+    %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant
+    seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n}, maximize);
+    clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n});
+  end
+end
+
+
+%%%%
+function [clpot, seppot] = distribute_evidence(clpot, seppot, maximize, preorder, preorder_children,...
+					       separator)
+for n=preorder
+  for c=preorder_children{n}
+    clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); 
+    seppot{n,c} = marginalize_pot(clpot{n}, separator{n,c}, maximize);
+    clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/enter_soft_evidence_trans.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,135 @@
+function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type)
+% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn)
+% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type, filter)
+
+[ss T] = size(CPDpot);
+Q = length(engine.jtree_struct.cliques);
+clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) 
+seppot = cell(Q,Q,T);
+ll = zeros(1,Q);
+logscale = zeros(1,T);
+bnet = bnet_from_engine(engine);
+
+% Forwards pass.
+% Compute distribution on clq C,
+% where C is the out interface to (t-1,t).
+% Then pass this to clq D, where D is the in inferface to (t+1,t).
+% Then propagate from D to later slices.
+
+C = engine.out_clq;
+assert(C==engine.jtree_struct.root_clq);
+D = engine.in_clq;
+slice1 = 1:ss;
+slice2 = slice1 + ss;
+Ntransient = length(engine.transient);
+trans = cell(Ntransient,1);
+for t=1:T
+  if t==1
+    pots = [CPDpot(:,1); CPDpot(engine.persist, 2)];
+    clqs = engine.jtree_struct.clq_ass_to_node([slice1 engine.persist+ss]);
+    obs = find(observed(:,1:2));
+  elseif t==T
+    clqs = [D engine.jtree_struct.clq_ass_to_node(engine.transient)];
+    phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1
+    for i=1:Ntransient
+      trans{i} = CPDpot{engine.transient(i), t};
+      trans{i} = set_domain_pot(trans{i}, domain_pot(trans{i})-ss); % shift back to slice 1
+    end
+    pots = [ {phiC}; trans]; 
+    obs = find(observed(:,T));
+  else
+    clqs = [D engine.jtree_struct.clq_ass_to_node([engine.transient engine.persist+ss])];
+    phiC = set_domain_pot(phiC, engine.interface); % shift back to slice 1
+    for i=1:Ntransient
+      trans{i} = CPDpot{engine.transient(i), t};
+      trans{i} = set_domain_pot(trans{i}, domain_pot(trans{i})-ss); % shift back to slice 1
+    end
+    pots = [ {phiC}; trans; CPDpot(engine.persist, t+1)]; 
+    obs = find(observed(:,t:t+1));
+  end
+  [clpot(:,t), seppot(:,:,t)] =  init_pot(engine.jtree_struct.cliques, clqs, pots, pot_type, ...
+					 obs, bnet.node_sizes(:), bnet.cnodes);
+  [clpot(:,t), seppot(:,:,t)] = collect_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.postorder, ...
+						    engine.jtree_struct.postorder_parents,...
+						    engine.jtree_struct.separator);
+
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  logscale(t) = ll(C);
+
+  phiC = marginalize_pot(clpot{C,t}, engine.interface+ss, engine.maximize);
+end
+
+
+
+% Backwards pass.
+% Pass evidence from clq C to clq D,
+% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t)
+% Then propagate evidence from D to earlier slices.
+C = engine.in_clq;
+D = engine.out_clq;
+for t=T:-1:1
+  [clpot(:,t), seppot(:,:,t)] = distribute_evidence(clpot(:,t), seppot(:,:,t), engine.maximize, ...
+						    engine.jtree_struct.preorder, ...
+						    engine.jtree_struct.preorder_children, ...
+						    engine.jtree_struct.separator);
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  %logscale(t) = ll(C);
+  
+  if t >= 2
+    phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize);
+    phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2
+    phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize);
+    ratio = divide_by_pot(phiC, phiD);
+    clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio);
+  end
+end
+
+loglik = sum(logscale);
+
+
+%%%%%%%
+function [clpot, seppot] = init_pot(cliques, clqs, pots, pot_type, onodes, ns, cnodes);
+
+% Set the clique potentials to all 1s
+C = length(cliques);
+clpot = cell(1,C);
+for i=1:C
+  clpot{i} = mk_initial_pot(pot_type, cliques{i}, ns, cnodes, onodes);
+end
+
+% Multiply on specified potentials
+for i=1:length(clqs)
+  c = clqs(i);
+  clpot{c} = multiply_by_pot(clpot{c}, pots{i});
+end
+
+seppot = cell(C,C); % implicitely initialized to 1
+
+
+%%%%
+function [clpot, seppot] = collect_evidence(clpot, seppot, maximize, postorder, postorder_parents,...
+					    separator)
+for n=postorder %postorder(1:end-1)
+  for p=postorder_parents{n}
+    %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant
+    seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n}, maximize);
+    clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n});
+  end
+end
+
+
+%%%%
+function [clpot, seppot] = distribute_evidence(clpot, seppot, maximize, preorder, preorder_children,...
+					       separator)
+for n=preorder
+  for c=preorder_children{n}
+    clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); 
+    seppot{n,c} = marginalize_pot(clpot{n}, separator{n,c}, maximize);
+    clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,67 @@
+function engine = jtree_dbn_inf_engine(bnet, varargin)
+% JTREE_DBN_INF_ENGINE Junction tree inference algorithm for DBNs.
+
+ss = length(bnet.intra);
+
+onodes = [];
+
+if nargin >= 2
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'observed', onodes = args{i+1};
+    end
+  end
+end
+
+[int, engine.persist, engine.transient] = compute_interface_nodes(bnet.intra, bnet.inter);
+%engine.interface = engine.persist; % WRONG!
+engine.interface = int;
+engine.nonint = mysetdiff(1:ss, int);
+
+if 0
+  % Create a 2 slice jtree
+  % We force there to be cliques containing the in and out interfaces for slices t and t+1.
+  obs_nodes = [onodes(:) onodes(:)+ss];
+  engine.jtree_engine = jtree_inf_engine(bnet, 'observed', obs_nodes(:), ...
+					 'clusters', {int, int+ss}, 'root', int+ss);
+else
+  % Create a "1.5 slice" jtree, containing slice 1 and the interface nodes of slice 2
+  nodes15 = [1:ss int+ss];
+  N = length(nodes15);
+  dag15 = bnet.dag(nodes15, nodes15);
+  ns15 = bnet.node_sizes(nodes15);
+  eclass15 = bnet.equiv_class(nodes15);
+  discrete_bitv = zeros(1,2*ss);
+  discrete_bitv(bnet.dnodes) = 1;
+  discrete15 = find(discrete_bitv(nodes15));
+  bnet15 = mk_bnet(dag15, ns15, 'equiv_class', eclass15, 'discrete', discrete15);
+  bnet15.CPD = bnet.CPD; % CPDs for non-interface nodes in slice 2 will not be used
+  obs_bitv = zeros(1, 2*ss);
+  obs_bitv([onodes onodes+ss]) = 1;
+  obs_nodes15 = find(obs_bitv(nodes15));
+  int_bitv = zeros(1,ss);
+  int_bitv(int) = 1;
+  engine.jtree_engine = jtree_inf_engine(bnet15, 'observed', obs_nodes15(:), ...
+				     'clusters', {int, int+ss}, 'root', int+ss);
+end
+
+engine.in_clq = clq_containing_nodes(engine.jtree_engine, int);
+engine.out_clq = clq_containing_nodes(engine.jtree_engine, int+ss);
+
+engine.clq_ass_to_node = zeros(ss, 2);
+for i=1:ss
+  engine.clq_ass_to_node(i, 1) = clq_containing_nodes(engine.jtree_engine, i);
+  engine.clq_ass_to_node(i, 2) = clq_containing_nodes(engine.jtree_engine, i+ss);
+end
+
+engine.jtree_struct = struct(engine.jtree_engine); % violate object privacy
+
+% stuff needed by marginal_nodes
+engine.clpot = [];
+engine.maximize = [];
+engine.T = [];
+
+engine = class(engine, 'jtree_dbn_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,62 @@
+function engine = jtree_dbn_inf_engine(bnet, varargin)
+% JTREE_DBN_INF_ENGINE Junction tree inference algorithm for DBNs.
+
+ss = length(bnet.intra);
+
+onodes = [];
+
+if nargin >= 2
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'observed', onodes = args{i+1};
+    end
+  end
+end
+
+[int, engine.persist, engine.transient] = compute_interface_nodes(bnet.intra, bnet.inter);
+%engine.interface = engine.persist; % WRONG!
+engine.interface = int;
+engine.nonint = mysetdiff(1:ss, int);
+
+if 1
+  % Create a 2 slice jtree
+  % We force there to be cliques containing the in and out interfaces for slices t and t+1.
+  obs_nodes = [onodes(:) onodes(:)+ss];
+  engine.jtree_engine = jtree_inf_engine(bnet, 'observed', obs_nodes(:), ...
+					 'clusters', {int, int+ss}, 'root', int+ss);
+else
+  % Create a "1.5 slice" jtree, containing slice 1 and the interface nodes of slice 2
+  % To keep the node numbering the same, we simply disconnect the non-interface nodes
+  % from slice 2.
+  intra15 = bnet.intra;
+  for i=engine.nonint(:)'
+    intra15(i,:) = 0;
+    intra15(:,i) = 0;
+  end
+  bnet15 = mk_dbn(intra15, bnet.inter, bnet.node_sizes_slice, bnet.dnodes_slice, ...
+		  bnet.equiv_class(:,1), bnet.equiv_class(:,2), bnet.intra);
+  obs_nodes = [onodes(:) onodes(:)+ss];
+  engine.jtree_engine = jtree_inf_engine(bnet15, 'observed', obs_nodes(:), ...
+				     'clusters', {int, int+ss}, 'root', int+ss);
+end
+
+engine.in_clq = clq_containing_nodes(engine.jtree_engine, int);
+engine.out_clq = clq_containing_nodes(engine.jtree_engine, int+ss);
+
+engine.clq_ass_to_node = zeros(ss, 2);
+for i=1:ss
+  engine.clq_ass_to_node(i, 1) = clq_containing_nodes(engine.jtree_engine, i);
+  engine.clq_ass_to_node(i, 2) = clq_containing_nodes(engine.jtree_engine, i+ss);
+end
+
+engine.jtree_struct = struct(engine.jtree_engine); % violate object privacy
+
+% stuff needed by marginal_nodes
+engine.clpot = [];
+engine.maximize = [];
+engine.T = [];
+
+engine = class(engine, 'jtree_dbn_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/Old/jtree_dbn_inf_engine2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+function engine = jtree_dbn_inf_engine(bnet, varargin)
+% JTREE_DBN_INF_ENGINE Junction tree inference algorithm for DBNs.
+
+ss = length(bnet.intra);
+
+onodes = [];
+
+if nargin >= 2
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'observed', onodes = args{i+1};
+    end
+  end
+end
+
+[int, engine.persist, engine.transient] = compute_interface_nodes(bnet.intra, bnet.inter);
+%engine.interface = engine.persist; % WRONG!
+engine.interface = int;
+engine.nonint = mysetdiff(1:ss, int);
+
+
+% Create a 2 slice jtree
+% We force there to be cliques containing the in and out interfaces for slices t and t+1.
+obs_nodes = [onodes(:) onodes(:)+ss];
+engine.jtree_engine = jtree_inf_engine(bnet, 'observed', obs_nodes(:), ...
+					 'clusters', {int, int+ss}, 'root', int+ss);
+
+engine.in_clq = clq_containing_nodes(engine.jtree_engine, int);
+engine.out_clq = clq_containing_nodes(engine.jtree_engine, int+ss);
+engine.jtree_struct = struct(engine.jtree_engine); % violate object privacy
+
+
+
+% Also create an engine just for slice 1
+bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, bnet.dnodes, bnet.equiv_class(:,1));
+for i=1:max(bnet1.equiv_class)
+  bnet1.CPD{i} = bnet.CPD{i};
+end
+
+engine.jtree_engine1 = jtree_inf_engine(bnet1, 'observed', onodes, 'clusters', {int}, ...
+					'root', int);
+
+engine.in_clq1 = clq_containing_nodes(engine.jtree_engine1, int);
+engine.jtree_struct1 = struct(engine.jtree_engine1); % violate object privacy
+
+
+
+
+% stuff needed by marginal_nodes
+engine.clpot = [];
+engine.T = [];
+engine.maximize = [];
+
+engine = class(engine, 'jtree_dbn_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,70 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (jtree_dbn)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product instead of sum-product [engine.maximize]
+% softCPDpot{n,t} - use soft potential for node n instead of its CPD; set to [] to use CPD
+% soft_evidence_nodes(i,1:2) = [n t] means the i'th piece of soft evidence is on node n in slice t 
+% soft_evidence{i} - prob distribution over values for soft_evidence_nodes(i,:)
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+
+% for add_ev in marginal_nodes
+T = size(evidence, 2);
+engine.evidence = evidence;
+bnet = bnet_from_engine(engine);
+ss = length(bnet.node_sizes_slice);
+ns = bnet.node_sizes_slice(:);
+engine.node_sizes = repmat(ns, [1 T]);
+softCPDpot = cell(ss,T);
+soft_evidence = {};
+soft_evidence_nodes = [];
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', engine.maximize = args{i+1}; 
+     case 'softCPDpot', softCPDpot = args{i+1};
+     case 'soft_evidence', soft_evidence = args{i+1};
+     case 'soft_evidence_nodes', soft_evidence_nodes = args{i+1};
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+engine.jtree_engine = set_fields(engine.jtree_engine, 'maximize', engine.maximize);
+engine.jtree_engine1 = set_fields(engine.jtree_engine1, 'maximize', engine.maximize);
+
+[ss T] = size(evidence);
+engine.T = T;
+observed_bitv = ~isemptycell(evidence);
+onodes = find(observed_bitv);
+pot_type = determine_pot_type(bnet, onodes);
+CPDpot = convert_dbn_CPDs_to_pots(bnet, evidence, pot_type, softCPDpot);
+
+if ~isempty(soft_evidence_nodes)
+  nsoft = size(soft_evidence_nodes,1);
+  for i=1:nsoft
+    n = soft_evidence_nodes(i,1);
+    t = soft_evidence_nodes(i,2);
+    if t==1
+      dom = n;
+    else
+      dom = n+ss;
+    end
+    pot = dpot(dom, ns(n), soft_evidence{i});
+    CPDpot{n,t} = multiply_by_pot(CPDpot{n,t}, pot);
+  end
+end
+  
+[engine.clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed_bitv, pot_type);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/enter_soft_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,126 @@
+function [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type)
+% ENTER_SOFT_EVIDENCE Add the specified soft evidence to the network (jtree_dbn)
+% [clpot, loglik] = enter_soft_evidence(engine, CPDpot, observed, pot_type)
+
+scale = 1;
+verbose = 0;
+
+[ss T] = size(CPDpot);
+Q = length(engine.jtree_struct.cliques);
+clpot = cell(Q,T); % clpot{t} contains evidence from slices (t-1, t) 
+seppot = cell(Q,Q,T);
+ll = zeros(1,Q);
+logscale = zeros(1,T);
+bnet = bnet_from_engine(engine);
+root = engine.jtree_struct.root_clq;
+
+% Forwards pass.
+% Compute distribution on clq C,
+% where C is the out interface to (t-1,t).
+% Then pass this to clq D, where D is the in inferface to (t+1,t).
+
+% Then propagate from D to later slices.
+
+slice1 = 1:ss;
+slice2 = slice1 + ss; 
+transient = engine.transient;
+persist = engine.persist;
+Ntransient = length(transient);
+trans = cell(Ntransient,1);
+if verbose, fprintf('forward pass\n'); end
+for t=1:T
+  if verbose, fprintf('%d ', t); end
+  if t==1
+    pots = [CPDpot(:,1); CPDpot(persist, 2)];
+    clqs = engine.jtree_struct.clq_ass_to_node([slice1 persist+ss]);
+    obs = find(observed(:,1:2));
+  elseif t==T
+    clqs = [engine.in_clq1 engine.jtree_struct1.clq_ass_to_node(transient)];
+    phi = set_domain_pot(phi, engine.interface); % shift back to slice 1
+    for i=1:Ntransient
+      trans{i} = CPDpot{transient(i), t};
+      trans{i} = set_domain_pot(trans{i}, domain_pot(trans{i})-ss); % shift back to slice 1
+    end
+    pots = [ {phi}; trans]; 
+    obs = find(observed(:,T));
+  else
+    clqs = [engine.in_clq engine.jtree_struct.clq_ass_to_node([transient persist+ss])];
+    phi = set_domain_pot(phi, engine.interface); % shift back to slice 1
+    for i=1:Ntransient
+      trans{i} = CPDpot{transient(i), t};
+      trans{i} = set_domain_pot(trans{i}, domain_pot(trans{i})-ss); % shift back to slice 1
+    end
+    pots = [ {phi}; trans; CPDpot(persist, t+1)]; 
+    obs = find(observed(:,t:t+1));
+  end
+
+  if t < T
+    [clpot(1:Q,t), seppot(1:Q,1:Q,t)] =  init_pot(engine.jtree_engine, clqs, pots, pot_type, obs);
+    [clpot(1:Q,t), seppot(1:Q,1:Q,t)] = collect_evidence(engine.jtree_engine, clpot(1:Q,t), seppot(1:Q,1:Q,t));
+  else
+    Q = length(engine.jtree_struct1.cliques);
+    root = engine.jtree_struct1.root_clq;
+    [clpot(1:Q,t), seppot(1:Q,1:Q,t)] =  init_pot(engine.jtree_engine1, clqs, pots, pot_type, obs);
+    [clpot(1:Q,t), seppot(1:Q,1:Q,t)] = collect_evidence(engine.jtree_engine1, clpot(1:Q,t), seppot(1:Q,1:Q,t));
+  end
+
+
+  if scale
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  logscale(t) = ll(root);
+  end
+  
+  if t < T
+    % bug fix by Bob Welch 30 Jan 04
+    phi = marginalize_pot(clpot{engine.out_clq,t}, engine.interface+ss,engine.maximize);
+    %phi = marginalize_pot(clpot{root,t}, engine.interface+ss, engine.maximize);
+  end
+end
+
+if scale
+loglik = sum(logscale);
+else
+loglik = [];
+end
+
+
+% Backwards pass.
+% Pass evidence from clq C to clq D,
+% where C is the in interface to (t,t+1) and D is the out inferface to (t-1,t)
+% Then propagate evidence from D to earlier slices.
+% (C and D are reversed names from the tech report!)
+D = engine.out_clq;
+if verbose, fprintf('\nbackwards pass\n'); end
+for t=T:-1:1
+  if verbose, fprintf('%d ', t); end
+  
+  if t == T
+    Q = length(engine.jtree_struct1.cliques);
+    C = engine.in_clq1;
+    [clpot(1:Q,t), seppot(1:Q,1:Q,t)] = distribute_evidence(engine.jtree_engine1, clpot(1:Q,t), seppot(1:Q,1:Q,t));
+  else
+    Q = length(engine.jtree_struct.cliques);
+    C = engine.in_clq;
+    [clpot(1:Q,t), seppot(1:Q,1:Q,t)] = distribute_evidence(engine.jtree_engine, clpot(1:Q,t), seppot(1:Q,1:Q,t));
+  end
+
+  if scale
+  for c=1:Q
+    [clpot{c,t}, ll(c)] = normalize_pot(clpot{c,t});
+  end
+  end
+  
+  if t >= 2
+    phiC = marginalize_pot(clpot{C,t}, engine.interface, engine.maximize);
+    phiC = set_domain_pot(phiC, engine.interface+ss); % shift forward to slice 2
+    phiD = marginalize_pot(clpot{D,t-1}, engine.interface+ss, engine.maximize);
+    ratio = divide_by_pot(phiC, phiD);
+    clpot{D,t-1} = multiply_by_pot(clpot{D,t-1}, ratio);
+  end
+end
+if verbose, fprintf('\n'); end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/jtree_dbn_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,109 @@
+function engine = jtree_dbn_inf_engine(bnet, varargin)
+% JTREE_DBN_INF_ENGINE Junction tree inference algorithm for DBNs.
+% engine = jtree_inf_engine(bnet, ...)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% clusters - specifies variables that must be grouped in the 1.5 slice DBN
+% maximize - 1 means max-product, 0 means sum-product [0]
+%
+% e.g., engine = jtree_dbn_inf_engine(dbn, 'clusters', {[1 2]});
+%
+% This uses all of slice t-1 plus the backwards interface of slice t.
+% By contrast, jtree_2TBN_inf_engine in the online directory uses
+% the forwards interface of slice t-1 plus all of slice t.
+% See my thesis for details.
+
+ss = length(bnet.intra);
+
+engine.maximize = 0;
+clusters = {};
+
+args = varargin;
+for i=1:2:length(args)
+  switch args{i},
+   case 'clusters', clusters = args{i+1};
+   case 'maximize', engine.maximize = args{i+1};
+   otherwise, error(['unrecognized argument ' args{i}])
+  end
+end
+
+
+engine.evidence = [];
+engine.node_sizes = [];
+
+[int, engine.persist, engine.transient] = compute_interface_nodes(bnet.intra, bnet.inter);
+engine.interface = int;
+engine.nonint = mysetdiff(1:ss, int);
+
+onodes = bnet.observed;
+
+if 0
+  % Create a 2 slice jtree
+  % We force there to be cliques containing the in and out interfaces for slices t and t+1.
+  obs_nodes = [onodes(:) onodes(:)+ss];
+  engine.jtree_engine = jtree_inf_engine(bnet, 'observed', obs_nodes(:), ...
+					 'clusters', {int, int+ss}, 'root', int+ss);
+else
+  % Create a "1.5 slice" jtree, containing slice 1 and the interface nodes of slice 2
+  % To keep the node numbering the same, we simply disconnect the non-interface nodes
+  % from slice 2, and set their size to 1.
+  % We do this to speed things up, and so that the likelihood is computed correctly - we do not need to do
+  % this if we just want to compute marginals. 
+  intra15 = bnet.intra;
+  for i=engine.nonint(:)'
+    intra15(i,:) = 0;
+    intra15(:,i) = 0;
+  end
+  dag15 = [bnet.intra bnet.inter;
+	 zeros(ss)    intra15];
+  ns = bnet.node_sizes(:);
+  ns(engine.nonint+ss) = 1; % disconnected nodes get size 1
+  obs_nodes = [onodes(:) onodes(:)+ss];
+  bnet15 = mk_bnet(dag15, ns, 'discrete', bnet.dnodes, 'equiv_class', bnet.equiv_class(:), ...
+		   'observed', obs_nodes(:));
+
+  %bnet15 = mk_dbn(intra15, bnet.inter, bnet.node_sizes_slice, bnet.dnodes_slice, ...
+  %		  bnet.equiv_class(:,1), bnet.equiv_class(:,2), bnet.intra);
+  % with the dbn, we can't independently control the sizes of slice 2 nodes
+  
+  if 1
+    % use unconstrained elimination,
+    % but force there to be a clique containing both interfaces
+    clusters(end+1:end+2) = {int, int+ss};
+    engine.jtree_engine = jtree_inf_engine(bnet15, 'clusters', clusters, 'root', int+ss);
+  else
+    % Use constrained elimination - this induces a clique that contain the 2nd interface,
+    % but not the first.
+    % Hence we throw in the first interface as an extra.
+    stages = {1:ss, [1:ss]+ss};
+    clusters(end+1:end+2) = {int, int+ss};
+    engine.jtree_engine = jtree_inf_engine(bnet15, 'clusters', clusters, ...
+					   'stages', stages, 'root', int+ss);
+  end
+end
+
+engine.in_clq = clq_containing_nodes(engine.jtree_engine, int);
+engine.out_clq = clq_containing_nodes(engine.jtree_engine, int+ss);
+engine.jtree_struct = struct(engine.jtree_engine); % violate object privacy
+
+
+% Also create an engine just for slice 1
+bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, 'discrete', myintersect(bnet.dnodes,1:ss), ...
+		'equiv_class', bnet.equiv_class(:,1), 'observed', onodes);
+for i=1:max(bnet1.equiv_class)
+  bnet1.CPD{i} = bnet.CPD{i};
+end
+
+engine.jtree_engine1 = jtree_inf_engine(bnet1, 'clusters', {int}, 'root', int);
+
+engine.in_clq1 = clq_containing_nodes(engine.jtree_engine1, int);
+engine.jtree_struct1 = struct(engine.jtree_engine1); % violate object privacy
+
+% stuff needed by marginal_nodes
+engine.clpot = [];
+engine.T = [];
+
+engine = class(engine, 'jtree_dbn_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function m = marginal_family(engine, i, t, add_ev)
+% MARGINAL_FAMILY Compute the marginal on the specified family (jtree_dbn)
+% marginal = marginal_family(engine, i, t)
+
+% This is just like inf_engine/marginal_family, except when we call
+% marginal_nodes, we provide a 4th argument, to tell it's a family.
+
+if nargin < 3, t = 1; end
+if nargin < 4, add_ev = 0; end
+
+bnet = bnet_from_engine(engine);
+if t==1
+  m = marginal_nodes(engine, family(bnet.dag, i), t, add_ev, 1);
+else
+  ss = length(bnet.intra);
+  fam = family(bnet.dag, i+ss);
+  if any(fam<=ss)
+    % i has a parent in the preceeding slice
+    % Hence the lowest numbered slice containing the family is t-1
+    m = marginal_nodes(engine, fam, t-1, add_ev, 1);
+  else
+    % The family all fits inside slice t
+    % Hence shift the indexes back to slice 1
+    m = marginal_nodes(engine, fam-ss, t, add_ev, 1);
+  end
+end     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_dbn_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,66 @@
+function marginal = marginal_nodes(engine, nodes, t, add_ev, fam)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (bk)
+%
+%   marginal = marginal_nodes(engine, i, t)
+% returns Pr(X(i,t) | Y(1:T)), where X(i,t) is the i'th node in the t'th slice.
+%
+%   marginal = marginal_nodes(engine, query, t)
+% returns Pr(X(query(1),t), ... X(query(end),t) | Y(1:T)),
+% where 't' specifies the time slice of the earliest node in the query.
+% 'query' cannot span more than 2 time slices.
+%
+% Example:
+% Consider a DBN with 2 nodes per slice.
+% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3.
+%
+% marginal = marginal_nodes(engine, nodes, t, add_ev, fam)
+% add_ev is an optional argument; if 1, we will "inflate" the marginal of observed nodes
+% to their original size, adding 0s to the positions which contradict the evidence
+   
+if nargin < 3, t = 1; end
+if nargin < 4, add_ev = 0; end
+if nargin < 5, fam = 0; end
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+
+if t==1 | t==engine.T
+  slice = t;
+  nodes2 = nodes;
+elseif mysubset(nodes, engine.persist)
+  slice = t-1;
+  nodes2 = nodes+ss;
+else
+  slice = t;
+  nodes2 = nodes;
+end
+
+%disp(['computing marginal on ' num2str(nodes) ' t = ' num2str(t) ' fam = ' num2str(fam)]);
+
+if t==engine.T
+  c = clq_containing_nodes(engine.jtree_engine1, nodes2, fam);
+else
+  c = clq_containing_nodes(engine.jtree_engine, nodes2, fam);
+end
+if c == -1
+  error(['no clique contains ' nodes2])
+end
+
+
+%disp(['using ' num2str(nodes2) ' slice = ' num2str(slice) ' clq = ' num2str(c)]);
+
+bigpot = engine.clpot{c, slice};
+
+pot = marginalize_pot(bigpot, nodes2, engine.maximize);
+%pot = normalize_pot(pot);
+marginal = pot_to_marginal(pot);
+
+
+% we convert the domain to the unrolled numbering system
+% so that add_ev_to_dmarginal (maybe called in update_ess) extracts the right evidence.
+marginal.domain = nodes+(t-1)*ss;
+
+if add_ev
+  marginal = add_ev_to_dmarginal(marginal, engine.evidence, engine.node_sizes);
+end    
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/jtree_unrolled_dbn_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/update_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/Old/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function marginal = marginal_family(engine, i, t)
+% MARGINAL_FAMILY Compute the marginal on the specified family (jtree_unrolled_dbn)
+% marginal = marginal_family(engine, i, t)
+
+if nargin < 3, t = 1; end
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+marginal = marginal_family(engine.sub_engine, i + (t-1)*ss);
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/Old/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function marginal = marginal_nodes(engine, nodes, t)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (jtree_unrolled_dbn)
+% marginal = marginal_nodes(engine, nodes, t)
+%
+% 't' specifies the time slice of the earliest node in 'nodes'.
+% 'nodes' must occur in some clique.
+%
+% Example:
+% Consider a DBN with 2 nodes per slice.
+% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3,
+% i.e., nodes 3 and 5 in the unrolled network,
+
+if nargin < 3, t = 1; end
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+query = nodes + (t-1)*ss;
+marginal = marginal_nodes(engine.sub_engine, query);    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,43 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (jtree_unrolled_dbn)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+% 
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product instead of sum-product [0]
+% filter   - if 1, does filtering (not supported), else smoothing [0]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+maximize = 0;
+filter = 0;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1}; 
+     case 'filter',  filter = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+if filter
+  error('jtree_unrolled_dbn does not support filtering')
+end
+
+if size(evidence,2) ~= engine.nslices
+  error(['engine was created assuming there are ' num2str(engine.nslices) ...
+	 ' slices, but evidence has ' num2str(size(evidence,2))])
+end
+
+[engine.unrolled_engine, loglik] = enter_evidence(engine.unrolled_engine, evidence, 'maximize', maximize);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/jtree_unrolled_dbn_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+function engine = jtree_unrolled_dbn_inf_engine(bnet, T, varargin)
+% JTREE_UNROLLED_DBN_INF_ENGINE Unroll the DBN for T time-slices and apply jtree to the resulting static net
+% engine = jtree_unrolled_dbn_inf_engine(bnet, T, ...)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% useC      - 1 means use jtree_C_inf_engine instead of jtree_inf_engine [0]
+% constrained - 1 means we constrain ourselves to eliminate slice t before t+1 [1]
+%
+% e.g., engine = jtree_unrolled_inf_engine(bnet, 'useC', 1);
+
+% set default params
+N = length(bnet.intra);
+useC = 0;
+constrained = 1;
+
+if nargin >= 3
+  args = varargin;
+  nargs = length(args);
+  if isstr(args{1})
+    for i=1:2:nargs
+      switch args{i},
+       case 'useC',   useC = args{i+1};
+       case 'constrained',  constrained = args{i+1};
+       otherwise,  
+	error(['invalid argument name ' args{i}]);       
+      end
+    end
+  else
+    error(['invalid argument name ' args{1}]);       
+  end
+end
+
+bnet2 = dbn_to_bnet(bnet, T);
+ss = length(bnet.intra);
+engine.ss = ss;
+
+% If constrained_order = 1 we constrain ourselves to eliminate slice t before t+1.
+% This prevents cliques containing nodes from far-apart time-slices.
+if constrained
+  stages = num2cell(unroll_set(1:ss, ss, T), 1);
+else
+  stages = { 1:length(bnet2.dag) };
+end
+if useC
+  jengine = jtree_C_inf_engine(bnet2, 'stages', stages);
+else
+  jengine = jtree_inf_engine(bnet2, 'stages', stages);
+end
+
+engine.unrolled_engine = jengine;
+% we don't inherit from jtree_inf_engine, because that would only store bnet2,
+% and we would lose access to the DBN-specific fields like intra/inter
+
+engine.nslices = T;
+engine = class(engine, 'jtree_unrolled_dbn_inf_engine', inf_engine(bnet));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function marginal = marginal_family(engine, i, t, add_ev)
+% MARGINAL_FAMILY Compute the marginal on the specified family (jtree_unrolled_dbn)
+% marginal = marginal_family(engine, i, t)
+
+if nargin < 3, t = 1; end
+if nargin < 4, add_ev = 0; end
+assert(~add_ev);
+
+%marginal = marginal_family(engine.unrolled_engine, i + (t-1)*engine.ss, add_ev);
+marginal = marginal_family(engine.unrolled_engine, i + (t-1)*engine.ss);
+              
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function marginal = marginal_nodes(engine, nodes, t, add_ev)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (loopy_unrolled_dbn)
+% marginal = marginal_nodes(engine, nodes, t)
+%
+% 't' specifies the time slice of the earliest node in 'nodes'.
+% 'nodes' must occur in some clique.
+%
+% Example:
+% Consider a DBN with 2 nodes per slice.
+% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3,
+% i.e., nodes 3 and 5 in the unrolled network,
+
+if nargin < 3, t = 1; end
+if nargin < 4, add_ev = 0; end
+
+marginal = marginal_nodes(engine.unrolled_engine, nodes + (t-1)*engine.ss, add_ev);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@jtree_unrolled_dbn_inf_engine/update_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function engine = update_engine(engine, newCPDs)
+% UPDATE_ENGINE Update the engine to take into account the new parameters (jtree_unrolled_dbn)
+% engine = update_engine(engine, newCPDs)
+
+engine.inf_engine = update_engine(engine.inf_engine, newCPDs);
+engine.unrolled_engine = update_engine(engine.unrolled_engine, newCPDs);
+                                                            
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@kalman_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/kalman_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/update_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@kalman_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@kalman_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@kalman_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@kalman_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,83 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (kalman)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product (same as sum-product for Gaussians!), else sum-product [0]
+% filter -   if 1, do filtering, else smoothing [0]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+maximize = 0;
+filter = 0;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1}; 
+     case 'filter', filter = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+assert(~maximize);
+
+bnet = bnet_from_engine(engine);
+n = length(bnet.intra);
+onodes = bnet.observed;
+hnodes = mysetdiff(1:n, onodes);
+T = size(evidence, 2);
+ns = bnet.node_sizes;
+O = sum(ns(onodes));
+data = reshape(cat(1, evidence{onodes,:}), [O T]);
+
+A = engine.trans_mat;
+C = engine.obs_mat;
+Q = engine.trans_cov;
+R = engine.obs_cov;
+init_x = engine.init_state;
+init_V = engine.init_cov;
+
+if filter
+  [x, V, VV, loglik] = kalman_filter(data, A, C, Q, R, init_x, init_V);
+else
+  [x, V, VV, loglik] = kalman_smoother(data, A, C, Q, R, init_x, init_V);
+end
+
+  
+% Wrap the posterior inside a potential, so it can be marginalized easily
+engine.one_slice_marginal = cell(1,T);
+engine.two_slice_marginal = cell(1,T);
+ns(onodes) = 0;
+ns(onodes+n) = 0;
+ss = length(bnet.intra);
+for t=1:T
+  dom = (1:n);
+  engine.one_slice_marginal{t} = mpot(dom+(t-1)*ss, ns(dom), 1, x(:,t), V(:,:,t));
+end
+% for t=1:T-1
+%   dom = (1:(2*n));
+%   mu = [x(:,t); x(:,t)];
+%   Sigma = [V(:,:,t) VV(:,:,t+1)';
+% 	   VV(:,:,t+1) V(:,:,t+1)];
+%   engine.two_slice_marginal{t} = mpot(dom+(t-1)*ss, ns(dom), 1, mu, Sigma);
+% end
+for t=2:T
+  %dom = (1:(2*n));
+  current_slice = hnodes;
+  next_slice = hnodes + ss;
+  dom = [current_slice next_slice];   
+  mu = [x(:,t-1); x(:,t)];
+  Sigma = [V(:,:,t-1) VV(:,:,t)';
+	   VV(:,:,t) V(:,:,t)];
+  engine.two_slice_marginal{t-1} = mpot(dom+(t-2)*ss, ns(dom), 1, mu, Sigma);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@kalman_inf_engine/kalman_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+function engine = kalman_inf_engine(bnet)
+% KALMAN_INF_ENGINE Inference engine for Linear-Gaussian state-space models.
+% engine = kalman_inf_engine(bnet)
+%
+% 'onodes' specifies which nodes are observed; these must be leaves.
+% The remaining nodes are all hidden. All nodes must have linear-Gaussian CPDs.
+% The hidden nodes must be persistent, i.e., they must have children in
+% the next time slice. In addition, they may not have any children within the current slice,
+% except to the observed leaves. In other words, the topology must be isomorphic to a standard LDS.
+%
+% There are many derivations of the filtering and smoothing equations for Linear Dynamical
+% Systems in the literature. I particularly like the following
+% - "From HMMs to LDSs", T. Minka, MIT Tech Report, (no date), available from
+%    ftp://vismod.www.media.mit.edu/pub/tpminka/papers/minka-lds-tut.ps.gz
+
+[engine.trans_mat, engine.trans_cov, engine.obs_mat, engine.obs_cov, engine.init_state, engine.init_cov] = ...
+    dbn_to_lds(bnet);
+
+% This is where we will store the results between enter_evidence and marginal_nodes
+engine.one_slice_marginal = [];
+engine.two_slice_marginal = [];
+
+engine = class(engine, 'kalman_inf_engine', inf_engine(bnet));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@kalman_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function marginal = marginal_nodes(engine, nodes, t)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (kalman)
+% marginal = marginal_nodes(engine, nodes, t)
+%
+% 't' specifies the time slice of the earliest node in 'nodes'.
+% 'nodes' cannot span more than 2 time slices.
+%
+% Example:
+% Consider a DBN with 2 nodes per slice.
+% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3,
+% i.e., nodes 3 and 5 in the unrolled network,
+
+if nargin < 3, t = 1; end
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+if all(nodes <= ss)
+  bigpot = engine.one_slice_marginal{t};
+else
+  bigpot = engine.two_slice_marginal{t};
+end
+
+nodes = nodes + (t-1)*ss;
+pot = marginalize_pot(bigpot, nodes);
+marginal = pot_to_marginal(pot);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+/dbn_to_lds.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/extract_params_from_gbn.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@kalman_inf_engine/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@kalman_inf_engine/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@kalman_inf_engine/private/dbn_to_lds.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function [trans_mat, trans_cov, obs_mat, obs_cov, init_state, init_cov] = dbn_to_lds(bnet)
+% DBN_TO_LDS Compute the Linear Dynamical System parameters from the Gaussian DBN.
+% [trans_mat, trans_cov, obs_mat, obs_cov, init_state, init_cov] = dbn_to_lds(bnet)
+
+onodes = bnet.observed;
+ss = length(bnet.intra);
+num_nodes = ss*2;
+assert(isequal(bnet.cnodes_slice, 1:ss));
+[W,D,mu] = extract_params_from_gbn(bnet);
+
+hnodes = mysetdiff(1:ss, onodes);
+bs = bnet.node_sizes(:); % block sizes
+
+obs_mat = W(block(hnodes,bs), block(onodes,bs))';
+u = block(onodes,bs);
+obs_cov = D(u,u);
+
+trans_mat = W(block(hnodes,bs), block(hnodes + ss, bs))';
+u = block(hnodes + ss, bs);
+trans_cov = D(u,u);
+
+u = block(hnodes,bs);
+init_cov = D(u,u);
+init_state = mu(u);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@kalman_inf_engine/private/extract_params_from_gbn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function [B,D,mu] = extract_params_from_gbn(bnet)
+% Extract all the local parameters of each Gaussian node, and collect them into global matrices.
+% [B,D,mu] = extract_params_from_gbn(bnet)
+%
+% B(i,j) is a block matrix that contains the transposed weight matrix from node i to node j.
+% D(i,i) is a block matrix that contains the noise covariance matrix for node i.
+% mu(i) is a block vector that contains the shifted noise mean for node i.
+
+% In Shachter's model, the mean of each node in the global gaussian is
+% the same as the node's local unconditional mean.
+% In Alag's model (which we use), the global mean gets shifted.
+
+
+num_nodes = length(bnet.dag);
+bs = bnet.node_sizes(:); % bs = block sizes
+N = sum(bs); % num scalar nodes
+
+B = zeros(N,N);
+D = zeros(N,N);
+mu = zeros(N,1);
+
+for i=1:num_nodes % in topological order
+  ps = parents(bnet.dag, i);
+  e = bnet.equiv_class(i);
+  %[m, Sigma, weights] = extract_params_from_CPD(bnet.CPD{e});
+  s = struct(bnet.CPD{e}); % violate privacy of object
+  m = s.mean; Sigma = s.cov; weights = s.weights;
+  if length(ps) == 0
+    mu(block(i,bs)) = m;
+  else
+    mu(block(i,bs)) = m + weights *  mu(block(ps,bs));
+  end
+  B(block(ps,bs), block(i,bs)) = weights';
+  D(block(i,bs), block(i,bs)) = Sigma;
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@kalman_inf_engine/update_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function engine = update_engine(engine, newCPDs)
+% UPDATE_ENGINE Update the engine to take into account the new parameters (kalman)
+% engine = update_engine(engine, newCPDs)
+
+engine.inf_engine = update_engine(engine.inf_engine, newCPDs);
+[engine.trans_mat, engine.trans_cov, engine.obs_mat, engine.obs_cov, engine.init_state, engine.init_cov] = ...
+    dbn_to_lds(bnet_from_engine(engine));
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_soft_ev.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/pearl_dbn_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D/Old////
+D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+/correct_smooth.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/filter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/filter_evidence_obj_oriented.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/smooth_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/smooth_evidence_fast.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/wrong_smooth.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/correct_smooth.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,244 @@
+function [marginal, msg, loglik] = smooth_evidence(engine, evidence)
+% [marginal, msg, loglik] = smooth_evidence(engine, evidence) (pearl_dbn)
+
+disp('warning: broken');
+
+[ss T] = size(evidence);
+bnet = bnet_from_engine(engine);
+bnet2 = dbn_to_bnet(bnet, T);
+ns = bnet2.node_sizes;
+hnodes = mysetdiff(1:ss, engine.onodes);
+hnodes = hnodes(:)';
+
+onodes2 = unroll_set(engine.onodes(:), ss, T);
+onodes2 = onodes2(:)';
+
+hnodes2 = unroll_set(hnodes(:), ss, T);
+hnodes2 = hnodes2(:)';
+
+[engine.parent_index, engine.child_index] = mk_pearl_msg_indices(bnet2);
+
+msg = init_msgs(bnet2.dag, ns, evidence, bnet2.equiv_class, bnet2.CPD);
+
+verbose = 0;
+
+niter = 1;
+for iter=1:niter
+  % FORWARD
+  for t=1:T
+    if verbose, fprintf('t=%d\n', t); end
+    % observed leaves send lambda to parents
+    for i=engine.onodes(:)'
+      n = i + (t-1)*ss;
+      ps = parents(bnet2.dag, n);
+      for p=ps(:)'
+	j = engine.child_index{p}(n); % n is p's j'th child
+	if t > 1
+	  e = bnet.equiv_class(i, 2);
+	else
+	  e = bnet.equiv_class(i, 1);
+	end
+	lam_msg = normalise(compute_lambda_msg(bnet.CPD{e}, n, ps, msg, p));
+	msg{p}.lambda_from_child{j} = lam_msg;
+	if verbose, fprintf('%d sends lambda to %d\n', n, p); disp(lam_msg); end
+      end 
+    end
+
+    % update pi
+    for i=hnodes
+      n = i + (t-1)*ss;
+      ps = parents(bnet2.dag, n);
+      if t==1
+	e = bnet.equiv_class(i,1);
+      else
+	e = bnet.equiv_class(i,2);
+      end
+      msg{n}.pi = compute_pi(bnet.CPD{e}, n, ps, msg);
+      if verbose, fprintf('%d computes pi\n', n); disp(msg{n}.pi); end
+    end
+    
+    % send pi msg to children
+    for i=hnodes
+      n = i + (t-1)*ss;
+      %cs = myintersect(children(bnet2.dag, n), hnodes2);
+      cs = children(bnet2.dag, n);
+      for c=cs(:)'
+	j = engine.parent_index{c}(n); % n is c's j'th parent
+	pi_msg = normalise(compute_pi_msg(n, cs, msg, c, ns));
+	msg{c}.pi_from_parent{j} = pi_msg;
+	if verbose, fprintf('%d sends pi to %d\n', n, c); disp(pi_msg); end
+      end
+    end
+  end
+
+  % BACKWARD
+  for t=T:-1:1
+    if verbose, fprintf('t = %d\n', t); end
+    % update lambda
+    for i=hnodes
+      n = i + (t-1)*ss;
+      cs = children(bnet2.dag, n);
+      msg{n}.lambda = compute_lambda(n, cs, msg, ns);
+      if verbose, fprintf('%d computes lambda\n', n); disp(msg{n}.lambda); end
+    end
+    % send lambda msgs to parents
+    for i=hnodes
+      n = i + (t-1)*ss;
+      %ps = myintersect(parents(bnet2.dag, n), hnodes2);
+      ps = parents(bnet2.dag, n);
+      for p=ps(:)'
+	j = engine.child_index{p}(n); % n is p's j'th child
+	if t > 1
+	  e = bnet.equiv_class(i, 2);
+	else
+	  e = bnet.equiv_class(i, 1);
+	end
+	lam_msg = normalise(compute_lambda_msg(bnet.CPD{e}, n, ps, msg, p));
+	msg{p}.lambda_from_child{j} = lam_msg;
+	if verbose, fprintf('%d sends lambda to %d\n', n, p); disp(lam_msg); end
+      end 
+    end
+  end
+  
+end
+
+
+marginal = cell(ss,T);
+lik = zeros(1,ss*T);
+for t=1:T
+  for i=1:ss
+    n = i + (t-1)*ss;
+    [bel, lik(n)] = normalise(msg{n}.pi .* msg{n}.lambda);     
+    marginal{i,t} = bel;
+  end
+end
+
+loglik = sum(log(lik));
+
+
+
+%%%%%%%
+
+function lambda = compute_lambda(n, cs, msg, ns)
+% Pearl p183 eq 4.50
+lambda = prod_lambda_msgs(n, cs, msg, ns);
+
+%%%%%%%
+
+function pi_msg = compute_pi_msg(n, cs, msg, c, ns)
+% Pearl p183 eq 4.53 and 4.51
+pi_msg = msg{n}.pi .* prod_lambda_msgs(n, cs, msg, ns, c);
+
+%%%%%%%%%
+
+function lam = prod_lambda_msgs(n, cs, msg, ns, except)
+
+if nargin < 5, except = -1; end
+
+lam = msg{n}.lambda_from_self(:);
+lam = ones(ns(n), 1);
+for i=1:length(cs)
+  c = cs(i);
+  if c ~= except
+    lam = lam .* msg{n}.lambda_from_child{i};
+  end
+end   
+
+
+%%%%%%%%%
+
+function msg = init_msgs(dag, ns, evidence, eclass, CPD)
+% INIT_MSGS Initialize the lambda/pi message and state vectors (pearl_dbn)
+% msg =  init_msgs(dag, ns, evidence)
+
+N = length(dag);
+msg = cell(1,N);
+observed = ~isemptycell(evidence(:));
+
+for n=1:N
+  ps = parents(dag, n);
+  msg{n}.pi_from_parent = cell(1, length(ps));
+  for i=1:length(ps)
+    p = ps(i);
+    msg{n}.pi_from_parent{i} = ones(ns(p), 1);
+  end
+  
+  cs = children(dag, n);
+  msg{n}.lambda_from_child = cell(1, length(cs));
+  for i=1:length(cs)
+    c = cs(i);
+    msg{n}.lambda_from_child{i} = ones(ns(n), 1);
+  end
+
+  msg{n}.lambda = ones(ns(n), 1);
+  msg{n}.lambda_from_self = ones(ns(n), 1);
+  msg{n}.pi = ones(ns(n), 1);
+
+ % Initialize the lambdas with any evidence
+  if observed(n)
+    v = evidence{n};
+    %msg{n}.lambda_from_self = zeros(ns(n), 1);
+    %msg{n}.lambda_from_self(v) = 1; % delta function
+    msg{n}.lambda = zeros(ns(n), 1);
+    msg{n}.lambda(v) = 1; % delta function
+  end      
+  
+end
+
+
+%%%%%%%%
+
+function msg = init_ev_msgs(engine, evidence, msg)
+
+[ss T] = size(evidence);
+bnet = bnet_from_engine(engine);
+pot_type = 'd';
+t = 1;
+hnodes = mysetdiff(1:ss, engine.onodes);
+for i=engine.onodes(:)'
+  fam = family(bnet.dag, i);
+  e = bnet.equiv_class(i, 1);
+  CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,1));
+  temp = pot_to_marginal(CPDpot);
+  msg{i}.lambda_from_self = temp.T;
+end
+for t=2:T
+  for i=engine.onodes(:)'
+    fam = family(bnet.dag, i, 2); % extract from slice t
+    e = bnet.equiv_class(i, 2);
+    CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,t-1:t));
+    temp = pot_to_marginal(CPDpot);
+    n = i + (t-1)*ss;
+    msg{n}.lambda_from_self = temp.T;
+  end
+end
+
+
+%%%%%%%%%%%
+
+function msg = init_ev_msgs2(engine, evidence, msg)
+
+[ss T] = size(evidence);
+bnet = bnet_from_engine(engine);
+pot_type = 'd';
+t = 1;
+hnodes = mysetdiff(1:ss, engine.onodes);
+for i=engine.onodes(:)'
+  fam = family(bnet.dag, i);
+  e = bnet.equiv_class(i, 1);
+  CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,1));
+  temp = pot_to_marginal(CPDpot);
+  msg{i}.lambda_from_self = temp.T;
+end
+for t=2:T
+  for i=engine.onodes(:)'
+    fam = family(bnet.dag, i, 2); % extract from slice t
+    e = bnet.equiv_class(i, 2);
+    CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,t-1:t));
+    temp = pot_to_marginal(CPDpot);
+    n = i + (t-1)*ss;
+    msg{n}.lambda_from_self = temp.T;
+  end
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,123 @@
+function [engine, loglik] = enter_evidence(engine, evidence, filter)
+% ENTER_EVIDENCE Add the specified evidence to the network (pearl_dbn)
+% [engine, loglik] = enter_evidence(engine, evidence, filter)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+% If filter = 1, we do filtering, otherwise smoothing (default).
+
+if nargin < 3, filter = 0; end
+
+[ss T] = size(evidence);
+bnet = bnet_from_engine(engine);
+bnet2 = dbn_to_bnet(bnet, T);
+ns = bnet2.node_sizes;
+hnodes = mysetdiff(1:ss, engine.onodes);
+hnodes = hnodes(:)';
+
+[engine.parent_index, engine.child_index] = mk_pearl_msg_indices(bnet2);
+
+msg = init_msgs(bnet2.dag, ns, evidence);
+msg = init_ev_msgs(engine, evidence, msg);
+
+niter = 1;
+for iter=1:niter
+  % FORWARD
+  for t=1:T
+    % update pi
+    for i=1:ss %hnodes
+      n = i + (t-1)*ss;
+      ps = parents(bnet2.dag, n);
+      if t==1
+	e = bnet.equiv_class(i,1);
+      else
+	e = bnet.equiv_class(i,2);
+      end
+      msg{n}.pi = compute_pi(bnet.CPD{e}, n, ps, msg);
+      %msg{n}.pi = normalise(msg{n}.pi(:) .* msg{n}.lambda_from_self(:));
+    end
+    % send pi msg to children
+    for i=1:ss % hnodes
+      n = i + (t-1)*ss;
+      cs = children(bnet2.dag, n);
+      for c=cs(:)'
+	j = engine.parent_index{c}(n); % n is c's j'th parent
+	msg{c}.pi_from_parent{j} = normalise(compute_pi_msg(n, cs, msg, c, ns));
+      end
+    end
+  end
+
+  if filter
+    disp('skipping smoothing');
+    break;
+  end
+    
+  % BACKWARD
+  for t=T:-1:1
+    % update lambda
+    for i=1:ss % hnodes
+      n = i + (t-1)*ss;
+      cs = children(bnet2.dag, n);
+      msg{n}.lambda = compute_lambda(n, cs, msg, ns);
+    end
+    % send lambda msgs to parents
+    for i=1:ss % hnodes
+      n = i + (t-1)*ss;
+      ps = parents(bnet2.dag, n);
+      for p=ps(:)'
+	j = engine.child_index{p}(n); % n is p's j'th child
+	if t > 1
+	  e = bnet.equiv_class(i, 2);
+	else
+	  e = bnet.equiv_class(i, 1);
+	end
+	msg{p}.lambda_from_child{j} = normalise(compute_lambda_msg(bnet.CPD{e}, n, ps, msg, p));
+      end 
+    end
+  end
+  
+end
+
+
+engine.marginal = cell(ss,T);
+lik = zeros(1,ss*T);
+for t=1:T
+  for i=1:ss
+    n = i + (t-1)*ss;
+    [bel, lik(n)] = normalise(msg{n}.pi .* msg{n}.lambda);     
+    engine.marginal{i,t} = bel;
+  end
+end
+
+engine.evidence = evidence; % needed by marginal_nodes and marginal_family
+engine.msg = msg;  % needed by marginal_family
+loglik = sum(log(lik));
+
+
+
+%%%%%%%
+
+function lambda = compute_lambda(n, cs, msg, ns)
+% Pearl p183 eq 4.50
+lambda = prod_lambda_msgs(n, cs, msg, ns);
+
+%%%%%%%
+
+function pi_msg = compute_pi_msg(n, cs, msg, c, ns)
+% Pearl p183 eq 4.53 and 4.51
+pi_msg = msg{n}.pi .* prod_lambda_msgs(n, cs, msg, ns, c);
+
+%%%%%%%%%
+
+function lam = prod_lambda_msgs(n, cs, msg, ns, except)
+
+if nargin < 5, except = -1; end
+
+lam = msg{n}.lambda_from_self(:);
+%lam = ones(ns(n), 1);
+for i=1:length(cs)
+  c = cs(i);
+  if c ~= except
+    lam = lam .* msg{n}.lambda_from_child{i};
+  end
+end   
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/filter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,146 @@
+function [marginal, msg, loglik] = filter_evidence(engine, evidence)
+
+error('broken');
+
+[ss T] = size(evidence);
+bnet = bnet_from_engine(engine);
+onodes = engine.onodes;
+hnodes = mysetdiff(1:ss, onodes);
+hnodes = hnodes(:)';
+
+ns = bnet.node_sizes(:);
+onodes2 = [onodes(:); onodes(:)+ss];
+ns(onodes2) = 1;
+	   
+verbose = 1;
+if verbose, fprintf('\nnew filtering\n'); end
+  
+pot_type = 'd';
+niter = engine.max_iter;
+
+% msg(i1,t1,i2,j2) (i1,t1) -> (i2,t2)
+%lambda_msg = cell(ss,T,ss,T);
+%pi_msg = cell(ss,T,ss,T);
+
+% intra_lambda_msg(i,j,t) (i,t) -> (j,t), i is child
+% inter_lambda_msg(i,j,t) (i,t+1) -> (j,t), i is child
+% inter_pi_msg(i,j,t) (i,t-1) -> (j,t), i is parent
+intra_lambda_msg = cell(ss,ss,T);
+inter_lambda_msg = cell(ss,ss,T);
+inter_pi_msg = cell(ss,ss,T);
+
+lambda = cell(ss,T);
+pi = cell(ss,T);
+
+for t=1:T
+  for i=1:ss
+    lambda{i,t} = ones(ns(i), 1);
+    pi{i,t} = ones(ns(i), 1);
+    
+    cs = children(bnet.intra, i);
+    for c=cs(:)'
+      intra_lambda_msg{c,i,t} = ones(ns(i),1);
+    end
+    
+    cs = children(bnet.inter, i);
+    for c=cs(:)'
+      inter_lambda_msg{c,i,t} = ones(ns(i),1);
+    end
+    
+    ps = parents(bnet.inter, i);
+    for p=ps(:)'
+      inter_pi_msg{p,i,t} = ones(ns(i), 1); % not used for t==1
+    end
+  end
+end
+
+% each hidden node absorbs lambda from its observed child (if any)
+for t=1:T
+  for i=hnodes
+    c = engine.obschild(i);
+    if c > 0
+      if t==1
+	fam = family(bnet.dag, c);
+	e = bnet.equiv_class(c, 1);
+	CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,1));
+      else
+	fam = family(bnet.dag, c, 2); % within 2 slice network
+	e = bnet.equiv_class(c, 2);
+	CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,t-1:t));
+      end
+      temp = pot_to_marginal(CPDpot);
+      lam_msg = normalise(temp.T);
+      %if verbose, fprintf('(%d,%d) sends lambda to (%d,%d)\n', c,t, i,t); disp(lam_msg); end
+      intra_lambda_msg{c,i,t} = lam_msg;
+    end
+  end
+end
+
+% FORWARD
+for t=1:T
+  % update pi
+  for i=hnodes
+    if t==1
+      e = bnet.equiv_class(i,1);
+      temp = struct(bnet.CPD{e});
+      pi{i,t} = temp.CPT;
+    else
+      e = bnet.equiv_class(i,2);
+      temp = struct(bnet.CPD{e});
+      ps = parents(bnet.inter, i);
+      dom = [ps i+ss];
+      pot = dpot(dom, ns(dom), temp.CPT);
+      for p=ps(:)'
+	temp = dpot(p, ns(p), inter_pi_msg{p,i,t});
+	pot = multiply_by_pot(pot, temp);
+      end
+      pot = marginalize_pot(pot, i+ss);
+      temp = pot_to_marginal(pot);
+      pi{i,t} = temp.T;
+      %if verbose, fprintf('(%d,%d) computes pi\n', i,t); disp(pi{i,t}); end
+    end
+    
+    c = engine.obschild(i);
+    if c > 0
+      pi{i,t} = normalise(pi{i,t} .* intra_lambda_msg{c,i,t});
+    end
+    %if verbose, fprintf('(%d,%d) recomputes pi\n', i,t); disp(pi{i,t}); end
+    if verbose, fprintf('%d recomputes pi\n', i+(t-1)*ss); disp(pi{i,t}); end
+  end
+  
+  % send pi msg to children 
+  for i=hnodes
+    cs = children(bnet.inter, i);
+    for c=cs(:)'
+      pot = pi{i,t};
+      for k=cs(:)'
+	if k ~= c
+	  pot = pot .* inter_lambda_msg{k,i,t};
+	end
+      end
+      cs2 = children(bnet.intra, i);
+      for k=cs2(:)'
+	pot = pot .* intra_lambda_msg{k,i,t};
+      end
+      pot = normalise(pot);
+      %if verbose, fprintf('(%d,%d) sends pi to (%d,%d)\n', i,t, c,t+1); disp(pot); end
+      if verbose, fprintf('%d sends pi to %d\n', i+(t-1)*ss, c+t*ss); disp(pot); end
+      inter_pi_msg{i,c,t+1} = pot;
+    end
+  end
+end
+
+
+marginal = cell(ss,T);
+for t=1:T
+  for i=hnodes
+    %marginal{i,t} = normalise(pi{i,t} .* lambda{i,t});     
+    marginal{i,t} = normalise(pi{i,t});
+  end
+end
+
+loglik = 0;
+
+msg.inter_pi_msg = inter_pi_msg;
+msg.inter_lambda_msg = inter_lambda_msg;
+msg.intra_lambda_msg = intra_lambda_msg;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/filter_evidence_obj_oriented.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,158 @@
+function [marginal, msg, loglik] = filter_evidence_old(engine, evidence)
+% [marginal, msg, loglik] = filter_evidence(engine, evidence) (pearl_dbn)
+
+[ss T] = size(evidence);
+bnet = bnet_from_engine(engine);
+bnet2 = dbn_to_bnet(bnet, T);
+ns = bnet2.node_sizes;
+hnodes = mysetdiff(1:ss, engine.onodes);
+hnodes = hnodes(:)';
+
+[engine.parent_index, engine.child_index] = mk_pearl_msg_indices(bnet2);
+
+msg = init_msgs(bnet2.dag, ns, evidence);
+msg = init_ev_msgs(engine, evidence, msg);
+
+verbose = 1;
+if verbose, fprintf('\nold filtering\n'); end
+
+for t=1:T
+  % update pi
+  for i=hnodes
+    n = i + (t-1)*ss;
+    ps = parents(bnet2.dag, n);
+    if t==1
+      e = bnet.equiv_class(i,1);
+    else
+      e = bnet.equiv_class(i,2);
+    end
+    msg{n}.pi = compute_pi(bnet.CPD{e}, n, ps, msg);
+    %if verbose, fprintf('%d computes pi\n', n); disp(msg{n}.pi); end
+    msg{n}.pi = normalise(msg{n}.pi(:) .* msg{n}.lambda_from_self(:));
+    if verbose, fprintf('%d recomputes pi\n', n); disp(msg{n}.pi); end
+  end
+  % send pi msg to children
+  for i=hnodes
+    n = i + (t-1)*ss;
+    cs = children(bnet2.dag, n);
+    for c=cs(:)'
+      j = engine.parent_index{c}(n); % n is c's j'th parent
+      pi_msg = normalise(compute_pi_msg(n, cs, msg, c, ns));
+      msg{c}.pi_from_parent{j} = pi_msg;
+      if verbose, fprintf('%d sends pi to %d\n', n,c); disp(pi_msg); end
+    end
+  end
+end
+
+
+marginal = cell(ss,T);
+lik = zeros(1,ss*T);
+for t=1:T
+  for i=1:ss
+    n = i + (t-1)*ss;
+    %[bel, lik(n)] = normalise(msg{n}.pi .* msg{n}.lambda);     
+    [bel, lik(n)] = normalise(msg{n}.pi);
+    marginal{i,t} = bel;
+  end
+end
+
+loglik = sum(log(lik));
+
+
+
+%%%%%%%
+
+function lambda = compute_lambda(n, cs, msg, ns)
+% Pearl p183 eq 4.50
+lambda = prod_lambda_msgs(n, cs, msg, ns);
+
+%%%%%%%
+
+function pi_msg = compute_pi_msg(n, cs, msg, c, ns)
+% Pearl p183 eq 4.53 and 4.51
+pi_msg = msg{n}.pi .* prod_lambda_msgs(n, cs, msg, ns, c);
+
+%%%%%%%%%
+
+function lam = prod_lambda_msgs(n, cs, msg, ns, except)
+
+if nargin < 5, except = -1; end
+
+%lam = msg{n}.lambda_from_self(:);
+lam = ones(ns(n), 1);
+for i=1:length(cs)
+  c = cs(i);
+  if c ~= except
+    lam = lam .* msg{n}.lambda_from_child{i};
+  end
+end   
+
+
+%%%%%%%%%%%
+
+function msg = init_msgs(dag, ns, evidence)
+% INIT_MSGS Initialize the lambda/pi message and state vectors (pearl_dbn)
+% msg =  init_msgs(dag, ns, evidence)
+%
+% We assume all the hidden nodes are discrete.
+
+N = length(dag);
+msg = cell(1,N);
+observed = ~isemptycell(evidence(:));
+
+for n=1:N
+  ps = parents(dag, n);
+  msg{n}.pi_from_parent = cell(1, length(ps));
+  for i=1:length(ps)
+    p = ps(i);
+    msg{n}.pi_from_parent{i} = ones(ns(p), 1);
+  end
+  
+  cs = children(dag, n);
+  msg{n}.lambda_from_child = cell(1, length(cs));
+  for i=1:length(cs)
+    c = cs(i);
+    msg{n}.lambda_from_child{i} = ones(ns(n), 1);
+  end
+
+  msg{n}.lambda = ones(ns(n), 1);
+  msg{n}.pi = ones(ns(n), 1);
+  
+  msg{n}.lambda_from_self = ones(ns(n), 1);
+end
+
+
+%%%%%%%%%
+
+function msg = init_ev_msgs(engine, evidence, msg)
+% Initialize the lambdas with any evidence
+
+[ss T] = size(evidence);
+bnet = bnet_from_engine(engine);
+pot_type = 'd';
+t = 1;
+hnodes = mysetdiff(1:ss, engine.onodes);
+for i=hnodes(:)'
+  c = engine.obschild(i);
+  if c > 0
+    fam = family(bnet.dag, c);
+    e = bnet.equiv_class(c, 1);
+    CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,1));
+    temp = pot_to_marginal(CPDpot);
+    n = i;
+    msg{n}.lambda_from_self = temp.T;
+  end
+end
+for t=2:T
+  for i=hnodes(:)'
+    c = engine.obschild(i);
+    if c > 0 
+      fam = family(bnet.dag, c, 2);
+      e = bnet.equiv_class(c, 2);
+      CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,t-1:t));
+      temp = pot_to_marginal(CPDpot);
+      n = i + (t-1)*ss;
+      msg{n}.lambda_from_self = temp.T;
+    end
+  end
+end       
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/smooth_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,181 @@
+function [marginal, msg, loglik] = smooth_evidence(engine, evidence)
+
+[ss T] = size(evidence);
+bnet = bnet_from_engine(engine);
+onodes = engine.onodes;
+hnodes = mysetdiff(1:ss, onodes);
+hnodes = hnodes(:)';
+
+ns = bnet.node_sizes(:);
+onodes2 = [onodes(:); onodes(:)+ss];
+ns(onodes2) = 1;
+	   
+verbose = 0;
+pot_type = 'd';
+niter = engine.max_iter;
+
+if verbose, fprintf('new smooth\n'); end
+
+% msg(i1,t1,i2,j2) (i1,t1) -> (i2,t2)
+%lambda_msg = cell(ss,T,ss,T);
+%pi_msg = cell(ss,T,ss,T);
+
+% intra_lambda_msg(i,j,t) (i,t) -> (j,t), i is child
+% inter_lambda_msg(i,j,t) (i,t+1) -> (j,t), i is child
+% inter_pi_msg(i,j,t) (i,t-1) -> (j,t), i is parent
+intra_lambda_msg = cell(ss,ss,T);
+inter_lambda_msg = cell(ss,ss,T);
+inter_pi_msg = cell(ss,ss,T);
+
+lambda = cell(ss,T);
+pi = cell(ss,T);
+
+for t=1:T
+  for i=1:ss
+    lambda{i,t} = ones(ns(i), 1);
+    pi{i,t} = ones(ns(i), 1);
+    
+    cs = children(bnet.intra, i);
+    for c=cs(:)'
+      intra_lambda_msg{c,i,t} = ones(ns(i),1);
+    end
+    
+    cs = children(bnet.inter, i);
+    for c=cs(:)'
+      inter_lambda_msg{c,i,t} = ones(ns(i),1);
+    end
+    
+    ps = parents(bnet.inter, i);
+    for p=ps(:)'
+      inter_pi_msg{p,i,t} = ones(ns(i), 1); % not used for t==1
+    end
+  end
+end
+
+
+% each hidden node absorbs lambda from its observed child (if any)
+for t=1:T
+  for i=hnodes
+    c = engine.obschild(i);
+    if c > 0
+      if t==1
+	fam = family(bnet.dag, c);
+	e = bnet.equiv_class(c, 1);
+	CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,1));
+      else
+	fam = family(bnet.dag, c, 2); % within 2 slice network
+	e = bnet.equiv_class(c, 2);
+	CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,t-1:t));
+      end
+      temp = pot_to_marginal(CPDpot);
+      lam_msg = normalise(temp.T);
+      intra_lambda_msg{c,i,t} = lam_msg;
+    end
+  end
+end
+
+for iter=1:engine.max_iter
+  % FORWARD
+  for t=1:T
+    % update pi
+    for i=hnodes
+      if t==1
+	e = bnet.equiv_class(i,1);
+	CPD = struct(bnet.CPD{e});
+	pi{i,t} = CPD.CPT;
+      else
+	e = bnet.equiv_class(i,2);
+	CPD = struct(bnet.CPD{e});
+	ps = parents(bnet.inter, i);
+	dom = [ps i+ss];
+	pot = dpot(dom, ns(dom), CPD.CPT);
+	for p=ps(:)'
+	  temp = dpot(p, ns(p), inter_pi_msg{p,i,t});
+	  pot = multiply_by_pot(pot, temp);
+	end
+	pot = marginalize_pot(pot, i+ss);
+	temp = pot_to_marginal(pot);
+	pi{i,t} = temp.T;
+      end
+      if verbose, fprintf('%d updates pi\n', i+(t-1)*ss); disp(pi{i,t}); end
+    end
+    
+    % send pi msg to children 
+    for i=hnodes
+      cs = children(bnet.inter, i);
+      for c=cs(:)'
+	pot = pi{i,t};
+	for k=cs(:)'
+	  if k ~= c
+	    pot = pot .* inter_lambda_msg{k,i,t};
+	  end
+	end
+	cs2 = children(bnet.intra, i);
+	for k=cs2(:)'
+	  pot = pot .* intra_lambda_msg{k,i,t};
+	end
+	inter_pi_msg{i,c,t+1} = normalise(pot);
+	if verbose, fprintf('%d sends pi to %d\n', i+(t-1)*ss, c+t*ss); disp(inter_pi_msg{i,c,t+1}); end
+      end
+    end
+  end
+
+  if verbose, fprintf('backwards\n'); end
+  % BACKWARD
+  for t=T:-1:1
+    % update lambda
+    for i=hnodes
+      pot = ones(ns(i), 1);
+      cs = children(bnet.inter, i);
+      for c=cs(:)'
+	pot = pot .* inter_lambda_msg{c,i,t};
+      end
+      cs = children(bnet.intra, i);
+      for c=cs(:)'
+	pot = pot .* intra_lambda_msg{c,i,t};
+      end
+      lambda{i,t} = normalise(pot);
+      if verbose, fprintf('%d computes lambda\n', i+(t-1)*ss); disp(lambda{i,t}); end
+    end
+    
+    % send lambda msgs to hidden parents in prev slcie
+    for i=hnodes
+      ps = parents(bnet.inter, i);
+      if t > 1
+	e = bnet.equiv_class(i, 2);
+	CPD = struct(bnet.CPD{e});
+	fam = [ps i+ss];
+	for p=ps(:)'
+	  pot = dpot(fam, ns(fam), CPD.CPT);
+	  temp = dpot(i+ss, ns(i), lambda{i,t});
+	  pot = multiply_by_pot(pot, temp);
+	  for k=ps(:)'
+	    if k ~= p
+	      temp = dpot(k, ns(k), inter_pi_msg{k,i,t});
+	      pot = multiply_by_pot(pot, temp);
+	    end
+	  end
+	  pot = marginalize_pot(pot, p);
+	  temp = pot_to_marginal(pot);
+	  inter_lambda_msg{i,p,t-1} = normalise(temp.T);
+	  if verbose, fprintf('%d sends lambda to %d\n', i+(t-1)*ss, p+(t-2)*ss); disp(inter_lambda_msg{i,p,t-1}); end
+	end
+      end
+    end
+  end
+end
+
+
+
+marginal = cell(ss,T);
+for t=1:T
+  for i=hnodes
+    marginal{i,t} = normalise(pi{i,t} .* lambda{i,t});     
+  end
+end
+
+loglik = 0;
+
+msg.inter_pi_msg = inter_pi_msg;
+msg.inter_lambda_msg = inter_lambda_msg;
+msg.intra_lambda_msg = intra_lambda_msg;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/smooth_evidence_fast.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,179 @@
+function [marginal, msg, loglik] = smooth_evidence_fast(engine, evidence)
+
+[ss T] = size(evidence);
+bnet = bnet_from_engine(engine);
+onodes = engine.onodes;
+hnodes = mysetdiff(1:ss, onodes);
+hnodes = hnodes(:)';
+
+ns = bnet.node_sizes(:);
+onodes2 = [onodes(:); onodes(:)+ss];
+ns(onodes2) = 1;
+	   
+verbose = 0;
+pot_type = 'd';
+niter = engine.max_iter;
+
+if verbose, fprintf('new smooth\n'); end
+
+% msg(i1,t1,i2,j2) (i1,t1) -> (i2,t2)
+%lambda_msg = cell(ss,T,ss,T);
+%pi_msg = cell(ss,T,ss,T);
+
+% intra_lambda_msg(i,j,t) (i,t) -> (j,t), i is child
+% inter_lambda_msg(i,j,t) (i,t+1) -> (j,t), i is child
+% inter_pi_msg(i,j,t) (i,t-1) -> (j,t), i is parent
+intra_lambda_msg = cell(ss,ss,T);
+inter_lambda_msg = cell(ss,ss,T);
+inter_pi_msg = cell(ss,ss,T);
+
+lambda = cell(ss,T);
+pi = cell(ss,T);
+
+for t=1:T
+  for i=1:ss
+    lambda{i,t} = ones(ns(i), 1);
+    pi{i,t} = ones(ns(i), 1);
+    
+    cs = children(bnet.intra, i);
+    for c=cs(:)'
+      intra_lambda_msg{c,i,t} = ones(ns(i),1);
+    end
+    
+    cs = children(bnet.inter, i);
+    for c=cs(:)'
+      inter_lambda_msg{c,i,t} = ones(ns(i),1);
+    end
+    
+    ps = parents(bnet.inter, i);
+    for p=ps(:)'
+      inter_pi_msg{p,i,t} = ones(ns(i), 1); % not used for t==1
+    end
+  end
+end
+
+
+% each hidden node absorbs lambda from its observed child (if any)
+for t=1:T
+  for i=hnodes
+    c = engine.obschild(i);
+    if c > 0
+      if t==1
+	fam = family(bnet.dag, c);
+	e = bnet.equiv_class(c, 1);
+	CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,1));
+      else
+	fam = family(bnet.dag, c, 2); % within 2 slice network
+	e = bnet.equiv_class(c, 2);
+	CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,t-1:t));
+      end
+      temp = pot_to_marginal(CPDpot);
+      lam_msg = normalise(temp.T);
+      intra_lambda_msg{c,i,t} = lam_msg;
+    end
+  end
+end
+
+for iter=1:engine.max_iter
+  % FORWARD
+  for t=1:T
+    % update pi
+    for i=hnodes
+      if t==1
+	e = bnet.equiv_class(i,1);
+	temp = struct(bnet.CPD{e});
+	pi{i,t} = temp.CPT;
+      else
+	e = bnet.equiv_class(i,2);
+	CPD = struct(bnet.CPD{e});
+	ps = parents(bnet.inter, i);
+	temp = CPD.CPT;
+	for p=ps(:)'
+	  temp(:) = temp(:) .* inter_pi_msg{p,i,t}(engine.mult_parent_ndx{i,p});
+	end
+	dom = [ps i+ss];
+	pot = dpot(dom, ns(dom), temp);
+	pot = marginalize_pot(pot, i+ss);
+	temp = pot_to_marginal(pot);
+	pi{i,t} = temp.T;
+      end
+      if verbose, fprintf('%d updates pi\n', i+(t-1)*ss); disp(pi{i,t}); end
+    end
+    
+    % send pi msg to children 
+    for i=hnodes
+      cs = children(bnet.inter, i);
+      for c=cs(:)'
+	pot = pi{i,t};
+	for k=cs(:)'
+	  if k ~= c
+	    pot = pot .* inter_lambda_msg{k,i,t};
+	  end
+	end
+	cs2 = children(bnet.intra, i);
+	for k=cs2(:)'
+	  pot = pot .* intra_lambda_msg{k,i,t};
+	end
+	inter_pi_msg{i,c,t+1} = normalise(pot);
+	if verbose, fprintf('%d sends pi to %d\n', i+(t-1)*ss, c+t*ss); disp(inter_pi_msg{i,c,t+1}); end
+      end
+    end
+  end
+
+  if verbose, fprintf('backwards\n'); end
+  % BACKWARD
+  for t=T:-1:1
+    % update lambda
+    for i=hnodes
+      pot = ones(ns(i), 1);
+      cs = children(bnet.inter, i);
+      for c=cs(:)'
+	pot = pot .* inter_lambda_msg{c,i,t};
+      end
+      cs = children(bnet.intra, i);
+      for c=cs(:)'
+	pot = pot .* intra_lambda_msg{c,i,t};
+      end
+      lambda{i,t} = normalise(pot);
+      if verbose, fprintf('%d computes lambda\n', i+(t-1)*ss); disp(lambda{i,t}); end
+    end
+    
+    % send lambda msgs to hidden parents in prev slcie
+    for i=hnodes
+      ps = parents(bnet.inter, i);
+      if t > 1
+	e = bnet.equiv_class(i, 2);
+	CPD = struct(bnet.CPD{e});
+	for p=ps(:)'
+	  temp = CPD.CPT(:) .* lambda{i,t}(engine.mult_self_ndx{i});
+	  for k=ps(:)'
+	    if k ~= p
+	      temp(:) = temp(:) .* inter_pi_msg{k,i,t}(engine.mult_parent_ndx{i,k});
+	    end
+	  end
+	  fam = [ps i+ss];
+	  pot = dpot(fam, ns(fam), temp);
+	  pot = marginalize_pot(pot, p);
+	  temp = pot_to_marginal(pot);
+	  inter_lambda_msg{i,p,t-1} = normalise(temp.T);
+	  if verbose, fprintf('%d sends lambda to %d\n', i+(t-1)*ss, p+(t-2)*ss); disp(inter_lambda_msg{i,p,t-1}); end
+	end
+      end
+    end
+  end
+end
+
+
+
+marginal = cell(ss,T);
+for t=1:T
+  for i=hnodes
+    marginal{i,t} = normalise(pi{i,t} .* lambda{i,t});     
+  end
+end
+
+loglik = 0;
+
+msg.inter_pi_msg = inter_pi_msg;
+msg.inter_lambda_msg = inter_lambda_msg;
+msg.intra_lambda_msg = intra_lambda_msg;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/Old/wrong_smooth.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,210 @@
+function [marginal, msg, loglik] = smooth_evidence(engine, evidence)
+% [marginal, msg, loglik] = smooth_evidence(engine, evidence) (pearl_dbn)
+
+disp('warning: pearl_dbn smoothing is broken');
+
+[ss T] = size(evidence);
+bnet = bnet_from_engine(engine);
+bnet2 = dbn_to_bnet(bnet, T);
+ns = bnet2.node_sizes;
+hnodes = mysetdiff(1:ss, engine.onodes);
+hnodes = hnodes(:)';
+
+onodes2 = unroll_set(engine.onodes(:), ss, T);
+onodes2 = onodes2(:)';
+
+hnodes2 = unroll_set(hnodes(:), ss, T);
+hnodes2 = hnodes2(:)';
+
+[engine.parent_index, engine.child_index] = mk_pearl_msg_indices(bnet2);
+
+msg = init_msgs(bnet2.dag, ns, evidence, bnet2.equiv_class, bnet2.CPD);
+
+verbose = 0;
+pot_type = 'd';
+niter = 1;
+for iter=1:niter
+  % FORWARD
+  for t=1:T
+    if verbose, fprintf('t=%d\n', t); end
+
+    % each hidden node absorbs lambda from its observed child (if any)
+    for i=hnodes
+      c = engine.obschild(i);
+      if c > 0
+	if t==1
+	  fam = family(bnet.dag, c);
+	  e = bnet.equiv_class(c, 1);
+	  CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,1));
+	else
+	  fam = family(bnet.dag, 2); % within 2 slice network
+	  e = bnet.equiv_class(c, 2);
+	  CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,t-1:t));
+	end
+	temp = pot_to_marginal(CPDpot);
+	n = i + (t-1)*ss;
+	lam_msg = normalise(temp.T);
+	j = engine.child_index{n}(c+(t-1)*ss);
+	assert(j==1);
+	msg{n}.lambda_from_child{j} = lam_msg;
+	if verbose, fprintf('%d sends lambda to %d\n', c + (t-1)*ss, n); disp(lam_msg); end
+      end
+    end
+    
+    % update pi
+    for i=hnodes
+      n = i + (t-1)*ss;
+      ps = parents(bnet2.dag, n);
+      if t==1
+	e = bnet.equiv_class(i,1);
+      else
+	e = bnet.equiv_class(i,2);
+      end
+      msg{n}.pi = compute_pi(bnet.CPD{e}, n, ps, msg);
+      if verbose, fprintf('%d computes pi\n', n); disp(msg{n}.pi); end
+    end
+    
+    % send pi msg to children in next slice
+    for i=hnodes
+      n = i + (t-1)*ss;
+      %cs = myintersect(children(bnet2.dag, n), hnodes2);
+      cs = children(bnet2.dag, n);
+      for c=cs(:)'
+	j = engine.parent_index{c}(n); % n is c's j'th parent
+	pi_msg = normalise(compute_pi_msg(n, cs, msg, c, ns));
+	msg{c}.pi_from_parent{j} = pi_msg;
+	if verbose, fprintf('%d sends pi to %d\n', n, c); disp(pi_msg); end
+      end
+    end
+  end
+
+  % BACKWARD
+  for t=T:-1:1
+    if verbose, fprintf('t = %d\n', t); end
+
+    % update lambda
+    for i=hnodes
+      n = i + (t-1)*ss;
+      cs = children(bnet2.dag, n);
+      msg{n}.lambda = compute_lambda(n, cs, msg, ns);
+      if verbose, fprintf('%d computes lambda\n', n); disp(msg{n}.lambda); end
+    end
+    
+    % send lambda msgs to hidden parents in prev slcie
+    for i=hnodes
+      n = i + (t-1)*ss;
+      %ps = myintersect(parents(bnet2.dag, n), hnodes2);
+      ps = parents(bnet2.dag, n);
+      for p=ps(:)'
+	j = engine.child_index{p}(n); % n is p's j'th child
+	if t > 1
+	  e = bnet.equiv_class(i, 2);
+	else
+	  e = bnet.equiv_class(i, 1);
+	end
+	lam_msg = normalise(compute_lambda_msg(bnet.CPD{e}, n, ps, msg, p));
+	msg{p}.lambda_from_child{j} = lam_msg;
+	if verbose, fprintf('%d sends lambda to %d\n', n, p); disp(lam_msg); end
+      end 
+    end
+        
+    % send pi msg to observed children 
+    if 0
+    for i=hnodes
+      n = i + (t-1)*ss;
+      cs = myintersect(children(bnet2.dag, n), onodes2);
+      %cs = children(bnet2.dag, n);
+      for c=cs(:)'
+	j = engine.parent_index{c}(n); % n is c's j'th parent
+	pi_msg = normalise(compute_pi_msg(n, cs, msg, c, ns));
+	msg{c}.pi_from_parent{j} = pi_msg;
+	if verbose, fprintf('%d sends pi to %d\n', n, c); disp(pi_msg); end
+      end
+    end
+    end
+    
+  end
+end
+
+
+marginal = cell(ss,T);
+lik = zeros(1,ss*T);
+for t=1:T
+  for i=hnodes
+    n = i + (t-1)*ss;
+    [bel, lik(n)] = normalise(msg{n}.pi .* msg{n}.lambda);     
+    marginal{i,t} = bel;
+  end
+end
+
+loglik = 0;
+%loglik = sum(log(lik));
+
+
+
+%%%%%%%
+
+function lambda = compute_lambda(n, cs, msg, ns)
+% Pearl p183 eq 4.50
+lambda = prod_lambda_msgs(n, cs, msg, ns);
+
+%%%%%%%
+
+function pi_msg = compute_pi_msg(n, cs, msg, c, ns)
+% Pearl p183 eq 4.53 and 4.51
+pi_msg = msg{n}.pi .* prod_lambda_msgs(n, cs, msg, ns, c);
+
+%%%%%%%%%
+
+function lam = prod_lambda_msgs(n, cs, msg, ns, except)
+
+if nargin < 5, except = -1; end
+
+%lam = msg{n}.lambda_from_self(:);
+lam = ones(ns(n), 1);
+for i=1:length(cs)
+  c = cs(i);
+  if c ~= except
+    lam = lam .* msg{n}.lambda_from_child{i};
+  end
+end   
+
+
+%%%%%%%%%
+
+function msg = init_msgs(dag, ns, evidence, eclass, CPD)
+% INIT_MSGS Initialize the lambda/pi message and state vectors (pearl_dbn)
+% msg =  init_msgs(dag, ns, evidence)
+
+N = length(dag);
+msg = cell(1,N);
+observed = ~isemptycell(evidence(:));
+
+for n=1:N
+  ps = parents(dag, n);
+  msg{n}.pi_from_parent = cell(1, length(ps));
+  for i=1:length(ps)
+    p = ps(i);
+    msg{n}.pi_from_parent{i} = ones(ns(p), 1);
+  end
+  
+  cs = children(dag, n);
+  msg{n}.lambda_from_child = cell(1, length(cs));
+  for i=1:length(cs)
+    c = cs(i);
+    msg{n}.lambda_from_child{i} = ones(ns(n), 1);
+  end
+
+  msg{n}.lambda = ones(ns(n), 1);
+  msg{n}.pi = ones(ns(n), 1);
+
+  % Initialize the lambdas with any evidence
+  if observed(n)
+    v = evidence{n};
+    msg{n}.lambda = zeros(ns(n), 1);
+    msg{n}.lambda(v) = 1; % delta function
+    msg{n}.lambda = [];
+  end      
+  
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,35 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (loopy_dbn)
+% [engine, loglik] = enter_evidence(engine, evidence, ....)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product (not yet supported), else sum-product [0]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+maximize = 0;
+filter = 0;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1}; 
+     case 'filter', filter = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+assert(~maximize);
+assert(~filter);
+
+[engine.marginal, engine.msg, loglik] = enter_soft_ev(engine, evidence);
+engine.evidence = evidence; % needed by marginal_nodes and marginal_family
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/enter_soft_ev.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,137 @@
+function [marginal, msg, loglik] = enter_soft_ev(engine, evidence)
+% [marginal, msg, loglik] = smooth_evidence(engine, evidence) (pearl_dbn)
+
+
+[ss T] = size(evidence);
+bnet = bnet_from_engine(engine);
+bnet2 = dbn_to_bnet(bnet, T);
+ns = bnet2.node_sizes;
+hnodes = mysetdiff(1:ss, engine.onodes);
+hnodes = hnodes(:)';
+
+onodes2 = unroll_set(engine.onodes(:), ss, T);
+onodes2 = onodes2(:)';
+
+hnodes2 = unroll_set(hnodes(:), ss, T);
+hnodes2 = hnodes2(:)';
+
+[engine.parent_index, engine.child_index] = mk_pearl_msg_indices(bnet2);
+
+rand_init = 0;
+use_ev = 0;
+msg = init_pearl_msgs(bnet2.dag, ns, evidence, rand_init, use_ev);
+msg = init_pearl_dbn_ev_msgs(bnet, evidence, engine);
+
+verbose = 0;
+pot_type = 'd';
+niter = engine.max_iter;
+
+if verbose, fprintf('old smooth\n'); end
+
+for iter=1:niter
+  % FORWARD
+  for t=1:T
+    if verbose, fprintf('t=%d\n', t); end
+    
+    % update pi
+    for i=hnodes
+      n = i + (t-1)*ss;
+      ps = parents(bnet2.dag, n);
+      if t==1
+	e = bnet.equiv_class(i,1);
+      else
+	e = bnet.equiv_class(i,2);
+      end
+      msg{n}.pi = compute_pi(bnet.CPD{e}, n, ps, msg);
+      if verbose, fprintf('%d computes pi\n', n); disp(msg{n}.pi); end
+    end
+    
+    % send pi msg to children 
+    for i=hnodes
+      n = i + (t-1)*ss;
+      %cs = myintersect(children(bnet2.dag, n), hnodes2);
+      cs = children(bnet2.dag, n); % must use all children to get index right
+      for c=cs(:)'
+	j = engine.parent_index{c}(n); % n is c's j'th parent
+	pi_msg = normalise(compute_pi_msg(n, cs, msg, c, ns));
+	msg{c}.pi_from_parent{j} = pi_msg;
+	if verbose, fprintf('%d sends pi to %d\n', n, c); disp(pi_msg); end
+      end
+    end
+  end
+
+  % BACKWARD
+  for t=T:-1:1
+    if verbose, fprintf('t = %d\n', t); end
+
+    % update lambda
+    for i=hnodes
+      n = i + (t-1)*ss;
+      cs = children(bnet2.dag, n);
+      msg{n}.lambda = compute_lambda(n, cs, msg, ns);
+      if verbose, fprintf('%d computes lambda\n', n); disp(msg{n}.lambda); end
+    end
+    
+    % send lambda msgs to hidden parents in prev slcie
+    for i=hnodes
+      n = i + (t-1)*ss;
+      ps = parents(bnet2.dag, n);
+      for p=ps(:)'
+	j = engine.child_index{p}(n); % n is p's j'th child
+	if t > 1
+	  e = bnet.equiv_class(i, 2);
+	else
+	  e = bnet.equiv_class(i, 1);
+	end
+	lam_msg = normalise(compute_lambda_msg(bnet.CPD{e}, n, ps, msg, p));
+	msg{p}.lambda_from_child{j} = lam_msg;
+	if verbose, fprintf('%d sends lambda to %d\n', n, p); disp(lam_msg); end
+      end 
+    end
+    
+  end
+end
+
+
+marginal = cell(ss,T);
+lik = zeros(1,ss*T);
+for t=1:T
+  for i=hnodes
+    n = i + (t-1)*ss;
+    [bel, lik(n)] = normalise(msg{n}.pi .* msg{n}.lambda);     
+    marginal{i,t} = bel;
+  end
+end
+
+loglik = 0;
+%loglik = sum(log(lik));
+
+
+
+%%%%%%%
+
+function lambda = compute_lambda(n, cs, msg, ns)
+% Pearl p183 eq 4.50
+lambda = prod_lambda_msgs(n, cs, msg, ns);
+
+%%%%%%%
+
+function pi_msg = compute_pi_msg(n, cs, msg, c, ns)
+% Pearl p183 eq 4.53 and 4.51
+pi_msg = msg{n}.pi .* prod_lambda_msgs(n, cs, msg, ns, c);
+
+%%%%%%%%%
+
+function lam = prod_lambda_msgs(n, cs, msg, ns, except)
+
+if nargin < 5, except = -1; end
+
+%lam = msg{n}.lambda_from_self(:);
+lam = ones(ns(n), 1);
+for i=1:length(cs)
+  c = cs(i);
+  if c ~= except
+    lam = lam .* msg{n}.lambda_from_child{i};
+  end
+end   
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function marginal = marginal_nodes(engine, nodes, t)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (pearl_dbn)
+% marginal = marginal_nodes(engine, i, t)
+% returns Pr(X(i,t) | Y(1:T)), where X(i,t) is the i'th node in the t'th slice.
+% If enter_evidence used filtering instead of smoothing, this will return  Pr(X(i,t) | Y(1:t)).
+
+if nargin < 3, t = 1; end
+assert(length(nodes)==1);
+i = nodes(end);
+if ~myismember(i, engine.onodes)
+  marginal.T = engine.marginal{i,t};
+else
+  marginal.T = 1; % observed
+end
+
+% we convert the domain to the unrolled numbering system
+% so that update_ess extracts the right evidence.
+marginal.domain = nodes+(t-1)*engine.ss;       
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/pearl_dbn_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,65 @@
+function engine = pearl_dbn_inf_engine(bnet, varargin)
+% LOOPY_DBN_INF_ENGINE Loopy Pearl version of forwards-backwards
+% engine = loopy_dbn_inf_engine(bnet, ...)
+%
+% Optional arguments
+% 'max_iter' - specifies the max num. forward-backward passes to perform [1]
+% 'tol' - as in loopy_pearl [1e-3]
+% 'momentum' - as in loopy_pearl [0]
+
+error('pearl_dbn does not work yet')
+
+max_iter = 1;
+tol = 1e-3;
+momentum = 0;
+
+if nargin >= 2
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'max_iter', max_iter = args{i+1};
+     case 'tol', tol = args{i+1};
+     case 'momentum', momentum = args{i+1};
+    end
+  end
+end
+
+          
+engine.max_iter = max_iter;
+engine.tol = tol;
+engine.momentum = momentum;
+engine.pearl_engine = [];
+engine.T = [];
+engine.ss = length(bnet.intra);
+
+engine.marginal = [];
+engine.evidence = [];
+engine.msg = [];
+engine.parent_index = [];
+engine.child_index = [];
+%[engine.parent_index, engine.child_index] = mk_pearl_msg_indices(bnet); % need to unroll first
+
+ss = length(bnet.intra);
+engines.ss = ss;
+onodes = bnet.observed;
+hnodes = mysetdiff(1:ss, onodes);
+obschild = zeros(1,ss);
+for i=hnodes(:)'
+  %ocs = myintersect(children(bnet.dag, i), onodes);
+  ocs = children(bnet.intra, i);
+  assert(length(ocs) <= 1);
+  if length(ocs)==1
+    obschild(i) = ocs(1);
+  end
+end
+engine.obschild = obschild;
+
+engine.mult_self_ndx = [];
+engine.mult_parent_ndx = [];
+engine.marg_self_ndx = [];
+engine.marg_parent_ndx = [];
+
+
+engine = class(engine, 'loopy_dbn_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/init_pearl_dbn_ev_msgs.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_dbn_inf_engine/private/init_pearl_dbn_ev_msgs.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function msg = init_pearl_dbn_ev_msgs(bnet, evidence, engine)
+
+[ss T] = size(evidence);
+pot_type = 'd';
+
+% each hidden node absorbs lambda from its observed child (if any)
+for t=1:T
+  for i=hnodes
+    c = engine.obschild(i);
+    if c > 0
+      if t==1
+	fam = family(bnet.dag, c);
+	e = bnet.equiv_class(c, 1);
+	CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,1));
+      else
+	fam = family(bnet.dag, c, 2); % within 2 slice network
+	e = bnet.equiv_class(c, 2);
+	CPDpot = CPD_to_pot(pot_type, bnet.CPD{e}, fam, bnet.node_sizes(:), bnet.cnodes(:), evidence(:,t-1:t));
+      end
+      temp = pot_to_marginal(CPDpot);
+      n = i + (t-1)*ss;
+      lam_msg = normalise(temp.T);
+      j = engine.child_index{n}(c+(t-1)*ss);
+      assert(j==1);
+      msg{n}.lambda_from_child{j} = lam_msg;
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/pearl_unrolled_dbn_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/update_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,41 @@
+function [engine, loglik, niter] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (loopy_unrolled_dbn)
+% [engine, loglik, niter] = enter_evidence(engine, evidence, ....)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product (not yet supported), else sum-product [0]
+% filename - as in loopy_pearl
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+maximize = 0;
+filename = engine.filename;
+
+if nargin >= 2
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1};
+     case 'filename', filename = args{i+1};
+    end
+  end
+end
+
+
+[ss T] = size(evidence);
+if T ~= engine.T
+  bnetT = dbn_to_bnet(bnet_from_engine(engine), T);
+  engine.unrolled_engine = pearl_inf_engine(bnetT, 'protocol', engine.protocol, ...
+					    'max_iter', engine.max_iter_per_slice * T, ...
+					    'tol', engine.tol, 'momentum', engine.momentum);
+  engine.T = T;
+end
+[engine.unrolled_engine, loglik, niter] = enter_evidence(engine.unrolled_engine, evidence(:), ...
+						  'maximize', maximize, 'filename', filename);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function marginal = marginal_family(engine, i, t, add_ev)
+% MARGINAL_FAMILY Compute the marginal on the specified family (jtree_unrolled_dbn)
+% marginal = marginal_family(engine, i, t)
+
+if nargin < 3, t = 1; end
+if nargin < 4, add_ev = 0; end
+assert(~add_ev);
+
+%marginal = marginal_family(engine.unrolled_engine, i + (t-1)*engine.ss, add_ev);
+marginal = marginal_family(engine.unrolled_engine, i + (t-1)*engine.ss);
+              
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function marginal = marginal_nodes(engine, nodes, t, add_ev)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (loopy_unrolled_dbn)
+% marginal = marginal_nodes(engine, nodes, t)
+%
+% 't' specifies the time slice of the earliest node in 'nodes'.
+% 'nodes' must occur in some clique.
+%
+% Example:
+% Consider a DBN with 2 nodes per slice.
+% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3,
+% i.e., nodes 3 and 5 in the unrolled network,
+
+if nargin < 3, t = 1; end
+if nargin < 4, add_ev = 0; end
+
+marginal = marginal_nodes(engine.unrolled_engine, nodes + (t-1)*engine.ss, add_ev);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/pearl_unrolled_dbn_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,39 @@
+function engine = pearl_unrolled_dbn_inf_engine(bnet, varargin)
+% LOOPY_DBN_INF_ENGINE Loopy Pearl version of forwards-backwards
+% engine = loopy_unrolld_dbn_inf_engine(bnet, ...)
+%
+% Optional arguments
+% 'max_iter' - specifies the max num. forward-backward passes to perform PER SLICE [2]
+% 'tol' - as in loopy_pearl [1e-3]
+% 'momentum' - as in loopy_pearl [0]
+% protocol - tree or parallel [parallel]
+% filename - as in pearl [ '' ]
+
+max_iter_per_slice = 2;
+tol = 1e-3;
+momentum = 0;
+protocol = 'parallel';
+filename = '';
+
+args = varargin;
+for i=1:2:length(args)
+  switch args{i},
+   case 'max_iter', max_iter_per_slice = args{i+1};
+   case 'tol', tol = args{i+1};
+   case 'momentum', momentum = args{i+1};
+   case 'protocol', protocol = args{i+1};
+   case 'filename', filename = args{i+1};
+  end
+end
+
+engine.filename = filename;
+engine.max_iter_per_slice = max_iter_per_slice;
+engine.tol = tol;
+engine.momentum = momentum;
+engine.unrolled_engine = [];
+engine.T = -1;
+engine.ss = length(bnet.intra);
+engine.protocol = protocol;
+
+engine = class(engine, 'pearl_unrolled_dbn_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@pearl_unrolled_dbn_inf_engine/update_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function engine = update_engine(engine, newCPDs) 
+% UPDATE_ENGINE Update the engine to take into account the new parameters (pearl_unrolled_dbn)
+% engine = update_engine(engine, newCPDs)
+
+engine.inf_engine = update_engine(engine.inf_engine, newCPDs);
+engine.unrolled_engine = update_engine(engine.unrolled_engine, newCPDs);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/enter_evidence.m/1.1.1.1/Wed Feb 19 09:52:12 2003//
+/marginal_family.m/1.1.1.1/Wed Feb 19 09:52:12 2003//
+/marginal_nodes.m/1.1.1.1/Wed Feb 19 09:52:12 2003//
+/stable_ho_inf_engine.m/1.1.1.1/Fri Mar 14 09:45:34 2003//
+/test_ho_inf_enginge.m/1.1.1.1/Wed Feb 19 09:52:12 2003//
+/update_engine.m/1.1.1.1/Wed Feb 19 09:52:12 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,43 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (jtree_unrolled_dbn)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+% 
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product instead of sum-product [0]
+% filter   - if 1, does filtering (not supported), else smoothing [0]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+maximize = 0;
+filter = 0;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1}; 
+     case 'filter',  filter = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+if filter
+  error('jtree_unrolled_dbn does not support filtering')
+end
+
+if size(evidence,2) ~= engine.nslices
+  error(['engine was created assuming there are ' num2str(engine.nslices) ...
+	 ' slices, but evidence has ' num2str(size(evidence,2))])
+end
+
+[engine.unrolled_engine, loglik] = enter_evidence(engine.unrolled_engine, evidence, 'maximize', maximize);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function marginal = marginal_family(engine, i, t, add_ev)
+% MARGINAL_FAMILY Compute the marginal on the specified family (jtree_unrolled_dbn)
+% marginal = marginal_family(engine, i, t)
+
+if nargin < 3, t = 1; end
+if nargin < 4, add_ev = 0; end
+assert(~add_ev);
+
+%marginal = marginal_family(engine.unrolled_engine, i + (t-1)*engine.ss, add_ev);
+marginal = marginal_family(engine.unrolled_engine, i + (t-1)*engine.ss);
+              
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function marginal = marginal_nodes(engine, nodes, t, add_ev)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (loopy_unrolled_dbn)
+% marginal = marginal_nodes(engine, nodes, t)
+%
+% 't' specifies the time slice of the earliest node in 'nodes'.
+% 'nodes' must occur in some clique.
+%
+% Example:
+% Consider a DBN with 2 nodes per slice.
+% Then t=2, nodes=[1 3] refers to node 1 in slice 2 and node 1 in slice 3,
+% i.e., nodes 3 and 5 in the unrolled network,
+
+if nargin < 3, t = 1; end
+if nargin < 4, add_ev = 0; end
+
+marginal = marginal_nodes(engine.unrolled_engine, nodes + (t-1)*engine.ss, add_ev);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/stable_ho_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,67 @@
+function engine = dv_unrolled_dbn_inf_engine(bnet, T, varargin)
+% JTREE_UNROLLED_DBN_INF_ENGINE Unroll the DBN for T time-slices and apply jtree to the resulting static net
+% engine = jtree_unrolled_dbn_inf_engine(bnet, T, ...)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% useC      - 1 means use jtree_C_inf_engine instead of jtree_inf_engine [0]
+% constrained - 1 means we constrain ourselves to eliminate slice t before t+1 [1]
+%
+% e.g., engine = jtree_unrolled_inf_engine(bnet, 'useC', 1);
+
+% set default params
+N = length(bnet.intra);
+useC = 0;
+constrained = 1;
+
+if nargin >= 3
+  args = varargin;
+  nargs = length(args);
+  if isstr(args{1})
+    for i=1:2:nargs
+      switch args{i},
+       case 'useC',   useC = args{i+1};
+       case 'constrained',  constrained = args{i+1};
+       otherwise,  
+	error(['invalid argument name ' args{i}]);       
+      end
+    end
+  else
+    error(['invalid argument name ' args{1}]);       
+  end
+end
+
+bnet2 = hodbn_to_bnet(bnet, T);
+ss = length(bnet.intra);
+engine.ss = ss;
+
+% If constrained_order = 1 we constrain ourselves to eliminate slice t before t+1.
+% This prevents cliques containing nodes from far-apart time-slices.
+if constrained
+  stages = num2cell(unroll_set(1:ss, ss, T), 1);
+else
+  stages = { 1:length(bnet2.dag) };
+end
+if useC
+  %jengine = jtree_C_inf_engine(bnet2, 'stages', stages);
+  %function is not implemented
+  assert(0)
+else
+  jengine = stab_cond_gauss_inf_engine(bnet2);
+end
+
+engine.unrolled_engine = jengine;
+% we don't inherit from jtree_inf_engine, because that would only store bnet2,
+% and we would lose access to the DBN-specific fields like intra/inter
+
+engine.nslices = T;
+engine = class(engine, 'stable_ho_inf_engine', inf_engine(bnet));
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/test_ho_inf_enginge.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,87 @@
+function [engine,engine2] = test_ho_inf_enginge(order,T)
+
+assert(order >= 1)
+% Model a SISO system, i. e. all node are one-dimensional
+% The nodes are numbered as follows
+% u(t) = 1 input
+% y(t) = 2 model output
+% z(t) = 3 noise
+% q(t) = 4 observed output = noise + model output
+
+ns = [1 1 1 1];
+
+% Model a linear system, i.e. there are no discrete nodes
+dn = [];
+
+% Modeling of connections within a time slice
+intra = zeros(4);
+intra(2,4) = 1; % Connection y(t) -> q(t)
+intra(3,4) = 1; % Connection z(t) -> q(t)
+
+% Connections to the next time slice
+inter = zeros(4,4,order);
+inter(1,2,1) = 1; % u(t) -> y(t+1);
+inter(2,2,1) = 1; %y(t) -> y(t+1);
+inter(3,3,1) = 1; %z(t) -> z(t+1);
+
+if order >= 2
+    inter(1,2,2) = 1; % u(t) -> y(t+2);
+    inter(2,2,2) = 1; % y(t) -> y(t+2);
+end
+
+for i = 3: order
+    inter(:,:,i) = inter(:,:,i-1); %u(t) -> y(t+i) y(t) -> y(t) +i
+end;
+
+
+% Compution of a higer order Markov Model
+bnet = mk_higher_order_dbn(intra,inter,ns,'discrete',dn);
+bnet2 = mk_dbn(intra,inter(:,:,1),ns,'discrete',dn)
+
+
+%Calculation of the number of nodes with different parameters
+%There is one input and one output nodes  2
+%There are two different disturbance node 2
+%There are order +1 nodes for y           1 + order
+numOfNodes = 5 + order; 
+
+% First input node
+bnet.CPD{1} = gaussian_CPD(bnet,1,'mean',0);
+bnet2.CPD{1} = gaussian_CPD(bnet,1,'mean',0);
+% Modeled output
+bnet.CPD{2} = gaussian_CPD(bnet,2,'mean',0);
+bnet2.CPD{2} = gaussian_CPD(bnet,2,'mean',0);
+%Disturbance
+bnet.CPD{3} = gaussian_CPD(bnet,3,'mean',0);
+bnet2.CPD{3} = gaussian_CPD(bnet,3,'mean',0);
+
+%Qutput
+bnet.CPD{4} = gaussian_CPD(bnet,4,'mean',0);
+bnet2.CPD{4} = gaussian_CPD(bnet,4,'mean',0);
+
+
+%Output node in the second time-slice
+%Remember that node number 6 is an example for 
+%the fifth equivalence class
+bnet.CPD{5} = gaussian_CPD(bnet,6,'mean',0);
+bnet2.CPD{5} = gaussian_CPD(bnet,6,'mean',0);
+
+%Disturbance node in the second time slice
+bnet.CPD{6} = gaussian_CPD(bnet,7,'mean',0);
+bnet2.CPD{6} = gaussian_CPD(bnet,7,'mean',0);
+
+% Modeling of the remaining nodes for y
+for i = 7:numOfNodes
+    bnet.CPD{i} = gaussian_CPD(bnet,(i - 6)*4 + 7,'mean',0);
+end
+
+% Generation of the inference engine
+engine = dv_unrolled_dbn_inf_engine(bnet,T);
+engine2 = jtree_unrolled_dbn_inf_engine(bnet,T);
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/@stable_ho_inf_engine/update_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function engine = update_engine(engine, newCPDs)
+% UPDATE_ENGINE Update the engine to take into account the new parameters (jtree_unrolled_dbn)
+% engine = update_engine(engine, newCPDs)
+
+engine.inf_engine = update_engine(engine.inf_engine, newCPDs);
+engine.unrolled_engine = update_engine(engine.unrolled_engine, newCPDs);
+                                                            
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/dummy/1.1.1.1/Sat Jan 18 22:22:28 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+A D/@bk_ff_hmm_inf_engine////
+A D/@bk_inf_engine////
+A D/@cbk_inf_engine////
+A D/@ff_inf_engine////
+A D/@frontier_inf_engine////
+A D/@hmm_inf_engine////
+A D/@jtree_dbn_inf_engine////
+A D/@jtree_unrolled_dbn_inf_engine////
+A D/@kalman_inf_engine////
+A D/@pearl_dbn_inf_engine////
+A D/@pearl_unrolled_dbn_inf_engine////
+A D/@stable_ho_inf_engine////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/dynamic
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/dynamic/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@filter_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/bnet_from_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/filter_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@filter_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/online/@filter_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@filter_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@filter_engine/bnet_from_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function bnet = bnet_from_engine(engine)
+% BNET_FROM_ENGINE Return the bnet structure stored inside the engine (smoother_engine)
+% bnet = bnet_from_engine(engine)
+
+bnet = bnet_from_engine(engine.tbn_engine);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@filter_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+function [engine, LL] = enter_evidence(engine, ev, t)
+% ENTER_EVIDENCE Call the online filter
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value (scalar or column vector)
+
+engine.old_f = engine.f;
+if t==1
+  [engine.f, LL] = fwd1(engine.tbn_engine, ev, 1);
+else
+  [engine.f, LL] = fwd(engine.tbn_engine, engine.old_f, ev, t);
+end
+engine.b = backT(engine.tbn_engine, engine.f, t);
+engine.t = t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@filter_engine/filter_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function engine = filter_engine(tbn_engine)
+% FILTER_ENGINE Create an engine which does online filtering
+% function engine = filter_engine(tbn_engine)
+
+engine.tbn_engine = tbn_engine;
+engine.f = [];  % space to store filtered message
+engine.old_f = [];
+engine.b = []; % space to store smoothed message
+engine.t = [];
+engine = class(engine, 'filter_engine');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@filter_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function marginal = marginal_family(engine, i, t, add_ev)
+% MARGINAL_FAMILY Compute the joint distribution on a set of family (filter_engine)
+% function marginal = marginal_family(engine, i, t, add_ev)
+
+if nargin < 4, add_ev = 0; end
+
+if t ~= engine.t
+  error('mixed up time stamps')
+end
+
+marginal = marginal_family(engine.tbn_engine, engine.b, i, t, add_ev);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@filter_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function marginal = marginal_nodes(engine, nodes, t, add_ev)
+% MARGINAL_NODES Compute the joint distribution on a set of nodes (filter_engine)
+% function marginal = marginal_nodes(engine, nodes, t, add_ev)
+
+if nargin < 4, add_ev = 0; end
+
+if t ~= engine.t
+  error('mixed up time stamps')
+end
+marginal = marginal_nodes(engine.tbn_engine, engine.b, nodes, t, add_ev);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+/back.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/backT.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/fwd.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/fwd1.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/hmm_2TBN_inf_engine.m/1.1.1.1/Thu Nov 14 20:03:50 2002//
+/marginal_family.m/1.1.1.1/Thu Nov 14 20:05:36 2002//
+/marginal_nodes.m/1.1.1.1/Thu Nov 14 20:02:46 2002//
+/update_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/back.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function b = back(engine, bfuture, f, t)
+
+if f.t ~= t
+  error('mixed up time stamps')
+end
+
+b.t = t;
+b.obslik = f.obslik;
+bb_future = bfuture.beta .* bfuture.obslik;
+if engine.maximize
+  B = repmat(bb_future(:)', length(bfuture.beta), 1);
+  b.beta = normalise(max(engine.transprob .* B, [], 2));
+else
+  b.beta = normalise((engine.transprob * bb_future));
+end
+b.gamma = normalise(f.alpha .* b.beta);
+if t > 1
+  bb_t = b.beta .* b.obslik;
+  b.xi = normalise((engine.transprob .* (f.past_alpha * bb_t'))); % t-1,t
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/backT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function b = backT(engine, f, t)
+
+b.t = t;
+b.obslik = f.obslik;
+Q = length(f.alpha);
+b.beta = ones(Q,1);
+b.gamma = f.alpha;
+if t > 1
+  bb_t = b.obslik;
+  b.xi = normalise((engine.transprob .* (f.past_alpha * bb_t'))); % T-1,T
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/fwd.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function [f, logscale] = fwd(engine, fpast, ev, t)
+% Forwards pass.
+
+f.obslik = mk_hmm_obs_lik_vec(engine, ev);
+transmat = engine.transprob;
+f.past_alpha = fpast.alpha;
+if engine.maximize
+  Q = length(fpast.alpha);
+  A = repmat(fpast.alpha, [1 Q]);
+  m = max(transmat .* A, [], 1);
+  [f.alpha, scale] = normalise(m(:) .* f.obslik);
+else
+  [f.alpha, scale] = normalise((transmat' * fpast.alpha) .* f.obslik);
+end
+logscale = log(scale);
+%f.xi = normalise((fpast.alpha * obslik') .* transmat); % t-1,t
+f.t = t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/fwd1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function [f, logscale] = fwd1(engine, ev, t)
+% Forwards pass for slice 1.
+
+if t ~= 1
+  error('mixed up time stamps')
+end
+prior = engine.startprob(:);
+f.obslik = mk_hmm_obs_lik_vec(engine, ev);
+[f.alpha, lik] = normalise(prior .* f.obslik);
+logscale = log(lik);
+f.t = t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/hmm_2TBN_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,86 @@
+function engine = hmm_2TBN_inf_engine(bnet, varargin)
+% HMM_2TBN_INF_ENGINE Inference engine for DBNs which uses the forwards-backwards algorithm.
+% engine = hmm_2TBN_inf_engine(bnet, ...)
+%
+% The DBN is converted to an HMM with a single meganode, but the observed nodes remain factored.
+% This can be faster than jtree if the num. hidden nodes is low, because of lower constant factors.
+%
+% All hidden nodes must be discrete.
+% All observed nodes are assumed to be leaves.
+% The parents of each observed leaf are assumed to be a subset of the hidden nodes within the same slice.
+% The only exception is if bnet is an AR-HMM, where the parents are assumed to be self in the
+% previous slice (continuous), plus all the discrete nodes in the current slice.
+
+
+%% Optional arguments
+%% ndx_type - 'B', 'D', or 'SD', used in marginal_family [ 'SD' ]
+
+ndx_type = 'SD';
+ss = bnet.nnodes_per_slice;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     %case 'ndx_type', ndx_type = args{i+1};
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+% Stuff to do with speeding up marginal_family
+%engine.ndx_type = ndx_type;
+
+[int, engine.persist, engine.transient] = compute_interface_nodes(bnet.intra, bnet.inter);
+engine.persist_bitv = zeros(1, ss);
+engine.persist_bitv(engine.persist) = 1;
+
+
+ns = bnet.node_sizes(:);
+ns(bnet.observed) = 1;
+ns(bnet.observed+ss) = 1;
+engine.eff_node_sizes = ns;
+
+% for n=1:ss
+%   dom = 1:(2*ss); % domain of xi(:,:,1)
+%   fam = family(bnet.dag, n+ss);
+%   engine.marg_fam2_ndx_id(n) = add_ndx(dom, fam, ns, ndx_type);
+ 
+%   dom = 1:ss; % domain of gamma(:,:,1)
+%   fam = family(bnet.dag, n);
+%   engine.marg_fam1_ndx_id(n) = add_ndx(dom, fam, ns, ndx_type);
+
+%   engine.marg_singleton_ndx_id(n) = add_ndx(dom, n, ns, ndx_type);
+% end
+
+for o=bnet.observed(:)'
+  %if bnet.equiv_class(o,1) ~= bnet.equiv_class(o,2)
+  %  error(['observed node ' num2str(o) ' is not tied'])
+  %end
+  cs = children(bnet.dag, o);
+  if ~isempty(cs)
+    error(['observed node ' num2str(o) ' is not allowed children'])
+  end
+end
+
+[engine.startprob, engine.transprob, engine.obsprob] = dbn_to_hmm(bnet);
+
+% This is where we will store the results between enter_evidence and marginal_nodes
+engine.one_slice_marginal = [];
+engine.two_slice_marginal = [];
+
+ss = length(bnet.intra);
+engine.maximize = [];
+engine.evidence = [];
+engine.node_sizes = [];
+
+% avoid the need to do bnet_from_engine, which is slow
+engine.slice_size = ss;
+engine.parents = bnet.parents;
+
+engine.bel = [];
+engine = class(engine, 'hmm_2TBN_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,35 @@
+function marginal = marginal_family(engine, b, i, t, add_ev)
+% MARGINAL_FAMILY Compute the marginal on the specified family (hmm_2TBN)
+% marginal = marginal_family(engine, b, i, t, add_ev)
+
+ns = engine.eff_node_sizes(:);
+ss = engine.slice_size;
+
+if t==1 % | ~engine.persist_bitv(i)
+  bigT = b.gamma;
+  ps = engine.parents{i};
+  dom = [ps i];
+  %id = engine.marg_fam1_ndx_id(i);
+  bigdom = 1:ss;
+  bigsz = ns(bigdom);
+  bigdom = bigdom + (t-1)*ss;
+else % some parents are in previous slice
+  bigT = b.xi; % (t-1,t)
+  ps = engine.parents{i+ss};
+  dom = [ps i+ss] + (t-2)*ss;
+  %id = engine.marg_fam2_ndx_id(i);
+  bigdom = 1:(2*ss); % domain of xi(:,:,t)
+  bigsz = ns(bigdom);
+  bigdom = bigdom + (t-2)*ss;
+end
+marginal.domain = dom;
+
+%ndx = get_ndx(id, engine.ndx_type);
+%marginal.T = marg_table_ndx(bigT, engine.maximize, ndx, engine.ndx_type);
+%global SD_NDX
+%ndx = SD_NDX{id};
+%marginal.T = marg_table_ndxSD(bigT, engine.maximize, ndx);
+marginal.T = marg_table(bigT, bigdom, bigsz, dom, engine.maximize); 
+
+assert(~add_ev);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,27 @@
+function marginal = marginal_nodes(engine, b, nodes, t, add_ev)
+% MARGINAL_NODES Compute the marginal on the specified nodes (hmm_2TBN)
+% marginal = marginal_nodes(engine, b, nodes, t, add_ev)
+%
+% nodes must be a singleton set 
+
+assert(length(nodes)==1)
+ss = engine.slice_size;
+
+i = nodes(1);
+bigT = b.gamma;
+dom = i + (t-1)*ss;
+
+%id = engine.marg_singleton_ndx_id(i);
+%global SD_NDX
+%ndx = SD_NDX{id};
+%marginal.T = marg_table_ndxSD(bigT, engine.maximize, ndx);
+
+ns = engine.eff_node_sizes(:);
+bigdom = 1:ss;
+marginal.T = marg_table(bigT, bigdom + (t-1)*ss, ns(bigdom), dom, engine.maximize);
+
+marginal.domain = dom;
+assert(~add_ev);
+%if add_ev
+%  marginal = add_ev_to_dmarginal(marginal, engine.evidence, engine.node_sizes);
+%end    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/mk_hmm_obs_lik_vec.m/1.1.1.1/Sun May  4 21:47:44 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/private/mk_hmm_obs_lik_vec.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,53 @@
+function obslik = mk_hmm_obs_lik_vec(engine, evidence)
+
+% P(o1,o2| h) = P(o1|h) * P(o2|h) where h = Q1,Q2,...
+
+bnet = bnet_from_engine(engine);
+ss = length(bnet.intra);
+onodes = bnet.observed;
+hnodes = mysetdiff(1:ss, onodes);
+ns = bnet.node_sizes(:);
+ns(onodes) = 1;
+
+Q = length(engine.startprob);
+obslik = ones(Q, 1);
+
+for i=1:length(onodes)
+  o = onodes(i);
+  %data = cell2num(evidence(o,1));
+  data = evidence{o,1};
+  if myismember(o, bnet.dnodes)
+    %obslik_i = eval_pdf_cond_multinomial(data, engine.obsprob{i}.CPT);
+    obslik_i = multinomial_prob(data, engine.obsprob{i}.CPT);
+  else
+    if bnet.auto_regressive(o)
+      error('can''t handle AR nodes')
+    end
+    %% calling mk_ghmm_obs_lik, which calls gaussian_prob, is slow, so we inline it
+    %% and use the pre-computed  inverse matrix
+    %obslik_i = mk_ghmm_obs_lik(data, engine.obsprob{i}.mu, engine.obsprob{i}.Sigma);
+    x = data(:);
+    m = engine.obsprob{i}.mu;
+    Qi = size(m, 2);
+    obslik_i = size(Qi, 1);
+    invC = engine.obsprob{i}.inv_Sigma;
+    denom = engine.obsprob{i}.denom;
+    for j=1:Qi
+      numer = exp(-0.5 * (x-m(:,j))' * invC(:,:,j) * (x-m(:,j)));
+      obslik_i(j) = numer / denom(j);
+    end
+  end
+  % convert P(o|ps) into P(o|h) by multiplying onto a (h,o) potential of all 1s
+  ps = bnet.parents{o};
+  dom = [ps o];
+  obspot_i = dpot(dom, ns(dom), obslik_i);
+  dom = [hnodes o];
+  obspot = dpot(dom, ns(dom));
+  obspot = multiply_by_pot(obspot, obspot_i);
+  % compute p(oi|h) * p(oj|h)
+  S = struct(obspot);
+  obslik = obslik .* S.T(:);
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@hmm_2TBN_inf_engine/update_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function engine = update_engine(engine, newCPDs)
+% UPDATE_ENGINE Update the engine to take into account the new parameters (hmm)
+% engine = update_engine(engine, newCPDs)
+
+%engine.inf_engine.bnet.CPD = newCPDs;
+engine.inf_engine = update_engine(engine.inf_engine, newCPDs);
+[engine.startprob, engine.transprob, engine.obsprob] = dbn_to_hmm(bnet_from_engine(engine));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+/back.m/1.1.1.1/Mon Jun 17 23:34:12 2002//
+/back1.m/1.1.1.1/Mon Jun 17 23:34:26 2002//
+/back1_mpe.m/1.1.1.1/Mon Jun 17 23:49:40 2002//
+/backT.m/1.1.1.1/Mon Jun 17 23:34:20 2002//
+/backT_mpe.m/1.1.1.1/Mon Jun 17 23:38:56 2002//
+/back_mpe.m/1.1.1.1/Sun Jul 21 00:32:52 2002//
+/fwd.m/1.1.1.1/Mon Jun 17 23:46:06 2002//
+/fwd1.m/1.1.1.1/Mon Jun 17 23:46:20 2002//
+/jtree_2TBN_inf_engine.m/1.1.1.1/Thu Nov 14 16:31:58 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/set_fields.m/1.1.1.1/Sun Jul 21 01:25:30 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/jtree_2TBN_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/Old/jtree_2TBN_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,116 @@
+function engine = jtree_2TBN_inf_engine(bnet, varargin)
+% JTREE_ONLINE_INF_ENGINE Online Junction tree inference algorithm for DBNs.
+% engine = jtree_online_inf_engine(bnet, ...)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% clusters - specifies variables that must be grouped in the 1.5 slice DBN
+% maximize - 1 means do max-product, 0 means sum-product [0]
+%
+% The same nodes must be observed in every slice.
+
+ss = length(bnet.intra);
+clusters = {};
+engine.maximize = 0;
+
+args = varargin;
+nargs = length(args);
+for i=1:2:length(args)
+  switch args{i},
+   case 'clusters', clusters = args{i+1};
+   case 'maximize', engine.maximize = args{i+1};
+   otherwise, error(['unrecognized argument ' args{i}])
+  end
+end
+
+engine.evidence = [];
+engine.node_sizes = [];
+
+%int = compute_interface_nodes(bnet.intra, bnet.inter);
+int = [];
+
+if 1
+% include nodes with any outgoing arcs
+for u=1:ss
+  if any(bnet.inter(u,:))
+    int = [int u];
+  end
+end
+end
+
+if 0
+% include nodes with any incoming  arcs
+incoming = [];
+for u=1:ss
+  if any(bnet.inter(:,u))
+    int = [int u];
+    incoming = [incoming u];
+  end
+end
+% include nodes which are parents of nodes with incoming
+for u=1:ss
+  cs = children(bnet.intra, u);
+  if ~isempty(cs) & mysubset(cs, incoming)
+    int = [int u];
+  end
+end
+int = unique(int);
+end % if
+
+int
+engine.interface = int;
+engine.nonint = mysetdiff(1:ss, int);
+
+onodes = bnet.observed;
+
+% Create a "1.5 slice" jtree, containing the interface nodes of slice 1
+% and all the nodes of slice 2
+% To keep the node numbering the same, we simply disconnect the non-interface nodes
+% from slice 1, and set their size to 1.
+% We do this to speed things up, and so that the likelihood is computed correctly - we do not need to do
+% this if we just want to compute marginals (i.e., we can include nodes whose potentials will
+% be left as all 1s).
+intra15 = bnet.intra;
+for i=engine.nonint(:)'
+  intra15(:,i) = 0;
+  intra15(i,:) = 0;
+end
+dag15 = [intra15      bnet.inter;
+	 zeros(ss)    bnet.intra];
+ns = bnet.node_sizes(:);
+%ns(engine.nonint) = 1; % disconnected nodes get size 1
+obs_nodes = [onodes(:) onodes(:)+ss];
+bnet15 = mk_bnet(dag15, ns, 'discrete', bnet.dnodes, 'equiv_class', bnet.equiv_class(:), ...
+		 'observed', obs_nodes(:));
+
+% use unconstrained elimination,
+% but force there to be a clique containing both interfaces
+clusters(end+1:end+2) = {int, int+ss};
+engine.jtree_engine = jtree_inf_engine(bnet15, 'clusters', clusters, 'root', int+ss);
+jtree_engine = struct(engine.jtree_engine); % violate object privacy
+
+engine.in_clq = clq_containing_nodes(engine.jtree_engine, int);
+engine.out_clq = clq_containing_nodes(engine.jtree_engine, int+ss);
+engine.clq_ass_to_node = jtree_engine.clq_ass_to_node;
+engine.root = jtree_engine.root_clq;
+
+% Also create an engine just for slice 1
+bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, 'discrete', myintersect(bnet.dnodes,1:ss), ...
+		'equiv_class', bnet.equiv_class(:,1), 'observed', onodes);
+for i=1:max(bnet1.equiv_class)
+  bnet1.CPD{i} = bnet.CPD{i};
+end
+engine.jtree_engine1 = jtree_inf_engine(bnet1, 'clusters', {int}, 'root', int);
+jtree_engine1 = struct(engine.jtree_engine1); % violate object privacy
+engine.int_clq1 = clq_containing_nodes(engine.jtree_engine1, int);
+engine.clq_ass_to_node1 = jtree_engine1.clq_ass_to_node;
+engine.root1 = jtree_engine1.root_clq;
+
+engine.observed = [onodes onodes+ss];
+engine.observed1 = onodes;
+engine.pot_type = determine_pot_type(bnet, onodes);
+engine.slice_size = bnet.nnodes_per_slice;
+
+engine = class(engine, 'jtree_2TBN_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/back.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,27 @@
+function b = back(engine, bfuture, f, t)
+
+if f.t ~= t
+  error('mixed up time stamps')
+end
+if t==1
+  b = back1(engine, bfuture, f, t);
+  return;
+end
+
+bnet = bnet_from_engine(engine);
+ss = bnet.nnodes_per_slice;
+
+int = engine.interface;
+D = engine.in_clq;
+C = engine.out_clq;
+phiD = marginalize_pot(bfuture.clpot{D}, int, engine.maximize);
+phiD = set_domain_pot(phiD, int+ss); % shift to slice 2
+phiC = marginalize_pot(f.clpot{C}, int+ss, engine.maximize);
+ratio = divide_by_pot(phiD, phiC);
+f.clpot{C} = multiply_by_pot(f.clpot{C}, ratio);
+
+[b.clpot, seppot] = distribute_evidence(engine.jtree_engine, f.clpot, f.seppot);
+for c=1:length(b.clpot)
+  [b.clpot{c}, ll(c)] = normalize_pot(b.clpot{c});
+end
+b.t = t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/back1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function b = back1(engine, bfuture, f, t)
+
+if t ~= 1
+  error('mixed up time stamps')
+end
+bnet = bnet_from_engine(engine);
+ss = bnet.nnodes_per_slice;
+
+int = engine.interface;
+D = engine.in_clq; % from J2
+C = engine.int_clq1; % from J1
+phiD = marginalize_pot(bfuture.clpot{D}, int, engine.maximize);
+phiC = marginalize_pot(f.clpot{C}, int, engine.maximize);
+ratio = divide_by_pot(phiD, phiC);
+f.clpot{C} = multiply_by_pot(f.clpot{C}, ratio);
+
+[b.clpot, seppot] = distribute_evidence(engine.jtree_engine1, f.clpot, f.seppot);
+for c=1:length(b.clpot)
+  [b.clpot{c}, ll(c)] = normalize_pot(b.clpot{c});
+end
+b.t = t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/back1_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function [b, mpe] = back1_mpe(engine, bfuture, f, ev1, t)
+
+if t ~= 1
+  error('mixed up time stamps')
+end
+bnet = bnet_from_engine(engine);
+ss = bnet.nnodes_per_slice;
+maximize = 1;
+
+int = engine.interface;
+D = engine.in_clq; % from J2
+C = engine.int_clq1; % from J1
+phiD = marginalize_pot(bfuture.clpot{D}, int, maximize);
+phiC = marginalize_pot(f.clpot{C}, int, maximize);
+ratio = divide_by_pot(phiD, phiC);
+f.clpot{C} = multiply_by_pot(f.clpot{C}, ratio);
+
+[mpe, b.clpot] = find_max_config(engine.jtree_engine1, f.clpot, f.seppot, ev1);
+for c=1:length(b.clpot)
+  [b.clpot{c}, ll(c)] = normalize_pot(b.clpot{c});
+end
+b.t = t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/backT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function b = backT(engine, f, t)
+
+if t==1
+  [b.clpot, seppot] = distribute_evidence(engine.jtree_engine1, f.clpot, f.seppot);
+else
+  [b.clpot, seppot] = distribute_evidence(engine.jtree_engine, f.clpot, f.seppot);
+end
+for c=1:length(b.clpot)
+  [b.clpot{c}, ll(c)] = normalize_pot(b.clpot{c});
+end
+b.t = t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/backT_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function [b, mpe] = backT_mpe(engine, f, ev2, t)
+
+bnet = bnet_from_engine(engine);
+ss = bnet.nnodes_per_slice;
+
+if t==1
+  % ev2 is just the evidence on slice 1
+  [mpe, b.clpot] = find_max_config(engine.jtree_engine1, f.clpot, f.seppot, ev2);
+else
+  [mpe, b.clpot] = find_max_config(engine.jtree_engine, f.clpot, f.seppot, ev2);
+  mpe = mpe((1:ss)+ss); % extract values for slice 2
+end
+for c=1:length(b.clpot)
+  [b.clpot{c}, ll(c)] = normalize_pot(b.clpot{c});
+end
+b.t = t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/back_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+function [b, mpe] = back_mpe(engine, bfuture, f, ev2, t)
+
+if f.t ~= t
+  error('mixed up time stamps')
+end
+if t==1
+  error('should call back1_mpe')
+end
+
+maximize = 1;
+bnet = bnet_from_engine(engine);
+ss = bnet.nnodes_per_slice;
+clear bnet % added by matthiasm to save 
+
+int = engine.interface;
+D = engine.in_clq;
+C = engine.out_clq;
+phiD = marginalize_pot(bfuture.clpot{D}, int, maximize);
+phiD = set_domain_pot(phiD, int+ss); % shift to slice 2
+phiC = marginalize_pot(f.clpot{C}, int+ss, maximize);
+ratio = divide_by_pot(phiD, phiC);
+f.clpot{C} = multiply_by_pot(f.clpot{C}, ratio);
+
+[mpe, b.clpot] = find_max_config(engine.jtree_engine, f.clpot, f.seppot, ev2);
+mpe = mpe((1:ss)+ss); % extract values for slice 2
+for c=1:length(b.clpot)
+  [b.clpot{c}, ll(c)] = normalize_pot(b.clpot{c});
+end
+b.t = t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/fwd.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+function [f, logscale] = fwd(engine, fpast, ev, t)
+% Forwards pass.
+
+bnet = bnet_from_engine(engine);
+ss = bnet.nnodes_per_slice;
+
+ev2 = cell(ss, 2);
+ev2(:,1) = fpast.evidence;
+ev2(:,2) = ev;
+
+CPDpot = cell(1,ss);
+for n=1:ss
+  fam = family(bnet.dag, n, 2);
+  e = bnet.equiv_class(n, 2);
+  CPDpot{n} = convert_to_pot(bnet.CPD{e}, engine.pot_type, fam(:), ev2);
+end       
+clear bnet % inserted by matthias mauch to save memory
+f.evidence = ev;
+f.t = t;
+
+% get prior
+int = engine.interface;
+if fpast.t==1
+  prior = marginalize_pot(fpast.clpot{engine.int_clq1}, int, engine.maximize);
+else
+  prior = marginalize_pot(fpast.clpot{engine.out_clq}, int+ss, engine.maximize);
+  prior = set_domain_pot(prior, int); % shift back to slice 1
+end
+
+pots = [ {prior} CPDpot ];
+slice1 = 1:ss;
+slice2 = slice1 + ss; 
+CPDclqs = engine.clq_ass_to_node(slice2);
+D = engine.in_clq;
+clqs = [D CPDclqs];
+
+[f.clpot, f.seppot] =  init_pot(engine.jtree_engine, clqs, pots, engine.pot_type, engine.observed);
+[f.clpot, f.seppot] = collect_evidence(engine.jtree_engine, f.clpot, f.seppot);
+for c=1:length(f.clpot)
+  [f.clpot{c}, ll(c)] = normalize_pot(f.clpot{c});
+end
+logscale = ll(engine.root);
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/fwd1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function [f, logscale] = fwd1(engine, ev, t)
+% Forwards pass for slice 1.
+
+bnet = bnet_from_engine(engine);
+ss = bnet.nnodes_per_slice;
+
+CPDpot = cell(1,ss);
+for n=1:ss
+  fam = family(bnet.dag, n, 1);
+  e = bnet.equiv_class(n, 1);
+  CPDpot{n} = convert_to_pot(bnet.CPD{e}, engine.pot_type, fam(:), ev);
+end       
+f.t = t;
+f.evidence = ev;
+clear bnet % by matthias to save memory
+% pots = CPDpot;
+slice1 = 1:ss;
+CPDclqs = engine.clq_ass_to_node1(slice1);
+
+[f.clpot, f.seppot] =  init_pot(engine.jtree_engine1, CPDclqs, CPDpot, engine.pot_type, engine.observed1);
+[f.clpot, f.seppot] = collect_evidence(engine.jtree_engine1, f.clpot, f.seppot);
+for c=1:length(f.clpot)
+  [f.clpot{c}, ll(c)] = normalize_pot(f.clpot{c});
+end
+logscale = ll(engine.root1);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/fwdMM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,50 @@
+function f = fwdMM(engine, fpast, ev, t)
+% Forwards pass.
+
+bnet = bnet_from_engine(engine);
+ss = bnet.nnodes_per_slice;
+
+ev2 = cell(ss, 2);
+ev2(:,1) = fpast.evidence;
+ev2(:,2) = ev;
+CPDpot = cell(1,ss);
+for n=1:ss
+  fam = family(bnet.dag, n, 2);
+  e = bnet.equiv_class(n, 2);
+  CPDpot{n} = convert_to_pot(bnet.CPD{e}, engine.pot_type, fam(:), ev2);
+end       
+clear bnet % by matthias mauch to save memory
+
+f.evidence = ev;
+f.t = t;
+
+% get prior
+int = engine.interface;
+if fpast.t==1
+  prior = marginalize_pot(fpast.clpot{engine.int_clq1}, int, engine.maximize);
+else
+  prior = marginalize_pot(fpast.clpot{engine.out_clq}, int+ss, engine.maximize);
+  prior = set_domain_pot(prior, int); % shift back to slice 1
+end
+
+pots = [ {prior} CPDpot ];
+slice1 = 1:ss;
+slice2 = slice1 + ss; 
+CPDclqs = engine.clq_ass_to_node(slice2);
+D = engine.in_clq;
+clqs = [D CPDclqs];
+
+[f.clpot, f.seppot] =  init_pot(engine.jtree_engine, clqs, pots, engine.pot_type, engine.observed);
+[f.clpot, f.seppot] = collect_evidence(engine.jtree_engine, f.clpot, f.seppot);
+for c=1:length(f.clpot)
+  if isa(f.clpot{c}, 'struct')
+     domain = f.clpot{c}.domain;
+     sizes = f.clpot{c}.sizes;
+     T = f.clpot{c}.T;
+     f.clpot{c} = dpot(domain, sizes, T);
+  end
+%   [f.clpot{c}, ll(c)] = normalize_pot(f.clpot{c});
+  f.clpot{c} = normalize_pot(f.clpot{c});
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/jtree_2TBN_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,69 @@
+function engine = jtree_2TBN_inf_engine(bnet, varargin)
+% JTREE_ONLINE_INF_ENGINE Online Junction tree inference algorithm for DBNs.
+% engine = jtree_online_inf_engine(bnet, ...)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% clusters - specifies variables that must be grouped in the 1.5 slice DBN
+%
+% The same nodes must be observed in every slice.
+%
+% This uses the forwards interface of slice t-1 plus all of slice t.
+% By contrast, jtree_dbn uses all of slice t-1 plus the backwards interface of slice t.
+% See my thesis for details.
+
+
+clusters = {};
+
+args = varargin;
+nargs = length(args);
+for i=1:2:length(args)
+  switch args{i},
+   case 'clusters', clusters = args{i+1};
+   otherwise, error(['unrecognized argument ' args{i}])
+  end
+end
+
+engine.maximize = 0;
+engine.evidence = [];
+engine.node_sizes = [];
+
+int = compute_fwd_interface(bnet.intra, bnet.inter);
+engine.interface = int;
+ss = length(bnet.intra);
+engine.nonint = mysetdiff(1:ss, int);
+onodes = bnet.observed;
+
+bnet15 = mk_slice_and_half_dbn(bnet, int);
+
+% use unconstrained elimination,
+% but force there to be a clique containing both interfaces
+clusters(end+1:end+2) = {int, int+ss};
+engine.jtree_engine = jtree_inf_engine(bnet15, 'clusters', clusters, 'root', int+ss);
+jtree_engine = struct(engine.jtree_engine); % violate object privacy
+
+engine.in_clq = clq_containing_nodes(engine.jtree_engine, int);
+engine.out_clq = clq_containing_nodes(engine.jtree_engine, int+ss);
+engine.clq_ass_to_node = jtree_engine.clq_ass_to_node;
+engine.root = jtree_engine.root_clq;
+
+% Also create an engine just for slice 1
+bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, 'discrete', myintersect(bnet.dnodes,1:ss), ...
+		'equiv_class', bnet.equiv_class(:,1), 'observed', onodes);
+for i=1:max(bnet1.equiv_class)
+  bnet1.CPD{i} = bnet.CPD{i};
+end
+engine.jtree_engine1 = jtree_inf_engine(bnet1, 'clusters', {int}, 'root', int);
+jtree_engine1 = struct(engine.jtree_engine1); % violate object privacy
+engine.int_clq1 = clq_containing_nodes(engine.jtree_engine1, int);
+engine.clq_ass_to_node1 = jtree_engine1.clq_ass_to_node;
+engine.root1 = jtree_engine1.root_clq;
+
+engine.observed = [onodes onodes+ss];
+engine.observed1 = onodes;
+engine.pot_type = determine_pot_type(bnet, onodes);
+engine.slice_size = bnet.nnodes_per_slice;
+
+engine = class(engine, 'jtree_2TBN_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function m = marginal_family(engine, b, i, t, add_ev)
+% MARGINAL_FAMILY Compute the marginal on the specified family (jtree_2TBN)
+% marginal = marginal_family(engine, b, i, t, add_ev)
+
+bnet = bnet_from_engine(engine);
+if t==1
+  m = marginal_nodes(engine, b, family(bnet.dag, i), t, add_ev, 1);
+else
+  ss = length(bnet.intra);
+  fam = family(bnet.dag, i+ss);
+  m = marginal_nodes(engine, b, fam, t, add_ev, 1);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function marginal = marginal_nodes(engine, b, nodes, t, add_ev, is_fam)
+% function marginal = marginal_nodes(engine, b, nodes, t, add_ev, is_fam) (jtree_2TBN)
+
+if nargin < 6, is_fam = 0; end
+ss = engine.slice_size;
+
+if ~is_fam & (t > 1) & all(nodes<=ss)
+  nodes = nodes + ss;
+end
+
+if t==1
+  c = clq_containing_nodes(engine.jtree_engine1, nodes, is_fam);
+else
+  c = clq_containing_nodes(engine.jtree_engine, nodes, is_fam);
+end
+if c == -1
+  error(['no clique contains ' nodes])
+end
+bigpot = b.clpot{c};
+pot = marginalize_pot(bigpot, nodes, engine.maximize);
+marginal = pot_to_marginal(pot);
+
+% we convert the domain to the unrolled numbering system
+% so that add_ev_to_dmarginal (maybe called in update_ess) extracts the right evidence.
+if t > 1
+  marginal.domain = nodes+(t-2)*engine.slice_size;
+end
+assert(~add_ev);
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_2TBN_inf_engine/set_fields.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function engine = set_fields(engine, varargin)
+% SET_FIELDS Set the fields for a generic engine
+% engine = set_fields(engine, name/value pairs)
+%
+% e.g., engine = set_fields(engine, 'maximize', 1)
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'maximize',
+     engine.maximize = args{i+1};
+     engine.jtree_engine = set_fields(engine.jtree_engine, 'maximize', args{i+1});
+     engine.jtree_engine1 = set_fields(engine.jtree_engine1, 'maximize', args{i+1});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+/back.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/back1.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/backT.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/fwd.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/fwd1.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/jtree_sparse_2TBN_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/back.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,27 @@
+function b = back(engine, bfuture, f, t)
+
+if f.t ~= t
+  error('mixed up time stamps')
+end
+if t==1
+  b = back1(engine, bfuture, f, t);
+  return;
+end
+
+bnet = bnet_from_engine(engine);
+ss = bnet.nnodes_per_slice;
+
+int = engine.interface;
+D = engine.in_clq;
+C = engine.out_clq;
+phiD = marginalize_pot(bfuture.clpot{D}, int, engine.maximize);
+phiD = set_domain_pot(phiD, int+ss); % shift to slice 2
+phiC = marginalize_pot(f.clpot{C}, int+ss, engine.maximize);
+ratio = divide_by_pot(phiD, phiC);
+f.clpot{C} = multiply_by_pot(f.clpot{C}, ratio);
+
+[b.clpot, seppot] = distribute_evidence(engine.jtree_engine, f.clpot, f.seppot);
+for c=1:length(b.clpot)
+  [b.clpot{c}, ll(c)] = normalize_pot(b.clpot{c});
+end
+b.t = t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/back1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function b = back1(engine, bfuture, f, t)
+
+if t ~= 1
+  error('mixed up time stamps')
+end
+bnet = bnet_from_engine(engine);
+ss = bnet.nnodes_per_slice;
+
+int = engine.interface;
+D = engine.in_clq; % from J2
+C = engine.int_clq1; % from J1
+phiD = marginalize_pot(bfuture.clpot{D}, int, engine.maximize);
+phiC = marginalize_pot(f.clpot{C}, int, engine.maximize);
+ratio = divide_by_pot(phiD, phiC);
+f.clpot{C} = multiply_by_pot(f.clpot{C}, ratio);
+
+[b.clpot, seppot] = distribute_evidence(engine.jtree_engine1, f.clpot, f.seppot);
+for c=1:length(b.clpot)
+  [b.clpot{c}, ll(c)] = normalize_pot(b.clpot{c});
+end
+b.t = t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/backT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function b = backT(engine, f, t)
+
+if t==1
+  [b.clpot, seppot] = distribute_evidence(engine.jtree_engine1, f.clpot, f.seppot);
+else
+  [b.clpot, seppot] = distribute_evidence(engine.jtree_engine, f.clpot, f.seppot);
+end
+for c=1:length(b.clpot)
+  [b.clpot{c}, ll(c)] = normalize_pot(b.clpot{c});
+end
+b.t = t;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (jtree_online)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product instead of sum-product [0]
+%
+
+engine.maximize = 0;
+args = varargin;
+for i=1:2:length(args)
+  switch args{i}
+   case 'maximize', engine.maximize = args{i+1};
+   otherwise, error(['unrecognized argument ' args{i}])
+  end
+end
+
+[engine, loglik] = offline_smoother(engine, evidence);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/fwd.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,49 @@
+function [f, logscale] = fwd(engine, fpast, ev, t)
+% Forwards pass.
+
+bnet = bnet_from_engine(engine);
+ss = bnet.nnodes_per_slice;
+
+ev2 = cell(ss, 2);
+ev2(:,1) = fpast.evidence;
+ev2(:,2) = ev;
+CPDpot = cell(1,ss);
+for n=1:ss
+  fam = family(bnet.dag, n, 2);
+  e = bnet.equiv_class(n, 2);
+  CPDpot{n} = convert_to_pot(bnet.CPD{e}, engine.pot_type, fam(:), ev2);
+end       
+clear bnet % by matthias mauch to save memory
+
+f.evidence = ev;
+f.t = t;
+
+% get prior
+int = engine.interface;
+if fpast.t==1
+  prior = marginalize_pot(fpast.clpot{engine.int_clq1}, int, engine.maximize);
+else
+  prior = marginalize_pot(fpast.clpot{engine.out_clq}, int+ss, engine.maximize);
+  prior = set_domain_pot(prior, int); % shift back to slice 1
+end
+
+pots = [ {prior} CPDpot ];
+slice1 = 1:ss;
+slice2 = slice1 + ss; 
+CPDclqs = engine.clq_ass_to_node(slice2);
+D = engine.in_clq;
+clqs = [D CPDclqs];
+
+[f.clpot, f.seppot] =  init_pot(engine.jtree_engine, clqs, pots, engine.pot_type, engine.observed);
+[f.clpot, f.seppot] = collect_evidence(engine.jtree_engine, f.clpot, f.seppot);
+for c=1:length(f.clpot)
+  if isa(f.clpot{c}, 'struct')
+     domain = f.clpot{c}.domain;
+     sizes = f.clpot{c}.sizes;
+     T = f.clpot{c}.T;
+     f.clpot{c} = dpot(domain, sizes, T);
+  end
+  [f.clpot{c}, ll(c)] = normalize_pot(f.clpot{c});
+end
+logscale = ll(engine.root);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/fwd1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function [f, logscale] = fwd1(engine, ev, t)
+% Forwards pass for slice 1.
+
+bnet = bnet_from_engine(engine);
+ss = bnet.nnodes_per_slice;
+
+CPDpot = cell(1,ss);
+for n=1:ss
+  fam = family(bnet.dag, n, 1);
+  e = bnet.equiv_class(n, 1);
+  CPDpot{n} = convert_to_pot(bnet.CPD{e}, engine.pot_type, fam(:), ev);
+end       
+f.evidence = ev;
+f.t = t;
+
+pots = CPDpot;
+slice1 = 1:ss;
+CPDclqs = engine.clq_ass_to_node1(slice1);
+
+[f.clpot, f.seppot] =  init_pot(engine.jtree_engine1, CPDclqs, CPDpot, engine.pot_type, engine.observed1);
+[f.clpot, f.seppot] = collect_evidence(engine.jtree_engine1, f.clpot, f.seppot);
+for c=1:length(f.clpot)
+  if isa(f.clpot{c}, 'struct')
+     domain = f.clpot{c}.domain;
+     sizes = f.clpot{c}.sizes;
+     T = f.clpot{c}.T;
+     f.clpot{c} = dpot(domain, sizes, T);
+  end
+  [f.clpot{c}, ll(c)] = normalize_pot(f.clpot{c});
+end
+logscale = ll(engine.root1);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/jtree_sparse_2TBN_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,95 @@
+function engine = jtree_sparse_2TBN_inf_engine(bnet, varargin)
+% JTREE_ONLINE_INF_ENGINE Online Junction tree inference algorithm for DBNs.
+% engine = jtree_online_inf_engine(bnet, ...)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% clusters - specifies variables that must be grouped in the 1.5 slice DBN
+% maximize - 1 means do max-product, 0 means sum-product [0]
+%
+% The same nodes must be observed in every slice.
+
+ss = length(bnet.intra);
+clusters = {};
+engine.maximize = 0;
+
+args = varargin;
+nargs = length(args);
+for i=1:2:length(args)
+  switch args{i},
+   case 'clusters', clusters = args{i+1};
+   case 'maximize', engine.maximize = args{i+1};
+   otherwise, error(['unrecognized argument ' args{i}])
+  end
+end
+
+engine.evidence = [];
+engine.node_sizes = [];
+
+int = [];
+% include nodes with any outgoing arcs
+for u=1:ss
+  if any(bnet.inter(u,:))
+    int = [int u];
+  end
+end
+
+engine.interface = int;
+engine.nonint = mysetdiff(1:ss, int);
+
+onodes = bnet.observed;
+
+% Create a "1.5 slice" jtree, containing the interface nodes of slice 1
+% and all the nodes of slice 2
+% To keep the node numbering the same, we simply disconnect the non-interface nodes
+% from slice 1, and set their size to 1.
+% We do this to speed things up, and so that the likelihood is computed correctly - we do not need to do
+% this if we just want to compute marginals (i.e., we can include nodes whose potentials will
+% be left as all 1s).
+intra15 = bnet.intra;
+for i=engine.nonint(:)'
+  intra15(:,i) = 0;
+  intra15(i,:) = 0;
+  assert(~any(bnet.inter(i,:)))
+end
+dag15 = [intra15      bnet.inter;
+	 zeros(ss)    bnet.intra];
+ns = bnet.node_sizes(:);
+ns(engine.nonint) = 1; % disconnected nodes get size 1
+obs_nodes = [onodes(:) onodes(:)+ss];
+bnet15 = mk_bnet(dag15, ns, 'discrete', bnet.dnodes, 'equiv_class', bnet.equiv_class(:), ...
+		 'observed', obs_nodes(:));
+
+% use unconstrained elimination,
+% but force there to be a clique containing both interfaces
+clusters(end+1:end+2) = {int, int+ss};
+%engine.jtree_engine = jtree_inf_engine(bnet15, 'clusters', clusters, 'root', int+ss);
+engine.jtree_engine = jtree_sparse_inf_engine(bnet15, 'clusters', clusters, 'root', int+ss);
+jtree_engine = struct(engine.jtree_engine); % violate object privacy
+
+engine.in_clq = clq_containing_nodes(engine.jtree_engine, int);
+engine.out_clq = clq_containing_nodes(engine.jtree_engine, int+ss);
+engine.clq_ass_to_node = jtree_engine.clq_ass_to_node;
+engine.root = jtree_engine.root_clq;
+
+% Also create an engine just for slice 1
+bnet1 = mk_bnet(bnet.intra1, bnet.node_sizes_slice, 'discrete', myintersect(bnet.dnodes,1:ss), ...
+		'equiv_class', bnet.equiv_class(:,1), 'observed', onodes);
+for i=1:max(bnet1.equiv_class)
+  bnet1.CPD{i} = bnet.CPD{i};
+end
+%engine.jtree_engine1 = jtree_inf_engine(bnet1, 'clusters', {int}, 'root', int);
+engine.jtree_engine1 = jtree_sparse_inf_engine(bnet1, 'clusters', {int}, 'root', int);
+jtree_engine1 = struct(engine.jtree_engine1); % violate object privacy
+engine.int_clq1 = clq_containing_nodes(engine.jtree_engine1, int);
+engine.clq_ass_to_node1 = jtree_engine1.clq_ass_to_node;
+engine.root1 = jtree_engine1.root_clq;
+
+engine.observed = [onodes onodes+ss];
+engine.observed1 = onodes;
+engine.pot_type = determine_pot_type(bnet, onodes);
+engine.slice_size = bnet.nnodes_per_slice;
+
+engine = class(engine, 'jtree_sparse_2TBN_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function m = marginal_family(engine, b, i, t, add_ev)
+% MARGINAL_FAMILY Compute the marginal on the specified family (jtree_2TBN)
+% marginal = marginal_family(engine, b, i, t, add_ev)
+
+bnet = bnet_from_engine(engine);
+if t==1
+  m = marginal_nodes(engine, b, family(bnet.dag, i), t, add_ev, 1);
+else
+  ss = length(bnet.intra);
+  fam = family(bnet.dag, i+ss);
+  m = marginal_nodes(engine, b, fam, t, add_ev, 1);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@jtree_sparse_2TBN_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function marginal = marginal_nodes(engine, b, nodes, t, add_ev, is_fam)
+% function marginal = marginal_nodes(engine, b, nodes, t, add_ev, is_fam) (jtree_2TBN)
+
+if nargin < 6, is_fam = 0; end
+ss = engine.slice_size;
+
+if ~is_fam & (t > 1) & all(nodes<=ss)
+  nodes = nodes + ss;
+end
+
+if t==1
+  c = clq_containing_nodes(engine.jtree_engine1, nodes, is_fam);
+else
+  c = clq_containing_nodes(engine.jtree_engine, nodes, is_fam);
+end
+if c == -1
+  error(['no clique contains ' nodes])
+end
+bigpot = b.clpot{c};
+pot = marginalize_pot(bigpot, nodes, engine.maximize);
+marginal = pot_to_marginal(pot);
+
+% we convert the domain to the unrolled numbering system
+% so that add_ev_to_dmarginal (maybe called in update_ess) extracts the right evidence.
+if t > 1
+  marginal.domain = nodes+(t-2)*engine.slice_size;
+end
+assert(~add_ev);
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@smoother_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+/bnet_from_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_evidence.m/1.1.1.1/Mon Jun 17 23:46:46 2002//
+/find_mpe.m/1.1.1.1/Mon Jun 17 23:50:16 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/smoother_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/update_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@smoother_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/online/@smoother_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@smoother_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@smoother_engine/bnet_from_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function bnet = bnet_from_engine(engine)
+% BNET_FROM_ENGINE Return the bnet structure stored inside the engine (smoother_engine)
+% bnet = bnet_from_engine(engine)
+
+bnet = bnet_from_engine(engine.tbn_engine);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@smoother_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function [engine, LL] = enter_evidence(engine, ev)
+% ENTER_EVIDENCE Call the offline smoother
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+
+T = size(ev, 2);
+f = cell(1,T);
+b = cell(1,T); % b{t}.clpot{c}
+ll = zeros(1,T);
+[f{1}, ll(1)] = fwd1(engine.tbn_engine, ev(:,1), 1);
+for t=2:T
+  [f{t}, ll(t)] = fwd(engine.tbn_engine, f{t-1}, ev(:,t), t);
+end
+LL = sum(ll);
+b{T} = backT(engine.tbn_engine, f{T}, T);
+for t=T-1:-1:1
+  b{t} = back(engine.tbn_engine, b{t+1}, f{t}, t);
+end
+engine.b = b;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@smoother_engine/find_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,33 @@
+function mpe = find_mpe(engine, ev)
+% FIND_MPE Find the most probable explanation (Viterbi)
+% mpe = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+
+mpe = cell(size(ev));
+engine.tbn_engine = set_fields(engine.tbn_engine, 'maximize', 1);
+
+T = size(ev, 2);
+f = cell(1,T);
+b = cell(1,T); % b{t}.clpot{c}
+ll = zeros(1,T);
+[f{1}, ll(1)] = fwd1(engine.tbn_engine, ev(:,1), 1);
+for t=2:T
+  [f{t}, ll(t)] = fwd(engine.tbn_engine, f{t-1}, ev(:,t), t);
+end
+
+if T==1
+  [b{1}, mpe(:,1)] = backT_mpe(engine.tbn_engine, f{1}, ev(:,1), 1);
+else
+  [b{T}, mpe(:,T)] = backT_mpe(engine.tbn_engine, f{T}, ev(:,T-1:T), T);
+  for t=T-1:-1:2
+    [b{t}, mpe(:,t)] = back_mpe(engine.tbn_engine, b{t+1}, f{t}, ev(:,t-1:t), t);
+  end
+  t = 1;
+  [b{t}, mpe(:,t)] = back1_mpe(engine.tbn_engine, b{t+1}, f{t}, ev(:,1), t);
+end
+engine.b = b;
+  
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@smoother_engine/find_mpeMM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,34 @@
+function mpe = find_mpeMM(engine, ev)
+% FIND_MPE Find the most probable explanation (Viterbi)
+% mpe = enter_evidence(engine, evidence, ...)
+%
+% evidence{i,t} = [] if if X(i,t) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+
+mpe = cell(size(ev));
+engine.tbn_engine = set_fields(engine.tbn_engine, 'maximize', 1);
+disp('forward step')
+T = size(ev, 2);
+f = cell(1,T);
+% b = cell(1,T); % b{t}.clpot{c}
+
+f{1} = fwd1(engine.tbn_engine, ev(:,1), 1);
+for t=2:T
+%   [f{t}, ll(t)] = fwd(engine.tbn_engine, f{t-1}, ev(:,t), t);
+  f{t} = fwdMM(engine.tbn_engine, f{t-1}, ev(:,t), t);
+end
+disp('backward step')
+if T==1
+  [b, mpe(:,1)] = backT_mpe(engine.tbn_engine, f{1}, ev(:,1), 1);
+else
+  [b, mpe(:,T)] = backT_mpe(engine.tbn_engine, f{T}, ev(:,T-1:T), T);
+  for t=T-1:-1:2
+    [b, mpe(:,t)] = back_mpe(engine.tbn_engine, b, f{t}, ev(:,t-1:t), t);
+  end
+  t = 1;
+  [b, mpe(:,t)] = back1_mpe(engine.tbn_engine, b, f{t}, ev(:,1), t);
+end
+engine.b = b;
+  
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@smoother_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function marginal = marginal_family(engine, i, t, add_ev)
+% MARGINAL_FAMILY Compute the joint distribution on a set of family (smoother_engine)
+% function marginal = marginal_family(engine, i, t, add_ev)
+
+if nargin < 4, add_ev = 0; end
+marginal = marginal_family(engine.tbn_engine, engine.b{t}, i, t, add_ev);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@smoother_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function marginal = marginal_nodes(engine, nodes, t, add_ev)
+% MARGINAL_NODES Compute the joint distribution on a set of nodes (smoother_engine)
+% function marginal = marginal_nodes(engine, nodes, t, add_ev)
+
+if nargin < 4, add_ev = 0; end
+
+marginal = marginal_nodes(engine.tbn_engine, engine.b{t}, nodes, t, add_ev);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@smoother_engine/smoother_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function engine = smoother_engine(tbn_engine)
+% SMOOTHER_ENGINE Create an engine which does offline (fixed-interval) smoothing in O(T) space/time
+% function engine = smoother_engine(tbn_engine)
+%
+% tbn_engine is any 2TBN inference engine which supports the following methods:
+% fwd, fwd1, back, backT, back, marginal_nodes and marginal_family.
+
+engine.tbn_engine = tbn_engine;
+engine.b = []; % space to store smoothed messages
+engine = class(engine, 'smoother_engine');
+%engine = class(engine, 'smoother_engine', inf_engine(bnet_from_engine(tbn_engine)));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/@smoother_engine/update_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function engine = update_engine(engine, newCPDs)
+% UPDATE_ENGINE Update the engine to take into account the new parameters (smoother_engine).
+% engine = update_engine(engine, newCPDs)
+
+engine.tbn_engine = update_engine(engine.tbn_engine, newCPDs);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/dummy/1.1.1.1/Sat Jan 18 22:22:38 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+A D/@filter_engine////
+A D/@hmm_2TBN_inf_engine////
+A D/@jtree_2TBN_inf_engine////
+A D/@jtree_sparse_2TBN_inf_engine////
+A D/@smoother_engine////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/online
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/online/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_fg_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/belprop_fg_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/find_mpe.m/1.1.1.1/Thu Jun 20 00:02:12 2002//
+/loopy_converged.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/set_params.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_fg_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@belprop_fg_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_fg_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_fg_inf_engine/belprop_fg_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,47 @@
+function engine = belprop_fg_inf_engine(fg, varargin) 
+% BELPROP_FG_INF_ENGINE Make a belief propagation inference engine for factor graphs
+% engine = belprop_fg_inf_engine(factor_graph, ...)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default in brackets]
+% e.g., engine = belprop_inf_engine(fg, 'tol', 1e-2, 'max_iter', 10)
+%
+% max_iter - max. num. iterations [ 2*num_nodes ]
+% momentum - weight assigned to old message in convex combination (useful for damping oscillations) [0]
+% tol - tolerance used to assess convergence [1e-3]
+% maximize - 1 means use max-product, 0 means use sum-product [0]
+%
+% This uses potential objects, like belprop_inf_engine, and hence is quite slow.
+
+engine = init_fields;
+engine = class(engine, 'belprop_fg_inf_engine');
+
+% set params to default values
+N = length(fg.G);
+engine.max_iter = 2*N;
+engine.momentum = 0;
+engine.tol = 1e-3;
+engine.maximize = 0;
+
+% parse optional arguments
+engine = set_params(engine, varargin);
+
+engine.fgraph = fg;
+
+% store results computed by enter_evidence here
+engine.marginal_nodes = cell(1, fg.nvars);
+engine.evidence = [];
+
+
+%%%%%%%%%%%%
+
+function engine = init_fields()
+
+engine.fgraph = [];
+engine.max_iter = [];
+engine.momentum = [];
+engine.tol = [];
+engine.maximize = [];
+engine.marginal_nodes = [];
+engine.evidence = [];
+engine.niter = [];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_fg_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,126 @@
+function [engine, ll, niter] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Propagate evidence using belief propagation
+% [engine, ll, niter] = enter_evidence(engine, evidence, ...)
+%
+% The log-likelihood is not computed; ll = 0.
+% niter contains the number of iterations used 
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - 1 means use max-product, 0 means use sum-product [0]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+ll = 0;
+maximize = 0;
+
+if nargin >= 3
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1};
+     otherwise,
+      error(['invalid argument name ' args{i}]);
+    end
+  end
+end
+
+verbose = 0;
+
+ns = engine.fgraph.node_sizes;
+onodes = find(~isemptycell(evidence));
+hnodes = find(isemptycell(evidence));
+cnodes = engine.fgraph.cnodes;
+pot_type = determine_pot_type(engine.fgraph, onodes);
+
+% prime each local kernel with evidence (if any)
+nfactors = engine.fgraph.nfactors;
+nvars = engine.fgraph.nvars;
+factors = cell(1,nfactors);
+for f=1:nfactors
+  K = engine.fgraph.factors{engine.fgraph.equiv_class(f)};
+  factors{f} = convert_to_pot(K, pot_type, engine.fgraph.dom{f}(:), evidence);
+end
+  
+% initialise msgs
+msg_var_to_fac = cell(nvars, nfactors);
+for x=1:nvars
+  for f=engine.fgraph.dep{x}
+    msg_var_to_fac{x,f} = mk_initial_pot(pot_type, x, ns, cnodes, onodes);
+  end
+end
+msg_fac_to_var = cell(nfactors, nvars);
+dom = cell(1, nfactors);
+for f=1:nfactors
+  %hdom{f} = myintersect(engine.fgraph.dom{f}, hnodes);
+  dom{f} = engine.fgraph.dom{f}(:)';
+  for x=dom{f}
+    msg_fac_to_var{f,x} = mk_initial_pot(pot_type, x, ns, cnodes, onodes);
+    %msg_fac_to_var{f,x} = marginalize_pot(factors{f}, x);
+  end
+end
+
+
+
+converged = 0;
+iter = 1;
+var_prod = cell(1, nvars);
+fac_prod = cell(1, nfactors);
+
+while ~converged & (iter <= engine.max_iter)
+  if verbose, fprintf('iter %d\n', iter);  end
+  
+  % absorb
+  old_var_prod = var_prod;
+  for x=1:nvars
+    var_prod{x} = mk_initial_pot(pot_type, x, ns, cnodes, onodes);
+    for f=engine.fgraph.dep{x}
+      var_prod{x} = multiply_by_pot(var_prod{x}, msg_fac_to_var{f,x});
+    end
+  end
+  for f=1:nfactors
+    fac_prod{f} = mk_initial_pot(pot_type, dom{f}, ns, cnodes, onodes);
+    for x=dom{f}
+      fac_prod{f} = multiply_by_pot(fac_prod{f}, msg_var_to_fac{x,f});
+    end
+  end
+
+  % send msgs to neighbors
+  old_msg_var_to_fac = msg_var_to_fac;
+  old_msg_fac_to_var = msg_fac_to_var;
+  converged = 1;
+  for x=1:nvars
+    %if verbose, disp(['var ' num2str(x) ' sending to fac ' num2str(engine.fgraph.dep{x})]); end
+    for f=engine.fgraph.dep{x}
+      temp = divide_by_pot(var_prod{x}, old_msg_fac_to_var{f,x});
+      msg_var_to_fac{x,f} = normalize_pot(temp);
+      if ~approxeq_pot(msg_var_to_fac{x,f}, old_msg_var_to_fac{x,f}, engine.tol), converged = 0; end
+    end
+  end
+  for f=1:nfactors
+    %if verbose, disp(['fac ' num2str(f) ' sending to var ' num2str(dom{f})]); end
+    for x=dom{f}
+      temp = divide_by_pot(fac_prod{f}, old_msg_var_to_fac{x,f});
+      temp2 = multiply_by_pot(factors{f}, temp);
+      temp3 = marginalize_pot(temp2, x, maximize);
+      msg_fac_to_var{f,x} = normalize_pot(temp3);
+      if ~approxeq_pot(msg_fac_to_var{f,x}, old_msg_fac_to_var{f,x}, engine.tol), converged = 0; end
+    end
+  end
+
+  if iter==1
+    converged = 0;
+  end
+  iter = iter + 1;
+end
+
+niter = iter - 1;
+engine.niter = niter;
+
+for x=1:nvars
+  engine.marginal_nodes{x} = normalize_pot(var_prod{x});
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_fg_inf_engine/find_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,49 @@
+function mpe = find_mpe(engine, evidence, varargin)
+% FIND_MPE Find the most probable explanation of the data  (belprop_fg)
+% function mpe = find_mpe(engine, evidence,...)
+%
+% evidence{i} = [] if X(i) is hidden, and otherwise contains its observed value (scalar or column vector).
+%
+% This finds the marginally most likely value for each hidden node,
+% and may give the wrong results even if the graph is acyclic,
+% unless you set break_ties = 1.
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% break_ties is optional. If 1, we will force ties to be broken consistently
+%  by calling enter_evidence N times. (see Jensen96, p106) Default = 1.
+
+break_ties = 1;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'break_ties',    break_ties = args{i+1}; 
+   otherwise,  
+    error(['invalid argument name ' args{i}]);       
+  end
+end
+
+engine = enter_evidence(engine, evidence, 'maximize', 1);
+
+observed = ~isemptycell(evidence);
+evidence = evidence(:); % hack to handle unrolled DBNs
+N = length(evidence);
+mpe = cell(1,N);
+for i=1:N
+  m = marginal_nodes(engine, i);
+  % observed nodes are all set to 1 inside the inference engine, so we must undo this
+  if observed(i)
+    mpe{i} = evidence{i};
+  else
+    mpe{i} = argmax(m.T);
+    if break_ties
+      evidence{i} = mpe{i};                             
+      [engine, ll] = enter_evidence(engine, evidence, 'maximize', 1);  
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_fg_inf_engine/loopy_converged.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function niter = loopy_converged(engine)
+% LOOPY_CONVERGED Did loopy belief propagation converge? 0 means no, eles we return the num. iterations.
+% function niter = loopy_converged(engine)
+%
+% We use a simple heuristic: we say convergence occurred if the number of iterations
+% used was less than the maximum allowed.
+
+if engine.niter == engine.max_iter
+  niter = 0;
+else
+  niter = engine.niter;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_fg_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function marginal = marginal_nodes(engine, query)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (belprop)
+% marginal = marginal_nodes(engine, query)
+
+assert(length(query)==1);
+marginal = pot_to_marginal(engine.marginal_nodes{query});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_fg_inf_engine/set_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function engine = set_params(engine, varargin)
+% SET_PARAMS Set the parameters (fields) for a belprop_inf_engine object
+% engine = set_params(engine, name/value pairs)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% e.g., engine = set_params(engine, 'tol', 1e-2, 'max_iter', 10)
+%
+% max_iter - max. num. loopy iterations 
+% momentum - weight assigned to old message in convex combination 
+% tol - tolerance used to assess convergence 
+% maximize - 1 means use max-product, 0 means use sum-product
+
+args = varargin{1};
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'max_iter', engine.max_iter = args{i+1};
+   case 'momentum', engine.momentum = args{i+1};
+   case 'tol',      engine.tol = args{i+1};
+   case 'maximize', engine.maximize = args{i+1};
+   otherwise,
+    error(['invalid argument name ' args{i}]);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/belprop_inf_engine.m/1.1.1.1/Tue Dec 31 19:00:06 2002//
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/find_mpe.m/1.1.1.1/Wed Jun 19 22:08:40 2002//
+/loopy_converged.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+A D/Old////
+A D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@belprop_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/belprop_gdl_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/belprop_inf_engine_nostr.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_evidence1.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_domain.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@belprop_inf_engine/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/Old/belprop_gdl_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,67 @@
+function engine = belprop_gdl_inf_engine(gdl, varargin) 
+% BELPROP_GDL_INF_ENGINE Make a belief propagation inference engine for a GDL graph
+% engine = belprop_gdl_inf_engine(gdl_graph, ...)
+%
+% If the GDL graph is a tree, this will give exact results.
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default in brackets]
+% e.g., engine = belprop_inf_engine(gdl, 'tol', 1e-2, 'max_iter', 10)
+%
+% protocol - 'tree' means send messages up then down the tree,
+%            'parallel' means use synchronous updates ['parallel']
+% max_iter - max. num. iterations [ 2*num_nodes ]
+% momentum - weight assigned to old message in convex combination (useful for damping oscillations) [0]
+% tol - tolerance used to assess convergence [1e-3]
+% maximize - 1 means use max-product, 0 means use sum-product [0]
+
+
+engine = init_fields;
+engine = class(engine, 'belprop_gdl_inf_engine');
+
+% set default params
+N = length(gdl.G);
+engine.protocol = 'parallel';
+engine.max_iter = 2*N;
+engine.momentum = 0;
+engine.tol = 1e-3;
+engine.maximize = 0;
+
+engine = set_params(engine, varargin);
+
+engine.gdl = gdl;
+
+if strcmp(engine.protocol, 'tree')
+  % Make a rooted tree, so there is a fixed message passing order.
+  root = N;
+  [engine.tree, engine.preorder, engine.postorder, height, cyclic] = mk_rooted_tree(gdl.G, root);
+  assert(~cyclic);
+end
+
+% store results computed by enter_evidence here
+ndoms = length(gdl.doms);
+nvars = length(gdl.vars);
+engine.marginal_domains = cell(1, ndoms);
+
+% to compute the marginal on each variable, we need to know which domain to marginalize
+% and we want to choose the lightest. We compute the weight once we have seen the evidence.
+engine.dom_weight = [];
+engine.evidence = [];
+
+
+%%%%%%%%%
+
+function engine = init_fields()
+
+engine.protocol = [];
+engine.gdl = [];
+engine.max_iter = [];
+engine.momentum = [];
+engine.tol = [];
+engine.maximize = [];
+engine.marginal_domains = [];
+engine.evidence = [];
+engine.tree = [];
+engine.preorder = [];
+engine.postorder = [];
+engine.dom_weight = [];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/Old/belprop_inf_engine_nostr.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,31 @@
+function engine = belprop_inf_engine(fg, max_iter, momentum, tol, maximize)
+
+if nargin < 2, max_iter = length(fg.G); end
+if nargin < 3, momentum = 0; end
+if nargin < 4, tol = 1e-3; end
+if nargin < 5, maximize = 0; end
+
+engine.fgraph = fg;
+engine.max_iter = max_iter;
+engine.momentum = momentum;
+engine.tol = tol;
+engine.maximize = maximize;
+
+% store results computed by enter_evidence here
+ndoms = length(fg.doms);
+nvars = length(fg.vars);
+engine.marginal_domains = cell(1, ndoms);
+
+% to compute the marginal on each variable, we need to know which domain to marginalize
+% so we represent each domain as a bit vector, and compute its (pre-evidence) weight
+engine.dom_weight = [];
+
+% engine.dom_bitv = sparse(ndoms, nvars);
+% ns = fg.node_sizes;
+% for i=1:ndoms
+%   engine.dom_bitv(i, fg.doms{i}) = 1;
+%   engine.dom_weight(i) = prod(ns(fg.doms{i}));
+% end
+
+
+engine = class(engine, 'belprop_inf_engine');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/Old/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,80 @@
+function engine = enter_evidence(engine, evidence)
+
+doms = engine.fg.doms;
+ndoms = length(doms);
+ns = engine.fg.node_sizes;
+obs = find(~isemptycell(evidence));
+cobs = myintersect(obs, engine.fg.cnodes);
+dobs = myintersect(obs, engine.fg.dnodes);
+ns(cobs) = 0;
+ns(dobs) = 1;
+
+% prime each local kernel with evidence (if any)
+local_kernel = cell(1, ndoms);
+for i=1:length(engine.fg.kernels_of_type)
+  u = engine.fg.kernels_of_type{i};
+  local_kernel(u) = kernel_to_dpots(engine.fg.kernels{i}, evidence, engine.fg.domains_of_type{i});
+end
+  
+% initialise all msgs to 1s
+nedges = engine.fg.nedges;
+msg = cell(1, nedges);
+for i=1:nedges
+  msg{i} = dpot(engine.fg.sepset{i}, ns(engine.fg.sepset{i}));
+end
+
+prod_of_msg = cell(1, ndoms);
+bel = cell(1, ndoms);
+old_bel = cell(1, ndoms);
+
+converged = 0;
+iter = 1;
+while ~converged & (iter <= engine.max_iter)
+  
+  % each node multiplies all its incoming msgs
+  for i=1:ndoms
+    prod_of_msg{i} = dpot(doms{i}, ns(doms{i}));
+    nbrs = engine.fg.nbrs{i};
+    for j=1:length(nbrs)
+      ndx = engine.fg.edge_ndx(j,i);
+      prod_of_msg{i} = multiply_by_pot(prod_of_msg{i}, msg{ndx});
+    end
+  end
+  old_msg = msg;
+  
+  % each node computes its local belief
+  for i=1:ndoms
+    bel{i} = normalize_pot(multiply_pots(prod_of_msg{i}, local_kernel{i}));
+  end
+
+  % converged?
+  converged = 1;
+  for i=1:ndoms
+    if ~approxeq(bel{i}, old_bel{i}, engine.tol)
+      converged = 0;
+      break;
+    end
+  end
+
+  if ~converged
+    % each node sends a msg to each of its neighbors
+    for i=1:ndoms
+      nbrs = engine.fg.nbrs{i};
+      for j=1:length(nbrs)
+	% multiply all incoming msgs except from j
+	temp = prod_of_msg{i};
+	ndx = engine.fg.edge_ndx(j,i);
+	temp = divide_by_pot(temp, old_msg{ndx});
+	% send msg from i to j
+	temp = multiply_by_pot(temp, local_kernel{i});
+	ndx = engine.fg.edge_ndx(i,j);
+	msg{ndx} = normalize_pot(marginalize_pot(temp, engine.fg.sepset{ndx}));
+      end
+    end
+  end
+
+  iter = iter + 1;
+end
+
+  
+engine.marginal = bel;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/Old/enter_evidence1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,94 @@
+function engine = enter_evidence(engine, evidence)
+
+doms = engine.fgraph.doms;
+ndoms = length(doms);
+ns = engine.fgraph.node_sizes;
+obs = find(~isemptycell(evidence));
+cobs = myintersect(obs, engine.fgraph.cnodes);
+dobs = myintersect(obs, engine.fgraph.dnodes);
+ns(cobs) = 0;
+ns(dobs) = 1;
+
+% recompute the weight of each domain now that we know what nodes are observed
+for i=1:ndoms
+  engine.dom_weight(i) = prod(ns(engine.fgraph.doms{i}));
+end
+
+% prime each local kernel with evidence (if any)
+local_kernel = cell(1, ndoms);
+for i=1:length(engine.fgraph.kernels_of_type)
+  u = engine.fgraph.kernels_of_type{i};
+  local_kernel(u) = kernel_to_dpots(engine.fgraph.kernels{i}, evidence, engine.fgraph.domains_of_type{i});
+end
+  
+% initialise all msgs to 1s
+msg = cell(ndoms, ndoms);
+for i=1:ndoms
+  nbrs = engine.fgraph.nbrs{i};
+  for j=nbrs(:)'
+    dom = engine.fgraph.sepset{i,j};
+    msg{i,j} = dpot(dom, ns(dom));
+  end
+end
+
+prod_of_msg = cell(1, ndoms);
+bel = cell(1, ndoms);
+old_bel = cell(1, ndoms);
+
+converged = 0;
+iter = 1;
+while ~converged & (iter <= engine.max_iter)
+  
+  % each node multiplies all its incoming msgs
+  for i=1:ndoms
+    prod_of_msg{i} = dpot(doms{i}, ns(doms{i}));
+    nbrs = engine.fgraph.nbrs{i};
+    for j=nbrs(:)'
+      prod_of_msg{i} = multiply_by_pot(prod_of_msg{i}, msg{j,i});
+    end
+  end
+  
+  % each node computes its local belief
+  old_bel = bel;
+  for i=1:ndoms
+    bel{i} = normalize_pot(multiply_pots(prod_of_msg{i}, local_kernel{i}));
+  end
+
+  % converged?
+  if iter==1
+    converged = 0;
+  else
+    converged = 1;
+    for i=1:ndoms
+      belT = get_params(bel{i}, 'table');
+      old_belT = get_params(old_bel{i}, 'table');
+      if ~approxeq(belT, old_belT, engine.tol)
+	converged = 0;
+	break;
+      end
+    end
+  end
+
+  if ~converged
+    old_msg = msg;
+    % each node sends a msg to each of its neighbors
+    for i=1:ndoms
+      nbrs = engine.fgraph.nbrs{i};
+      for j=nbrs(:)'
+	% multiply all incoming msgs except from j
+	temp = prod_of_msg{i};
+	temp = divide_by_pot(temp, old_msg{j,i});
+	% send msg from i to j
+	temp = multiply_by_pot(temp, local_kernel{i});
+	msg{i,j} = normalize_pot(marginalize_pot(temp, engine.fgraph.sepset{i,j}));
+      end
+    end
+  end
+
+  iter = iter + 1
+end
+
+engine.marginal_domains = bel;
+%for i=1:ndoms  
+  %engine.marginal_domains{i} = get_params(bel{i}, 'table');
+%end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/Old/marginal_domain.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function marginal = marginal_domain(engine, i)
+% MARGINAL_DOMAIN Return the marginal on the specified domain (belprop)
+% marginal = marginal_domain(engine, i)
+
+marginal = pot_to_marginal(engine.marginal_domains{i});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/belprop_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,90 @@
+function engine = belprop_inf_engine(bnet, varargin) 
+% BELPROP_INF_ENGINE Make a loopy belief propagation inference engine
+% engine = belprop_inf_engine(bnet, ...)
+%
+% This is like pearl_inf_engine, except it uses potential objects,
+% instead of lambda/pi structs. Hence it is slower.
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default in brackets]
+%
+% protocol - 'tree' means send messages up then down the tree,
+%            'parallel' means use synchronous updates ['parallel']
+% max_iter - max. num. iterations [ 2*num_nodes ]
+% momentum - weight assigned to old message in convex combination (useful for damping oscillations) [0]
+% tol      - tolerance used to assess convergence [1e-3]
+% maximize - 1 means use max-product, 0 means use sum-product [0]
+% filename - name of file to write beliefs to after each iteration within enter_evidence [ [] ]
+%
+% e.g., engine = belprop_inf_engine(bnet, 'maximize', 1, 'max_iter', 10)
+
+% gdl = general distributive law
+engine.gdl = bnet_to_gdl(bnet);
+
+% set default params
+N = length(engine.gdl.G);
+engine.protocol = 'parallel';
+engine.max_iter = 2*N;
+engine.momentum = 0;
+engine.tol = 1e-3;
+engine.maximize = 0;
+engine.filename = [];
+engine.fid = [];
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'max_iter', engine.max_iter = args{i+1};
+   case 'momentum', engine.momentum = args{i+1};
+   case 'tol',      engine.tol = args{i+1};
+   case 'protocol', engine.protocol = args{i+1};
+   case 'filename', engine.filename = args{i+1};
+   otherwise,
+    error(['invalid argument name ' args{i}]);
+  end
+end
+
+
+if strcmp(engine.protocol, 'tree')
+  % Make a rooted tree, so there is a fixed message passing order.
+  root = N;
+  [engine.tree, engine.preorder, engine.postorder, height, cyclic] = mk_rooted_tree(engine.gdl.G, root);
+  assert(~cyclic);
+end
+
+% store results computed by enter_evidence here
+engine.marginal_domains = cell(1, N);
+
+engine.niter = [];
+
+engine = class(engine, 'belprop_inf_engine', inf_engine(bnet));
+
+%%%%%%%%%
+
+function gdl = bnet_to_gdl(bnet)
+
+gdl.G = mk_undirected(bnet.dag);
+N = length(bnet.dag);
+gdl.doms = cell(1,N);
+for i=1:N
+  gdl.doms{i} = family(bnet.dag, i);
+end 
+
+% Compute a bit vector representation of the set of domains
+% dom_bitv(i,j) = 1 iff variable j occurs in domain i
+gdl.dom_bitv = zeros(N, N);
+for i=1:N
+  gdl.dom_bitv(i, gdl.doms{i}) = 1;
+end
+   
+% compute the interesection of the domains on either side of each edge (separating set)
+gdl.sepset = cell(N, N);
+gdl.nbrs = cell(1,N);
+for i=1:N
+  nbrs = neighbors(gdl.G, i);
+  gdl.nbrs{i} = nbrs;
+  for j = nbrs(:)'
+    gdl.sepset{i,j} = myintersect(gdl.doms{i}, gdl.doms{j});
+  end
+end  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,86 @@
+function [engine, ll, niter] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Propagate evidence using belief propagation
+% [engine, ll, niter] = enter_evidence(engine, evidence, ...)
+%
+% The log-likelihood is not computed; ll = 0.
+% niter contains the number of iterations used (if engine.protocol = 'parallel')
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - 1 means use max-product, 0 means use sum-product [0]
+% exclude  - list of nodes whose potential will not be included in the joint [ [] ]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+
+ll = 0;
+exclude = [];
+maximize = 0;
+
+if nargin >= 3
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'exclude', exclude = args{i+1};
+     case 'maximize', maximize = args{i+1};
+     otherwise,
+      error(['invalid argument name ' args{i}]);
+    end
+  end
+end
+
+engine.maximize = maximize;
+
+if ~isempty(engine.filename)
+  engine.fid = fopen(engine.filename, 'w');
+  if engine.fid == 0
+    error(['can''t open ' engine.filename]);
+  end
+else
+  engine.fid = [];
+end
+
+gdl = engine.gdl;
+bnet = bnet_from_engine(engine);
+
+ndoms = length(gdl.doms);
+ns = bnet.node_sizes;
+onodes = find(~isemptycell(evidence));
+pot_type = determine_pot_type(bnet, onodes);
+
+% prime each local kernel with evidence (if any)
+local_kernel = cell(1, ndoms);
+for i=1:ndoms
+  if myismember(i, exclude)
+    local_kernel{i} =  mk_initial_pot(pot_type, gdl.doms{i}, ns, bnet.cnodes, onodes);
+  else
+    e = bnet.equiv_class(i);
+    local_kernel{i} =  convert_to_pot(bnet.CPD{e}, pot_type, gdl.doms{i}(:), evidence);
+  end
+end
+  
+% initialise all msgs to 1s
+msg = cell(ndoms, ndoms);
+for i=1:ndoms
+  nbrs = gdl.nbrs{i};
+  for j=nbrs(:)'
+    dom = gdl.sepset{i,j};
+    msg{i,j} = mk_initial_pot(pot_type, dom, ns, bnet.cnodes, onodes);
+  end
+end
+
+switch engine.protocol
+ case 'parallel', 
+   [engine.marginal_domains, niter] = parallel_protocol(engine, evidence, pot_type, local_kernel, msg);
+ case 'tree',
+  engine.marginal_domains = serial_protocol(engine, evidence, pot_type, local_kernel, msg);
+  niter = 1;
+end
+engine.niter = niter;
+
+%fprintf('just finished %d iterations of belprop\n', niter);
+
+if ~isempty(engine.filename)
+  fclose(engine.fid);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/find_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,49 @@
+function mpe = find_mpe(engine, evidence, varargin)
+% FIND_MPE Find the most probable explanation of the data  (belprop)
+% function mpe = find_mpe(engine, evidence,...)
+%
+% evidence{i} = [] if X(i) is hidden, and otherwise contains its observed value (scalar or column vector).
+%
+% This finds the marginally most likely value for each hidden node,
+% and may give the wrong results even if the graph is acyclic,
+% unless you set break_ties = 1.
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% break_ties is optional. If 1, we will force ties to be broken consistently
+%  by calling enter_evidence N times. (see Jensen96, p106) Default = 1.
+
+break_ties = 1;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'break_ties',    break_ties = args{i+1}; 
+   otherwise,  
+    error(['invalid argument name ' args{i}]);       
+  end
+end
+
+engine = enter_evidence(engine, evidence, 'maximize', 1);
+
+observed = ~isemptycell(evidence);
+evidence = evidence(:); % hack to handle unrolled DBNs
+N = length(evidence);
+mpe = cell(1,N);
+for i=1:N
+  m = marginal_nodes(engine, i);
+  % observed nodes are all set to 1 inside the inference engine, so we must undo this
+  if observed(i)
+    mpe{i} = evidence{i};
+  else
+    mpe{i} = argmax(m.T);
+    if break_ties
+      evidence{i} = mpe{i};                             
+      [engine, ll] = enter_evidence(engine, evidence, 'maximize', 1);  
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/loopy_converged.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function niter = loopy_converged(engine)
+% LOOPY_CONVERGED Did loopy belief propagation converge? 0 means no, eles we return the num. iterations.
+% function niter = loopy_converged(engine)
+%
+% We use a simple heuristic: we say convergence occurred if the number of iterations
+% used was less than the maximum allowed.
+
+if engine.niter == engine.max_iter
+  niter = 0;
+else
+  niter = engine.niter;
+end
+%conv = (strcmp(engine.protocol, 'tree') | (engine.niter < engine.max_iter));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function [marginal, pot] = marginal_family(engine, query)
+% MARGINAL_NODES Compute the marginal on the family of the specified query node (belprop)
+% [marginal, pot] = marginal_family(engine, query)
+
+pot = engine.marginal_domains{query};
+marginal = pot_to_marginal(pot);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+function [marginal, pot] = marginal_nodes(engine, query)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (belprop)
+% [marginal, pot] = marginal_nodes(engine, query)
+%
+% query must be a subset of a family
+
+if isempty(query)
+  big_pot = engine.marginal_domains{1}; % pick an arbitrary domain
+else
+  big_pot = engine.marginal_domains{query(end)};   
+end
+pot = marginalize_pot(big_pot, query);
+marginal = pot_to_marginal(pot);
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+/junk/1.1.1.1/Wed May 29 15:59:56 2002//
+/parallel_protocol.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/tree_protocol.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@belprop_inf_engine/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/private/junk	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,68 @@
+fgraph
+fgraph%fgraph%fgraph%fgraph%fgraph%fgraph%fgraph%fgraph%fgraph%fgraph%fgraph%fgraph
+fgraph
+fgraphffgraphufgraphnfgraphcfgraphtfgraphifgraphofgraphnfgraph fgraph[fgraphbfgraphefgraphlfgraph,fgraph fgraphifgraphtfgraphefgraphrfgraph]fgraph fgraph=fgraph fgraphpfgraphafgraphrfgraphafgraphlfgraphlfgraphefgraphlfgraph_fgraphpfgraphrfgraphofgraphtfgraphofgraphcfgraphofgraphlfgraph(fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph,fgraph fgraphefgraphvfgraphifgraphdfgraphefgraphnfgraphcfgraphefgraph,fgraph fgraphpfgraphofgraphtfgraph_fgraphtfgraphyfgraphpfgraphefgraph,fgraph fgraphlfgraphofgraphcfgraphafgraphlfgraph_fgraphkfgraphefgraphrfgraphnfgraphefgraphlfgraph,fgraph fgraphmfgraphsfgraphgfgraph)fgraph
+fgraph
+fgraphdfgraphofgraphmfgraphsfgraph fgraph=fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphdfgraphofgraphmfgraphsfgraph;fgraph
+fgraphnfgraphdfgraphofgraphmfgraphsfgraph fgraph=fgraph fgraphlfgraphefgraphnfgraphgfgraphtfgraphhfgraph(fgraphdfgraphofgraphmfgraphsfgraph)fgraph;fgraph
+fgraphnfgraphsfgraph fgraph=fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphnfgraphofgraphdfgraphefgraph_fgraphsfgraphifgraphzfgraphefgraphsfgraph;fgraph
+fgraphofgraphnfgraphofgraphdfgraphefgraphsfgraph fgraph=fgraph fgraphffgraphifgraphnfgraphdfgraph(fgraph~fgraphifgraphsfgraphefgraphmfgraphpfgraphtfgraphyfgraphcfgraphefgraphlfgraphlfgraph(fgraphefgraphvfgraphifgraphdfgraphefgraphnfgraphcfgraphefgraph)fgraph)fgraph;fgraph
+fgraphcfgraphnfgraphofgraphdfgraphefgraphsfgraph fgraph=fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphcfgraphnfgraphofgraphdfgraphefgraphsfgraph;fgraph
+fgraph
+fgraphpfgraphrfgraphofgraphdfgraph_fgraphofgraphffgraph_fgraphmfgraphsfgraphgfgraph fgraph=fgraph fgraphcfgraphefgraphlfgraphlfgraph(fgraph1fgraph,fgraph fgraphnfgraphdfgraphofgraphmfgraphsfgraph)fgraph;fgraph
+fgraphbfgraphefgraphlfgraph fgraph=fgraph fgraphcfgraphefgraphlfgraphlfgraph(fgraph1fgraph,fgraph fgraphnfgraphdfgraphofgraphmfgraphsfgraph)fgraph;fgraph
+fgraphofgraphlfgraphdfgraph_fgraphbfgraphefgraphlfgraph fgraph=fgraph fgraphcfgraphefgraphlfgraphlfgraph(fgraph1fgraph,fgraph fgraphnfgraphdfgraphofgraphmfgraphsfgraph)fgraph;fgraph
+fgraph
+fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph fgraph=fgraph fgraph0fgraph;fgraph
+fgraphifgraphtfgraphefgraphrfgraph fgraph=fgraph fgraph1fgraph;fgraph
+fgraphwfgraphhfgraphifgraphlfgraphefgraph fgraph~fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph fgraph&fgraph fgraph(fgraphifgraphtfgraphefgraphrfgraph fgraph<fgraph=fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphmfgraphafgraphxfgraph_fgraphifgraphtfgraphefgraphrfgraph)fgraph
+fgraph fgraph fgraph
+fgraph fgraph fgraph%fgraph fgraphefgraphafgraphcfgraphhfgraph fgraphnfgraphofgraphdfgraphefgraph fgraphmfgraphufgraphlfgraphtfgraphifgraphpfgraphlfgraphifgraphefgraphsfgraph fgraphafgraphlfgraphlfgraph fgraphifgraphtfgraphsfgraph fgraphifgraphnfgraphcfgraphofgraphmfgraphifgraphnfgraphgfgraph fgraphmfgraphsfgraphgfgraphsfgraph fgraphafgraphnfgraphdfgraph fgraphcfgraphofgraphmfgraphpfgraphufgraphtfgraphefgraphsfgraph fgraphifgraphtfgraphsfgraph fgraphlfgraphofgraphcfgraphafgraphlfgraph fgraphbfgraphefgraphlfgraphifgraphefgraphffgraph
+fgraph fgraph fgraphofgraphlfgraphdfgraph_fgraphbfgraphefgraphlfgraph fgraph=fgraph fgraphbfgraphefgraphlfgraph;fgraph
+fgraph fgraph fgraphffgraphofgraphrfgraph fgraphifgraph=fgraph1fgraph:fgraphnfgraphdfgraphofgraphmfgraphsfgraph
+fgraph fgraph fgraph fgraph fgraphpfgraphrfgraphofgraphdfgraph_fgraphofgraphffgraph_fgraphmfgraphsfgraphgfgraph{fgraphifgraph}fgraph fgraph=fgraph fgraphmfgraphkfgraph_fgraphifgraphnfgraphifgraphtfgraphifgraphafgraphlfgraph_fgraphpfgraphofgraphtfgraph(fgraphpfgraphofgraphtfgraph_fgraphtfgraphyfgraphpfgraphefgraph,fgraph fgraphdfgraphofgraphmfgraphsfgraph{fgraphifgraph}fgraph,fgraph fgraphnfgraphsfgraph,fgraph fgraphcfgraphnfgraphofgraphdfgraphefgraphsfgraph,fgraph fgraphofgraphnfgraphofgraphdfgraphefgraphsfgraph)fgraph;fgraph
+fgraph fgraph fgraph fgraph fgraphnfgraphbfgraphrfgraphsfgraph fgraph=fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphnfgraphbfgraphrfgraphsfgraph{fgraphifgraph}fgraph;fgraph
+fgraph fgraph fgraph fgraph fgraphffgraphofgraphrfgraph fgraphjfgraph=fgraphnfgraphbfgraphrfgraphsfgraph(fgraph:fgraph)fgraph'fgraph
+fgraph fgraph fgraph fgraph fgraph fgraph fgraphpfgraphrfgraphofgraphdfgraph_fgraphofgraphffgraph_fgraphmfgraphsfgraphgfgraph{fgraphifgraph}fgraph fgraph=fgraph fgraphmfgraphufgraphlfgraphtfgraphifgraphpfgraphlfgraphyfgraph_fgraphbfgraphyfgraph_fgraphpfgraphofgraphtfgraph(fgraphpfgraphrfgraphofgraphdfgraph_fgraphofgraphffgraph_fgraphmfgraphsfgraphgfgraph{fgraphifgraph}fgraph,fgraph fgraphmfgraphsfgraphgfgraph{fgraphjfgraph,fgraphifgraph}fgraph)fgraph;fgraph
+fgraph fgraph fgraph fgraph fgraphefgraphnfgraphdfgraph
+fgraph fgraph fgraph fgraph fgraphbfgraphefgraphlfgraph{fgraphifgraph}fgraph fgraph=fgraph fgraphnfgraphofgraphrfgraphmfgraphafgraphlfgraphifgraphzfgraphefgraph_fgraphpfgraphofgraphtfgraph(fgraphmfgraphufgraphlfgraphtfgraphifgraphpfgraphlfgraphyfgraph_fgraphpfgraphofgraphtfgraphsfgraph(fgraphpfgraphrfgraphofgraphdfgraph_fgraphofgraphffgraph_fgraphmfgraphsfgraphgfgraph{fgraphifgraph}fgraph,fgraph fgraphlfgraphofgraphcfgraphafgraphlfgraph_fgraphkfgraphefgraphrfgraphnfgraphefgraphlfgraph{fgraphifgraph}fgraph)fgraph)fgraph;fgraph
+fgraph fgraph fgraphefgraphnfgraphdfgraph
+fgraph
+fgraph fgraph fgraph%fgraph fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph?fgraph
+fgraph fgraph fgraphifgraphffgraph fgraphifgraphtfgraphefgraphrfgraph=fgraph=fgraph1fgraph
+fgraph fgraph fgraph fgraph fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph fgraph=fgraph fgraph0fgraph;fgraph
+fgraph fgraph fgraphefgraphlfgraphsfgraphefgraph
+fgraph fgraph fgraph fgraph fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph fgraph=fgraph fgraph1fgraph;fgraph
+fgraph fgraph fgraph fgraph fgraphffgraphofgraphrfgraph fgraphifgraph=fgraph1fgraph:fgraphnfgraphdfgraphofgraphmfgraphsfgraph
+fgraph fgraph fgraph fgraph fgraph fgraph fgraphifgraphffgraph fgraph~fgraphafgraphpfgraphpfgraphrfgraphofgraphxfgraphefgraphqfgraph_fgraphpfgraphofgraphtfgraph(fgraphbfgraphefgraphlfgraph{fgraphifgraph}fgraph,fgraph fgraphofgraphlfgraphdfgraph_fgraphbfgraphefgraphlfgraph{fgraphifgraph}fgraph,fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphtfgraphofgraphlfgraph)fgraph
+fgraph	fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph fgraph=fgraph fgraph0fgraph;fgraph
+fgraph	fgraphbfgraphrfgraphefgraphafgraphkfgraph;fgraph
+fgraph fgraph fgraph fgraph fgraph fgraph fgraphefgraphnfgraphdfgraph
+fgraph fgraph fgraph fgraph fgraphefgraphnfgraphdfgraph
+fgraph fgraph fgraphefgraphnfgraphdfgraph
+fgraph
+fgraph fgraph fgraphifgraphffgraph fgraph~fgraphcfgraphofgraphnfgraphvfgraphefgraphrfgraphgfgraphefgraphdfgraph
+fgraph fgraph fgraph fgraph fgraphofgraphlfgraphdfgraph_fgraphmfgraphsfgraphgfgraph fgraph=fgraph fgraphmfgraphsfgraphgfgraph;fgraph
+fgraph fgraph fgraph fgraph fgraph%fgraph fgraphefgraphafgraphcfgraphhfgraph fgraphnfgraphofgraphdfgraphefgraph fgraphsfgraphefgraphnfgraphdfgraphsfgraph fgraphafgraph fgraphmfgraphsfgraphgfgraph fgraphtfgraphofgraph fgraphefgraphafgraphcfgraphhfgraph fgraphofgraphffgraph fgraphifgraphtfgraphsfgraph fgraphnfgraphefgraphifgraphgfgraphhfgraphbfgraphofgraphrfgraphsfgraph
+fgraph fgraph fgraph fgraph fgraphffgraphofgraphrfgraph fgraphifgraph=fgraph1fgraph:fgraphnfgraphdfgraphofgraphmfgraphsfgraph
+fgraph fgraph fgraph fgraph fgraph fgraph fgraphnfgraphbfgraphrfgraphsfgraph fgraph=fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphnfgraphbfgraphrfgraphsfgraph{fgraphifgraph}fgraph;fgraph
+fgraph fgraph fgraph fgraph fgraph fgraph fgraphffgraphofgraphrfgraph fgraphjfgraph=fgraphnfgraphbfgraphrfgraphsfgraph(fgraph:fgraph)fgraph'fgraph
+fgraph	fgraph%fgraph fgraphmfgraphufgraphlfgraphtfgraphifgraphpfgraphlfgraphyfgraph fgraphafgraphlfgraphlfgraph fgraphifgraphnfgraphcfgraphofgraphmfgraphifgraphnfgraphgfgraph fgraphmfgraphsfgraphgfgraphsfgraph fgraphefgraphxfgraphcfgraphefgraphpfgraphtfgraph fgraphffgraphrfgraphofgraphmfgraph fgraphjfgraph
+fgraph	fgraphtfgraphefgraphmfgraphpfgraph fgraph=fgraph fgraphpfgraphrfgraphofgraphdfgraph_fgraphofgraphffgraph_fgraphmfgraphsfgraphgfgraph{fgraphifgraph}fgraph;fgraph
+fgraph	fgraphtfgraphefgraphmfgraphpfgraph fgraph=fgraph fgraphdfgraphifgraphvfgraphifgraphdfgraphefgraph_fgraphbfgraphyfgraph_fgraphpfgraphofgraphtfgraph(fgraphtfgraphefgraphmfgraphpfgraph,fgraph fgraphofgraphlfgraphdfgraph_fgraphmfgraphsfgraphgfgraph{fgraphjfgraph,fgraphifgraph}fgraph)fgraph;fgraph
+fgraph	fgraph%fgraph fgraphsfgraphefgraphnfgraphdfgraph fgraphmfgraphsfgraphgfgraph fgraphffgraphrfgraphofgraphmfgraph fgraphifgraph fgraphtfgraphofgraph fgraphjfgraph
+fgraph	fgraphtfgraphefgraphmfgraphpfgraph fgraph=fgraph fgraphmfgraphufgraphlfgraphtfgraphifgraphpfgraphlfgraphyfgraph_fgraphbfgraphyfgraph_fgraphpfgraphofgraphtfgraph(fgraphtfgraphefgraphmfgraphpfgraph,fgraph fgraphlfgraphofgraphcfgraphafgraphlfgraph_fgraphkfgraphefgraphrfgraphnfgraphefgraphlfgraph{fgraphifgraph}fgraph)fgraph;fgraph
+fgraph	fgraphifgraphffgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphmfgraphafgraphxfgraphifgraphmfgraphifgraphzfgraphefgraph
+fgraph	fgraph fgraph fgraphtfgraphefgraphmfgraphpfgraph2fgraph fgraph=fgraph fgraphmfgraphafgraphrfgraphgfgraphifgraphnfgraphafgraphlfgraphifgraphzfgraphefgraph_fgraphpfgraphofgraphtfgraph_fgraphmfgraphafgraphxfgraph(fgraphtfgraphefgraphmfgraphpfgraph,fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphsfgraphefgraphpfgraphsfgraphefgraphtfgraph{fgraphifgraph,fgraphjfgraph}fgraph)fgraph;fgraph
+fgraph	fgraphefgraphlfgraphsfgraphefgraph
+fgraph	fgraph fgraph fgraphtfgraphefgraphmfgraphpfgraph2fgraph fgraph=fgraph fgraphmfgraphafgraphrfgraphgfgraphifgraphnfgraphafgraphlfgraphifgraphzfgraphefgraph_fgraphpfgraphofgraphtfgraph(fgraphtfgraphefgraphmfgraphpfgraph,fgraph fgraphefgraphnfgraphgfgraphifgraphnfgraphefgraph.fgraphffgraphgfgraphrfgraphafgraphpfgraphhfgraph.fgraphsfgraphefgraphpfgraphsfgraphefgraphtfgraph{fgraphifgraph,fgraphjfgraph}fgraph)fgraph;fgraph
+fgraph	fgraphefgraphnfgraphdfgraph
+fgraph	fgraphmfgraphsfgraphgfgraph{fgraphifgraph,fgraphjfgraph}fgraph fgraph=fgraph fgraphnfgraphofgraphrfgraphmfgraphafgraphlfgraphifgraphzfgraphefgraph_fgraphpfgraphofgraphtfgraph(fgraphtfgraphefgraphmfgraphpfgraph2fgraph)fgraph;fgraph
+fgraph fgraph fgraph fgraph fgraph fgraph fgraphefgraphnfgraphdfgraph
+fgraph fgraph fgraph fgraph fgraphefgraphnfgraphdfgraph
+fgraph fgraph fgraphefgraphnfgraphdfgraph
+fgraph
+fgraph fgraph fgraphifgraphtfgraphefgraphrfgraph fgraph=fgraph fgraphifgraphtfgraphefgraphrfgraph fgraph+fgraph fgraph1fgraph;fgraph
+fgraphefgraphnfgraphdfgraph
+fgraph
+gdl
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/private/parallel_protocol.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,86 @@
+function [bel, niter] = parallel_protocol(engine, evidence, pot_type, local_kernel, msg)
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes;
+onodes = find(~isemptycell(evidence));
+
+ndoms = length(engine.gdl.doms);
+prod_of_msg = cell(1, ndoms);
+bel = cell(1, ndoms);
+old_bel = cell(1, ndoms);
+
+converged = 0;
+iter = 1;
+while ~converged & (iter <= engine.max_iter)
+  
+  % each node multiplies all its incoming msgs and computes its local belief
+  old_bel = bel;
+  for i=1:ndoms
+    prod_of_msg{i} = mk_initial_pot(pot_type, engine.gdl.doms{i}, ns, bnet.cnodes, onodes);
+    nbrs = engine.gdl.nbrs{i};
+    for j=nbrs(:)'
+      prod_of_msg{i} = multiply_by_pot(prod_of_msg{i}, msg{j,i});
+    end
+    bel{i} = normalize_pot(multiply_by_pot(local_kernel{i}, prod_of_msg{i}));
+  end
+
+  if ~isempty(engine.fid)
+    for i=1:ndoms
+      tmp = pot_to_marginal(bel{i});
+      %fprintf(engine.fid, '%9.7f ', tmp.T(1));
+      fprintf(engine.fid, '%9.7f ', tmp.U(1));
+    end
+    %fprintf(engine.fid, '  U ');
+    %for i=1:ndoms
+    %  tmp = pot_to_marginal(bel{i});
+    %  fprintf(engine.fid, '%9.7f ', tmp.U(1));
+    %end
+    fprintf(engine.fid, '\n');
+  end
+
+  % converged?
+  if iter==1
+    converged = 0;
+  else
+    converged = 1;
+    for i=1:ndoms
+      if ~approxeq_pot(bel{i}, old_bel{i}, engine.tol)
+	converged = 0;
+	break;
+      end
+    end
+  end
+
+  if ~converged
+    old_msg = msg;
+    % each node sends a msg to each of its neighbors
+    for i=1:ndoms
+      nbrs = engine.gdl.nbrs{i};
+      for j=nbrs(:)'
+	% multiply all incoming msgs except from j
+	temp = prod_of_msg{i};
+	temp = divide_by_pot(temp, old_msg{j,i});
+	% send msg from i to j
+	temp = multiply_by_pot(temp, local_kernel{i});
+	temp2 = marginalize_pot(temp, engine.gdl.sepset{i,j}, engine.maximize);
+	msg{i,j} = normalize_pot(temp2);
+      end
+    end
+  end
+
+  iter = iter + 1;
+end
+
+
+niter = iter-1;
+
+if 0
+for i=1:ndoms
+  prod_of_msg{i} = mk_initial_pot(pot_type, engine.gdl.doms{i}, ns, bnet.cnodes, onodes);
+  nbrs = engine.gdl.nbrs{i};
+  for j=nbrs(:)'
+    prod_of_msg{i} = multiply_by_pot(prod_of_msg{i}, msg{j,i});
+  end
+  bel{i} = normalize_pot(multiply_by_pot(local_kernel{i}, prod_of_msg{i}));
+end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_inf_engine/private/tree_protocol.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,48 @@
+function bel = tree_protocol(engine, evidence, pot_type, local_kernel, msg)
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes;
+onodes = find(~isemptycell(evidence));
+
+ndoms = length(engine.gdl.doms);
+prod_of_msg = cell(1, ndoms);
+bel = cell(1, ndoms);
+  
+% collect to root (node to parents)
+for n=engine.postorder
+  % absorb msgs from children
+  prod_of_msg{n} = mk_initial_pot(pot_type, engine.gdl.doms{n}, ns, bnet.cnodes, onodes);
+  for c=children(engine.tree, n)
+    prod_of_msg{n} = multiply_by_pot(prod_of_msg{n}, msg{c,n});
+  end
+  % send msg to parents
+  for p=parents(engine.tree, n)
+    if iter==1
+      temp = prod_of_msg{n};
+    else
+      temp = divide_by_pot(prod_of_msg{n}, old_msg{p,n});
+    end
+    temp = multiply_by_pot(temp, local_kernel{n});
+    temp2 = marginalize_pot(temp, engine.gdl.sepset{n,p}, engine.maximize);
+    %fprintf('%d sends %d\n', n, p);
+    msg{n,p} = normalize_pot(temp2);
+  end
+end
+
+% distribute from root (node to children)
+for n=engine.preorder
+  % absorb from parents
+  %prod_of_msg{n} = mk_initial_pot(pot_type, doms{n}, ns, cnodes, onodes);
+  for p=parents(engine.tree, n)
+    prod_of_msg{n} = multiply_by_pot(prod_of_msg{n}, msg{p,n});
+  end
+  bel{n} = normalize_pot(multiply_pots(prod_of_msg{n}, local_kernel{n}));
+  % send msg to children
+  for c=children(engine.tree, n)
+    temp = divide_by_pot(prod_of_msg{n}, msg{c,n});
+    temp = multiply_by_pot(temp, local_kernel{n});
+    temp2 = marginalize_pot(temp, engine.gdl.sepset{n,c}, engine.maximize);
+    %fprintf('%d sends %d\n', n, c);
+    msg{n,c} = normalize_pot(temp2);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/belprop_mrf2_inf_engine.m/1.1.1.1/Fri Jan  3 22:01:56 2003//
+/bp_mrf2.m/1.1.1.1/Mon Jan  5 01:23:34 2004//
+/enter_soft_evidence.m/1.1.1.1/Thu Jan  2 17:29:54 2003//
+/find_mpe.m/1.1.1.1/Thu Jan  2 17:49:18 2003//
+/marginal_nodes.m/1.1.1.1/Tue Dec 31 21:24:30 2002//
+/set_params.m/1.1.1.1/Thu Jan  2 17:28:56 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/belprop_mrf2_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,46 @@
+function engine = belprop_mrf2_inf_engine(mrf2, varargin) 
+% BELPROP_MRF2_INF_ENGINE Belief propagation for MRFs with discrete pairwise potentials
+% engine = belprop_mrf2_inf_engine(mrf2, ...)
+%
+% This is like belprop_inf_engine, except it is designed for mrf2, so is much faster.
+%
+% [ ... ] = belprop_mrf2_inf_engine(..., 'param1',val1, 'param2',val2, ...)
+% allows you to specify optional parameters as name/value pairs.
+% Parameters modifying behavior of enter_evidence are below [default value in brackets]
+%
+% max_iter - max. num. iterations [ 5*nnodes]
+% momentum - weight assigned to old message in convex combination
+%            (useful for damping oscillations) [0]
+% tol      - tolerance used to assess convergence [1e-3]
+% verbose - 1 means print error at every iteration [0]
+%
+% Parameters can be changed later using set_params 
+
+
+% The advantages of pairwise potentials are
+% (1) we can compute messages using vector-matrix multiplication
+% (2) we can easily specify the parameters: one potential per edge
+% In contrast, potentials on larger cliques are more complicated to deal with.
+
+
+nnodes = length(mrf2.adj_mat);
+
+[engine.max_iter, engine.momentum, engine.tol, engine.verbose] = ...
+    process_options(varargin, 'max_iter', [], 'momentum', 0, 'tol', 1e-3, ...
+		   'verbose', 0);
+
+if isempty(engine.max_iter) % no user supplied value, so compute default
+  engine.max_iter = 5*nnodes;
+  %if acyclic(mrf2.adj_mat, 0) --- can be very slow!
+  %  engine.max_iter = nnodes;
+  %else
+  %  engine.max_iter = 5*nnodes;
+  %end
+end
+
+engine.bel = cell(1, nnodes); % store results of enter_evidence here
+engine.mrf2 = mrf2;
+
+engine = class(engine, 'belprop_mrf2_inf_engine');
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/bp_mrf2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,209 @@
+function [new_bel, niter, new_msg, edge_id, nstates] = bp_mrf2_general(adj_mat, pot, local_evidence, varargin)
+% BP_MRF2_GENERAL Belief propagation on an MRF with pairwise potentials
+% function [bel, niter] = bp_mrf2_general(adj_mat, pot, local_evidence, varargin)
+%
+% Input:
+% adj_mat(i,j) = 1 iff there is an edge between nodes i and j
+% pot(ki,kj,i,j) or pot{i,j}(ki,kj) = potential on edge between nodes i,j
+%   If the potentials on all edges are the same,
+%   you can just pass in 1 array, pot(ki,kj)
+% local_evidence(state, node) or local_evidence{i}(k) = Pr(observation at node i | Xi=k)
+%
+% Use cell arrays if the hidden nodes do not all have the same number of values.
+%
+% Output:
+% bel(k,i) or bel{i}(k) = P(Xi=k|evidence)
+% niter contains the number of iterations used 
+%
+% [ ... ] = bp_mrf2(..., 'param1',val1, 'param2',val2, ...)
+% allows you to specify optional parameters as name/value pairs.
+% Parameters names are below [default value in brackets]
+%
+% max_iter - max. num. iterations [ 5*nnodes]
+% momentum - weight assigned to old message in convex combination
+%            (useful for damping oscillations) - currently ignored i[0]
+% tol      - tolerance used to assess convergence [1e-3]
+% maximize - 1 means use max-product, 0 means use sum-product [0]
+% verbose - 1 means print error at every iteration [0]
+%
+% fn - name of function to call at end of every iteration [ [] ]
+% fnargs - we call feval(fn, bel, iter, fnargs{:}) [ [] ]
+
+nnodes = length(adj_mat);
+
+[max_iter, momentum, tol, maximize, verbose, fn, fnargs] = ...
+    process_options(varargin, 'max_iter', 5*nnodes, 'momentum', 0, ...
+		    'tol', 1e-3, 'maximize', 0, 'verbose', 0, ...
+		    'fn', [], 'fnargs', []);
+
+if iscell(local_evidence)
+  use_cell = 1;
+else
+  use_cell = 0;
+  [nstates nnodes] = size(local_evidence);
+end
+
+if iscell(pot)
+  tied_pot = 0;
+else
+  tied_pot = (ndims(pot)==2);
+end
+
+
+% give each edge a unique number
+ndx = find(adj_mat);
+nedges = length(ndx);
+edge_id = zeros(1, nnodes*nnodes);
+edge_id(ndx) = 1:nedges; 
+edge_id = reshape(edge_id, nnodes, nnodes);
+
+% initialise messages
+if use_cell
+  prod_of_msgs = cell(1, nnodes);
+  old_bel = cell(1, nnodes);
+  nstates = zeros(1, nnodes);
+  old_msg = cell(1, nedges);
+  for i=1:nnodes
+    nstates(i) = length(local_evidence{i});
+    prod_of_msgs{i} = local_evidence{i};
+    old_bel{i} = local_evidence{i};
+  end
+  for i=1:nnodes
+    nbrs = find(adj_mat(:,i));
+    for j=nbrs(:)'
+      old_msg{edge_id(i,j)} = normalise(ones(nstates(j),1));
+    end
+  end
+else
+  prod_of_msgs = local_evidence;
+  old_bel = local_evidence;
+  %old_msg = zeros(nstates, nnodes, nnodes); 
+  old_msg = zeros(nstates, nedges); 
+  m = normalise(ones(nstates,1));
+  for i=1:nnodes
+    nbrs = find(adj_mat(:,i));
+    for j=nbrs(:)'
+      old_msg(:, edge_id(i,j)) = m;
+      %old_msg(:,i,j) = m;
+    end
+  end
+end
+
+
+converged = 0;
+iter = 1;
+
+while ~converged & (iter <= max_iter)
+  
+  % each node sends a msg to each of its neighbors
+  for i=1:nnodes
+    nbrs = find(adj_mat(i,:));
+    for j=nbrs(:)'
+      if tied_pot
+	pot_ij = pot;
+      else
+	if iscell(pot)
+	  pot_ij = pot{i,j};
+	else
+	  pot_ij = pot(:,:,i,j);
+	end
+      end
+      pot_ij = pot_ij'; % now pot_ij(xj, xi) 
+      % so pot_ij * msg(xi) = sum_xi pot(xj,xi) msg(xi) = f(xj)
+
+      if 1
+	% Compute temp = product of all incoming msgs except from j
+	% by dividing out old msg from j from the product of all msgs sent to i
+	if use_cell
+	  temp = prod_of_msgs{i};
+	  m = old_msg{edge_id(j,i)};
+	else
+	  temp = prod_of_msgs(:,i);
+	  m = old_msg(:, edge_id(j,i));
+	end
+	if any(m==0)
+	  fprintf('iter=%d, send from i=%d to j=%d\n', iter, i, j);
+	  keyboard
+	end
+	m = m + (m==0); % valid since m(k)=0 => temp(k)=0, so can replace 0's with anything
+	temp = temp ./ m;
+	temp_div = temp;
+      end
+      
+      if 1
+	% Compute temp = product of all incoming msgs except from j in obvious way
+	if use_cell
+	  %temp = ones(nstates(i),1);
+	  temp = local_evidence{i};
+	  for k=nbrs(:)'
+	    if k==j, continue, end;
+	    temp = temp .* old_msg{edge_id(k,i)};
+	  end
+	else
+	  %temp = ones(nstates,1);
+	  temp = local_evidence(:,i);
+	  for k=nbrs(:)'
+	    if k==j, continue, end;
+	    temp = temp .* old_msg(:, edge_id(k,i));
+	  end
+	end
+      end
+      %assert(approxeq(temp, temp_div))
+      assert(approxeq(normalise(pot_ij * temp), normalise(pot_ij * temp_div)))
+	
+      if maximize
+	newm = max_mult(pot_ij, temp); % bottleneck
+      else
+	newm = pot_ij * temp;
+      end
+      newm = normalise(newm);
+      if use_cell
+	new_msg{edge_id(i,j)} = newm;
+      else
+	new_msg(:, edge_id(i,j)) = newm;
+      end
+    end % for j 
+  end % for i
+  old_prod_of_msgs = prod_of_msgs;
+  
+  % each node multiplies all its incoming msgs and computes its local belief
+  if use_cell
+    for i=1:nnodes
+      nbrs = find(adj_mat(:,i));
+      prod_of_msgs{i} = local_evidence{i};
+      for j=nbrs(:)'
+	prod_of_msgs{i} = prod_of_msgs{i} .* new_msg{edge_id(j,i)};
+      end
+      new_bel{i} = normalise(prod_of_msgs{i});
+    end
+    err = abs(cat(1,new_bel{:}) - cat(1, old_bel{:}));
+  else
+    for i=1:nnodes
+      nbrs = find(adj_mat(:,i));
+      prod_of_msgs(:,i) = local_evidence(:,i);
+      for j=nbrs(:)'
+	prod_of_msgs(:,i) = prod_of_msgs(:,i) .* new_msg(:,edge_id(j,i));
+      end
+      new_bel(:,i) = normalise(prod_of_msgs(:,i));
+    end
+    err = abs(new_bel(:) - old_bel(:));
+  end
+  converged = all(err < tol);
+  if verbose, fprintf('error at iter %d = %f\n', iter, sum(err)); end
+  if ~isempty(fn)
+    if isempty(fnargs)
+      feval(fn, new_bel);
+    else
+      feval(fn, new_bel, iter, fnargs{:});
+    end
+  end
+  
+  iter = iter + 1;
+  old_msg = new_msg;
+  old_bel = new_bel;
+end % while
+
+niter = iter-1;
+
+fprintf('converged in %d iterations\n', niter);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/enter_soft_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function [engine, ll, niter] = enter_soft_evidence(engine, local_evidence)
+% ENTER_SOFT_EVIDENCE Propagate evidence using belief propagation
+% [engine, ll, niter] = enter_soft_evidence(engine, local_evidence)
+%
+% local_evidence{i}(j) = Pr(observation at node i | S(i)=j)
+%
+% The log-likelihood is not computed; ll = 0.
+% niter contains the number of iterations used 
+
+ll = 0;
+mrf2 = engine.mrf2;
+[bel, niter] = bp_mrf2(mrf2.adj_mat, mrf2.pot, local_evidence, ...
+		       'max_iter', engine.max_iter, 'momentum', engine.momentum, ...
+		       'tol', engine.tol, 'maximize', 0, 'verbose', engine.verbose);
+engine.bel = bel;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/find_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function mpe = find_mpe(engine, local_evidence)
+% FIND_MPE Find the most probable explanation of the data  
+% function mpe = find_mpe(engine, local_evidence
+%
+% local_evidence{i}(j) = Pr(observation at node i | S(i)=j)
+%
+% This finds the marginally most likely value for each hidden node.
+% It may give inconsistent results if there are ties.
+
+[mpe, niter] = bp_mpe_mrf2(engine.mrf2.adj_mat, engine.mrf2.pot, local_evidence, ...
+			   'max_iter', engine.max_iter, 'momentum', engine.momentum, ...
+			   'tol', engine.tol);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function marginal = marginal_nodes(engine, query)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (belprop)
+% marginal = marginal_nodes(engine, query)
+%
+% query must be a single node
+
+if length(query)>1
+  error('can only handle single node marginals')
+end
+marginal = engine.bel{query};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@belprop_mrf2_inf_engine/set_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function engine = set_params(engine, varargin)
+% SET_PARAMS Modify parameters of the inference engine
+% engine = set_params(engine, 'param1',val1, 'param2',val2, ...)
+%
+% Parameter names are listed below.
+%
+% max_iter - max. num. iterations 
+% momentum - weight assigned to old message in convex combination
+%            (useful for damping oscillations) 
+% tol      - tolerance used to assess convergence
+% verbose - 1 means print error at every iteration [0]
+
+[engine.max_iter, engine.momentum, engine.tol, engine.verbose] = ...
+    process_options('max_iter', engine.max_iter, 'momentum', engine.momentum, ...
+		    'tol', engine.tol, 'verbose', engine.verbose);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@cond_gauss_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+/cond_gauss_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@cond_gauss_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@cond_gauss_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@cond_gauss_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@cond_gauss_inf_engine/cond_gauss_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+function engine = cond_gauss_inf_engine(bnet)
+% COND_GAUSS_INF_ENGINE Conditional Gaussian inference engine
+% engine = cond_gauss_inf_engine(bnet)
+%
+% Enumerates all the discrete roots, and runs jtree on the remaining Gaussian nodes.
+
+dnodes = mysetdiff(1:length(bnet.dag), bnet.cnodes);
+
+%onodes = dnodes; % all the discrete ndoes will be observed
+%engine.sub_engine = jtree_inf_engine(bnet, onodes);
+bnet2 = bnet;
+bnet2.observed = dnodes;
+engine.sub_engine = jtree_inf_engine(bnet2);
+
+% This is where we will store the results between enter_evidence and marginal_nodes
+engine.T = [];
+engine.mu = [];
+engine.Sigma = [];
+engine.joint_dmarginal = [];
+engine.onodes = []; % needed for marginal_nodes
+engine.evidence = []; % needed for marginal_nodes add_ev
+
+engine = class(engine, 'cond_gauss_inf_engine', inf_engine(bnet));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@cond_gauss_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (cond_gauss)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value (scalar or column vector)
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes(:);
+observed = ~isemptycell(evidence);
+onodes = find(observed);
+hnodes = find(isemptycell(evidence));
+engine.evidence = evidence;
+
+% check there are no C->D links where C is hidden
+pot_type = determine_pot_type(bnet, onodes);
+
+dhid = myintersect(hnodes, bnet.dnodes);
+S = prod(ns(dhid));
+T = zeros(S,1);
+
+N = length(bnet.dag);
+mu = cell(1,N);
+Sigma = cell(1,N); 
+cobs = myintersect(bnet.cnodes, onodes);
+chid = myintersect(bnet.cnodes, hnodes);
+ens = ns;
+ens(cobs) = 0;
+for j=chid(:)'
+  mu{j} = zeros(ens(j), S);
+  Sigma{j} = zeros(ens(j), ens(j), S);
+end
+ 
+for i=1:S
+  dvals = ind2subv(ns(dhid), i);
+  evidence(dhid) = num2cell(dvals);
+  [sub_engine, loglik] = enter_evidence(engine.sub_engine, evidence);
+  for j=chid(:)'
+    m = marginal_nodes(sub_engine, j);
+    mu{j}(:,i) = m.mu;
+    Sigma{j}(:,:,i) = m.Sigma;
+  end
+  T(i) = exp(loglik);
+end
+
+[T, lik] = normalise(T);
+loglik = log(lik);
+
+engine.T = T;
+engine.mu = mu;
+engine.Sigma = Sigma;
+
+dnodes = bnet.dnodes;
+dobs = myintersect(dnodes, onodes);
+ens(dobs) = 1;
+engine.joint_dmarginal = dpot(dnodes, ens(dnodes), myreshape(engine.T, ens(dnodes)));
+
+engine.onodes = onodes;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@cond_gauss_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+function marginal = marginal_nodes(engine, query, add_ev)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (cond_gauss)
+% marginal = marginal_nodes(engine, query, add_ev)
+%
+% 'query' must be a singleton set
+% add_ev is an optional argument; if 1, we will "inflate" the marginal of observed nodes
+% to their original size, adding 0s to the positions which contradict the evidence
+
+if nargin < 3, add_ev = 0; end
+
+if length(query) ~= 1
+  error('cond_gauss_inf_engine can only handle marginal queries on single nodes')
+end
+j = query;
+bnet = bnet_from_engine(engine);
+
+if myismember(j, bnet.cnodes)
+  if ~myismember(j, engine.onodes)
+    [m, C] = collapse_mog(engine.mu{j}, engine.Sigma{j}, engine.T);    
+    marginal.mu = m;
+    marginal.Sigma = C;
+    marginal.T = 1.0; % single mixture component
+  else
+    marginal.mu = engine.evidence{j};
+    k = bnet.node_sizes(j);
+    marginal.Sigma = zeros(k,k);
+    marginal.T = 1.0; % since P(E|E)=1
+  end
+else
+  marginal = pot_to_marginal(marginalize_pot(engine.joint_dmarginal, j));
+  if add_ev
+    marginal = add_ev_to_dmarginal(marginal, engine.evidence, bnet.node_sizes);
+  end
+end
+
+marginal.domain = query;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@enumerative_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enumerative_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@enumerative_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@enumerative_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@enumerative_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@enumerative_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function [engine, loglik] = enter_evidence(engine, evidence)
+% ENTER_EVIDENCE Add the specified evidence to the network (enumerative_inf)
+% [engine, loglik] = enter_evidence(engine, evidence)
+%
+% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value (scalar or column vector)
+
+engine.evidence = evidence;
+if nargout == 2
+  [m, loglik] = marginal_nodes(engine, []);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@enumerative_inf_engine/enumerative_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function engine = enumerative_inf_engine(bnet)
+% ENUMERATIVE_INF_ENGINE Inference engine for fully discrete BNs that uses exhaustive enumeration.
+% engine = enumerative_inf_engine(bnet)
+
+
+assert(isempty(bnet.cnodes));
+
+% This is where we store stuff between enter_evidence and marginal_nodes
+engine.evidence = [];
+
+engine = class(engine, 'enumerative_inf_engine', inf_engine(bnet));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@enumerative_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,41 @@
+function [marginal, loglik] = marginal_nodes(engine, query)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (enumerative_inf)
+% [marginal, loglik] = marginal_nodes(engine, query)
+
+
+if isempty(query) & nargout < 2
+  marginal.T = 1;
+  marginal.domain = [];
+  return;
+end
+
+evidence = engine.evidence;
+bnet = bnet_from_engine(engine);
+assert(isempty(bnet.cnodes));
+n = length(bnet.dag);
+observed = ~isemptycell(evidence);
+vals = cat(1,evidence{observed});
+vals = vals(:)';
+ns = bnet.node_sizes;
+
+sz = ns(query);
+T = 0*myones(sz);
+p = 0;
+for i=1:prod(ns)
+  inst = ind2subv(ns, i); % i'th instantiation
+  if isempty(vals) | inst(observed) == vals % agrees with evidence
+    prob = exp(log_lik_complete(bnet, num2cell(inst(:))));
+    p = p + prob;
+    v = inst(query);
+    j = subv2ind(sz, v);
+    T(j) = T(j) + prob;
+  end
+end
+
+[T, lik] = normalise(T);
+lik = p;
+loglik = log(lik);
+
+Tsmall = shrink_obs_dims_in_table(T, query, evidence);
+marginal.domain = query;
+marginal.T = Tsmall;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gaussian_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/gaussian_inf_engine.m/1.1.1.1/Fri May 14 01:13:26 2004//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gaussian_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@gaussian_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gaussian_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gaussian_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,46 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (gaussian_inf_engine)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value (scalar or column vector)
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes;
+O = find(~isemptycell(evidence));
+H = find(isemptycell(evidence));
+vals = cat(1, evidence{O});
+
+% Compute Pr(H|o)
+[Hmu, HSigma, loglik] = condition_gaussian(engine.mu, engine.Sigma, H, O, vals(:), ns);
+
+engine.Hmu = Hmu;
+engine.HSigma = HSigma;
+engine.hnodes = H;
+
+%%%%%%%%
+
+function [mu2, Sigma2, loglik] = condition_gaussian(mu, Sigma, X, Y, y, ns)
+% CONDITION_GAUSSIAN Compute Pr(X|Y=y) where X and Y are jointly Gaussian.
+% [mu2, Sigma2, ll] = condition_gaussian(mu, Sigma, X, Y, y, ns)
+
+if isempty(y)
+  mu2 = mu;
+  Sigma2 = Sigma;
+  loglik = 0;
+  return;
+end
+
+use_log = 1;
+
+if length(Y)==length(mu) % instantiating every variable
+  mu2 = y;
+  Sigma2 = zeros(length(y));
+  loglik = gaussian_prob(y, mu, Sigma, use_log);
+  return;
+end
+
+[muX, muY, SXX, SXY, SYX, SYY] = partition_matrix_vec(mu, Sigma, X, Y, ns);
+K = SXY*inv(SYY);
+mu2 = muX + K*(y-muY);
+Sigma2 = SXX - K*SYX;
+loglik = gaussian_prob(y, muY, SYY, use_log);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gaussian_inf_engine/gaussian_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function engine = gaussian_inf_engine(bnet)
+% GAUSSIAN_INF_ENGINE Computes the joint multivariate Gaussian corresponding to the bnet
+% engine = gaussian_inf_engine(bnet)
+%
+% For details on how to compute the joint Gaussian from the bnet, see
+% - "Gaussian Influence Diagrams", R. Shachter and C. R. Kenley, Management Science, 35(5):527--550, 1989.
+% Once we have the Gaussian, we can apply the standard formulas for conditioning and marginalization.
+
+assert(isequal(bnet.cnodes, 1:length(bnet.dag)));
+
+[W, D, mu] = extract_params_from_gbn(bnet);
+U = inv(eye(size(W)) - W')';
+Sigma = U' * D * U;
+
+engine.mu = mu;
+engine.Sigma = Sigma;
+%engine.logp = log(normal_coef(Sigma));
+
+% This is where we will store the results between enter_evidence and marginal_nodes  
+engine.Hmu = [];
+engine.HSigma = [];
+engine.hnodes = [];
+
+engine = class(engine, 'gaussian_inf_engine', inf_engine(bnet));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gaussian_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function marginal = marginal_nodes(engine, query)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (gaussian)
+% marginal = marginal_nodes(engine, query)
+
+% Compute sum_{Hsum} Pr(Hkeep, Hsum | o)
+H = engine.hnodes;
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes;
+Hkeep = myintersect(H, query);
+Hsum = mysetdiff(H, Hkeep);
+
+[marginal.mu, marginal.Sigma] = marginalize_gaussian(engine.Hmu, engine.HSigma, Hkeep, Hsum, ns);
+marginal.domain = query;
+marginal.T = 1;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gaussian_inf_engine/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/extract_params_from_gbn.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gaussian_inf_engine/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@gaussian_inf_engine/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gaussian_inf_engine/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gaussian_inf_engine/private/extract_params_from_gbn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function [B,D,mu] = extract_params_from_gbn(bnet)
+% Extract all the local parameters of each Gaussian node, and collect them into global matrices.
+% [B,D,mu] = extract_params_from_gbn(bnet)
+%
+% B(i,j) is a block matrix that contains the transposed weight matrix from node i to node j.
+% D(i,i) is a block matrix that contains the noise covariance matrix for node i.
+% mu(i) is a block vector that contains the shifted noise mean for node i.
+
+% In Shachter's model, the mean of each node in the global gaussian is
+% the same as the node's local unconditional mean.
+% In Alag's model (which we use), the global mean gets shifted.
+
+
+num_nodes = length(bnet.dag);
+bs = bnet.node_sizes(:); % bs = block sizes
+N = sum(bs); % num scalar nodes
+
+B = zeros(N,N);
+D = zeros(N,N);
+mu = zeros(N,1);
+
+for i=1:num_nodes % in topological order
+  ps = parents(bnet.dag, i);
+  e = bnet.equiv_class(i);
+  %[m, Sigma, weights] = extract_params_from_CPD(bnet.CPD{e});
+  s = struct(bnet.CPD{e}); % violate privacy of object
+  m = s.mean; Sigma = s.cov; weights = s.weights;
+  if length(ps) == 0
+    mu(block(i,bs)) = m;
+  else
+    mu(block(i,bs)) = m + weights *  mu(block(ps,bs));
+  end
+  B(block(ps,bs), block(i,bs)) = weights';
+  D(block(i,bs), block(i,bs)) = Sigma;
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/gibbs_sampling_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+function [engine, loglik] = enter_evidence(engine, evidence)
+% ENTER_EVIDENCE Add the specified evidence to the network (gibbs_sampling_inf_engine)
+% [engine, loglik] = enter_evidence(engine, evidence)
+%
+% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value 
+%
+% loglik is not computed... we just return a 0 value
+
+bnet = bnet_from_engine(engine);
+
+engine.hnodes = find(isemptycell(evidence));
+engine.onodes = mysetdiff(1:length(evidence), engine.hnodes);
+
+engine.evidence = zeros(engine.slice_size, 1);
+
+% Reset all counts since they are no longer valid
+engine.marginal_counts = {};
+%engine.state = sample_bnet (bnet, 1, 0);
+engine.state = cell2num(sample_bnet(bnet));
+
+% For speed, we use a normal (not cell) array.  We're making use of
+% the current restriction to discrete nodes.
+for i = engine.onodes
+    engine.evidence(i) = evidence{i};
+end
+
+loglik = 0;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/gibbs_sampling_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,104 @@
+function engine = gibbs_sampling_inf_engine(bnet, varargin)
+% GIBBS_SAMPLING_INF_ENGINE
+%
+% engine = gibbs_sampling_inf_engine(bnet, ...) 
+%
+% Optional parameters [default in brackets]
+% 'burnin' - How long before you start using the samples [100].
+% 'gap' - how often you use the samples in the estimate [1].
+% 'T' - number of samples [1000]
+%   i.e, number of node flips (so, for
+%   example if there are 10 nodes in the bnet, and T is 1000, each
+%   node will get flipped 100 times (assuming a deterministic schedule)) 
+%   The total running time is proportional to burnin + T*gap.
+%
+% 'order' - if the sampling schedule is deterministic, use this
+% parameter to specify the order in which nodes are sampled.
+% Order is allowed to include multiple copies of nodes, which is
+% useful if you want to, say, focus sampling on particular nodes.
+% Default is to use a deterministic schedule that goes through the
+% nodes in order.
+%
+% 'sampling_dist' - when using a stochastic sampling method, at
+% each step the node to sample is chosen according to this
+% distribution (may be unnormalized)
+% 
+% The sampling_dist and order parameters shouldn't both be used,
+% and this will cause an assert.
+%
+%
+% Written by "Bhaskara Marthi" <bhaskara@cs.berkeley.edu> Feb 02.
+
+
+engine.burnin = 100;
+engine.gap = 1;
+engine.T = 1000; 
+use_default_order = 1;
+engine.deterministic = 1;
+engine.order = {};
+engine.sampling_dist = {};
+
+if nargin >= 2
+  args = varargin;
+  nargs = length(args);
+  for i = 1:2:nargs
+    switch args{i}
+     case 'burnin'
+      engine.burnin = args{i+1};
+     case 'gap'
+      engine.gap = args{i+1};
+     case 'T'
+      engine.T = args{i+1};
+     case 'order'
+      assert (use_default_order);
+      use_default_order = 0;
+      engine.order = args{i+1};
+     case 'sampling_dist'
+      assert (use_default_order);
+      use_default_order = 0;
+      engine.deterministic = 0;
+      engine.sampling_dist = args{i+1};
+     otherwise
+      error(['unrecognized parameter to gibbs_sampling_inf_engine']);
+    end
+  end
+end
+
+engine.slice_size = size(bnet.dag, 2);
+if (use_default_order)
+  engine.order = 1:engine.slice_size;
+end
+engine.hnodes = [];
+engine.onodes = [];
+engine.evidence = [];
+engine.state = [];
+engine.marginal_counts = {};
+
+% Precompute the strides for each CPT
+engine.strides = compute_strides(bnet);
+
+% Precompute graphical information
+engine.families = compute_families(bnet);
+engine.children = compute_children(bnet);
+
+% For convenience, store the CPTs as tables rather than objects
+engine.CPT = get_cpts(bnet);
+
+engine = class(engine, 'gibbs_sampling_inf_engine', inf_engine(bnet));
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,135 @@
+function [marginal, engine] = marginal_nodes(engine, nodes, varargin);
+% MARGINAL_NODES Compute the marginal on the specified query nodes
+% (gibbs_sampling_engine)
+% [marginal, engine] = marginal_nodes(engine, nodes, ...)
+%
+% returns Pr(X(nodes) | X(observedNodes))
+%
+% The engine is also modified, and so it is returned as well, since
+% Matlab doesn't support passing by reference(!)  So
+% if you want to, for example, incrementally run gibbs for a few 100
+% steps at a time, you should use the returned value.
+%
+% Optional arguments :
+%
+% 'reset_counts' is 1 if you want to reset the counts made in the
+% past, and 0 otherwise (if the current query nodes are different
+% from the previous query nodes, or if marginal_nodes has not been
+% called before, reset_counts should be set to 1).
+% By default it is 1.
+
+
+reset_counts = 1;
+
+if (nargin > 3)
+  args = varargin;
+  nargs = length(args);
+  for i = 1:2:nargs
+    switch args{i}
+     case 'reset_counts'
+      reset_counts = args{i+1};
+     otherwise
+      error(['Incorrect argument to gibbs_sampling_engine/' ...
+	     ' marginal_nodes']);
+    end
+  end
+end
+
+% initialization stuff 
+bnet = bnet_from_engine(engine);
+slice_size = engine.slice_size;
+hnodes = engine.hnodes;
+onodes = engine.onodes;
+nonqnodes = mysetdiff(1:slice_size, nodes);
+gap = engine.gap;
+burnin = engine.burnin;
+T_max = engine.T;
+ns = bnet.node_sizes(nodes);
+
+
+% Cache the strides for the marginal table
+marg_strides = [1 cumprod(ns(1:end-1))];
+  
+% Reset counts if necessary
+if (reset_counts == 1) 
+  %state = sample_bnet(bnet, 1, 0);
+  %state = cell2num(sample_bnet(bnet, 'evidence', num2cell(engine.evidence)));
+  state = cell2num(sample_bnet(bnet));
+  state(onodes) = engine.evidence(onodes);
+  if (length(ns) == 1)
+    marginal_counts = zeros(ns(1),1);
+  else
+    marginal_counts = zeros(ns);
+  end
+  
+% Otherwise, use the counts that have been stored in the engine  
+else
+  state = engine.state;
+  state(onodes, :) = engine.evidence(onodes, :);
+  marginal_counts = engine.marginal_counts;
+end
+
+if (engine.deterministic == 1)
+  pos = 1;
+  order = engine.order;
+  orderSize = length(engine.order);
+else
+  sampling_dist = normalise(engine.sampling_dist);
+end
+
+
+for t = 1:(T_max*gap+burnin)
+
+  % First, select node m to sample
+  if (engine.deterministic == 1)
+    m = engine.order(pos);
+    pos = pos+1;
+    if (pos > orderSize)
+      pos = 1;
+    end
+  else
+    m = my_sample_discrete(sampling_dist);
+  end
+
+  
+  % If the node is observed, then don't bother resampling
+  if (myismember(m, onodes))
+    continue;
+  end
+
+  % Next, compute the posterior
+  post = compute_posterior (bnet, state, m, engine.strides, engine.families, ...
+			    engine.children, engine.CPT);
+  state(m) = my_sample_discrete(post);
+
+  % Now update our monte carlo estimate of the posterior
+  % distribution on the query node 
+  if ((mod(t-burnin, gap) == 0) & (t > burnin))
+
+    vals = state(nodes);
+    index = 1+marg_strides*(vals-1);
+    marginal_counts(index) = marginal_counts(index)+1;
+  end
+end
+
+% Store results for future computation.  Note that we store
+% unnormalized counts
+engine.state = state;
+engine.marginal_counts = marginal_counts;
+
+marginal.T = normalise(marginal_counts);
+
+
+  
+    
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/CPT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function c = CPT(bnet, i)
+% CPT Helper function avoid having to type in
+% CPD_to_CPT(bnet.CPD{i}) every time
+
+c = CPD_to_CPT(bnet.CPD{i});
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+/CPT.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/compute_children.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/compute_families.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/compute_families_dbn.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/compute_posterior.c/1.1.1.1/Wed May 29 15:59:56 2002//
+/compute_posterior_dbn.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/compute_strides.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/get_cpts.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/get_slice_dbn.c/1.1.1.1/Wed May 29 15:59:56 2002//
+/get_slice_dbn.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/my_sample_discrete.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/sample_single_discrete.c/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_children.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function c = compute_children(bnet)
+% COMPUTE_CHILDREN
+% precomputes the children of nodes in a bnet
+%
+% The return value is a cell array for now
+
+ss = size(bnet.dag, 1);
+c = cell(ss, 1);
+for i = 1:ss
+  c{i} = children(bnet.dag, i);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_families.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function families = compute_families(bnet)
+% COMPUTE_FAMILIES 
+% precomputes the families of nodes in a bnet
+%
+% The return value is a cell array for now
+
+ss = size(bnet.dag, 1);
+families = cell(ss, 1);
+for i = 1:ss
+  families{i} = family(bnet.dag, i);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_families_dbn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function families = compute_families_dbn(bnet)
+% COMPUTE_FAMILIES 
+% precomputes the families of nodes in a dbn
+%
+% The return value is a cell array for now
+
+ss = size(bnet.intra, 1);
+families = cell(ss, 2);
+for i = 1:ss
+  families{i, 1} = family(bnet.dag, i, 1);
+  families{i, 2} = family(bnet.dag, i, 2);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_posterior.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,107 @@
+#include "mex.h"
+
+/* Helper function that extracts a one-dimensional slice from a cpt */
+/*
+void multiplySlice(mxArray *bnet, mxArray *state, int i, int nsi, int j,
+		   mxArray *strides, mxArray *fam, mxArray *cpts,
+		   double *y)
+*/
+void multiplySlice(const mxArray *bnet, const mxArray *state, int i, int nsi, int j,
+		   const mxArray *strides, const mxArray *fam, const mxArray *cpts,
+		   double *y)
+{
+  mxArray *ec, *cpt, *family;
+  double *ecElts, *cptElts, *famElts, *strideElts, *ev;
+  int c1, k, famSize, startInd, strideStride, pos, stride;
+  
+  strideStride = mxGetM(strides);
+  strideElts = mxGetPr(strides);
+
+  ev = mxGetPr(state);
+
+  /* Get the CPT */
+  ec = mxGetField (bnet, 0, "equiv_class");
+  ecElts = mxGetPr(ec);
+  k = (int) ecElts[j-1];
+  cpt = mxGetCell (cpts, k-1);
+  cptElts = mxGetPr (cpt);
+
+  /* Get the family vector for this cpt */
+  family = mxGetCell (fam, j-1);
+  famSize = mxGetNumberOfElements (family);
+  famElts = mxGetPr (family);
+
+  /* Figure out starting position and stride */
+  startInd = 0;
+  for (c1 = 0, pos = k-1; c1 < famSize; c1++, pos +=strideStride) {
+    if (famElts[c1] != i) {
+      startInd += strideElts[pos]*(ev[(int)famElts[c1]-1]-1);
+    }
+    else {
+      stride = strideElts[pos];
+    }
+  }
+
+  for (c1 = 0, pos = startInd; c1 < nsi; c1++, pos+=stride) {
+    y[c1] *= cptElts[pos];
+  }
+}
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray
+		 *prhs[])
+{
+  double *pi, *nsElts, *y, *childrenElts;
+  mxArray *ns, *children;
+  double sum;
+  int i, nsi, c1, numChildren;
+
+  pi = mxGetPr(prhs[2]);
+  i = (int) pi[0];
+
+  ns = mxGetField(prhs[0], 0, "node_sizes");
+  nsElts = mxGetPr(ns);
+  nsi = (int) nsElts[i-1];
+
+  /* Initialize the posterior */
+  plhs[0] = mxCreateDoubleMatrix (1, nsi, mxREAL);
+  y = mxGetPr(plhs[0]);
+  for (c1 = 0; c1 < nsi; c1++) {
+    y[c1] = 1;
+  }
+
+  /* Multiply in the cpt of the node i */
+  multiplySlice(prhs[0], prhs[1], i, nsi, i, prhs[3], prhs[4],
+		prhs[6], y);
+
+
+  /* Multiply in cpts of children of i */
+  children = mxGetCell (prhs[5], i-1);
+  numChildren = mxGetNumberOfElements (children);
+  childrenElts = mxGetPr (children);
+  
+  for (c1 = 0; c1 < numChildren; c1++) {
+    int j;
+    j = (int) childrenElts[c1];
+    multiplySlice (prhs[0], prhs[1], i, nsi, j, prhs[3], prhs[4],
+		   prhs[6], y);
+  }
+
+  sum = 0;
+  /* normalize! */
+  for (c1 = 0; c1 < nsi; c1++) {
+    sum += y[c1];
+  }
+
+  for (c1 = 0; c1 < nsi; c1++) {
+    y[c1] /= sum;
+  }
+}
+
+
+
+
+
+
+
+
Binary file _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_posterior.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_posterior_dbn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function post = compute_posterior_dbn(bnet, state, i, n, strides, families, ...
+				  CPT)
+% COMPUTE_POSTERIOR
+%
+% post = compute_posterior(bnet, state, i, n, strides, families,
+% cpts)
+%
+% Compute the posterior distribution on node X_i^n of a DBN,
+% conditional on evidence in the cell array state
+%
+% strides is the cached result of compute_strides(bnet)
+% families is the cached result of compute_families(bnet)
+% cpt is the cached result of get_cpts(bnet)
+%
+% post is a one-dimensional table
+
+
+
+% First multiply in the cpt of the node itself
+post = get_slice_dbn(bnet, state, i, n, i, n, strides, families, CPT);
+post = post(:);
+
+% Then multiply in CPTs of children that are in this slice
+for j = children(bnet.intra, i)
+  slice = get_slice_dbn(bnet, state, j, n, i, n, strides, families, CPT);
+  post = post.*slice(:);
+end
+
+% Finally, if necessary, multiply in CPTs of children in the next
+% slice 
+if (n < size(state,2))
+  for j = children(bnet.inter, i)
+    slice = get_slice_dbn(bnet, state, j, n+1, i, n, strides, families, ...
+			    CPT);
+    post = post.*slice(:);
+  end
+end
+
+post = normalise(post);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/compute_strides.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,27 @@
+function strides = compute_strides(bnet)
+% COMPUTE_STRIDES For each CPT and each variable in that CPT,
+% returns the stride of that variable.  So in future, we can
+% quickly extract a slice of the CPT.
+%
+% The return value is a 2d array, where strides(i,j) contains the
+% stride of the jth variable in the ith CPT.  Cell arrays would
+% have saved space but they are slower.
+% 
+
+num_cpts = size(bnet.CPD, 2);
+max_cpt_dim = 1 + max(sum(bnet.dag));
+strides = zeros(num_cpts, max_cpt_dim);
+
+for i = 1:num_cpts
+  c = CPT(bnet, i);
+  siz = size(CPT(bnet, i));
+  
+  % Deal with the special case of a 1-d array separately
+  if siz(2) == 1
+    dim = 1;
+  else
+    dim = size(siz, 2);
+  end
+
+  strides(i, 1:dim ) = [1 cumprod(siz(1:dim-1))];
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_cpts.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function c = get_cpts(bnet)
+% Get all the cpts in tabular form
+
+cpds = bnet.CPD;
+c = cell(size(cpds));
+for i = 1:length(c)
+  c{i} = CPT(bnet, i);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_slice_dbn.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,116 @@
+#include "mex.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray
+		 *prhs[]) 
+{
+  double *pn, *pi, *pj, *pm, *y, *ecElts, *pcpt, *famElts, *strideElts,
+    *ev, *nsElts;
+  int i, k, j, m, n;
+  mxArray *ec, *cpt, *fam, *ns;
+  int c1, famSize, nsj;
+  int strideStride, startInd, stride, pos, numNodes;
+
+  const int BNET = 0;
+  const int STATE = 1;
+  const int STRIDES = 6;
+  const int FAMILIES = 7;
+  const int CPT = 8;
+
+  pn = mxGetPr(prhs[3]);
+  n = (int) pn[0];
+  pi = mxGetPr(prhs[2]);
+  i = (int) pi[0];
+  pj = mxGetPr(prhs[4]);
+  j = (int) pj[0];
+  pm = mxGetPr(prhs[5]);
+  m = (int) pm[0];
+  ev = mxGetPr(prhs[STATE]);
+  ns = mxGetField (prhs[BNET], 0, "node_sizes");
+  nsElts = mxGetPr (ns);
+  numNodes = mxGetM(ns);
+
+  strideStride = mxGetM(prhs[STRIDES]);
+  strideElts = mxGetPr(prhs[STRIDES]);
+
+
+  
+  /* Treat the case n = 1 separately */
+  if (pn[0] == 1) {
+
+    /* Get the appropriate CPT */
+    ec = mxGetField (prhs[BNET], 0, "eclass1");
+    ecElts = mxGetPr(ec);
+    k = (int) ecElts[i-1];
+    cpt = mxGetCell (prhs[8], k-1);
+    pcpt = mxGetPr(cpt);
+
+    nsj = (int) nsElts[j-1];
+
+    /* Get the correct family vector */
+    /* (Note : MEX is painful) */
+    fam = mxGetCell (prhs[FAMILIES], i - 1);
+    famSize = mxGetNumberOfElements(fam);
+    famElts = mxGetPr(fam);
+
+
+    /* Figure out starting position and stride */
+    startInd = 0;
+    for (c1 = 0, pos = k-1; c1 < famSize; c1++, pos+=strideStride) {
+      if (famElts[c1] != j) {
+	startInd += strideElts[pos]*(ev[(int)famElts[c1]-1]-1);
+      }
+      else {
+	stride = strideElts[pos];
+      }
+    }
+    
+    plhs[0] = mxCreateDoubleMatrix (1, nsj, mxREAL);
+    y = mxGetPr(plhs[0]);
+    for (c1 = 0, pos = startInd; c1 < nsj; c1++, pos+=stride) {
+      y[c1] = pcpt[pos];
+    }
+  }
+
+  /* Handle the case n > 1 */
+  else {
+
+    /* Get the appropriate CPT */
+    ec = mxGetField (prhs[BNET], 0, "eclass2");
+    ecElts = mxGetPr(ec);
+    k = (int) ecElts[i-1];
+    cpt = mxGetCell (prhs[8], k-1);
+    pcpt = mxGetPr(cpt);
+
+    /* Figure out size of slice */
+    if (m == 1) {
+      nsj = (int) nsElts[j-1];
+    }
+    else {
+      nsj = (int) nsElts[j-1+numNodes];
+    }
+
+    /* Figure out family */
+    fam = mxGetCell (prhs[FAMILIES], i - 1 + numNodes);
+    famSize = mxGetNumberOfElements(fam);
+    famElts = mxGetPr(fam);
+    
+    startInd = 0;
+    for (c1 = 0, pos = k-1; c1 < famSize; c1++, pos+=strideStride) {
+      int f = (int) famElts[c1];
+
+      if (((f == j+numNodes) && (m == n)) || ((f == j) && (m ==
+							    n-1))) {
+	stride = strideElts[pos];
+      }
+      else {
+	startInd += strideElts[pos] * (ev[f-1+((n-2)*numNodes)]-1);
+      }
+    }
+
+    plhs[0] = mxCreateDoubleMatrix(1,nsj, mxREAL);
+    y = mxGetPr(plhs[0]);
+    for (c1 = 0, pos = startInd; c1 < nsj; c1++, pos+=stride) {
+      y[c1] = pcpt[pos];
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_slice_dbn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,87 @@
+function slice = get_slice_dbn(bnet, state, i, n, j, m, strides, families, ...
+				 CPT)
+% slice = get_slice(bnet, state, i, n, j, m, strides, families, cpt)
+%
+% GET_SLICE get one-dimensional slice of the CPT for node X_i^n
+% that corresponds to the different values of X_j^m, where all
+% other nodes have values given by state.  
+% strides is the result of
+% calling compute_strides(bnet)
+% families is the result of calling compute_families(bnet)
+% cpts is the result of calling get_cpts(bnet)
+%
+% slice is a 1-d array
+
+
+if (n == 1)
+
+  k = bnet.eclass1(i);
+  c = CPT{k};
+  
+  % Figure out evidence on family
+  fam = families{i, 1};
+  ev = state(fam, 1);
+  
+  % Remove evidence on node j
+  pos = find(fam == j);
+  ev(pos) = 1;
+  dim = size(ev, 1);
+  
+  % Compute initial index and stride
+  start_ind = 1+strides(k, 1:dim)*(ev-1);
+  stride = strides(k, pos);
+
+  % Compute the slice
+  slice = c(start_ind:stride:start_ind+(bnet.node_sizes(j, 1)-1)*stride);
+						  
+else
+  
+  k = bnet.eclass2(i);
+  c = CPT{k};
+  
+  fam = families{i, 2};
+  ss = length(bnet.intra);
+  
+  % Divide the family into nodes in this time step and nodes in the
+  % previous time step
+  this_time_step = fam(find(fam > ss));
+  prev_time_step = fam(find(fam <= ss));
+
+  % Normalize the node numbers
+  this_time_step = this_time_step - ss;
+  
+  % Get the evidence
+  this_step_ev = state(this_time_step, n);
+  prev_step_ev = state(prev_time_step, n-1);
+  
+  % Remove the evidence for X_j^m
+  if (m == n)
+    pos = find(this_time_step == j);
+    this_step_ev(pos) = 1;
+    pos = pos + size(prev_time_step, 2);
+  else
+    assert (m == n-1);
+    pos = find(prev_time_step == j);
+    prev_step_ev(pos) = 1;
+  end
+  
+  % Combine the two time steps
+  ev = [prev_step_ev; this_step_ev];
+  dim = size(ev, 1);
+
+
+  % Compute starting index and stride
+  start_ind = 1 + strides(k, 1:dim)*(ev-1);
+  stride = strides(k, pos);
+  
+  % Compute slice 
+  if (m == 1)
+    q = 1;
+  else
+    q = 2;
+  end
+  slice = c(start_ind:stride:start_ind+(bnet.node_sizes(j, q)-1)*stride);
+end
+
+
+
Binary file _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/get_slice_dbn.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/my_sample_discrete.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function M = my_sample_discrete(prob)
+% A faster version that calls a c subfunction.  Will update one
+% day to have r and c parameters as well
+
+R = rand (1,1);
+M = sample_single_discrete(R, prob);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/sample_single_discrete.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+#include "mex.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray
+		 *prhs[]) 
+{
+  double *y, *pr, *dist;
+  int k, distSize;
+  double r, cumSum;
+  
+  plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);
+  y = mxGetPr (plhs[0]);
+
+  pr = mxGetPr (prhs[0]);
+  r = pr[0];
+
+  dist = mxGetPr (prhs[1]);
+  distSize = mxGetNumberOfElements (prhs[1]);
+
+  for (k = 0, cumSum = 0; (k < distSize) && (r >= cumSum); cumSum += dist[k], k++);
+
+  y[0] = k;
+}
Binary file _FullBNT/BNT/inference/static/@gibbs_sampling_inf_engine/private/sample_single_discrete.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@global_joint_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/enter_evidence.m/1.1.1.1/Mon Jun  7 19:05:42 2004//
+/find_mpe.m/1.1.1.1/Wed Jun 19 21:56:32 2002//
+/global_joint_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Mon Jun  7 19:04:48 2004//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@global_joint_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@global_joint_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@global_joint_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@global_joint_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,42 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (global_joint)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value.
+%
+% Warning: Computing the log likelihood requires marginalizing all the nodes and can be slow.
+%
+% The list below gives optional arguments [default value in brackets].      
+%
+% exclude - list of nodes whose potential will not be included in the joint [ [] ]
+%
+% e.g., engine = enter_evidence(engine, ev, 'exclude', 3)
+
+exclude = [];
+maximize = 0;
+
+if nargin >= 3
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'exclude', exclude = args{i+1};
+     case 'maximize', maximize = args{i+1};
+     otherwise,
+      error(['invalid argument name ' args{i}]);
+    end
+  end
+end
+  
+assert(~maximize)
+bnet = bnet_from_engine(engine);
+N = length(bnet.node_sizes);
+%[engine.jpot, loglik] = compute_joint_pot(bnet, mysetdiff(1:N, exclude), evidence, 1:N);
+[engine.jpot] = compute_joint_pot(bnet, mysetdiff(1:N, exclude), evidence, 1:N);
+% jpot should not be normalized, otherwise it gives wrong resutls for limids like asia_dt1
+if nargout == 2
+  [m] = marginal_nodes(engine, []);
+  [T, lik] = normalize(m.T);
+  loglik = log(lik);
+end     
+%[engine.jpot loglik] = normalize_pot(engine.jpot);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@global_joint_inf_engine/find_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function [mpe, ll] = find_mpe(engine, evidence)
+% FIND_MPE_GLOBAL Compute the most probable explanation(s) from the global joint
+% [mpe, ll] = find_mpe(engine, evidence)
+%
+% mpe(k,i) is the most probable value of node i in the k'th global mode  (cell array)
+%
+% We assume all nodes are discrete
+
+%engine = global_joint_inf_engine(bnet);
+bnet = bnet_from_engine(engine);
+engine = enter_evidence(engine, evidence);
+S1 = struct(engine); % violate object privacy
+S2 = struct(S1.jpot); % joint potential
+prob = max(S2.T(:));
+modes = find(S2.T(:) == prob);
+
+ens = bnet.node_sizes;
+onodes = find(~isemptycell(evidence));
+ens(onodes) = 1;
+mpe = ind2subv(ens, modes);
+for k=1:length(modes)
+  for i=onodes(:)'
+    mpe(k,i) = evidence{i};
+  end
+end
+ll = log(prob);
+
+mpe = num2cell(mpe);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@global_joint_inf_engine/global_joint_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function engine = global_joint_inf_engine(bnet)
+% GLOBAL_JOINT_INF_ENGINE Construct the global joint distribution as a potential
+% engine = global_joint_inf_engine(bnet)
+%
+% Warning: this has size exponential in the number of discrete hidden variables
+
+engine.jpot = [];
+engine = class(engine, 'global_joint_inf_engine', inf_engine(bnet));    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@global_joint_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function [m, pot] = marginal_family(engine, i)
+% MARGINAL_FAMILY Compute the marginal on i's family (global_inf_engine)
+% [m, pot] = marginal_family(engine, i)
+%
+
+bnet = bnet_from_engine(engine);
+[m, pot] = marginal_nodes(engine, family(bnet.dag, i));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@global_joint_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function [m, pot] = marginal_nodes(engine, query)
+% MARGINAL_NODES Compute the marginal on the specified set of nodes (global_joint)
+% [m, pot] = marginal_nodes(engine, query)
+
+pot = marginalize_pot(engine.jpot, query);
+m = pot_to_marginal(pot);
+%[m.T, lik] = normalize(m.T);
+%loglik = log(lik);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+/cliques_from_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/clq_containing_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/collect_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/distribute_evidence.m/1.1.1.1/Mon Jun 17 21:00:08 2002//
+/enter_evidence.m/1.1.1.1/Mon Jun 17 20:59:30 2002//
+/enter_soft_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/find_max_config.m/1.1.1.1/Mon Jun 17 23:14:52 2002//
+/find_mpe.m/1.1.1.1/Mon Jun 17 23:14:08 2002//
+/init_pot.m/1.1.1.1/Sun Jun 16 19:34:56 2002//
+/jtree_inf_engine.m/1.1.1.1/Fri Oct 31 22:37:48 2003//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/set_fields.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@jtree_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+/collect_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/distribute_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_soft_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@jtree_inf_engine/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/Old/collect_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+function engine = collect_evidence(engine, root)
+
+if isempty(engine.postorder{root})
+  % this is the first time we have collected to this root
+  % memoize the order
+  [jtree, preorder, postorder] = mk_rooted_tree(engine.jtree, root);
+  postorder_parents = cell(1,length(postorder));
+  for n=postorder(1:end-1)
+    postorder_parents{n} = parents(jtree, n);
+  end
+  engine.postorder{root} = postorder;
+  engine.postorder_parents{root} = postorder_parents;
+else
+  postorder = engine.postorder{root};
+  postorder_parents = engine.postorder_parents{root};
+end
+
+C = length(engine.clpot);
+seppot = cell(C, C);
+% separators are implicitely initialized to 1s
+
+% collect to root (node to parents)
+for n=postorder(1:end-1)
+  for p=postorder_parents{n}
+    %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant
+    engine.seppot{p,n} = marginalize_pot(engine.clpot{n}, engine.separator{p,n}, engine.maximize);
+    engine.clpot{p} = multiply_by_pot(engine.clpot{p}, engine.seppot{p,n});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/Old/distribute_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function engine = distribute_evidence(engine, root)
+
+if isempty(engine.preorder{root})
+  % this is the first time we have distributed from this root
+  % memoize the order
+  [jtree, preorder, postorder] = mk_rooted_tree(engine.jtree, root);
+  preorder_children = cell(1,length(preorder));
+  for n=preorder
+    preorder_children{n} = children(jtree, n);
+  end
+  engine.preorder{root} = preorder;
+  engine.preorder_children{root} = preorder_children;
+else
+  preorder = engine.preorder{root};
+  preorder_children = engine.preorder_children{root};
+end
+
+
+% distribute from root (node to children)
+for n=preorder(:)'
+  for c=preorder_children{n}(:)'
+    engine.clpot{c} = divide_by_pot(engine.clpot{c}, engine.seppot{n,c}); 
+    engine.seppot{n,c} = marginalize_pot(engine.clpot{n}, engine.separator{n,c}, engine.maximize);
+    engine.clpot{c} = multiply_by_pot(engine.clpot{c}, engine.seppot{n,c});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/Old/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,107 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (jtree)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i} = [] if X(i) is hidden, and otherwise contains its observed value (scalar or column vector).
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product instead of sum-product [0]
+% soft    - a cell array of soft/virtual evidence;
+%           soft{i} is a prob. distrib. over i's values, or [] [ cell(1,N) ]
+%
+% e.g., engine = enter_evidence(engine, ev, 'soft', soft_ev)
+%
+% For backwards compatibility with BNT2, you can also specify the parameters in the following order
+%  engine = enter_evidence(engine, ev, soft_ev)
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes(:);
+N = length(bnet.dag);
+
+% set default params
+exclude = [];
+soft_evidence = cell(1,N);
+maximize = 0;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  if iscell(args{1})
+    soft_evidence = args{1};
+  else
+    for i=1:2:nargs
+      switch args{i},
+       case 'soft',    soft_evidence = args{i+1}; 
+       case 'maximize', maximize = args{i+1}; 
+       otherwise,  
+	error(['invalid argument name ' args{i}]);       
+      end
+    end
+  end
+end
+
+engine.maximize = maximize;
+
+onodes = find(~isemptycell(evidence));
+hnodes = find(isemptycell(evidence));
+pot_type = determine_pot_type(bnet, onodes);
+ if strcmp(pot_type, 'cg')
+  check_for_cd_arcs(onodes, bnet.cnodes, bnet.dag);
+end
+
+
+hard_nodes = 1:N;
+soft_nodes = find(~isemptycell(soft_evidence));
+S = length(soft_nodes);
+if S > 0
+  assert(pot_type == 'd');
+  assert(mysubset(soft_nodes, bnet.dnodes));
+end
+ 
+% Evaluate CPDs with evidence, and convert to potentials  
+pot = cell(1, N+S);
+for n=1:N
+  fam = family(bnet.dag, n);
+  e = bnet.equiv_class(n);
+  pot{n} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence);
+end
+
+for i=1:S
+  n = soft_nodes(i);
+  pot{N+i} = dpot(n, ns(n), soft_evidence{n});
+end
+
+%clqs = engine.clq_ass_to_node([hard_nodes soft_nodes]); 
+%[clpot, loglik] = enter_soft_evidence(engine, clqs, pot, onodes, pot_type);
+%engine.clpot = clpot; % save the results for marginal_nodes
+
+
+clique = engine.clq_ass_to_node([hard_nodes soft_nodes]); 
+potential = pot;
+
+
+% Set the clique potentials to all 1s
+C = length(engine.cliques);
+for i=1:C
+  engine.clpot{i} = mk_initial_pot(pot_type, engine.cliques{i}, ns, bnet.cnodes, onodes);
+end
+
+% Multiply on specified potentials
+for i=1:length(clique)
+  c = clique(i);
+  engine.clpot{c} = multiply_by_pot(engine.clpot{c}, potential{i});
+end
+
+root = 1; % arbitrary
+engine = collect_evidence(engine, root);
+engine = distribute_evidence(engine, root);
+
+ll = zeros(1, C);
+for i=1:C
+  [engine.clpot{i}, ll(i)] = normalize_pot(engine.clpot{i});
+end
+loglik = ll(1); % we can extract the likelihood from any clique
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/Old/enter_soft_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function [clpot, loglik] = enter_soft_evidence(engine, clique, potential, onodes, pot_type)
+% ENTER_SOFT_EVIDENCE Add the specified potentials to the network (jtree)
+% [clpot, loglik] = enter_soft_evidence(engine, clique, potential, onodes, pot_type, maximize)
+%
+% We multiply potential{i} onto clique(i) before propagating.
+% We return all the modified clique potentials.
+
+[clpot, seppot] = init_pot(engine, clique, potential, pot_type, onodes);
+[clpot, seppot] = collect_evidence(engine, clpot, seppot);
+[clpot, seppot] = distribute_evidence(engine, clpot, seppot);
+
+C = length(clpot);
+ll = zeros(1, C);
+for i=1:C
+  [clpot{i}, ll(i)] = normalize_pot(clpot{i});
+end
+loglik = ll(1); % we can extract the likelihood from any clique
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/cliques_from_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function cliques = cliques_from_engine(engine)
+% CLIQUES_FROM_ENGINE Return the cliques stored inside the inf. engine (jtree)
+% cliques = cliques_from_engine(engine)
+
+cliques = engine.cliques;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/clq_containing_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function c = clq_containing_nodes(engine, nodes, fam)
+% CLQ_CONTAINING_NODES Find the lightest clique (if any) that contains the set of nodes
+% c = clq_containing_nodes(engine, nodes, family)
+%
+% If the optional 'family' argument is specified, it means nodes = family(nodes(end)).
+% (This is useful since clq_ass_to_node is not accessible to outsiders.)
+% Returns c=-1 if there is no such clique.
+
+if nargin < 3, fam = 0; else fam = 1; end
+
+if length(nodes)==1
+  c = engine.clq_ass_to_node(nodes(1));
+%elseif fam
+%  c = engine.clq_ass_to_node(nodes(end));
+else
+  B = engine.cliques_bitv;
+  w = engine.clique_weight;
+  clqs = find(all(B(:,nodes), 2)); % all selected columns must be 1
+  if isempty(clqs)
+    c = -1;
+  else
+    c = clqs(argmin(w(clqs)));     
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/collect_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function [clpot, seppot] = collect_evidence(engine, clpot, seppot)
+% COLLECT_EVIDENCE Do message passing from leaves to root (children then parents)
+% [clpot, seppot] = collect_evidence(engine, clpot, seppot)
+
+for n=engine.postorder %postorder(1:end-1)
+  for p=engine.postorder_parents{n}
+    %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant
+    seppot{p,n} = marginalize_pot(clpot{n}, engine.separator{p,n}, engine.maximize);
+    clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n});
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/distribute_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function [clpot, seppot] = distribute_evidence(engine, clpot, seppot)
+% DISTRIBUTE_EVIDENCE Do message passing from root to leaves (parents then children)
+% [clpot, seppot] = distribute_evidence(engine, clpot, seppot)
+
+for n=engine.preorder
+  for c=engine.preorder_children{n}
+    clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); 
+    seppot{n,c} = marginalize_pot(clpot{n}, engine.separator{n,c}, engine.maximize);
+    clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,88 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (jtree)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i} = [] if X(i) is hidden, and otherwise contains its observed value (scalar or column vector).
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% soft    - a cell array of soft/virtual evidence;
+%           soft{i} is a prob. distrib. over i's values, or [] [ cell(1,N) ]
+%
+% e.g., engine = enter_evidence(engine, ev, 'soft', soft_ev)
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes(:);
+N = length(bnet.dag);
+
+engine.evidence = evidence; % store this for marginal_nodes with add_ev option
+engine.maximize = 0;
+
+% set default params
+exclude = [];
+soft_evidence = cell(1,N);
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'soft',    soft_evidence = args{i+1}; 
+   case 'maximize', engine.maximize = args{i+1};
+   otherwise,  
+    error(['invalid argument name ' args{i}]);       
+  end
+end
+
+onodes = find(~isemptycell(evidence));
+hnodes = find(isemptycell(evidence));
+pot_type = determine_pot_type(bnet, onodes);
+ if strcmp(pot_type, 'cg')
+  check_for_cd_arcs(onodes, bnet.cnodes, bnet.dag);
+end
+
+if is_mnet(bnet)
+  pot = engine.user_pot;
+  clqs = engine.nums_ass_to_user_clqs;
+else
+  % Evaluate CPDs with evidence, and convert to potentials  
+  pot = cell(1, N);
+  for n=1:N
+    fam = family(bnet.dag, n);
+    e = bnet.equiv_class(n);
+    if isempty(bnet.CPD{e})
+      error(['must define CPD ' num2str(e)])
+    else
+      pot{n} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence);
+    end
+  end
+  clqs = engine.clq_ass_to_node(1:N);
+end
+
+% soft evidence
+soft_nodes = find(~isemptycell(soft_evidence));
+S = length(soft_nodes);
+if S > 0
+  assert(pot_type == 'd');
+  assert(mysubset(soft_nodes, bnet.dnodes));
+end
+for i=1:S
+  n = soft_nodes(i);
+  pot{end+1} = dpot(n, ns(n), soft_evidence{n});
+end
+clqs = [clqs engine.clq_ass_to_node(soft_nodes)]; 
+
+
+[clpot, seppot] = init_pot(engine, clqs, pot, pot_type, onodes);
+[clpot, seppot] = collect_evidence(engine, clpot, seppot);
+[clpot, seppot] = distribute_evidence(engine, clpot, seppot);
+
+C = length(clpot);
+ll = zeros(1, C);
+for i=1:C
+  [clpot{i}, ll(i)] = normalize_pot(clpot{i});
+end
+loglik = ll(1); % we can extract the likelihood from any clique
+
+engine.clpot = clpot;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/enter_soft_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function [clpot, loglik] = enter_soft_evidence(engine, clique, potential, onodes, pot_type)
+% ENTER_SOFT_EVIDENCE Add the specified potentials to the network (jtree)
+% [clpot, loglik] = enter_soft_evidence(engine, clique, potential, onodes, pot_type, maximize)
+%
+% We multiply potential{i} onto clique(i) before propagating.
+% We return all the modified clique potentials.
+
+% only used by BK!
+
+[clpot, seppot] = init_pot(engine, clique, potential, pot_type, onodes);
+[clpot, seppot] = collect_evidence(engine, clpot, seppot);
+[clpot, seppot] = distribute_evidence(engine, clpot, seppot);
+
+C = length(clpot);
+ll = zeros(1, C);
+for i=1:C
+  [clpot{i}, ll(i)] = normalize_pot(clpot{i});
+end
+loglik = ll(1); % we can extract the likelihood from any clique
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/find_max_config.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,35 @@
+function [mpe, clpot, seppot] = find_max_config(engine, clpot, seppot, evidence)
+% FIND_MAX_CONFIG Backwards pass of Viterbi fro jtree
+% function [mpe, clpot, seppot] = find_max_config(engine, clpot, seppot, evidence)
+% See Cowell99 p98
+
+bnet = bnet_from_engine(engine);
+nnodes = length(bnet.dag);
+mpe = cell(1, nnodes);
+maximize = 1;
+
+c = engine.root_clq;
+pot = struct(clpot{c}); % violate object privacy
+dom = pot.domain;
+[indices, clpot{c}] = find_most_prob_entry(clpot{c});
+mpe(dom) = num2cell(indices);
+
+for n=engine.preorder
+  for c=engine.preorder_children{n}
+    clpot{c} = divide_by_pot(clpot{c}, seppot{n,c}); 
+    seppot{n,c} = marginalize_pot(clpot{n}, engine.separator{n,c}, maximize);
+    clpot{c} = multiply_by_pot(clpot{c}, seppot{n,c});
+    
+    pot = struct(clpot{c}); % violate object privacy
+    dom = pot.domain;
+    [indices, clpot{c}] = find_most_prob_entry(clpot{c});
+    mpe(dom) = num2cell(indices);
+  end
+end
+
+obs_nodes = find(~isemptycell(evidence));
+% indices for observed nodes will be 1 - need to overwrite these
+mpe(obs_nodes) = evidence(obs_nodes);
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/find_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,71 @@
+function mpe = find_mpe(engine, evidence, varargin)
+% FIND_MPE Find the most probable explanation of the data (assignment to the hidden nodes)
+% function mpe = find_mpe(engine, evidence,...)
+%
+% evidence{i} = [] if X(i) is hidden, and otherwise contains its observed value (scalar or column vector).
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% soft    - a cell array of soft/virtual evidence;
+%           soft{i} is a prob. distrib. over i's values, or [] [ cell(1,N) ]
+%
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes(:);
+N = length(bnet.dag);
+
+engine.evidence = evidence;
+  
+% set default params
+exclude = [];
+soft_evidence = cell(1,N);
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'soft',    soft_evidence = args{i+1}; 
+   otherwise,  
+    error(['invalid argument name ' args{i}]);       
+  end
+end
+engine.maximize = 1;
+
+onodes = find(~isemptycell(evidence));
+hnodes = find(isemptycell(evidence));
+pot_type = determine_pot_type(bnet, onodes);
+ if strcmp(pot_type, 'cg')
+  check_for_cd_arcs(onodes, bnet.cnodes, bnet.dag);
+end
+
+hard_nodes = 1:N;
+soft_nodes = find(~isemptycell(soft_evidence));
+S = length(soft_nodes);
+if S > 0
+  assert(pot_type == 'd');
+  assert(mysubset(soft_nodes, bnet.dnodes));
+end
+ 
+% Evaluate CPDs with evidence, and convert to potentials  
+pot = cell(1, N+S);
+for n=1:N
+  fam = family(bnet.dag, n);
+  e = bnet.equiv_class(n);
+  if isempty(bnet.CPD{e})
+    error(['must define CPD ' num2str(e)])
+  else
+    pot{n} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence);
+  end
+end
+
+for i=1:S
+  n = soft_nodes(i);
+  pot{N+i} = dpot(n, ns(n), soft_evidence{n});
+end
+clqs = engine.clq_ass_to_node([hard_nodes soft_nodes]); 
+
+[clpot, seppot] = init_pot(engine, clqs, pot, pot_type, onodes);
+[clpot, seppot] = collect_evidence(engine, clpot, seppot);
+mpe = find_max_config(engine, clpot, seppot, evidence); % instead of distribute evidence
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/init_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,20 @@
+function [clpot, seppot] = init_pot(engine, clqs, pots, pot_type, onodes)
+% INIT_POT Initialise potentials with evidence (jtree_inf)
+% function [clpot, seppot] = init_pot(engine, clqs, pots, pot_type, onodes)
+
+cliques = engine.cliques;
+bnet = bnet_from_engine(engine);
+% Set the clique potentials to all 1s
+C = length(cliques);
+clpot = cell(1,C);
+for i=1:C
+  clpot{i} = mk_initial_pot(pot_type, cliques{i}, bnet.node_sizes(:), bnet.cnodes(:), onodes);
+end
+
+% Multiply on specified potentials
+for i=1:length(clqs)
+  c = clqs(i);
+  clpot{c} = multiply_by_pot(clpot{c}, pots{i});
+end
+
+seppot = cell(C,C); % implicitely initialized to 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/jtree_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,134 @@
+function engine = jtree_inf_engine(bnet, varargin)
+% JTREE_INF_ENGINE Junction tree inference engine
+% engine = jtree_inf_engine(bnet, ...)
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% clusters  - a cell array of sets of nodes we want to ensure are in the same clique (in addition to families) [ {} ]
+% root      - the root of the junction tree will be a clique that contains this set of nodes [N]
+% stages    - stages{t} is a set of nodes we want to eliminate before stages{t+1}, ... [ {1:N} ]
+%
+% e.g., engine = jtree_inf_engine(bnet, 'maximize', 1);
+%
+% For more details on the junction tree algorithm, see
+% - "Probabilistic networks and expert systems", Cowell, Dawid, Lauritzen and Spiegelhalter, Springer, 1999
+% - "Inference in Belief Networks: A procedural guide", C. Huang and A. Darwiche, 
+%      Intl. J. Approximate Reasoning, 15(3):225-263, 1996.
+
+
+% set default params
+N = length(bnet.dag);
+clusters = {};
+root = N;
+stages = { 1:N };
+maximize = 0;
+
+if nargin >= 2
+  args = varargin;
+  nargs = length(args);
+  if ~isstr(args{1})
+    error('the interface to jtree has changed; now, onodes is not allowed and all optional params must be passed by name')
+  end
+  for i=1:2:nargs
+    switch args{i},
+     case 'clusters', clusters = args{i+1}; 
+     case 'root',     root = args{i+1}; 
+     case 'stages',   stages = args{i+1}; 
+     case 'maximize', maximize = args{i+1};
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+engine = init_fields;
+engine = class(engine, 'jtree_inf_engine', inf_engine(bnet));
+
+engine.maximize = maximize;
+
+onodes = bnet.observed;
+
+%[engine.jtree, dummy, engine.cliques, B, w, elim_order, moral_edges, fill_in_edges, strong] = ...
+%    dag_to_jtree(bnet, onodes, stages, clusters);
+
+porder = determine_elim_constraints(bnet, onodes);
+strong = ~isempty(porder);
+ns = bnet.node_sizes(:);
+ns(onodes) = 1; % observed nodes have only 1 possible value
+[engine.jtree, root2, engine.cliques, B, w] = ...
+    graph_to_jtree(moralize(bnet.dag), ns, porder, stages, clusters);
+
+
+engine.cliques_bitv = B;
+engine.clique_weight = w;
+C = length(engine.cliques);
+engine.clpot = cell(1,C);
+
+% Compute the separators between connected cliques.
+[is,js] = find(engine.jtree > 0);
+engine.separator = cell(C,C);
+for k=1:length(is)
+  i = is(k); j = js(k);
+  engine.separator{i,j} = find(B(i,:) & B(j,:)); % intersect(cliques{i}, cliques{j});
+end
+
+% A node can be a member of many cliques, but is assigned to exactly one, to avoid
+% double-counting its CPD. We assign node i to clique c if c is the "lightest" clique that
+% contains i's family, so it can accomodate its CPD.
+
+engine.clq_ass_to_node = zeros(1, N);
+for i=1:N
+  %c = clq_containing_nodes(engine, family(bnet.dag, i));
+  clqs_containing_family = find(all(B(:,family(bnet.dag, i)), 2)); % all selected columns must be 1
+  c = clqs_containing_family(argmin(w(clqs_containing_family)));  
+  engine.clq_ass_to_node(i) = c; 
+end
+
+% Make the jtree rooted, so there is a fixed message passing order.
+if strong
+  % the last clique is guaranteed to be a strong root
+  engine.root_clq = length(engine.cliques);
+else
+  % jtree_dbn_inf_engine requires the root to contain the interface.
+  % This may conflict with the strong root requirement! *********** BUG *************
+  engine.root_clq = clq_containing_nodes(engine, root);
+  if engine.root_clq <= 0
+    error(['no clique contains ' num2str(root)]);
+  end
+end  
+
+[engine.jtree, engine.preorder, engine.postorder] = mk_rooted_tree(engine.jtree, engine.root_clq);
+
+% collect 
+engine.postorder_parents = cell(1,length(engine.postorder));
+for n=engine.postorder(:)'
+  engine.postorder_parents{n} = parents(engine.jtree, n);
+end
+% distribute
+engine.preorder_children = cell(1,length(engine.preorder));
+for n=engine.preorder(:)'
+  engine.preorder_children{n} = children(engine.jtree, n);
+end
+
+  
+
+%%%%%%%%
+
+function engine = init_fields()
+
+engine.jtree = [];
+engine.cliques = [];
+engine.separator = [];
+engine.cliques_bitv = [];
+engine.clique_weight = [];
+engine.clpot = [];
+engine.clq_ass_to_node = [];
+engine.root_clq = [];
+engine.preorder = [];
+engine.postorder = [];
+engine.preorder_children = [];
+engine.postorder_parents = [];
+engine.maximize = [];
+engine.evidence = [];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function marginal = marginal_family(engine, i, add_ev)
+% MARGINAL_FAMILY Compute the marginal on the specified family (jtree)
+% marginal = marginal_family(engine, i)
+
+if nargin < 3, add_ev = 0; end
+assert(~add_ev);
+
+bnet = bnet_from_engine(engine);
+fam = family(bnet.dag, i);
+c = engine.clq_ass_to_node(i);
+marginal = pot_to_marginal(marginalize_pot(engine.clpot{c}, fam));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function marginal = marginal_nodes(engine, query, add_ev)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (jtree)
+% marginal = marginal_nodes(engine, query, add_ev)
+%
+% 'query' must be a subset of some clique; an error will be raised if not.
+% add_ev is an optional argument; if 1, we will "inflate" the marginal of observed nodes
+% to their original size, adding 0s to the positions which contradict the evidence
+
+if nargin < 3, add_ev = 0; end
+
+c = clq_containing_nodes(engine, query);
+if c == -1
+  error(['no clique contains ' num2str(query)]);
+end
+marginal = pot_to_marginal(marginalize_pot(engine.clpot{c}, query, engine.maximize));
+
+if add_ev
+  bnet = bnet_from_engine(engine);
+  %marginal = add_ev_to_dmarginal(marginal, engine.evidence, bnet.node_sizes);
+  marginal = add_evidence_to_gmarginal(marginal, engine.evidence, bnet.node_sizes, bnet.cnodes);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_inf_engine/set_fields.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function engine = set_fields(engine, varargin)
+% SET_FIELDS Set the fields for a generic engine
+% engine = set_fields(engine, name/value pairs)
+%
+% e.g., engine = set_fields(engine, 'maximize', 1)
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'maximize', engine.maximize = args{i+1};
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_limid_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/jtree_limid_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_limid_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@jtree_limid_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_limid_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes_SS.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@jtree_limid_inf_engine/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_limid_inf_engine/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_limid_inf_engine/Old/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function [m, pot] = marginal_family(engine, query)
+% MARGINAL_NODES Compute the marginal on the family of the specified node (jtree_limid)
+% [m, pot] = marginal_family(engine, query)
+%
+% query should be a single decision node, or [] (to compute global max expected utility)
+
+bnet = bnet_from_engine(engine);
+if isempty(query)
+  compute_meu = 1;
+  d = bnet.decision_nodes(1); % pick an arbitrary root to collect to
+  fam = []; % marginalize root pot down to a point
+else
+  compute_meu = 0;
+  d = query;
+  assert(myismember(d, bnet.decision_nodes));
+  fam = family(bnet.dag, d);
+end
+
+clpot = init_clpot(bnet, engine.cliques, engine.clq_ass_to_node, engine.evidence, engine.exclude);
+
+% collect to root (clique containing d) 
+C = length(engine.cliques);
+seppot = cell(C, C);    % separators are implicitely initialized to 1s
+for n=engine.postorder{d}(1:end-1)
+  for p=parents(engine.rooted_jtree{d}, n)
+    %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant
+    seppot{p,n} = marginalize_pot(clpot{n}, engine.separator{p,n});
+    clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n});
+  end
+end
+
+root = engine.clq_ass_to_node(d);
+assert(root == engine.postorder{d}(end));
+pot = marginalize_pot(clpot{root}, fam);
+m = pot_to_marginal(pot);
+
+%%%%%%%%%%%
+
+
+function clpot = init_clpot(bnet, cliques, clq_ass_to_node, evidence, exclude)
+
+% Set the clique potentials to all 1s
+C = length(cliques);
+clpot = cell(1, C);
+ns = bnet.node_sizes;
+for i=1:C
+  clpot{i} = upot(cliques{i}, ns(cliques{i}));
+end
+
+N = length(bnet.dag);
+nodes = mysetdiff(1:N, exclude);
+
+for n=nodes(:)'
+  fam = family(bnet.dag, n);
+  e = bnet.equiv_class(n);
+  c = clq_ass_to_node(n);
+  pot = convert_to_pot(bnet.CPD{e}, 'u', ns, fam, evidence);
+  clpot{c} = multiply_by_pot(clpot{c}, pot);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_limid_inf_engine/Old/marginal_nodes_SS.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+function [pot, MEU] = marginal_nodes(engine, d)
+
+C = length(cliques);
+%clpot = init_clpot(limid, cliques, d, clq_ass_to_node);
+clpot = init_clpot(limid, cliques, [], clq_ass_to_node);
+
+% collect to root
+if 1
+  % HUGIN
+  seppot = cell(C, C);    % separators are implicitely initialized to 1s
+  for n=postorder{di}(1:end-1)
+    for p=parents(rooted_jtree{di}, n)
+      %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant
+      seppot{p,n} = marginalize_pot(clpot{n}, separator{p,n});
+      clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n});
+    end
+  end
+else
+  % Shafer-Shenoy
+  msg = cell(C,C);
+  for n=postorder{di}(1:end-1)
+    for c=children(rooted_jtree{di}, n)
+      clpot{n} = multiply_by_pot(clpot{n}, msg{c,n});
+    end
+    p = parents(rooted_jtree{di}, n);
+    %msg{n,p} = marginalize_pot(clpot{n}, cliques{p});
+    msg{n,p} = marginalize_pot(clpot{n}, separator{n,p});
+  end
+  root = clq_ass_to_node(d);
+  n=postorder{di}(end);
+  assert(n == root);
+  for c=children(rooted_jtree{di}, n)
+    clpot{n} = multiply_by_pot(clpot{n}, msg{c,n});
+  end
+end	
+
+fam = family(limid.dag, d);
+pot = marginalize_pot(clpot{root}, fam);
+
+%%%%%%%
+jpot = compute_joint_pot_limid(limid);
+pot2 = marginalize_pot(jpot, fam);
+assert(approxeq_pot(pot, pot2))
+%%%%%%
+
+[policy, score] = extract_policy(pot);
+
+e = limid.equiv_class(d);
+limid.CPD{e} = set_params(limid.CPD{e}, 'policy', policy);
+
+  
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_limid_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function engine = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (jtree_limid)
+% engine = enter_evidence(engine, evidence, ...)
+%
+% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value.
+%
+% The list below gives optional arguments [default value in brackets].      
+%
+% exclude - list of nodes whose potential will not be included in the joint [ [] ]
+%
+% e.g., engine = enter_evidence(engine, ev, 'exclude', 3)
+
+exclude = [];
+
+if nargin >= 3
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'exclude', exclude = args{i+1};
+     otherwise,
+      error(['invalid argument name ' args{i}]);
+    end
+  end
+end
+  
+engine.exclude = exclude;
+engine.evidence = evidence;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_limid_inf_engine/jtree_limid_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+function engine = jtree_limid_inf_engine(bnet)
+% JTREE_LIMID_INF_ENGINE Make a junction tree engine for use by solve_limid
+% engine = jtree_limid_inf_engine(bnet)
+%
+% This engine is designed to compute marginals on decision nodes
+
+
+MG = moralize(bnet.dag);
+% We do not remove the utility nodes, because that complicates the book-keeping.
+% Leaving them in will not introduce any un-necessary triangulation arcs, because they are always leaves.
+% Also, since utility nodes have size 1, they do not increase the size of the potentials.
+
+ns = bnet.node_sizes;
+elim_order = best_first_elim_order(MG, ns);
+[MTG, engine.cliques]  = triangulate(MG, elim_order);
+[engine.jtree, root, B, w] = cliques_to_jtree(engine.cliques, ns);
+
+% A node can be a member of many cliques, but is assigned to exactly one, to avoid
+% double-counting its CPD. We assign node i to clique c if c is the "lightest" clique that
+% contains i's family, so it can accomodate its CPD.
+N = length(bnet.dag);
+engine.clq_ass_to_node = zeros(1, N);
+for i=1:N
+  clqs_containing_family = find(all(B(:,family(bnet.dag, i)), 2)); % all selected columns must be 1
+  c = clqs_containing_family(argmin(w(clqs_containing_family)));  
+  engine.clq_ass_to_node(i) = c; 
+end
+
+
+% Compute the separators between connected cliques.
+[is,js] = find(engine.jtree > 0);
+num_cliques = length(engine.cliques);
+engine.separator = cell(num_cliques, num_cliques);
+for k=1:length(is)
+  i = is(k); j = js(k);
+  engine.separator{i,j} = find(B(i,:) & B(j,:)); % intersect(cliques{i}, cliques{j});
+end
+
+
+% create |D| different rooted jtree's
+engine.rooted_jtree = cell(1, N);
+engine.preorder = cell(1, N);
+engine.postorder = cell(1, N);
+for d=bnet.decision_nodes(:)'
+  root = engine.clq_ass_to_node(d);
+  [engine.rooted_jtree{d}, engine.preorder{d}, engine.postorder{d}] = mk_rooted_tree(engine.jtree, root);
+end
+
+engine.exclude = [];
+engine.evidence = [];
+
+engine = class(engine, 'jtree_limid_inf_engine', inf_engine(bnet));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_limid_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+function [m, pot] = marginal_family(engine, query)
+% MARGINAL_NODES Compute the marginal on the family of the specified node (jtree_limid)
+% [m, pot] = marginal_family(engine, query)
+%
+% query should be a single decision node
+
+bnet = bnet_from_engine(engine);
+d = query;
+assert(myismember(d, bnet.decision_nodes));
+fam = family(bnet.dag, d);
+
+clpot = init_clpot(bnet, engine.cliques, engine.clq_ass_to_node, engine.evidence, engine.exclude);
+
+% collect to root (clique containing d) 
+C = length(engine.cliques);
+seppot = cell(C, C);    % separators are implicitely initialized to 1s
+for n=engine.postorder{d}(1:end-1)
+  for p=parents(engine.rooted_jtree{d}, n)
+    %clpot{p} = divide_by_pot(clpot{n}, seppot{p,n}); % dividing by 1 is redundant
+    seppot{p,n} = marginalize_pot(clpot{n}, engine.separator{p,n});
+    clpot{p} = multiply_by_pot(clpot{p}, seppot{p,n});
+  end
+end
+
+root = engine.clq_ass_to_node(d);
+assert(root == engine.postorder{d}(end));
+pot = marginalize_pot(clpot{root}, fam);
+m = pot_to_marginal(pot);
+
+%%%%%%%%%%%
+
+
+function clpot = init_clpot(bnet, cliques, clq_ass_to_node, evidence, exclude)
+
+% Set the clique potentials to all 1s
+C = length(cliques);
+clpot = cell(1, C);
+ns = bnet.node_sizes;
+for i=1:C
+  clpot{i} = upot(cliques{i}, ns(cliques{i}));
+end
+
+N = length(bnet.dag);
+nodes = mysetdiff(1:N, exclude);
+
+for n=nodes(:)'
+  fam = family(bnet.dag, n);
+  e = bnet.equiv_class(n);
+  c = clq_ass_to_node(n);
+  pot = convert_to_pot(bnet.CPD{e}, 'u', fam(:), evidence);
+  clpot{c} = multiply_by_pot(clpot{c}, pot);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_limid_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function [m, pot] = marginal_nodes(engine, query)
+% MARGINAL_NODES Compute the marginal on the specified nodes (jtree_limid)
+% [m, pot] = marginal_nodes(engine, query)
+%
+% query should be a subset of a family of a decision node
+
+if isempty(query)
+  bnet = bnet_from_engine(engine);
+  d = bnet.decision_nodes(1); % pick an arbitrary decision node
+  [dummy, big_pot] = marginal_family(engine, d); 
+else
+  [dummy, big_pot] = marginal_family(engine, query);
+end
+pot = marginalize_pot(big_pot, query);
+m = pot_to_marginal(pot);
+
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+/enter_evidence.m/1.1.1.1/Mon Jun 17 20:30:02 2002//
+/find_mpe.m/1.1.1.1/Mon Jun 17 20:29:40 2002//
+/jtree_mnet_inf_engine.m/1.1.1.1/Sat Jan 18 22:13:32 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@jtree_mnet_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_mnet_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_mnet_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,82 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (jtree)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i} = [] if X(i) is hidden, and otherwise contains its observed value (scalar or column vector).
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% soft    - a cell array of soft/virtual evidence;
+%           soft{i} is a prob. distrib. over i's values, or [] [ cell(1,N) ]
+%
+% e.g., engine = enter_evidence(engine, ev, 'soft', soft_ev)
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes(:);
+N = length(bnet.dag);
+
+engine.evidence = evidence; % store this for marginal_nodes with add_ev option
+engine.maximize = 0;
+
+% set default params
+exclude = [];
+soft_evidence = cell(1,N);
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'soft',    soft_evidence = args{i+1}; 
+   otherwise,  
+    error(['invalid argument name ' args{i}]);       
+  end
+end
+
+onodes = find(~isemptycell(evidence));
+hnodes = find(isemptycell(evidence));
+pot_type = determine_pot_type(bnet, onodes);
+ if strcmp(pot_type, 'cg')
+  check_for_cd_arcs(onodes, bnet.cnodes, bnet.dag);
+end
+
+% Evaluate CPDs with evidence, and convert to potentials  
+pot = cell(1, N);
+for n=1:N
+  fam = family(bnet.dag, n);
+  e = bnet.equiv_class(n);
+  if isempty(bnet.CPD{e})
+    error(['must define CPD ' num2str(e)])
+  else
+    pot{n} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence);
+  end
+end
+clqs = engine.clq_ass_to_node(1:N);
+
+% soft evidence
+soft_nodes = find(~isemptycell(soft_evidence));
+S = length(soft_nodes);
+if S > 0
+  assert(pot_type == 'd');
+  assert(mysubset(soft_nodes, bnet.dnodes));
+end
+for i=1:S
+  n = soft_nodes(i);
+  pot{end+1} = dpot(n, ns(n), soft_evidence{n});
+end
+clqs = [clqs engine.clq_ass_to_node(soft_nodes)]; 
+
+
+[clpot, seppot] = init_pot(engine, clqs, pot, pot_type, onodes);
+[clpot, seppot] = collect_evidence(engine, clpot, seppot);
+[clpot, seppot] = distribute_evidence(engine, clpot, seppot);
+
+C = length(clpot);
+ll = zeros(1, C);
+for i=1:C
+  [clpot{i}, ll(i)] = normalize_pot(clpot{i});
+end
+loglik = ll(1); % we can extract the likelihood from any clique
+
+engine.clpot = clpot;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_mnet_inf_engine/find_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,71 @@
+function mpe = find_mpe(engine, evidence, varargin)
+% FIND_MPE Find the most probable explanation of the data (assignment to the hidden nodes)
+% function mpe = find_mpe(engine, evidence,...)
+%
+% evidence{i} = [] if X(i) is hidden, and otherwise contains its observed value (scalar or column vector).
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% soft    - a cell array of soft/virtual evidence;
+%           soft{i} is a prob. distrib. over i's values, or [] [ cell(1,N) ]
+%
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes(:);
+N = length(bnet.dag);
+
+engine.evidence = evidence;
+  
+% set default params
+exclude = [];
+soft_evidence = cell(1,N);
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'soft',    soft_evidence = args{i+1}; 
+   otherwise,  
+    error(['invalid argument name ' args{i}]);       
+  end
+end
+engine.maximize = 1;
+
+onodes = find(~isemptycell(evidence));
+hnodes = find(isemptycell(evidence));
+pot_type = determine_pot_type(bnet, onodes);
+ if strcmp(pot_type, 'cg')
+  check_for_cd_arcs(onodes, bnet.cnodes, bnet.dag);
+end
+
+hard_nodes = 1:N;
+soft_nodes = find(~isemptycell(soft_evidence));
+S = length(soft_nodes);
+if S > 0
+  assert(pot_type == 'd');
+  assert(mysubset(soft_nodes, bnet.dnodes));
+end
+ 
+% Evaluate CPDs with evidence, and convert to potentials  
+pot = cell(1, N+S);
+for n=1:N
+  fam = family(bnet.dag, n);
+  e = bnet.equiv_class(n);
+  if isempty(bnet.CPD{e})
+    error(['must define CPD ' num2str(e)])
+  else
+    pot{n} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence);
+  end
+end
+
+for i=1:S
+  n = soft_nodes(i);
+  pot{N+i} = dpot(n, ns(n), soft_evidence{n});
+end
+clqs = engine.clq_ass_to_node([hard_nodes soft_nodes]); 
+
+[clpot, seppot] = init_pot(engine, clqs, pot, pot_type, onodes);
+[clpot, seppot] = collect_evidence(engine, clpot, seppot);
+mpe = find_max_config(engine, clpot, seppot);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_mnet_inf_engine/jtree_mnet_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,101 @@
+function engine = jtree_mnet_inf_engine(model, varargin)
+% JTREE_MNET_INF_ENGINE Junction tree inference engine for Markov nets
+% engine = jtree_inf_engine(mnet, ...)
+%
+
+% set default params
+N = length(mnet.graph);
+root = N;
+
+engine = init_fields;
+engine = class(engine, 'jtree_mnet_inf_engine', inf_engine(bnet));
+
+onodes = bnet.observed;
+if is_mnet(bnet)
+  MG = bnet.graph;
+else
+  error('should be a mnet')
+end
+
+%[engine.jtree, dummy, engine.cliques, B, w, elim_order, moral_edges, fill_in_edges, strong] = ...
+%    dag_to_jtree(bnet, onodes, stages, clusters);
+
+porder = determine_elim_constraints(bnet, onodes);
+strong = ~isempty(porder);
+ns = bnet.node_sizes(:);
+ns(onodes) = 1; % observed nodes have only 1 possible value
+[engine.jtree, root2, engine.cliques, B, w] = ...
+    graph_to_jtree(MG, ns, porder, stages, clusters);
+
+engine.cliques_bitv = B;
+engine.clique_weight = w;
+C = length(engine.cliques);
+engine.clpot = cell(1,C);
+
+% Compute the separators between connected cliques.
+[is,js] = find(engine.jtree > 0);
+engine.separator = cell(C,C);
+for k=1:length(is)
+  i = is(k); j = js(k);
+  engine.separator{i,j} = find(B(i,:) & B(j,:)); % intersect(cliques{i}, cliques{j});
+end
+
+% A node can be a member of many cliques, but is assigned to exactly one, to avoid
+% double-counting its CPD. We assign node i to clique c if c is the "lightest" clique that
+% contains i's family, so it can accomodate its CPD.
+
+engine.clq_ass_to_node = zeros(1, N);
+for i=1:N
+  %c = clq_containing_nodes(engine, family(bnet.dag, i));
+  clqs_containing_family = find(all(B(:,family(bnet.dag, i)), 2)); % all selected columns must be 1
+  c = clqs_containing_family(argmin(w(clqs_containing_family)));  
+  engine.clq_ass_to_node(i) = c; 
+end
+
+% Make the jtree rooted, so there is a fixed message passing order.
+if strong
+  % the last clique is guaranteed to be a strong root
+  engine.root_clq = length(engine.cliques);
+else
+  % jtree_dbn_inf_engine requires the root to contain the interface.
+  % This may conflict with the strong root requirement! *********** BUG *************
+  engine.root_clq = clq_containing_nodes(engine, root);
+  if engine.root_clq <= 0
+    error(['no clique contains ' num2str(root)]);
+  end
+end  
+
+[engine.jtree, engine.preorder, engine.postorder] = mk_rooted_tree(engine.jtree, engine.root_clq);
+
+% collect 
+engine.postorder_parents = cell(1,length(engine.postorder));
+for n=engine.postorder(:)'
+  engine.postorder_parents{n} = parents(engine.jtree, n);
+end
+% distribute
+engine.preorder_children = cell(1,length(engine.preorder));
+for n=engine.preorder(:)'
+  engine.preorder_children{n} = children(engine.jtree, n);
+end
+
+  
+
+%%%%%%%%
+
+function engine = init_fields()
+
+engine.jtree = [];
+engine.cliques = [];
+engine.separator = [];
+engine.cliques_bitv = [];
+engine.clique_weight = [];
+engine.clpot = [];
+engine.clq_ass_to_node = [];
+engine.root_clq = [];
+engine.preorder = [];
+engine.postorder = [];
+engine.preorder_children = [];
+engine.postorder_parents = [];
+engine.maximize = [];
+engine.evidence = [];
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+/cliques_from_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/clq_containing_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/collect_evidence.c/1.1.1.1/Wed May 29 15:59:56 2002//
+/distribute_evidence.c/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/enter_soft_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/init_pot.c/1.1.1.1/Wed May 29 15:59:56 2002//
+/jtree_sparse_inf_engine.m/1.1.1.1/Sat Jan 18 22:11:32 2003//
+/marginal_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/set_fields.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@jtree_sparse_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/cliques_from_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function cliques = cliques_from_engine(engine)
+% CLIQUES_FROM_ENGINE Return the cliques stored inside the inf. engine (jtree)
+% cliques = cliques_from_engine(engine)
+
+cliques = engine.cliques;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/clq_containing_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function c = clq_containing_nodes(engine, nodes, fam)
+% CLQ_CONTAINING_NODES Find the lightest clique (if any) that contains the set of nodes
+% c = clq_containing_nodes(engine, nodes, family)
+%
+% If the optional 'family' argument is specified, it means nodes = family(nodes(end)).
+% (This is useful since clq_ass_to_node is not accessible to outsiders.)
+% Returns c=-1 if there is no such clique.
+
+if nargin < 3, fam = 0; else fam = 1; end
+
+if length(nodes)==1
+  c = engine.clq_ass_to_node(nodes(1));
+%elseif fam
+%  c = engine.clq_ass_to_node(nodes(end));
+else
+  B = engine.cliques_bitv;
+  w = engine.clique_weight;
+  clqs = find(all(B(:,nodes), 2)); % all selected columns must be 1
+  if isempty(clqs)
+    c = -1;
+  else
+    c = clqs(argmin(w(clqs)));     
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/collect_evidence.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,634 @@
+/* C mex for collect_evidence.c in @jtree_sparse_inf_engine directory */
+/* File enter_evidence.m in directory @jtree_sparse_inf_engine call it*/
+
+/******************************************/
+/* collect_evidence has 3 input & 2 output*/
+/* engine                                 */
+/* clpot                                  */
+/* seppot                                 */
+/*                                        */
+/* clpot                                  */
+/* seppot                                 */
+/******************************************/
+
+#include <math.h>
+#include <stdlib.h>
+#include "mex.h"
+
+int compare(const void* src1, const void* src2){
+	int i1 = *(int*)src1 ;
+	int i2 = *(int*)src2 ;
+	return i1-i2 ;
+}
+
+void ind_subv(int index, const int *cumprod, int n, int *bsubv){
+	int i;
+
+	for (i = n-1; i >= 0; i--) {
+		bsubv[i] = ((int)floor(index / cumprod[i]));
+		index = index % cumprod[i];
+	}
+}
+
+int subv_ind(const int n, const int *cumprod, const int *subv){
+	int i, index=0;
+
+	for(i=0; i<n; i++){
+		index += subv[i] * cumprod[i];
+	}
+	return index;
+}
+
+void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){
+	int i, j;
+	int *eff_cumprod, *subv, *diffsize, *diff_cumprod;
+
+	subv = malloc(diffdim * sizeof(int));
+	eff_cumprod = malloc(diffdim * sizeof(int));
+	diffsize = malloc(diffdim * sizeof(int));
+	diff_cumprod = malloc(diffdim * sizeof(int));
+	for(i=0; i<diffdim; i++){
+		eff_cumprod[i] = bCumprod[dmask[i]];
+		diffsize[i] = (int)pbSize[dmask[i]];
+	}
+	diff_cumprod[0] = 1;
+	for(i=0; i<diffdim-1; i++){
+		diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i];
+	}
+	for(i=0; i<ND; i++){
+		ind_subv(i, diff_cumprod, diffdim, subv);
+		weight[i] = 0;
+		for(j=0; j<diffdim; j++){
+			weight[i] += eff_cumprod[j] * subv[j];
+		}
+	}
+	free(eff_cumprod);
+	free(subv);
+	free(diffsize);
+	free(diff_cumprod);
+}
+
+void reset_nzmax(mxArray *spArray, const int old_nzmax, const int new_nzmax){
+	double *ptr;
+	void   *newptr;
+	int    *ir, *jc;
+	int    nbytes;
+
+	if(new_nzmax == old_nzmax) return;
+	nbytes = new_nzmax * sizeof(*ptr);
+	ptr = mxGetPr(spArray);
+	newptr = mxRealloc(ptr, nbytes);
+	mxSetPr(spArray, newptr);
+	nbytes = new_nzmax * sizeof(*ir);
+	ir = mxGetIr(spArray);
+	newptr = mxRealloc(ir, nbytes);
+	mxSetIr(spArray, newptr);
+	jc = mxGetJc(spArray);
+	jc[0] = 0;
+	jc[1] = new_nzmax;
+	mxSetNzmax(spArray, new_nzmax);
+}
+
+mxArray* convert_ill_table_to_sparse(const double *Table, const int *sequence, const int nzCounts, const int N){
+	mxArray *spTable;
+	int     i, temp, *irs, *jcs, count=0;
+	double  *sr;
+
+	spTable = mxCreateSparse(N, 1, nzCounts, mxREAL);
+    sr  = mxGetPr(spTable);
+    irs = mxGetIr(spTable);
+    jcs = mxGetJc(spTable);
+
+	jcs[0] = 0;
+	jcs[1] = nzCounts;
+
+	for(i=0; i<nzCounts; i++){
+		irs[i] = sequence[count];
+		count++;
+		temp = sequence[count];
+		sr[i] = Table[temp];
+		count++;
+	}
+	return spTable;
+}
+
+void multiply_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex, nzCounts=0;
+	int     *samemask, *diffmask, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *sequence, *weight;
+	double  *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *spr, *bpr;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	if(sdim == 0){
+		pTemp = mxCreateSparse(NB, 1, NB, mxREAL);
+		mxSetField(bigPot, 0, "T", pTemp);
+		bpr = mxGetPr(pTemp);
+		sir = mxGetIr(pTemp);
+		sjc = mxGetJc(pTemp);
+		sjc[0] = 0;
+		sjc[1] = NB;
+		for(i=0; i<NB; i++){
+			bpr[i] = *spr;
+			sir[i] = i;
+		}	
+		return;
+	}
+
+	NS = 1;
+	for(i=0; i<sdim; i++){
+		NS *= (int)psSize[i];
+	}
+	ND = NB / NS;
+
+	if(ND == 1){
+		pTemp1 = mxGetField(smallPot, 0, "T");
+		pTemp = mxDuplicateArray(pTemp1);
+		mxSetField(bigPot, 0, "T", pTemp);
+		return;
+	}
+
+
+	NZB = ND * NZS;
+
+	diffdim = bdim - sdim;
+	sequence = malloc(NZB * 2 * sizeof(int));
+	bigTable = malloc(NZB * sizeof(double));
+	samemask = malloc(sdim * sizeof(int));
+	diffmask = malloc(diffdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	weight = malloc(ND * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	count1 = 0;
+	for(i=0; i<bdim; i++){
+		match = 0;
+		for(j=0; j<sdim; j++){
+			if(pbDomain[i] == psDomain[j]){
+				samemask[count] = i;
+				match = 1;
+				count++;
+				break;
+			}
+		}
+		if(match == 0){
+			diffmask[count1] = i; 
+			count1++;
+		}
+	}
+
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	count = 0;
+	compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim);
+	for(i=0; i<NZS; i++){
+		sindex = sir[i];
+		ind_subv(sindex, sCumprod, sdim, ssubv);
+		temp = 0;
+		for(j=0; j<sdim; j++){
+			temp += ssubv[j] * bCumprod[samemask[j]];
+		}
+		for(j=0; j<ND; j++){
+			bindex = weight[j] + temp;
+			bigTable[nzCounts] = spr[i];
+			sequence[count] = bindex;
+			count++;
+			sequence[count] = nzCounts;
+			nzCounts++;
+			count++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	qsort(sequence, nzCounts, sizeof(int) * 2, compare);
+	pTemp = convert_ill_table_to_sparse(bigTable, sequence, nzCounts, NB);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(sequence); 
+	free(bigTable);
+	free(samemask);
+	free(diffmask);
+	free(bCumprod);
+	free(sCumprod);
+	free(weight);
+	free(ssubv);
+}
+
+void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0;
+	int     *mask, *result, *bir, *sir, *rir, *bjc, *sjc, *rjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, *rpr;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	if(sdim == 0){
+		for(i=0; i<NZB; i++){
+			bpr[i] *= *spr;
+		}	
+		return;
+	}
+
+	pTemp1 = mxCreateSparse(NB, 1, NZB, mxREAL);
+	rpr = mxGetPr(pTemp1);
+	rir = mxGetIr(pTemp1);
+	rjc = mxGetJc(pTemp1);
+	rjc[0] = 0;
+	rjc[1] = NZB;
+
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare);
+		if(result){
+			position = result - sir;
+			rpr[nzCounts] = bpr[i] * spr[position];
+			rir[nzCounts] = bindex;
+			nzCounts++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	reset_nzmax(pTemp1, NZB, nzCounts);
+	mxSetField(bigPot, 0, "T", pTemp1);
+
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+mxArray* marginal_null_to_spPot(const mxArray *bigPot, const mxArray *sDomain, const int maximize){
+	int     i, j, count, bdim, sdim, NB, NS, ND;
+	int     *mask, *sir, *sjc;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *spr;
+	mxArray *pTemp, *smallPot;
+	const char *field_names[] = {"domain", "T", "sizes"};
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	psDomain = mxGetPr(sDomain);
+	sdim = mxGetNumberOfElements(sDomain);
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+
+	smallPot = mxCreateStructMatrix(1, 1, 3, field_names);
+	pTemp = mxDuplicateArray(sDomain);
+	mxSetField(smallPot, 0, "domain", pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	if(sdim == 0){
+		pTemp = mxCreateSparse(1, 1, 1, mxREAL);
+		mxSetField(smallPot, 0, "T", pTemp);
+		spr = mxGetPr(pTemp);
+		sir = mxGetIr(pTemp);
+		sjc = mxGetJc(pTemp);
+		*spr = 0;
+		*sir = 0;
+		sjc[0] = 0;
+		sjc[1] = 1;
+		if(maximize) *spr = 1;
+		else *spr = NB;
+
+		pTemp = mxCreateDoubleMatrix(1, 1, mxREAL);
+		*mxGetPr(pTemp) = 1;
+		mxSetField(smallPot, 0, "sizes", pTemp);
+		return smallPot;
+	}
+
+	mask = malloc(sdim * sizeof(int));
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	pTemp = mxCreateDoubleMatrix(1, count, mxREAL);
+	psSize = mxGetPr(pTemp);
+	NS = 1;
+	for(i=0; i<count; i++){
+		psSize[i] = pbSize[mask[i]];
+		NS *= (int)psSize[i];
+	}
+	mxSetField(smallPot, 0, "sizes", pTemp);
+
+	ND = NB / NS;
+
+	pTemp = mxCreateSparse(NS, 1, NS, mxREAL);
+	mxSetField(smallPot, 0, "T", pTemp);
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	if(maximize){
+		for(i=0; i<NS; i++){
+			spr[i] = 1;
+			sir[i] = i;
+		}
+	}
+	else{
+		for(i=0; i<NS; i++){
+			spr[i] = ND;
+			sir[i] = i;
+		}
+	}
+	sjc[0] = 0;
+	sjc[1] = NS;
+
+	free(mask);
+	return smallPot;
+}
+
+mxArray* marginal_spPot_to_spPot(const mxArray *bigPot, const mxArray *sDomain, const int maximize){
+	int     i, j, count, bdim, sdim, NB, NS, NZB, position, bindex, sindex, nzCounts=0;
+	int     *mask, *sequence, *result, *bir, *bjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *sTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr;
+	mxArray *pTemp, *smallPot;
+	const char *field_names[] = {"domain", "T", "sizes"};
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	psDomain = mxGetPr(sDomain);
+	sdim = mxGetNumberOfElements(sDomain);
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	smallPot = mxCreateStructMatrix(1, 1, 3, field_names);
+	pTemp = mxDuplicateArray(sDomain);
+	mxSetField(smallPot, 0, "domain", pTemp);
+
+	if(sdim == 0){
+		pTemp = mxCreateSparse(1, 1, 1, mxREAL);
+		mxSetField(smallPot, 0, "T", pTemp);
+		spr = mxGetPr(pTemp);
+		bir = mxGetIr(pTemp);
+		bjc = mxGetJc(pTemp);
+		*spr = 0;
+		*bir = 0;
+		bjc[0] = 0;
+		bjc[1] = 1;
+		if(maximize){
+			for(i=0; i<NZB; i++){
+				*spr = (*spr < bpr[i])? bpr[i] : *spr;
+			}
+		}
+		else{
+			for(i=0; i<NZB; i++){
+				*spr += bpr[i];
+			}
+		}
+
+		pTemp = mxCreateDoubleMatrix(1, 1, mxREAL);
+		*mxGetPr(pTemp) = 1;
+		mxSetField(smallPot, 0, "sizes", pTemp);
+		return smallPot;
+	}
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	mask = malloc(sdim * sizeof(int));
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	pTemp = mxCreateDoubleMatrix(1, count, mxREAL);
+	psSize = mxGetPr(pTemp);
+	NS = 1;
+	for(i=0; i<count; i++){
+		psSize[i] = pbSize[mask[i]];
+		NS *= (int)psSize[i];
+	}
+	mxSetField(smallPot, 0, "sizes", pTemp);
+
+
+	sTable = malloc(NZB * sizeof(double));
+	sequence = malloc(NZB * 2 * sizeof(double));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	for(i=0; i<NZB; i++)sTable[i] = 0;
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	count = 0;
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sequence, nzCounts, sizeof(int)*2, compare);
+		if(result){
+			position = (result - sequence) / 2;
+			if(maximize) 
+				sTable[position] = (sTable[position] < bpr[i]) ? bpr[i] : sTable[position];
+			else sTable[position] += bpr[i];
+		}
+		else {
+			if(maximize) 
+				sTable[nzCounts] = (sTable[nzCounts] < bpr[i]) ? bpr[i] : sTable[nzCounts];
+			else sTable[nzCounts] += bpr[i];
+			sequence[count] = sindex;
+			count++;
+			sequence[count] = nzCounts;
+			nzCounts++;
+			count++;
+		}
+	}
+	
+	qsort(sequence, nzCounts, sizeof(int) * 2, compare);
+	pTemp = convert_ill_table_to_sparse(sTable, sequence, nzCounts, NS);
+	mxSetField(smallPot, 0, "T", pTemp);
+
+	free(sTable);
+	free(sequence);
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+
+	return smallPot;
+}
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, n, p, np, pn, loop, loops, nCliques, temp, maximize;
+	int     *collect_order;
+	double  *pr, *pr1;
+	mxArray *pTemp, *pTemp1, *pPostP, *pClpot, *pSeppot, *pSeparator;
+
+	pTemp = mxGetField(prhs[0], 0, "cliques");
+	nCliques = mxGetNumberOfElements(pTemp);
+	loops = nCliques - 1;
+	pTemp = mxGetField(prhs[0], 0, "maximize");
+	maximize = (int)mxGetScalar(pTemp);
+	pSeparator = mxGetField(prhs[0], 0, "separator");
+
+	collect_order = malloc(2 * loops * sizeof(int));
+
+	pTemp = mxGetField(prhs[0], 0, "postorder");
+	pr = mxGetPr(pTemp);
+	pPostP = mxGetField(prhs[0], 0, "postorder_parents");
+	for(i=0; i<loops; i++){
+		temp = (int)pr[i] - 1;
+		pTemp = mxGetCell(pPostP, temp);
+		pr1 = mxGetPr(pTemp);
+		collect_order[i] = (int)pr1[0] - 1;
+		collect_order[i+loops] = temp;
+	}
+
+	plhs[0] = mxDuplicateArray(prhs[1]);
+	plhs[1] = mxDuplicateArray(prhs[2]);
+
+	for(loop=0; loop<loops; loop++){
+		p = collect_order[loop];
+		n = collect_order[loop+loops];
+		np = p * nCliques + n;
+		pn = n * nCliques + p;
+		pClpot = mxGetCell(plhs[0], n);
+		pTemp1 = mxGetField(pClpot, 0, "T");
+		pTemp = mxGetCell(pSeparator, pn);
+		if(pTemp1)
+			pSeppot = marginal_spPot_to_spPot(pClpot, pTemp, maximize);
+		else pSeppot = marginal_null_to_spPot(pClpot, pTemp, maximize);
+		mxSetCell(plhs[1], pn, pSeppot);
+
+		pClpot = mxGetCell(plhs[0], p);
+		pTemp1 = mxGetField(pClpot, 0, "T");
+		if(pTemp1)
+			multiply_spPot_by_spPot(pClpot, pSeppot);
+		else multiply_null_by_spPot(pClpot, pSeppot);
+	}
+	free(collect_order);
+}
+	
+
+
+
+
+
Binary file _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/collect_evidence.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/distribute_evidence.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,618 @@
+/* C mex for distribute_evidence.c in @jtree_sparse_inf_engine directory*/
+/* File enter_evidence.m in directory @jtree_sparse_inf_engine call it  */
+
+/*********************************************/
+/* distribute_evidence has 3 input & 2 output*/
+/* engine                                    */
+/* clpot                                     */
+/* seppot                                    */
+/*                                           */
+/* clpot                                     */
+/* seppot                                    */
+/*********************************************/
+
+#include <math.h>
+#include <stdlib.h>
+#include "mex.h"
+
+int compare(const void* src1, const void* src2){
+	int i1 = *(int*)src1 ;
+	int i2 = *(int*)src2 ;
+	return i1-i2 ;
+}
+
+void ind_subv(int index, const int *cumprod, int n, int *bsubv){
+	int i;
+
+	for (i = n-1; i >= 0; i--) {
+		bsubv[i] = ((int)floor(index / cumprod[i]));
+		index = index % cumprod[i];
+	}
+}
+
+int subv_ind(const int n, const int *cumprod, const int *subv){
+	int i, index=0;
+
+	for(i=0; i<n; i++){
+		index += subv[i] * cumprod[i];
+	}
+	return index;
+}
+
+void reset_nzmax(mxArray *spArray, const int old_nzmax, const int new_nzmax){
+	double *ptr;
+	void   *newptr;
+	int    *ir, *jc;
+	int    nbytes;
+
+	if(new_nzmax == old_nzmax) return;
+	nbytes = new_nzmax * sizeof(*ptr);
+	ptr = mxGetPr(spArray);
+	newptr = mxRealloc(ptr, nbytes);
+	mxSetPr(spArray, newptr);
+	nbytes = new_nzmax * sizeof(*ir);
+	ir = mxGetIr(spArray);
+	newptr = mxRealloc(ir, nbytes);
+	mxSetIr(spArray, newptr);
+	jc = mxGetJc(spArray);
+	jc[0] = 0;
+	jc[1] = new_nzmax;
+	mxSetNzmax(spArray, new_nzmax);
+}
+
+void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){
+	int i, j;
+	int *eff_cumprod, *subv, *diffsize, *diff_cumprod;
+
+	subv = malloc(diffdim * sizeof(int));
+	eff_cumprod = malloc(diffdim * sizeof(int));
+	diffsize = malloc(diffdim * sizeof(int));
+	diff_cumprod = malloc(diffdim * sizeof(int));
+	for(i=0; i<diffdim; i++){
+		eff_cumprod[i] = bCumprod[dmask[i]];
+		diffsize[i] = (int)pbSize[dmask[i]];
+	}
+	diff_cumprod[0] = 1;
+	for(i=0; i<diffdim-1; i++){
+		diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i];
+	}
+	for(i=0; i<ND; i++){
+		ind_subv(i, diff_cumprod, diffdim, subv);
+		weight[i] = 0;
+		for(j=0; j<diffdim; j++){
+			weight[i] += eff_cumprod[j] * subv[j];
+		}
+	}
+	free(eff_cumprod);
+	free(subv);
+	free(diffsize);
+	free(diff_cumprod);
+}
+
+mxArray* convert_ill_table_to_sparse(const double *Table, const int *sequence, const int nzCounts, const int N){
+	mxArray *spTable;
+	int     i, temp, *irs, *jcs, count=0;
+	double  *sr;
+
+	spTable = mxCreateSparse(N, 1, nzCounts, mxREAL);
+    sr  = mxGetPr(spTable);
+    irs = mxGetIr(spTable);
+    jcs = mxGetJc(spTable);
+
+	jcs[0] = 0;
+	jcs[1] = nzCounts;
+
+	for(i=0; i<nzCounts; i++){
+		irs[i] = sequence[count];
+		count++;
+		temp = sequence[count];
+		sr[i] = Table[temp];
+		count++;
+	}
+	return spTable;
+}
+
+void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0;
+	int     *mask, *result, *bir, *sir, *rir, *bjc, *sjc, *rjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, *rpr;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	if(sdim == 0){
+		for(i=0; i<NZB; i++){
+			bpr[i] *= *spr;
+		}	
+		return;
+	}
+
+	pTemp1 = mxCreateSparse(NB, 1, NZB, mxREAL);
+	rpr = mxGetPr(pTemp1);
+	rir = mxGetIr(pTemp1);
+	rjc = mxGetJc(pTemp1);
+	rjc[0] = 0;
+	rjc[1] = NZB;
+
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare);
+		if(result){
+			position = result - sir;
+			rpr[nzCounts] = bpr[i] * spr[position];
+			rir[nzCounts] = bindex;
+			nzCounts++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	reset_nzmax(pTemp1, NZB, nzCounts);
+	mxSetField(bigPot, 0, "T", pTemp1);
+
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+void marginal_spPot_to_spPot(const mxArray *bigPot, mxArray *smallPot, const int maximize){
+	int     i, j, count, bdim, sdim, NB, NS, NZB, position, bindex, sindex, nzCounts=0;
+	int     *mask, *sequence, *result, *bir, *bjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *sTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr;
+	mxArray *pTemp;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+	NS = 1;
+	for(i=0; i<sdim; i++){
+		NS *= (int)psSize[i];
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	if(sdim == 0){
+		pTemp = mxGetField(smallPot, 0, "T");
+		spr = mxGetPr(pTemp);
+		*spr = 0;
+		if(maximize){
+			for(i=0; i<NZB; i++){
+				*spr = (*spr < bpr[i])? bpr[i] : *spr;
+			}
+		}
+		else{
+			for(i=0; i<NZB; i++){
+				*spr += bpr[i];
+			}
+		}	
+		return;
+	}
+
+	mask = malloc(sdim * sizeof(int));
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+
+
+	sTable = malloc(NZB * sizeof(double));
+	sequence = malloc(NZB * 2 * sizeof(double));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	for(i=0; i<NZB; i++){
+		sTable[i] = 0;
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	count = 0;
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sequence, nzCounts, sizeof(int)*2, compare);
+		if(result){
+			position = (result - sequence) / 2;
+			if(maximize)
+				sTable[position] = (sTable[position] < bpr[i]) ? bpr[i] : sTable[position];
+			else sTable[position] += bpr[i];
+		}
+		else {
+			if(maximize) 
+				sTable[nzCounts] = (sTable[nzCounts] < bpr[i]) ? bpr[i] : sTable[nzCounts];
+			else sTable[nzCounts] += bpr[i];
+			sequence[count] = sindex;
+			count++;
+			sequence[count] = nzCounts;
+			nzCounts++;
+			count++;
+		}
+	}
+	
+	pTemp = mxGetField(smallPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	qsort(sequence, nzCounts, sizeof(int) * 2, compare);
+	pTemp = convert_ill_table_to_sparse(sTable, sequence, nzCounts, NS);
+	mxSetField(smallPot, 0, "T", pTemp);
+
+	free(sTable);
+	free(sequence);
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+void divide_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex;
+	int     *samemask, *diffmask, *rir, *rjc, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *weight;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *rpr, *spr, value;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	if(sdim == 0){
+		pTemp1 = mxGetField(bigPot, 0, "T");
+		if(pTemp1)mxDestroyArray(pTemp1);
+		pTemp = mxCreateSparse(NB, 1, NB, mxREAL);
+		mxSetField(bigPot, 0, "T", pTemp);
+		rpr = mxGetPr(pTemp);
+		rir = mxGetIr(pTemp);
+		rjc = mxGetJc(pTemp);
+		rjc[0] = 0;
+		rjc[1] = NB;
+		value = *spr;
+		if(value == 0) value = 1;
+		for(i=0; i<NB; i++){
+			rpr[i] = 1 / value;
+			rir[i] = i;
+		}	
+		return;
+	}
+
+	NS = 1;
+	for(i=0; i<sdim; i++){
+		NS *= (int)psSize[i];
+	}
+	ND = NB / NS;
+
+	pTemp = mxCreateSparse(NB, 1, NB, mxREAL);
+	rpr = mxGetPr(pTemp);
+	rir = mxGetIr(pTemp);
+	rjc = mxGetJc(pTemp);
+	rjc[0] = 0;
+	rjc[1] = NB;
+	for(i=0; i<NB; i++){
+		rpr[i] = 1;
+		rir[i] = i;
+	}
+
+	NZB = ND * NZS;
+
+	diffdim = bdim - sdim;
+	samemask = malloc(sdim * sizeof(int));
+	diffmask = malloc(diffdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	weight = malloc(ND * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	count1 = 0;
+	for(i=0; i<bdim; i++){
+		match = 0;
+		for(j=0; j<sdim; j++){
+			if(pbDomain[i] == psDomain[j]){
+				samemask[count] = i;
+				match = 1;
+				count++;
+				break;
+			}
+		}
+		if(match == 0){
+			diffmask[count1] = i; 
+			count1++;
+		}
+	}
+
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	count = 0;
+	compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim);
+	for(i=0; i<NZS; i++){
+		sindex = sir[i];
+		ind_subv(sindex, sCumprod, sdim, ssubv);
+		temp = 0;
+		for(j=0; j<sdim; j++){
+			temp += ssubv[j] * bCumprod[samemask[j]];
+		}
+		for(j=0; j<ND; j++){
+			bindex = weight[j] + temp;
+			rpr[bindex] = 1 / (spr[i]);
+		}
+	}
+
+	pTemp1 = mxGetField(bigPot, 0, "T");
+	if(pTemp1)mxDestroyArray(pTemp1);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(samemask);
+	free(diffmask);
+	free(bCumprod);
+	free(sCumprod);
+	free(weight);
+	free(ssubv);
+}
+
+void divide_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex;
+	int     *mask, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp1 = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp1);
+	bir = mxGetIr(pTemp1);
+	bjc = mxGetJc(pTemp1);
+	NZB = bjc[1];
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	if(sdim == 0){
+		value = *spr;
+		if(value == 0)value = 1;
+		for(i=0; i<NZB; i++){
+			bpr[i] /= value;
+		}	
+		return;
+	}
+
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare);
+		if(result){
+			position = result - sir;
+			bpr[i] /= spr[position];
+		}
+	}
+
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, j, loop, loops, nCliques, temp, count, parent, child, maximize, *distribute_order;
+	double  *pr, *pr1;
+	mxArray *pTemp, *pPreCh, *pClpot, *pSeppot;
+
+	pTemp = mxGetField(prhs[0], 0, "cliques");
+	nCliques = mxGetNumberOfElements(pTemp);
+	loops = nCliques - 1;
+	pTemp = mxGetField(prhs[0], 0, "maximize");
+	maximize = (int)mxGetScalar(pTemp);
+
+	distribute_order = malloc(2 * loops * sizeof(int));
+	pTemp = mxGetField(prhs[0], 0, "preorder");
+	pr = mxGetPr(pTemp);
+	pPreCh = mxGetField(prhs[0], 0, "preorder_children");
+	count = 0;
+	for(i=0; i<nCliques; i++){
+		temp = (int)pr[i] - 1;
+		pTemp = mxGetCell(pPreCh, temp);
+		pr1 = mxGetPr(pTemp);
+		loop = mxGetNumberOfElements(pTemp);
+		for(j=0; j<loop; j++){
+			distribute_order[count] = temp;
+			distribute_order[count + loops] = (int)pr1[j] - 1;
+			count++;
+		}
+	}
+
+	plhs[0] = mxDuplicateArray(prhs[1]);
+	plhs[1] = mxDuplicateArray(prhs[2]);
+
+	for(loop=0; loop<loops; loop++){
+		parent = distribute_order[loop];
+		child  = distribute_order[loop+loops];
+		i = nCliques * child + parent;
+		pClpot = mxGetCell(plhs[0], child);
+		pTemp = mxGetField(pClpot, 0, "T");
+		pSeppot = mxGetCell(plhs[1], i);
+		if(pTemp){
+			if(mxIsEmpty(pTemp)) 
+				divide_null_by_spPot(pClpot, pSeppot);
+			else 
+				divide_spPot_by_spPot(pClpot, pSeppot);
+		}
+		else divide_null_by_spPot(pClpot, pSeppot);
+
+		pClpot = mxGetCell(plhs[0], parent);
+		marginal_spPot_to_spPot(pClpot, pSeppot, maximize);
+		mxSetCell(plhs[1], i, pSeppot);
+
+		pClpot = mxGetCell(plhs[0], child);
+		multiply_spPot_by_spPot(pClpot, pSeppot); 
+	}
+	free(distribute_order);
+}
Binary file _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/distribute_evidence.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,100 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (jtree)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i} = [] if X(i) is hidden, and otherwise contains its observed value (scalar or column vector).
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product instead of sum-product [0]
+% soft    - a cell array of soft/virtual evidence;
+%           soft{i} is a prob. distrib. over i's values, or [] [ cell(1,N) ]
+%
+% e.g., engine = enter_evidence(engine, ev, 'soft', soft_ev)
+%
+% For backwards compatibility with BNT2, you can also specify the parameters in the following order
+%  engine = enter_evidence(engine, ev, soft_ev)
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes(:);
+N = length(bnet.dag);
+
+engine.evidence = evidence; % store this for marginal_nodes with add_ev option
+  
+% set default params
+exclude = [];
+soft_evidence = cell(1,N);
+maximize = 0;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  if iscell(args{1})
+    soft_evidence = args{1};
+  else
+    for i=1:2:nargs
+      switch args{i},
+       case 'soft',    soft_evidence = args{i+1}; 
+       case 'maximize', maximize = args{i+1}; 
+       otherwise,  
+	error(['invalid argument name ' args{i}]);       
+      end
+    end
+  end
+end
+
+engine.maximize = maximize;
+
+onodes = find(~isemptycell(evidence));
+hnodes = find(isemptycell(evidence));
+pot_type = determine_pot_type(bnet, onodes);
+ if strcmp(pot_type, 'cg')
+  check_for_cd_arcs(onodes, bnet.cnodes, bnet.dag);
+end
+
+hard_nodes = 1:N;
+soft_nodes = find(~isemptycell(soft_evidence));
+S = length(soft_nodes);
+if S > 0
+  assert(pot_type == 'd');
+  assert(mysubset(soft_nodes, bnet.dnodes));
+end
+ 
+% Evaluate CPDs with evidence, and convert to potentials  
+pot = cell(1, N+S);
+for n=1:N
+  fam = family(bnet.dag, n);
+  e = bnet.equiv_class(n);
+  if isempty(bnet.CPD{e})
+    error(['must define CPD ' num2str(e)])
+  else
+    pot{n} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence);
+  end
+end
+
+for i=1:S
+  n = soft_nodes(i);
+  pot{N+i} = dpot(n, ns(n), soft_evidence{n});
+end
+clqs = engine.clq_ass_to_node([hard_nodes soft_nodes]); 
+
+[clpot, seppot] = init_pot(engine, clqs, pot, pot_type, onodes);
+[clpot, seppot] = collect_evidence(engine, clpot, seppot);
+[clpot, seppot] = distribute_evidence(engine, clpot, seppot);
+C = length(clpot);
+ll = zeros(1, C);
+for i=1:C
+   domain = clpot{i}.domain;
+   sizes = clpot{i}.sizes;
+   T = clpot{i}.T;
+   clpot{i} = dpot(domain, sizes, T);
+end
+   
+for i=1:C
+  [clpot{i}, ll(i)] = normalize_pot(clpot{i});
+end
+loglik = ll(1); % we can extract the likelihood from any clique
+
+engine.clpot = clpot;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/enter_soft_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function [clpot, loglik] = enter_soft_evidence(engine, clique, potential, onodes, pot_type)
+% ENTER_SOFT_EVIDENCE Add the specified potentials to the network (jtree)
+% [clpot, loglik] = enter_soft_evidence(engine, clique, potential, onodes, pot_type, maximize)
+%
+% We multiply potential{i} onto clique(i) before propagating.
+% We return all the modified clique potentials.
+
+[clpot, seppot] = init_pot(engine, clique, potential, pot_type, onodes);
+[clpot, seppot] = collect_evidence(engine, clpot, seppot);
+[clpot, seppot] = distribute_evidence(engine, clpot, seppot);
+
+C = length(clpot);
+ll = zeros(1, C);
+for i=1:C
+  [clpot{i}, ll(i)] = normalize_pot(clpot{i});
+end
+loglik = ll(1); % we can extract the likelihood from any clique
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/init_pot.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,624 @@
+/* C mex init_pot for in @jtree_sparse_inf_engine directory               */
+/* The file enter_evidence.m in directory @jtree_sparse_inf_engine call it*/
+
+/**************************************/
+/* init_pot.c has 5 input & 2 output  */
+/* engine                             */
+/* clqs                               */
+/* pots                               */
+/* pot_type                           */
+/* onodes                             */
+/*                                    */
+/* clpot                              */
+/* seppot                             */
+/**************************************/
+#include <math.h>
+#include <stdlib.h>
+#include "mex.h"
+
+int compare(const void* src1, const void* src2){
+	int i1 = *(int*)src1 ;
+	int i2 = *(int*)src2 ;
+	return i1-i2 ;
+}
+
+void ind_subv(int index, const int *cumprod, int n, int *bsubv){
+	int i;
+
+	for (i = n-1; i >= 0; i--) {
+		bsubv[i] = ((int)floor(index / cumprod[i]));
+		index = index % cumprod[i];
+	}
+}
+
+int subv_ind(const int n, const int *cumprod, const int *subv){
+	int i, index=0;
+
+	for(i=0; i<n; i++){
+		index += subv[i] * cumprod[i];
+	}
+	return index;
+}
+
+void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){
+	int i, j;
+	int *eff_cumprod, *subv, *diffsize, *diff_cumprod;
+
+	subv = malloc(diffdim * sizeof(int));
+	eff_cumprod = malloc(diffdim * sizeof(int));
+	diffsize = malloc(diffdim * sizeof(int));
+	diff_cumprod = malloc(diffdim * sizeof(int));
+	for(i=0; i<diffdim; i++){
+		eff_cumprod[i] = bCumprod[dmask[i]];
+		diffsize[i] = (int)pbSize[dmask[i]];
+	}
+	diff_cumprod[0] = 1;
+	for(i=0; i<diffdim-1; i++){
+		diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i];
+	}
+	for(i=0; i<ND; i++){
+		ind_subv(i, diff_cumprod, diffdim, subv);
+		weight[i] = 0;
+		for(j=0; j<diffdim; j++){
+			weight[i] += eff_cumprod[j] * subv[j];
+		}
+	}
+	free(eff_cumprod);
+	free(subv);
+	free(diffsize);
+	free(diff_cumprod);
+}
+
+void reset_nzmax(mxArray *spArray, const int old_nzmax, const int new_nzmax){
+	double *ptr;
+	void   *newptr;
+	int    *ir, *jc;
+	int    nbytes;
+
+	if(new_nzmax == old_nzmax) return;
+	nbytes = new_nzmax * sizeof(*ptr);
+	ptr = mxGetPr(spArray);
+	newptr = mxRealloc(ptr, nbytes);
+	mxSetPr(spArray, newptr);
+	nbytes = new_nzmax * sizeof(*ir);
+	ir = mxGetIr(spArray);
+	newptr = mxRealloc(ir, nbytes);
+	mxSetIr(spArray, newptr);
+	jc = mxGetJc(spArray);
+	jc[0] = 0;
+	jc[1] = new_nzmax;
+	mxSetNzmax(spArray, new_nzmax);
+}
+
+mxArray* convert_ill_table_to_sparse(const double *bigTable, const int *sequence, const int nzCounts, const int NB){
+	mxArray *spTable;
+	int     i, temp, *irs, *jcs, count=0;
+	double  *sr;
+
+	spTable = mxCreateSparse(NB, 1, nzCounts, mxREAL);
+    sr  = mxGetPr(spTable);
+    irs = mxGetIr(spTable);
+    jcs = mxGetJc(spTable);
+
+	jcs[0] = 0;
+	jcs[1] = nzCounts;
+
+	for(i=0; i<nzCounts; i++){
+		irs[i] = sequence[count];
+		count++;
+		temp = sequence[count];
+		sr[i] = bigTable[temp];
+		count++;
+	}
+	return spTable;
+}
+
+void multiply_null_by_fuPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, NB, NS, siz_b, siz_s, ndim, nzCounts=0;
+	int     *mask, *sx, *sy, *cpsy, *subs, *s, *cpsy2, *bir, *bjc;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *spr, *bpr, value;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	siz_b = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	siz_s = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<siz_b; i++){
+		NB *= (int)pbSize[i];
+	}
+	NS = 1;
+	for(i=0; i<siz_s; i++){
+		NS *= (int)psSize[i];
+	}
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+
+	pTemp1 = mxCreateSparse(NB, 1, NB, mxREAL);
+	bpr = mxGetPr(pTemp1);
+	bir = mxGetIr(pTemp1);
+	bjc = mxGetJc(pTemp1);
+	bjc[0] = 0;
+	bjc[1] = NB;
+
+	if(NS == 1){
+		value = *spr;
+		for(i=0; i<NB; i++){
+			bpr[i] = value;
+			bir[i] = i;
+		}
+		nzCounts = NB;
+		pTemp = mxGetField(bigPot, 0, "T");
+		if(pTemp)mxDestroyArray(pTemp);
+		reset_nzmax(pTemp1, NB, nzCounts);
+		mxSetField(bigPot, 0, "T", pTemp1);
+		return;
+	}
+
+	if(NS == NB){
+		for(i=0; i<NB; i++){
+			if(spr[i] != 0){
+				bpr[nzCounts] = spr[i];
+				bir[nzCounts] = i;
+				nzCounts++;
+			}
+		}
+		pTemp = mxGetField(bigPot, 0, "T");
+		if(pTemp)mxDestroyArray(pTemp);
+		reset_nzmax(pTemp1, NB, nzCounts);
+		mxSetField(bigPot, 0, "T", pTemp1);
+		return;
+	}
+
+	mask = malloc(siz_s * sizeof(int));
+	count = 0;
+	for(i=0; i<siz_s; i++){
+		for(j=0; j<siz_b; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	ndim = siz_b;
+	sx = (int *)malloc(sizeof(int)*ndim);
+	sy = (int *)malloc(sizeof(int)*ndim);
+	for(i=0; i<ndim; i++){
+		sx[i] = (int)pbSize[i];
+		sy[i] = 1;
+	}
+	for(i=0; i<count; i++){
+		sy[mask[i]] = sx[mask[i]];
+	}
+
+	s = (int *)malloc(sizeof(int)*ndim);
+	*(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1;
+	subs =   (int *)malloc(sizeof(int)*ndim);
+	cpsy2 =  (int *)malloc(sizeof(int)*ndim);
+	for(i = 0; i < ndim; i++){
+		subs[i] = 0;
+		s[i] = sx[i] - 1;
+	}
+			
+	for(i = 0; i < ndim-1; i++){
+		cpsy[i+1] = cpsy[i]*sy[i]--;
+		cpsy2[i] = cpsy[i]*sy[i];
+	}
+	cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]);
+
+	for(j=0; j<NB; j++){
+		if(*spr != 0){
+			bpr[nzCounts] = *spr;
+			bir[nzCounts] = j;
+			nzCounts++;
+		}
+		for(i = 0; i < ndim; i++){
+			if(subs[i] == s[i]){
+				subs[i] = 0;
+				if(sy[i])
+					spr -= cpsy2[i];
+			}
+			else{
+				subs[i]++;
+				if(sy[i])
+					spr += cpsy[i];
+				break;
+			}
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	reset_nzmax(pTemp1, NB, nzCounts);
+	mxSetField(bigPot, 0, "T", pTemp1);
+
+	free(sx);
+	free(sy);
+	free(s);
+	free(cpsy);
+	free(subs);
+	free(cpsy2);
+    free(mask);
+}
+
+void multiply_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex, nzCounts=0;
+	int     *samemask, *diffmask, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *sequence, *weight;
+	double  *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *spr;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+	NS = 1;
+	for(i=0; i<sdim; i++){
+		NS *= (int)psSize[i];
+	}
+	ND = NB / NS;
+
+	if(ND == 1){
+		pTemp = mxGetField(bigPot, 0, "T");
+		if(pTemp)mxDestroyArray(pTemp);
+		pTemp1 = mxGetField(smallPot, 0, "T");
+		pTemp = mxDuplicateArray(pTemp1);
+		mxSetField(bigPot, 0, "T", pTemp);
+		return;
+	}
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	NZB = ND * NZS;
+
+	diffdim = bdim - sdim;
+	sequence = malloc(NZB * 2 * sizeof(int));
+	bigTable = malloc(NZB * sizeof(double));
+	samemask = malloc(sdim * sizeof(int));
+	diffmask = malloc(diffdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	weight = malloc(ND * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	count1 = 0;
+	for(i=0; i<bdim; i++){
+		match = 0;
+		for(j=0; j<sdim; j++){
+			if(pbDomain[i] == psDomain[j]){
+				samemask[count] = i;
+				match = 1;
+				count++;
+				break;
+			}
+		}
+		if(match == 0){
+			diffmask[count1] = i; 
+			count1++;
+		}
+	}
+
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	count = 0;
+	compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim);
+	for(i=0; i<NZS; i++){
+		sindex = sir[i];
+		ind_subv(sindex, sCumprod, sdim, ssubv);
+		temp = 0;
+		for(j=0; j<sdim; j++){
+			temp += ssubv[j] * bCumprod[samemask[j]];
+		}
+		for(j=0; j<ND; j++){
+			bindex = weight[j] + temp;
+			bigTable[nzCounts] = spr[i];
+			sequence[count] = bindex;
+			count++;
+			sequence[count] = nzCounts;
+			nzCounts++;
+			count++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	qsort(sequence, nzCounts, sizeof(int) * 2, compare);
+	pTemp = convert_ill_table_to_sparse(bigTable, sequence, nzCounts, NB);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(sequence); 
+	free(bigTable);
+	free(samemask);
+	free(diffmask);
+	free(bCumprod);
+	free(sCumprod);
+	free(weight);
+	free(ssubv);
+}
+
+void multiply_spPot_by_fuPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, bdim, sdim, NB, NZB, bindex, sindex, nzCounts=0;
+	int     *mask, *bir, *bjc, *rir, *rjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, *rpr, value;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+
+	pTemp1 = mxCreateSparse(NB, 1, NZB, mxREAL);
+	rpr = mxGetPr(pTemp1);
+	rir = mxGetIr(pTemp1);
+	rjc = mxGetJc(pTemp1);
+	rjc[0] = 0;
+	rjc[1] = NZB;
+
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		value = spr[sindex];
+		if(value != 0){
+			rpr[nzCounts] = bpr[i] * value;
+			rir[nzCounts] = bindex;
+			nzCounts++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	reset_nzmax(pTemp1, NZB, nzCounts);
+	mxSetField(bigPot, 0, "T", pTemp1);
+
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0;
+	int     *mask, *result, *bir, *sir, *rir, *bjc, *sjc, *rjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, *rpr;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	pTemp1 = mxCreateSparse(NB, 1, NZB, mxREAL);
+	rpr = mxGetPr(pTemp1);
+	rir = mxGetIr(pTemp1);
+	rjc = mxGetJc(pTemp1);
+	rjc[0] = 0;
+	rjc[1] = NZB;
+
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare);
+		if(result){
+			position = result - sir;
+			rpr[nzCounts] = bpr[i] * spr[position];
+			rir[nzCounts] = bindex;
+			nzCounts++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	reset_nzmax(pTemp1, NZB, nzCounts);
+	mxSetField(bigPot, 0, "T", pTemp1);
+
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, j, c, loop, nNodes, nCliques, ndomain, ns_num, nOnodes, dims[2];
+	double  *pClqs, *pr, *pt, *pSize, *eff_ns;
+	mxArray *pTemp, *pTemp1, *pStruct, *pCliques, *pBigpot, *pSmallpot;
+	const char *field_names[] = {"domain", "T", "sizes"};
+
+	nNodes = mxGetNumberOfElements(prhs[1]);
+	pCliques = mxGetField(prhs[0], 0, "cliques");
+	nCliques = mxGetNumberOfElements(pCliques);
+	pTemp = mxGetField(prhs[0], 0, "actual_node_sizes");
+	ns_num = mxGetNumberOfElements(pTemp);
+	pSize = mxGetPr(pTemp);
+
+	eff_ns = (double *)malloc(ns_num * sizeof(double));
+	for(i=0; i<ns_num; i++) eff_ns[i] = pSize[i];
+	nOnodes = mxGetNumberOfElements(prhs[4]);
+	pr = mxGetPr(prhs[4]);
+	for(i=0; i<nOnodes; i++) eff_ns[(int)pr[i] - 1] = 1;
+
+	plhs[0] = mxCreateCellArray(1, &nCliques);
+    for(i=0; i<nCliques; i++){
+        pStruct = mxCreateStructMatrix(1, 1, 3, field_names);
+		mxSetCell(plhs[0], i, pStruct);
+		pTemp = mxGetCell(pCliques, i);
+		ndomain = mxGetNumberOfElements(pTemp);
+		pt = mxGetPr(pTemp);
+		pTemp1 = mxDuplicateArray(pTemp);
+		mxSetField(pStruct, 0, "domain", pTemp1);
+		
+		pTemp = mxCreateDoubleMatrix(1, ndomain, mxREAL);
+		mxSetField(pStruct, 0, "sizes", pTemp);
+		pr = mxGetPr(pTemp);
+        for(j=0; j<ndomain; j++){
+            pr[j] = eff_ns[(int)pt[j]-1];
+        }
+    }
+
+	pClqs = mxGetPr(prhs[1]);
+	for(loop=0; loop<nNodes; loop++){
+		c = (int)pClqs[loop] - 1;
+		pSmallpot = mxGetCell(prhs[2], loop);
+		pTemp = mxGetField(pSmallpot, 0, "T");
+		pBigpot = mxGetCell(plhs[0], c);
+		pTemp1 = mxGetField(pBigpot, 0, "T");
+		if(pTemp1){
+			if(mxIsSparse(pTemp))
+				multiply_spPot_by_spPot(pBigpot, pSmallpot);
+			else multiply_spPot_by_fuPot(pBigpot, pSmallpot);
+		}
+		else{
+			if(mxIsSparse(pTemp))
+				multiply_null_by_spPot(pBigpot, pSmallpot);
+			else multiply_null_by_fuPot(pBigpot, pSmallpot);
+		}		
+	}
+
+	free(eff_ns);
+	dims[0] = nCliques;
+	dims[1] = nCliques;
+	plhs[1] = mxCreateCellArray(2, dims);
+}
+
+
Binary file _FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/init_pot.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/jtree_sparse_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,126 @@
+function engine = jtree_sparse_inf_engine(bnet, varargin)
+% JTREE_SPARSE_INF_ENGINE Junction tree inference engine when CPTs and Potentials are sparse
+% engine = jtree_sparse_inf_engine(bnet, ...)
+% It differs from jtree_inf_engine with all CPTs and potentials are 1D sparse arrays.
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% clusters  - a cell array of sets of nodes we want to ensure are in the same clique (in addition to families) [ {} ]
+% root      - the root of the junction tree will be a clique that contains this set of nodes [N]
+% stages    - stages{t} is a set of nodes we want to eliminate before stages{t+1}, ... [ {1:N} ]
+%
+% e.g., engine = jtree_inf_engine(bnet, 'maximize', 1);
+%
+% For more details on the junction tree algorithm, see
+% - "Probabilistic networks and expert systems", Cowell, Dawid, Lauritzen and Spiegelhalter, Springer, 1999
+% - "Inference in Belief Networks: A procedural guide", C. Huang and A. Darwiche, 
+%      Intl. J. Approximate Reasoning, 15(3):225-263, 1996.
+
+
+% set default params
+N = length(bnet.dag);
+clusters = {};
+root = N;
+stages = { 1:N };
+
+if nargin >= 2
+  args = varargin;
+  nargs = length(args);
+  if ~isstr(args{1})
+    error('the interface to jtree has changed; now, onodes is not allowed and all optional params must be passed by name')
+  end
+  for i=1:2:nargs
+    switch args{i},
+     case 'clusters', clusters = args{i+1}; 
+     case 'root',     root = args{i+1}; 
+     case 'stages',   stages = args{i+1}; 
+     otherwise,  
+      error(['invalid argument name ' args{i}]);       
+    end
+  end
+end
+
+engine = init_fields;
+engine = class(engine, 'jtree_sparse_inf_engine', inf_engine(bnet));
+
+onodes = bnet.observed;
+%[engine.jtree, dummy, engine.cliques, B, w] = dag_to_jtree(bnet, onodes, stages, clusters);
+
+porder = determine_elim_constraints(bnet, onodes);
+strong = ~isempty(porder);
+ns = bnet.node_sizes(:);
+ns(onodes) = 1; % observed nodes have only 1 possible value
+[engine.jtree, root2, engine.cliques, B, w] = ...
+    graph_to_jtree(moralize(bnet.dag), ns, porder, stages, clusters);
+
+engine.cliques_bitv = B;
+engine.clique_weight = w;
+C = length(engine.cliques);
+engine.clpot = cell(1,C);
+
+% Compute the separators between connected cliques.
+[is,js] = find(engine.jtree > 0);
+engine.separator = cell(C,C);
+for k=1:length(is)
+  i = is(k); j = js(k);
+  engine.separator{i,j} = find(B(i,:) & B(j,:)); % intersect(cliques{i}, cliques{j});
+end
+
+% A node can be a member of many cliques, but is assigned to exactly one, to avoid
+% double-counting its CPD. We assign node i to clique c if c is the "lightest" clique that
+% contains i's family, so it can accomodate its CPD.
+
+engine.clq_ass_to_node = zeros(1, N);
+for i=1:N
+  %c = clq_containing_nodes(engine, family(bnet.dag, i));
+  clqs_containing_family = find(all(B(:,family(bnet.dag, i)), 2)); % all selected columns must be 1
+  c = clqs_containing_family(argmin(w(clqs_containing_family)));  
+  engine.clq_ass_to_node(i) = c; 
+end
+
+% Make the jtree rooted, so there is a fixed message passing order.
+engine.root_clq = clq_containing_nodes(engine, root);
+if engine.root_clq <= 0
+  error(['no clique contains ' num2str(root)]);
+end
+
+[engine.jtree, engine.preorder, engine.postorder] = mk_rooted_tree(engine.jtree, engine.root_clq);
+
+% collect 
+engine.postorder_parents = cell(1,length(engine.postorder));
+for n=engine.postorder(:)'
+  engine.postorder_parents{n} = parents(engine.jtree, n);
+end
+% distribute
+engine.preorder_children = cell(1,length(engine.preorder));
+for n=engine.preorder(:)'
+  engine.preorder_children{n} = children(engine.jtree, n);
+end
+
+ns = bnet.node_sizes;
+engine.actual_node_sizes = ns;
+ 
+
+%%%%%%%%
+
+function engine = init_fields()
+
+engine.jtree = [];
+engine.cliques = [];
+engine.separator = [];
+engine.cliques_bitv = [];
+engine.clique_weight = [];
+engine.clpot = [];
+engine.clq_ass_to_node = [];
+engine.root_clq = [];
+engine.preorder = [];
+engine.postorder = [];
+engine.preorder_children = [];
+engine.postorder_parents = [];
+engine.maximize = [];
+engine.evidence = [];
+engine.actual_node_sizes = [];
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function marginal = marginal_family(engine, i, add_ev)
+% MARGINAL_FAMILY Compute the marginal on the specified family (jtree)
+% marginal = marginal_family(engine, i)
+
+if nargin < 3, add_ev = 0; end
+assert(~add_ev);
+
+bnet = bnet_from_engine(engine);
+fam = family(bnet.dag, i);
+c = engine.clq_ass_to_node(i);
+marginal = pot_to_marginal(marginalize_pot(engine.clpot{c}, fam));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function marginal = marginal_nodes(engine, query, add_ev)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (jtree)
+% marginal = marginal_nodes(engine, query, add_ev)
+%
+% 'query' must be a subset of some clique; an error will be raised if not.
+% add_ev is an optional argument; if 1, we will "inflate" the marginal of observed nodes
+% to their original size, adding 0s to the positions which contradict the evidence
+
+if nargin < 3, add_ev = 0; end
+
+c = clq_containing_nodes(engine, query);
+if c == -1
+  error(['no clique contains ' num2str(query)]);
+end
+marginal = pot_to_marginal(marginalize_pot(engine.clpot{c}, query, engine.maximize));
+
+if add_ev
+  bnet = bnet_from_engine(engine);
+  %marginal = add_ev_to_dmarginal(marginal, engine.evidence, bnet.node_sizes);
+  marginal = add_evidence_to_gmarginal(marginal, engine.evidence, bnet.node_sizes, bnet.cnodes);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/collect_evidence.c/1.1.1.1/Wed May 29 15:59:56 2002//
+/distribute_evidence.c/1.1.1.1/Wed May 29 15:59:56 2002//
+/init_pot.c/1.1.1.1/Wed May 29 15:59:56 2002//
+/init_pot1.c/1.1.1.1/Wed May 29 15:59:56 2002//
+/init_pot1.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/collect_evidence.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,635 @@
+/* C mex for collect_evidence.c in @jtree_sparse_inf_engine directory */
+/* File enter_evidence.m in directory @jtree_sparse_inf_engine call it*/
+
+/******************************************/
+/* collect_evidence has 3 input & 2 output*/
+/* engine                                 */
+/* clpot                                  */
+/* seppot                                 */
+/*                                        */
+/* clpot                                  */
+/* seppot                                 */
+/******************************************/
+
+#include <math.h>
+#include <search.h>
+#include "mex.h"
+
+int compare(const void* src1, const void* src2){
+	int i1 = *(int*)src1 ;
+	int i2 = *(int*)src2 ;
+	return i1-i2 ;
+}
+
+void ind_subv(int index, const int *cumprod, int n, int *bsubv){
+	int i;
+
+	for (i = n-1; i >= 0; i--) {
+		bsubv[i] = ((int)floor(index / cumprod[i]));
+		index = index % cumprod[i];
+	}
+}
+
+int subv_ind(const int n, const int *cumprod, const int *subv){
+	int i, index=0;
+
+	for(i=0; i<n; i++){
+		index += subv[i] * cumprod[i];
+	}
+	return index;
+}
+
+void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){
+	int i, j;
+	int *eff_cumprod, *subv, *diffsize, *diff_cumprod;
+
+	subv = malloc(diffdim * sizeof(int));
+	eff_cumprod = malloc(diffdim * sizeof(int));
+	diffsize = malloc(diffdim * sizeof(int));
+	diff_cumprod = malloc(diffdim * sizeof(int));
+	for(i=0; i<diffdim; i++){
+		eff_cumprod[i] = bCumprod[dmask[i]];
+		diffsize[i] = (int)pbSize[dmask[i]];
+	}
+	diff_cumprod[0] = 1;
+	for(i=0; i<diffdim-1; i++){
+		diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i];
+	}
+	for(i=0; i<ND; i++){
+		ind_subv(i, diff_cumprod, diffdim, subv);
+		weight[i] = 0;
+		for(j=0; j<diffdim; j++){
+			weight[i] += eff_cumprod[j] * subv[j];
+		}
+	}
+	free(eff_cumprod);
+	free(subv);
+	free(diffsize);
+	free(diff_cumprod);
+}
+
+mxArray* convert_table_to_sparse(const double *bT, const int *index, const int nzCounts, const int N){
+	mxArray  *spTable;
+    int      i, *irs, *jcs;
+    double   *sr;
+    
+	spTable = mxCreateSparse(N, 1, nzCounts, mxREAL);
+    sr  = mxGetPr(spTable);
+    irs = mxGetIr(spTable);
+    jcs = mxGetJc(spTable);
+
+	jcs[0] = 0;
+	jcs[1] = nzCounts;
+
+	for(i=0; i<nzCounts; i++){
+			sr[i] = bT[i];
+			irs[i] = index[i];
+    }
+	return spTable;	
+}
+
+mxArray* convert_ill_table_to_sparse(const double *Table, const int *sequence, const int nzCounts, const int N){
+	mxArray *spTable;
+	int     i, temp, *irs, *jcs, count=0;
+	double  *sr;
+
+	spTable = mxCreateSparse(N, 1, nzCounts, mxREAL);
+    sr  = mxGetPr(spTable);
+    irs = mxGetIr(spTable);
+    jcs = mxGetJc(spTable);
+
+	jcs[0] = 0;
+	jcs[1] = nzCounts;
+
+	for(i=0; i<nzCounts; i++){
+		irs[i] = sequence[count];
+		count++;
+		temp = sequence[count];
+		sr[i] = Table[temp];
+		count++;
+	}
+	return spTable;
+}
+
+void multiply_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex, nzCounts=0;
+	int     *samemask, *diffmask, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *sequence, *weight;
+	double  *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *spr, *bpr;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	if(sdim == 0){
+		pTemp = mxCreateSparse(NB, 1, NB, mxREAL);
+		mxSetField(bigPot, 0, "T", pTemp);
+		bpr = mxGetPr(pTemp);
+		sir = mxGetIr(pTemp);
+		sjc = mxGetJc(pTemp);
+		sjc[0] = 0;
+		sjc[1] = NB;
+		for(i=0; i<NB; i++){
+			bpr[i] = *spr;
+			sir[i] = i;
+		}	
+		return;
+	}
+
+	NS = 1;
+	for(i=0; i<sdim; i++){
+		NS *= (int)psSize[i];
+	}
+	ND = NB / NS;
+
+	if(ND == 1){
+		pTemp1 = mxGetField(smallPot, 0, "T");
+		pTemp = mxDuplicateArray(pTemp1);
+		mxSetField(bigPot, 0, "T", pTemp);
+		return;
+	}
+
+
+	NZB = ND * NZS;
+
+	diffdim = bdim - sdim;
+	sequence = malloc(NZB * 2 * sizeof(int));
+	bigTable = malloc(NZB * sizeof(double));
+	samemask = malloc(sdim * sizeof(int));
+	diffmask = malloc(diffdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	weight = malloc(ND * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	count1 = 0;
+	for(i=0; i<bdim; i++){
+		match = 0;
+		for(j=0; j<sdim; j++){
+			if(pbDomain[i] == psDomain[j]){
+				samemask[count] = i;
+				match = 1;
+				count++;
+				break;
+			}
+		}
+		if(match == 0){
+			diffmask[count1] = i; 
+			count1++;
+		}
+	}
+
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	count = 0;
+	compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim);
+	for(i=0; i<NZS; i++){
+		sindex = sir[i];
+		ind_subv(sindex, sCumprod, sdim, ssubv);
+		temp = 0;
+		for(j=0; j<sdim; j++){
+			temp += ssubv[j] * bCumprod[samemask[j]];
+		}
+		for(j=0; j<ND; j++){
+			bindex = weight[j] + temp;
+			bigTable[nzCounts] = spr[i];
+			sequence[count] = bindex;
+			count++;
+			sequence[count] = nzCounts;
+			nzCounts++;
+			count++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	qsort(sequence, nzCounts, sizeof(int) * 2, compare);
+	pTemp = convert_ill_table_to_sparse(bigTable, sequence, nzCounts, NB);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(sequence); 
+	free(bigTable);
+	free(samemask);
+	free(diffmask);
+	free(bCumprod);
+	free(sCumprod);
+	free(weight);
+	free(ssubv);
+}
+
+void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0;
+	int     *mask, *index, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value;
+	mxArray *pTemp;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	if(sdim == 0){
+		for(i=0; i<NZB; i++){
+			bpr[i] *= *spr;
+		}	
+		return;
+	}
+
+	bigTable = malloc(NZB * sizeof(double));
+	index = malloc(NZB * sizeof(double));
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	for(i=0; i<NZB; i++){
+		bigTable[i] = 0;
+	}
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		value = bpr[i];
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare);
+		if(result){
+			position = result - sir;
+			value *= spr[position];
+			bigTable[nzCounts] = value;
+			index[nzCounts] = bindex;
+			nzCounts++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	pTemp = convert_table_to_sparse(bigTable, index, nzCounts, NB);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(bigTable);
+	free(index);
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+mxArray* marginal_null_to_spPot(const mxArray *bigPot, const mxArray *sDomain, const int maximize){
+	int     i, j, count, bdim, sdim, NB, NS, ND;
+	int     *mask, *sir, *sjc;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *spr;
+	mxArray *pTemp, *smallPot;
+	const char *field_names[] = {"domain", "T", "sizes"};
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	psDomain = mxGetPr(sDomain);
+	sdim = mxGetNumberOfElements(sDomain);
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+
+	smallPot = mxCreateStructMatrix(1, 1, 3, field_names);
+	pTemp = mxDuplicateArray(sDomain);
+	mxSetField(smallPot, 0, "domain", pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	if(sdim == 0){
+		pTemp = mxCreateSparse(1, 1, 1, mxREAL);
+		mxSetField(smallPot, 0, "T", pTemp);
+		spr = mxGetPr(pTemp);
+		sir = mxGetIr(pTemp);
+		sjc = mxGetJc(pTemp);
+		*spr = 0;
+		*sir = 0;
+		sjc[0] = 0;
+		sjc[1] = 1;
+		if(maximize) *spr = 1;
+		else *spr = NB;
+
+		pTemp = mxCreateDoubleMatrix(1, 1, mxREAL);
+		*mxGetPr(pTemp) = 1;
+		mxSetField(smallPot, 0, "sizes", pTemp);
+		return smallPot;
+	}
+
+	mask = malloc(sdim * sizeof(int));
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	pTemp = mxCreateDoubleMatrix(1, count, mxREAL);
+	psSize = mxGetPr(pTemp);
+	NS = 1;
+	for(i=0; i<count; i++){
+		psSize[i] = pbSize[mask[i]];
+		NS *= (int)psSize[i];
+	}
+	mxSetField(smallPot, 0, "sizes", pTemp);
+
+	ND = NB / NS;
+
+	pTemp = mxCreateSparse(NS, 1, NS, mxREAL);
+	mxSetField(smallPot, 0, "T", pTemp);
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	if(maximize){
+		for(i=0; i<NS; i++){
+			spr[i] = 1;
+			sir[i] = i;
+		}
+	}
+	else{
+		for(i=0; i<NS; i++){
+			spr[i] = ND;
+			sir[i] = i;
+		}
+	}
+	sjc[0] = 0;
+	sjc[1] = NS;
+
+	free(mask);
+	return smallPot;
+}
+
+mxArray* marginal_spPot_to_spPot(const mxArray *bigPot, const mxArray *sDomain, const int maximize){
+	int     i, j, count, bdim, sdim, NB, NS, NZB, position, bindex, sindex, nzCounts=0;
+	int     *mask, *sequence, *result, *bir, *bjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *sTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr;
+	mxArray *pTemp, *smallPot;
+	const char *field_names[] = {"domain", "T", "sizes"};
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	psDomain = mxGetPr(sDomain);
+	sdim = mxGetNumberOfElements(sDomain);
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	smallPot = mxCreateStructMatrix(1, 1, 3, field_names);
+	pTemp = mxDuplicateArray(sDomain);
+	mxSetField(smallPot, 0, "domain", pTemp);
+
+	if(sdim == 0){
+		pTemp = mxCreateSparse(1, 1, 1, mxREAL);
+		mxSetField(smallPot, 0, "T", pTemp);
+		spr = mxGetPr(pTemp);
+		bir = mxGetIr(pTemp);
+		bjc = mxGetJc(pTemp);
+		*spr = 0;
+		*bir = 0;
+		bjc[0] = 0;
+		bjc[1] = 1;
+		if(maximize){
+			for(i=0; i<NZB; i++){
+				*spr = (*spr < bpr[i])? bpr[i] : *spr;
+			}
+		}
+		else{
+			for(i=0; i<NZB; i++){
+				*spr += bpr[i];
+			}
+		}
+
+		pTemp = mxCreateDoubleMatrix(1, 1, mxREAL);
+		*mxGetPr(pTemp) = 1;
+		mxSetField(smallPot, 0, "sizes", pTemp);
+		return smallPot;
+	}
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	mask = malloc(sdim * sizeof(int));
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	pTemp = mxCreateDoubleMatrix(1, count, mxREAL);
+	psSize = mxGetPr(pTemp);
+	NS = 1;
+	for(i=0; i<count; i++){
+		psSize[i] = pbSize[mask[i]];
+		NS *= (int)psSize[i];
+	}
+	mxSetField(smallPot, 0, "sizes", pTemp);
+
+
+	sTable = malloc(NZB * sizeof(double));
+	sequence = malloc(NZB * 2 * sizeof(double));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	for(i=0; i<NZB; i++)sTable[i] = 0;
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	count = 0;
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sequence, nzCounts, sizeof(int)*2, compare);
+		if(result){
+			position = (result - sequence) / 2;
+			if(maximize) 
+				sTable[position] = (sTable[position] < bpr[i]) ? bpr[i] : sTable[position];
+			else sTable[position] += bpr[i];
+		}
+		else {
+			if(maximize) 
+				sTable[nzCounts] = (sTable[nzCounts] < bpr[i]) ? bpr[i] : sTable[nzCounts];
+			else sTable[nzCounts] += bpr[i];
+			sequence[count] = sindex;
+			count++;
+			sequence[count] = nzCounts;
+			nzCounts++;
+			count++;
+		}
+	}
+	
+	qsort(sequence, nzCounts, sizeof(int) * 2, compare);
+	pTemp = convert_ill_table_to_sparse(sTable, sequence, nzCounts, NS);
+	mxSetField(smallPot, 0, "T", pTemp);
+
+	free(sTable);
+	free(sequence);
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+
+	return smallPot;
+}
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, n, p, np, pn, loop, loops, nCliques, temp, maximize;
+	int     *collect_order;
+	double  *pr, *pr1;
+	mxArray *pTemp, *pTemp1, *pPostP, *pClpot, *pSeppot, *pSeparator;
+
+	pTemp = mxGetField(prhs[0], 0, "cliques");
+	nCliques = mxGetNumberOfElements(pTemp);
+	loops = nCliques - 1;
+	pTemp = mxGetField(prhs[0], 0, "maximize");
+	maximize = (int)mxGetScalar(pTemp);
+	pSeparator = mxGetField(prhs[0], 0, "separator");
+
+	collect_order = malloc(2 * loops * sizeof(int));
+
+	pTemp = mxGetField(prhs[0], 0, "postorder");
+	pr = mxGetPr(pTemp);
+	pPostP = mxGetField(prhs[0], 0, "postorder_parents");
+	for(i=0; i<loops; i++){
+		temp = (int)pr[i] - 1;
+		pTemp = mxGetCell(pPostP, temp);
+		pr1 = mxGetPr(pTemp);
+		collect_order[i] = (int)pr1[0] - 1;
+		collect_order[i+loops] = temp;
+	}
+
+	plhs[0] = mxDuplicateArray(prhs[1]);
+	plhs[1] = mxDuplicateArray(prhs[2]);
+
+	for(loop=0; loop<loops; loop++){
+		p = collect_order[loop];
+		n = collect_order[loop+loops];
+		np = p * nCliques + n;
+		pn = n * nCliques + p;
+		pClpot = mxGetCell(plhs[0], n);
+		pTemp1 = mxGetField(pClpot, 0, "T");
+		pTemp = mxGetCell(pSeparator, pn);
+		if(pTemp1)
+			pSeppot = marginal_spPot_to_spPot(pClpot, pTemp, maximize);
+		else pSeppot = marginal_null_to_spPot(pClpot, pTemp, maximize);
+		mxSetCell(plhs[1], pn, pSeppot);
+
+		pClpot = mxGetCell(plhs[0], p);
+		pTemp1 = mxGetField(pClpot, 0, "T");
+		if(pTemp1)
+			multiply_spPot_by_spPot(pClpot, pSeppot);
+		else multiply_null_by_spPot(pClpot, pSeppot);
+	}
+	free(collect_order);
+}
+	
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/distribute_evidence.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,613 @@
+/* C mex for distribute_evidence.c in @jtree_sparse_inf_engine directory*/
+/* File enter_evidence.m in directory @jtree_sparse_inf_engine call it  */
+
+/*********************************************/
+/* distribute_evidence has 3 input & 2 output*/
+/* engine                                    */
+/* clpot                                     */
+/* seppot                                    */
+/*                                           */
+/* clpot                                     */
+/* seppot                                    */
+/*********************************************/
+
+#include "mex.h"
+
+#include <math.h>
+#include <search.h>
+#include "mex.h"
+
+int compare(const void* src1, const void* src2){
+	int i1 = *(int*)src1 ;
+	int i2 = *(int*)src2 ;
+	return i1-i2 ;
+}
+
+void ind_subv(int index, const int *cumprod, int n, int *bsubv){
+	int i;
+
+	for (i = n-1; i >= 0; i--) {
+		bsubv[i] = ((int)floor(index / cumprod[i]));
+		index = index % cumprod[i];
+	}
+}
+
+int subv_ind(const int n, const int *cumprod, const int *subv){
+	int i, index=0;
+
+	for(i=0; i<n; i++){
+		index += subv[i] * cumprod[i];
+	}
+	return index;
+}
+
+void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){
+	int i, j;
+	int *eff_cumprod, *subv, *diffsize, *diff_cumprod;
+
+	subv = malloc(diffdim * sizeof(int));
+	eff_cumprod = malloc(diffdim * sizeof(int));
+	diffsize = malloc(diffdim * sizeof(int));
+	diff_cumprod = malloc(diffdim * sizeof(int));
+	for(i=0; i<diffdim; i++){
+		eff_cumprod[i] = bCumprod[dmask[i]];
+		diffsize[i] = (int)pbSize[dmask[i]];
+	}
+	diff_cumprod[0] = 1;
+	for(i=0; i<diffdim-1; i++){
+		diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i];
+	}
+	for(i=0; i<ND; i++){
+		ind_subv(i, diff_cumprod, diffdim, subv);
+		weight[i] = 0;
+		for(j=0; j<diffdim; j++){
+			weight[i] += eff_cumprod[j] * subv[j];
+		}
+	}
+	free(eff_cumprod);
+	free(subv);
+	free(diffsize);
+	free(diff_cumprod);
+}
+
+mxArray* convert_table_to_sparse(const double *bT, const int *index, const int nzCounts, const int N){
+	mxArray  *spTable;
+    int      i, *irs, *jcs;
+    double   *sr;
+    
+	spTable = mxCreateSparse(N, 1, nzCounts, mxREAL);
+    sr  = mxGetPr(spTable);
+    irs = mxGetIr(spTable);
+    jcs = mxGetJc(spTable);
+
+	jcs[0] = 0;
+	jcs[1] = nzCounts;
+
+	for(i=0; i<nzCounts; i++){
+			sr[i] = bT[i];
+			irs[i] = index[i];
+    }
+	return spTable;	
+}
+
+mxArray* convert_ill_table_to_sparse(const double *Table, const int *sequence, const int nzCounts, const int N){
+	mxArray *spTable;
+	int     i, temp, *irs, *jcs, count=0;
+	double  *sr;
+
+	spTable = mxCreateSparse(N, 1, nzCounts, mxREAL);
+    sr  = mxGetPr(spTable);
+    irs = mxGetIr(spTable);
+    jcs = mxGetJc(spTable);
+
+	jcs[0] = 0;
+	jcs[1] = nzCounts;
+
+	for(i=0; i<nzCounts; i++){
+		irs[i] = sequence[count];
+		count++;
+		temp = sequence[count];
+		sr[i] = Table[temp];
+		count++;
+	}
+	return spTable;
+}
+
+void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0;
+	int     *mask, *index, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value;
+	mxArray *pTemp;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	if(sdim == 0){
+		for(i=0; i<NZB; i++){
+			bpr[i] *= *spr;
+		}	
+		return;
+	}
+
+	bigTable = malloc(NZB * sizeof(double));
+	index = malloc(NZB * sizeof(double));
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		value = bpr[i];
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare);
+		if(result){
+			position = result - sir;
+			value *= spr[position];
+			bigTable[nzCounts] = value;
+			index[nzCounts] = bindex;
+			nzCounts++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	pTemp = convert_table_to_sparse(bigTable, index, nzCounts, NB);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(bigTable);
+	free(index);
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+void marginal_spPot_to_spPot(const mxArray *bigPot, mxArray *smallPot, const int maximize){
+	int     i, j, count, bdim, sdim, NB, NS, NZB, position, bindex, sindex, nzCounts=0;
+	int     *mask, *sequence, *result, *bir, *bjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *sTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr;
+	mxArray *pTemp;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+	NS = 1;
+	for(i=0; i<sdim; i++){
+		NS *= (int)psSize[i];
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	if(sdim == 0){
+		pTemp = mxGetField(smallPot, 0, "T");
+		spr = mxGetPr(pTemp);
+		*spr = 0;
+		if(maximize){
+			for(i=0; i<NZB; i++){
+				*spr = (*spr < bpr[i])? bpr[i] : *spr;
+			}
+		}
+		else{
+			for(i=0; i<NZB; i++){
+				*spr += bpr[i];
+			}
+		}	
+		return;
+	}
+
+	mask = malloc(sdim * sizeof(int));
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+
+
+	sTable = malloc(NZB * sizeof(double));
+	sequence = malloc(NZB * 2 * sizeof(double));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	for(i=0; i<NZB; i++){
+		sTable[i] = 0;
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	count = 0;
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sequence, nzCounts, sizeof(int)*2, compare);
+		if(result){
+			position = (result - sequence) / 2;
+			if(maximize)
+				sTable[position] = (sTable[position] < bpr[i]) ? bpr[i] : sTable[position];
+			else sTable[position] += bpr[i];
+		}
+		else {
+			if(maximize) 
+				sTable[nzCounts] = (sTable[nzCounts] < bpr[i]) ? bpr[i] : sTable[nzCounts];
+			else sTable[nzCounts] += bpr[i];
+			sequence[count] = sindex;
+			count++;
+			sequence[count] = nzCounts;
+			nzCounts++;
+			count++;
+		}
+	}
+	
+	pTemp = mxGetField(smallPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	qsort(sequence, nzCounts, sizeof(int) * 2, compare);
+	pTemp = convert_ill_table_to_sparse(sTable, sequence, nzCounts, NS);
+	mxSetField(smallPot, 0, "T", pTemp);
+
+	free(sTable);
+	free(sequence);
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+void divide_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex;
+	int     *samemask, *diffmask, *rir, *rjc, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *weight;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *rpr, *spr, value;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	if(sdim == 0){
+		pTemp = mxCreateSparse(NB, 1, NB, mxREAL);
+		mxSetField(bigPot, 0, "T", pTemp);
+		rpr = mxGetPr(pTemp);
+		rir = mxGetIr(pTemp);
+		rjc = mxGetJc(pTemp);
+		rjc[0] = 0;
+		rjc[1] = NB;
+		value = *spr;
+		if(value == 0) value = 1;
+		for(i=0; i<NB; i++){
+			rpr[i] = 1 / value;
+			rir[i] = i;
+		}	
+		return;
+	}
+
+	NS = 1;
+	for(i=0; i<sdim; i++){
+		NS *= (int)psSize[i];
+	}
+	ND = NB / NS;
+
+
+	pTemp = mxCreateSparse(NB, 1, NB, mxREAL);
+	rpr = mxGetPr(pTemp);
+	rir = mxGetIr(pTemp);
+	rjc = mxGetJc(pTemp);
+	rjc[0] = 0;
+	rjc[1] = NB;
+	for(i=0; i<NB; i++){
+		rpr[i] = 1;
+		rir[i] = i;
+	}
+
+	NZB = ND * NZS;
+
+	diffdim = bdim - sdim;
+	samemask = malloc(sdim * sizeof(int));
+	diffmask = malloc(diffdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	weight = malloc(ND * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	count1 = 0;
+	for(i=0; i<bdim; i++){
+		match = 0;
+		for(j=0; j<sdim; j++){
+			if(pbDomain[i] == psDomain[j]){
+				samemask[count] = i;
+				match = 1;
+				count++;
+				break;
+			}
+		}
+		if(match == 0){
+			diffmask[count1] = i; 
+			count1++;
+		}
+	}
+
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	count = 0;
+	compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim);
+	for(i=0; i<NZS; i++){
+		sindex = sir[i];
+		ind_subv(sindex, sCumprod, sdim, ssubv);
+		temp = 0;
+		for(j=0; j<sdim; j++){
+			temp += ssubv[j] * bCumprod[samemask[j]];
+		}
+		for(j=0; j<ND; j++){
+			bindex = weight[j] + temp;
+			rpr[bindex] = 1 / (spr[i]);
+		}
+	}
+
+	pTemp1 = mxGetField(bigPot, 0, "T");
+	if(pTemp1)mxDestroyArray(pTemp1);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(samemask);
+	free(diffmask);
+	free(bCumprod);
+	free(sCumprod);
+	free(weight);
+	free(ssubv);
+}
+
+void divide_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex;
+	int     *mask, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp1 = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp1);
+	bir = mxGetIr(pTemp1);
+	bjc = mxGetJc(pTemp1);
+	NZB = bjc[1];
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	if(sdim == 0){
+		value = *spr;
+		if(value == 0)value = 1;
+		for(i=0; i<NZB; i++){
+			bpr[i] /= value;
+		}	
+		return;
+	}
+
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare);
+		if(result){
+			position = result - sir;
+			bpr[i] /= spr[position];
+		}
+	}
+
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, j, loop, loops, nCliques, temp, count, parent, child, maximize, *distribute_order;
+	double  *pr, *pr1;
+	mxArray *pTemp, *pPreCh, *pClpot, *pSeppot;
+
+	pTemp = mxGetField(prhs[0], 0, "cliques");
+	nCliques = mxGetNumberOfElements(pTemp);
+	loops = nCliques - 1;
+	pTemp = mxGetField(prhs[0], 0, "maximize");
+	maximize = (int)mxGetScalar(pTemp);
+
+	distribute_order = malloc(2 * loops * sizeof(int));
+	pTemp = mxGetField(prhs[0], 0, "preorder");
+	pr = mxGetPr(pTemp);
+	pPreCh = mxGetField(prhs[0], 0, "preorder_children");
+	count = 0;
+	for(i=0; i<nCliques; i++){
+		temp = (int)pr[i] - 1;
+		pTemp = mxGetCell(pPreCh, temp);
+		pr1 = mxGetPr(pTemp);
+		loop = mxGetNumberOfElements(pTemp);
+		for(j=0; j<loop; j++){
+			distribute_order[count] = temp;
+			distribute_order[count + loops] = (int)pr1[j] - 1;
+			count++;
+		}
+	}
+
+	plhs[0] = mxDuplicateArray(prhs[1]);
+	plhs[1] = mxDuplicateArray(prhs[2]);
+
+	for(loop=0; loop<loops; loop++){
+		parent = distribute_order[loop];
+		child  = distribute_order[loop+loops];
+		i = nCliques * child + parent;
+		pClpot = mxGetCell(plhs[0], child);
+		pTemp = mxGetField(pClpot, 0, "T");
+		pSeppot = mxGetCell(plhs[1], i);
+		if(pTemp)
+			divide_spPot_by_spPot(pClpot, pSeppot);
+		else divide_null_by_spPot(pClpot, pSeppot);
+
+		pClpot = mxGetCell(plhs[0], parent);
+		marginal_spPot_to_spPot(pClpot, pSeppot, maximize);
+		mxSetCell(plhs[1], i, pSeppot);
+
+		pClpot = mxGetCell(plhs[0], child);
+		multiply_spPot_by_spPot(pClpot, pSeppot); 
+	}
+	free(distribute_order);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,637 @@
+/* C mex init_pot for in @jtree_sparse_inf_engine directory               */
+/* The file enter_evidence.m in directory @jtree_sparse_inf_engine call it*/
+
+/**************************************/
+/* init_pot.c has 6 input & 2 output  */
+/* engine                             */
+/* clqs                               */
+/* pots                               */
+/* pot_type                           */
+/* onodes                             */
+/* ndx                                */
+/*                                    */
+/* clpot                              */
+/* seppot                             */
+/**************************************/
+#include <math.h>
+#include <search.h>
+#include "mex.h"
+
+int compare(const void* src1, const void* src2){
+	int i1 = *(int*)src1 ;
+	int i2 = *(int*)src2 ;
+	return i1-i2 ;
+}
+
+void ind_subv(int index, const int *cumprod, int n, int *bsubv){
+	int i;
+
+	for (i = n-1; i >= 0; i--) {
+		bsubv[i] = ((int)floor(index / cumprod[i]));
+		index = index % cumprod[i];
+	}
+}
+
+int subv_ind(const int n, const int *cumprod, const int *subv){
+	int i, index=0;
+
+	for(i=0; i<n; i++){
+		index += subv[i] * cumprod[i];
+	}
+	return index;
+}
+
+void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){
+	int i, j;
+	int *eff_cumprod, *subv, *diffsize, *diff_cumprod;
+
+	subv = malloc(diffdim * sizeof(int));
+	eff_cumprod = malloc(diffdim * sizeof(int));
+	diffsize = malloc(diffdim * sizeof(int));
+	diff_cumprod = malloc(diffdim * sizeof(int));
+	for(i=0; i<diffdim; i++){
+		eff_cumprod[i] = bCumprod[dmask[i]];
+		diffsize[i] = (int)pbSize[dmask[i]];
+	}
+	diff_cumprod[0] = 1;
+	for(i=0; i<diffdim-1; i++){
+		diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i];
+	}
+	for(i=0; i<ND; i++){
+		ind_subv(i, diff_cumprod, diffdim, subv);
+		weight[i] = 0;
+		for(j=0; j<diffdim; j++){
+			weight[i] += eff_cumprod[j] * subv[j];
+		}
+	}
+	free(eff_cumprod);
+	free(subv);
+	free(diffsize);
+	free(diff_cumprod);
+}
+
+mxArray* convert_to_sparse(const double *table, const int NB, const int counts){
+	mxArray  *spTable;
+    int      i, k, *ir, *jc;
+    double   *sr;
+    
+	spTable = mxCreateSparse(NB, 1, counts, mxREAL);
+    sr = mxGetPr(spTable);
+    ir = mxGetIr(spTable);
+    jc = mxGetJc(spTable);
+
+    k = 0; 
+	jc[0] = 0;
+	jc[1] = counts;
+	for(i=0; i<NB; i++){
+		if(table[i] != 0.0){
+			sr[k] = table[i];
+			ir[k] = i;
+			k++;
+		}
+    }
+
+	return spTable;
+}
+
+mxArray* convert_table_to_sparse(const double *bT, const int *index, const int nzCounts, const int NB){
+	mxArray  *spTable;
+    int      i, *irs, *jcs;
+    double   *sr;
+    
+	spTable = mxCreateSparse(NB, 1, nzCounts, mxREAL);
+    sr  = mxGetPr(spTable);
+    irs = mxGetIr(spTable);
+    jcs = mxGetJc(spTable);
+
+	jcs[0] = 0;
+	jcs[1] = nzCounts;
+
+	for(i=0; i<nzCounts; i++){
+			sr[i] = bT[i];
+			irs[i] = index[i];
+    }
+	return spTable;	
+}
+
+mxArray* convert_ill_table_to_sparse(const double *bigTable, const int *sequence, const int nzCounts, const int NB){
+	mxArray *spTable;
+	int     i, temp, *irs, *jcs, count=0;
+	double  *sr;
+
+	spTable = mxCreateSparse(NB, 1, nzCounts, mxREAL);
+    sr  = mxGetPr(spTable);
+    irs = mxGetIr(spTable);
+    jcs = mxGetJc(spTable);
+
+	jcs[0] = 0;
+	jcs[1] = nzCounts;
+
+	for(i=0; i<nzCounts; i++){
+		irs[i] = sequence[count];
+		count++;
+		temp = sequence[count];
+		sr[i] = bigTable[temp];
+		count++;
+	}
+	return spTable;
+}
+
+void multiply_null_by_fuPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, NB, NS, siz_b, siz_s, ndim, nzCounts=0;
+	int     *mask, *sx, *sy, *cpsy, *subs, *s, *cpsy2, *jc;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *bTable, *sTable, value;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	siz_b = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	siz_s = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<siz_b; i++){
+		NB *= (int)pbSize[i];
+	}
+	NS = 1;
+	for(i=0; i<siz_s; i++){
+		NS *= (int)psSize[i];
+	}
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	sTable = mxGetPr(pTemp);
+	bTable = malloc(NB * sizeof(double));
+	for(i=0; i<NB; i++){
+		bTable[i] = 0;
+	}
+
+	if(NS == 1){
+		value = *sTable;
+		for(i=0; i<NB; i++){
+			bTable[i] = value;
+		}
+		nzCounts = NB;
+		pTemp = mxGetField(bigPot, 0, "T");
+		if(pTemp)mxDestroyArray(pTemp);
+		pTemp = convert_to_sparse(bTable, NB, NB);
+		mxSetField(bigPot, 0, "T", pTemp);
+		free(bTable);
+		return;
+	}
+
+	if(NS == NB){
+		for(i=0; i<NB; i++){
+			bTable[i] = sTable[i];
+			if(sTable[i] != 0) nzCounts++;
+		}
+		pTemp = mxGetField(bigPot, 0, "T");
+		if(pTemp)mxDestroyArray(pTemp);
+		pTemp = convert_to_sparse(bTable, NB, nzCounts);
+		mxSetField(bigPot, 0, "T", pTemp);
+		free(bTable);
+		return;
+	}
+
+	mask = malloc(siz_s * sizeof(int));
+	count = 0;
+	for(i=0; i<siz_s; i++){
+		for(j=0; j<siz_b; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	ndim = siz_b;
+	sx = (int *)malloc(sizeof(int)*ndim);
+	sy = (int *)malloc(sizeof(int)*ndim);
+	for(i=0; i<ndim; i++){
+		sx[i] = (int)pbSize[i];
+		sy[i] = 1;
+	}
+	for(i=0; i<count; i++){
+		sy[mask[i]] = sx[mask[i]];
+	}
+
+	s = (int *)malloc(sizeof(int)*ndim);
+	*(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1;
+	subs =   (int *)malloc(sizeof(int)*ndim);
+	cpsy2 =  (int *)malloc(sizeof(int)*ndim);
+	for(i = 0; i < ndim; i++){
+		subs[i] = 0;
+		s[i] = sx[i] - 1;
+	}
+			
+	for(i = 0; i < ndim-1; i++){
+		cpsy[i+1] = cpsy[i]*sy[i]--;
+		cpsy2[i] = cpsy[i]*sy[i];
+	}
+	cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]);
+
+	for(j=0; j<NB; j++){
+		bTable[j] = *sTable;
+		if(*sTable != 0.0) nzCounts++;
+		for(i = 0; i < ndim; i++){
+			if(subs[i] == s[i]){
+				subs[i] = 0;
+				if(sy[i])
+					sTable -= cpsy2[i];
+			}
+			else{
+				subs[i]++;
+				if(sy[i])
+					sTable += cpsy[i];
+				break;
+			}
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	pTemp = convert_to_sparse(bTable, NB, nzCounts);
+	mxSetField(bigPot, 0, "T", pTemp);
+	pTemp1 = mxGetField(bigPot, 0, "T");
+	jc = mxGetJc(pTemp1);
+
+	free(sx);
+	free(sy);
+	free(s);
+	free(cpsy);
+	free(subs);
+	free(cpsy2);
+    free(mask);
+	free(bTable);
+}
+
+void multiply_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex, nzCounts=0;
+	int     *samemask, *diffmask, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *sequence, *weight;
+	double  *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *spr;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+	NS = 1;
+	for(i=0; i<sdim; i++){
+		NS *= (int)psSize[i];
+	}
+	ND = NB / NS;
+
+	if(ND == 1){
+		pTemp = mxGetField(bigPot, 0, "T");
+		if(pTemp)mxDestroyArray(pTemp);
+		pTemp1 = mxGetField(smallPot, 0, "T");
+		pTemp = mxDuplicateArray(pTemp1);
+		mxSetField(bigPot, 0, "T", pTemp);
+		return;
+	}
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	NZB = ND * NZS;
+
+	diffdim = bdim - sdim;
+	sequence = malloc(NZB * 2 * sizeof(int));
+	bigTable = malloc(NZB * sizeof(double));
+	samemask = malloc(sdim * sizeof(int));
+	diffmask = malloc(diffdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	weight = malloc(ND * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	count1 = 0;
+	for(i=0; i<bdim; i++){
+		match = 0;
+		for(j=0; j<sdim; j++){
+			if(pbDomain[i] == psDomain[j]){
+				samemask[count] = i;
+				match = 1;
+				count++;
+				break;
+			}
+		}
+		if(match == 0){
+			diffmask[count1] = i; 
+			count1++;
+		}
+	}
+
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	count = 0;
+	compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim);
+	for(i=0; i<NZS; i++){
+		sindex = sir[i];
+		ind_subv(sindex, sCumprod, sdim, ssubv);
+		temp = 0;
+		for(j=0; j<sdim; j++){
+			temp += ssubv[j] * bCumprod[samemask[j]];
+		}
+		for(j=0; j<ND; j++){
+			bindex = weight[j] + temp;
+			bigTable[nzCounts] = spr[i];
+			sequence[count] = bindex;
+			count++;
+			sequence[count] = nzCounts;
+			nzCounts++;
+			count++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	qsort(sequence, nzCounts, sizeof(int) * 2, compare);
+	pTemp = convert_ill_table_to_sparse(bigTable, sequence, nzCounts, NB);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(sequence); 
+	free(bigTable);
+	free(samemask);
+	free(diffmask);
+	free(bCumprod);
+	free(sCumprod);
+	free(weight);
+	free(ssubv);
+}
+
+void multiply_spPot_by_fuPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, bdim, sdim, NB, NZB, bindex, sindex, nzCounts=0;
+	int     *mask, *index, *bir, *bjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value;
+	mxArray *pTemp;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+
+	bigTable = malloc(NZB * sizeof(double));
+	index = malloc(NZB * sizeof(double));
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	for(i=0; i<NZB; i++){
+		bigTable[i] = 0;
+	}
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		value = spr[sindex];
+		if(value != 0){
+			bigTable[nzCounts] = bpr[i] * value;
+			index[nzCounts] = bindex;
+			nzCounts++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	pTemp = convert_table_to_sparse(bigTable, index, nzCounts, NB);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(bigTable);
+	free(index);
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0;
+	int     *mask, *index, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value;
+	mxArray *pTemp;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	bigTable = malloc(NZB * sizeof(double));
+	index = malloc(NZB * sizeof(double));
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	for(i=0; i<NZB; i++){
+		bigTable[i] = 0;
+	}
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		value = bpr[i];
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare);
+		if(result){
+			position = result - sir;
+			value *= spr[position];
+			bigTable[nzCounts] = value;
+			index[nzCounts] = bindex;
+			nzCounts++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	pTemp = convert_table_to_sparse(bigTable, index, nzCounts, NB);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(bigTable);
+	free(index);
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, j, c, loop, nNodes, nCliques, ndomain, dims[2];
+	double  *pClqs, *pr, *pt, *pSize;
+	mxArray *pTemp, *pTemp1, *pStruct, *pCliques, *pBigpot, *pSmallpot;
+	const char *field_names[] = {"domain", "T", "sizes"};
+
+	nNodes = mxGetNumberOfElements(prhs[1]);
+	pCliques = mxGetField(prhs[0], 0, "cliques");
+	nCliques = mxGetNumberOfElements(pCliques);
+	pTemp = mxGetField(prhs[0], 0, "eff_node_sizes");
+	pSize = mxGetPr(pTemp);
+
+	plhs[0] = mxCreateCellArray(1, &nCliques);
+    for(i=0; i<nCliques; i++){
+        pStruct = mxCreateStructMatrix(1, 1, 3, field_names);
+		mxSetCell(plhs[0], i, pStruct);
+		pTemp = mxGetCell(pCliques, i);
+		ndomain = mxGetNumberOfElements(pTemp);
+		pt = mxGetPr(pTemp);
+		pTemp1 = mxDuplicateArray(pTemp);
+		mxSetField(pStruct, 0, "domain", pTemp1);
+		
+		pTemp = mxCreateDoubleMatrix(1, ndomain, mxREAL);
+		mxSetField(pStruct, 0, "sizes", pTemp);
+		pr = mxGetPr(pTemp);
+        for(j=0; j<ndomain; j++){
+            pr[j] = pSize[(int)pt[j]-1];
+        }
+    }
+
+	pClqs = mxGetPr(prhs[1]);
+	for(loop=0; loop<nNodes; loop++){
+		c = (int)pClqs[loop] - 1;
+		pSmallpot = mxGetCell(prhs[2], loop);
+		pTemp = mxGetField(pSmallpot, 0, "T");
+		pBigpot = mxGetCell(plhs[0], c);
+		pTemp1 = mxGetField(pBigpot, 0, "T");
+		if(pTemp1){
+			if(mxIsSparse(pTemp))
+				multiply_spPot_by_spPot(pBigpot, pSmallpot);
+			else multiply_spPot_by_fuPot(pBigpot, pSmallpot);
+		}
+		else{
+			if(mxIsSparse(pTemp))
+				multiply_null_by_spPot(pBigpot, pSmallpot);
+			else multiply_null_by_fuPot(pBigpot, pSmallpot);
+		}		
+	}
+
+	dims[0] = nCliques;
+	dims[1] = nCliques;
+	plhs[1] = mxCreateCellArray(2, dims);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot1.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,636 @@
+/* C mex init_pot for in @jtree_sparse_inf_engine directory               */
+/* The file enter_evidence.m in directory @jtree_sparse_inf_engine call it*/
+
+/**************************************/
+/* init_pot.c has 6 input & 2 output  */
+/* engine                             */
+/* clqs                               */
+/* pots                               */
+/* pot_type                           */
+/* onodes                             */
+/* ndx                                */
+/*                                    */
+/* clpot                              */
+/* seppot                             */
+/**************************************/
+#include <math.h>
+#include <search.h>
+#include "mex.h"
+
+int compare(const void* src1, const void* src2){
+	int i1 = *(int*)src1 ;
+	int i2 = *(int*)src2 ;
+	return i1-i2 ;
+}
+
+void ind_subv(int index, const int *cumprod, int n, int *bsubv){
+	int i;
+
+	for (i = n-1; i >= 0; i--) {
+		bsubv[i] = ((int)floor(index / cumprod[i]));
+		index = index % cumprod[i];
+	}
+}
+
+int subv_ind(const int n, const int *cumprod, const int *subv){
+	int i, index=0;
+
+	for(i=0; i<n; i++){
+		index += subv[i] * cumprod[i];
+	}
+	return index;
+}
+
+void compute_fixed_weight(int *weight, const double *pbSize, const int *dmask, const int *bCumprod, const int ND, const int diffdim){
+	int i, j;
+	int *eff_cumprod, *subv, *diffsize, *diff_cumprod;
+
+	subv = malloc(diffdim * sizeof(int));
+	eff_cumprod = malloc(diffdim * sizeof(int));
+	diffsize = malloc(diffdim * sizeof(int));
+	diff_cumprod = malloc(diffdim * sizeof(int));
+	for(i=0; i<diffdim; i++){
+		eff_cumprod[i] = bCumprod[dmask[i]];
+		diffsize[i] = (int)pbSize[dmask[i]];
+	}
+	diff_cumprod[0] = 1;
+	for(i=0; i<diffdim-1; i++){
+		diff_cumprod[i+1] = diff_cumprod[i] * diffsize[i];
+	}
+	for(i=0; i<ND; i++){
+		ind_subv(i, diff_cumprod, diffdim, subv);
+		weight[i] = 0;
+		for(j=0; j<diffdim; j++){
+			weight[i] += eff_cumprod[j] * subv[j];
+		}
+	}
+	free(eff_cumprod);
+	free(subv);
+	free(diffsize);
+	free(diff_cumprod);
+}
+
+void reset_nzmax(mxArray *spArray, const int old_nzmax, const int new_nzmax){
+	double *ptr;
+	void   *newptr;
+	int    *ir, *jc;
+	int    nbytes;
+
+	if(new_nzmax == old_nzmax) return;
+	nbytes = new_nzmax * sizeof(*ptr);
+	ptr = mxGetPr(spArray);
+	newptr = mxRealloc(ptr, nbytes);
+	mxSetPr(spArray, newptr);
+	nbytes = new_nzmax * sizeof(*ir);
+	ir = mxGetIr(spArray);
+	newptr = mxRealloc(ir, nbytes);
+	mxSetIr(spArray, newptr);
+	jc = mxGetJc(spArray);
+	jc[0] = 0;
+	jc[1] = new_nzmax;
+	mxSetNzmax(spArray, new_nzmax);
+}
+
+mxArray* convert_table_to_sparse(const double *bT, const int *index, const int nzCounts, const int NB){
+	mxArray  *spTable;
+    int      i, *irs, *jcs;
+    double   *sr;
+    
+	spTable = mxCreateSparse(NB, 1, nzCounts, mxREAL);
+    sr  = mxGetPr(spTable);
+    irs = mxGetIr(spTable);
+    jcs = mxGetJc(spTable);
+
+	jcs[0] = 0;
+	jcs[1] = nzCounts;
+
+	for(i=0; i<nzCounts; i++){
+			sr[i] = bT[i];
+			irs[i] = index[i];
+    }
+	return spTable;	
+}
+
+mxArray* convert_ill_table_to_sparse(const double *bigTable, const int *sequence, const int nzCounts, const int NB){
+	mxArray *spTable;
+	int     i, temp, *irs, *jcs, count=0;
+	double  *sr;
+
+	spTable = mxCreateSparse(NB, 1, nzCounts, mxREAL);
+    sr  = mxGetPr(spTable);
+    irs = mxGetIr(spTable);
+    jcs = mxGetJc(spTable);
+
+	jcs[0] = 0;
+	jcs[1] = nzCounts;
+
+	for(i=0; i<nzCounts; i++){
+		irs[i] = sequence[count];
+		count++;
+		temp = sequence[count];
+		sr[i] = bigTable[temp];
+		count++;
+	}
+	return spTable;
+}
+
+void multiply_null_by_fuPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, NB, NS, siz_b, siz_s, ndim, nzCounts=0;
+	int     *mask, *sx, *sy, *cpsy, *subs, *s, *cpsy2, *bir, *bjc;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *spr, *bpr, value;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	siz_b = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	siz_s = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<siz_b; i++){
+		NB *= (int)pbSize[i];
+	}
+	NS = 1;
+	for(i=0; i<siz_s; i++){
+		NS *= (int)psSize[i];
+	}
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+
+	pTemp1 = mxCreateSparse(NB, 1, NB, mxREAL);
+	bpr = mxGetPr(pTemp1);
+	bir = mxGetIr(pTemp1);
+	bjc = mxGetJc(pTemp1);
+	bjc[0] = 0;
+	bjc[1] = NB;
+
+	if(NS == 1){
+		value = *spr;
+		for(i=0; i<NB; i++){
+			bpr[i] = value;
+			bir[i] = i;
+		}
+		nzCounts = NB;
+		pTemp = mxGetField(bigPot, 0, "T");
+		if(pTemp)mxDestroyArray(pTemp);
+		reset_nzmax(pTemp1, NB, nzCounts);
+		mxSetField(bigPot, 0, "T", pTemp1);
+		return;
+	}
+
+	if(NS == NB){
+		for(i=0; i<NB; i++){
+			if(spr[i] != 0){
+				bpr[nzCounts] = spr[i];
+				bir[nzCounts] = i;
+				nzCounts++;
+			}
+		}
+		pTemp = mxGetField(bigPot, 0, "T");
+		if(pTemp)mxDestroyArray(pTemp);
+		reset_nzmax(pTemp1, NB, nzCounts);
+		mxSetField(bigPot, 0, "T", pTemp1);
+		return;
+	}
+
+	mask = malloc(siz_s * sizeof(int));
+	count = 0;
+	for(i=0; i<siz_s; i++){
+		for(j=0; j<siz_b; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	ndim = siz_b;
+	sx = (int *)malloc(sizeof(int)*ndim);
+	sy = (int *)malloc(sizeof(int)*ndim);
+	for(i=0; i<ndim; i++){
+		sx[i] = (int)pbSize[i];
+		sy[i] = 1;
+	}
+	for(i=0; i<count; i++){
+		sy[mask[i]] = sx[mask[i]];
+	}
+
+	s = (int *)malloc(sizeof(int)*ndim);
+	*(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1;
+	subs =   (int *)malloc(sizeof(int)*ndim);
+	cpsy2 =  (int *)malloc(sizeof(int)*ndim);
+	for(i = 0; i < ndim; i++){
+		subs[i] = 0;
+		s[i] = sx[i] - 1;
+	}
+			
+	for(i = 0; i < ndim-1; i++){
+		cpsy[i+1] = cpsy[i]*sy[i]--;
+		cpsy2[i] = cpsy[i]*sy[i];
+	}
+	cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]);
+
+	for(j=0; j<NB; j++){
+		if(*spr != 0){
+			bpr[nzCounts] = *spr;
+			bir[nzCounts] = j;
+			nzCounts++;
+		}
+		for(i = 0; i < ndim; i++){
+			if(subs[i] == s[i]){
+				subs[i] = 0;
+				if(sy[i])
+					spr -= cpsy2[i];
+			}
+			else{
+				subs[i]++;
+				if(sy[i])
+					spr += cpsy[i];
+				break;
+			}
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	reset_nzmax(pTemp1, NB, nzCounts);
+	mxSetField(bigPot, 0, "T", pTemp1);
+
+	free(sx);
+	free(sy);
+	free(s);
+	free(cpsy);
+	free(subs);
+	free(cpsy2);
+    free(mask);
+}
+
+void multiply_null_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, count1, match, temp, bdim, sdim, diffdim, NB, NS, ND, NZB, NZS, bindex, sindex, nzCounts=0;
+	int     *samemask, *diffmask, *sir, *sjc, *bCumprod, *sCumprod, *ssubv, *sequence, *weight;
+	double  *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *spr;
+	mxArray *pTemp, *pTemp1;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+	NS = 1;
+	for(i=0; i<sdim; i++){
+		NS *= (int)psSize[i];
+	}
+	ND = NB / NS;
+
+	if(ND == 1){
+		pTemp = mxGetField(bigPot, 0, "T");
+		if(pTemp)mxDestroyArray(pTemp);
+		pTemp1 = mxGetField(smallPot, 0, "T");
+		pTemp = mxDuplicateArray(pTemp1);
+		mxSetField(bigPot, 0, "T", pTemp);
+		return;
+	}
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	NZB = ND * NZS;
+
+	diffdim = bdim - sdim;
+	sequence = malloc(NZB * 2 * sizeof(int));
+	bigTable = malloc(NZB * sizeof(double));
+	samemask = malloc(sdim * sizeof(int));
+	diffmask = malloc(diffdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	weight = malloc(ND * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	count1 = 0;
+	for(i=0; i<bdim; i++){
+		match = 0;
+		for(j=0; j<sdim; j++){
+			if(pbDomain[i] == psDomain[j]){
+				samemask[count] = i;
+				match = 1;
+				count++;
+				break;
+			}
+		}
+		if(match == 0){
+			diffmask[count1] = i; 
+			count1++;
+		}
+	}
+
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	count = 0;
+	compute_fixed_weight(weight, pbSize, diffmask, bCumprod, ND, diffdim);
+	for(i=0; i<NZS; i++){
+		sindex = sir[i];
+		ind_subv(sindex, sCumprod, sdim, ssubv);
+		temp = 0;
+		for(j=0; j<sdim; j++){
+			temp += ssubv[j] * bCumprod[samemask[j]];
+		}
+		for(j=0; j<ND; j++){
+			bindex = weight[j] + temp;
+			bigTable[nzCounts] = spr[i];
+			sequence[count] = bindex;
+			count++;
+			sequence[count] = nzCounts;
+			nzCounts++;
+			count++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	qsort(sequence, nzCounts, sizeof(int) * 2, compare);
+	pTemp = convert_ill_table_to_sparse(bigTable, sequence, nzCounts, NB);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(sequence); 
+	free(bigTable);
+	free(samemask);
+	free(diffmask);
+	free(bCumprod);
+	free(sCumprod);
+	free(weight);
+	free(ssubv);
+}
+
+void multiply_spPot_by_fuPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, bdim, sdim, NB, NZB, bindex, sindex, nzCounts=0;
+	int     *mask, *index, *bir, *bjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value;
+	mxArray *pTemp;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+
+	bigTable = malloc(NZB * sizeof(double));
+	index = malloc(NZB * sizeof(double));
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		value = spr[sindex];
+		if(value != 0){
+			bigTable[nzCounts] = bpr[i] * value;
+			index[nzCounts] = bindex;
+			nzCounts++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	pTemp = convert_table_to_sparse(bigTable, index, nzCounts, NB);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(bigTable);
+	free(index);
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+void multiply_spPot_by_spPot(mxArray *bigPot, const mxArray *smallPot){
+	int     i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0;
+	int     *mask, *index, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *bigTable, *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value;
+	mxArray *pTemp;
+
+	pTemp = mxGetField(bigPot, 0, "domain");
+	pbDomain = mxGetPr(pTemp);
+	bdim = mxGetNumberOfElements(pTemp);
+	pTemp = mxGetField(smallPot, 0, "domain");
+	psDomain = mxGetPr(pTemp);
+	sdim = mxGetNumberOfElements(pTemp);
+
+	pTemp = mxGetField(bigPot, 0, "sizes");
+	pbSize = mxGetPr(pTemp);
+	pTemp = mxGetField(smallPot, 0, "sizes");
+	psSize = mxGetPr(pTemp);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	bpr = mxGetPr(pTemp);
+	bir = mxGetIr(pTemp);
+	bjc = mxGetJc(pTemp);
+	NZB = bjc[1];
+
+	pTemp = mxGetField(smallPot, 0, "T");
+	spr = mxGetPr(pTemp);
+	sir = mxGetIr(pTemp);
+	sjc = mxGetJc(pTemp);
+	NZS = sjc[1];
+
+	bigTable = malloc(NZB * sizeof(double));
+	index = malloc(NZB * sizeof(double));
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	for(i=0; i<NZB; i++){
+		bigTable[i] = 0;
+	}
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		value = bpr[i];
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare);
+		if(result){
+			position = result - sir;
+			value *= spr[position];
+			bigTable[nzCounts] = value;
+			index[nzCounts] = bindex;
+			nzCounts++;
+		}
+	}
+
+	pTemp = mxGetField(bigPot, 0, "T");
+	if(pTemp)mxDestroyArray(pTemp);
+	pTemp = convert_table_to_sparse(bigTable, index, nzCounts, NB);
+	mxSetField(bigPot, 0, "T", pTemp);
+
+	free(bigTable);
+	free(index);
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, j, c, loop, nNodes, nCliques, ndomain, dims[2];
+	double  *pClqs, *pr, *pt, *pSize;
+	mxArray *pTemp, *pTemp1, *pStruct, *pCliques, *pBigpot, *pSmallpot;
+	const char *field_names[] = {"domain", "T", "sizes"};
+
+	nNodes = mxGetNumberOfElements(prhs[1]);
+	pCliques = mxGetField(prhs[0], 0, "cliques");
+	nCliques = mxGetNumberOfElements(pCliques);
+	pTemp = mxGetField(prhs[0], 0, "eff_node_sizes");
+	pSize = mxGetPr(pTemp);
+
+	plhs[0] = mxCreateCellArray(1, &nCliques);
+    for(i=0; i<nCliques; i++){
+        pStruct = mxCreateStructMatrix(1, 1, 3, field_names);
+		mxSetCell(plhs[0], i, pStruct);
+		pTemp = mxGetCell(pCliques, i);
+		ndomain = mxGetNumberOfElements(pTemp);
+		pt = mxGetPr(pTemp);
+		pTemp1 = mxDuplicateArray(pTemp);
+		mxSetField(pStruct, 0, "domain", pTemp1);
+		
+		pTemp = mxCreateDoubleMatrix(1, ndomain, mxREAL);
+		mxSetField(pStruct, 0, "sizes", pTemp);
+		pr = mxGetPr(pTemp);
+        for(j=0; j<ndomain; j++){
+            pr[j] = pSize[(int)pt[j]-1];
+        }
+    }
+
+	pClqs = mxGetPr(prhs[1]);
+	for(loop=0; loop<nNodes; loop++){
+		c = (int)pClqs[loop] - 1;
+		pSmallpot = mxGetCell(prhs[2], loop);
+		pTemp = mxGetField(pSmallpot, 0, "T");
+		pBigpot = mxGetCell(plhs[0], c);
+		pTemp1 = mxGetField(pBigpot, 0, "T");
+		if(pTemp1){
+			if(mxIsSparse(pTemp))
+				multiply_spPot_by_spPot(pBigpot, pSmallpot);
+			else multiply_spPot_by_fuPot(pBigpot, pSmallpot);
+		}
+		else{
+			if(mxIsSparse(pTemp))
+				multiply_null_by_spPot(pBigpot, pSmallpot);
+			else multiply_null_by_fuPot(pBigpot, pSmallpot);
+		}		
+	}
+
+	dims[0] = nCliques;
+	dims[1] = nCliques;
+	plhs[1] = mxCreateCellArray(2, dims);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/old/init_pot1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,20 @@
+function [clpot, seppot] = init_pot(engine, clqs, pots, pot_type, onodes, ndx)
+% INIT_POT Initialise potentials with evidence (jtree_inf)
+% function [clpot, seppot] = init_pot(engine, clqs, pots, pot_type, onodes)
+
+cliques = engine.cliques;
+bnet = bnet_from_engine(engine);
+% Set the clique potentials to all 1s
+C = length(cliques);
+clpot = cell(1,C);
+for i=1:C
+  clpot{i} = mk_initial_pot(pot_type, cliques{i}, bnet.node_sizes(:), bnet.cnodes(:), onodes);
+end
+
+% Multiply on specified potentials
+for i=1:length(clqs)
+  c = clqs(i);
+  clpot{c} = multiply_by_pot(clpot{c}, pots{i});
+end
+
+seppot = cell(C,C); % implicitely initialized to 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@jtree_sparse_inf_engine/set_fields.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function engine = set_fields(engine, varargin)
+% SET_FIELDS Set the fields for a generic engine
+% engine = set_fields(engine, name/value pairs)
+%
+% e.g., engine = set_fields(engine, 'maximize', 1)
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'maximize', engine.maximize = args{i+1};
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/likelihood_weighting_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,39 @@
+function [engine, ll] = enter_evidence(engine, evidence, nsamples)
+% ENTER_EVIDENCE Add the specified evidence to the network (likelihood_weighting)
+% [engine, ll] = enter_evidence(engine, evidence, nsamples)
+% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+% If nsamples is not specified, the value specified when the engine was created will be used.
+% ll (log-likelihood) is set to [].
+
+ll = [];
+if nargin < 3, nsamples = engine.nsamples; end
+
+bnet = bnet_from_engine(engine);
+N = length(bnet.dag);
+samples = cell(nsamples, N);
+weights = zeros(1, nsamples);
+
+ns = bnet.node_sizes;
+original_evidence = evidence;
+observed = ~isemptycell(original_evidence);
+for s=1:nsamples
+  evidence = original_evidence(:); % must be a column vector
+  w = 1;
+  for i=1:N
+    ps = parents(bnet.dag, i);
+    e = bnet.equiv_class(i);
+    if observed(i)
+      p = exp(log_prob_node(bnet.CPD{e}, evidence(i), evidence(ps)));
+      w = w * p;
+    else
+      x = sample_node(bnet.CPD{e}, evidence(ps));
+      evidence{i} = x;
+    end
+  end
+  samples(s,:) = evidence;
+  weights(s) = w;
+end                 
+
+engine.samples = samples;
+engine.weights = weights;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine/likelihood_weighting_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function engine = likelihood_weighting_inf_engine(bnet, varargin)
+% LIKELIHOOD_WEIGHTING_INF_ENGINE 
+% engine = likelihood_weighting_inf_engine(bnet, ...)
+%
+% Optional arguments [defaults]
+% nsamples - [500]
+
+nsamples = 500;
+
+if nargin >= 2
+  args = varargin;
+  nargs = length(args);
+  for i=1:2:nargs
+    switch args{i},
+     case 'nsamples', nsamples= args{i+1};
+     otherwise,
+      error(['invalid argument name ' args{i}]);
+    end
+  end
+end   
+
+engine.nsamples = nsamples;
+engine.samples = [];
+engine.weights = [];
+engine = class(engine, 'likelihood_weighting_inf_engine', inf_engine(bnet));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@likelihood_weighting_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,53 @@
+function marginal = marginal_nodes(engine, nodes)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (likelihood_weighting)
+% marginal = marginal_nodes(engine, nodes)
+
+bnet = bnet_from_engine(engine);
+ddom = myintersect(nodes, bnet.dnodes);
+cdom = myintersect(nodes, bnet.cnodes);
+nsamples = size(engine.samples, 1);
+ns = bnet.node_sizes;
+
+%w = normalise(engine.weights);
+w = engine.weights;
+if mysubset(nodes, ddom)
+  T = 0*myones(ns(nodes));
+  P = prod(ns(nodes));
+  indices = ind2subv(ns(nodes), 1:P);
+  samples = reshape(cat(1, engine.samples{:,nodes}), nsamples, length(nodes));
+  for j = 1:P
+    rows = find_rows(samples, indices(j,:));
+    T(j) = sum(w(rows));
+  end
+  T = normalise(T);
+  marginal.T = T;
+elseif subset(nodes, cdom)
+  samples = reshape(cat(1, engine.samples{:,nodes}), nsamples*sum(ns(nodes)), length(nodes));
+  [marginal.mu, marginal.Sigma] =  wstats(samples', normalise(w));
+else
+  error('can''t handle mixed marginals yet');
+end
+
+marginal.domain = nodes;
+
+%%%%%%%%%
+
+function rows = find_rows(M, v)
+% FINDROWS Find rows which are equal to a specified vector
+% rows = findrows(M, v)
+% Each row of M is a sample
+
+temp = abs(M - repmat(v, size(M, 1), 1));
+rows = find(sum(temp,2) == 0);      
+
+%%%%%%%%
+
+function [mu, Sigma] = wstats(X, w)
+
+% Computes the weighted mean and weighted covariance matrix for a given
+% set of observations X(:,i), and a set of normalised weights w(i).
+% Each column of X is a sample.
+
+d = X - repmat(X * w', 1, size(X, 2));
+mu = sum(X .* repmat(w, size(X, 1), 1), 2);
+Sigma = d * diag(w) * d';          
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/bethe_free_energy.m/1.1.1.1/Sun Jul  6 20:57:18 2003//
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/loopy_converged.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_family.m/1.1.1.1/Fri Oct 18 20:05:16 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/pearl_inf_engine.m/1.1.1.1/Sat Jan 11 18:53:28 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@pearl_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/bethe_free_energy.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,50 @@
+function loglik = bethe_free_energy(engine, evidence)
+% BETHE_FREE_ENERGY Compute Bethe free energy approximation to the log likelihood
+% loglik = bethe_free_energy(engine, evidence)
+%
+% The Bethe free energy is given by an exact energy term and an approximate entropy term.
+% Energy
+%  E = -sum_f sum_i b(f,i) ln theta(f,i)
+% where b(f,i) = approximate Pr(family f = i) 
+% and theta(f,i) = Pr(f = i)
+% Entropy
+%  S = H1 - H2
+%  H1 = sum_f sum_p H(b(f))
+% where b(f) = belief on family f, H(.) = entropy
+%  H2 = sum_n (q(n)-1) H(b(n))
+% where q(n) = num. neighbors of n
+%
+% This function was written by Yair Weiss, 8/22/01.
+
+hidden = find(isemptycell(evidence));
+bnet = bnet_from_engine(engine);
+N = length(bnet.dag);
+
+add_ev = 1;
+E=0;H1=0;H2=0;
+loglik=0;
+for n=1:N
+  ps=parents(bnet.dag,n);
+  if (length(ps)==0) % root node
+    qi=length(children(bnet.dag,n))-1;
+  else
+    qi=length(children(bnet.dag,n));
+  end
+  bf = marginal_family(engine, n, add_ev);
+  bf = bf.T(:);
+  e = bnet.equiv_class(n);
+  T = CPD_to_CPT(bnet.CPD{e});
+  T = T(:);
+  E = E-sum(log(T+(T==0)).*bf);
+
+  if length(ps) > 0
+    % root nodes don't count as fmailies
+    H1 = H1+sum(log(bf+(bf==0)).*bf);
+  end
+  
+  bi = marginal_nodes(engine, n, add_ev);
+  bi = bi.T(:);
+  H2 = H2+qi*sum(log(bi+(bi==0)).*bi);
+end
+loglik=E+H1-H2;
+loglik=-loglik;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,153 @@
+function [engine, loglik, niter] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (pearl)
+% [engine, loglik, num_iter] = enter_evidence(engine, evidence, ...)
+% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value (scalar or column vector)
+%
+% The following optional arguments can be specified in the form of name/value pa irs:
+% [default value in brackets]
+%
+% maximize - if 1, does max-product instead of sum-product [0]
+% 'filename' -  msgs will be printed to this file, so you can assess convergence while it runs [engine.filename]
+%
+% e.g., engine = enter_evidence(engine, ev, 'maximize', 1)
+%     
+% For discrete nodes, loglik is the negative Bethe free energy evaluated at the final beliefs.
+% For Gaussian nodes, loglik is currently always 0.
+%
+% 'num_iter' returns the number of iterations used.
+
+maximize = 0;
+filename = engine.filename;
+
+% parse optional params
+args = varargin;
+nargs = length(args);
+if nargs > 0
+  for i=1:2:nargs
+    switch args{i},
+     case 'maximize', maximize = args{i+1};
+     case 'filename', filename = args{i+1};
+     otherwise,
+      error(['invalid argument name ' args{i}]);
+    end
+  end
+end
+    
+
+if maximize
+  error('can''t handle max-prop yet')
+end
+
+engine.maximize = maximize;
+engine.filename = filename;
+engine.bel = []; % reset if necessary
+
+bnet = bnet_from_engine(engine);
+N = length(bnet.dag);
+ns = bnet.node_sizes(:);
+
+observed_bitv = ~isemptycell(evidence);
+disconnected = find(engine.disconnected_nodes_bitv);
+if ~all(observed_bitv(disconnected))
+  error(['The following discrete nodes must be observed: ' num2str(disconnected)])
+end
+msg = init_pearl_msgs(engine.msg_type, engine.msg_dag, ns, evidence);
+
+niter = 1;
+switch engine.protocol
+ case 'parallel', [msg, niter] = parallel_protocol(engine, evidence, msg);
+ case 'tree', msg = tree_protocol(engine, evidence, msg);
+ otherwise,
+  error(['unrecognized protocol ' engine.protocol])
+end
+engine.niter = niter;
+
+engine.marginal = cell(1,N);
+nodes = find(~engine.disconnected_nodes_bitv);
+for n=nodes(:)'
+  engine.marginal{n} = compute_bel(engine.msg_type, msg{n}.pi, msg{n}.lambda);
+end
+
+engine.evidence = evidence; % needed by marginal_nodes and marginal_family
+engine.msg = msg;  % needed by marginal_family
+
+if (nargout >= 2)
+  if (engine.msg_type == 'd')
+    loglik = bethe_free_energy(engine, evidence);
+  else
+    loglik = 0;
+  end
+end
+
+
+
+%%%%%%%%%%%
+
+function msg =  init_pearl_msgs(msg_type, dag, ns, evidence)
+% INIT_MSGS Initialize the lambda/pi message and state vectors
+% msg =  init_msgs(dag, ns, evidence)
+%
+
+N = length(dag);
+msg = cell(1,N);
+observed = ~isemptycell(evidence);
+lam_msg = 1;
+
+for n=1:N
+  ps = parents(dag, n);
+  msg{n}.pi_from_parent = cell(1, length(ps));
+  for i=1:length(ps)
+    p = ps(i);
+    msg{n}.pi_from_parent{i} = mk_msg(msg_type, ns(p));
+  end
+  
+  cs = children(dag, n);
+  msg{n}.lambda_from_child = cell(1, length(cs));
+  for i=1:length(cs)
+    c = cs(i);
+    msg{n}.lambda_from_child{i} = mk_msg(msg_type, ns(n), lam_msg);
+  end
+
+  msg{n}.lambda = mk_msg(msg_type, ns(n), lam_msg);
+  msg{n}.pi = mk_msg(msg_type, ns(n));
+  
+  if observed(n)
+    msg{n}.lambda_from_self = mk_msg_with_evidence(msg_type, ns(n), evidence{n});
+  else
+    msg{n}.lambda_from_self = mk_msg(msg_type, ns(n), lam_msg);
+  end
+end
+
+
+
+%%%%%%%%%
+
+function msg =  mk_msg(msg_type, sz, is_lambda_msg)
+
+if nargin < 3, is_lambda_msg = 0; end
+
+switch msg_type
+ case 'd', msg = ones(sz, 1);
+ case 'g', 
+  if is_lambda_msg
+    msg.precision = zeros(sz, sz);
+    msg.info_state = zeros(sz, 1);
+  else
+    msg.Sigma = zeros(sz, sz);
+    msg.mu = zeros(sz,1);
+  end
+end
+
+%%%%%%%%%%%%
+
+function msg = mk_msg_with_evidence(msg_type, sz, val)
+
+switch msg_type
+ case 'd',
+  msg = zeros(sz, 1);
+  msg(val) = 1;
+ case 'g',
+  %msg.observed_val = val(:);
+  msg.precision = inf;
+  msg.mu = val(:);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/loopy_converged.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function niter = loopy_converged(engine)
+% LOOPY_CONVERGED Did loopy belief propagation converge? 0 means no, eles we return the num. iterations.
+% function niter = loopy_converged(engine)
+%
+% We use a simple heuristic: we say convergence occurred if the number of iterations
+% used was less than the maximum allowed.
+
+if engine.niter == engine.max_iter
+  niter = 0;
+else
+  niter = engine.niter;
+end
+%conv = (strcmp(engine.protocol, 'tree') | (engine.niter < engine.max_iter));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/marginal_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,80 @@
+function m = marginal_family(engine, n, add_ev)
+% MARGINAL_FAMILY Compute the marginal on i's family (loopy)
+% m = marginal_family(engine, n, add_ev)
+
+if nargin < 3, add_ev = 0; end
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes;
+ps = parents(bnet.dag, n);
+dom = [ps n];
+CPD = bnet.CPD{bnet.equiv_class(n)};
+
+switch engine.msg_type
+  case 'd',
+   % The method is similar to the following HMM equation:
+   % xi(i,j,t) = normalise( alpha(i,t) * transmat(i,j) * obsmat(j,t+1) * beta(j,t+1) )
+   % where xi(i,j,t) = Pr(Q(t)=i, Q(t+1)=j | y(1:T))   
+   % beta == lambda, alpha == pi, alpha from each parent = pi msg
+   % In general, if A,B are parents of C,
+   % P(A,B,C) = P(C|A,B) pi_msg(A->C) pi_msg(B->C) lambda(C)
+   % where lambda(C) = P(ev below and including C|C) = prod incoming lamba_msg(children->C)
+   % and pi_msg(X->C) = P(X|ev above) etc
+   
+   T = dpot(dom, ns(dom), CPD_to_CPT(CPD));
+   for j=1:length(ps)
+     p = ps(j);
+     pi_msg = dpot(p, ns(p), engine.msg{n}.pi_from_parent{j});
+     T = multiply_by_pot(T, pi_msg);
+   end         
+   lambda = dpot(n, ns(n), engine.msg{n}.lambda);
+   T = multiply_by_pot(T, lambda);
+   T = normalize_pot(T);
+   m = pot_to_marginal(T);
+   if ~add_ev
+     m.T = shrink_obs_dims_in_table(m.T, dom, engine.evidence);
+   end
+ case 'g',
+  if engine.disconnected_nodes_bitv(n)
+    m.T = 1;
+    m.domain = dom;
+    if add_ev
+      m = add_ev_to_dmarginal(m, engine.evidence, ns)
+    end
+    return;
+  end
+
+  [m, C, W] = gaussian_CPD_params_given_dps(CPD, dom, engine.evidence);
+  cdom = myintersect(dom, bnet.cnodes);
+  pot = linear_gaussian_to_cpot(m, C, W, dom, ns, cdom, engine.evidence); 
+  % linear_gaussian_to_cpot will set the effective size of observed nodes to 0,
+  % so we need to do this explicitely for the messages, too,
+  % so they are all the same size.
+  obs_bitv = ~isemptycell(engine.evidence);
+  ps = parents(engine.msg_dag, n);
+  for j=1:length(ps)
+    p = ps(j);
+    msg = engine.msg{n}.pi_from_parent{j};
+    if obs_bitv(p)
+      pi_msg = mpot(p, 0);
+    else
+      pi_msg = mpot(p, ns(p), 0, msg.mu, msg.Sigma);
+    end
+    pot = multiply_by_pot(pot, mpot_to_cpot(pi_msg));
+  end         
+  msg = engine.msg{n}.lambda;
+  if obs_bitv(n)
+    lambda = cpot(n, 0);
+  else
+    lambda = cpot(n, ns(n), 0, msg.info_state, msg.precision);
+  end
+  pot = multiply_by_pot(pot, lambda);
+  m = pot_to_marginal(pot);
+  if add_ev
+    m = add_evidence_to_gmarginal(m, engine.evidence, bnet.node_sizes, bnet.cnodes);
+  end
+end
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,43 @@
+function marginal = marginal_nodes(engine, query, add_ev)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (loopy)
+% marginal = marginal_nodes(engine, query, add_ev)
+%
+% 'query' must be a single node.
+% add_ev is an optional argument; if 1, observed nodes will be set to their original size,
+% otherwise they will be treated like points.
+   
+if nargin < 3, add_ev = 0; end
+
+if length(query) > 1
+  error('can only compute marginal on single nodes or families')
+end
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes(:);
+
+switch engine.msg_type
+ case 'd',
+  T = engine.marginal{query};
+  if ~add_ev
+    marginal.T = shrink_obs_dims_in_table(T, query, engine.evidence);
+  else
+    marginal.T = T;
+  end
+  marginal.domain = query;
+ 
+ case 'g',
+  if engine.disconnected_nodes_bitv(query)
+    marginal.T = 1;
+    marginal.domain = query;
+    if add_ev
+      marginal = add_ev_to_dmarginal(marginal, engine.evidence, ns)
+    end
+    return;
+  end
+
+  marginal = engine.marginal{query};
+  marginal.domain = query;
+  if ~add_ev
+    marginal = shrink_obs_dims_in_gaussian(marginal, query, engine.evidence, ns);
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/pearl_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,158 @@
+function engine = pearl_inf_engine(bnet, varargin)
+% PEARL_INF_ENGINE Pearl's algorithm (belief propagation)
+% engine = pearl_inf_engine(bnet, ...)
+%
+% If the graph has no loops (undirected cycles), you should use the tree protocol,
+% and the results will be exact.
+% Otherwise, you should use the parallel protocol, and the results may be approximate.
+%
+% Optional arguments [default in brackets]
+% 'protocol' - tree or parallel ['parallel']
+%
+% Optional arguments for the loopy case
+% 'max_iter' - specifies the max num. iterations to perform [2*num nodes]
+% 'tol' - convergence criterion on messages  [1e-3]
+% 'momentum' - msg = (m*old + (1-m)*new). [m=0]
+% 'filename' -  msgs will be printed to this file, so you can assess convergence while it runs [[]]
+% 'storebel' - 1 means save engine.bel{n,t} for every iteration t and hidden node n [0]
+%
+% If there are discrete and cts nodes, we assume all the discretes are observed. In this
+% case, you must use the parallel protocol, and the evidence pattern must be fixed.
+
+
+N = length(bnet.dag);
+protocol = 'parallel';
+max_iter = 2*N;
+% We use N+2 for the following reason:
+% In N iterations, we get the exact answer for a tree.
+% In the N+1st iteration, we notice that the results are the same as before, and terminate.
+% In loopy_converged, we see that N+1 < max = N+2, and declare convergence.
+tol = 1e-3;
+momentum = 0;
+filename = [];
+storebel = 0;
+
+args = varargin;
+for i=1:2:length(args)
+  switch args{i},
+   case 'protocol', protocol = args{i+1};
+   case 'max_iter', max_iter = args{i+1};
+   case 'tol', tol = args{i+1};
+   case 'momentum', momentum = args{i+1};
+   case 'filename', filename = args{i+1};
+   case 'storebel', storebel = args{i+1};
+  end
+end
+
+engine.filename = filename;
+engine.storebel = storebel;
+engine.bel = [];
+
+if strcmp(protocol, 'tree')
+  % We first send messages up to the root (pivot node), and then back towards the leaves.
+  % If the bnet is a singly connected graph (no loops), choosing a root induces a directed tree.
+  % Peot and Shachter discuss ways to pick the root so as to minimize the work,
+  % taking into account which nodes have changed.
+  % For simplicity, we always pick the root to be the last node in the graph.
+  % This means the first pass is equivalent to going forward in time in a DBN.
+
+  engine.root = N;
+  [engine.adj_mat, engine.preorder, engine.postorder, loopy] = ...
+    mk_rooted_tree(bnet.dag, engine.root);
+  % engine.adj_mat might have different edge orientations from bnet.dag
+  if loopy
+    error('can only apply tree protocol to loop-less graphs')
+  end
+else
+  engine.root = [];
+  engine.adj_mat = [];
+  engine.preorder = [];
+  engine.postorder = [];
+end
+
+engine.niter = [];
+engine.protocol = protocol;
+engine.max_iter = max_iter;
+engine.tol = tol;
+engine.momentum = momentum;
+engine.maximize = [];
+
+%onodes = find(~isemptycell(evidence));
+onodes = bnet.observed;
+engine.msg_type = determine_pot_type(bnet, onodes, 1:N); % needed also by marginal_nodes
+if strcmp(engine.msg_type, 'cg')
+  error('messages must be discrete or Gaussian')
+end
+[engine.msg_dag, disconnected_nodes] = mk_msg_dag(bnet, engine.msg_type, onodes);
+engine.disconnected_nodes_bitv = zeros(1,N);
+engine.disconnected_nodes_bitv(disconnected_nodes) = 1;
+
+
+% this is where we store stuff between enter_evidence and marginal_nodes
+engine.marginal = cell(1,N);
+engine.evidence = []; 
+engine.msg = [];
+
+[engine.parent_index, engine.child_index] = mk_loopy_msg_indices(engine.msg_dag);
+
+engine = class(engine, 'pearl_inf_engine', inf_engine(bnet));
+ 
+
+%%%%%%%%%
+
+function [dag, disconnected_nodes] = mk_msg_dag(bnet, msg_type, onodes)
+
+% If we are using Gaussian msgs, all discrete nodes must be observed;
+% they are then disconnected from the graph, so we don't try to send
+% msgs to/from them: their observed value simply serves to index into
+% the right set of parameters for the Gaussian nodes (which use CPD.ps
+% instead of parents(dag), and hence are unaffected by this "surgery").
+
+disconnected_nodes = [];
+switch msg_type
+ case 'd', dag = bnet.dag;
+ case 'g',
+  disconnected_nodes = bnet.dnodes;
+  dag = bnet.dag;
+  for i=disconnected_nodes(:)'
+    ps = parents(bnet.dag, i);
+    cs = children(bnet.dag, i);
+    if ~isempty(ps), dag(ps, i) = 0; end
+    if ~isempty(cs), dag(i, cs) = 0; end
+  end
+end
+
+
+%%%%%%%%%%
+function [parent_index, child_index] = mk_loopy_msg_indices(dag)
+% MK_LOOPY_MSG_INDICES Compute "port numbers" for message passing
+% [parent_index, child_index] = mk_loopy_msg_indices(bnet)
+%
+% child_index{n}(c) = i means c is n's i'th child, i.e., i = find_equiv_posns(c, children(n))
+% child_index{n}(c) = 0 means c is not a child of n.
+% parent_index{n}{p} is defined similarly.
+% We need to use these indices since the pi_from_parent/ lambda_from_child cell arrays
+% cannot be sparse, and hence cannot be indexed by the actual number of the node.
+% Instead, we use the number of the "port" on which the message arrived.
+
+N = length(dag);
+child_index = cell(1,N);
+parent_index = cell(1,N);
+for n=1:N
+  cs = children(dag, n);
+  child_index{n} = sparse(1,N);
+  for i=1:length(cs)
+    c = cs(i);
+    child_index{n}(c) = i;
+  end
+  ps = parents(dag, n);
+  parent_index{n} = sparse(1,N);
+  for i=1:length(ps)
+    p = ps(i);
+    parent_index{n}(p) = i;
+  end
+end
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+/compute_bel.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/parallel_protocol.m/1.1.1.1/Sun Aug 21 20:00:12 2005//
+/prod_lambda_msgs.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/tree_protocol.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@pearl_inf_engine/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/private/compute_bel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function bel = compute_bel(msg_type, pi, lambda)
+
+switch msg_type,
+ case 'd', bel = normalise(pi .* lambda);
+ case 'g',
+  if isinf(lambda.precision) % ignore pi because lambda is completely certain (observed)
+    bel.mu = lambda.mu;
+    bel.Sigma = zeros(length(bel.mu)); % infinite precision => 0 variance
+  elseif all(pi.Sigma==0) % ignore lambda because pi is completely certain (delta fn prior)
+    bel.Sigma = pi.Sigma;
+    bel.mu = pi.mu;
+  elseif all(isinf(pi.Sigma)) % ignore pi because pi is completely uncertain
+    bel.Sigma  = inv(lambda.precision);
+    bel.mu = bel.Sigma * lambda.info_state;
+  elseif all(lambda.precision == 0) % ignore lambda because lambda is completely uncertain
+    bel.Sigma = pi.Sigma;
+    bel.mu = pi.mu;
+  else % combine both pi and lambda
+    pi_precision = inv(pi.Sigma);
+    bel.Sigma = inv(pi_precision + lambda.precision);
+    bel.mu = bel.Sigma*(pi_precision * pi.mu + lambda.info_state);
+  end
+ otherwise, error(['unrecognized msg type ' msg_type])
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/private/parallel_protocol.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,114 @@
+function [msg, niter] = parallel_protocol(engine, evidence, msg)
+
+bnet = bnet_from_engine(engine);
+N = length(bnet.dag);
+ns = bnet.node_sizes(:);
+
+if ~isempty(engine.filename)
+  fid = fopen(engine.filename, 'w');
+  if fid == 0
+    error(['could not open ' engine.filename ' for writing'])
+  end
+else
+  fid = [];
+end
+
+converged = 0;
+iter = 1;
+hidden = find(isemptycell(evidence));
+bel = cell(1,N);
+old_bel = cell(1,N);
+%nodes = mysetdiff(1:N, engine.disconnected_nodes);
+nodes = find(~engine.disconnected_nodes_bitv);
+while ~converged & (iter <= engine.max_iter)
+  % Everybody updates their state in parallel
+  for n=nodes(:)'
+    cs_msg = children(engine.msg_dag, n);
+    %msg{n}.lambda = compute_lambda(n, cs, msg);
+    msg{n}.lambda = prod_lambda_msgs(n, cs_msg, msg, engine.msg_type);
+    ps_orig = parents(bnet.dag, n);
+    msg{n}.pi = CPD_to_pi(bnet.CPD{bnet.equiv_class(n)}, engine.msg_type, n, ps_orig, msg, evidence);
+  end
+  
+  changed = 0;
+  if ~isempty(fid)
+    fprintf(fid, 'ITERATION %d\n', iter);
+  end
+  for n=hidden(:)' % this will not contain any disconnected nodes
+    old_bel{n} = bel{n};
+    bel{n}  = compute_bel(engine.msg_type, msg{n}.pi, msg{n}.lambda);
+    if ~isempty(fid)
+      fprintf(fid, 'node %d: %s\n', n, bel_to_str(bel{n}, engine.msg_type));
+    end
+    if engine.storebel
+      engine.bel{n,iter} = bel{n};
+    end
+    if (iter == 1) | ~approxeq_bel(bel{n}, old_bel{n}, engine.tol, engine.msg_type)
+      changed = 1;
+    end
+  end
+  %converged = ~changed;
+  converged = ~changed & (iter > 1);  % Sonia Leach changed this
+
+  if ~converged
+    % Everybody sends to all their neighbors in parallel
+    for n=nodes(:)'
+      % lambda msgs to parents
+      ps_msg = parents(engine.msg_dag, n);
+      ps_orig = parents(bnet.dag, n);
+      for p=ps_msg(:)'
+	j = engine.child_index{p}(n); % n is p's j'th child
+	old_msg = msg{p}.lambda_from_child{j}(:);
+	new_msg = CPD_to_lambda_msg(bnet.CPD{bnet.equiv_class(n)}, engine.msg_type, n, ps_orig, ...
+				    msg, p, evidence);
+	lam_msg = convex_combination_msg(old_msg, new_msg, engine.momentum, engine.msg_type);
+	msg{p}.lambda_from_child{j} = lam_msg;
+      end 
+
+      % pi msgs to children
+      cs_msg = children(engine.msg_dag, n);
+      for c=cs_msg(:)'
+	j = engine.parent_index{c}(n); % n is c's j'th parent
+	old_msg = msg{c}.pi_from_parent{j}(:);
+	%new_msg = compute_pi_msg(n, cs, msg, c));
+	new_msg = compute_bel(engine.msg_type, msg{n}.pi, prod_lambda_msgs(n, cs_msg, msg, engine.msg_type, c));
+	pi_msg = convex_combination_msg(old_msg, new_msg, engine.momentum, engine.msg_type);
+	msg{c}.pi_from_parent{j} = pi_msg;
+      end
+    end
+    iter = iter + 1;
+  end
+end
+
+if fid > 0, fclose(fid); end
+%niter = iter - 1;
+niter = iter;
+
+%%%%%%%%%%
+
+function str = bel_to_str(bel, type)
+
+switch type
+ case 'd', str = sprintf('%9.4f ', bel(:)');
+ case 'g', str = sprintf('%9.4f ', bel.mu(:)');
+end
+
+
+%%%%%%%
+
+function a = approxeq_bel(bel1, bel2, tol, type)
+
+switch type
+ case 'd', a = approxeq(bel1, bel2, tol);
+ case 'g', a = approxeq(bel1.mu, bel2.mu, tol) & approxeq(bel1.Sigma, bel2.Sigma, tol);
+end
+
+
+%%%%%%%
+
+function msg = convex_combination_msg(old_msg, new_msg, old_weight, type)
+
+switch type
+ case 'd', msg = old_weight * old_msg + (1-old_weight)*new_msg;
+ case 'g', msg = new_msg;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/private/prod_lambda_msgs.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+function lam = prod_lambda_msgs(n, cs, msg, msg_type, except)
+
+if nargin < 5, except = -1; end
+
+lam = msg{n}.lambda_from_self;
+switch msg_type
+  case 'd',
+   for i=1:length(cs)
+     c = cs(i);
+     if c ~= except
+       lam = lam .* msg{n}.lambda_from_child{i};
+     end
+   end  
+ case 'g',
+  if isinf(lam.precision) % isfield(lam, 'observed_val')
+    return; % pass on the observed msg
+  end
+   for i=1:length(cs)
+     c = cs(i);
+     if c ~= except
+       m = msg{n}.lambda_from_child{i};
+       lam.precision = lam.precision + m.precision;
+       lam.info_state = lam.info_state + m.info_state;
+     end
+   end  
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@pearl_inf_engine/private/tree_protocol.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,71 @@
+function msg = tree_protocol(engine, evidence, msg)
+
+bnet = bnet_from_engine(engine);
+N = length(bnet.dag);
+
+% Send messages from leaves to root
+for i=1:N-1
+  n = engine.postorder(i);
+  above = parents(engine.adj_mat, n);
+  msg = send_msgs_to_some_neighbors(n, msg, above, bnet, engine.child_index, engine.parent_index, ...
+				    engine.msg_type, evidence);
+end
+
+% Process root
+n = engine.root;
+cs = children(bnet.dag, n);
+%msg{n}.lambda = compute_lambda(n, cs, msg, engine.msg_type);
+msg{n}.lambda = prod_lambda_msgs(n, cs, msg, engine.msg_type);
+ps = parents(bnet.dag, n);
+msg{n}.pi = CPD_to_pi(bnet.CPD{bnet.equiv_class(n)}, engine.msg_type, n, ps, msg, evidence);
+
+% Send messages from root to leaves
+for i=1:N
+  n = engine.preorder(i);
+  below = children(engine.adj_mat, n);
+  msg = send_msgs_to_some_neighbors(n, msg, below, bnet, engine.child_index, engine.parent_index, ...
+				    engine.msg_type, evidence);
+end
+
+  
+%%%%%%%%%%
+
+function msg = send_msgs_to_some_neighbors(n, msg, valid_nbrs, bnet, child_index, parent_index, ...
+					   msg_type, evidence)
+
+verbose = 0;
+
+ns = bnet.node_sizes;
+dag = bnet.dag;
+e = bnet.equiv_class(n);
+CPD = bnet.CPD{e};
+
+
+cs = children(dag, n);
+%msg{n}.lambda = compute_lambda(n, cs, msg);
+msg{n}.lambda = prod_lambda_msgs(n, cs, msg, msg_type);
+if verbose, fprintf('%d computes lambda\n', n); display(msg{n}.lambda); end
+
+ps = parents(dag, n);
+msg{n}.pi = CPD_to_pi(CPD, msg_type, n, ps, msg, evidence);
+if verbose, fprintf('%d computes pi\n', n); display(msg{n}.pi); end
+
+ps2 = myintersect(parents(dag, n), valid_nbrs);
+for p=ps2(:)'
+  lam_msg = CPD_to_lambda_msg(CPD, msg_type, n, ps, msg, p, evidence);
+  j = child_index{p}(n); % n is p's j'th child
+  msg{p}.lambda_from_child{j} = lam_msg;
+  if verbose, fprintf('%d sends lambda to %d\n', n, p); display(lam_msg); end
+end
+
+cs2 = myintersect(cs, valid_nbrs);
+for c=cs2(:)'
+  %pi_msg = compute_pi_msg(n, cs, msg, c);
+  pi_msg = compute_bel(msg_type, msg{n}.pi, prod_lambda_msgs(n, cs, msg, msg_type, c));
+  j = parent_index{c}(n); % n is c's j'th parent
+  msg{c}.pi_from_parent{j} = pi_msg;
+  if verbose, fprintf('%d sends pi to %d\n', n, c); display(pi_msg); end
+end
+
+
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+/enter_evidence.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/marginal_nodes.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/quickscore_inf_engine.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D/private////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@quickscore_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function engine = enter_evidence(engine, pos, neg)
+% ENTER_EVIDENCE Add evidence to the QMR network
+% engine = enter_evidence(engine, pos, neg)
+%
+% pos = list of leaves that have positive observations
+% neg = list of leaves that have negative observations
+
+% Extract params for the observed findings
+obs = myunion(pos, neg);
+%inhibit_obs = engine.inhibit(obs, :);
+inhibit_obs = engine.inhibit(:,obs)';
+leak_obs = engine.leak(obs);
+
+% Find what nodes correspond to the original observed leaves
+pos2 = find_equiv_posns(pos, obs);
+neg2 = find_equiv_posns(neg, obs);
+engine.post = quickscore(pos2, neg2, inhibit_obs, engine.prior, leak_obs); 
+%engine.post = C_quickscore(pos2, neg2, inhibit_obs, engine.prior, leak_obs); 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function m = marginal_nodes(engine, query)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (quickscore)
+% marginal = marginal_nodes(engine, query)
+%
+% 'query' must be a single disease (root) node.
+
+assert(length(query)==1);
+p = engine.post(query);
+m.T = [1-p p]';
+m.domain = query;
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/private/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/C_quickscore.c/1.1.1.1/Wed May 29 15:59:56 2002//
+/nr.h/1.1.1.1/Wed May 29 15:59:56 2002//
+/nrutil.c/1.1.1.1/Wed May 29 15:59:56 2002//
+/nrutil.h/1.1.1.1/Wed May 29 15:59:56 2002//
+/quickscore.m/1.1.1.1/Wed May 29 15:59:56 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/private/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@quickscore_inf_engine/private
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/private/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/private/C_quickscore.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,164 @@
+/* To compile, type "mex C_quickscore.c" */
+
+#include <stdio.h>
+#include "nrutil.h"
+#include "nrutil.c"
+#include <math.h>
+#include "mex.h"
+
+#define MAX(X,Y) (X)>(Y)?(X):(Y)
+
+int two_to_the(int n)
+{
+  return 1 << n;
+}
+
+void int2bin(int num, int nbits, int bits[])
+{
+  int i, mask;
+  mask = 1 << (nbits-1); /* mask = 0010...0 , where the 1 is in col nbits (rightmost = col 1) */
+  for (i = 0; i < nbits; i++) {
+    bits[i] = ((num & mask) == 0) ? 0 : 1;
+    num <<= 1;
+  }
+}
+
+
+void quickscore(int ndiseases, int nfindings, const double *fpos, int npos, const double *fneg, int nneg,
+                  const double *inhibit, const double *prior, const double *leak, double *prob)
+{
+  double *Pon, *Poff, **Uon, **Uoff, **post, *pterm, *ptermOff, *ptermOn, temp, p, myp;
+  int *bits, nsubsets, *fmask;
+  int f, d, i, j, si, size_subset, sign;
+
+  Pon = dvector(0, ndiseases);
+  Poff = dvector(0, ndiseases);
+  Pon[0] = 1;
+  Poff[0] = 0;
+  for (i=1; i <= ndiseases; i++) {
+    Pon[i] = prior[i-1];
+    Poff[i] = 1-Pon[i];
+  }
+
+  Uon = dmatrix(0, nfindings-1, 0, ndiseases);
+  Uoff = dmatrix(0, nfindings-1, 0, ndiseases);
+  d = 0;
+  for (f=0; f < nfindings; f++) {
+    Uon[f][d] = leak[f];
+    Uoff[f][d] = leak[f];
+  }
+  for (f=0; f < nfindings; f++) {
+    for (d=1; d <= ndiseases; d++) {
+      Uon[f][d] = inhibit[f + nfindings*(d-1)];
+      Uoff[f][d] = 1;
+    }
+  }
+  
+  post = dmatrix(0, ndiseases, 0, 1);
+  for (d = 0; d <= ndiseases; d++) {
+    post[d][0] = 0;
+    post[d][1] = 0;
+  }
+  
+  bits = ivector(0, npos-1);
+  fmask = ivector(0, nfindings-1);
+  pterm = dvector(0, ndiseases);
+  ptermOff = dvector(0, ndiseases);
+  ptermOn = dvector(0, ndiseases);
+
+  nsubsets = two_to_the(npos);
+
+  for (si = 0; si < nsubsets; si++) {
+    int2bin(si, npos, bits);
+    for (i=0; i < nfindings; i++) fmask[i] = 0;
+    for (i=0; i < nneg; i++) fmask[(int)fneg[i]-1] = 1;
+    size_subset = 0;
+    for (i=0; i < npos; i++) {
+      if (bits[i]) {
+	size_subset++;
+	fmask[(int)fpos[i]-1] = 1;
+      }
+    }
+    p = 1;
+    for (d=0; d <= ndiseases; d++) {
+      temp = 1;
+      for (j = 0; j < nfindings; j++) {
+	if (fmask[j]) temp *= Uoff[j][d];
+      }
+      ptermOff[d] = temp;
+
+      temp = 1;
+      for (j = 0; j < nfindings; j++) {
+	if (fmask[j]) temp *= Uon[j][d];
+      }
+      ptermOn[d] = temp;
+
+      pterm[d] = Poff[d]*ptermOff[d] + Pon[d]*ptermOn[d];
+      p *= pterm[d];
+    }
+    sign = (int) pow(-1, size_subset);
+    for (d=0; d <= ndiseases; d++) {
+      myp = p / pterm[d];
+      post[d][0] += sign*(myp * ptermOff[d]);
+      post[d][1] += sign*(myp * ptermOn[d]);
+    }
+  } /* next si */
+
+  
+  for (d=0; d <= ndiseases; d++) {
+    post[d][0] *= Poff[d];
+    post[d][1] *= Pon[d];
+  }
+  for (d=0; d <= ndiseases; d++) {
+    temp = post[d][0] + post[d][1];
+    post[d][0] /= temp;
+    post[d][1] /= temp;
+    if (d>0) { prob[d-1] = post[d][1]; }
+  }
+
+  
+  free_dvector(Pon, 0, ndiseases);
+  free_dvector(Poff, 0, ndiseases);
+  free_dmatrix(Uon, 0, nfindings-1, 0, ndiseases);
+  free_dmatrix(Uoff, 0, nfindings-1, 0, ndiseases);
+  free_dmatrix(post, 0, ndiseases, 0, 1);
+  free_ivector(bits, 0, npos-1);
+  free_ivector(fmask, 0, nfindings-1);
+  free_dvector(pterm, 0, ndiseases);
+  free_dvector(ptermOff, 0, ndiseases);
+  free_dvector(ptermOn, 0, ndiseases);
+}
+
+
+void mexFunction(
+                 int nlhs,       mxArray *plhs[],
+                 int nrhs, const mxArray *prhs[]
+                 )
+{
+  double *fpos, *fneg, *inhibit, *prior, *leak, *prob;
+  int npos, nneg, ndiseases, nfindings;
+  double *p;
+
+  /* read the input args */
+  fpos = mxGetPr(prhs[0]);
+  npos = MAX(mxGetM(prhs[0]), mxGetN(prhs[0]));
+
+  fneg = mxGetPr(prhs[1]);
+  nneg = MAX(mxGetM(prhs[1]), mxGetN(prhs[1]));
+
+  inhibit = mxGetPr(prhs[2]); /* inhibit(finding, disease) */
+  nfindings = mxGetM(prhs[2]);
+  ndiseases = mxGetN(prhs[2]);
+
+  prior = mxGetPr(prhs[3]);
+
+  leak = mxGetPr(prhs[4]);
+
+
+ /* set the output pointers */
+  plhs[0] = mxCreateDoubleMatrix(1, ndiseases, mxREAL);
+  prob = mxGetPr(plhs[0]);
+
+  quickscore(ndiseases, nfindings, fpos, npos, fneg, nneg, inhibit, prior, leak, prob);
+}
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/private/nr.h	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,536 @@
+/* CAUTION: This is the ANSI C (only) version of the Numerical Recipes
+   utility file nr.h.  Do not confuse this file with the same-named
+   file nr.h that is supplied in the 'misc' subdirectory.
+   *That* file is the one from the book, and contains both ANSI and
+   traditional K&R versions, along with #ifdef macros to select the
+   correct version.  *This* file contains only ANSI C.               */
+
+#ifndef _NR_H_
+#define _NR_H_
+
+#ifndef _FCOMPLEX_DECLARE_T_
+typedef struct FCOMPLEX {float r,i;} fcomplex;
+#define _FCOMPLEX_DECLARE_T_
+#endif /* _FCOMPLEX_DECLARE_T_ */
+
+#ifndef _ARITHCODE_DECLARE_T_
+typedef struct {
+	unsigned long *ilob,*iupb,*ncumfq,jdif,nc,minint,nch,ncum,nrad;
+} arithcode;
+#define _ARITHCODE_DECLARE_T_
+#endif /* _ARITHCODE_DECLARE_T_ */
+
+#ifndef _HUFFCODE_DECLARE_T_
+typedef struct {
+	unsigned long *icod,*ncod,*left,*right,nch,nodemax;
+} huffcode;
+#define _HUFFCODE_DECLARE_T_
+#endif /* _HUFFCODE_DECLARE_T_ */
+
+#include <stdio.h>
+
+void addint(double **uf, double **uc, double **res, int nf);
+void airy(float x, float *ai, float *bi, float *aip, float *bip);
+void amebsa(float **p, float y[], int ndim, float pb[],	float *yb,
+	float ftol, float (*funk)(float []), int *iter, float temptr);
+void amoeba(float **p, float y[], int ndim, float ftol,
+	float (*funk)(float []), int *iter);
+float amotry(float **p, float y[], float psum[], int ndim,
+	float (*funk)(float []), int ihi, float fac);
+float amotsa(float **p, float y[], float psum[], int ndim, float pb[],
+	float *yb, float (*funk)(float []), int ihi, float *yhi, float fac);
+void anneal(float x[], float y[], int iorder[], int ncity);
+double anorm2(double **a, int n);
+void arcmak(unsigned long nfreq[], unsigned long nchh, unsigned long nradd,
+	arithcode *acode);
+void arcode(unsigned long *ich, unsigned char **codep, unsigned long *lcode,
+	unsigned long *lcd, int isign, arithcode *acode);
+void arcsum(unsigned long iin[], unsigned long iout[], unsigned long ja,
+	int nwk, unsigned long nrad, unsigned long nc);
+void asolve(unsigned long n, double b[], double x[], int itrnsp);
+void atimes(unsigned long n, double x[], double r[], int itrnsp);
+void avevar(float data[], unsigned long n, float *ave, float *var);
+void balanc(float **a, int n);
+void banbks(float **a, unsigned long n, int m1, int m2, float **al,
+	unsigned long indx[], float b[]);
+void bandec(float **a, unsigned long n, int m1, int m2, float **al,
+	unsigned long indx[], float *d);
+void banmul(float **a, unsigned long n, int m1, int m2, float x[], float b[]);
+void bcucof(float y[], float y1[], float y2[], float y12[], float d1,
+	float d2, float **c);
+void bcuint(float y[], float y1[], float y2[], float y12[],
+	float x1l, float x1u, float x2l, float x2u, float x1,
+	float x2, float *ansy, float *ansy1, float *ansy2);
+void beschb(double x, double *gam1, double *gam2, double *gampl,
+	double *gammi);
+float bessi(int n, float x);
+float bessi0(float x);
+float bessi1(float x);
+void bessik(float x, float xnu, float *ri, float *rk, float *rip,
+	float *rkp);
+float bessj(int n, float x);
+float bessj0(float x);
+float bessj1(float x);
+void bessjy(float x, float xnu, float *rj, float *ry, float *rjp,
+	float *ryp);
+float bessk(int n, float x);
+float bessk0(float x);
+float bessk1(float x);
+float bessy(int n, float x);
+float bessy0(float x);
+float bessy1(float x);
+float beta(float z, float w);
+float betacf(float a, float b, float x);
+float betai(float a, float b, float x);
+float bico(int n, int k);
+void bksub(int ne, int nb, int jf, int k1, int k2, float ***c);
+float bnldev(float pp, int n, long *idum);
+float brent(float ax, float bx, float cx,
+	float (*f)(float), float tol, float *xmin);
+float brent_arg(float ax, float bx, float cx,
+	float (*f)(float, void*), float tol, float *xmin, void *arg);
+void broydn(float x[], int n, int *check,
+	void (*vecfunc)(int, float [], float []));
+void bsstep(float y[], float dydx[], int nv, float *xx, float htry,
+	float eps, float yscal[], float *hdid, float *hnext,
+	void (*derivs)(float, float [], float []));
+void caldat(long julian, int *mm, int *id, int *iyyy);
+void chder(float a, float b, float c[], float cder[], int n);
+float chebev(float a, float b, float c[], int m, float x);
+void chebft(float a, float b, float c[], int n, float (*func)(float));
+void chebpc(float c[], float d[], int n);
+void chint(float a, float b, float c[], float cint[], int n);
+float chixy(float bang);
+void choldc(float **a, int n, float p[]);
+void cholsl(float **a, int n, float p[], float b[], float x[]);
+void chsone(float bins[], float ebins[], int nbins, int knstrn,
+	float *df, float *chsq, float *prob);
+void chstwo(float bins1[], float bins2[], int nbins, int knstrn,
+	float *df, float *chsq, float *prob);
+void cisi(float x, float *ci, float *si);
+void cntab1(int **nn, int ni, int nj, float *chisq,
+	float *df, float *prob, float *cramrv, float *ccc);
+void cntab2(int **nn, int ni, int nj, float *h, float *hx, float *hy,
+	float *hygx, float *hxgy, float *uygx, float *uxgy, float *uxy);
+void convlv(float data[], unsigned long n, float respns[], unsigned long m,
+	int isign, float ans[]);
+void copy(double **aout, double **ain, int n);
+void correl(float data1[], float data2[], unsigned long n, float ans[]);
+void cosft(float y[], int n, int isign);
+void cosft1(float y[], int n);
+void cosft2(float y[], int n, int isign);
+void covsrt(float **covar, int ma, int ia[], int mfit);
+void crank(unsigned long n, float w[], float *s);
+void cyclic(float a[], float b[], float c[], float alpha, float beta,
+	float r[], float x[], unsigned long n);
+void daub4(float a[], unsigned long n, int isign);
+float dawson(float x);
+float dbrent(float ax, float bx, float cx,
+	float (*f)(float), float (*df)(float), float tol, float *xmin);
+void ddpoly(float c[], int nc, float x, float pd[], int nd);
+int decchk(char string[], int n, char *ch);
+void derivs(float x, float y[], float dydx[]);
+float df1dim(float x);
+void dfour1(double data[], unsigned long nn, int isign);
+void dfpmin(float p[], int n, float gtol, int *iter, float *fret,
+	float (*func)(float []), void (*dfunc)(float [], float []));
+float dfridr(float (*func)(float), float x, float h, float *err);
+void dftcor(float w, float delta, float a, float b, float endpts[],
+	float *corre, float *corim, float *corfac);
+void dftint(float (*func)(float), float a, float b, float w,
+	float *cosint, float *sinint);
+void difeq(int k, int k1, int k2, int jsf, int is1, int isf,
+	int indexv[], int ne, float **s, float **y);
+void dlinmin(float p[], float xi[], int n, float *fret,
+	float (*func)(float []), void (*dfunc)(float [], float[]));
+double dpythag(double a, double b);
+void drealft(double data[], unsigned long n, int isign);
+void dsprsax(double sa[], unsigned long ija[], double x[], double b[],
+	unsigned long n);
+void dsprstx(double sa[], unsigned long ija[], double x[], double b[],
+	unsigned long n);
+void dsvbksb(double **u, double w[], double **v, int m, int n, double b[],
+	double x[]);
+void dsvdcmp(double **a, int m, int n, double w[], double **v);
+void eclass(int nf[], int n, int lista[], int listb[], int m);
+void eclazz(int nf[], int n, int (*equiv)(int, int));
+float ei(float x);
+void eigsrt(float d[], float **v, int n);
+float elle(float phi, float ak);
+float ellf(float phi, float ak);
+float ellpi(float phi, float en, float ak);
+void elmhes(float **a, int n);
+float erfcc(float x);
+float erff(float x);
+float erffc(float x);
+void eulsum(float *sum, float term, int jterm, float wksp[]);
+float evlmem(float fdt, float d[], int m, float xms);
+float expdev(long *idum);
+float expint(int n, float x);
+float f1(float x);
+float f1dim(float x);
+float f1dim_arg(float x, void *arg);
+float f2(float y);
+float f3(float z);
+float factln(int n);
+float factrl(int n);
+void fasper(float x[], float y[], unsigned long n, float ofac, float hifac,
+	float wk1[], float wk2[], unsigned long nwk, unsigned long *nout,
+	unsigned long *jmax, float *prob);
+void fdjac(int n, float x[], float fvec[], float **df,
+	void (*vecfunc)(int, float [], float []));
+void fgauss(float x, float a[], float *y, float dyda[], int na);
+void fill0(double **u, int n);
+void fit(float x[], float y[], int ndata, float sig[], int mwt,
+	float *a, float *b, float *siga, float *sigb, float *chi2, float *q);
+void fitexy(float x[], float y[], int ndat, float sigx[], float sigy[],
+	float *a, float *b, float *siga, float *sigb, float *chi2, float *q);
+void fixrts(float d[], int m);
+void fleg(float x, float pl[], int nl);
+void flmoon(int n, int nph, long *jd, float *frac);
+float fmin(float x[]);
+void four1(float data[], unsigned long nn, int isign);
+void fourew(FILE *file[5], int *na, int *nb, int *nc, int *nd);
+void fourfs(FILE *file[5], unsigned long nn[], int ndim, int isign);
+void fourn(float data[], unsigned long nn[], int ndim, int isign);
+void fpoly(float x, float p[], int np);
+void fred2(int n, float a, float b, float t[], float f[], float w[],
+	float (*g)(float), float (*ak)(float, float));
+float fredin(float x, int n, float a, float b, float t[], float f[], float w[],
+	float (*g)(float), float (*ak)(float, float));
+void frenel(float x, float *s, float *c);
+void frprmn(float p[], int n, float ftol, int *iter, float *fret,
+	float (*func)(float []), void (*dfunc)(float [], float []));
+void frprmn_arg(float p[], int n, float ftol, int *iter, float *fret,
+	float (*func)(float [], void*), void (*dfunc)(float [], float [], void*), void* arg);
+void ftest(float data1[], unsigned long n1, float data2[], unsigned long n2,
+	float *f, float *prob);
+float gamdev(int ia, long *idum);
+float gammln(float xx);
+float gammp(float a, float x);
+float gammq(float a, float x);
+float gasdev(long *idum);
+void gaucof(int n, float a[], float b[], float amu0, float x[], float w[]);
+void gauher(float x[], float w[], int n);
+void gaujac(float x[], float w[], int n, float alf, float bet);
+void gaulag(float x[], float w[], int n, float alf);
+void gauleg(float x1, float x2, float x[], float w[], int n);
+void gaussj(float **a, int n, float **b, int m);
+void gcf(float *gammcf, float a, float x, float *gln);
+float golden(float ax, float bx, float cx, float (*f)(float), float tol,
+	float *xmin);
+void gser(float *gamser, float a, float x, float *gln);
+void hpsel(unsigned long m, unsigned long n, float arr[], float heap[]);
+void hpsort(unsigned long n, float ra[]);
+void hqr(float **a, int n, float wr[], float wi[]);
+void hufapp(unsigned long index[], unsigned long nprob[], unsigned long n,
+	unsigned long i);
+void hufdec(unsigned long *ich, unsigned char *code, unsigned long lcode,
+	unsigned long *nb, huffcode *hcode);
+void hufenc(unsigned long ich, unsigned char **codep, unsigned long *lcode,
+	unsigned long *nb, huffcode *hcode);
+void hufmak(unsigned long nfreq[], unsigned long nchin, unsigned long *ilong,
+	unsigned long *nlong, huffcode *hcode);
+void hunt(float xx[], unsigned long n, float x, unsigned long *jlo);
+void hypdrv(float s, float yy[], float dyyds[]);
+fcomplex hypgeo(fcomplex a, fcomplex b, fcomplex c, fcomplex z);
+void hypser(fcomplex a, fcomplex b, fcomplex c, fcomplex z,
+	fcomplex *series, fcomplex *deriv);
+unsigned short icrc(unsigned short crc, unsigned char *bufptr,
+	unsigned long len, short jinit, int jrev);
+unsigned short icrc1(unsigned short crc, unsigned char onech);
+unsigned long igray(unsigned long n, int is);
+void iindexx(unsigned long n, long arr[], unsigned long indx[]);
+void indexx(unsigned long n, float arr[], unsigned long indx[]);
+void interp(double **uf, double **uc, int nf);
+int irbit1(unsigned long *iseed);
+int irbit2(unsigned long *iseed);
+void jacobi(float **a, int n, float d[], float **v, int *nrot);
+void jacobn(float x, float y[], float dfdx[], float **dfdy, int n);
+long julday(int mm, int id, int iyyy);
+void kendl1(float data1[], float data2[], unsigned long n, float *tau, float *z,
+	float *prob);
+void kendl2(float **tab, int i, int j, float *tau, float *z, float *prob);
+void kermom(double w[], double y, int m);
+void ks2d1s(float x1[], float y1[], unsigned long n1,
+	void (*quadvl)(float, float, float *, float *, float *, float *),
+	float *d1, float *prob);
+void ks2d2s(float x1[], float y1[], unsigned long n1, float x2[], float y2[],
+	unsigned long n2, float *d, float *prob);
+void ksone(float data[], unsigned long n, float (*func)(float), float *d,
+	float *prob);
+void kstwo(float data1[], unsigned long n1, float data2[], unsigned long n2,
+	float *d, float *prob);
+void laguer(fcomplex a[], int m, fcomplex *x, int *its);
+void lfit(float x[], float y[], float sig[], int ndat, float a[], int ia[],
+	int ma, float **covar, float *chisq, void (*funcs)(float, float [], int));
+void linbcg(unsigned long n, double b[], double x[], int itol, double tol,
+	 int itmax, int *iter, double *err);
+void linmin(float p[], float xi[], int n, float *fret,
+	float (*func)(float []));
+void linmin_arg(float p[], float xi[], int n, float *fret,
+	float (*func)(float [], void*), void *arg);
+void lnsrch(int n, float xold[], float fold, float g[], float p[], float x[],
+	 float *f, float stpmax, int *check, float (*func)(float []));
+void load(float x1, float v[], float y[]);
+void load1(float x1, float v1[], float y[]);
+void load2(float x2, float v2[], float y[]);
+void locate(float xx[], unsigned long n, float x, unsigned long *j);
+void lop(double **out, double **u, int n);
+void lubksb(float **a, int n, int *indx, float b[]);
+void ludcmp(float **a, int n, int *indx, float *d);
+void machar(int *ibeta, int *it, int *irnd, int *ngrd,
+	int *machep, int *negep, int *iexp, int *minexp, int *maxexp,
+	float *eps, float *epsneg, float *xmin, float *xmax);
+void matadd(double **a, double **b, double **c, int n);
+void matsub(double **a, double **b, double **c, int n);
+void medfit(float x[], float y[], int ndata, float *a, float *b, float *abdev);
+void memcof(float data[], int n, int m, float *xms, float d[]);
+int metrop(float de, float t);
+void mgfas(double **u, int n, int maxcyc);
+void mglin(double **u, int n, int ncycle);
+float midexp(float (*funk)(float), float aa, float bb, int n);
+float midinf(float (*funk)(float), float aa, float bb, int n);
+float midpnt(float (*func)(float), float a, float b, int n);
+float midsql(float (*funk)(float), float aa, float bb, int n);
+float midsqu(float (*funk)(float), float aa, float bb, int n);
+void miser(float (*func)(float []), float regn[], int ndim, unsigned long npts,
+	float dith, float *ave, float *var);
+void mmid(float y[], float dydx[], int nvar, float xs, float htot,
+	int nstep, float yout[], void (*derivs)(float, float[], float[]));
+void mnbrak(float *ax, float *bx, float *cx, float *fa, float *fb,
+	float *fc, float (*func)(float));
+void mnbrak_arg(float *ax, float *bx, float *cx, float *fa, float *fb,
+	float *fc, float (*func)(float, void*), void *arg);
+void mnewt(int ntrial, float x[], int n, float tolx, float tolf);
+void moment(float data[], int n, float *ave, float *adev, float *sdev,
+	float *var, float *skew, float *curt);
+void mp2dfr(unsigned char a[], unsigned char s[], int n, int *m);
+void mpadd(unsigned char w[], unsigned char u[], unsigned char v[], int n);
+void mpdiv(unsigned char q[], unsigned char r[], unsigned char u[],
+	unsigned char v[], int n, int m);
+void mpinv(unsigned char u[], unsigned char v[], int n, int m);
+void mplsh(unsigned char u[], int n);
+void mpmov(unsigned char u[], unsigned char v[], int n);
+void mpmul(unsigned char w[], unsigned char u[], unsigned char v[], int n,
+	int m);
+void mpneg(unsigned char u[], int n);
+void mppi(int n);
+void mprove(float **a, float **alud, int n, int indx[], float b[],
+	float x[]);
+void mpsad(unsigned char w[], unsigned char u[], int n, int iv);
+void mpsdv(unsigned char w[], unsigned char u[], int n, int iv, int *ir);
+void mpsmu(unsigned char w[], unsigned char u[], int n, int iv);
+void mpsqrt(unsigned char w[], unsigned char u[], unsigned char v[], int n,
+	int m);
+void mpsub(int *is, unsigned char w[], unsigned char u[], unsigned char v[],
+	int n);
+void mrqcof(float x[], float y[], float sig[], int ndata, float a[],
+	int ia[], int ma, float **alpha, float beta[], float *chisq,
+	void (*funcs)(float, float [], float *, float [], int));
+void mrqmin(float x[], float y[], float sig[], int ndata, float a[],
+	int ia[], int ma, float **covar, float **alpha, float *chisq,
+	void (*funcs)(float, float [], float *, float [], int), float *alamda);
+void newt(float x[], int n, int *check,
+	void (*vecfunc)(int, float [], float []));
+void odeint(float ystart[], int nvar, float x1, float x2,
+	float eps, float h1, float hmin, int *nok, int *nbad,
+	void (*derivs)(float, float [], float []),
+	void (*rkqs)(float [], float [], int, float *, float, float,
+	float [], float *, float *, void (*)(float, float [], float [])));
+void orthog(int n, float anu[], float alpha[], float beta[], float a[],
+	float b[]);
+void pade(double cof[], int n, float *resid);
+void pccheb(float d[], float c[], int n);
+void pcshft(float a, float b, float d[], int n);
+void pearsn(float x[], float y[], unsigned long n, float *r, float *prob,
+	float *z);
+void period(float x[], float y[], int n, float ofac, float hifac,
+	float px[], float py[], int np, int *nout, int *jmax, float *prob);
+void piksr2(int n, float arr[], float brr[]);
+void piksrt(int n, float arr[]);
+void pinvs(int ie1, int ie2, int je1, int jsf, int jc1, int k,
+	float ***c, float **s);
+float plgndr(int l, int m, float x);
+float poidev(float xm, long *idum);
+void polcoe(float x[], float y[], int n, float cof[]);
+void polcof(float xa[], float ya[], int n, float cof[]);
+void poldiv(float u[], int n, float v[], int nv, float q[], float r[]);
+void polin2(float x1a[], float x2a[], float **ya, int m, int n,
+	float x1, float x2, float *y, float *dy);
+void polint(float xa[], float ya[], int n, float x, float *y, float *dy);
+void powell(float p[], float **xi, int n, float ftol, int *iter, float *fret,
+	float (*func)(float []));
+void predic(float data[], int ndata, float d[], int m, float future[], int nfut);
+float probks(float alam);
+void psdes(unsigned long *lword, unsigned long *irword);
+void pwt(float a[], unsigned long n, int isign);
+void pwtset(int n);
+float pythag(float a, float b);
+void pzextr(int iest, float xest, float yest[], float yz[], float dy[],
+	int nv);
+float qgaus(float (*func)(float), float a, float b);
+void qrdcmp(float **a, int n, float *c, float *d, int *sing);
+float qromb(float (*func)(float), float a, float b);
+float qromo(float (*func)(float), float a, float b,
+	float (*choose)(float (*)(float), float, float, int));
+void qroot(float p[], int n, float *b, float *c, float eps);
+void qrsolv(float **a, int n, float c[], float d[], float b[]);
+void qrupdt(float **r, float **qt, int n, float u[], float v[]);
+float qsimp(float (*func)(float), float a, float b);
+float qtrap(float (*func)(float), float a, float b);
+float quad3d(float (*func)(float, float, float), float x1, float x2);
+void quadct(float x, float y, float xx[], float yy[], unsigned long nn,
+	float *fa, float *fb, float *fc, float *fd);
+void quadmx(float **a, int n);
+void quadvl(float x, float y, float *fa, float *fb, float *fc, float *fd);
+float ran0(long *idum);
+float ran1(long *idum);
+float ran2(long *idum);
+float ran3(long *idum);
+float ran4(long *idum);
+void rank(unsigned long n, unsigned long indx[], unsigned long irank[]);
+void ranpt(float pt[], float regn[], int n);
+void ratint(float xa[], float ya[], int n, float x, float *y, float *dy);
+void ratlsq(double (*fn)(double), double a, double b, int mm, int kk,
+	double cof[], double *dev);
+double ratval(double x, double cof[], int mm, int kk);
+float rc(float x, float y);
+float rd(float x, float y, float z);
+void realft(float data[], unsigned long n, int isign);
+void rebin(float rc, int nd, float r[], float xin[], float xi[]);
+void red(int iz1, int iz2, int jz1, int jz2, int jm1, int jm2, int jmf,
+	int ic1, int jc1, int jcf, int kc, float ***c, float **s);
+void relax(double **u, double **rhs, int n);
+void relax2(double **u, double **rhs, int n);
+void resid(double **res, double **u, double **rhs, int n);
+float revcst(float x[], float y[], int iorder[], int ncity, int n[]);
+void reverse(int iorder[], int ncity, int n[]);
+float rf(float x, float y, float z);
+float rj(float x, float y, float z, float p);
+void rk4(float y[], float dydx[], int n, float x, float h, float yout[],
+	void (*derivs)(float, float [], float []));
+void rkck(float y[], float dydx[], int n, float x, float h,
+	float yout[], float yerr[], void (*derivs)(float, float [], float []));
+void rkdumb(float vstart[], int nvar, float x1, float x2, int nstep,
+	void (*derivs)(float, float [], float []));
+void rkqs(float y[], float dydx[], int n, float *x,
+	float htry, float eps, float yscal[], float *hdid, float *hnext,
+	void (*derivs)(float, float [], float []));
+void rlft3(float ***data, float **speq, unsigned long nn1,
+	unsigned long nn2, unsigned long nn3, int isign);
+float rofunc(float b);
+void rotate(float **r, float **qt, int n, int i, float a, float b);
+void rsolv(float **a, int n, float d[], float b[]);
+void rstrct(double **uc, double **uf, int nc);
+float rtbis(float (*func)(float), float x1, float x2, float xacc);
+float rtflsp(float (*func)(float), float x1, float x2, float xacc);
+float rtnewt(void (*funcd)(float, float *, float *), float x1, float x2,
+	float xacc);
+float rtsafe(void (*funcd)(float, float *, float *), float x1, float x2,
+	float xacc);
+float rtsec(float (*func)(float), float x1, float x2, float xacc);
+void rzextr(int iest, float xest, float yest[], float yz[], float dy[], int nv);
+void savgol(float c[], int np, int nl, int nr, int ld, int m);
+void score(float xf, float y[], float f[]);
+void scrsho(float (*fx)(float));
+float select(unsigned long k, unsigned long n, float arr[]);
+float selip(unsigned long k, unsigned long n, float arr[]);
+void shell(unsigned long n, float a[]);
+void shoot(int n, float v[], float f[]);
+void shootf(int n, float v[], float f[]);
+void simp1(float **a, int mm, int ll[], int nll, int iabf, int *kp,
+	float *bmax);
+void simp2(float **a, int n, int l2[], int nl2, int *ip, int kp, float *q1);
+void simp3(float **a, int i1, int k1, int ip, int kp);
+void simplx(float **a, int m, int n, int m1, int m2, int m3, int *icase,
+	int izrov[], int iposv[]);
+void simpr(float y[], float dydx[], float dfdx[], float **dfdy,
+	int n, float xs, float htot, int nstep, float yout[],
+	void (*derivs)(float, float [], float []));
+void sinft(float y[], int n);
+void slvsm2(double **u, double **rhs);
+void slvsml(double **u, double **rhs);
+void sncndn(float uu, float emmc, float *sn, float *cn, float *dn);
+double snrm(unsigned long n, double sx[], int itol);
+void sobseq(int *n, float x[]);
+void solvde(int itmax, float conv, float slowc, float scalv[],
+	int indexv[], int ne, int nb, int m, float **y, float ***c, float **s);
+void sor(double **a, double **b, double **c, double **d, double **e,
+	double **f, double **u, int jmax, double rjac);
+void sort(unsigned long n, float arr[]);
+void sort2(unsigned long n, float arr[], float brr[]);
+void sort3(unsigned long n, float ra[], float rb[], float rc[]);
+void spctrm(FILE *fp, float p[], int m, int k, int ovrlap);
+void spear(float data1[], float data2[], unsigned long n, float *d, float *zd,
+	float *probd, float *rs, float *probrs);
+void sphbes(int n, float x, float *sj, float *sy, float *sjp, float *syp);
+void splie2(float x1a[], float x2a[], float **ya, int m, int n, float **y2a);
+void splin2(float x1a[], float x2a[], float **ya, float **y2a, int m, int n,
+	float x1, float x2, float *y);
+void spline(float x[], float y[], int n, float yp1, float ypn, float y2[]);
+void splint(float xa[], float ya[], float y2a[], int n, float x, float *y);
+void spread(float y, float yy[], unsigned long n, float x, int m);
+void sprsax(float sa[], unsigned long ija[], float x[], float b[],
+	unsigned long n);
+void sprsin(float **a, int n, float thresh, unsigned long nmax, float sa[],
+	unsigned long ija[]);
+void sprspm(float sa[], unsigned long ija[], float sb[], unsigned long ijb[],
+	float sc[], unsigned long ijc[]);
+void sprstm(float sa[], unsigned long ija[], float sb[], unsigned long ijb[],
+	float thresh, unsigned long nmax, float sc[], unsigned long ijc[]);
+void sprstp(float sa[], unsigned long ija[], float sb[], unsigned long ijb[]);
+void sprstx(float sa[], unsigned long ija[], float x[], float b[],
+	unsigned long n);
+void stifbs(float y[], float dydx[], int nv, float *xx,
+	float htry, float eps, float yscal[], float *hdid, float *hnext,
+	void (*derivs)(float, float [], float []));
+void stiff(float y[], float dydx[], int n, float *x,
+	float htry, float eps, float yscal[], float *hdid, float *hnext,
+	void (*derivs)(float, float [], float []));
+void stoerm(float y[], float d2y[], int nv, float xs,
+	float htot, int nstep, float yout[],
+	void (*derivs)(float, float [], float []));
+void svbksb(float **u, float w[], float **v, int m, int n, float b[],
+	float x[]);
+void svdcmp(float **a, int m, int n, float w[], float **v);
+void svdfit(float x[], float y[], float sig[], int ndata, float a[],
+	int ma, float **u, float **v, float w[], float *chisq,
+	void (*funcs)(float, float [], int));
+void svdvar(float **v, int ma, float w[], float **cvm);
+void toeplz(float r[], float x[], float y[], int n);
+void tptest(float data1[], float data2[], unsigned long n, float *t, float *prob);
+void tqli(float d[], float e[], int n, float **z);
+float trapzd(float (*func)(float), float a, float b, int n);
+void tred2(float **a, int n, float d[], float e[]);
+void tridag(float a[], float b[], float c[], float r[], float u[],
+	unsigned long n);
+float trncst(float x[], float y[], int iorder[], int ncity, int n[]);
+void trnspt(int iorder[], int ncity, int n[]);
+void ttest(float data1[], unsigned long n1, float data2[], unsigned long n2,
+	float *t, float *prob);
+void tutest(float data1[], unsigned long n1, float data2[], unsigned long n2,
+	float *t, float *prob);
+void twofft(float data1[], float data2[], float fft1[], float fft2[],
+	unsigned long n);
+void vander(double x[], double w[], double q[], int n);
+void vegas(float regn[], int ndim, float (*fxn)(float [], float), int init,
+	unsigned long ncall, int itmx, int nprn, float *tgral, float *sd,
+	float *chi2a);
+void voltra(int n, int m, float t0, float h, float *t, float **f,
+	float (*g)(int, float), float (*ak)(int, int, float, float));
+void wt1(float a[], unsigned long n, int isign,
+	void (*wtstep)(float [], unsigned long, int));
+void wtn(float a[], unsigned long nn[], int ndim, int isign,
+	void (*wtstep)(float [], unsigned long, int));
+void wwghts(float wghts[], int n, float h,
+	void (*kermom)(double [], double ,int));
+int zbrac(float (*func)(float), float *x1, float *x2);
+void zbrak(float (*fx)(float), float x1, float x2, int n, float xb1[],
+	float xb2[], int *nb);
+float zbrent(float (*func)(float), float x1, float x2, float tol);
+void zrhqr(float a[], int m, float rtr[], float rti[]);
+float zriddr(float (*func)(float), float x1, float x2, float xacc);
+void zroots(fcomplex a[], int m, fcomplex roots[], int polish);
+
+#endif /* _NR_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/private/nrutil.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,321 @@
+/* CAUTION: This is the ANSI C (only) version of the Numerical Recipes
+   utility file nrutil.c.  Do not confuse this file with the same-named
+   file nrutil.c that is supplied in the 'misc' subdirectory.
+   *That* file is the one from the book, and contains both ANSI and
+   traditional K&R versions, along with #ifdef macros to select the
+   correct version.  *This* file contains only ANSI C.               */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#define NR_END 1
+#define FREE_ARG char*
+
+void nrerror(char error_text[])
+/* Numerical Recipes standard error handler */
+{
+	fprintf(stderr,"Numerical Recipes run-time error...\n");
+	fprintf(stderr,"%s\n",error_text);
+	fprintf(stderr,"...now exiting to system...\n");
+	exit(1);
+}
+
+float *vector(long nl, long nh)
+/* allocate a float vector with subscript range v[nl..nh] */
+{
+	float *v;
+
+	v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float)));
+	if (!v) nrerror("allocation failure in vector()");
+	return v-nl+NR_END;
+}
+
+int *ivector(long nl, long nh)
+/* allocate an int vector with subscript range v[nl..nh] */
+{
+	int *v;
+
+	v=(int *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(int)));
+	if (!v) nrerror("allocation failure in ivector()");
+	return v-nl+NR_END;
+}
+
+unsigned char *cvector(long nl, long nh)
+/* allocate an unsigned char vector with subscript range v[nl..nh] */
+{
+	unsigned char *v;
+
+	v=(unsigned char *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(unsigned char)));
+	if (!v) nrerror("allocation failure in cvector()");
+	return v-nl+NR_END;
+}
+
+unsigned long *lvector(long nl, long nh)
+/* allocate an unsigned long vector with subscript range v[nl..nh] */
+{
+	unsigned long *v;
+
+	v=(unsigned long *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(long)));
+	if (!v) nrerror("allocation failure in lvector()");
+	return v-nl+NR_END;
+}
+
+double *dvector(long nl, long nh)
+/* allocate a double vector with subscript range v[nl..nh] */
+{
+	double *v;
+
+	v=(double *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(double)));
+	if (!v) nrerror("allocation failure in dvector()");
+	return v-nl+NR_END;
+}
+
+float **matrix(long nrl, long nrh, long ncl, long nch)
+/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */
+{
+	long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
+	float **m;
+
+	/* allocate pointers to rows */
+	m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*)));
+	if (!m) nrerror("allocation failure 1 in matrix()");
+	m += NR_END;
+	m -= nrl;
+
+	/* allocate rows and set pointers to them */
+	m[nrl]=(float *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(float)));
+	if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
+	m[nrl] += NR_END;
+	m[nrl] -= ncl;
+
+	for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
+
+	/* return pointer to array of pointers to rows */
+	return m;
+}
+
+double **dmatrix(long nrl, long nrh, long ncl, long nch)
+/* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */
+{
+	long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
+	double **m;
+
+	/* allocate pointers to rows */
+	m=(double **) malloc((size_t)((nrow+NR_END)*sizeof(double*)));
+	if (!m) nrerror("allocation failure 1 in matrix()");
+	m += NR_END;
+	m -= nrl;
+
+	/* allocate rows and set pointers to them */
+	m[nrl]=(double *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(double)));
+	if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
+	m[nrl] += NR_END;
+	m[nrl] -= ncl;
+
+	for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
+
+	/* return pointer to array of pointers to rows */
+	return m;
+}
+
+int **imatrix(long nrl, long nrh, long ncl, long nch)
+/* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */
+{
+	long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
+	int **m;
+
+	/* allocate pointers to rows */
+	m=(int **) malloc((size_t)((nrow+NR_END)*sizeof(int*)));
+	if (!m) nrerror("allocation failure 1 in matrix()");
+	m += NR_END;
+	m -= nrl;
+
+
+	/* allocate rows and set pointers to them */
+	m[nrl]=(int *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(int)));
+	if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
+	m[nrl] += NR_END;
+	m[nrl] -= ncl;
+
+	for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
+
+	/* return pointer to array of pointers to rows */
+	return m;
+}
+
+float **submatrix(float **a, long oldrl, long oldrh, long oldcl, long oldch,
+	long newrl, long newcl)
+/* point a submatrix [newrl..][newcl..] to a[oldrl..oldrh][oldcl..oldch] */
+{
+	long i,j,nrow=oldrh-oldrl+1,ncol=oldcl-newcl;
+	float **m;
+
+	/* allocate array of pointers to rows */
+	m=(float **) malloc((size_t) ((nrow+NR_END)*sizeof(float*)));
+	if (!m) nrerror("allocation failure in submatrix()");
+	m += NR_END;
+	m -= newrl;
+
+	/* set pointers to rows */
+	for(i=oldrl,j=newrl;i<=oldrh;i++,j++) m[j]=a[i]+ncol;
+
+	/* return pointer to array of pointers to rows */
+	return m;
+}
+
+float **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch)
+/* allocate a float matrix m[nrl..nrh][ncl..nch] that points to the matrix
+declared in the standard C manner as a[nrow][ncol], where nrow=nrh-nrl+1
+and ncol=nch-ncl+1. The routine should be called with the address
+&a[0][0] as the first argument. */
+{
+	long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1;
+	float **m;
+
+	/* allocate pointers to rows */
+	m=(float **) malloc((size_t) ((nrow+NR_END)*sizeof(float*)));
+	if (!m) nrerror("allocation failure in convert_matrix()");
+	m += NR_END;
+	m -= nrl;
+
+	/* set pointers to rows */
+	m[nrl]=a-ncl;
+	for(i=1,j=nrl+1;i<nrow;i++,j++) m[j]=m[j-1]+ncol;
+	/* return pointer to array of pointers to rows */
+	return m;
+}
+
+double **convert_dmatrix(double *a, long nrl, long nrh, long ncl, long nch)
+/* allocate a float matrix m[nrl..nrh][ncl..nch] that points to the matrix
+declared in the standard C manner as a[nrow][ncol], where nrow=nrh-nrl+1
+and ncol=nch-ncl+1. The routine should be called with the address
+&a[0][0] as the first argument. */
+{
+	long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1;
+	double **m;
+
+	/* allocate pointers to rows */
+	m=(double **) malloc((size_t) ((nrow+NR_END)*sizeof(double*)));
+	if (!m) nrerror("allocation failure in convert_dmatrix()");
+	m += NR_END;
+	m -= nrl;
+
+	/* set pointers to rows */
+	m[nrl]=a-ncl;
+	for(i=1,j=nrl+1;i<nrow;i++,j++) m[j]=m[j-1]+ncol;
+	/* return pointer to array of pointers to rows */
+	return m;
+}
+
+float ***f3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh)
+/* allocate a float 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
+{
+	long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
+	float ***t;
+
+	/* allocate pointers to pointers to rows */
+	t=(float ***) malloc((size_t)((nrow+NR_END)*sizeof(float**)));
+	if (!t) nrerror("allocation failure 1 in f3tensor()");
+	t += NR_END;
+	t -= nrl;
+
+	/* allocate pointers to rows and set pointers to them */
+	t[nrl]=(float **) malloc((size_t)((nrow*ncol+NR_END)*sizeof(float*)));
+	if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
+	t[nrl] += NR_END;
+	t[nrl] -= ncl;
+
+	/* allocate rows and set pointers to them */
+	t[nrl][ncl]=(float *) malloc((size_t)((nrow*ncol*ndep+NR_END)*sizeof(float)));
+	if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
+	t[nrl][ncl] += NR_END;
+	t[nrl][ncl] -= ndl;
+
+	for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
+	for(i=nrl+1;i<=nrh;i++) {
+		t[i]=t[i-1]+ncol;
+		t[i][ncl]=t[i-1][ncl]+ncol*ndep;
+		for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
+	}
+
+	/* return pointer to array of pointers to rows */
+	return t;
+}
+
+void free_vector(float *v, long nl, long nh)
+/* free a float vector allocated with vector() */
+{
+	free((FREE_ARG) (v+nl-NR_END));
+}
+
+void free_ivector(int *v, long nl, long nh)
+/* free an int vector allocated with ivector() */
+{
+	free((FREE_ARG) (v+nl-NR_END));
+}
+
+void free_cvector(unsigned char *v, long nl, long nh)
+/* free an unsigned char vector allocated with cvector() */
+{
+	free((FREE_ARG) (v+nl-NR_END));
+}
+
+void free_lvector(unsigned long *v, long nl, long nh)
+/* free an unsigned long vector allocated with lvector() */
+{
+	free((FREE_ARG) (v+nl-NR_END));
+}
+
+void free_dvector(double *v, long nl, long nh)
+/* free a double vector allocated with dvector() */
+{
+	free((FREE_ARG) (v+nl-NR_END));
+}
+
+void free_matrix(float **m, long nrl, long nrh, long ncl, long nch)
+/* free a float matrix allocated by matrix() */
+{
+	free((FREE_ARG) (m[nrl]+ncl-NR_END));
+	free((FREE_ARG) (m+nrl-NR_END));
+}
+
+void free_dmatrix(double **m, long nrl, long nrh, long ncl, long nch)
+/* free a double matrix allocated by dmatrix() */
+{
+	free((FREE_ARG) (m[nrl]+ncl-NR_END));
+	free((FREE_ARG) (m+nrl-NR_END));
+}
+
+void free_imatrix(int **m, long nrl, long nrh, long ncl, long nch)
+/* free an int matrix allocated by imatrix() */
+{
+	free((FREE_ARG) (m[nrl]+ncl-NR_END));
+	free((FREE_ARG) (m+nrl-NR_END));
+}
+
+void free_submatrix(float **b, long nrl, long nrh, long ncl, long nch)
+/* free a submatrix allocated by submatrix() */
+{
+	free((FREE_ARG) (b+nrl-NR_END));
+}
+
+void free_convert_matrix(float **b, long nrl, long nrh, long ncl, long nch)
+/* free a matrix allocated by convert_matrix() */
+{
+	free((FREE_ARG) (b+nrl-NR_END));
+}
+
+void free_convert_dmatrix(double **b, long nrl, long nrh, long ncl, long nch)
+/* free a matrix allocated by convert_matrix() */
+{
+	free((FREE_ARG) (b+nrl-NR_END));
+}
+
+void free_f3tensor(float ***t, long nrl, long nrh, long ncl, long nch,
+	long ndl, long ndh)
+/* free a float f3tensor allocated by f3tensor() */
+{
+	free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
+	free((FREE_ARG) (t[nrl]+ncl-NR_END));
+	free((FREE_ARG) (t+nrl-NR_END));
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/private/nrutil.h	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,79 @@
+/* CAUTION: This is the ANSI C (only) version of the Numerical Recipes
+   utility file nrutil.h.  Do not confuse this file with the same-named
+   file nrutil.h that is supplied in the 'misc' subdirectory.
+   *That* file is the one from the book, and contains both ANSI and
+   traditional K&R versions, along with #ifdef macros to select the
+   correct version.  *This* file contains only ANSI C.               */
+
+#ifndef _NR_UTILS_H_
+#define _NR_UTILS_H_
+
+static float sqrarg;
+#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)
+
+static double dsqrarg;
+#define DSQR(a) ((dsqrarg=(a)) == 0.0 ? 0.0 : dsqrarg*dsqrarg)
+
+static double dmaxarg1,dmaxarg2;
+#define DMAX(a,b) (dmaxarg1=(a),dmaxarg2=(b),(dmaxarg1) > (dmaxarg2) ?\
+        (dmaxarg1) : (dmaxarg2))
+
+static double dminarg1,dminarg2;
+#define DMIN(a,b) (dminarg1=(a),dminarg2=(b),(dminarg1) < (dminarg2) ?\
+        (dminarg1) : (dminarg2))
+
+static float maxarg1,maxarg2;
+#define FMAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\
+        (maxarg1) : (maxarg2))
+
+static float minarg1,minarg2;
+#define FMIN(a,b) (minarg1=(a),minarg2=(b),(minarg1) < (minarg2) ?\
+        (minarg1) : (minarg2))
+
+static long lmaxarg1,lmaxarg2;
+#define LMAX(a,b) (lmaxarg1=(a),lmaxarg2=(b),(lmaxarg1) > (lmaxarg2) ?\
+        (lmaxarg1) : (lmaxarg2))
+
+static long lminarg1,lminarg2;
+#define LMIN(a,b) (lminarg1=(a),lminarg2=(b),(lminarg1) < (lminarg2) ?\
+        (lminarg1) : (lminarg2))
+
+static int imaxarg1,imaxarg2;
+#define IMAX(a,b) (imaxarg1=(a),imaxarg2=(b),(imaxarg1) > (imaxarg2) ?\
+        (imaxarg1) : (imaxarg2))
+
+static int iminarg1,iminarg2;
+#define IMIN(a,b) (iminarg1=(a),iminarg2=(b),(iminarg1) < (iminarg2) ?\
+        (iminarg1) : (iminarg2))
+
+#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
+
+void nrerror(char error_text[]);
+float *vector(long nl, long nh);
+int *ivector(long nl, long nh);
+unsigned char *cvector(long nl, long nh);
+unsigned long *lvector(long nl, long nh);
+double *dvector(long nl, long nh);
+float **matrix(long nrl, long nrh, long ncl, long nch);
+double **dmatrix(long nrl, long nrh, long ncl, long nch);
+int **imatrix(long nrl, long nrh, long ncl, long nch);
+float **submatrix(float **a, long oldrl, long oldrh, long oldcl, long oldch,
+	long newrl, long newcl);
+float **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch);
+double **convert_dmatrix(double *a, long nrl, long nrh, long ncl, long nch);
+float ***f3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh);
+void free_vector(float *v, long nl, long nh);
+void free_ivector(int *v, long nl, long nh);
+void free_cvector(unsigned char *v, long nl, long nh);
+void free_lvector(unsigned long *v, long nl, long nh);
+void free_dvector(double *v, long nl, long nh);
+void free_matrix(float **m, long nrl, long nrh, long ncl, long nch);
+void free_dmatrix(double **m, long nrl, long nrh, long ncl, long nch);
+void free_imatrix(int **m, long nrl, long nrh, long ncl, long nch);
+void free_submatrix(float **b, long nrl, long nrh, long ncl, long nch);
+void free_convert_matrix(float **b, long nrl, long nrh, long ncl, long nch);
+void free_convert_dmatrix(double **b, long nrl, long nrh, long ncl, long nch);
+void free_f3tensor(float ***t, long nrl, long nrh, long ncl, long nch,
+	long ndl, long ndh);
+
+#endif /* _NR_UTILS_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/private/quickscore.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,76 @@
+function prob = quickscore(fpos, fneg, inhibit, prior, leak)
+% QUICKSCORE Heckerman's algorithm for BN2O networks.
+% prob = quickscore(fpos, fneg, inhibit, prior, leak)
+% 
+% Consider a BN2O (Binary Node 2-layer Noisy-or) network such as QMR with
+% dieases on the top and findings on the bottom. (We assume all findings are observed,
+% since hidden leaves can be marginalized away.)
+% This algorithm takes O(2^|fpos|) time to compute the marginal on all the diseases.
+%
+% Inputs:
+% fpos = the positive findings (a vector of numbers in {1, ..., Nfindings})
+% fneg = the negative findings (a vector of numbers in {1, ..., Nfindings})
+% inhibit(i,j) = inhibition prob. for finding i, disease j, or 1.0 if j is not a parent.
+% prior(j) = prior prob. disease j is ON. We assume prior(off) = 1-prior(on).
+% leak(i) = inhibition prob. for the leak node for finding i
+%
+% Output:
+% prob(d) = Pr(disease d = on | ev)
+%
+% For details, see
+% - Heckerman, "A tractable inference algorithm for diagnosing multiple diseases", UAI89.
+% - Rish and Dechter, "On the impact of causal independence", UCI tech report, 1998.
+%
+% Note that this algorithm is numerically unstable, since it adds a large number of positive and
+% negative terms and hopes that some of them exactly cancel.
+%
+% For matlab experts, use 'mex' to compile C_quickscore, which has identical behavior to this function.
+
+[nfindings ndiseases] = size(inhibit);
+
+% make the first disease be always on, for the leak term
+Pon = [1 prior(:)'];
+Poff = 1-Pon;
+Uon = [leak(:) inhibit]; % U(f,d) = Pr(f=0|d=1)
+Uoff = [leak(:) ones(nfindings, ndiseases)]; % Uoff(f,d) = Pr(f=0|d=0)
+ndiseases = ndiseases + 1;
+
+npos = length(fpos);
+post = zeros(ndiseases, 2);
+% post(d,1) = alpha Pr(d=off), post(d,2) = alpha Pr(d=m)
+
+FP = length(fpos);
+%allbits = logical(dec2bitv(0:(2^FP - 1), FP));
+allbits = logical(ind2subv(2*ones(1,FP), 1:(2^FP))-1);
+
+for si=1:2^FP
+  bits = allbits(si,:);
+  fprime = fpos(bits);
+  fmask = zeros(1, nfindings);
+  fmask(fneg)=1;
+  fmask(fprime)=1;
+  fmask = logical(fmask);
+  p = 1;
+  pterm = zeros(1, ndiseases);
+  ptermOff = zeros(1, ndiseases);
+  ptermOn = zeros(1, ndiseases);
+  for d=1:ndiseases
+    ptermOff(d) = prod(Uoff(fmask,d));
+    ptermOn(d) = prod(Uon(fmask,d));
+    pterm(d) = Poff(d)*ptermOff(d) + Pon(d)*ptermOn(d);
+  end
+  p = prod(pterm);
+  sign = (-1)^(length(fprime));
+  for d=1:ndiseases
+    myp = p / pterm(d);
+    post(d,1) = post(d,1) + sign*(myp * ptermOff(d));
+    post(d,2) = post(d,2) + sign*(myp * ptermOn(d));
+  end
+end
+
+post(:,1) = post(:,1) .* Poff(:);
+post(:,2) = post(:,2) .* Pon(:);
+post = mk_stochastic(post);
+prob = post(2:end,2)'; % skip the leak term
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@quickscore_inf_engine/quickscore_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function engine = quickscore_inf_engine(inhibit, leak, prior)
+% QUICKSCORE_INF_ENGINE Exact inference for the QMR network
+% engine = quickscore_inf_engine(inhibit, leak, prior)
+%
+% We create an inference engine for QMR-like networks.
+% QMR is a bipartite graph, where the top layer contains hidden disease nodes,
+% and the bottom later contains observed finding nodes.
+% The diseases have Bernoulli CPDs, the findings noisy-or CPDs.
+% The original QMR (Quick Medical Reference) network has specific parameter values which we are not
+% allowed to release, for commercial reasons.
+%
+% inhibit(f,d) = inhibition probability on f->d arc for disease d, finding f
+% If inhibit(f,d) = 1, there is effectively no arc from d->f
+% leak(j) = inhibition prob. on leak node -> finding j arc
+% prior(i) = prob. disease i is on
+%
+% We use exact inference, which takes O(2^P) time, where P is the number of positive findings.
+% For details, see
+% - Heckerman, "A tractable inference algorithm for diagnosing multiple diseases", UAI 89.
+% - Rish and Dechter, "On the impact of causal independence", UCI tech report, 1998.
+% Note that this algorithm is numerically unstable, since it adds a large number of positive and
+% negative terms and hopes that some of them exactly cancel.
+%
+% For an interesting variational approximation, see
+% - Jaakkola and Jordan, "Variational probabilistic inference and the QMR-DT network", JAIR 10, 1999.
+%
+% See also 
+% - "Loopy belief propagation for approximate inference: an empirical study",
+%      K. Murphy, Y. Weiss and M. Jordan, UAI 99.
+
+engine.inhibit = inhibit;
+engine.leak = leak;
+engine.prior = prior;
+
+% store results here between enter_evidence and marginal_nodes
+engine.post = [];
+
+engine = class(engine, 'quickscore_inf_engine'); % not a child of the inf_engine class!
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+/README/1.1.1.1/Sun May 11 15:39:50 2003//
+/clq_containing_nodes.m/1.1.1.1/Wed May 29 11:59:46 2002//
+/enter_evidence.m/1.1.1.1/Wed Mar 12 10:38:00 2003//
+/marginal_difclq_nodes.m/1.1.1.1/Fri Feb 21 11:20:32 2003//
+/marginal_nodes.m/1.1.1.1/Fri Feb 21 11:13:10 2003//
+/marginal_singleclq_nodes.m/1.1.1.1/Wed Jan 29 11:23:58 2003//
+/problems.txt/1.1.1.1/Wed May 29 11:59:46 2002//
+/push.m/1.1.1.1/Mon Feb 10 15:38:04 2003//
+/push_pot_toclique.m/1.1.1.1/Wed May 29 11:59:46 2002//
+/stab_cond_gauss_inf_engine.m/1.1.1.1/Fri Mar 28 17:12:42 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/initialize_engine.m/1.1.1.1/Wed May 29 11:59:46 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/Old/initialize_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,65 @@
+function [engine, loglik] = initialize_engine(engine)
+%initialize
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes(:);
+N = length(bnet.dag);
+
+pot_type = 'scg'
+check_for_cd_arcs([], bnet.cnodes, bnet.dag);
+
+% Evaluate CPDs with evidence, and convert to potentials  
+pot = cell(1, N);
+C = length(engine.cliques);
+inited = zeros(1, C);
+clpot = cell(1, C);
+evidence = cell(1, N);
+for n=1:N
+  fam = family(bnet.dag, n);
+  e = bnet.equiv_class(n);
+  pot{n} = CPD_to_scgpot(bnet.CPD{e}, fam, ns, bnet.cnodes, evidence);
+  cindex = engine.clq_ass_to_node(n);
+  if inited(cindex)
+      %clpot{cindex} = direct_combine_pots(clpot{cindex}, pot{n});
+      clpot{cindex} = direct_combine_pots(pot{n}, clpot{cindex});
+  else
+      clpot{cindex} = pot{n};
+      inited(cindex) = 1;
+  end
+end
+
+for i=1:C
+    if inited(i) == 0
+        clpot{i} = scgpot([], [], [], []);
+    end
+end
+
+seppot = cell(C, C);
+% separators are is not need to initialize
+
+% collect to root (node to parents)
+for n=engine.postorder(1:end-1)
+  for p=parents(engine.jtree, n)
+      [margpot, comppot] = complement_pot(clpot{n}, engine.separator{p,n});
+      margpot = marginalize_pot(clpot{n}, engine.separator{p,n});
+      clpot{n} = comppot;
+      %seppot{p, n} = margpot;
+      clpot{p} = combine_pots(clpot{p}, margpot);
+      %clpot{p} = combine_pots(margpot, clpot{p});
+  end
+end
+
+temppot = clpot;
+%temppot = clpot{engine.root};
+for n=engine.preorder
+  for c=children(engine.jtree, n)
+    seppot{n,c} = marginalize_pot(temppot{n}, engine.separator{n,c});
+    %seppot{n,c} = marginalize_pot(clpot{n}, engine.separator{n,c});
+    %clpot{c} = direct_combine_pots(clpot{c}, seppot{n,c});
+    temppot{c} = direct_combine_pots(temppot{c}, seppot{n,c});
+  end
+end
+
+engine.clpot = clpot;
+engine.seppot = seppot;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/README	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+% Stable conditional Gaussian inference
+% Originally written by Huang, Shan <shan.huang@intel.com> 2001
+% Fixed by Rainer Deventer 2003
+
+
+@techreport{Lauritzen99,
+  author = "S. Lauritzen and F. Jensen",
+  title = "Stable Local Computation with Conditional {G}aussian Distributions",
+  year = 1999,
+  number = "R-99-2014",
+  institution = "Dept. Math. Sciences, Aalborg Univ."
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/clq_containing_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function c = clq_containing_nodes(engine, nodes, fam)
+% CLQ_CONTAINING_NODES Find the lightest clique (if any) that contains the set of nodes
+% c = clq_containing_nodes(engine, nodes, family)
+%
+% If the optional 'family' argument is specified, it means nodes = family(nodes(end)).
+% (This is useful since clq_ass_to_node is not accessible to outsiders.)
+% Returns c=-1 if there is no such clique.
+
+if nargin < 3, fam = 0; else fam = 1; end
+
+if length(nodes)==1
+  c = engine.clq_ass_to_node(nodes(1));
+elseif fam
+  c = engine.clq_ass_to_node(nodes(end));
+else
+  B = engine.cliques_bitv;
+  w = engine.clique_weight;
+  clqs = find(all(B(:,nodes), 2)); % all selected columns must be 1
+  if isempty(clqs)
+    c = -1;
+  else
+    c = clqs(argmin(w(clqs)));     
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,260 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE enter evidence to engine including discrete and continuous evidence
+% [engine, ll] = enter_evidence(engine, evidence)
+%
+% ll is always 0, which is wrong.
+
+if ~isempty(engine.evidence)
+    bnet = bnet_from_engine(engine);
+    engine = stab_cond_gauss_inf_engine(bnet);
+    engine.evidence = evidence;
+else
+    engine.evidence = evidence;
+    bnet = bnet_from_engine(engine);
+end
+
+engine.evidence = evidence;
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes(:);
+observed = ~isemptycell(evidence);
+onodes = find(observed);
+hnodes = find(isemptycell(evidence));
+cobs = myintersect(bnet.cnodes, onodes);
+dobs = myintersect(bnet.dnodes, onodes);
+
+engine = incorporate_dis_evidence(engine, dobs, evidence);
+l = length(cobs);
+for i = 1:l
+    node = cobs(i);
+    engine = incorporate_singleconts_evidence(engine, node, evidence);
+end
+clpot = engine.clpot;
+
+clq_num = length(engine.cliques);
+for n=engine.postorder(1:end-1)
+  for p=parents(engine.jtree, n)
+      [margpot, comppot] = complement_pot(clpot{n}, engine.separator{p,n});
+      clpot{n} = comppot;
+      clpot{p} = combine_pots(clpot{p}, margpot);
+  end
+end
+
+temppot = clpot;
+for n=engine.preorder
+  for c=children(engine.jtree, n)
+    seppot{n,c} = marginalize_pot(temppot{n}, engine.separator{n,c});
+    temppot{c} = direct_combine_pots(temppot{c}, seppot{n,c});
+  end
+end
+engine.clpot = clpot;
+engine.seppot = seppot;
+
+[pot,loglik]=normalize_pot(clpot{engine.root});
+
+%%%%%%%%%%%%%%%%%%
+function engine = incorporate_dis_evidence(engine, donodes, evidence)
+l = length(donodes);
+for i=donodes(:)'
+    node = i;
+    clqid = engine.clq_ass_to_node(node);
+    pot = struct(engine.clpot{clqid});
+    ns = zeros(1, max(pot.domain));
+    ns(pot.ddom) = pot.dsizes;
+    ns(pot.cheaddom) = pot.cheadsizes;
+    ns(pot.ctaildom) = pot.ctailsizes;
+    ddom = pot.ddom;
+    
+    potcarray = cell(1, pot.dsize);
+    for j =1:pot.dsize
+        tpotc = struct(pot.scgpotc{j});
+        potcarray{j} = scgcpot(tpotc.cheadsize, tpotc.ctailsize, 0, tpotc.A, tpotc.B, tpotc.C);
+    end
+    
+    if length(ns(ddom)) == 1
+        matrix = pot.scgpotc;
+    else
+        matrix = reshape(pot.scgpotc,ns(ddom)); 
+        potcarray = reshape(potcarray, ns(ddom));
+    end
+    
+    map = find_equiv_posns(node, ddom);
+    vals = cat(1, evidence{node});
+    index = mk_multi_index(length(ddom), map, vals);
+    potcarray(index{:}) = matrix(index{:});
+    potcarray = potcarray(:);
+    %keyboard;
+    engine.clpot{clqid} = scgpot(pot.ddom, pot.cheaddom, pot.ctaildom, ns, potcarray);
+end
+
+%%%%%%%%%%%%%%%%%%
+function engine = incorporate_singleconts_evidence(engine, node, evidence)
+%incorporate_singleconts_evidence incorporate evidence of 1 continuous node
+B = engine.cliques_bitv;
+clqs_containnode = find(all(B(:,node), 2)); % all selected columns must be 1
+% Every continuous node necessarily apears as head in exactly one clique,
+% which is the clique where it appears closest to the strong root. In all other
+% clique potentials where it appears, it must be a tail node.
+clq_ev_as_head = [];
+for i = clqs_containnode(:)'
+    pot = struct(engine.clpot{i});
+    if myismember(node, pot.cheaddom)
+        clq_ev_as_head = [clq_ev_as_head i];
+        break;
+    end
+end
+	       
+% If we will incorporate the evidence node which is head of a potential we must rearrange
+% the juntion tree by push operation until the tail of the include potential is empty
+if ~isempty(clq_ev_as_head)
+    assert(1 == length(clq_ev_as_head));
+    i = clq_ev_as_head;
+    pot = struct(engine.clpot{i});
+    while ~isempty(pot.ctaildom)
+        [engine, clqtoroot] = push(engine, i, node);
+        i = clqtoroot;
+        pot = struct(engine.clpot{i});
+    end
+    B = engine.cliques_bitv;
+    clqs_containnode = find(all(B(:,node), 2));
+end
+
+for i = clqs_containnode(:)'
+    pot = struct(engine.clpot{i});
+    if myismember(node, pot.cheaddom)
+        engine.clpot{i} = incoporate_evidence_headnode(engine.clpot{i}, node, evidence);
+    else
+        %assert(myismember(node, pot.ctaildom));
+        engine.clpot{i} = incoporate_evidence_tailnode(engine.clpot{i}, node, evidence);
+    end
+end
+
+%%%%%%%%%%%%%%%%%%
+function newscgpot = incoporate_evidence_tailnode(pot, node, evidence)
+%ENTER_EVIDENCE_TAILNODE enter the evidence of 1 tailnode of the scgpot
+newscgpot = pot;
+pot = struct(pot);
+%if isempty(pot.ctaildom)
+if ~myismember(node, pot.ctaildom)
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    % In this case there is no real dependency of the head nodes %
+    % on the tail. The potential should be returned unchanged    %
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    return;
+end
+%newscgpot = scgpot([], [], [], []);
+assert(myismember(node, pot.ctaildom));
+ni = block(find_equiv_posns(node, pot.ctaildom), pot.ctailsizes);
+
+ctaildom = mysetdiff(pot.ctaildom, node);
+cheaddom = pot.cheaddom;
+ddom = pot.ddom;
+domain = mysetdiff(pot.domain, node);
+dsize = pot.dsize;
+ns = zeros(1, max(pot.domain));
+ns(pot.ddom) = pot.dsizes;
+ns(pot.cheaddom) = pot.cheadsizes;
+ns(pot.ctaildom) = pot.ctailsizes;
+cheadsizes = pot.cheadsizes;
+cheadsize = pot.cheadsize;
+ctailsizes = ns(ctaildom);
+ctailsize = sum(ns(ctaildom));
+
+potarray = cell(1, dsize);
+for i=1:dsize
+    potc = struct(pot.scgpotc{i});
+    B = potc.B;
+    A = potc.A + B(:, ni)*evidence{node};
+    B(:, ni) = [];
+    potarray{i} = scgcpot(cheadsize, ctailsize, potc.p, A, B, potc.C);
+end
+
+newscgpot = scgpot(ddom, cheaddom, ctaildom, ns, potarray);
+
+%%%%%%%%%%%%%%%%
+function newscgpot = incoporate_evidence_headnode(pot, node, evidence)
+%ENTER_EVIDENCE_HEADNODE 
+pot = struct(pot);
+y2 = evidence{node};
+assert(myismember(node, pot.cheaddom));
+assert(isempty(pot.ctaildom));
+ddom = pot.ddom;
+cheaddom = mysetdiff(pot.cheaddom, node);
+ctaildom = pot.ctaildom;
+dsize = pot.dsize;
+domain = mysetdiff(pot.domain, node);
+
+ns = zeros(1, max(pot.domain));
+ns(pot.ddom) = pot.dsizes;
+ns(pot.cheaddom) = pot.cheadsizes;
+ns(pot.ctaildom) = pot.ctailsizes;
+ctailsizes = ns(ctaildom);
+ctailsize = sum(ctailsizes);
+cheadsizes = ns(cheaddom);
+cheadsize = sum(cheadsizes);
+onodesize = ns(node);
+
+p = zeros(1,dsize);
+A1 = zeros(cheadsize, dsize);
+A2 = zeros(onodesize, dsize);
+C11 = zeros(cheadsize, cheadsize, dsize);
+C12 = zeros(cheadsize, onodesize, dsize);
+C21 = zeros(onodesize, cheadsize, dsize);
+C22 = zeros(onodesize, onodesize, dsize);
+ZM = zeros(onodesize, onodesize);
+
+n1i = block(find_equiv_posns(cheaddom, pot.cheaddom), pot.cheadsizes);
+n2i = block(find_equiv_posns(node, pot.cheaddom), pot.cheadsizes);
+
+indic = 0;
+for i=1:dsize
+    potc = struct(pot.scgpotc{i});
+    p(i) = potc.p;
+    if ~isempty(n1i)
+        A1(:,i) = potc.A(n1i);
+    end 
+    if ~isempty(n2i)
+        A2(:,i) = potc.A(n2i);
+    end
+    C11(:,:,i) = potc.C(n1i, n1i);
+    C12(:,:,i) = potc.C(n1i, n2i);
+    C21(:,:,i) = potc.C(n2i, n1i);
+    C22(:,:,i) = potc.C(n2i, n2i);
+    if isequal(0, C22(:,:,i)) & isequal(evidence{node}, A2(:, i))
+        indic = i;
+    end
+end
+
+np = zeros(1,dsize);
+nA = zeros(cheadsize, dsize);
+nC = zeros(cheadsize, cheadsize, dsize);
+
+if indic
+    np(:) = 0;
+    np(indic) = p(indic);
+    nA = A1;
+    nC = C11;
+else
+    for i=1:dsize
+        if isequal(0, C22(:,:,i))
+            p(i) = 0;
+            nA(:, i) = A1(:, i);
+            nC(:,:,i) = C11(:,:,i);
+        else
+            sq = (y2 - A2(:,i))' * inv(C22(:,:,i)) * (y2 - A2(:,i));
+            ex = exp(-0.5*sq);
+            %np(i) = p(i) * ex / ( (2 * pi)^(-onodesize/2) * sqrt(det(C22(:,:,i))) );
+            np(i) = p(i) * ex / ( (2 * pi)^(onodesize/2) * sqrt(det(C22(:,:,i))) );
+            nA(:,i) = A1(:,i) + C12(:,:,i) * inv(C22(:,:,i)) * (y2 - A2(:,i));
+            tmp1 = C12(:,:,i) * inv(C22(:,:,i)) * C21(:,:,i);
+            nC(:,:,i) = C11(:,:,i) - tmp1;
+        end
+    end
+end 
+
+scpot = cell(1, dsize);
+W = zeros(cheadsize,ctailsize);
+for i=1:dsize
+    scpot{i} = scgcpot(cheadsize, ctailsize, np(i), nA(:,i), W, nC(:,:,i));
+end
+ns(node) = 0;
+newscgpot = scgpot(ddom, cheaddom, ctaildom, ns, scpot);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_difclq_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,55 @@
+function marginal = marginal_difclq_nodes(engine, query_nodes)
+% MARGINAL_DIFCLQ_NODES get the marginal distribution of nodes which is not in a single clique
+% marginal = marginal_difclq_nodes(engine, query_nodes)
+
+keyboard
+num_clique = length(engine.cliques);
+B = engine.cliques_bitv;
+clqs_containnodes = [];
+for i=1:length(query_nodes)
+    node = query_nodes(i);
+    tnodes = find(all(B(:, node), 2));
+    clqs_containnodes = myunion(clqs_containnodes, tnodes);
+end
+% get all cliques contains query nodes
+
+% get the minimal sub tree in junction which contains these cliques and the node closest to the root of jtree
+[subtree, nroot_node] = min_subtree_conti_nodes(engine.jtree, engine.root, clqs_containnodes);
+if ~mysubset(query_nodes, engine.cliques{nroot_node});
+    % if query nodes is not all memers of the clique closest to the root clique performe push operation
+    engine = push_tree(engine, subtree, query_nodes, nroot_node);
+end
+
+if ~(nroot_node == engine.root)
+    % if the clique closest to the root clique is not the root clique we must direct combine the 
+    % potential with the potential stored in separator toward to root
+    p = parents(engine.jtree, nroot_node);
+    tpot = direct_combine_pots(engine.clpot{nroot_node}, engine.seppot{p, nroot_node});
+else
+    tpot = engine.clpot{nroot_node};
+end
+
+pot = marginalize_pot(tpot, query_nodes);
+marginal = pot_to_marginal(pot);
+marginal.T = normalise(marginal.T);
+
+
+
+function engine = push_tree(engine, tree, query_nodes, inode)
+% PUSH_TREE recursive perform push opeartion on tree
+% engine = push_tree(engine, tree, query_nodes, inode)
+
+cs = children(tree, inode);
+for i = 1:length(cs)
+    node = cs(i);
+    push_tree(engine, tree, query_nodes, node);
+    push_dom = myintersect(engine.cliques{node}, query_nodes);
+    [engine, clqtoroot] = push(engine, node, push_dom);
+end
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,77 @@
+function marginal = marginal_nodes(engine, query, add_ev)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (stab_cond_gauss)
+% marginal = marginal_nodes(engine, query, add_ev)
+%
+% 'query' must be a singleton set.
+% add_ev is an optional argument; if 1, we will "inflate" the marginal of observed nodes
+% to their original size, adding 0s to the positions which contradict the evidence
+
+if nargin < 3, add_ev = 0; end
+if isempty(engine.evidence)
+    hquery = query;  
+else   
+    hquery = [];
+    for i = query
+        if isempty(engine.evidence{i})
+        hquery = [hquery i];
+        end
+    end
+end
+
+bnet = bnet_from_engine(engine);
+
+nclq = length(engine.cliques);
+clique = 0;
+for i = 1:nclq
+  if mysubset(hquery, engine.cliques{i})
+    pot = struct(engine.clpot{i});
+    %if mysubset(hquery, pot.cheaddom) | mysubset(hquery, pot.ddom)
+    if mysubset(hquery, pot.domain)
+     clique = i;
+      break;
+    end
+  end
+end
+
+if isempty(hquery)
+     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+     % If all requested variables are observed, no query is necessary %
+     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+     marginal.mu = [];
+     marginal.Sigma = [];
+     marginal.T = 1.0;
+     marginal.domain = query;
+else
+    if clique == 0
+        marginal = marginal_difclq_nodes(engine, hquery);
+    else 
+        marginal = marginal_singleclq_nodes(engine, clique, hquery);
+    end
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    % Change the format of output, so that it is identical to the %
+    % format obtained by the same request for the junction-tree   %
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    marginal.domain = query;
+    bnet = bnet_from_engine(engine);
+    dquery = myintersect(bnet.dnodes,hquery);
+    ns = bnet.node_sizes(dquery);
+    if length(ns) == 0
+    marginal.T = 1;
+    else
+        if length(ns) == 1
+            ns = [1 ns];
+        end
+        marginal.T = reshape(marginal.T,ns);
+    end
+end
+if add_ev
+  bnet = bnet_from_engine(engine);
+  %marginal = add_ev_to_dmarginal(marginal, engine.evidence, bnet.node_sizes);
+  marginal = add_evidence_to_gmarginal(marginal, engine.evidence, bnet.node_sizes, bnet.cnodes);
+end
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_singleclq_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function marginal = marginal_singleclq_nodes(engine, i, query)
+% MARGINAL_SINGLECLQ_NODES get the marginal distribution of nodes which is in a single clique
+% marginal = marginal_singleclq_nodes(engine, i, query)
+
+pot = struct(engine.clpot{i});
+if isempty(pot.ctaildom)
+    if i ~= engine.root
+        p = parents(engine.jtree, i);
+        tpot = direct_combine_pots(engine.clpot{i}, engine.seppot{p, i});
+    else
+        tpot = engine.clpot{i};
+    end
+    pot = marginalize_pot(tpot, query);
+    
+    marginal = pot_to_marginal(pot);
+    marginal.T = normalise(marginal.T);
+else
+    [engine, clqtoroot] = push(engine, i, query);
+    if clqtoroot == engine.root
+        tpot = engine.clpot{clqtoroot};
+    else
+        p = parents(engine.jtree, clqtoroot);
+        tpot = direct_combine_pots(engine.clpot{clqtoroot}, engine.seppot{p, clqtoroot});
+    end
+    pot = marginalize_pot(tpot, query);
+    
+    marginal = pot_to_marginal(pot);
+    marginal.T = normalise(marginal.T);
+end
+                
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/problems.txt	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,76 @@
+PROBLEMS WITH STAB_COND_GAUSS_INF_ENGINE
+
+
+- enter_evidence always returns ll=0
+  (I set ll=0 since it is not computed)
+
+- fails on scg_3node, probably because the engine needs to be
+re-initialized every time before enter_evidence is called, not just
+when the engine is constructed.
+
+??? Error using ==> assert
+assertion violated: 
+
+K>> dbstack
+dbstack
+> In /home/eecs/murphyk/matlab/BNT/HMM/assert.m at line 9
+  In /home/eecs/murphyk/matlab/BNT/examples/static/SCG/scg_3node.m at line 45
+
+
+
+- crashes on scg3
+
+Error in ==> /home/eecs/murphyk/matlab/BNT/inference/static/@stab_cond_gauss_inf_engine/stab_cond_gauss_inf_engine.m
+On line 77  ==>       clpot{cindex} = direct_combine_pots(pot{n}, clpot{cindex});
+
+K>> dbstack
+dbstack
+> In /home/eecs/murphyk/matlab/BNT/inference/static/@stab_cond_gauss_inf_engine/stab_cond_gauss_inf_engine.m at line 77
+  In /home/eecs/murphyk/matlab/BNT/examples/static/SCG/scg3.m at line 41
+K>> 
+
+
+
+
+
+- fails on scg1 and scg2
+
+Warning: One or more output arguments not assigned during call to 'min_subtree_conti_nodes (nearsest_node2)'.
+Warning in ==> /home/eecs/murphyk/matlab/BNT/graph/min_subtree_conti_nodes.m (nearsest_node2)
+On line 60  ==>     nea_node = nearsest_node2(tree, nodes, n);
+
+K>> dbstack
+dbstack
+> In /home/eecs/murphyk/matlab/BNT/graph/min_subtree_conti_nodes.m (nearsest_node2) at line 60
+  In /home/eecs/murphyk/matlab/BNT/graph/min_subtree_conti_nodes.m (nearest_node) at line 50
+  In /home/eecs/murphyk/matlab/BNT/graph/min_subtree_conti_nodes.m at line 11
+  In /home/eecs/murphyk/matlab/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_difclq_nodes.m at line 17
+  In /home/eecs/murphyk/matlab/BNT/inference/static/@stab_cond_gauss_inf_engine/marginal_nodes.m at line 23
+  In /home/eecs/murphyk/matlab/BNT/examples/static/SCG/scg1.m at line 42
+
+
+
+
+
+- This code fragment, from BNT/graph/min_subtree_conti_nodes, is clearly redundant
+
+function nea_node = nearest_node(tree, root, nodes)
+%get the nearest node to the root in the tree
+nea_node = nearsest_node2(tree, nodes, root);
+
+function nea_node = nearsest_node2(tree, nodes, inode)
+if myismember(inode, nodes)
+    nea_node = inode;
+    return;
+end
+cs = children(tree, inode);
+for i = 1:length(cs)
+    n = cs(i);
+    nea_node = nearsest_node2(tree, nodes, n);
+end
+    
+
+- Some names are badly chosen. 'nearsest' is a mis-spelling. 'min_subtree_conti_nodes' should be
+'min_subtree_containing_nodes' or 'min_subtree_con_nodes'.
+
+- In general, the code needs some heavy polishing.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/push.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function [engine, clqtoroot] = push(engine, clq, pushdom)
+%PUSH_POT push the variables in putshdom which is subset of clq to the clique toword the root and get new engine
+%pushdom is pushed variables set
+%clq is the index of the clique that pushdom belongs to
+
+clqdom = engine.cliques{clq};
+assert( mysubset(pushdom, clqdom));
+clqtoroot = parents(engine.jtree, clq);
+%sepdom = engine.separator{clq, clqtoroot};
+sepdom = engine.separator{clqtoroot, clq};
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Calculate the strong marginal of the union of pushdom and and the separatordomain and  %
+% the corresponding complement                                                           %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%[margpot, comppot] = complement_pot(engine.clpot{clq}, pushdom);
+newsepdom = myunion(pushdom,sepdom);
+[margpot,comppot] = complement_pot(engine.clpot{clq}, newsepdom);
+engine.clpot{clqtoroot} = direct_combine_pots(engine.clpot{clqtoroot}, margpot);
+engine.clpot{clq} = comppot;
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Calculation of the new separator and separatorpotential of the junction tree %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+engine.seppot{clqtoroot, clq} = direct_combine_pots(engine.seppot{clqtoroot, clq}, margpot);
+engine.separator{clqtoroot, clq} = myunion(engine.separator{clqtoroot, clq}, pushdom);
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Add pushdomain to the clique towards the root %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 
+engine.cliques{clqtoroot} = myunion(engine.cliques{clqtoroot}, pushdom);
+
+num_cliques = length(engine.cliques);
+B = sparse(num_cliques, 1);
+for i=1:num_cliques
+  B(i, engine.cliques{i}) = 1;
+end
+engine.cliques_bitv = B;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/push_pot_toclique.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function engine = push_pot_toclique(engine, clqtarget, clq, nodes)
+% PUSH_POT push the variables in putshdom which is subset of clq to the target clique toword the root and get new engine
+% engine = push_pot_toclique(engine, clqtarget, clq, nodes)
+[engine, clqtoroot] = push_pot(engine, clq, nodes)
+while clqtoroot ~= clqtarget
+    [engine, clqtoroot] = push_pot(engine, clqtoroot, nodes)
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@stab_cond_gauss_inf_engine/stab_cond_gauss_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,178 @@
+function engine = stab_cond_gauss_inf_engine(bnet)
+% STAB_COND_GAUSS_INF_ENGINE Junction tree using stable CG potentials
+% engine = cond_gauss_inf_engine(bnet)
+% 
+% This class was written by Shan Huang (shan.huang@intel.com) 2001
+% and fixed by Rainer Deventer deventer@informatik.uni-erlangen.de March 2003
+N = length(bnet.dag);
+clusters = {};
+root = N;
+stages = { 1:N };
+onodes = [];
+engine = init_fields;
+engine.evidence = [];
+engine = class(engine, 'stab_cond_gauss_inf_engine', inf_engine(bnet));
+
+ns = bnet.node_sizes(:);
+ns(onodes) = 1; % observed nodes have only 1 possible value
+
+%[engine.jtree, dummy, engine.cliques, B, w, elim_order, moral_edges, fill_in_edges, strong] = ...
+%    dag_to_jtree(bnet, onodes, stages, clusters);
+
+
+partial_order = determine_elim_constraints(bnet, onodes);
+strong = ~isempty(partial_order);
+stages = {};
+clusters = {};
+[engine.jtree, dummy_root, engine.cliques, B, w, elim_order] = 
+    graph_to_jtree(moralize(bnet.dag), ns, partial_order, stages, clusters);
+
+    
+engine.cliques_bitv = B;
+engine.clique_weight = w;
+C = length(engine.cliques);
+engine.clpot = cell(1,C);
+
+% A node can be a member of many cliques, but is assigned to exactly one, to avoid
+% double-counting its CPD. We assign node i to clique c if c is the "lightest" clique that
+% contains i's family, so it can accomodate its CPD.
+
+engine.clq_ass_to_node = zeros(1, N);
+num_cliques = length(engine.cliques);
+for i=1:N
+  clqs_containing_family = find(all(B(:,family(bnet.dag, i)), 2)); % all selected columns must be 1
+  c = clqs_containing_family(argmin(w(clqs_containing_family)));  
+  engine.clq_ass_to_node(i) = c; 
+end
+
+% Compute the separators between connected cliques.
+[is,js] = find(engine.jtree > 0);
+engine.separator = cell(num_cliques, num_cliques);
+for k=1:length(is)
+  i = is(k); j = js(k);
+  engine.separator{i,j} = find(B(i,:) & B(j,:)); % intersect(cliques{i}, cliques{j});
+end
+%keyboard;
+engine.seppot = cell(C,C);
+
+pot_type = 'scg';
+check_for_cd_arcs([], bnet.cnodes, bnet.dag);
+
+% Make the jtree rooted, so there is a fixed message passing order.
+if strong
+  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+  % Start the search for the strong root at the clique with the  %
+  % highest number.                                              %
+  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+  root = length(engine.cliques);
+  root_found = 0;
+  
+  while ((~root_found) & (root >= 1))
+      root_found = test_strong_root(engine.jtree,engine.cliques,bnet.dnodes,root);
+      if ~root_found
+          root = root - 1;
+      end
+  end
+  assert(root > 0)
+  engine.root = root;
+  % the last clique is guaranteed to be a strong root
+  %engine.root = length(engine.cliques);
+else
+  % jtree_dbn_inf_engine requires the root to contain the interface.
+  % This may conflict with the strong root requirement! *********** BUG *************
+  engine.root = clq_containing_nodes(engine, root);
+  if engine.root <= 0
+    error(['no clique contains ' num2str(root)]);
+  end
+end  
+
+[engine.jtree, engine.preorder, engine.postorder] = mk_rooted_tree(engine.jtree, engine.root);
+
+% Evaluate CPDs with evidence, and convert to potentials  
+pot = cell(1, N);
+inited = zeros(1, C);
+clpot = cell(1, C);
+evidence = cell(1, N);
+for n=1:N
+  fam = family(bnet.dag, n);
+  e = bnet.equiv_class(n);
+  %pot{n} = CPD_to_scgpot(bnet.CPD{e}, fam, ns, bnet.cnodes, evidence);
+  pot{n} = convert_to_pot(bnet.CPD{e}, pot_type, fam(:), evidence);
+  cindex = engine.clq_ass_to_node(n);
+  if inited(cindex)
+      clpot{cindex} = direct_combine_pots(pot{n}, clpot{cindex});
+  else
+      clpot{cindex} = pot{n};
+      inited(cindex) = 1;
+  end
+end
+
+for i=1:C
+    if inited(i) == 0
+        clpot{i} = scgpot([], [], [], []);
+    end
+end
+
+seppot = cell(C, C);
+% separators are is not need to initialize
+
+% collect to root (node to parents)
+% Unlike the HUGIN architecture the complements are stored in the cliques during COLLECT 
+% and the separators are not playing a specific role during this process
+for n=engine.postorder(1:end-1)
+  for p=parents(engine.jtree, n)
+    if ~isempty(engine.separator{p,n})
+      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+      % The empty case might happen for unlinked nodes, i.e. the DAG is not %
+      % a single tree, but a forest                                           %
+      %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+      [margpot, comppot] = complement_pot(clpot{n}, engine.separator{p,n});
+      clpot{n} = comppot;
+      clpot{p} = combine_pots(clpot{p}, margpot);
+    end
+  end
+end
+
+% distribute message from root
+% We have not to store the weak clique marginals and keep the original complement potentials. 
+% This is a minor variation of HUGIN architecture.
+temppot = clpot;
+for n=engine.preorder
+  for c=children(engine.jtree, n)
+    seppot{n,c} = marginalize_pot(temppot{n}, engine.separator{n,c});
+    temppot{c} = direct_combine_pots(temppot{c}, seppot{n,c});
+  end
+end
+
+engine.clpot = clpot;
+engine.seppot = seppot;
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% init_fields()                  %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function engine = init_fields()
+
+engine.evidence = [];
+engine.jtree = [];
+engine.cliques = [];
+engine.cliques_bitv = [];
+engine.clique_weight = [];
+engine.preorder = [];
+engine.postorder = [];
+engine.root = []; 
+engine.clq_ass_to_node = [];
+engine.separator = [];
+engine.clpot =[];
+engine.seppot = [];
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@var_elim_inf_engine/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+/enter_evidence.m/1.1.1.1/Wed Jun 19 22:05:04 2002//
+/find_mpe.m/1.1.1.1/Wed Jun 19 22:11:42 2002//
+/marginal_nodes.m/1.1.1.1/Thu Sep 30 03:09:00 2004//
+/var_elim_inf_engine.m/1.1.1.1/Wed Jun 19 22:04:50 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@var_elim_inf_engine/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static/@var_elim_inf_engine
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@var_elim_inf_engine/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@var_elim_inf_engine/enter_evidence.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function [engine, loglik] = enter_evidence(engine, evidence, varargin)
+% ENTER_EVIDENCE Add the specified evidence to the network (var_elim)
+% [engine, loglik] = enter_evidence(engine, evidence, ...)
+%
+% evidence{i} = [] if if X(i) is hidden, and otherwise contains its observed value (scalar or column vector)
+
+% we could pre-process the evidence here, to prevent repeated work, but we don't.
+engine.evidence = evidence;
+
+if nargout == 2
+  [m, loglik] = marginal_nodes(engine, [1]);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@var_elim_inf_engine/find_mpe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,163 @@
+function mpe = find_mpe(engine, new_evidence, max_over)
+% FIND_MPE Find the most probable explanation of the data (assignment to the hidden nodes)
+% function mpe = find_mpe(engine, evidence, order)
+%
+% PURPOSE:
+%       CALC_MPE Computes the most probable explanation to the network nodes
+%       given the evidence.
+%       
+%       [mpe, ll] = calc_mpe(engine, new_evidence, max_over)
+%
+% INPUT:
+%       bnet  - the bayesian network
+%       new_evidence - optional, if specified - evidence to be incorporated [cell(1,n)]
+%       max_over - optional, if specified determines the variable elimination order [1:n]
+%
+% OUTPUT:
+%       mpe - the MPE assignmet for the net variables (or [] if no satisfying assignment)
+%       ll - log assignment probability.
+%
+% Notes:
+% 1. Adapted from '@var_elim_inf_engine\marginal_nodes' for MPE by Ron Zohar, 8/7/01
+% 2. Only discrete potentials are supported at this time.
+% 3. Complexity: O(nw*) where n is the number of nodes and w* is the induced tree width.
+% 4. Implementation based on:
+%  - R. Dechter, "Bucket Elimination: A Unifying Framework for Probabilistic Inference", 
+%                 UA1 96, pp. 211-219.
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes;
+n = length(bnet.dag);
+evidence = cell(1,n);
+if (nargin<2)
+    new_evidence = evidence;
+end
+
+onodes = find(~isemptycell(new_evidence));  % observed nodes
+hnodes = find(isemptycell(new_evidence));  % hidden nodes
+pot_type = determine_pot_type(bnet, onodes);
+
+if pot_type ~= 'd'
+  error('only disrete potentials supported at this time')    
+end
+
+for i=1:n
+  fam = family(bnet.dag, i);
+  CPT{i} = convert_to_pot(bnet.CPD{bnet.equiv_class(i)}, pot_type, fam(:), evidence);        
+end 
+
+% handle observed nodes: set impossible cases' probability to zero
+% rather than prun matrix (this makes backtracking easier)
+
+for ii=onodes
+  lIdx = 1:ns(ii);
+  lIdx = setdiff(lIdx, new_evidence{ii});
+  
+  sCPT=struct(CPT{ii});  % violate object privacy
+  
+  sargs = '';
+  for jj=1:(length(sCPT.domain)-1)
+    sargs = [sargs, ':,']; 
+  end        
+  for jj=lIdx
+    eval(['sCPT.T(', sargs, num2str(jj), ')=0;']);
+  end
+  CPT{ii}=dpot(sCPT.domain, sCPT.sizes, sCPT.T);        
+end
+
+B = cell(1,n); 
+for b=1:n
+  B{b} = mk_initial_pot(pot_type, [], [], [], []);
+end
+
+if (nargin<3)
+  max_over = (1:n);
+end   
+order = max_over; % no attempt to optimize this
+
+
+% Initialize the buckets with the CPDs assigned to them
+for i=1:n
+  b = bucket_num(domain_pot(CPT{i}), order);
+  B{b} = multiply_pots(B{b}, CPT{i});
+end
+
+% Do backward phase
+max_over = max_over(length(max_over):-1:1); % reverse
+maximize = 1;
+for i=max_over(1:end-1)        
+  % max-ing over variable i which occurs in bucket j
+  j = bucket_num(i, order);
+  rest = mysetdiff(domain_pot(B{j}), i);
+  %temp = marginalize_pot_max(B{j}, rest);
+  temp = marginalize_pot(B{j}, rest, maximize);
+  b = bucket_num(domain_pot(temp), order);
+  %        fprintf('maxing over bucket %d (var %d), putting result into bucket %d\n', j, i, b);
+  sB=struct(B{b});  % violate object privacy
+  if ~isempty(sB.domain)
+    B{b} = multiply_pots(B{b}, temp);
+  else
+    B{b} = temp;
+  end
+end
+result = B{1};
+marginal = pot_to_marginal(result);
+[prob, mpe] = max(marginal.T);
+
+% handle impossible cases
+if ~(prob>0)
+  mpe = [];    
+  ll = -inf;
+  %warning('evidence has zero probability')
+  return
+end
+
+ll = log(prob);
+
+% Do forward phase    
+for ii=2:n
+  marginal = pot_to_marginal(B{ii});
+  mpeidx = [];
+  for jj=order(1:length(mpe))
+    %assert(ismember(jj, marginal.domain)) %%% bug
+    temp = find_equiv_posns(jj, marginal.domain);
+    mpeidx = [mpeidx, temp] ;
+    if isempty(temp)
+      mpeidx = [mpeidx, Inf] ;
+    end
+  end
+  [mpeidxsorted sortedtompe] = sort(mpeidx) ;
+  
+  % maximize the matrix obtained from assigning values from previous buckets.
+  % this is done by building a string and using eval.
+  
+  kk=1;
+  sargs = '(';
+  for jj=1:length(marginal.domain)
+    if (jj~=1)
+      sargs = [sargs, ','];
+    end
+    if (mpeidxsorted(kk)==jj)
+      sargs = [sargs, num2str(mpe(sortedtompe(kk)))];
+      if (kk<length(mpe))
+	kk = kk+1 ;
+      end
+    else
+      sargs = [sargs, ':'];
+    end
+  end
+  sargs = [sargs, ')'] ;   
+  eval(['[val, loc] = max(marginal.T', sargs, ');'])        
+  mpe = [mpe loc];
+end     
+[I,J] = sort(order);
+mpe = mpe(J);
+
+mpe = num2cell(mpe);
+
+%%%%%%%%%
+
+function b = bucket_num(domain, order)
+
+b = max(find_equiv_posns(domain, order));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@var_elim_inf_engine/marginal_nodes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,79 @@
+function [marginal, loglik] = marginal_nodes(engine, query, add_ev)
+% MARGINAL_NODES Compute the marginal on the specified query nodes (var_elim)
+% [marginal, loglik] = marginal_nodes(engine, query)
+
+if nargin < 3, add_ev = 0; end
+
+assert(length(query)>=1);
+
+evidence = engine.evidence;
+
+bnet = bnet_from_engine(engine);
+ns = bnet.node_sizes;
+n = length(bnet.dag);
+
+onodes = find(~isemptycell(evidence));
+hnodes = find(isemptycell(evidence));
+pot_type = determine_pot_type(bnet, onodes);
+
+% Fold the evidence into the CPTs - this could be done in 'enter_evidence'
+CPT = cell(1,n);
+for i=1:n
+  fam = family(bnet.dag, i);
+  CPT{i} = convert_to_pot(bnet.CPD{bnet.equiv_class(i)}, pot_type, fam(:), evidence);
+end
+
+
+
+sum_over = mysetdiff(1:n, query);
+order = [query sum_over]; % no attempt to optimize this
+
+% Initialize the buckets with the product of the CPTs assigned to them
+B = cell(1,n+1); 
+for b=1:n+1
+  B{b} = mk_initial_pot(pot_type, [], [], [], []);
+end
+for i=1:n
+  b = bucket_num(domain_pot(CPT{i}), order);
+  B{b} = multiply_pots(B{b}, CPT{i});
+end
+
+% Do the marginalization
+sum_over = sum_over(length(sum_over):-1:1); % reverse
+for i=sum_over(:)'
+  % summing over variable i which occurs in bucket j
+  j = bucket_num(i, order);
+  rest = mysetdiff(domain_pot(B{j}), i);
+  % minka
+  if ~isempty(rest)
+    temp = marginalize_pot(B{j}, rest);
+    b = bucket_num(domain_pot(temp), order);
+    %fprintf('summing over bucket %d (var %d), putting result into bucket %d\n', j, i, b);
+    B{b} = multiply_pots(B{b}, temp);
+  end
+end
+
+% Combine all the remaining buckets into one
+result = B{1};
+for i=2:length(query)
+  if ~isempty(domain_pot(B{i}))
+    result = multiply_pots(result, B{i});
+  end
+end
+[result, loglik] = normalize_pot(result);
+
+
+marginal = pot_to_marginal(result);
+% minka: from jtree_inf_engine
+if add_ev
+  bnet = bnet_from_engine(engine);
+  %marginal = add_ev_to_dmarginal(marginal, engine.evidence, bnet.node_sizes);
+  marginal = add_evidence_to_gmarginal(marginal, engine.evidence, bnet.node_sizes, bnet.cnodes);
+end
+
+%%%%%%%%%
+
+function b = bucket_num(domain, order)
+
+b = max(find_equiv_posns(domain, order));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/@var_elim_inf_engine/var_elim_inf_engine.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function engine = var_elim_inf_engine(bnet, varargin)
+% VAR_ELIM_INF_ENGINE Variable elimination inference engine
+% engine = var_elim_inf_engine(bnet)
+%
+% For details on variable elimination, see
+% - R. Dechter, "Bucket Elimination: A Unifying Framework for Probabilistic Inference", UA1 96, pp. 211-219. 
+% - Z. Li and B. D'Ambrosio, "Efficient inference in Bayes networks as a combinatorial
+%     optimization problem", Intl. J. Approximate Reasoning, 11(1):55-81, 1994
+% - R. McEliece and S. M. Aji, "The Generalized Distributive Law", IEEE Trans. Inform. Theory, 46(2), 2000
+
+
+% This is where we will store the results between enter_evidence and marginal_nodes
+engine.evidence = [];
+
+engine = class(engine, 'var_elim_inf_engine', inf_engine(bnet));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/dummy/1.1.1.1/Sat Jan 18 22:22:46 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+A D/@belprop_fg_inf_engine////
+A D/@belprop_inf_engine////
+A D/@belprop_mrf2_inf_engine////
+A D/@cond_gauss_inf_engine////
+A D/@enumerative_inf_engine////
+A D/@gaussian_inf_engine////
+A D/@gibbs_sampling_inf_engine////
+A D/@global_joint_inf_engine////
+A D/@jtree_inf_engine////
+A D/@jtree_limid_inf_engine////
+A D/@jtree_mnet_inf_engine////
+A D/@jtree_sparse_inf_engine////
+A D/@likelihood_weighting_inf_engine////
+A D/@pearl_inf_engine////
+A D/@quickscore_inf_engine////
+A D/@stab_cond_gauss_inf_engine////
+A D/@var_elim_inf_engine////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/inference/static
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/inference/static/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/installC_BNT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+BNT_HOME = '/Users/matthiasmauch/Documents/_workspace/_MATLAB/_Toolboxes/FullBNT-1.0.4'; % edit this
+
+d = fullfile(BNT_HOME, 'BNT');
+%PC = (strncmp(computer,'PC',2));
+
+cd(sprintf('%s/potentials/Tables', d))
+mex marg_table.c % used by @dpot/marginalize_pot.m
+mex marg_sparse_table.c %used by sparse jtree
+mex mult_by_table.c
+mex mult_by_sparse_table.c
+mex divide_by_table.c
+mex divide_by_sparse_table.c
+mex rep_mult.c
+
+% Written by Wei Hu
+cd(sprintf('%s/CPDs/@discrete_CPD', d))
+mex convert_to_sparse_table.c
+
+% Written by Wei Hu
+cd(sprintf('%s/inference/static/@jtree_sparse_inf_engine', d))
+mex init_pot.c
+mex collect_evidence.c
+mex distribute_evidence.c
+
+% written by Bhaskara Marthi 
+cd(sprintf('%s/inference/static/@gibbs_sampling_inf_engine/private', d))
+mex compute_posterior.c
+mex get_slice_dbn.c
+mex sample_single_discrete.c
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/installC_graph.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+% These C functions were written by Ilya Shpitser.
+
+if isunix
+  mex -c elim.c;
+  mex -c cell.c;
+  mex -c map.c;
+  mex -DUNIX  best_first_elim_order.c  elim.o  cell.o  map.o;
+  mex -DUNIX  triangulate.c  elim.o  cell.o  map.o;
+else
+  mex -c elim.c;
+  mex -c cell.c;
+  mex -c map.c;
+  mex  best_first_elim_order.c  elim.obj  cell.obj  map.obj;
+  mex  triangulate.c  elim.obj  cell.obj  map.obj;
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+/CovMat.m/1.1.1.1/Sun Jul 28 23:09:42 2002//
+/bayes_update_params.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/bic_score_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/compute_cooling_schedule.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/dirichlet_score_family.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/kpm_learn_struct_mcmc.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/learn_params.m/1.1.1.1/Thu Jun 10 01:28:08 2004//
+/learn_params_dbn.m/1.1.1.1/Sun Feb  2 00:23:38 2003//
+/learn_params_dbn_em.m/1.1.1.1/Mon Aug 18 21:50:34 2003//
+/learn_params_em.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/learn_struct_K2.m/1.1.1.1/Thu Sep 26 08:39:16 2002//
+/learn_struct_dbn_reveal.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/learn_struct_mcmc.m/1.1.1.1/Fri Sep  5 14:06:40 2003//
+/learn_struct_pdag_ic_star.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/learn_struct_pdag_pc.m/1.2/Mon Feb 12 01:15:13 2007//
+/learn_struct_pdag_pc_constrain.m/1.1.1.1/Sun Jul 28 23:09:38 2002//
+/mcmc_sample_to_hist.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/mk_schedule.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/mk_tetrad_data_file.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/score_dags.m/1.1.1.1/Mon Apr  4 01:39:46 2005//
+/score_dags_old.m/1.1.1.1/Wed May 29 15:59:56 2002//
+/score_family.m/1.1.1.1/Thu Jun 10 01:33:14 2004//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/learning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/CovMat.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,39 @@
+function [CovMatrix, obs, varfields] = CovMat(filename,row_cols)
+%[CovMatrix, obs, varfields] = CovMat(filename,row_cols)
+%% generates a Covariance Matrix from a file of data consisting of N columns of M data rows
+%%      filename        string name (with path and extension) of file to open
+%%      row_cols        Number_of_converstions_per_row  (turns into  [3 inf])
+%% Return
+%%      CovMatrix       Covariance matrix
+%%      obs             Number of observations read in
+%%      varfields       Labels of the variables see filename structure below
+%%
+%%  Filename structure: 
+%%      Comma separated, starting with the variable labels, then the data in rows.
+%%    filename test.txt consists of:
+%%
+%%      Earthquake,Burglar,Radio,Alarm,Call
+%%      1,2,3,4,5
+%%      11,22,33,44,55
+%%      . . .
+%%
+%% Example call: 
+%%  [cvmat numdat lables] = CovMat('test.txt',5);
+%%
+%%      Returns Covariance matrix, number of date rows and variable field names
+%% Gary R. Bradski   7/2002
+
+fmtstr = '%f';
+for i = 2:row_cols
+    fmtstr = strcat(fmtstr,',%f');
+end
+
+%% load data
+fidCov = fopen(filename,'r');
+
+varfields = fgetl(fidCov);
+Corx = fscanf(fidCov,fmtstr,[row_cols inf]);
+Corx= Corx';
+[obs bla] = size(Corx);
+CovMatrix = cov(Corx); 
+fclose(fidCov);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/bayes_update_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function bnet = bayes_update_params(bnet, cases, clamped)
+% BAYES_UPDATE_PARAMS Bayesian parameter updating given completely observed data
+% bnet = bayes_update_params(bnet, cases, clamped)
+%
+% If there is a missing data, you must use EM.
+% cases(i,m) is the value assigned to node i in case m (this can also be a cell array).
+% clamped(i,m) = 1 if node i was set by intervention in case m (default: clamped = zeros).
+% Clamped nodes are not updated.
+% If there is a single case, clamped is a list of the clamped nodes, not a bit vector.
+
+
+%if iscell(cases), usecell = 1; else usecell = 0; end
+
+n = length(bnet.dag);
+ncases = size(cases, 2);
+if n ~= size(cases, 1)
+  error('data must be of size nnodes * ncases');
+end
+
+if ncases == 1 % clamped is a list of nodes
+  if nargin < 3, clamped = []; end
+  clamp_set = clamped;
+  clamped = zeros(n,1);
+  clamped(clamp_set) = 1;
+else % each row of clamped is a bit vector
+  if nargin < 3, clamped = zeros(n,ncases); end
+end
+
+for i=1:n
+  e = bnet.equiv_class(i);
+  if adjustable_CPD(bnet.CPD{e})
+    u = find(clamped(i,:)==0);
+    ps = parents(bnet.dag, i);
+    bnet.CPD{e} = bayes_update_params(bnet.CPD{e}, cases(i,u), cases(ps,u));
+  end
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/bic_score_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+function [S, LL] = bic_score(counts, CPT, ncases)
+% BIC_SCORE Bayesian Information Criterion score for a single family
+% [S, LL] = bic_score(counts, CPT, ncases)
+%
+% S is a large sample approximation to the log marginal likelihood,
+% which can be computed using dirichlet_score.
+%
+% S  = \log [ prod_j _prod_k theta_ijk ^ N_ijk ]  - 0.5*d*log(ncases) 
+% where counts encode N_ijk, theta_ijk is the MLE comptued from counts,
+% and d is the num of free parameters.
+
+%CPT = mk_stochastic(counts);
+tiny = exp(-700);
+LL = sum(log(CPT(:)  + tiny) .* counts(:));
+% CPT(i) = 0 iff counts(i) = 0 so it is okay to add tiny
+
+ns = mysize(counts);
+ns_ps = ns(1:end-1);
+ns_self = ns(end);
+nparams = prod([ns_ps (ns_self-1)]);
+% sum-to-1 constraint reduces the effective num. vals of the node by 1
+
+S = LL - 0.5*nparams*log(ncases);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/compute_cooling_schedule.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function temp_schedule = compute_cooling_schedule(init_temp, final_temp, anneal_rate)
+
+temp_schedule = [];
+i = 1;
+temp_schedule(i)=init_temp;
+while temp_schedule(i) > final_temp
+  i = i + 1;
+  temp_schedule(i)=temp_schedule(i-1)*anneal_rate;
+end
+
+  
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/dirichlet_score_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,42 @@
+function LL = dirichlet_score_family(counts, prior)
+% DIRICHLET_SCORE Compute the log marginal likelihood of a single family
+% LL = dirichlet_score(counts, prior)
+%
+% counts(a, b, ..., z) is the number of times parent 1 = a, parent 2 = b, ..., child = z
+% prior is an optional multidimensional array of the same shape as counts.
+% It defaults to a uniform prior.
+% 
+% We marginalize out the parameters:
+% LL = log \int \prod_m P(x(i,m) | x(Pa_i,m), theta_i) P(theta_i) d(theta_i)
+
+
+% LL = log[  prod_j gamma(alpha_ij)/gamma(alpha_ij + N_ij)  *
+%            prod_k gamma(alpha_ijk + N_ijk)/gamma(alpha_ijk)  ]
+% Call the prod_k term U and the prod_j term  V.
+% We reshape all quantities into (j,k) matrices
+% This formula was first derived by Cooper and Herskovits, 1992.
+% See also "Learning Bayesian Networks", Heckerman, Geiger and Chickering, MLJ 95.
+
+ns = mysize(counts);
+ns_ps = ns(1:end-1);
+ns_self = ns(end);
+
+if nargin < 2, prior = normalise(myones(ns)); end
+
+
+if 1
+  prior = reshape(prior(:), [prod(ns_ps) ns_self]);
+  counts = reshape(counts,  [prod(ns_ps) ns_self]);
+  %U = prod(gamma(prior + counts) ./ gamma(prior), 2); % mult over k
+  LU = sum(gammaln(prior + counts) - gammaln(prior), 2);
+  alpha_ij = sum(prior, 2); % sum over k
+  N_ij = sum(counts, 2);
+  %V = gamma(alpha_ij) ./ gamma(alpha_ij + N_ij);
+  LV = gammaln(alpha_ij) - gammaln(alpha_ij + N_ij);
+  %L = prod(U .* V);
+  LL = sum(LU + LV);
+else
+  CPT = mk_stochastic(prior + counts);
+  LL = sum(log(CPT(:) .* counts(:)));
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/kpm_learn_struct_mcmc.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,265 @@
+function [sampled_graphs, accept_ratio, num_edges] = learn_struct_mcmc(data, ns, varargin)
+% LEARN_STRUCT_MCMC  Monte Carla Markov Chain search over DAGs assuming fully observed data
+% [sampled_graphs, accept_ratio, num_edges] = learn_struct_mcmc(data, ns, ...)
+% 
+% data(i,m) is the value of node i in case m.
+% ns(i) is the number of discrete values node i can take on.
+%
+% sampled_graphs{m} is the m'th sampled graph.
+% accept_ratio(t) = acceptance ratio at iteration t
+% num_edges(t) = number of edges in model at iteration t
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% scoring_fn - 'bayesian' or 'bic' [ 'bayesian' ]
+%              Currently, only networks with all tabular nodes support Bayesian scoring.
+% type       - type{i} is the type of CPD to use for node i, where the type is a string
+%              of the form 'tabular', 'noisy_or', 'gaussian', etc. [ all cells contain 'tabular' ]
+% params     - params{i} contains optional arguments passed to the CPD constructor for node i,
+%              or [] if none.  [ all cells contain {'prior', 1}, meaning use uniform Dirichlet priors ]
+% discrete   - the list of discrete nodes [ 1:N ]
+% clamped    - clamped(i,m) = 1 if node i is clamped in case m [ zeros(N, ncases) ]
+% nsamples   - number of samples to draw from the chain after burn-in [ 100*N ]
+% burnin     - number of steps to take before drawing samples [ 5*N ]
+% init_dag   - starting point for the search [ zeros(N,N) ]
+%
+% e.g., samples = learn_struct_mcmc(data, ns, 'nsamples', 1000);
+%
+% This interface is not backwards compatible with BNT2,
+% but is designed to be compatible with the other learn_struct_xxx routines.
+%
+% Note: We currently assume a uniform structural prior.
+
+[n ncases] = size(data);
+
+
+% set default params
+type = cell(1,n);
+params = cell(1,n);
+for i=1:n
+  type{i} = 'tabular';
+  %params{i} = { 'prior', 1 };
+  params{i} = { 'prior_type', 'dirichlet', 'dirichlet_weight', 1 };
+end
+scoring_fn = 'bayesian';
+discrete = 1:n;
+clamped = zeros(n, ncases);
+nsamples = 100*n;
+burnin = 5*n;
+dag = zeros(n);
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'nsamples',   nsamples = args{i+1};
+   case 'burnin',     burnin = args{i+1};
+   case 'init_dag',   dag = args{i+1};
+   case 'scoring_fn', scoring_fn = args{i+1};
+   case 'type',       type = args{i+1}; 
+   case 'discrete',   discrete = args{i+1}; 
+   case 'clamped',    clamped = args{i+1}; 
+   case 'params',     if isempty(args{i+1}), params = cell(1,n); else params = args{i+1};  end
+  end
+end
+
+% We implement the fast acyclicity check described by P. Giudici and R. Castelo,
+% "Improving MCMC model search for data mining", submitted to J. Machine Learning, 2001.
+use_giudici = 1;
+if use_giudici
+  [nbrs, ops, nodes] = mk_nbrs_of_digraph(dag);
+  A = init_ancestor_matrix(dag);
+else
+  [nbrs, ops, nodes] = mk_nbrs_of_dag(dag);
+  A = [];
+end
+
+num_accepts = 1;
+num_rejects = 1;
+T = burnin + nsamples;
+accept_ratio = zeros(1, T);
+num_edges = zeros(1, T);
+sampled_graphs = cell(1, nsamples);
+%sampled_bitv = zeros(nsamples, n^2);
+
+for t=1:T
+  [dag, nbrs, ops, nodes, A, accept] = take_step(dag, nbrs, ops, nodes, ns, data, clamped, A, ...
+						 scoring_fn, discrete, type, params);
+  num_edges(t) = sum(dag(:));
+  num_accepts = num_accepts + accept;
+  num_rejects = num_rejects + (1-accept);
+  accept_ratio(t) =  num_accepts/num_rejects;
+  if t > burnin
+    sampled_graphs{t-burnin} = dag;
+    %sampled_bitv(t-burnin, :) = dag(:)';
+  end
+end
+
+
+%%%%%%%%%
+
+
+function [new_dag, new_nbrs, new_ops, new_nodes, A, accept] = ...
+    take_step(dag, nbrs, ops, nodes, ns, data, clamped, A, ...
+	      scoring_fn, discrete, type, params)
+
+
+use_giudici = ~isempty(A);
+if use_giudici
+  [new_dag, op, i, j] = pick_digraph_nbr(dag, nbrs, ops, nodes, A);
+  %assert(acyclic(new_dag));
+  [new_nbrs, new_ops, new_nodes] = mk_nbrs_of_digraph(new_dag);
+else
+  d = sample_discrete(normalise(ones(1, length(nbrs))));
+  new_dag = nbrs{d};
+  op = ops{d};
+  i = nodes(d, 1); j = nodes(d, 2);
+  [new_nbrs, new_ops, new_nodes] = mk_nbrs_of_dag(new_dag);
+end
+
+bf =  bayes_factor(dag, new_dag, op, i, j, ns, data, clamped, scoring_fn, discrete, type, params);
+
+%R = bf * (new_prior / prior) * (length(nbrs) / length(new_nbrs)); 
+R = bf * (length(nbrs) / length(new_nbrs)); 
+u = rand(1,1);
+if u > min(1,R) % reject the move
+  accept = 0;
+  new_dag = dag;
+  new_nbrs = nbrs;
+  new_ops = ops;
+  new_nodes = nodes;
+else
+  accept = 1;
+  if use_giudici
+    A = update_ancestor_matrix(A, op, i, j, new_dag);
+  end
+end
+
+
+%%%%%%%%%
+
+function bfactor = bayes_factor(old_dag, new_dag, op, i, j, ns, data, clamped, scoring_fn, discrete, type, params)
+
+u = find(clamped(j,:)==0);
+LLnew = score_family(j, parents(new_dag, j), type{j}, scoring_fn, ns, discrete, data(:,u), params{j});
+LLold = score_family(j, parents(old_dag, j), type{j}, scoring_fn, ns, discrete, data(:,u), params{j});
+bf1 = exp(LLnew - LLold);
+
+if strcmp(op, 'rev')  % must also multiply in the changes to i's family
+  u = find(clamped(i,:)==0);
+  LLnew = score_family(i, parents(new_dag, i), type{i}, scoring_fn, ns, discrete, data(:,u), params{i});
+  LLold = score_family(i, parents(old_dag, i), type{i}, scoring_fn, ns, discrete, data(:,u), params{i});
+  bf2 = exp(LLnew - LLold);
+else
+  bf2 = 1;
+end
+bfactor = bf1 * bf2;
+
+
+%%%%%%%% Giudici stuff follows %%%%%%%%%%
+
+
+function [new_dag, op, i, j] = pick_digraph_nbr(dag, digraph_nbrs, ops, nodes, A)
+
+legal = 0;
+while ~legal
+  d = sample_discrete(normalise(ones(1, length(digraph_nbrs))));
+  i = nodes(d, 1); j = nodes(d, 2);
+  switch ops{d}
+   case 'add',
+    if A(i,j)==0
+      legal = 1;
+    end
+   case 'del',
+    legal = 1;
+   case 'rev',
+    ps = mysetdiff(parents(dag, j), i);
+    % if any(A(ps,i)) then there is a path i -> parent of j -> j
+    % so reversing i->j would create a cycle
+    legal = ~any(A(ps, i));
+  end
+end
+%new_dag = digraph_nbrs{d};
+new_dag = digraph_nbrs(:,:,d);
+op = ops{d};
+i = nodes(d, 1); j = nodes(d, 2);
+
+
+%%%%%%%%%%%%%%
+
+
+function A = update_ancestor_matrix(A, op, i, j, dag)
+
+switch op
+ case 'add',
+  A = do_addition(A, op, i, j, dag);
+ case 'del', 
+  A = do_removal(A, op, i, j, dag);
+ case 'rev', 
+  A = do_removal(A, op, i, j, dag);
+  A = do_addition(A, op, j, i, dag);
+end
+
+  
+%%%%%%%%%%%%
+
+function A = do_addition(A, op, i, j, dag)
+
+A(j,i) = 1; % i is an ancestor of j
+anci = find(A(i,:));
+if ~isempty(anci)
+  A(j,anci) = 1; % all of i's ancestors are added to Anc(j)
+end
+ancj = find(A(j,:));
+descj = find(A(:,j)); 
+if ~isempty(ancj)
+  for k=descj(:)'
+    A(k,ancj) = 1; % all of j's ancestors are added to each descendant of j
+  end
+end
+
+%%%%%%%%%%%
+
+function A = do_removal(A, op, i, j, dag)
+
+% find all the descendants of j, and put them in topological order
+%descj = find(A(:,j)); 
+R = reachability_graph(dag);
+descj = find(R(j,:)); 
+order = topological_sort(dag);
+descj_topnum = order(descj);
+[junk, perm] = sort(descj_topnum);
+descj = descj(perm);
+% Update j and all its descendants
+A = update_row(A, j, dag);
+for k = descj(:)'
+  A = update_row(A, k, dag);
+end
+
+%%%%%%%%%
+
+function A = update_row(A, j, dag)
+
+% We compute row j of A
+A(j, :) = 0;
+ps = parents(dag, j);
+if ~isempty(ps)
+  A(j, ps) = 1;
+end
+for k=ps(:)'
+  anck = find(A(k,:));
+  if ~isempty(anck)
+    A(j, anck) = 1;
+  end
+end
+  
+%%%%%%%%
+
+function A = init_ancestor_matrix(dag)
+
+order = topological_sort(dag);
+A = zeros(length(dag));
+for j=order(:)'
+  A = update_row(A, j, dag);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/learn_params.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function bnet = learn_params(bnet, data)
+% LEARN_PARAMS Find the maximum likelihood params for a fully observed model
+% bnet = learn_params(bnet, data)
+%
+% data(i,m) is the value of node i in case m (can be a cell array)
+%
+% We set bnet.CPD{i} to its ML/MAP estimate.
+%
+% Currently we assume no param tying
+
+% AND THAT EACH DATA POINT IS A SCALAR - no longer assumed
+
+%if iscell(data)
+%  data=cell2num(data);
+%end
+[n ncases] = size(data);
+for j=1:n
+  e = bnet.equiv_class(j);
+  assert(e==j);
+  if adjustable_CPD(bnet.CPD{e})
+    fam = family(bnet.dag,j);
+    %bnet.CPD{j} = learn_params(bnet.CPD{j}, data(fam,:));
+    bnet.CPD{j} = learn_params(bnet.CPD{j}, fam, data, bnet.node_sizes, bnet.cnodes);
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/learn_params_dbn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+function bnet = learn_params_dbn(bnet, data)
+% LEARN_PARAM_DBN Estimate params of a DBN for a fully observed model
+% bnet = learn_params_dbn(bnet, data)
+%
+% data(i,t) is the value of node i in slice t (can be a cell array)
+% We currently assume there is a single time series
+%
+% We set bnet.CPD{i} to its ML/MAP estimate.
+%
+% Currently we assume each node in the first 2 slices has its own CPD (no param tying);
+% all nodes in slices >2 share their params with slice 2 as usual.
+
+[ss T] = size(data);
+
+% slice 1
+for j=1:ss
+  if adjustable_CPD(bnet.CPD{j})
+    fam = family(bnet.dag,j);
+    bnet.CPD{j} = learn_params(bnet.CPD{j}, data(fam,1));
+  end
+end
+
+
+% slices 2:T
+% data2(:,t) contains [data(:,t-1); data(:,t)].
+% Then we extract out the rows corresponding to the parents in the current and previous slice.
+data2 = [data(:,1:T-1);
+	 data(:,2:T)];
+for j=1:ss
+  j2 = j+ss;
+  if adjustable_CPD(bnet.CPD{j2})
+    fam = family(bnet.dag,j2);
+    bnet.CPD{j2} = learn_params(bnet.CPD{j2}, data2(fam,:));
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/learn_params_dbn_em.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,179 @@
+function [bnet, LL, engine] = learn_params_dbn_em(engine, evidence, varargin)
+% LEARN_PARAMS_DBN Set the parameters in a DBN to their ML/MAP values using batch EM.
+% [bnet, LLtrace, engine] = learn_params_dbn_em(engine, data, ...)
+%
+% data{l}{i,t} = value of node i in slice t of time-series l, or [] if hidden.
+%   Suppose you have L time series, each of length T, in an O*T*L array D, 
+%   where O is the num of observed scalar nodes, and N is the total num nodes per slice.
+%   Then you can create data as follows, where onodes is the index of the observable nodes:
+%      data = cell(1,L);
+%      for l=1:L
+%        data{l} = cell(N, T);
+%        data{l}(onodes,:) = num2cell(D(:,:,l));
+%      end
+% Of course it is possible for different sets of nodes to be observed in
+% each slice/ sequence, and for each sequence to be a different length.
+%
+% LLtrace is the learning curve: the vector of log-likelihood scores at each iteration.
+%
+% Optional arguments [default]
+%
+% max_iter - specifies the maximum number of iterations [100]
+% thresh - specifies the thresold for stopping EM [1e-3]
+%   We stop when |f(t) - f(t-1)| / avg < threshold,
+%   where avg = (|f(t)| + |f(t-1)|)/2 and f is log lik.
+% verbose - display loglik at each iteration [1]
+% anneal - 1 means do deterministic annealing (only for entropic priors) [0]
+% anneal_rate - geometric cooling rate [0.8]
+% init_temp - initial annealing temperature [10]
+% final_temp - final annealing temperature [1e-3]
+%
+
+max_iter = 100;
+thresh = 1e-3;
+anneal = 0;
+anneal_rate = 0.8;
+init_temp = 10;
+final_temp = 1e-3;
+verbose = 1;
+
+for i=1:2:length(varargin)
+  switch varargin{i}
+   case 'max_iter', max_iter = varargin{i+1}; 
+   case 'thresh', thresh = varargin{i+1}; 
+   case 'anneal', anneal = varargin{i+1}; 
+   case 'anneal_rate', anneal_rate = varargin{i+1}; 
+   case 'init_temp', init_temp = varargin{i+1}; 
+   case 'final_temp', final_temp = varargin{i+1}; 
+   otherwise, error(['unrecognized argument' varargin{i}])
+  end
+end
+
+% take 1 EM step at each temperature value, then when temp=0, run to convergence
+% When using an entropic prior, Z = 1-T, so 
+% T=2 => Z=-1 (max entropy)
+% T=1 => Z=0 (max likelihood)
+% T=0 => Z=1 (min entropy / max structure)
+num_iter = 1;
+LL = [];
+if anneal
+  temperature = init_temp;
+  while temperature > final_temp
+    [engine, loglik, logpost] = EM_step(engine, evidence, temperature);
+    if verbose
+      fprintf('EM iteration %d, loglik = %8.4f, logpost = %8.4f, temp=%8.4f\n', ...
+	      num_iter, loglik, logpost, temperature);
+    end
+    num_iter = num_iter + 1;
+    LL = [LL loglik];
+    temperature = temperature * anneal_rate;
+  end
+  temperature = 0;
+  previous_loglik = loglik;
+  previous_logpost = logpost;
+else
+  temperature = 0;
+  previous_loglik = -inf;
+  previous_logpost = -inf;
+end
+
+converged = 0;
+while ~converged & (num_iter <= max_iter)
+  [engine, loglik, logpost] = EM_step(engine, evidence, temperature);
+  if verbose
+    %fprintf('EM iteration %d, loglik = %8.4f, logpost = %8.4f\n', ...
+    %	    num_iter, loglik, logpost);
+    fprintf('EM iteration %d, loglik = %8.4f\n', num_iter, loglik);
+  end
+  num_iter = num_iter + 1;
+  [converged, decreased] = em_converged(loglik, previous_loglik, thresh);
+  %[converged, decreased] = em_converged(logpost, previous_logpost, thresh);
+  previous_loglik = loglik;
+  previous_logpost = logpost;
+  LL = [LL loglik];
+end
+
+bnet = bnet_from_engine(engine);
+
+%%%%%%%%%
+
+function [engine, loglik, logpost] = EM_step(engine, cases, temp)
+
+bnet = bnet_from_engine(engine); % engine contains the old params that are used for the E step
+ss = length(bnet.intra);
+CPDs = bnet.CPD; % these are the new params that get maximized
+num_CPDs = length(CPDs);
+
+% log P(theta|D) = (log P(D|theta) + log P(theta)) - log(P(D))
+% where log P(D|theta) = sum_cases log P(case|theta)
+% and log P(theta) = sum_CPDs log P(CPD) - only count once even if tied!
+% logpost = log P(theta,D) (un-normalized)
+% This should be negative, and increase at every step.
+
+adjustable = zeros(1,num_CPDs);
+logprior = zeros(1, num_CPDs);
+for e=1:num_CPDs
+  adjustable(e) = adjustable_CPD(CPDs{e});
+end
+adj = find(adjustable);
+
+for e=adj(:)'
+  logprior(e) = log_prior(CPDs{e});
+  CPDs{e} = reset_ess(CPDs{e});
+end
+
+loglik = 0;
+for l=1:length(cases)
+  evidence = cases{l};
+  if ~iscell(evidence)
+    error('training data must be a cell array of cell arrays')
+  end
+  [engine, ll] = enter_evidence(engine, evidence);
+  assert(~isnan(ll))
+  loglik = loglik + ll;
+  T = size(evidence, 2);
+  
+  % We unroll ns etc because in update_ess, we refer to nodes by their unrolled number
+  % so that they extract evidence from the right place.
+  % (The CPD should really store its own version of ns and cnodes...)
+  ns = repmat(bnet.node_sizes_slice(:), [1 T]);
+  cnodes = unroll_set(bnet.cnodes_slice, ss, T);
+ 
+  %hidden_bitv = repmat(bnet.hidden_bitv(1:ss), [1 T]);
+  hidden_bitv = zeros(ss, T);
+  hidden_bitv(isemptycell(evidence))=1;
+  % hidden_bitv(i) = 1 means node i is hidden.
+  % We pass this in, rather than using isemptycell(evidence(dom)), because
+  % isemptycell is very slow.
+  
+  t = 1;
+  for i=1:ss
+    e = bnet.equiv_class(i,1);
+    if adjustable(e)
+      fmarg = marginal_family(engine, i, t);
+      CPDs{e} = update_ess(CPDs{e}, fmarg, evidence, ns(:), cnodes(:), hidden_bitv(:)); 
+    end
+  end
+  
+  for i=1:ss   
+    e = bnet.equiv_class(i,2);
+    if adjustable(e)
+      for t=2:T
+	fmarg = marginal_family(engine, i, t);
+	CPDs{e} = update_ess(CPDs{e}, fmarg, evidence, ns(:), cnodes(:), hidden_bitv(:));
+      end
+    end
+  end
+end
+
+logpost = loglik + sum(logprior(:));
+
+for e=adj(:)'
+  CPDs{e} = maximize_params(CPDs{e}, temp);
+end
+
+engine = update_engine(engine, CPDs);
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/learn_params_em.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,88 @@
+function [bnet, LL, engine] = learn_params_em(engine, evidence, max_iter, thresh)
+% LEARN_PARAMS_EM Set the parameters of each adjustable node to their ML/MAP values using batch EM.
+% [bnet, LLtrace, engine] = learn_params_em(engine, data, max_iter, thresh)
+%
+% data{i,l} is the value of node i in case l, or [] if hidden.
+%   Suppose you have L training cases in an O*L array, D, where O is the num observed
+%   scalar nodes, and N is the total num nodes.
+%   Then you can create 'data' as follows, where onodes is the index of the observable nodes:
+%      data = cell(N, L);
+%      data(onodes,:) = num2cell(D);
+%   Of course it is possible for different sets of nodes to be observed in each case.
+%
+% We return the modified bnet and engine.
+% To see the learned parameters for node i, use the construct
+%   s = struct(bnet.CPD{i}); % violate object privacy
+% LLtrace is the learning curve: the vector of log-likelihood scores at each iteration.
+%
+% max_iter specifies the maximum number of iterations. Default: 10.
+%
+% thresh specifies the thresold for stopping EM. Default: 1e-3.
+% We stop when |f(t) - f(t-1)| / avg < threshold,
+% where avg = (|f(t)| + |f(t-1)|)/2 and f is log lik.  
+
+if nargin < 3, max_iter = 10; end
+if nargin < 4, thresh = 1e-3; end
+
+verbose = 1;
+
+loglik = 0;
+previous_loglik = -inf;
+converged = 0;
+num_iter = 1;
+LL = [];
+
+while ~converged & (num_iter <= max_iter)
+  [engine, loglik] = EM_step(engine, evidence);
+  if verbose, fprintf('EM iteration %d, ll = %8.4f\n', num_iter, loglik); end
+  num_iter = num_iter + 1;
+  converged = em_converged(loglik, previous_loglik, thresh);
+  previous_loglik = loglik;
+  LL = [LL loglik];
+end
+if verbose, fprintf('\n'); end
+
+bnet = bnet_from_engine(engine);
+
+%%%%%%%%%
+
+function [engine, loglik] = EM_step(engine, cases)
+
+bnet = bnet_from_engine(engine); % engine contains the old params that are used for the E step
+CPDs = bnet.CPD; % these are the new params that get maximized
+num_CPDs = length(CPDs);
+adjustable = zeros(1,num_CPDs);
+for e=1:num_CPDs
+  adjustable(e) = adjustable_CPD(CPDs{e});
+end
+adj = find(adjustable);
+n = length(bnet.dag);
+
+for e=adj(:)'
+  CPDs{e} = reset_ess(CPDs{e});
+end
+
+loglik = 0;
+ncases = size(cases, 2);
+for l=1:ncases
+  evidence = cases(:,l);
+  [engine, ll] = enter_evidence(engine, evidence);
+  loglik = loglik + ll;
+  hidden_bitv = zeros(1,n);
+  hidden_bitv(isemptycell(evidence))=1;
+  for i=1:n
+    e = bnet.equiv_class(i);
+    if adjustable(e)
+      fmarg = marginal_family(engine, i);
+      CPDs{e} = update_ess(CPDs{e}, fmarg, evidence, bnet.node_sizes, bnet.cnodes, hidden_bitv);
+    end
+  end
+end
+
+for e=adj(:)'
+  CPDs{e} = maximize_params(CPDs{e});
+end
+
+engine = update_engine(engine, CPDs);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/learn_params_em2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,91 @@
+function [bnet, LL, engine] = learn_params_em(engine, evidence, max_iter, thresh)
+% LEARN_PARAMS_EM Set the parameters of each adjustable node to their ML/MAP values using batch EM.
+% [bnet, LLtrace, engine] = learn_params_em(engine, data, max_iter, thresh)
+%
+% data{i,l} is the value of node i in case l, or [] if hidden.
+%   Suppose you have L training cases in an O*L array, D, where O is the num observed
+%   scalar nodes, and N is the total num nodes.
+%   Then you can create 'data' as follows, where onodes is the index of the observable nodes:
+%      data = cell(N, L);
+%      data(onodes,:) = num2cell(D);
+%   Of course it is possible for different sets of nodes to be observed in each case.
+%
+% We return the modified bnet and engine.
+% To see the learned parameters for node i, use the construct
+%   s = struct(bnet.CPD{i}); % violate object privacy
+% LLtrace is the learning curve: the vector of log-likelihood scores at each iteration.
+%
+% max_iter specifies the maximum number of iterations. Default: 10.
+%
+% thresh specifies the thresold for stopping EM. Default: 1e-3.
+% We stop when |f(t) - f(t-1)| / avg < threshold,
+% where avg = (|f(t)| + |f(t-1)|)/2 and f is log lik.  
+
+if nargin < 3, max_iter = 10; end
+if nargin < 4, thresh = 1e-3; end
+
+verbose = 0;
+
+loglik = 0;
+previous_loglik = -inf;
+converged = 0;
+num_iter = 1;
+LL = [];
+
+while ~converged & (num_iter <= max_iter)
+  [engine, loglik] = EM_step(engine, evidence);
+  if verbose, fprintf('EM iteration %d, ll = %8.4f\n', num_iter, loglik); end
+  num_iter = num_iter + 1;
+  converged = em_converged(loglik, previous_loglik, thresh);
+  previous_loglik = loglik;
+  LL = [LL loglik];
+end
+if verbose, fprintf('\n'); end
+
+bnet = bnet_from_engine(engine);
+
+%%%%%%%%%
+
+function [engine, loglik] = EM_step(engine, cases)
+
+bnet = bnet_from_engine(engine); % engine contains the old params that are used for the E step
+CPDs = bnet.CPD; % these are the new params that get maximized
+num_CPDs = length(CPDs);
+adjustable = zeros(1,num_CPDs);
+for e=1:num_CPDs
+  adjustable(e) = adjustable_CPD(CPDs{e});
+end
+adj = find(adjustable);
+n = length(bnet.dag);
+
+for e=adj(:)'
+  CPDs{e} = reset_ess(CPDs{e});
+end
+
+loglik = 0;
+ncases = size(cases, 2);
+for l=1:ncases
+  evidence = cases(:,l);
+  [engine, ll] = enter_evidence(engine, evidence);
+  loglik = loglik + ll;
+  hidden_bitv = zeros(1,n);
+  hidden_bitv(isemptycell(evidence))=1;
+  for i=1:n
+    e = bnet.equiv_class(i);
+    if adjustable(e)
+      fmarg = marginal_family(engine, i);
+      CPDs{e} = update_ess(CPDs{e}, fmarg, evidence, bnet.node_sizes, bnet.cnodes, hidden_bitv);
+    end
+  end
+end
+
+for e=adj(:)'
+  CPDs{e} = maximize_params(CPDs{e});
+end
+one_mean = get_field(CPDs{1},'mean');
+one_cov = get_field(CPDs{1},'cov');
+CPDs{1} = gaussian_CPD(bnet,1,'mean',max(one_mean,0),'cov',one_cov,'cov_type', 'diag', ...
+        'clamp_cov',1);
+engine = update_engine(engine, CPDs);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/learn_struct_K2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,104 @@
+function dag = learn_struct_K2(data, ns, order, varargin)
+% LEARN_STRUCT_K2 Greedily learn the best structure compatible with a fixed node ordering
+% best_dag = learn_struct_K2(data, node_sizes, order, ...)
+%
+% data(i,m) = value of node i in case m (can be a cell array).
+% node_sizes(i) is the size of node i.
+% order(i) is the i'th node in the topological ordering.
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% max_fan_in - this the largest number of parents we allow per node [N]
+% scoring_fn - 'bayesian' or 'bic' [ 'bayesian' ]
+%              Currently, only networks with all tabular nodes support Bayesian scoring.
+% type       - type{i} is the type of CPD to use for node i, where the type is a string
+%              of the form 'tabular', 'noisy_or', 'gaussian', etc. [ all cells contain 'tabular' ]
+% params     - params{i} contains optional arguments passed to the CPD constructor for node i,
+%              or [] if none.  [ all cells contain {'prior', 1}, meaning use uniform Dirichlet priors ]
+% discrete   - the list of discrete nodes [ 1:N ]
+% clamped    - clamped(i,m) = 1 if node i is clamped in case m [ zeros(N, ncases) ]
+% verbose    - 'yes' means display output while running [ 'no' ]
+%
+% e.g., dag = learn_struct_K2(data, ns, order, 'scoring_fn', 'bic', 'params', [])
+%
+% To be backwards compatible with BNT2, you can also specify arguments as follows
+%   dag = learn_struct_K2(data, node_sizes, order, max_fan_in)    
+%
+% This algorithm is described in
+% - Cooper and Herskovits,  "A Bayesian method for the induction of probabilistic
+%      networks from data", Machine Learning Journal 9:308--347, 1992
+
+[n ncases] = size(data);
+
+% set default params
+type = cell(1,n);
+params = cell(1,n);
+for i=1:n
+  type{i} = 'tabular';
+  %params{i} = { 'prior', 1 };
+  params{i} = { 'prior_type', 'dirichlet', 'dirichlet_weight', 1 };
+end
+scoring_fn = 'bayesian';
+discrete = 1:n;
+clamped = zeros(n, ncases);
+
+max_fan_in = n;
+verbose = 0;
+
+args = varargin;
+nargs = length(args);
+if length(args) > 0 
+  if isstr(args{1})
+    for i=1:2:nargs
+      switch args{i},
+       case 'verbose',    verbose = strcmp(args{i+1}, 'yes');
+       case 'max_fan_in', max_fan_in = args{i+1}; 
+       case 'scoring_fn', scoring_fn = args{i+1};
+       case 'type',       type = args{i+1}; 
+       case 'discrete',   discrete = args{i+1}; 
+       case 'clamped',    clamped = args{i+1}; 
+       case 'params',     if isempty(args{i+1}), params = cell(1,n); else params = args{i+1};  end
+      end
+    end
+  else
+    max_fan_in = args{1};
+  end
+end
+
+dag = zeros(n,n);
+
+for i=1:n
+  ps = [];
+  j = order(i);
+  u = find(clamped(j,:)==0);    
+  score = score_family(j, ps, type{j}, scoring_fn, ns, discrete, data(:,u), params{j});
+  if verbose, fprintf('\nnode %d, empty score %6.4f\n', j, score); end
+  done = 0;
+  while ~done & (length(ps) <= max_fan_in)
+    pps = mysetdiff(order(1:i-1), ps); % potential parents
+    nps = length(pps);
+    pscore = zeros(1, nps);
+    for pi=1:nps
+      p = pps(pi);
+      pscore(pi) = score_family(j, [ps p], type{j}, scoring_fn, ns, discrete, data(:,u), params{j});
+      if verbose, fprintf('considering adding %d to %d, score %6.4f\n', p, j, pscore(pi)); end
+    end
+    [best_pscore, best_p] = max(pscore);
+    best_p = pps(best_p);
+    if best_pscore > score
+      score = best_pscore;
+      ps = [ps best_p];
+      if verbose, fprintf('* adding %d to %d, score %6.4f\n', best_p, j, best_pscore); end
+    else
+      done = 1;
+    end
+  end
+  if ~isempty(ps) % need this check for matlab 5.2
+    dag(ps, j) = 1;
+  end
+end
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/learn_struct_dbn_reveal.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,101 @@
+function inter = learn_struct_dbn_reveal(seqs, ns, max_fan_in, penalty)
+% LEARN_STRUCT_DBN_REVEAL Learn inter-slice adjacency matrix given fully observable discrete time series
+% inter = learn_struct_dbn_reveal(seqs, node_sizes, max_fan_in, penalty)
+% 
+% seqs{l}{i,t} = value of node i in slice t of time-series l.
+%   If you have a single time series in an N*T array D, use
+%      seqs = { num2cell(D) }.
+%   If you have L time series, each of length T, in an N*T*L array D, use
+%      seqs= cell(1,L); for l=1:L, seqs{l} = num2cell(D(:,:,l)); end
+%   or, in vectorized form,
+%      seqs = squeeze(num2cell(num2cell(D),[1 2]));
+% Currently the data is assumed to be discrete (1,2,...)
+%
+% node_sizes(i) is the number of possible values for node i
+% max_fan_in is the largest number of parents we allow per node (default: N)
+% penalty is weight given to the complexity penalty (default: 0.5)
+%  A penalty of 0.5 gives the BIC score.
+%  A penalty of 0 gives the ML score.
+%  Maximizing likelihood is equivalent to maximizing mutual information between parents and child.
+%
+% inter(i,j) = 1 iff node in slice t connects to node j in slice t+1
+%
+% The parent set for each node in slice 2 is computed by evaluating all subsets of nodes in slice 1,
+% and picking the largest scoring one. This takes O(n^k) time per node, where n is the num. nodes
+% per slice, and k <= n is the max fan in.
+% Since all the nodes are observed, we do not need to use an inference engine.
+% And since we are only learning the inter-slice matrix, we do not need to check for cycles.
+%
+% This algorithm is described in
+% - "REVEAL: A general reverse engineering algorithm for inference of genetic network
+%      architectures", Liang et al. PSB 1998
+% - "Extended dependency analysis of large systems",
+%       Roger Conant, Intl. J. General Systems, 1988, vol 14, pp 97-141
+% - "Learning the structure of DBNs", Friedman, Murphy and Russell, UAI 1998.
+
+n = length(ns);
+
+if nargin < 3, max_fan_in = n; end
+if nargin < 4, penalty = 0.5; end
+
+inter = zeros(n,n);
+
+if ~iscell(seqs)
+  data{1} = seqs;
+end
+
+nseq = length(seqs);
+nslices = 0;
+data = cell(1, nseq);
+for l=1:nseq
+  nslices = nslices + size(seqs{l}, 2);
+  data{l} = cell2num(seqs{l})'; % each row is a case
+end
+ndata = nslices - nseq; % subtract off the initial slice of each sequence
+
+% We concatenate the sequences as in the following example.
+% Let there be 2 sequences of lengths 4 and 5, with n nodes per slice,
+% and let i be the target node.
+% Then we construct following matrix D 
+%
+% s{1}{1,1} ... s{1}{1,3}     s{2}{1,1} ... s{2}{1,4}
+% ....
+% s{1}{n,1} ... s{1}{n,3}     s{2}{n,1} ... s{2}{n,4}
+% s{1}{i,2} ... s{1}{i,4}     s{2}{i,2} ... s{2}{i,5}
+%
+% D(1:n, i) is the i'th input and D(n+1, i) is the i'th output.
+% 
+% We concatenate each sequence separately to avoid treating the transition
+% from the end of one sequence to the beginning of another as a "normal" transition.
+
+
+for i=1:n
+  D = [];
+  for l=1:nseq
+    T = size(seqs{l}, 2);
+    A = cell2num(seqs{l}(:, 1:T-1));
+    B = cell2num(seqs{l}(i, 2:T));
+    C = [A;B];
+    D = [D C];
+  end
+  SS = subsets(1:n, max_fan_in, 1); % skip the empty set 
+  nSS = length(SS);
+  bic_score = zeros(1, nSS);
+  ll_score = zeros(1, nSS);
+  target = n+1;
+  ns2 = [ns ns(i)];
+  for h=1:nSS
+    ps = SS{h};
+    dom = [ps target];
+    counts = compute_counts(D(dom, :), ns2(dom));
+    CPT = mk_stochastic(counts);
+    [bic_score(h), ll_score(h)] = bic_score_family(counts, CPT, ndata);
+  end
+  if penalty == 0
+    h = argmax(ll_score);
+  else
+    h = argmax(bic_score);
+  end
+  ps = SS{h};
+  inter(ps, i) = 1;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/learn_struct_mcmc.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,284 @@
+function [sampled_graphs, accept_ratio, num_edges] = learn_struct_mcmc(data, ns, varargin)
+% MY_LEARN_STRUCT_MCMC  Monte Carlo Markov Chain search over DAGs assuming fully observed data
+% [sampled_graphs, accept_ratio, num_edges] = learn_struct_mcmc(data, ns, ...)
+% 
+% data(i,m) is the value of node i in case m.
+% ns(i) is the number of discrete values node i can take on.
+%
+% sampled_graphs{m} is the m'th sampled graph.
+% accept_ratio(t) = acceptance ratio at iteration t
+% num_edges(t) = number of edges in model at iteration t
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% scoring_fn - 'bayesian' or 'bic' [ 'bayesian' ]
+%              Currently, only networks with all tabular nodes support Bayesian scoring.
+% type       - type{i} is the type of CPD to use for node i, where the type is a string
+%              of the form 'tabular', 'noisy_or', 'gaussian', etc. [ all cells contain 'tabular' ]
+% params     - params{i} contains optional arguments passed to the CPD constructor for node i,
+%              or [] if none.  [ all cells contain {'prior', 1}, meaning use uniform Dirichlet priors ]
+% discrete   - the list of discrete nodes [ 1:N ]
+% clamped    - clamped(i,m) = 1 if node i is clamped in case m [ zeros(N, ncases) ]
+% nsamples   - number of samples to draw from the chain after burn-in [ 100*N ]
+% burnin     - number of steps to take before drawing samples [ 5*N ]
+% init_dag   - starting point for the search [ zeros(N,N) ]
+%
+% e.g., samples = my_learn_struct_mcmc(data, ns, 'nsamples', 1000);
+%
+% Modified by Sonia Leach (SML) 2/4/02, 9/5/03
+
+
+
+[n ncases] = size(data);
+
+
+% set default params
+type = cell(1,n);
+params = cell(1,n);
+for i=1:n
+ type{i} = 'tabular';
+ %params{i} = { 'prior', 1};
+ params{i} = { 'prior_type', 'dirichlet', 'dirichlet_weight', 1 };
+end
+scoring_fn = 'bayesian';
+discrete = 1:n;
+clamped = zeros(n, ncases);
+nsamples = 100*n;
+burnin = 5*n;
+dag = zeros(n);
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+ switch args{i},
+  case 'nsamples',   nsamples = args{i+1};
+  case 'burnin',     burnin = args{i+1};
+  case 'init_dag',   dag = args{i+1};
+  case 'scoring_fn', scoring_fn = args{i+1};
+  case 'type',       type = args{i+1}; 
+  case 'discrete',   discrete = args{i+1}; 
+  case 'clamped',    clamped = args{i+1}; 
+  case 'params',     if isempty(args{i+1}), params = cell(1,n); else params = args{i+1};  end
+ end
+end
+
+% We implement the fast acyclicity check described by P. Giudici and R. Castelo,
+% "Improving MCMC model search for data mining", submitted to J. Machine Learning, 2001.
+
+% SML: also keep descendant matrix C
+use_giudici = 1;
+if use_giudici
+ [nbrs, ops, nodes, A] = mk_nbrs_of_digraph(dag);
+else
+ [nbrs, ops, nodes] = mk_nbrs_of_dag(dag);
+ A = [];
+end
+
+num_accepts = 1;
+num_rejects = 1;
+T = burnin + nsamples;
+accept_ratio = zeros(1, T);
+num_edges = zeros(1, T);
+sampled_graphs = cell(1, nsamples);
+%sampled_bitv = zeros(nsamples, n^2);
+
+for t=1:T
+ [dag, nbrs, ops, nodes, A, accept] = take_step(dag, nbrs, ops, ...
+                    nodes, ns, data, clamped, A, ...
+                      scoring_fn, discrete, type, params);
+ num_edges(t) = sum(dag(:));
+ num_accepts = num_accepts + accept;
+ num_rejects = num_rejects + (1-accept);
+ accept_ratio(t) =  num_accepts/num_rejects;
+ if t > burnin
+   sampled_graphs{t-burnin} = dag;
+   %sampled_bitv(t-burnin, :) = dag(:)';
+ end
+end
+
+
+%%%%%%%%%
+
+
+function [new_dag, new_nbrs, new_ops, new_nodes, A,  accept] = ...
+   take_step(dag, nbrs, ops, nodes, ns, data, clamped, A,  ...
+     scoring_fn, discrete, type, params, prior_w)
+
+
+use_giudici = ~isempty(A);
+if use_giudici
+ [new_dag, op, i, j, new_A] =  pick_digraph_nbr(dag, nbrs, ops, nodes,A); % updates A
+ [new_nbrs, new_ops, new_nodes] =  mk_nbrs_of_digraph(new_dag, new_A);
+else
+ d = sample_discrete(normalise(ones(1, length(nbrs))));
+ new_dag = nbrs{d};
+ op = ops{d};
+ i = nodes(d, 1); j = nodes(d, 2);
+ [new_nbrs, new_ops, new_nodes] = mk_nbrs_of_dag(new_dag);
+end
+
+bf =  bayes_factor(dag, new_dag, op, i, j, ns, data, clamped, scoring_fn, discrete, type, params);
+
+%R = bf * (new_prior / prior) * (length(nbrs) / length(new_nbrs)); 
+R = bf * (length(nbrs) / length(new_nbrs)); 
+u = rand(1,1);
+if u > min(1,R) % reject the move
+ accept = 0;
+ new_dag = dag;
+ new_nbrs = nbrs;
+ new_ops = ops;
+ new_nodes = nodes;
+else
+ accept = 1;
+ if use_giudici
+A = new_A; % new_A already updated in pick_digraph_nbr
+ end
+end
+
+
+%%%%%%%%%
+
+function bfactor = bayes_factor(old_dag, new_dag, op, i, j, ns, data, clamped, scoring_fn, discrete, type, params)
+
+u = find(clamped(j,:)==0);
+LLnew = score_family(j, parents(new_dag, j), type{j}, scoring_fn, ns, discrete, data(:,u), params{j});
+LLold = score_family(j, parents(old_dag, j), type{j}, scoring_fn, ns, discrete, data(:,u), params{j});
+bf1 = exp(LLnew - LLold);
+
+if strcmp(op, 'rev')  % must also multiply in the changes to i's family
+ u = find(clamped(i,:)==0);
+ LLnew = score_family(i, parents(new_dag, i), type{i}, scoring_fn, ns, discrete, data(:,u), params{i});
+ LLold = score_family(i, parents(old_dag, i), type{i}, scoring_fn, ns, discrete, data(:,u), params{i});
+ bf2 = exp(LLnew - LLold);
+else
+ bf2 = 1;
+end
+bfactor = bf1 * bf2;
+
+
+%%%%%%%% Giudici stuff follows %%%%%%%%%%
+
+
+% SML: This now updates A as it goes from digraph it choses
+function [new_dag, op, i, j, new_A] = pick_digraph_nbr(dag, digraph_nbrs, ops, nodes, A)
+
+d = sample_discrete(normalise(ones(1, length(digraph_nbrs))));
+%d = myunidrnd(length(digraph_nbrs),1,1);
+i = nodes(d, 1); j = nodes(d, 2);
+new_dag = digraph_nbrs(:,:,d);
+op = ops{d};
+new_A = update_ancestor_matrix(A, op, i, j, new_dag); 
+
+
+%%%%%%%%%%%%%%
+
+
+function A = update_ancestor_matrix(A,  op, i, j, dag)
+
+switch op
+case 'add',
+ A = do_addition(A,  op, i, j, dag);
+case 'del', 
+ A = do_removal(A,  op, i, j, dag);
+case 'rev', 
+ A = do_removal(A,  op, i, j, dag);
+ A = do_addition(A,  op, j, i, dag);
+end
+
+ 
+%%%%%%%%%%%%
+
+function A = do_addition(A, op, i, j, dag)
+
+A(j,i) = 1; % i is an ancestor of j
+anci = find(A(i,:));
+if ~isempty(anci)
+ A(j,anci) = 1; % all of i's ancestors are added to Anc(j)
+end
+ancj = find(A(j,:));
+descj = find(A(:,j)); 
+if ~isempty(ancj)
+ for k=descj(:)'
+   A(k,ancj) = 1; % all of j's ancestors are added to each descendant of j
+ end
+end
+
+%%%%%%%%%%%
+function A = do_removal(A, op, i, j, dag)
+
+% find all the descendants of j, and put them in topological order
+
+% SML: originally Kevin had the next line commented and the %* lines
+% being used but I think this is equivalent and much less expensive
+% I assume he put it there for debugging and never changed it back...?
+descj = find(A(:,j));
+%*  R = reachability_graph(dag);
+%*  descj = find(R(j,:));
+
+order = topological_sort(dag);
+
+% SML: originally Kevin used the %* line but this was extracting the
+% wrong things to sort
+%* descj_topnum = order(descj);
+[junk, perm] = sort(order); %SML:node i is perm(i)-TH in order
+descj_topnum = perm(descj); %SML:descj(i) is descj_topnum(i)-th in order
+
+% SML: now re-sort descj by rank in descj_topnum
+[junk, perm] = sort(descj_topnum);
+descj = descj(perm);
+
+% Update j and all its descendants
+A = update_row(A, j, dag);
+for k = descj(:)'
+   A = update_row(A, k, dag);
+end
+
+%%%%%%%%%%%
+
+function A = old_do_removal(A, op, i, j, dag)
+
+% find all the descendants of j, and put them in topological order
+% SML: originally Kevin had the next line commented and the %* lines
+% being used but I think this is equivalent and much less expensive
+% I assume he put it there for debugging and never changed it back...?
+descj = find(A(:,j)); 
+%*  R = reachability_graph(dag);
+%*  descj = find(R(j,:)); 
+
+order = topological_sort(dag);
+descj_topnum = order(descj);
+[junk, perm] = sort(descj_topnum);
+descj = descj(perm);
+% Update j and all its descendants
+A = update_row(A, j, dag);
+for k = descj(:)'
+ A = update_row(A, k, dag);
+end
+
+%%%%%%%%%
+
+function A = update_row(A, j, dag)
+
+% We compute row j of A
+A(j, :) = 0;
+ps = parents(dag, j);
+if ~isempty(ps)
+ A(j, ps) = 1;
+end
+for k=ps(:)'
+ anck = find(A(k,:));
+ if ~isempty(anck)
+   A(j, anck) = 1;
+ end
+end
+ 
+%%%%%%%%
+
+function A = init_ancestor_matrix(dag)
+
+order = topological_sort(dag);
+A = zeros(length(dag));
+for j=order(:)'
+ A = update_row(A, j, dag);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/learn_struct_pdag_ic_star.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,155 @@
+function [pdag, G] = learn_struct_pdag_ic_star(cond_indep, n, k, varargin)
+% LEARN_STRUCT_PDAG_IC_STAR Learn a partially oriented DAG (pattern) with latent 
+% variables using the IC* algorithm
+% P = learn_struct_pdag_ic_star(cond_indep, n, k, ...)
+%
+% n is the number of nodes.
+% k is an optional upper bound on the fan-in (default: n)
+% cond_indep is a boolean function that will be called as follows:
+% feval(cond_indep, x, y, S, ...)
+% where x and y are nodes, and S is a set of nodes (positive integers),
+% and ... are any optional parameters passed to this function.
+%
+% The output P is an adjacency matrix, in which
+% P(i,j) = -1 if there is either a latent variable L such that i <-L-> j 
+% OR there is a directed edge from i->j.
+% P(i,j) = -2 if there is a marked directed i-*>j edge.
+% P(i,j) = P(j,i) = 1 if there is and undirected edge i--j
+% P(i,j) = P(j,i) = 2 if there is a latent variable L such that i<-L->j.
+%
+% The IC* algorithm learns a latent structure associated with a set of observed 
+% variables. 
+% The latent structure revealed is the projection in which every latent variable is
+% 1) a root node
+% 2) linked to exactly two observed variables.
+% Latent variables in the projection are represented using a bidirectional graph, 
+% and thus remain implicit.
+%
+% See Pearl, "Causality: Models, Reasoning, and Inference", 2000, p52 for more details.
+% Written by Tamar Kushnir, 2000
+
+sep = cell(n,n);
+ord = 0;
+done = 0;
+G = ones(n,n);
+G = setdiag(G,0);
+while ~done
+  done = 1;
+  [X,Y] = find(G); 
+  for i=1:length(X)
+    x = X(i); y = Y(i);
+    nbrs = mysetdiff(myunion(neighbors(G, x), neighbors(G,y)), [x y]);
+    if length(nbrs) >= ord & G(x,y) ~= 0
+      done = 0;
+      SS = subsets(nbrs, ord, ord); % all subsets of size ord
+      for si=1:length(SS)
+	S = SS{si};
+	if feval(cond_indep, x, y, S, varargin{:})  
+	  G(x,y) = 0;
+	  G(y,x) = 0;
+	  sep{x,y} = myunion(sep{x,y}, S);
+	  sep{y,x} = myunion(sep{y,x}, S);
+	  break; % no need to check any more subsets 
+	end
+      end
+    end
+  end
+  ord = ord + 1;
+end
+
+% Create the minimal pattern,
+% i.e., the only directed edges are V structures.
+pdag = G;
+[X, Y] = find(G);
+% We want to generate all unique triples x,y,z
+% where y is a common neighbor to x and z
+for i=1:length(X)
+  x = X(i);
+  y = Y(i);
+  Z = find(G(y,:));
+  Z = mysetdiff(Z, x);
+  for z=Z(:)'
+    if G(x,z)==0 & ~ismember(y, sep{x,z}) & ~ismember(y, sep{z,x})
+      pdag(x,y) = -1; pdag(y,x) = 0;
+      pdag(z,y) = -1; pdag(y,z) = 0;
+    end
+  end
+end
+
+% Convert the minimal pattern to a complete one using the following rules:
+% Rule 1:
+% if a and b are non-adjacent nodes with a common neighbor c,
+% if a->c and not b->c then c-*>b (marked arrow).
+% Rule 2:
+% if a and b are adjacent and there is a directed path (marked links) from a to b
+% then a->b (add arrowhead).
+%Pearl (2000)
+
+arrowin = [-1 -2 2];
+old_pdag = zeros(n);
+iter = 0;
+while ~isequal(pdag, old_pdag)
+  iter = iter + 1;
+  old_pdag = pdag;
+  % rule 1
+  [X, Y] = find(pdag);
+  for i=1:length(X)
+    x = X(i);
+    y = Y(i);
+    Z = find(pdag(y,:));
+    Z = mysetdiff(Z, x);
+    for z=Z(:)'
+      if G(x,z)==0 & ismember(pdag(x,y),arrowin) & ~ismember(pdag(z,y),arrowin)
+        pdag(y,z) = -2; pdag(z,y) = 0;
+      end
+    end
+  end
+  % rule 2
+  [X, Y] = find(G); 
+  %check all adjacent nodes because if pdag(x,y) = -1 
+  %and pdag(y,x) = 0 there could still be an bidirected edge between x & y.
+  for i=1:length(X)
+    x = X(i);
+    y = Y(i);
+    if ~ismember(pdag(x,y), arrowin) %x->y doesn't exist yet
+      %find marked path from x to y
+      add_arrow = marked_path(x,y,pdag);
+      if add_arrow 
+        if pdag(y,x)==-1 %bidirected edge
+          pdag(x,y) = 2; pdag(y,x) = 2;
+        else
+          pdag(x,y) = -1;pdag(y,x) = 0;
+        end
+      end
+    end
+  end
+end
+
+
+%%%%%%%%%%%%%
+
+function t = marked_path(x,y,L)
+% MARKED_PATH is a boolean function which returns 1 if a marked path 
+% between nodes x and y exists in the partially directed latent structure L.
+%
+% t = marked_path(x,y,L)
+%
+% x and y are the starting and ending nodes in the path, respectively.
+% L is a latent structure (partially directed graph with possible latent variables).
+%
+% Rule 2 of IC* algorithm (see Pearl, 2000)
+
+t=0;
+
+%find set of marked links from x
+marked = find(L(x,:)==-2);
+if ismember(y,marked)
+  t=1; %marked path found
+else
+  for m=marked(:)'
+    t = marked_path(m,y,L);
+    if t==1
+      break; %stop when marked path found
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/learn_struct_pdag_pc.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,129 @@
+function [pdag, G] = learn_struct_pdag_pc(cond_indep, n, k, varargin)
+% LEARN_STRUCT_PDAG_PC Learn a partially oriented DAG (pattern) using the PC algorithm
+% P = learn_struct_pdag_pc(cond_indep, n, k, ...)
+%
+% n is the number of nodes.
+% k is an optional upper bound on the fan-in (default: n)
+% cond_indep is a boolean function that will be called as follows:
+%   feval(cond_indep, x, y, S, ...)
+% where x and y are nodes, and S is a set of nodes (positive integers),
+% and ... are any optional parameters passed to this function.
+%
+% The output P is an adjacency matrix, in which
+% P(i,j) = -1 if there is an i->j edge.
+% P(i,j) = P(j,i) = 1 if there is an undirected edge i <-> j
+%
+% The PC algorithm does structure learning assuming all variables are observed.
+% See Spirtes, Glymour and Scheines, "Causation, Prediction and Search", 1993, p117.
+% This algorithm may take O(n^k) time if there are n variables and k is the max fan-in,
+% but this is quicker than the Verma-Pearl IC algorithm, which is always O(n^n).
+
+  
+sep = cell(n,n);
+ord = 0;
+done = 0;
+G = ones(n,n);
+G=setdiag(G,0);
+while ~done
+  done = 1;
+  [X,Y] = find(G); 
+  for i=1:length(X)
+    x = X(i); y = Y(i);
+    %nbrs = mysetdiff(myunion(neighbors(G, x), neighbors(G,y)), [x y]);
+    nbrs = mysetdiff(neighbors(G, y), x);  % bug fix by Raanan Yehezkel <raanany@ee.bgu.ac.il> 6/27/04
+    if length(nbrs) >= ord & G(x,y) ~= 0
+      done = 0;
+      %SS = subsets(nbrs, ord, ord); % all subsets of size ord
+      SS = subsets1(nbrs, ord);
+      for si=1:length(SS)
+	S = SS{si};
+	if feval(cond_indep, x, y, S, varargin{:})
+	  %if isempty(S)
+ 	  %  fprintf('%d indep of %d ', x, y);
+	  %else
+ 	  %  fprintf('%d indep of %d given ', x, y); fprintf('%d ', S);
+ 	  %end
+ 	  %fprintf('\n');
+	  
+	  % diagnostic
+	  %[CI, r] = cond_indep_fisher_z(x, y, S, varargin{:});
+	  %fprintf(': r = %6.4f\n', r);
+	  
+	  G(x,y) = 0;
+	  G(y,x) = 0;
+	  sep{x,y} = myunion(sep{x,y}, S);
+	  sep{y,x} = myunion(sep{y,x}, S);
+	  break; % no need to check any more subsets 
+	end
+      end
+    end 
+  end
+  ord = ord + 1;
+end
+
+
+% Create the minimal pattern,
+% i.e., the only directed edges are V structures.
+pdag = G;
+[X, Y] = find(G);
+% We want to generate all unique triples x,y,z
+% This code generates x,y,z and z,y,x.
+for i=1:length(X)
+  x = X(i);
+  y = Y(i);
+  Z = find(G(y,:));
+  Z = mysetdiff(Z, x);
+  for z=Z(:)'
+    if G(x,z)==0 & ~ismember(y, sep{x,z}) & ~ismember(y, sep{z,x})
+      %fprintf('%d -> %d <- %d\n', x, y, z);
+      pdag(x,y) = -1; pdag(y,x) = 0;
+      pdag(z,y) = -1; pdag(y,z) = 0;
+    end
+  end
+end
+
+% Convert the minimal pattern to a complete one,
+% i.e., every directed edge in P is compelled
+% (must be directed in all Markov equivalent models),
+% and every undirected edge in P is reversible.
+% We use the rules of Pearl (2000) p51 (derived in Meek (1995))
+
+old_pdag = zeros(n);
+iter = 0;
+while ~isequal(pdag, old_pdag)
+  iter = iter + 1;
+  old_pdag = pdag;
+  % rule 1
+  [A,B] = find(pdag==-1); % a -> b
+  for i=1:length(A)
+    a = A(i); b = B(i);
+    C = find(pdag(b,:)==1 & G(a,:)==0); % all nodes adj to b but not a
+    if ~isempty(C)
+      pdag(b,C) = -1; pdag(C,b) = 0;
+      %fprintf('rule 1: a=%d->b=%d and b=%d-c=%d implies %d->%d\n', a, b, b, C, b, C);
+    end
+  end
+  % rule 2
+  [A,B] = find(pdag==1); % unoriented a-b edge
+  for i=1:length(A)
+    a = A(i); b = B(i);
+    if any( (pdag(a,:)==-1) & (pdag(:,b)==-1)' );
+      pdag(a,b) = -1; pdag(b,a) = 0;
+      %fprintf('rule 2: %d -> %d\n', a, b);
+    end
+  end
+  % rule 3
+  [A,B] = find(pdag==1); % a-b
+  for i=1:length(A)
+    a = A(i); b = B(i);
+    C = find( (pdag(a,:)==1) & (pdag(:,b)==-1)' );
+    % C contains nodes c s.t. a-c->ba
+    G2 = setdiag(G(C, C), 1);
+    if any(G2(:)==0) % there are 2 different non adjacent elements of C
+      pdag(a,b) = -1; pdag(b,a) = 0;
+      %fprintf('rule 3: %d -> %d\n', a, b);
+    end
+  end
+end
+
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/learn_struct_pdag_pc_constrain.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,177 @@
+function [pdag, G] = dn_learn_struct_pdag_pc_constrain(adj, cond_indep, n, k, varargin)
+% LEARN_STRUCT_PDAG_PC Learn a partially oriented DAG (pattern) using the PC algorithm
+% Pdag = learn_struct_pdag_pc_constrain(adj, cond_indep, n, k, ...)
+%
+% adj = adjacency matrix learned from dependency network P(i,j) = 1 => i--j; 0 => i  j
+% n is the number of nodes.
+% k is an optional upper bound on the fan-in (default: n)
+% cond_indep is a boolean function that will be called as follows:
+%   feval(cond_indep, x, y, S, ...)
+% where x and y are nodes, and S is a set of nodes (positive integers),
+% and ... are any optional parameters passed to this function.
+%
+%Output
+% pdag  Partially directed graph
+% G     Resulting adjacency graph prior to setting direction arrows
+%
+% The output P is an adjacency matrix, in which
+% P(i,j) = -1 if there is an i->j edge.
+% P(i,j) = P(j,i) = 1 if there is an undirected edge i <-> j
+%
+% The PC algorithm does structure learning assuming all variables are observed.
+% See Spirtes, Glymour and Scheines, "Causation, Prediction and Search", 1993, p117.
+% This algorithm may take O(n^k) time if there are n variables and k is the max fan-in,
+% but this is quicker than the Verma-Pearl IC algorithm, which is always O(n^n).
+% 
+%%  Example
+%%  Given data in a comma separated, filename starting with the variable labels, then the data in rows.
+%%    filename test.txt consists of:
+%%
+%%      Earthquake,Burglar,Radio,Alarm,Call
+%%      1,2,2,2,1
+%%      1,1,2,1,2
+%%      . . .
+%[CovMatrix, obs, varfields] = CovMat('test.txt',5);
+%
+%dn = zeros(5,5); 
+%dn(1,2) = 1;   % This was the known Markov blanket of the system that generated test.txt
+%dn(2,1) = 1;
+%dn(2,4) = 1;
+%dn(4,2) = 1;
+%dn(1,3) = 1;
+%dn(3,1) = 1;
+%dn(1,4) = 1;
+%dn(4,1) = 1;
+%dn(4,5) = 1;
+%dn(5,4) = 1;
+%dn(3,5) = 1; %loop r->c
+%dn(5,3) = 1; %loop c-r
+%dn(3,4) = 1;
+%dn(4,3) = 1;
+%
+%max_fan_in = 4;
+%alpha = 0.05;
+%
+%[pdag G] = learn_struct_pdag_pc_constrain(dn,'cond_indep_fisher_z', 5, max_fan_in, CovMatrix, obs, alpha);
+%%
+%%
+%% Gary Bradski, 7/2002 Modified this to take an adjacency matrix from a dependency network.
+
+  
+sep = cell(n,n);
+ord = 0;
+done = 0;
+G = ones(n,n);
+G=setdiag(G,0);
+
+while ~done
+    done = 1;
+    [X,Y] = find(G);
+    for i=1:length(X)
+        x = X(i); y = Y(i);
+%        nbrs = mysetdiff(myunion(neighbors(G, x), neighbors(G,y)), [x y]);%parents, children, but not self
+        nbrs = mysetdiff(myunion(neighbors(adj, x), neighbors(adj,y)), [x y]);%parents, children, but not self
+
+        if length(nbrs) >= ord & G(x,y) ~= 0
+            done = 0;
+            SS = subsets(nbrs, ord, ord); % all subsets of size ord
+            for si=1:length(SS)
+                S = SS{si};
+                 %if (feval(dsep,x,y,S,adj)) | (feval(cond_indep, x, y, S, varargin{:}))
+                 if feval(cond_indep, x, y, S, varargin{:})
+                     %if isempty(S)
+                    %  fprintf('%d indep of %d ', x, y);
+                    %else
+                    %  fprintf('%d indep of %d given ', x, y); fprintf('%d ', S);
+                    %end
+                    %fprintf('\n');
+                    
+                    % diagnostic
+                    %[CI, r] = cond_indep_fisher_z(x, y, S, varargin{:});
+                    %fprintf(': r = %6.4f\n', r);
+                    
+                    G(x,y) = 0;
+                    G(y,x) = 0;
+                    adj(x,y) = 0;  %make sure found cond. independencies are marked out
+                    adj(y,x) = 0;
+                    sep{x,y} = myunion(sep{x,y}, S);
+                    sep{y,x} = myunion(sep{y,x}, S);
+                    break; % no need to check any more subsets 
+                end
+            end
+        end 
+    end
+    ord = ord + 1;
+end
+
+
+
+
+% Create the minimal pattern,
+% i.e., the only directed edges are V structures.
+
+pdag = G;
+[X, Y] = find(G);
+% We want to generate all unique triples x,y,z
+% This code generates x,y,z and z,y,x.
+for i=1:length(X)
+  x = X(i);
+  y = Y(i);
+  Z = find(G(y,:));
+  Z = mysetdiff(Z, x);
+  for z=Z(:)'
+    if G(x,z)==0 & ~ismember(y, sep{x,z}) & ~ismember(y, sep{z,x})
+      %fprintf('%d -> %d <- %d\n', x, y, z);
+      pdag(x,y) = -1; pdag(y,x) = 0;
+      pdag(z,y) = -1; pdag(y,z) = 0;
+    end
+  end
+end
+
+% Convert the minimal pattern to a complete one,
+% i.e., every directed edge in P is compelled
+% (must be directed in all Markov equivalent models),
+% and every undirected edge in P is reversible.
+% We use the rules of Pearl (2000) p51 (derived in Meek (1995))
+
+old_pdag = zeros(n);
+iter = 0;
+while ~isequal(pdag, old_pdag)
+  iter = iter + 1;
+  old_pdag = pdag;
+  % rule 1
+  [A,B] = find(pdag==-1); % a -> b
+  for i=1:length(A)
+    a = A(i); b = B(i);
+    C = find(pdag(b,:)==1 & G(a,:)==0); % all nodes adj to b but not a
+    if ~isempty(C)
+      pdag(b,C) = -1; pdag(C,b) = 0;
+      %fprintf('rule 1: a=%d->b=%d and b=%d-c=%d implies %d->%d\n', a, b, b, C, b, C);
+    end
+  end
+  % rule 2
+  [A,B] = find(pdag==1); % unoriented a-b edge
+  for i=1:length(A)
+    a = A(i); b = B(i);
+    if any( (pdag(a,:)==-1) & (pdag(:,b)==-1)' );
+      pdag(a,b) = -1; pdag(b,a) = 0;
+      %fprintf('rule 2: %d -> %d\n', a, b);
+    end
+  end
+  % rule 3
+  [A,B] = find(pdag==1); % a-b
+  for i=1:length(A)
+    a = A(i); b = B(i);
+    C = find( (G(a,:)==1) & (pdag(:,b)==-1)' );
+    % C contains nodes c s.t. a-c->ba
+    G2 = setdiag(G(C, C), 1);
+    if any(G2(:)==0) % there are 2 different non adjacent elements of C
+      pdag(a,b) = -1; pdag(b,a) = 0;
+      %fprintf('rule 3: %d -> %d\n', a, b);
+    end
+  end
+end
+
+
+  
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/mcmc_sample_to_hist.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+function mcmc_post = mcmc_sample_to_hist(sampled_graphs, dags)
+% MCMC_SAMPLE_TO_HIST Convert a set of sampled dags into a histogram over dags
+% hist = mcmc_sample_to_hist(sampled_graphs, dags)
+%
+% sampled_graphs{m} is the m'th sampled dag
+% dags{i} is the i'th dag in the hypothesis space
+% hist(i) = Pr(model i | data)
+
+ndags = length(dags);
+nsamples = length(sampled_graphs);
+nnodes = length(dags{1});
+% sampled_bitv(m, :) is the m'th sampled graph represented as a vector of n^2 bits, computed
+% by stacking the columns of the adjacency matrix vertically.
+sampled_bitvs = zeros(nsamples, nnodes*nnodes);
+for m=1:nsamples
+  sampled_bitvs(m, :) = sampled_graphs{m}(:)';
+end
+  
+[ugraphs, I, J] = unique(sampled_bitvs, 'rows');  % each row of ugraphs is a unique bit vector
+sampled_indices  = subv2ind(2*ones(1,nnodes*nnodes), ugraphs+1);
+counts = hist(J, 1:size(ugraphs,1)); % counts(i) = number of times graphs(i,:) occurs in the sample
+
+mcmc_post = zeros(1, ndags);
+for i=1:ndags
+  bitv = dags{i}(:)';
+  % Find the samples that corresponds to this graph by converting the graphs to bitvectors and
+  % then to integers.
+  ndx = subv2ind(2*ones(1,nnodes*nnodes), bitv+1);
+  locn = find(ndx == sampled_indices);
+  if ~isempty(locn)
+    mcmc_post(i) = counts(locn);
+  end
+end
+mcmc_post = normalise(mcmc_post);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/mk_schedule.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function schedule = mk_schedule(init_temp, final_temp, anneal_rate)
+
+init_temp = 10; final_temp = 1e-2; anneal_rate = 0.8;
+schedule = [];
+temp=init_temp;
+schedule = [schedule temp];
+while temp > final_temp
+  temp = temp * anneal_rate;
+  schedule = [schedule temp];
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/mk_tetrad_data_file.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function mk_tetrad_data_file(filename, samples, sig)
+% MK_TETRAD_DATA_FILE Make a file containing raw discrete data for input to TETRAD
+% mk_tetrad_data_file(filename, samples, sig)
+%
+% samples(i,j) is the value for case i, variable j
+% The resulting file can be used for the 'build' part of Tetrad.
+% For details on tetrad, see hss.cmu.edu/html/departments/philosophy/TETRAD/tetrad.html
+
+[nsamples N] = size(samples);
+
+fid = fopen(filename, 'w');
+fprintf(fid, '/Raw\n');
+fprintf(fid, '%d\n', nsamples);
+for i=1:N
+  fprintf(fid, 'x%d ', i);
+end
+fprintf(fid, '\n');
+for i=1:nsamples
+  fprintf(fid, '%d ', samples(i,:)-1); % tetrad counts from 0
+  fprintf(fid, '\n');
+end
+%fprintf(fid, '/Knowledge\n');
+%fprintf(fid, 'Significance %4.2f\n', sig);
+fclose(fid);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/score_dags.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,67 @@
+function score = score_dags(data, ns, dags, varargin)
+% SCORE_DAGS Compute the score of one or more DAGs
+% score = score_dags(data, ns, dags, varargin)
+%
+% data{i,m} = value of node i in case m (can be a cell array).
+% node_sizes(i) is the number of size of node i.
+% dags{g} is the g'th dag
+% score(g) is the score of the i'th dag
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% scoring_fn - 'bayesian' or 'bic' [ 'bayesian' ]
+%              Currently, only networks with all tabular nodes support Bayesian scoring.
+% type       - type{i} is the type of CPD to use for node i, where the type is a string
+%              of the form 'tabular', 'noisy_or', 'gaussian', etc. [ all cells contain 'tabular' ]
+% params     - params{i} contains optional arguments passed to the CPD constructor for node i,
+%              or [] if none.  [ all cells contain {'prior', 1}, meaning use uniform Dirichlet priors ]
+% discrete   - the list of discrete nodes [ 1:N ]
+% clamped    - clamped(i,m) = 1 if node i is clamped in case m [ zeros(N, ncases) ]
+%
+% e.g., score = score_dags(data, ns, mk_all_dags(n), 'scoring_fn', 'bic', 'params', []);
+%
+% If the DAGs have a lot of families in common, we can cache the sufficient statistics,
+% making this potentially more efficient than scoring the DAGs one at a time.
+% (Caching is not currently implemented, however.)
+
+[n ncases] = size(data);
+
+% set default params
+type = cell(1,n);
+params = cell(1,n);
+for i=1:n
+  type{i} = 'tabular';
+  params{i} = { 'prior_type', 'dirichlet', 'dirichlet_weight', 1 };
+end
+scoring_fn = 'bayesian';
+discrete = 1:n;
+
+u = [1:ncases]'; % DWH
+isclamped = 0; %DWH
+clamped = zeros(n, ncases);
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'scoring_fn', scoring_fn = args{i+1};
+   case 'type',       type = args{i+1}; 
+   case 'discrete',   discrete = args{i+1}; 
+   case 'clamped',    clamped = args{i+1}, isclamped = 1; %DWH
+   case 'params',     if isempty(args{i+1}), params = cell(1,n); else params = args{i+1};  end
+  end
+end
+
+NG = length(dags);
+score = zeros(1, NG);
+for g=1:NG
+  dag = dags{g};
+  for j=1:n
+    if isclamped %DWH
+        u = find(clamped(j,:)==0);    
+    end
+    ps = parents(dag, j);
+    score(g) = score(g) + score_family(j, ps, type{j}, scoring_fn, ns, discrete, data(:,u), params{j});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/score_dags_old.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,62 @@
+function score = score_dags(data, ns, dags, varargin)
+% SCORE_DAGS Compute the score of one or more DAGs
+% score = score_dags(data, ns, dags, varargin)
+%
+% data{i,m} = value of node i in case m (can be a cell array).
+% node_sizes(i) is the number of size of node i.
+% dags{g} is the g'th dag
+% score(g) is the score of the i'th dag
+%
+% The following optional arguments can be specified in the form of name/value pairs:
+% [default value in brackets]
+%
+% scoring_fn - 'bayesian' or 'bic' [ 'bayesian' ]
+%              Currently, only networks with all tabular nodes support Bayesian scoring.
+% type       - type{i} is the type of CPD to use for node i, where the type is a string
+%              of the form 'tabular', 'noisy_or', 'gaussian', etc. [ all cells contain 'tabular' ]
+% params     - params{i} contains optional arguments passed to the CPD constructor for node i,
+%              or [] if none.  [ all cells contain {'prior', 1}, meaning use uniform Dirichlet priors ]
+% discrete   - the list of discrete nodes [ 1:N ]
+% clamped    - clamped(i,m) = 1 if node i is clamped in case m [ zeros(N, ncases) ]
+%
+% e.g., score = score_dags(data, ns, mk_all_dags(n), 'scoring_fn', 'bic', 'params', []);
+%
+% If the DAGs have a lot of families in common, we can cache the sufficient statistics,
+% making this potentially more efficient than scoring the DAGs one at a time.
+% (Caching is not currently implemented, however.)
+
+[n ncases] = size(data);
+
+% set default params
+type = cell(1,n);
+params = cell(1,n);
+for i=1:n
+  type{i} = 'tabular';
+  params{i} = { 'prior_type', 'dirichlet', 'dirichlet_weight', 1 };
+end
+scoring_fn = 'bayesian';
+discrete = 1:n;
+clamped = zeros(n, ncases);
+
+args = varargin;
+nargs = length(args);
+for i=1:2:nargs
+  switch args{i},
+   case 'scoring_fn', scoring_fn = args{i+1};
+   case 'type',       type = args{i+1}; 
+   case 'discrete',   discrete = args{i+1}; 
+   case 'clamped',    clamped = args{i+1}; 
+   case 'params',     if isempty(args{i+1}), params = cell(1,n); else params = args{i+1};  end
+  end
+end
+
+NG = length(dags);
+score = zeros(1, NG);
+for g=1:NG
+  dag = dags{g};
+  for j=1:n
+    u = find(clamped(j,:)==0);    
+    ps = parents(dag, j);
+    score(g) = score(g) + score_family(j, ps, type{j}, scoring_fn, ns, discrete, data(:,u), params{j});
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/learning/score_family.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+function score = score_family(j, ps, node_type, scoring_fn, ns, discrete, data, args)
+% SCORE_FAMILY_COMPLETE Compute the score of a node and its parents given completely observed data
+% score = score_family(j, ps, node_type, scoring_fn, ns, discrete, data, args)
+%
+% data(i,m) is the value of node i in case m (can be a cell array)
+% args is a cell array containing optional arguments passed to the constructor,
+% or is [] if none
+%
+% We create a whole Bayes net which only connects parents to node,
+% where node has a CPD of the specified type (with default parameters).
+% We then evaluate its score ('bic' or 'bayesian')
+
+% We should use a cache to avoid unnecessary computation.
+% In particular, log_marginal_prob_node for tabular CPDs calls gammaln
+% and compute_counts, both of which are slow.
+
+[n ncases] = size(data);
+dag = zeros(n,n);
+% SML added to sort ps b/c mk_bnet, learn_params use sorted ps to make
+% CPTs
+% Kevin had: if ~isempty(ps), dag(ps, j) = 1; end
+if ~isempty(ps), dag(ps, j) = 1;, ps = sort(ps);, end
+
+bnet = mk_bnet(dag, ns, 'discrete', discrete);
+%bnet.CPD{j} = xxx_CPD(bnet, j);
+%eval(sprintf('bnet.CPD{j} = %s_CPD(bnet, j);', node_type));
+fname = sprintf('%s_CPD', node_type);
+%fprintf('score CPD %d\n', j);
+if isempty(args)
+  bnet.CPD{j} = feval(fname, bnet, j);
+else
+  bnet.CPD{j} = feval(fname, bnet, j, args{:});
+end
+switch scoring_fn
+ case 'bic',
+  fam = [ps j];
+  %score = BIC_score_CPD(bnet.CPD{j}, fam, data, ns, bnet.cnodes);
+  %bnet.CPD{j} = learn_params(bnet.CPD{j}, fam, data, ns, bnet.cnodes);
+  
+  % SML 03/16/04 had to special case gaussian b/c generic_CPD/learn_params
+  % no longer supported because of simple interface to learn_params
+  % introduced by KPM for tabular nodes below:
+  % KPM 9 June 04 - tabular nodes have changed back!
+  if 1 % (isempty(find(j==discrete)))
+     bnet.CPD{j} = learn_params(bnet.CPD{j},  fam, data, ns, bnet.cnodes);
+  else 
+  	bnet.CPD{j} = learn_params(bnet.CPD{j}, data(fam, :));
+  end
+  L = log_prob_node(bnet.CPD{j}, data(j,:), data(ps,:));
+  S = struct(bnet.CPD{j}); % violate object privacy
+  score = L - 0.5*S.nparams*log(ncases);
+ case 'bayesian', 
+  %score = bayesian_score_CPD(bnet.CPD{j}, data(fam, :));
+  score = log_marg_prob_node(bnet.CPD{j}, data(j,:), data(ps,:));
+ otherwise,
+  error(['unrecognized scoring fn ' scoring_fn]);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/license.gpl.txt	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,450 @@
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License version 2 as published by the Free Software Foundation.
+
+This library 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. 
+
+GNU Library General Public License
+
+----------------------------------------------------------------------------
+
+Table of Contents
+
+   * GNU LIBRARY GENERAL PUBLIC LICENSE
+        o Preamble
+        o TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+----------------------------------------------------------------------------
+
+GNU LIBRARY GENERAL PUBLIC LICENSE
+
+Version 2, June 1991
+
+Copyright (C) 1991 Free Software Foundation, Inc.
+675 Mass Ave, Cambridge, MA 02139, USA
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+[This is the first released version of the library GPL.  It is
+ numbered 2 because it goes with version 2 of the ordinary GPL.]
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are
+intended to guarantee your freedom to share and change free software--to
+make sure the software is free for all its users.
+
+This license, the Library General Public License, applies to some specially
+designated Free Software Foundation software, and to any other libraries
+whose authors decide to use it. You can use it for your libraries, too.
+
+When we speak of free software, we are referring to freedom, not price. Our
+General Public Licenses are designed to make sure that you have the freedom
+to distribute copies of free software (and charge for this service if you
+wish), that you receive source code or can get it if you want it, that you
+can change the software or use pieces of it in new free programs; and that
+you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to
+deny you these rights or to ask you to surrender the rights. These
+restrictions translate to certain responsibilities for you if you distribute
+copies of the library, or if you modify it.
+
+For example, if you distribute copies of the library, whether gratis or for
+a fee, you must give the recipients all the rights that we gave you. You
+must make sure that they, too, receive or can get the source code. If you
+link a program with the library, you must provide complete object files to
+the recipients so that they can relink them with the library, after making
+changes to the library and recompiling it. And you must show them these
+terms so they know their rights.
+
+Our method of protecting your rights has two steps: (1) copyright the
+library, and (2) offer you this license which gives you legal permission to
+copy, distribute and/or modify the library.
+
+Also, for each distributor's protection, we want to make certain that
+everyone understands that there is no warranty for this free library. If the
+library is modified by someone else and passed on, we want its recipients to
+know that what they have is not the original version, so that any problems
+introduced by others will not reflect on the original authors' reputations.
+
+Finally, any free program is threatened constantly by software patents. We
+wish to avoid the danger that companies distributing free software will
+individually obtain patent licenses, thus in effect transforming the program
+into proprietary software. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+Most GNU software, including some libraries, is covered by the ordinary GNU
+General Public License, which was designed for utility programs. This
+license, the GNU Library General Public License, applies to certain
+designated libraries. This license is quite different from the ordinary one;
+be sure to read it in full, and don't assume that anything in it is the same
+as in the ordinary license.
+
+The reason we have a separate public license for some libraries is that they
+blur the distinction we usually make between modifying or adding to a
+program and simply using it. Linking a program with a library, without
+changing the library, is in some sense simply using the library, and is
+analogous to running a utility program or application program. However, in a
+textual and legal sense, the linked executable is a combined work, a
+derivative of the original library, and the ordinary General Public License
+treats it as such.
+
+Because of this blurred distinction, using the ordinary General Public
+License for libraries did not effectively promote software sharing, because
+most developers did not use the libraries. We concluded that weaker
+conditions might promote sharing better.
+
+However, unrestricted linking of non-free programs would deprive the users
+of those programs of all benefit from the free status of the libraries
+themselves. This Library General Public License is intended to permit
+developers of non-free programs to use free libraries, while preserving your
+freedom as a user of such programs to change the free libraries that are
+incorporated in them. (We have not seen how to achieve this as regards
+changes in header files, but we have achieved it as regards changes in the
+actual functions of the Library.) The hope is that this will lead to faster
+development of free libraries.
+
+The precise terms and conditions for copying, distribution and modification
+follow. Pay close attention to the difference between a "work based on the
+library" and a "work that uses the library". The former contains code
+derived from the library, while the latter only works together with the
+library.
+
+Note that it is possible for a library to be covered by the ordinary General
+Public License rather than by this special one.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License Agreement applies to any software library which contains a
+notice placed by the copyright holder or other authorized party saying it
+may be distributed under the terms of this Library General Public License
+(also called "this License"). Each licensee is addressed as "you".
+
+A "library" means a collection of software functions and/or data prepared so
+as to be conveniently linked with application programs (which use some of
+those functions and data) to form executables.
+
+The "Library", below, refers to any such software library or work which has
+been distributed under these terms. A "work based on the Library" means
+either the Library or any derivative work under copyright law: that is to
+say, a work containing the Library or a portion of it, either verbatim or
+with modifications and/or translated straightforwardly into another
+language. (Hereinafter, translation is included without limitation in the
+term "modification".)
+
+"Source code" for a work means the preferred form of the work for making
+modifications to it. For a library, complete source code means all the
+source code for all modules it contains, plus any associated interface
+definition files, plus the scripts used to control compilation and
+installation of the library.
+
+Activities other than copying, distribution and modification are not covered
+by this License; they are outside its scope. The act of running a program
+using the Library is not restricted, and output from such a program is
+covered only if its contents constitute a work based on the Library
+(independent of the use of the Library in a tool for writing it). Whether
+that is true depends on what the Library does and what the program that uses
+the Library does.
+
+1. You may copy and distribute verbatim copies of the Library's complete
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the notices
+that refer to this License and to the absence of any warranty; and
+distribute a copy of this License along with the Library.
+
+You may charge a fee for the physical act of transferring a copy, and you
+may at your option offer warranty protection in exchange for a fee.
+
+2. You may modify your copy or copies of the Library or any portion of it,
+thus forming a work based on the Library, and copy and distribute such
+modifications or work under the terms of Section 1 above, provided that you
+also meet all of these conditions:
+
+        o a) The modified work must itself be a software library.
+
+        o b) You must cause the files modified to carry prominent notices
+          stating that you changed the files and the date of any change.
+
+        o c) You must cause the whole of the work to be licensed at no
+          charge to all third parties under the terms of this License.
+
+        o d) If a facility in the modified Library refers to a function or a
+          table of data to be supplied by an application program that uses
+          the facility, other than as an argument passed when the facility
+          is invoked, then you must make a good faith effort to ensure that,
+          in the event an application does not supply such function or
+          table, the facility still operates, and performs whatever part of
+          its purpose remains meaningful.
+
+          (For example, a function in a library to compute square roots has
+          a purpose that is entirely well-defined independent of the
+          application. Therefore, Subsection 2d requires that any
+          application-supplied function or table used by this function must
+          be optional: if the application does not supply it, the square
+          root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If identifiable
+sections of that work are not derived from the Library, and can be
+reasonably considered independent and separate works in themselves, then
+this License, and its terms, do not apply to those sections when you
+distribute them as separate works. But when you distribute the same sections
+as part of a whole which is a work based on the Library, the distribution of
+the whole must be on the terms of this License, whose permissions for other
+licensees extend to the entire whole, and thus to each and every part
+regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your
+rights to work written entirely by you; rather, the intent is to exercise
+the right to control the distribution of derivative or collective works
+based on the Library.
+
+In addition, mere aggregation of another work not based on the Library with
+the Library (or with a work based on the Library) on a volume of a storage
+or distribution medium does not bring the other work under the scope of this
+License.
+
+3. You may opt to apply the terms of the ordinary GNU General Public License
+instead of this License to a given copy of the Library. To do this, you must
+alter all the notices that refer to this License, so that they refer to the
+ordinary GNU General Public License, version 2, instead of to this License.
+(If a newer version than version 2 of the ordinary GNU General Public
+License has appeared, then you can specify that version instead if you
+wish.) Do not make any other change in these notices.
+
+Once this change is made in a given copy, it is irreversible for that copy,
+so the ordinary GNU General Public License applies to all subsequent copies
+and derivative works made from that copy.
+
+This option is useful when you wish to copy part of the code of the Library
+into a program that is not a library.
+
+4. You may copy and distribute the Library (or a portion or derivative of
+it, under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you accompany it with the complete
+corresponding machine-readable source code, which must be distributed under
+the terms of Sections 1 and 2 above on a medium customarily used for
+software interchange.
+
+If distribution of object code is made by offering access to copy from a
+designated place, then offering equivalent access to copy the source code
+from the same place satisfies the requirement to distribute the source code,
+even though third parties are not compelled to copy the source along with
+the object code.
+
+5. A program that contains no derivative of any portion of the Library, but
+is designed to work with the Library by being compiled or linked with it, is
+called a "work that uses the Library". Such a work, in isolation, is not a
+derivative work of the Library, and therefore falls outside the scope of
+this License.
+
+However, linking a "work that uses the Library" with the Library creates an
+executable that is a derivative of the Library (because it contains portions
+of the Library), rather than a "work that uses the library". The executable
+is therefore covered by this License. Section 6 states terms for
+distribution of such executables.
+
+When a "work that uses the Library" uses material from a header file that is
+part of the Library, the object code for the work may be a derivative work
+of the Library even though the source code is not. Whether this is true is
+especially significant if the work can be linked without the Library, or if
+the work is itself a library. The threshold for this to be true is not
+precisely defined by law.
+
+If such an object file uses only numerical parameters, data structure
+layouts and accessors, and small macros and small inline functions (ten
+lines or less in length), then the use of the object file is unrestricted,
+regardless of whether it is legally a derivative work. (Executables
+containing this object code plus portions of the Library will still fall
+under Section 6.)
+
+Otherwise, if the work is a derivative of the Library, you may distribute
+the object code for the work under the terms of Section 6. Any executables
+containing that work also fall under Section 6, whether or not they are
+linked directly with the Library itself.
+
+6. As an exception to the Sections above, you may also compile or link a
+"work that uses the Library" with the Library to produce a work containing
+portions of the Library, and distribute that work under terms of your
+choice, provided that the terms permit modification of the work for the
+customer's own use and reverse engineering for debugging such modifications.
+
+You must give prominent notice with each copy of the work that the Library
+is used in it and that the Library and its use are covered by this License.
+You must supply a copy of this License. If the work during execution
+displays copyright notices, you must include the copyright notice for the
+Library among them, as well as a reference directing the user to the copy of
+this License. Also, you must do one of these things:
+
+        o a) Accompany the work with the complete corresponding
+          machine-readable source code for the Library including whatever
+          changes were used in the work (which must be distributed under
+          Sections 1 and 2 above); and, if the work is an executable linked
+          with the Library, with the complete machine-readable "work that
+          uses the Library", as object code and/or source code, so that the
+          user can modify the Library and then relink to produce a modified
+          executable containing the modified Library. (It is understood that
+          the user who changes the contents of definitions files in the
+          Library will not necessarily be able to recompile the application
+          to use the modified definitions.)
+
+        o b) Accompany the work with a written offer, valid for at least
+          three years, to give the same user the materials specified in
+          Subsection 6a, above, for a charge no more than the cost of
+          performing this distribution.
+
+        o c) If distribution of the work is made by offering access to copy
+          from a designated place, offer equivalent access to copy the above
+          specified materials from the same place.
+
+        o d) Verify that the user has already received a copy of these
+          materials or that you have already sent this user a copy.
+
+For an executable, the required form of the "work that uses the Library"
+must include any data and utility programs needed for reproducing the
+executable from it. However, as a special exception, the source code
+distributed need not include anything that is normally distributed (in
+either source or binary form) with the major components (compiler, kernel,
+and so on) of the operating system on which the executable runs, unless that
+component itself accompanies the executable.
+
+It may happen that this requirement contradicts the license restrictions of
+other proprietary libraries that do not normally accompany the operating
+system. Such a contradiction means you cannot use both them and the Library
+together in an executable that you distribute.
+
+7. You may place library facilities that are a work based on the Library
+side-by-side in a single library together with other library facilities not
+covered by this License, and distribute such a combined library, provided
+that the separate distribution of the work based on the Library and of the
+other library facilities is otherwise permitted, and provided that you do
+these two things:
+
+        o a) Accompany the combined library with a copy of the same work
+          based on the Library, uncombined with any other library
+          facilities. This must be distributed under the terms of the
+          Sections above.
+
+        o b) Give prominent notice with the combined library of the fact
+          that part of it is a work based on the Library, and explaining
+          where to find the accompanying uncombined form of the same work.
+
+8. You may not copy, modify, sublicense, link with, or distribute the
+Library except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense, link with, or distribute the Library
+is void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under this
+License will not have their licenses terminated so long as such parties
+remain in full compliance.
+
+9. You are not required to accept this License, since you have not signed
+it. However, nothing else grants you permission to modify or distribute the
+Library or its derivative works. These actions are prohibited by law if you
+do not accept this License. Therefore, by modifying or distributing the
+Library (or any work based on the Library), you indicate your acceptance of
+this License to do so, and all its terms and conditions for copying,
+distributing or modifying the Library or works based on it.
+
+10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the original
+licensor to copy, distribute, link with or modify the Library subject to
+these terms and conditions. You may not impose any further restrictions on
+the recipients' exercise of the rights granted herein. You are not
+responsible for enforcing compliance by third parties to this License.
+
+11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot distribute so
+as to satisfy simultaneously your obligations under this License and any
+other pertinent obligations, then as a consequence you may not distribute
+the Library at all. For example, if a patent license would not permit
+royalty-free redistribution of the Library by all those who receive copies
+directly or indirectly through you, then the only way you could satisfy both
+it and this License would be to refrain entirely from distribution of the
+Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents
+or other property right claims or to contest validity of any such claims;
+this section has the sole purpose of protecting the integrity of the free
+software distribution system which is implemented by public license
+practices. Many people have made generous contributions to the wide range of
+software distributed through that system in reliance on consistent
+application of that system; it is up to the author/donor to decide if he or
+she is willing to distribute software through any other system and a
+licensee cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a
+consequence of the rest of this License.
+
+12. If the distribution and/or use of the Library is restricted in certain
+countries either by patents or by copyrighted interfaces, the original
+copyright holder who places the Library under this License may add an
+explicit geographical distribution limitation excluding those countries, so
+that distribution is permitted only in or among countries not thus excluded.
+In such case, this License incorporates the limitation as if written in the
+body of this License.
+
+13. The Free Software Foundation may publish revised and/or new versions of
+the Library General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Library does not specify a license version
+number, you may choose any version ever published by the Free Software
+Foundation.
+
+14. If you wish to incorporate parts of the Library into other free programs
+whose distribution conditions are incompatible with these, write to the
+author to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals of
+preserving the free status of all derivatives of our free software and of
+promoting the sharing and reuse of software generally.
+
+NO WARRANTY
+
+15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
+THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO
+THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY
+PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO
+LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR
+THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER
+SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License version 2 as published by the Free Software Foundation.
+
+This library 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. 
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+/cg_can_to_mom.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/cg_mom_to_can.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/cgpot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/display.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/divide_by_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/domain_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/enter_cts_evidence_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/enter_discrete_evidence_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/marginalize_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/multiply_by_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/multiply_pots.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/normalize_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/pot_to_marginal.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/set_domain_pot.m/1.1.1.1/Wed Jul 30 13:38:24 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/potentials/@cgpot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+/normalize_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/set_domain_pot.m/1.1.1.1/Wed Jul 30 13:38:08 2003//
+/simple_marginalize_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/potentials/@cgpot/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/Old/normalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function [pot, loglik] = normalize_pot(pot)
+% NORMALIZE_POT Convert the CG potential Pr(X,E) into Pr(X|E) and return log Pr(E).
+% [pot, loglik] = normalize_pot(pot)
+
+% Marginalize down to [], so that the normalizing constant becomes Pr(E)
+temp = marginalize_pot(cg_can_to_mom(pot), []); 
+%loglik = temp.mom{1}.logp;
+[temp2, loglik] = normalize_pot(temp.mom{1});
+  
+% Adjust scale factor to reflect the fact that the pot now represents Pr(X | E) instead of Pr(X,E).
+
+scale = -loglik;
+if 1
+switch pot.subtype
+  case 'm'
+    for i=1:pot.dsize
+      pot.mom{i} = rescale_pot(pot.mom{i}, scale);
+    end
+  case 'c'
+    for i=1:pot.dsize
+      pot.can{i} = rescale_pot(pot.can{i}, scale);
+    end
+end        
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/Old/set_domain_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function pot = set_domain_pot(pot, domain)
+% SET_DOMAIN_POT Change the domain of a potential (cgpot)
+% pot = set_domain_pot(pot, domain)
+
+delta = domain(1) - pot.domain(1);
+assert(all(domain == pot.domain + delta));
+pot.domain = pot.domain + delta;
+pot.ddom = pot.ddom + delta;
+pot.cdom = pot.cdom + delta;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/Old/simple_marginalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,86 @@
+function smallpot = marginalize_pot(bigpot, keep)
+% MARGINALIZE_POT Marginalize a cgpot onto a smaller domain.
+% smallpot = marginalize_pot(bigpot, keep)
+
+sumover = mysetdiff(bigpot.domain, keep);
+csumover = myintersect(sumover, bigpot.cdom);
+dsumover = myintersect(sumover, bigpot.ddom);
+dkeep = myintersect(keep, bigpot.ddom);
+ckeep = myintersect(keep, bigpot.cdom);
+%ns = sparse(1, max(bigpot.domain)); % must be full, so I is an integer
+ns = zeros(1, max(bigpot.domain));
+ns(bigpot.ddom) = bigpot.dsizes;
+ns(bigpot.cdom) = bigpot.csizes;
+
+% sum(ns(csumover))==0 is like isempty(csumover) but handles observed nodes.
+% Similarly, prod(ns(dsumover))==1 is like isempty(dsumover)
+
+% Marginalize the cts parts.
+% If we are in canonical form, we stay that way, since moment form might not exist.
+% Besides, we would like to minimize the number of conversions.
+if sum(ns(csumover)) > 0
+  if bigpot.subtype == 'm'
+    for i=1:bigpot.dsize
+      bigpot.mom{i} = marginalize_pot(bigpot.mom{i}, ckeep);
+    end
+  else
+    for i=1:bigpot.dsize
+      bigpot.can{i} = marginalize_pot(bigpot.can{i}, ckeep);
+    end
+  end
+end
+
+% If we are not marginalizing over any discrete nodes, we are done.
+if prod(ns(dsumover))==1
+  smallpot = cgpot(dkeep, ckeep, ns, bigpot.can, bigpot.mom, bigpot.subtype);
+  return;
+end
+
+% To marginalize the discrete parts, we must be in moment form.
+bigpot = cg_can_to_mom(bigpot);
+
+I = prod(ns(dkeep));
+J = prod(ns(dsumover));
+C = sum(ns(ckeep));
+
+% Reshape bigpot into the form mu1(:,j,i), where i is in dkeep, j is in dsumover
+T1 = zeros(I,J);
+mu1 = zeros(C,J,I);
+Sigma1 = zeros(C,C,J,I);
+sum_map = find_equiv_posns(dsumover, bigpot.ddom);
+keep_map = find_equiv_posns(dkeep, bigpot.ddom);
+iv = zeros(1, length(bigpot.ddom)); % index vector
+for i=1:I
+  keep_iv = ind2subv(ns(dkeep), i);
+  iv(keep_map) = keep_iv;
+  for j=1:J
+    sum_iv = ind2subv(ns(dsumover), j);
+    iv(sum_map) = sum_iv;
+    k = subv2ind(ns(bigpot.ddom), iv);
+    mom = struct(bigpot.mom{k}); % violate object privacy
+    T1(i,j) = exp(mom.logp);
+    if C > 0 % so mu1 and Sigma1 are non-empty
+      mu1(:,j,i) = mom.mu;
+      Sigma1(:,:,j,i) = mom.Sigma;
+    end
+  end
+end
+
+% Collapse the mixture of Gaussians
+coef = mk_stochastic(T1); % coef must be convex combination
+T2 = sum(T1,2);
+T2 = T2 + (T2==0)*eps;
+%if C > 0, disp('collapsing onto '); disp(leep); end
+mu = [];
+Sigma = [];
+mom = cell(1,I);
+for i=1:I
+  if C > 0
+    [mu, Sigma] = collapse_mog(mu1(:,:,i), Sigma1(:,:,:,i), coef(i,:));
+  end
+  logp = log(T2(i));
+  mom{i} = mpot(ckeep, ns(ckeep), logp, mu, Sigma);
+end
+
+smallpot = cgpot(dkeep, ckeep, ns, [], mom, 'm');
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/cg_can_to_mom.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function pot = cg_can_to_mom(pot)
+% CG_CAN_TO_MOM Convert a CG potential from canonical to moment form, if necessary.
+% pot = cg_can_to_mom(pot)
+
+if pot.subtype ~= 'm'
+  for i=1:pot.dsize
+    pot.mom{i} = cpot_to_mpot(pot.can{i});
+  end
+  pot.subtype = 'm';
+end   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/cg_mom_to_can.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function pot = cg_mom_to_can(pot)
+% CG_MOM_TO_CAN Convert a CG potential from moment to canonical form, if necessary.
+% pot = cg_mom_to_can(pot)
+
+if pot.subtype ~= 'c'
+  for i=1:pot.dsize
+    pot.can{i} = mpot_to_cpot(pot.mom{i});
+  end
+  pot.subtype = 'c';
+end   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/cgpot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function pot = cgpot(ddom, cdom, node_sizes, can, mom, subtype)
+% CPOT Make a canonical CG potential.
+% function pot = cgpot(ddom, cdom, node_sizes, can, mom, subtype)
+%
+% node_sizes(i) is the size of the i'th node.
+% can and mom default to 0s.
+% subtype defaults to 'c'.
+
+if nargin < 6, subtype = 'c'; end
+
+pot.ddom = ddom;
+pot.cdom = cdom;
+node_sizes = node_sizes(:)'; % row vectors print better
+pot.domain = myunion(ddom, cdom);
+pot.dsizes = node_sizes(pot.ddom);
+pot.dsize = prod(node_sizes(pot.ddom));
+pot.csizes = node_sizes(pot.cdom);
+pot.csize = sum(node_sizes(pot.cdom));
+pot.subtype = subtype;
+
+if nargin < 4
+  can = cell(1, pot.dsize);
+  for i=1:pot.dsize
+    can{i} = cpot(cdom, node_sizes(cdom));
+  end
+end
+pot.can = can;              
+
+if nargin < 5
+  mom = cell(1, pot.dsize);
+  for i=1:pot.dsize
+    mom{i} = mpot(cdom, node_sizes(cdom));
+  end
+end
+pot.mom = mom;
+
+pot = class(pot, 'cgpot');
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function display(pot)
+
+disp('conditional Gaussian potential object');
+disp(struct(pot));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/divide_by_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function bigpot = divide_by_pot(bigpot, smallpot)
+% DIVIDE_BY_POT bigpot /= smallpot for cgpot
+% bigpot = divide_by_pot(bigpot, smallpot)
+%
+% smallpot's domain must be a subset of bigpot's domain.
+
+bigpot = cg_mom_to_can(bigpot);
+smallpot = cg_mom_to_can(smallpot);
+
+mask = find_equiv_posns(smallpot.ddom, bigpot.ddom);
+for i=1:bigpot.dsize
+  if isempty(smallpot.ddom)
+    src = 1;
+  else
+    sub = ind2subv(bigpot.dsizes, i);
+    src = subv2ind(smallpot.dsizes, sub(mask));
+  end
+  bigpot.can{i} = divide_by_pot(bigpot.can{i}, smallpot.can{src});
+end                   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/domain_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function dom = domain_pot(pot)
+% DOMAIN_POT Return the domain of this cgpot.
+% dom = domain_pot(pot)
+
+dom = pot.domain;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/enter_cts_evidence_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function pot = enter_cts_evidence_pot(pot, Y, y)
+% function pot = enter_cts_evidence_pot(pot, Y, y) cgpot
+
+
+pot = cg_mom_to_can(pot);
+for i=1:pot.dsize
+  pot.can{i} = enter_cts_evidence_pot(pot.can{i}, Y, y);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/enter_discrete_evidence_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function pot = enter_discrete_evidence_pot(pot, Y, y)
+
+%ns = sparse(1, max(pot.domain));
+ns = zeros(1, max(pot.domain));
+ns(pot.ddom) = pot.dsizes;
+ns(pot.cdom) = pot.csizes;
+
+ddom = pot.ddom;
+S = prod(ns(ddom));
+sub = ind2subv(ns(ddom), 1:S);
+mask = find_equiv_posns(Y, ddom);
+sub(mask) = y;
+ndx = subv2ind(ns(ddom), sub);
+
+pot.can = pot.can(ndx);
+pot.mom = pot.mom(ndx);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/marginalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,153 @@
+function smallpot = marginalize_pot(bigpot, keep, maximize, useC)
+% MARGINALIZE_POT Marginalize a cgpot onto a smaller domain.
+% smallpot = marginalize_pot(bigpot, keep, maximize, useC)
+%
+% If maximize = 1, we raise an error.
+% useC is ignored.
+
+if nargin < 3, maximize = 0; end
+assert(~maximize);
+
+
+sumover = mysetdiff(bigpot.domain, keep);
+csumover = myintersect(sumover, bigpot.cdom);
+dsumover = myintersect(sumover, bigpot.ddom);
+dkeep = myintersect(keep, bigpot.ddom);
+ckeep = myintersect(keep, bigpot.cdom);
+%ns = sparse(1, max(bigpot.domain)); % must be full, so I is an integer
+ns = zeros(1, max(bigpot.domain));
+ns(bigpot.ddom) = bigpot.dsizes;
+ns(bigpot.cdom) = bigpot.csizes;
+
+% sum(ns(csumover))==0 is like isempty(csumover) but handles observed nodes.
+% Similarly, prod(ns(dsumover))==1 is like isempty(dsumover)
+
+% Marginalize the cts parts.
+% If we are in canonical form, we stay that way, since moment form might not exist.
+% Besides, we would like to minimize the number of conversions.
+if sum(ns(csumover)) > 0
+  if bigpot.subtype == 'm'
+    for i=1:bigpot.dsize
+      bigpot.mom{i} = marginalize_pot(bigpot.mom{i}, ckeep);
+    end
+  else
+    for i=1:bigpot.dsize
+      bigpot.can{i} = marginalize_pot(bigpot.can{i}, ckeep);
+    end
+  end
+end
+
+% If we are not marginalizing over any discrete nodes, we are done.
+if prod(ns(dsumover))==1
+  smallpot = cgpot(dkeep, ckeep, ns, bigpot.can, bigpot.mom, bigpot.subtype);
+  return;
+end
+
+% To marginalize the discrete parts, we partition the cts parts into those that depend
+% on dkeep (i) and those that depend on on dsumover (j).
+
+I = prod(ns(dkeep));
+J = prod(ns(dsumover));
+C = sum(ns(ckeep));   
+sum_map = find_equiv_posns(dsumover, bigpot.ddom);
+keep_map = find_equiv_posns(dkeep, bigpot.ddom);
+iv = zeros(1, length(bigpot.ddom)); % index vector
+
+% If in canonical form, marginalize if possible, else convert to moment form.
+if 0 & bigpot.subtype == 'c'
+  p1 = zeros(I,J);
+  h1 = zeros(C,J,I);
+  K1 = zeros(C,C,J,I);
+  for i=1:I
+    keep_iv = ind2subv(ns(dkeep), i);
+    iv(keep_map) = keep_iv;
+    for j=1:J
+      sum_iv = ind2subv(ns(dsumover), j);
+      iv(sum_map) = sum_iv;
+      k = subv2ind(ns(bigpot.ddom), iv);
+      can = struct(bigpot.can{k}); % violate object privacy
+      p1(i,j) = exp(can.g);
+      if C > 0 % so mu1 and Sigma1 are non-empty
+	h1(:,j,i) = can.h;
+	K1(:,:,j,i) = can.K;
+      end
+    end
+  end
+  
+  % If the cts parts do not depend on j, we can just marginalize the weighting coefficient g.
+  jdepends = 0;
+  for i=1:I
+    for j=2:J
+      if ~approxeq(h1(:,j,i), h1(:,1,i)) | ~approxeq(K1(:,:,j,i), K1(:,:,1,i))
+	jdepends = 1;
+	break
+      end
+    end
+  end
+
+  if ~jdepends
+    %g2 = log(sum(p1, 2));
+    g2 = zeros(I,1);
+    for i=1:I
+      s = sum(p1(i,:));
+      if s > 0
+	g2(i) = log(s);
+      end
+    end
+    h2 = h1;
+    K2 = K1;
+    can = cell(1,I);
+    j = 1; % arbitrary
+    for i=1:I
+      can{i} = cpot(ckeep, ns(ckeep), g2(i), h2(:,j,i), K2(:,:,j,i));
+    end
+    smallpot = cgpot(dkeep, ckeep, ns, can, [], 'c');  
+    return;
+  else
+    % Since the cts parts depend on j, we must convert to moment form
+    bigpot = cg_can_to_mom(bigpot);
+  end
+end
+
+
+% Marginalize in moment form
+bigpot = cg_can_to_mom(bigpot);
+
+% Now partition the moment components.
+T1 = zeros(I,J);
+mu1 = zeros(C,J,I);
+Sigma1 = zeros(C,C,J,I);
+for i=1:I
+  keep_iv = ind2subv(ns(dkeep), i);
+  iv(keep_map) = keep_iv;
+  for j=1:J
+    sum_iv = ind2subv(ns(dsumover), j);
+    iv(sum_map) = sum_iv;
+    k = subv2ind(ns(bigpot.ddom), iv);
+    mom = struct(bigpot.mom{k}); % violate object privacy
+    T1(i,j) = exp(mom.logp);
+    if C > 0 % so mu1 and Sigma1 are non-empty
+      mu1(:,j,i) = mom.mu;
+      Sigma1(:,:,j,i) = mom.Sigma;
+    end
+  end
+end
+
+% Collapse the mixture of Gaussians
+coef = mk_stochastic(T1); % coef must be convex combination
+T2 = sum(T1,2);
+T2 = T2 + (T2==0)*eps;
+%if C > 0, disp('collapsing onto '); disp(leep); end
+mu = [];
+Sigma = [];
+mom = cell(1,I);
+for i=1:I
+  if C > 0
+    [mu, Sigma] = collapse_mog(mu1(:,:,i), Sigma1(:,:,:,i), coef(i,:));
+  end
+  logp = log(T2(i));
+  mom{i} = mpot(ckeep, ns(ckeep), logp, mu, Sigma);
+end
+
+smallpot = cgpot(dkeep, ckeep, ns, [], mom, 'm');
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/multiply_by_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function bigpot = multiply_by_pot(bigpot, smallpot, varargin)
+% MULTIPLY_BY_POT bigpot *= smallpot for cgpot
+% bigpot = multiply_by_pot(bigpot, smallpot)
+%
+% smallpot's domain must be a subset of bigpot's domain.
+
+bigpot = cg_mom_to_can(bigpot);
+smallpot = cg_mom_to_can(smallpot);
+
+mask = find_equiv_posns(smallpot.ddom, bigpot.ddom);
+for i=1:bigpot.dsize
+  if isempty(smallpot.ddom)
+    src = 1;
+  else
+    sub = ind2subv(bigpot.dsizes, i);
+    src = subv2ind(smallpot.dsizes, sub(mask));
+  end
+  bigpot.can{i} = multiply_by_pot(bigpot.can{i}, smallpot.can{src});
+end                   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/multiply_pots.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function T = multiply_pots(T1, T2)
+% MULTIPLY_POTS Multiply a pair of dpots together pointwise (cgpot)
+% T = multiply_pots(pots)
+
+ddom = myunion(T1.ddom, T2.ddom);
+cdom = myunion(T1.cdom, T2.cdom);
+dom = myunion(ddom, cdom);
+ns = zeros(1, max(dom));
+ns(T1.ddom) = T1.dsizes;
+ns(T2.ddom) = T2.dsizes;
+ns(T1.cdom) = T1.csizes;
+ns(T2.cdom) = T2.csizes;
+
+T = cgpot(ddom, cdom, ns);
+T = multiply_by_pot(T, T1);
+T = multiply_by_pot(T, T2);   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/normalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function [pot, loglik] = normalize_pot(pot)
+% NORMALIZE_POT Convert the CG potential Pr(X,E) into Pr(X|E) and return log Pr(E).
+% [pot, loglik] = normalize_pot(pot)
+
+% Marginalize down to [], so that the normalizing constant becomes Pr(E)
+temp = cg_can_to_mom(marginalize_pot(pot, []));
+%loglik = temp.mom{1}.logp;
+[temp2, loglik] = normalize_pot(temp.mom{1});
+  
+% Adjust scale factor to reflect the fact that the pot now represents Pr(X | E) instead of Pr(X,E).
+
+scale = -loglik;
+if 1
+switch pot.subtype
+  case 'm'
+    for i=1:pot.dsize
+      pot.mom{i} = rescale_pot(pot.mom{i}, scale);
+    end
+  case 'c'
+    for i=1:pot.dsize
+      pot.can{i} = rescale_pot(pot.can{i}, scale);
+    end
+end        
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/pot_to_marginal.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,27 @@
+function m = pot_to_marginal(pot)
+% POT_TO_MARGINAL Convert a cgpot to a marginal structure.
+% m = pot_to_marginal(pot)
+
+pot = cg_can_to_mom(pot);
+m.domain = pot.domain;
+n = pot.csize;
+d = length(pot.mom);
+if n==0
+  m.mu = [];
+  m.Sigma = [];
+else
+  m.mu = zeros(n, d);
+  m.Sigma = zeros(n, n, d);
+end
+m.T = 0*myones(pot.dsizes);
+for i=1:pot.dsize
+  s = struct(pot.mom{i}); % violate privacy of object
+  if n > 0
+    m.mu(:,i) = s.mu;
+    m.Sigma(:,:,i) = s.Sigma;
+  end
+  m.T(i) = exp(s.logp);
+end     
+if isvector(m.T)
+  m.T = m.T(:)';
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cgpot/set_domain_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function pot = set_domain_pot(pot, domain)
+% SET_DOMAIN_POT Change the domain of a potential (cgpot)
+% pot = set_domain_pot(pot, domain)
+
+delta = domain(1) - pot.domain(1);
+assert(all(domain == pot.domain + delta));
+pot.domain = pot.domain + delta;
+pot.ddom = pot.ddom + delta;
+pot.cdom = pot.cdom + delta;
+cdomain = pot.cdom;
+n = prod(pot.dsizes);
+if(pot.subtype == 'm')
+    for i = 1: n
+        pot.mom{i} = set_domain_pot(pot.mom{i}, cdomain);
+    end
+end
+if(pot.subtype == 'c')
+    for i = 1: n
+        pot.can{i} = set_domain_pot(pot.can{i}, cdomain);
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+/cpot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/cpot_to_mpot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/display.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/divide_by_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/domain_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/enter_cts_evidence_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/marginalize_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/multiply_by_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/multiply_pots.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/normalize_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/pot_to_marginal.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/rescale_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/set_domain_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+A D/Old////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/potentials/@cpot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+/cpot_to_mpot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/normalize_pot.convert.m/1.1.1.1/Wed May 29 15:59:58 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/potentials/@cpot/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/Old/cpot_to_mpot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function mom = cpot_to_mpot(can)
+% CPOT_TO_MPOT Convert a canonical potential to moment form.
+% mom = cpot_to_mpot(can)
+
+[logp, mu, Sigma] = canonical_to_moment(can.g, can.h, can.K);
+mom = mpot(can.domain, can.sizes, logp, mu, Sigma);
+
+%%%%%%%
+
+function [logp, mu, Sigma] = canonical_to_moment(g, h, K)
+% CANONICAL_TO_MOMENT Convert canonical characteristics to moment form.
+% [logp, mu, Sigma] = canonical_to_moment(g, h, K)
+
+if det(K)==0
+  Sigma = inf*size(K);
+else
+  Sigma = inv(K);
+end
+mu = Sigma*h;
+n = length(mu);
+if isempty(mu)
+  logp = g - 0.5*(log(det(K)) - n*log(2*pi));
+else
+  logp = g - 0.5*(log(det(K)) - n*log(2*pi) - mu'*K*mu);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/Old/normalize_pot.convert.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function [mom2, loglik] = normalize_pot(can)
+% NORMALIZE_POT Convert the canonical potential Pr(X,E) into moment potential Pr(X|E) and return log Pr(E).
+% [mom, loglik] = normalize_pot(can)
+
+mom = cpot_to_mpot(can);
+mom = struct(mom); % violate privacy of object
+loglik = mom.logp;
+%mom.logp = 0; % now represents Pr(X | E) instead of Pr(X, E). 
+mom2 = mpot(mom.domain, mom.sizes, 0, mom.mu, mom.Sigma);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/cpot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function pot = cpot(members, sizes, g, h, K)
+% CPOT Make a canonical Gaussian potential.
+% pot = cpot(members, sizes, g, h, K)
+%
+% All params default to 0 if omitted.
+
+n = sum(sizes);
+if nargin < 3, g = 0; end
+if nargin < 4, h = zeros(n,1); end
+if nargin < 5, K = zeros(n,n); end
+  
+pot.domain = members;
+pot.sizes = sizes(:)';
+pot.g = g;
+pot.h = h;
+pot.K = K;
+pot = class(pot, 'cpot');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/cpot_to_mpot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+function mom = cpot_to_mpot(can)
+% CPOT_TO_MPOT Convert a canonical potential to moment form.
+% mom = cpot_to_mpot(can)
+
+[logp, mu, Sigma] = canonical_to_moment(can.g, can.h, can.K);
+mom = mpot(can.domain, can.sizes, logp, mu, Sigma);
+
+%%%%%%%
+
+function [logp, mu, Sigma] = canonical_to_moment(g, h, K)
+% CANONICAL_TO_MOMENT Convert canonical characteristics to moment form.
+% [logp, mu, Sigma] = canonical_to_moment(g, h, K)
+
+n = length(K);
+if isempty(K)
+  logp = g - 0.5*(log(det(K)) - n*log(2*pi));
+  Sigma = [];
+  mu = [];
+else
+  if det(K)==0
+    Sigma = inf*ones(n,n);
+    mu = zeros(n,1); % if the precision is zero, the mean is arbitrary
+    logp = g; % the scaling factor for the uniform distribution is 1
+  else
+    Sigma = inv(K);
+    mu = Sigma*h;
+    logp = g - 0.5*(log(det(K)) - n*log(2*pi) - mu'*K*mu);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function display(pot)
+
+disp('canonical potential object');
+disp(struct(pot));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/divide_by_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function bigpot = divide_by_pot(bigpot, smallpot)
+% DIVIDE_BY_POT bigpot /= smallpot for cpot
+% bigpot = divide_by_pot(bigpot, smallpot)
+%
+% smallpot's domain must be a subset of bigpot's domain.
+
+bigpot.g = bigpot.g - smallpot.g;
+if sum(smallpot.sizes) > 0
+  mask = find_equiv_posns(smallpot.domain, bigpot.domain);
+  u = block(mask, bigpot.sizes);
+  bigpot.h(u) = bigpot.h(u) - smallpot.h;
+  bigpot.K(u, u) = bigpot.K(u, u) - smallpot.K;
+end               
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/domain_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function dom = domain_pot(pot)
+% DOMAIN_POT Return the domain of this cpot.
+% dom = domain_pot(pot)
+
+dom = pot.domain;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/enter_cts_evidence_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function pot = enter_cts_evidence_pot(pot, Y, y)
+% function pot = enter_cts_evidence_pot(pot, Y, y) (cpot)
+
+ns = sparse(1, max(pot.domain));
+ns(pot.domain) = pot.sizes;
+
+X = mysetdiff(pot.domain, Y);
+[hx, hy, KXX, KXY, KYX, KYY] = partition_matrix_vec(pot.h, pot.K, X, Y, ns);
+pot.g = pot.g + hy'*y - 0.5*y'*KYY*y;
+if ~isempty(X)
+  pot.h = hx - KXY*y;
+  pot.K = KXX;
+end
+
+pot.sizes(find_equiv_posns(Y,pot.domain)) = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/marginalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,31 @@
+function smallpot = marginalize_pot(bigpot, keep, maximize, useC)
+% MARGINALIZE_POT Marginalize a cpot onto a smaller domain.
+% smallpot = marginalize_pot(bigpot, keep, maximize, useC)
+%
+% The maximize argument is ignored - maxing out a Gaussian is the same as summing it out,
+% since the mode and mean are equal.
+% The useC argument is ignored.
+
+node_sizes = sparse(1, max(bigpot.domain));
+node_sizes(bigpot.domain) = bigpot.sizes;
+sum_over = mysetdiff(bigpot.domain, keep);
+
+if sum(node_sizes(sum_over))==0 % isempty(sum_over)
+  %smallpot = bigpot;
+  smallpot = cpot(keep, node_sizes(keep), bigpot.g, bigpot.h, bigpot.K);
+else
+  [h1, h2, K11, K12, K21, K22] = partition_matrix_vec(bigpot.h, bigpot.K, sum_over, keep, node_sizes);
+  n = length(h1);
+  K11inv = inv(K11);
+  g = bigpot.g + 0.5*(n*log(2*pi) - log(det(K11)) + h1'*K11inv*h1);
+  if length(h2) > 0 % ~isempty(keep) % we are are actually keeping something
+    A = K21*K11inv;
+    h = h2 - A*h1;
+    K = K22 - A*K12;
+  else
+    h = [];
+    K = [];
+  end
+  smallpot = cpot(keep, node_sizes(keep), g, h, K);
+end
+           
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/multiply_by_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function bigpot = multiply_by_pot(bigpot, smallpot, varargin)
+% MULTIPLY_BY_POT bigpot *= smallpot for cpot
+% bigpot = multiply_by_pot(bigpot, smallpot)
+%
+% smallpot's domain must be a subset of bigpot's domain.
+
+bigpot.g = bigpot.g + smallpot.g;
+if sum(smallpot.sizes) > 0
+  mask = find_equiv_posns(smallpot.domain, bigpot.domain);
+  u = block(mask, bigpot.sizes);
+  bigpot.h(u) = bigpot.h(u) + smallpot.h;
+  bigpot.K(u, u) = bigpot.K(u, u) + smallpot.K;
+end               
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/multiply_pots.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function T = multiply_pots(T1, T2)
+% MULTIPLY_POTS Multiply a pair of dpots together pointwise (cpot)
+% T = multiply_pots(pots)
+
+dom = myunion(T1.domain, T2.domain);
+ns = sparse(1, max(dom));
+ns(T1.domain) = T1.sizes;
+ns(T2.domain) = T2.sizes;
+T = cpot(dom, ns(dom));
+T = multiply_by_pot(T, T1);
+T = multiply_by_pot(T, T2);   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/normalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function [pot, loglik] = normalize_pot(pot)
+% NORMALIZE_POT Convert the canonical potential Pr(X,E) into Pr(X|E) and return log Pr(E).
+% [pot, loglik] = normalize_pot(pot)
+
+mom = cpot_to_mpot(pot);  % move the normalizing constant out of g, to reveal the coefficient          
+%loglik = scaling_factor_pot(mom);
+%loglik = mom.logp; 
+[temp, loglik] = normalize_pot(mom);
+pot.g = pot.g - loglik;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/pot_to_marginal.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function m = pot_to_marginal(pot)
+% POT_TO_MARGINAL Convert a cpot to a marginal structure.
+% m = pot_to_marginal(pot)
+
+mom = cpot_to_mpot(pot);
+m = pot_to_marginal(mom);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/rescale_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function pot = rescale_pot(pot, s)
+% RESCALE_POT Add a constant to the cpot scale factor.
+% pot = rescale_pot(pot, s)
+
+pot.g = pot.g + s;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@cpot/set_domain_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function pot = set_domain_pot(pot, domain)
+% SET_DOMAIN_POT Change the domain of a potential (dpot)
+% pot = set_domain_pot(pot, domain)
+
+pot.domain = domain;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+/approxeq_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/display.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/divide_by_pot.m/1.1.1.1/Thu Aug  5 15:25:08 2004//
+/domain_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/dpot.m/1.1.1.1/Tue Oct  1 19:04:44 2002//
+/dpot_to_table.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/find_most_prob_entry.m/1.1.1.1/Sun Jun 16 19:06:20 2002//
+/get_fields.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/marginalize_pot.m/1.1.1.1/Wed Aug  4 19:59:14 2004//
+/multiply_by_pot.m/1.1.1.1/Wed Aug  4 19:59:14 2004//
+/multiply_pots.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/normalize_pot.m/1.1.1.1/Wed Aug  4 15:54:48 2004//
+/pot_to_marginal.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/set_domain_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/subsasgn.m/1.1.1.1/Wed Apr 27 18:34:48 2005//
+/subsref.m/1.1.1.1/Wed Apr 27 18:34:48 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/potentials/@dpot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/approxeq_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function p = approxeq_pot(A, B, tol)
+
+if nargin < 3, tol = 1e-3; end
+
+p = approxeq(A.T, B.T, tol);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function display(pot)
+
+disp('discrete potential object');
+disp(struct(pot));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/divide_by_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+function Tbig = divide_by_pot(Tbig, Tsmall)
+% DIVIDE_BY_POT Tbig /= Tsmall
+% Tbig = divide_by_pot(Tbig, Tsmall)
+%
+% Tsmall's domain must be a subset of Tbig's domain.
+
+%process sparse dpot, we do not concern only one of the two pots is sparse
+if issparse(Tbig.T) & issparse(Tsmall.T)
+   Tbig.T = divide_by_sparse_table(Tbig.T, Tbig.domain, Tbig.sizes, Tsmall.T, Tsmall.domain, Tsmall.sizes);
+else
+   Tbig.T = divide_by_table(Tbig.T, Tbig.domain, Tbig.sizes, Tsmall.T, Tsmall.domain, Tsmall.sizes);
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/domain_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function dom = domain_pot(pot)
+% DOMAIN_POT Return the domain of this dpot.
+% dom = domain_pot(pot)
+
+dom = pot.domain;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/dpot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function pot = dpot(domain, sizes, T)
+% DPOT Make a discrete (sparse) potential.
+% pot = dpot(domain, sizes, T, spar)
+%
+% sizes(i) is the size of the i'th domain element.
+% T defaults to all 1s.
+
+%assert(length(sizes) == length(domain));
+
+pot.domain = domain(:)'; % so we can see it when we display
+if nargin < 3
+  pot.T = myones(sizes);
+  %pot.T = ones(1,prod(sizes)); % 1D vector
+else 
+   if isempty(T)
+      pot.T = [];
+   else
+      if issparse(T)
+         pot.T = T;   
+      else
+         pot.T = myreshape(T, sizes);  
+      end
+   end
+end
+pot.sizes = sizes(:)';
+pot = class(pot, 'dpot');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/dpot_to_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+function T = dpot_to_table(pot)
+
+T = pot.T;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/find_most_prob_entry.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function [indices, pot] = find_most_prob_entry(pot)
+% function [indices, pot] = find_most_prob_entry(pot)
+% function [indices, pot] = find_most_prob_entry(pot)
+% Find the indices of the argmax, and set all other enties to 0.
+
+%indices = argmax(pot.T);
+[m i] = max(pot.T(:));
+indices = ind2subv(pot.sizes, i);
+pot.T = 0*myones(pot.sizes);
+pot.T(i) = m;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/get_fields.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function val = get_params(pot, name)
+% GET_PARAMS Accessor function for a field (dpot)
+% val = get_params(pot, name)
+%
+% e.g., get_params(pot, 'table') or 'domain'
+
+switch name
+ case 'table', val = pot.T;
+ case 'domain', val = pot.domain;
+ otherwise,
+  error(['invalid field name ' name]);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/marginalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function smallpot = marginalize_pot(bigpot, onto, maximize)
+% MARGINALIZE_POT Marginalize a dpot onto a smaller domain.
+% smallpot = marginalize_pot(bigpot, onto, maximize)
+%
+% 'onto' must be in ascending order.
+
+if nargin < 3, maximize = 0; end
+
+ns = zeros(1, max(bigpot.domain));
+ns(bigpot.domain) = bigpot.sizes;
+%assert(isequal(bigpot.sizes, mysize(bigpot.T))); % may fail if there are trailing dimensions of size 1
+if issparse(bigpot.T)
+   smallT = marg_sparse_table(bigpot.T, bigpot.domain, bigpot.sizes, onto, maximize);
+else 
+   smallT = marg_table(bigpot.T, bigpot.domain, bigpot.sizes, onto, maximize);
+end
+smallpot = dpot(onto, ns(onto), smallT);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/multiply_by_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function Tbig = multiply_by_pot(Tbig, Tsmall)
+% MULTIPLY_BY_POT Tbig *= Tsmall
+% Tbig = multiply_by_pot(Tbig, Tsmall)
+%
+% Tsmall's domain must be a subset of Tbig's domain.
+
+%process sparse dpot, we do not consider only one of the two pots is sparse
+if issparse(Tbig.T) & issparse(Tsmall.T)
+   Tbig.T = mult_by_sparse_table(Tbig.T, Tbig.domain, Tbig.sizes, Tsmall.T, Tsmall.domain, Tsmall.sizes);
+else 
+   Tbig.T = mult_by_table(Tbig.T, Tbig.domain, Tbig.sizes, Tsmall.T, Tsmall.domain, Tsmall.sizes);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/multiply_pots.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function T = multiply_pots(T1, T2)
+% MULTIPLY_POTS Multiply a pair of dpots together pointwise.
+% T = multiply_pots(pots)
+
+dom = myunion(T1.domain, T2.domain);
+%ns = sparse(1, max(dom)); % causes problems in myreshape on NT
+ns = zeros(1, max(dom));
+ns(T1.domain) = T1.sizes;
+ns(T2.domain) = T2.sizes;
+T = dpot(dom, ns(dom));
+T = multiply_by_pot(T, T1);
+T = multiply_by_pot(T, T2);   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/normalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function [pot, loglik] = normalize_pot(pot)
+% NORMALIZE_POT Convert the discrete potential Pr(X,E) into Pr(X|E) and return log Pr(E).
+% [pot, loglik] = normalize_pot(pot)
+
+if isempty(pot.T)  %add to process sparse
+   loglik = 0;
+   return;
+end
+[pot.T, lik] = normalise(pot.T);
+loglik = log(lik + (lik==0)*eps);
+
+      
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/pot_to_marginal.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function m = pot_to_marginal(pot)
+% POT_TO_MARGINAL Convert a dpot to a marginal structure.
+% m = pot_to_marginal(pot)
+
+m.domain = pot.domain;
+m.T = pot.T;
+m.mu = [];
+m.Sigma = [];  
+
+%if isvector(m.T)
+%  m.T = m.T(:);
+%end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/set_domain_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function pot = set_domain_pot(pot, domain)
+% SET_DOMAIN_POT Change the domain of a potential (dpot)
+% pot = set_domain_pot(pot, domain)
+
+pot.domain = domain;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/subsasgn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+function B = subsasgn(A, S, B)
+
+B = builtin('subsasgn', A, S, B);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@dpot/subsref.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+function B = subsref(A, S)
+
+B = builtin('subsref', A, S);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@mpot/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+/display.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/marginalize_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/mpot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/mpot_to_cpot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/normalize_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/pot_to_marginal.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/rescale_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/set_domain_pot.m/1.1.1.1/Wed Jul 30 13:37:52 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@mpot/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/potentials/@mpot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@mpot/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@mpot/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function display(pot)
+
+disp('moment Gaussian potential object');
+disp(struct(pot));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@mpot/marginalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,27 @@
+function smallpot = marginalize_pot(bigpot, keep, maximize, useC)
+% MARGINALIZE_POT Marginalize a mpot onto a smaller domain.
+% smallpot = marginalize_pot(bigpot, keep, maximize, useC)
+%
+% The maximize argument is ignored - maxing out a Gaussian is the same as summing it out,
+% since the mode and mean are equal.
+% The useC argument is ignored.
+
+
+node_sizes = sparse(1, max(bigpot.domain));
+node_sizes(bigpot.domain) = bigpot.sizes;
+sum_over = mysetdiff(bigpot.domain, keep);
+
+[logp, mu, Sigma] = marginalize_gaussian(bigpot.logp, bigpot.mu, bigpot.Sigma, ...
+					 keep, sum_over, node_sizes);
+smallpot = mpot(keep, node_sizes(keep), logp, mu, Sigma);
+
+%%%%%%
+
+function [logpX, muX, SXX] = marginalize_gaussian(logp, mu, Sigma, X, Y, ns)
+% MARGINALIZE_GAUSSIAN Compute Pr(X) from Pr(X,Y) where X and Y are jointly Gaussian.
+% [logpX, muX, SXX] = marginalize_gaussian(logp, mu, Sigma, X, Y, ns)
+%
+% sizes(i) is the size of the i'th block in domain.
+ 
+[muX, muY, SXX, SXY, SYX, SYY] = partition_matrix_vec(mu, Sigma, X, Y, ns);
+logpX = logp; % Lauritzen (1996) p161          
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@mpot/mpot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function pot = mpot(members, sizes, logp, mu, Sigma)
+% MPOT Make a moment Gaussian potential.
+% pot = mpot(members, sizes, logp, mu, Sigma)
+%
+% All params default to 0 if omitted.
+
+n = sum(sizes);
+if nargin < 3, logp = 0; end
+if nargin < 4, mu = zeros(n,1); end
+if nargin < 5, Sigma = zeros(n,n); end
+  
+pot.domain = members;
+pot.sizes = sizes;
+pot.logp = logp;
+pot.mu = mu;
+pot.Sigma = Sigma;zeros(n,n);      
+pot = class(pot, 'mpot');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@mpot/mpot_to_cpot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function can = mpot_to_cpot(mom)
+% MPOT_TO_CPOT Convert a moment potential to canonical form.
+% mom = mpot_to_cpot(can)
+
+[g, h, K] = moment_to_canonical(mom.logp, mom.mu, mom.Sigma);
+can = cpot(mom.domain, mom.sizes, g, h, K);
+
+%%%%%%%%%%%
+
+function [g, h, K] = moment_to_canonical(logp, mu, Sigma)
+% MOMENT_TO_CANONICAL Convert moment characteristics to canonical form.
+% [g, h, K] = moment_to_canonical(logp, mu, Sigma)
+
+K = inv(Sigma);
+h = K*mu;
+n = length(K);
+if isempty(mu)
+  g = logp + 0.5*(log(det(K)) - n*log(2*pi));
+else
+  g = logp + 0.5*(log(det(K)) - n*log(2*pi) - mu'*K*mu);
+end        
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@mpot/normalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function [pot, loglik] = normalize_pot(pot)
+% NORMALIZE_POT Convert the moment potential Pr(X,E) into Pr(X|E) and return log Pr(E).
+% [pot, loglik] = normalize_pot(pot)
+
+loglik = pot.logp;
+pot.logp = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@mpot/pot_to_marginal.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function m = pot_to_marginal(pot)
+% POT_TO_MARGINAL Convert a mpot to a marginal structure.
+% m = pot_to_marginal(pot)
+
+m.domain = pot.domain;
+m.T = exp(pot.logp);
+m.mu = pot.mu;
+m.Sigma = pot.Sigma;
+
+if isvector(m.T)
+  m.T = m.T(:)';
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@mpot/rescale_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function pot = rescale_pot(pot, s)
+% RESCALE_POT Add a constant to the mpot scale factor.
+% pot = rescale_pot(pot, s)
+
+pot.logp = pot.logp + s;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@mpot/set_domain_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function pot = set_domain_pot(pot, domain)
+% SET_DOMAIN_POT Change the domain of a potential (mpot)
+% pot = set_domain_pot(pot, domain)
+
+pot.domain = domain;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgcpot/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+/marginalize_pot.m/1.1.1.1/Sun May 19 22:11:08 2002//
+/normalize_pot.m/1.1.1.1/Sun May 19 22:11:08 2002//
+/reduce_pot.m/1.1.1.1/Tue Mar 11 17:37:02 2003//
+/rescale_pot.m/1.1.1.1/Sun May 19 22:11:08 2002//
+/scgcpot.m/1.1.1.1/Sun May 19 22:11:08 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgcpot/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/potentials/@scgcpot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgcpot/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgcpot/marginalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function smallpot = marginalize_pot(bigpot, keepdom, sumoverdom, nodesizes)
+% MARGINALIZE_POT Marginalize a mpot onto a smaller domain.
+% smallpot = marginalize_pot(bigpot, keep)
+
+keepsize = sum(nodesizes(keepdom));
+[A1, A2, B1, B2, C11, C12, C21, C22] = partition_matrix_vec_3(bigpot.A, bigpot.B, bigpot.C, keepdom, sumoverdom, nodesizes);
+smallpot = scgcpot(keepsize, bigpot.ctailsize, bigpot.p, A1, B1, C11);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgcpot/normalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function [pot, loglik] = normalize_pot(pot)
+% NORMALIZE_POT Convert the element of stable conditional gaussian potential Pr(X,E) into Pr(X|E) and return log Pr(E).
+% [pot, loglik] = normalize_pot(pot)
+
+loglik = log(pot.p);
+pot.p = 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgcpot/reduce_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function [reduced_pot,successful] = reduce(pot,tailnodes)
+% Executes the reduce operation defined in 
+% Stable Local Computation with Conditional Gaussian Distributions
+% Steffen L. Lauritzen
+% Frank Jensen
+% September 1999
+% The potential pot is reduced if B contains any zero columns 
+% The test are restricted to the positions in tailnodes.
+% Any columns successfully deleted are entered in the array successful
+
+if nargin < 2
+    tailnodes = 1:pot.ctailsize;
+end
+
+successful = [];
+
+% Look for all columns beeing equal to zero
+for i = tailnodes
+    if ~any(pot.B(:,i))
+        successful = [successful i]; 
+    end
+end
+
+remain = mysetdiff(1:pot.ctailsize,successful);
+
+% Erase the zero-columns and decrease the tailsize
+pot.B = pot.B(:,remain);
+pot.ctailsize = pot.ctailsize - length(successful);
+
+% Return the reduced potential
+reduced_pot = pot;
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgcpot/rescale_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function pot = rescale_pot(pot, s)
+% RESCALE_POT Add a constant to the mpot scale factor.
+% pot = rescale_pot(pot, s)
+
+pot.p = pot.p*s;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgcpot/scgcpot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,49 @@
+function pot = scgcpot(cheadsize, ctailsize, p, A, B, C)
+% SCGCPOT Make a base object of stable conditional gaussian potential.
+% pot = scgcpot(cheadsize, ctailsize, p, A, B, C)
+%
+% cheadsize is the demension of head nodes.
+% ctailsize is the demension of tail nodes.
+% r = cheadsize, s = ctailsize
+% p is discrete probability.
+% A is table of r*1 vectors;
+% B is r*s matrices
+% C is r*r positive semidefinite symmetric matrices
+
+if nargin < 3
+    p = 1; 
+end
+if nargin < 4
+    A = zeros(cheadsize,1); 
+end
+if nargin < 5
+    B = zeros(cheadsize,ctailsize); 
+end
+if nargin < 6
+    C = zeros(cheadsize,cheadsize); 
+end
+
+if isempty(A)
+    A = zeros(cheadsize,1); 
+end
+if isempty(B)
+    B = zeros(cheadsize,ctailsize); 
+end
+if isempty(C)
+    C = zeros(cheadsize,cheadsize); 
+end
+  
+pot.cheadsize = cheadsize;
+pot.ctailsize = ctailsize;
+
+pot.p = p;
+pot.A = A;
+pot.B = B;
+pot.C = C;
+%if cheadsize == 0
+%   pot.A = [];
+%end
+%if ctailsize == 0
+%    pot.B = [];
+%end
+pot = class(pot, 'scgcpot');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+/README/1.1.1.1/Thu Mar 20 15:07:16 2003//
+/combine_pots.m/1.1.1.1/Tue Mar 11 17:49:28 2003//
+/complement_pot.m/1.1.1.1/Wed May 21 13:49:34 2003//
+/direct_combine_pots.m/1.1.1.1/Sun May 19 22:11:08 2002//
+/extension_pot.m/1.1.1.1/Fri Jan 24 12:52:34 2003//
+/marginalize_pot.m/1.1.1.1/Tue Mar 11 17:06:08 2003//
+/normalize_pot.m/1.1.1.1/Wed May 21 13:49:44 2003//
+/pot_to_marginal.m/1.1.1.1/Sun May 19 22:11:08 2002//
+/recursive_combine_pots.m/1.1.1.1/Wed May 21 13:49:48 2003//
+/reduce_pot.m/1.1.1.1/Tue Mar 11 18:07:12 2003//
+/scgpot.m/1.1.1.1/Tue Mar 11 14:04:48 2003//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/potentials/@scgpot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/README	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+% Stable conditional Gaussian inference
+% Written by Rainer Deventer
+
+
+@techreport{Lauritzen99,
+  author = "S. Lauritzen and F. Jensen",
+  title = "Stable Local Computation with Conditional {G}aussian Distributions",
+  year = 1999,
+  number = "R-99-2014",
+  institution = "Dept. Math. Sciences, Aalborg Univ."
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/combine_pots.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function pot = combine_pots(pot1, pot2)
+% COMBINE_POTS combine two potentials 
+% pot = combine_pots(pot1, pot2)
+
+% Reduce both potentials before trying to combine them. 
+% Cf. "Stable Local computation with Conditional Gaussian Distributions", page 9
+% Consider again two potentials with minimal tail
+
+% Guarantee minimal tails. If pot1 or pot2 are minimal, they are not changed
+pot1 = reduce_pot(pot1);
+pot2 = reduce_pot(pot2);
+
+%if the intersect set of these two potentials' head conts. combination is undifined
+if ~isempty( myintersect(pot1.cheaddom, pot2.cheaddom) )
+    return;
+end
+
+if  isempty( myintersect(pot1.domain, pot2.cheaddom) ) | isempty( myintersect(pot2.domain, pot1.cheaddom))
+    % if satisfy the condition of directed combine
+    pot = direct_combine_pots(pot1, pot2);
+else
+    % perform recursive combine
+    pot = recursive_combine_pots(pot1, pot2);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/complement_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,221 @@
+function [margpot, comppot] = complement_pot(pot, keep)
+% COMPLEMENT_POT complement means decompose of a potential into its strong marginal and 
+% its complement corresponds exactly to the decomposition of a probability distribution 
+% into its marginal and conditional
+% [margpot, comppot] = complement_pot(pot, keep)
+
+% keep can only include continuous head nodes and discrete nodes
+% margpot is the stable CG potential of keep nodes
+% comppot is the stable CG potential of others in corresponds exactly to 
+% the discomposition of a probability distribution of its marginal and conditional
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Calculation of the marginal requires integration over      %
+% all variables in csumover. Thus cheadkeep contains all     %
+% continuous variables in the marginal potential             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%keyboard;
+csumover = mysetdiff(pot.cheaddom, keep);
+cheadkeep = mysetdiff(pot.cheaddom, csumover);
+
+nodesizes = zeros(1, max(pot.domain));
+nodesizes(pot.ddom) = pot.dsizes;
+nodesizes(pot.cheaddom) = pot.cheadsizes;
+nodesizes(pot.ctaildom) = pot.ctailsizes;
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Description of the variables in the marginal domain        %
+% For the calculation of a strong marginal first integration %
+% over all continuous variables in the head takes place.     %
+% The calculation of the marginal over the head variables    %
+% might result in a smaller or empty tail                    %
+% If there are no head variables, and therefore no tail      %
+% variables, left marginalisation over discrete variables    %
+% may take place                                             %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
+margdom      = mysetdiff(pot.domain,keep);
+% margddom   = pot.ddom;
+margcheaddom = cheadkeep;
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Marginalisation over discrete variables is only allowed when %
+% the tail is empty                                            %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+margddom = myintersect(pot.ddom,keep);               % Discrete domain of marginal
+margctaildom = myintersect(pot.ctaildom,keep);       % Tail domain
+assert(isempty(mysetdiff(pot.ddom,margddom)) | isempty(margctaildom))  
+
+
+%margctaildom = pot.ctaildom;
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Even if marginalisation over continuous variables is only defined %
+% for head variables, the marginalisation over haed-variables might %
+% result in a smaller tail                                          %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+margctaildom = myintersect(pot.ctaildom,keep);
+
+margcheadsizes = nodesizes(margcheaddom);
+margcheadsize = sum(margcheadsizes);
+margctailsizes = nodesizes(margctaildom);
+margctailsize = sum(margctailsizes);
+
+compdom = pot.domain;
+compddom = pot.ddom;
+compcheaddom = csumover;
+compctaildom = myunion(pot.ctaildom, cheadkeep);
+compcheadsizes = nodesizes(compcheaddom);
+compcheadsize = sum(compcheadsizes);
+compctailsizes = nodesizes(compctaildom);
+compctailsize = sum(compctailsizes);
+
+dkeep = myintersect(pot.ddom, keep);
+%if dom is only contain discrete node
+if isempty(pot.cheaddom)
+    dsumover = mysetdiff(pot.ddom, dkeep);
+    
+    if isempty(dsumover)
+        margpot = pot;
+        comppot = scgpot([], [], [], []);
+        return;
+    end
+        
+    
+    I = prod(nodesizes(dkeep));
+    J = prod(nodesizes(dsumover));
+    sum_map = find_equiv_posns(dsumover, pot.ddom);
+    keep_map = find_equiv_posns(dkeep, pot.ddom);
+    iv = zeros(1, length(pot.ddom)); % index vector
+    p1 = zeros(I,J);
+    for i=1:I
+        keep_iv = ind2subv(nodesizes(dkeep), i);
+        iv(keep_map) = keep_iv;
+        for j=1:J
+            sum_iv = ind2subv(nodesizes(dsumover), j);
+            iv(sum_map) = sum_iv;
+            k = subv2ind(nodesizes(pot.ddom), iv);
+            potc = struct(pot.scgpotc{k}); % violate object privacy
+            p1(i,j) = potc.p;
+        end
+    end
+    p2 = sum(p1,2);
+    p2 = p2 + (p2==0)*eps;
+    
+    margscpot = cell(1, I);
+    compscpot = cell(1, I*J);
+    iv = zeros(1, length(pot.ddom)); % index vector
+    for i=1:I
+        margscpot{i} = scgcpot(0, 0, p2(i));
+        keep_iv = ind2subv(nodesizes(dkeep), i);
+        iv(keep_map) = keep_iv;
+        for j=1:J
+            sum_iv = ind2subv(nodesizes(dsumover), j);
+            iv(sum_map) = sum_iv;
+            k = subv2ind(nodesizes(pot.ddom), iv);
+            q = p1(i,j)/p2(i);
+            compscpot{k} = scgcpot(0, 0, q);
+        end
+    end
+    
+    margpot = scgpot(dkeep, [], [], nodesizes, margscpot);
+    comppot = scgpot(pot.ddom, [], [], nodesizes,compscpot);
+    return;
+end
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% head of the potential is not empty %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+dsize = pot.dsize;
+compscpot = cell(1, dsize);
+
+fmaskh = find_equiv_posns(margcheaddom, compctaildom);
+fmaskt = find_equiv_posns(margctaildom, compctaildom);
+
+fh = block(fmaskh, compctailsizes);
+ft = block(fmaskt, compctailsizes);
+
+
+if ~isempty(margcheaddom)
+    for i=1:dsize
+        potc = struct(pot.scgpotc{i});
+        q = 1;
+        p = potc.p;
+        [A1, A2, B1, B2, C11, C12, C21, C22] = partition_matrix_vec_3(potc.A, potc.B, potc.C, margcheaddom, compcheaddom, nodesizes);
+
+        if ~isempty(margcheaddom)
+            margscpot{i} = scgcpot(margcheadsize, margctailsize, p, A1, B1, C11);
+        else
+            margscpot{i} = scgcpot(margcheadsize, margctailsize, p);
+        end 
+    
+        if ~isempty(compcheaddom)
+            if ~isempty(margcheaddom)
+                E = A2 - C21*pinv(C11)*A1;
+                tmp1 = C21*pinv(C11);
+                tmp2 = B2 - C21*pinv(C11)*B1;
+                F = zeros(compcheadsize, compctailsize);
+                F(:, fh) = tmp1;
+                F(:, ft) = tmp2;
+                G = C22 - C21*pinv(C11)*C12;
+            else
+                E = A2;
+                F = B2;
+                G = C22;
+            end
+            compscpot{i} = scgcpot(compcheadsize, compctailsize, q, E, F, G);
+        else
+            compscpot{i} = scgcpot(compcheadsize, 0, q);
+        end
+        if isempty(margcheaddom)
+            margpot = scgpot(margddom, [], [], nodesizes, margscpot);
+        else
+            margpot = scgpot(margddom, margcheaddom, margctaildom, nodesizes, margscpot);
+        end
+    end
+else
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    % Marginalisation took place over all head variables.                               %
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    % Calculate the strong marginal %
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    margpot = marginalize_pot(pot,keep);
+    mPot    = struct(margpot); 
+    for i =1:dsize
+        potc = struct(pot.scgpotc{i});  
+        % Get the probability of the original potential % 
+	q = potc.p;
+         
+        % Get the configuration defined by the index i%
+        config = ind2subv(pot.dsizes,i);
+        
+        % Calculate the corresponding configuration in the marginal potential
+        if isempty(margpot.dsizes)
+            % keep == []
+	    indMargPot = 1;
+        else
+            equivPos   = find_equiv_posns(dkeep,pot.ddom);
+            indMargPot = subv2ind(margpot.dsizes,config(equivPos));
+        end
+        % Figure out the corresponding marginal potential
+        mPotC = struct(mPot.scgpotc{indMargPot});
+        p = mPotC.p;
+        if p == 0
+            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+            % The following assignment is correct as p is only zero if q is also zero %
+            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+            compscpot{i} = scgcpot(compcheadsize,compctailsize,0,potc.A,potc.B,potc.C);
+        else
+            compscpot{i} = scgcpot(compcheadsize,compctailsize,q/p,potc.A,potc.B,potc.C);
+        end
+    end
+end
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Put all components in one potential %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+if isempty(compcheaddom)
+    comppot = scgpot(compddom, [], [], nodesizes,compscpot);
+else
+    comppot = scgpot(compddom, compcheaddom, compctaildom, nodesizes,compscpot);
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/direct_combine_pots.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,161 @@
+function pot = direct_combine_pots(pot1, pot2)
+% DIRECTED_COMBINE_POTS The combination operation corresponds to ordinary composition of conditional distributions. 
+% In some sense is similar to that of forming disjoint union of set.
+% pot = direct_combine_pots(pot1, pot2)
+
+% directed combine can be performed under the conditon that the head node set of pot1 is disjoint from the domain of 
+% pot2 or vice versa. if the last conditon was satisfied we exchange the pot1 and pot2 firstly then perform the operation.
+% If neither of them was satified the directed combine is undifined.
+
+
+if isempty( myintersect(pot1.domain, pot2.cheaddom) )
+    pot1 = pot1;
+    pot2 = pot2;
+elseif  isempty( myintersect(pot2.domain, pot1.cheaddom))
+    temppot = pot1;
+    pot1 = pot2;
+    pot2 = temppot;
+else
+    assert(0);
+    return;
+end
+
+domain = myunion(pot1.domain, pot2.domain);
+nodesizes = zeros(1,max(domain));
+nodesizes(pot2.ctaildom) = pot2.ctailsizes;
+nodesizes(pot2.cheaddom) = pot2.cheadsizes;
+nodesizes(pot2.ddom) = pot2.dsizes;
+nodesizes(pot1.ctaildom) = pot1.ctailsizes;
+nodesizes(pot1.cheaddom) = pot1.cheadsizes;
+nodesizes(pot1.ddom) = pot1.dsizes;
+
+dom_u = mysetdiff(pot2.ctaildom, pot1.cheaddom);
+if ~isempty(dom_u) & ~mysubset(dom_u, pot1.ctaildom)
+    pot1 = extension_pot(pot1, [], [], dom_u, nodesizes(dom_u));
+end
+
+dom_u = myunion(pot1.cheaddom, pot1.ctaildom);
+if ~isempty(dom_u) & ~mysubset(dom_u, pot2.ctaildom)
+    pot2 = extension_pot(pot2, [], [], dom_u, nodesizes(dom_u));
+end
+
+
+cheaddom = myunion(pot1.cheaddom, pot2.cheaddom);
+ctaildom = mysetdiff(myunion(pot1.ctaildom, pot2.ctaildom), cheaddom);
+cdom = myunion(cheaddom, ctaildom);
+ddom = mysetdiff(domain, cdom);
+dsizes = nodesizes(ddom);
+dsize = prod(nodesizes(ddom));
+cheadsizes = nodesizes(cheaddom);
+cheadsize = sum(nodesizes(cheaddom));
+ctailsizes = nodesizes(ctaildom);
+ctailsize = sum(nodesizes(ctaildom));
+
+r1 = pot1.cheadsize;
+s1 = pot1.ctailsize;
+scpot = cell(1, dsize);
+mask1 = [];
+mask2 = [];
+if ~isempty(pot1.ddom)
+    mask1 = find_equiv_posns(pot1.ddom, ddom);
+end
+if ~isempty(pot2.ddom)
+    mask2 = find_equiv_posns(pot2.ddom, ddom);
+end
+cmask1 = [];
+cmask2 = [];
+if ~isempty(pot1.cheaddom)
+    cmask1 = find_equiv_posns(pot1.cheaddom, cheaddom);
+end
+if ~isempty(pot2.cheaddom)
+    cmask2 = find_equiv_posns(pot2.cheaddom, cheaddom);
+end
+
+u1 = block(cmask1, cheadsizes);
+u2 = block(cmask2, cheadsizes);
+
+fmaskh = find_equiv_posns(pot1.cheaddom, pot2.ctaildom);
+fmaskt = find_equiv_posns(pot1.ctaildom, pot2.ctaildom);
+
+fh = block(fmaskh, pot2.ctailsizes);
+ft = block(fmaskt, pot2.ctailsizes);
+
+for i=1:dsize
+    sub = ind2subv(dsizes, i);
+    sub1 = sub(mask1);
+    sub2 = sub(mask2);
+    ind1 = subv2ind(pot1.dsizes, sub1);
+    ind2 = subv2ind(pot2.dsizes, sub2);
+    
+    if isempty(ind1)
+        ind1 = 1;
+    end
+    if isempty(ind2)
+        ind2 = 1;
+    end
+    potc1 = struct(pot1.scgpotc{ind1});
+    potc2 = struct(pot2.scgpotc{ind2});
+    p = potc1.p;
+    q = potc2.p;
+    ro = p*q;
+    
+    A = potc1.A;
+    B = potc1.B;
+    C = potc1.C;
+   
+    E = potc2.A;
+    F = potc2.B;
+    G = potc2.C;
+    
+    F1 = F(:, fh);
+    F2 = F(:, ft);
+    
+    if ~isempty(F1)
+        K1 = F1*A;
+        K2 = F1*B;
+        FCF = F1*C*F1';
+        FC = F1*C;
+        CFT = C*F1';
+    else
+        K1 = zeros(size(E));
+        K2 = zeros(size(F2));
+        FCF = zeros(size(G));
+        FC = zeros(size(C, 1), size(G, 2));
+        CFT = zeros(size(G, 2), size(C, 1));
+    end
+    
+    
+    U = zeros(cheadsize,1); 
+    W = zeros(cheadsize,cheadsize);
+    V = zeros(cheadsize,ctailsize); 
+    
+    if cheadsize > 0
+        U(u1) = A;
+        U(u2) = E + K1;
+        W(u1, u1) = C;
+        W(u2, u2) = G + FCF;
+        W(u1, u2) = CFT;
+        W(u2, u1) = FC;
+    else
+        U = zeros(cheadsize,1); 
+        W = zeros(cheadsize,cheadsize); 
+    end
+    if cheadsize > 0 | ctailsize > 0
+        if ~isempty(u1)
+            V(u1, :) = B;
+        else
+            V(u1, :) = zeros(potc1.cheadsize, ctailsize);
+        end
+        if ~isempty(u2)
+            V(u2, :) = F2 + K2;
+        else
+            V(u2, :) = zeros(potc2.cheadsize, ctailsize);
+        end
+    else
+        V = zeros(cheadsize,ctailsize); 
+    end
+
+    scpot{i} = scgcpot(cheadsize, ctailsize, ro, U, V, W);
+end
+
+pot = scgpot(ddom, cheaddom, ctaildom, nodesizes, scpot);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/extension_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,55 @@
+function pot = extension_pot(oldpot, ddom_u, dsizes, ctaildom_u, csizes)
+% EXTENSION_POT Extense a stable CG potential.
+% pot = extension_pot(oldpot, ddom_u, ctaildom_u, dsizes, csizes)
+% ddom_u Added discrete nodes
+% ctaildom_u Added continuous tail nodes
+% csizes is the size of the tail nodes.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% A CG potential can be extended by adding discrete variables to its %
+% domain of continuous variables to its tail                         %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ddom = myunion(oldpot.ddom, ddom_u);
+ctaildom = myunion(oldpot.ctaildom, ctaildom_u);
+cheaddom = oldpot.cheaddom;
+udom = myunion(ddom_u, ctaildom_u);
+domain = myunion(oldpot.domain, udom);
+
+ns = zeros(1,max(domain));
+ns(ddom_u) = dsizes;
+ns(ctaildom_u) = csizes;
+ns(oldpot.ddom) = oldpot.dsizes;
+ns(oldpot.cheaddom) = oldpot.cheadsizes;
+ns(oldpot.ctaildom) = oldpot.ctailsizes;
+
+dsizes = ns(ddom);
+dsize = prod(ns(ddom));
+cheadsizes = ns(cheaddom);
+cheadsize = sum(ns(cheaddom));
+ctailsizes = ns(ctaildom);
+ctailsize = sum(ns(ctaildom));
+
+BZ = zeros(cheadsize, ctailsize);
+potarray = cell(1, dsize);
+mask = find_equiv_posns(oldpot.ddom, ddom);
+
+tmask = find_equiv_posns(oldpot.ctaildom, ctaildom);
+tu = block(tmask, ctailsizes);
+
+for i=1:dsize
+    sub1 = ind2subv(dsizes, i);
+    sub2 = sub1(mask);
+    ind = subv2ind(oldpot.dsizes, sub2);
+    if isempty(ind)
+        ind = 1;
+    end
+    potc = struct(oldpot.scgpotc{ind});
+    p = potc.p;
+    B = BZ;
+    if ~isempty(B)
+        B(:, tu) = potc.B;
+    end
+    potarray{i} = scgcpot(cheadsize, ctailsize, p, potc.A, B, potc.C);
+end
+
+pot = scgpot(ddom, cheaddom, ctaildom, ns,potarray);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/marginalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,92 @@
+function smallpot = marginalize_pot(bigpot, keep)
+% MARGINALIZE_POT Marginalize a cgpot onto a smaller domain.
+% smallpot = marginalize_pot(bigpot, keep)
+
+sumover = mysetdiff(bigpot.domain, keep);
+cdom = myunion(bigpot.cheaddom, bigpot.ctaildom);
+csumover = myintersect(sumover, bigpot.cheaddom);
+dsumover = myintersect(sumover, bigpot.ddom);
+
+dkeep = myintersect(keep, bigpot.ddom);
+ckeep = myintersect(keep, bigpot.cheaddom);
+cheaddom = myintersect(keep, bigpot.cheaddom);
+
+assert(isempty(myintersect(csumover,bigpot.ctaildom)));
+ns = zeros(1, max(bigpot.domain));
+ns(bigpot.ddom) = bigpot.dsizes;
+ns(bigpot.cheaddom) = bigpot.cheadsizes;
+ns(bigpot.ctaildom) = bigpot.ctailsizes;
+
+
+if sum(ns(csumover)) > 0
+    for i=1:bigpot.dsize
+      bigpot.scgpotc{i} = marginalize_pot(bigpot.scgpotc{i}, ckeep, csumover, ns);
+    end
+end
+
+if (isequal(csumover, cheaddom))
+    bigpot.ctaildom = [];
+end
+% If we are not marginalizing over any discrete nodes, we are done.
+if prod(ns(dsumover))==1
+  smallpot = scgpot(dkeep, cheaddom, bigpot.ctaildom, ns, bigpot.scgpotc);
+  return;
+end
+
+if (~isempty(bigpot.ctaildom))
+    assert(0);
+    return;
+end
+
+I = prod(ns(dkeep));
+J = prod(ns(dsumover));
+C = sum(ns(ckeep));   
+sum_map = find_equiv_posns(dsumover, bigpot.ddom);
+keep_map = find_equiv_posns(dkeep, bigpot.ddom);
+iv = zeros(1, length(bigpot.ddom)); % index vector
+
+p1 = zeros(I,J);
+A1 = zeros(C,J,I);
+C1 = zeros(C,C,J,I);
+for i=1:I
+  keep_iv = ind2subv(ns(dkeep), i);
+  iv(keep_map) = keep_iv;
+  for j=1:J
+    sum_iv = ind2subv(ns(dsumover), j);
+    iv(sum_map) = sum_iv;
+    k = subv2ind(ns(bigpot.ddom), iv);
+    pot = struct(bigpot.scgpotc{k}); % violate object privacy
+    p1(i,j) = pot.p;
+    if C > 0 % so mu1 and Sigma1 are non-empty
+      A1(:,j,i) = pot.A;
+      C1(:,:,j,i) = pot.C;
+    end
+  end
+end
+
+% Collapse the mixture of Gaussians
+coef = mk_stochastic(p1); % coef must be convex combination
+%keyboard
+p2 = sum(p1,2);
+if (all(p2 == 0))
+    p2 = p2 + (p2==0)*eps;
+end
+A = [];
+S = [];
+
+pot = cell(1,I);
+ctailsize = sum(ns(bigpot.ctaildom));
+tB = zeros(C, ctailsize);
+for i=1:I
+  if C > 0
+    [A, S] = collapse_mog(A1(:,:,i), C1(:,:,:,i), coef(i,:));
+  end
+  p = p2(i);
+  pot{i} = scgcpot(C, ctailsize, p, A, tB, S);
+end
+
+smallpot = scgpot(dkeep, ckeep, bigpot.ctaildom, ns, pot);
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/normalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function [pot, loglik] = normalize_pot(pot)
+% NORMALIZE_POT Convert the SCG potential Pr(X,E) into Pr(X|E) and return log Pr(E).
+% [pot, loglik] = normalize_pot(pot)
+
+% Marginalize down to [], so that the normalizing constant becomes Pr(E)
+temp = marginalize_pot(pot, []);
+[temp2, loglik] = normalize_pot(temp.scgpotc{1});
+  
+% Adjust scale factor to reflect the fact that the pot now represents Pr(X | E) instead of Pr(X,E).
+
+scale = -loglik;
+if 1
+    for i=1:pot.dsize
+        pot.scgpotc{i} = rescale_pot( pot.scgpotc{i}, scale);
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/pot_to_marginal.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+function m = pot_to_marginal(pot)
+% POT_TO_MARGINAL Convert a scgpot to a marginal structure.
+% m = pot_to_marginal(pot)
+
+assert(isempty(pot.ctaildom))
+m.domain = pot.domain;
+n = pot.cheadsize;
+d = pot.dsize;
+
+if n==0
+  m.mu = [];
+  m.Sigma = [];
+else
+  m.mu = zeros(n, d);
+  m.Sigma = zeros(n, n, d);
+end
+%m.T = 0*myones(pot.dsizes);
+m.T = 0*myones(pot.dsize);
+for i=1:pot.dsize
+  potc = struct(pot.scgpotc{i}); % violate privacy of object
+  if n > 0
+    m.mu(:,i) = potc.A;
+    m.Sigma(:,:,i) = potc.C;
+  end
+  m.T(i) = potc.p;
+end     
+if isvector(m.T)
+  m.T = m.T(:)';
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/recursive_combine_pots.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+function pot = recursive_combine_pots(pot1, pot2)
+% RECURSIVE_COMBINE_POTS recursive combine two potentials
+% pot = recursive_combine_pots(pot1, pot2)
+
+pot1 = reduce_pot(pot1);
+pot2 = reduce_pot(pot2);
+% Recursion is stopped, if recusive-combination is defined by direct combination, 
+% i.e. if the domain of one potential is disjoint from the head of the other.
+if (isempty(myintersect(pot1.domain,pot2.cheaddom))|...
+    isempty(myintersect(pot1.cheaddom,pot2.domain)))    
+    pot = direct_combine_pots(pot1,pot2);
+else 
+    % Test wether one of the set-differences is not empty 
+    % as defined in Lauritzen99 "Stable Local Computation with Conditional Gaussian Distributions"
+    % on page 9
+    D12 = mysetdiff(pot1.cheaddom, pot2.domain);
+    D21 = mysetdiff(pot2.cheaddom, pot1.domain);
+    if (isempty(D12) & isempty(D21))
+       assert(0,'Recursive combination is not defined');
+    end
+
+    if ~isempty(D12)
+        % Calculate the complementary potential for the set 
+        % D1\D12 as defined in Lauritzen 99, page 9
+    keep = mysetdiff(pot1.domain,D12);
+        [margpot, comppot] = complement_pot(pot1,keep);
+        margpot = reduce_pot(margpot);
+        comppot = reduce_pot(comppot);
+        pot = direct_combine_pots( recursive_combine_pots(margpot, pot2), comppot);
+    elseif ~isempty(D21)
+        keep = mysetdiff(pot2.domain,D21);
+        [margpot, comppot] = complement_pot(pot2,D21);
+        margpot = reduce_pot(margpot);
+        comppot = reduce_pot(comppot);
+        pot = direct_combine_pots( recursive_combine_pots(pot1, margpot), comppot);
+    end
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/reduce_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,53 @@
+function [reduced_pot,successful] = reduce_pot(pot,tailnodes)
+% Executes the reduce operation defined in
+% Stable Local Computation with Conditional Gaussian Distributions
+% Steffen L. Lauritzen
+% Frank Jensen
+% September 1999
+% The potential pot is reduced if B contains any zero columns
+% The test are restricted to the positions in tailnodes.
+% Any columns successfully deleted are entered in the array successful
+if nargin < 2
+    tailnodes = pot.ctaildom;
+end
+
+successful = [];
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Keep track of remaining tailnodes %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+rem_tailnodes = pot.ctaildom;
+for i = tailnodes
+    pos = find(i==rem_tailnodes);
+    successful_red = [pos];
+    red_scgcpot = cell(1,pot.dsize);
+    j = 1;
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    % Test whether all components of pot.scgpotc can be reduced %
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    while ((j <= pot.dsize) & ~isempty(successful_red))
+        [cpot,successful_red] = reduce_pot(pot.scgpotc{j},pos);
+        red_scgcpot{j} = cpot;
+        j = j + 1;
+    end
+
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    % If i is a reducible tailnode, then reduce the potential %
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+    if ~isempty(successful_red)
+        successful = [successful i];
+        pot.scgpotc = red_scgcpot;
+        rem_tailnodes = mysetdiff(rem_tailnodes,i);
+    end;
+end
+
+pot.ctaildom = rem_tailnodes;
+positions = find_equiv_posns(rem_tailnodes,pot.ctaildom);
+pot.ctailsizes = pot.ctailsizes(positions);
+pot.ctailsize = sum(pot.ctailsizes);
+pot.domain = mysetdiff(pot.domain,successful);
+reduced_pot = pot;
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@scgpot/scgpot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function pot = scgpot(ddom, cheaddom, ctaildom, node_sizes, scgpotc)
+% SCGPOT Make a stable CG potential.
+% pot = scgpot(ddom, cheaddom, ctaildom, node_sizes, scgpotc)
+%
+% ddom is discrete nodes contains in the potential
+% cheaddom is head nodes constains in the potential
+% ctaildom is tail nodes contains in the potential
+% node_sizes(i) is the size of the i'th node.
+% scgpotc is list of scgcpot objects.
+
+pot.ddom = ddom;
+pot.cheaddom = cheaddom;
+pot.ctaildom = ctaildom;
+pot.domain = myunion(ddom, myunion(cheaddom, ctaildom));
+pot.dsizes = node_sizes(pot.ddom);
+pot.dsize = prod(node_sizes(pot.ddom));
+pot.cheadsizes = node_sizes(pot.cheaddom);
+pot.cheadsize = sum(node_sizes(pot.cheaddom));
+pot.ctailsizes = node_sizes(pot.ctaildom);
+pot.ctailsize = sum(node_sizes(pot.ctaildom));
+
+if nargin < 5
+    scgpotc = cell(1, pot.dsize);
+    for i=1:pot.dsize
+        scgpotc{i} = scgcpot(pot.cheadsize, pot.ctailsize);
+    end
+end
+pot.scgpotc = scgpotc;              
+
+pot = class(pot, 'scgpot');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@upot/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+/approxeq_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/display.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/divide_by_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/marginalize_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/multiply_by_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/normalize_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/pot_to_marginal.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/upot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/upot_to_opt_policy.m/1.1.1.1/Wed May 29 15:59:58 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@upot/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/potentials/@upot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@upot/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@upot/approxeq_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function p = approxeq_pot(A, B, tol)
+
+if nargin < 3, tol = 1e-3; end
+
+p = approxeq(A.p, B.p, tol) & approxeq(A.u, B.u, tol);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@upot/display.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function display(pot)
+
+disp('utility potential object');
+disp(struct(pot));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@upot/divide_by_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function Tbig = divide_by_pot(Tbig, Tsmall)
+% DIVIDE_BY_POT Tbig /= Tsmall
+% Tbig = divide_by_pot(Tbig, Tsmall)
+%
+% Tsmall's domain must be a subset of Tbig's domain.
+
+smallp = extend_domain_table(Tsmall.p, Tsmall.domain, Tsmall.sizes, Tbig.domain, Tbig.sizes);
+smallp = smallp + (smallp==0);
+Tbig.p = Tbig.p ./ smallp;
+
+smallu = extend_domain_table(Tsmall.u, Tsmall.domain, Tsmall.sizes, Tbig.domain, Tbig.sizes);
+Tbig.u = Tbig.u - smallu;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@upot/marginalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function smallpot = marginalize_pot(bigpot, onto, maximize)
+% MARGINALIZE_POT Marginalize a upot onto a smaller domain.
+% smallpot = marginalize_pot(bigpot, onto, maximize)
+%
+% The maximize argument is ignored
+
+numer = marg_table(bigpot.p .* bigpot.u, bigpot.domain, bigpot.sizes, onto);
+denom = marg_table(bigpot.p, bigpot.domain, bigpot.sizes, onto);
+
+p = denom;
+% replace 0s by 1s before dividing. This is valid since demon(i) = 0 => numer(i) = 0
+denom = denom + (denom == 0); 
+u = numer ./ denom;
+
+ns = zeros(1, max(bigpot.domain));
+ns(bigpot.domain) = bigpot.sizes;
+
+smallpot = upot(onto, ns(onto), p, u);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@upot/multiply_by_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function Tbig = multiply_by_pot(Tbig, Tsmall)
+% MULTIPLY_BY_POT Tbig *= Tsmall
+% Tbig = multiply_by_pot(Tbig, Tsmall)
+%
+% Tsmall's domain must be a subset of Tbig's domain.
+
+smallp = extend_domain_table(Tsmall.p, Tsmall.domain, Tsmall.sizes, Tbig.domain, Tbig.sizes);
+Tbig.p = Tbig.p .* smallp;
+
+smallu = extend_domain_table(Tsmall.u, Tsmall.domain, Tsmall.sizes, Tbig.domain, Tbig.sizes);
+Tbig.u = Tbig.u + smallu;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@upot/normalize_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function [pot, loglik] = normalize_pot(pot)
+% NORMALIZE_POT Convert the probability part of a utility potential
+% [pot, loglik] = normalize_pot(pot)
+
+[pot.p, lik] = normalise(pot.p);
+%pot.u = pot.u - sum(pot.u(:));
+%pot.u = pot.u ./ sum(pot.u(:)); % same as normalise(pot.u)
+%pot.u = normalise(pot.u);
+%pot.u = pot.u / 726.8121;
+pot.u = pot.u / 10;
+loglik = log(lik + (lik==0)*eps);
+
+      
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@upot/pot_to_marginal.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function m = pot_to_marginal(pot)
+% POT_TO_MARGINAL Convert a upot to a structure.
+% m = pot_to_marginal(pot)
+
+m.domain = pot.domain;
+m.T = pot.p;
+m.U = pot.u;
+
+    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@upot/upot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function pot = upot(domain, sizes, p, u)
+% UPOT Make a discrete utility potential.
+% pot = upot(domain, sizes, p, u)
+%
+% sizes(i) is the size of the i'th domain element.
+% p defaults to all 1s, u defaults to all 0s.
+
+if nargin < 3, p = myones(sizes); end
+if nargin < 4, u = 0*myones(sizes); end
+
+pot.domain = domain;
+pot.p = myreshape(p, sizes);
+pot.u = myreshape(u, sizes);
+pot.sizes = sizes(:)';
+pot = class(pot, 'upot');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/@upot/upot_to_opt_policy.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function [policy, EU] = upot_to_opt_policy(pot)
+% UPOT_TO_OPT_POLICY Compute an optimal deterministic policy given a utility potential
+% [policy, EU] = upot_to_opt_policy(pot)
+%
+% policy(a,b, ..., z) = P(do z | a, b, ..), which will be a delta function
+% EU is the contraction of this potential, i.e., P .* U
+
+sz = pot.sizes; % mysize(pot.p);
+if isempty(sz)
+  EU = pot.u;
+  policy = [];
+  return;
+end
+
+parent_size = prod(sz(1:end-1));
+self_size = sz(end); 
+C = pot.p .* pot.u; % contraction
+C = reshape(C, parent_size, self_size);
+policy = zeros(parent_size, self_size);
+for i=1:parent_size
+  act = argmax(C(i,:));
+  policy(i, act) = 1;
+end
+policy = myreshape(policy, sz);
+EU = sum(C(:));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/CPD_to_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function pot = CPD_to_pot(pot_type, CPD, domain, ns, cnodes, evidence)
+% CPD_TO_POT Convert a CPD to a potential of the specified form, incorporating any evidence
+% pot = CPD_to_pot(pot_type, CPD, domain, node_sizes, cnodes, evidence)
+%
+% pot_type is one of 'd', 'g', or 'cg'.
+% domain is the domain of CPD.
+% node_sizes(i) is the size of node i.
+% cnodes = the cts nodes
+% evidence{i} is the evidence on the i'th node.
+
+switch pot_type
+ case 'd',
+  pot = CPD_to_dpot(CPD, domain, ns, cnodes, evidence);
+ case 'g',
+  pot = CPD_to_cpot(CPD, domain, ns, cnodes, evidence);
+ case 'cg',
+  pot = CPD_to_cgpot(CPD, domain, ns, cnodes, evidence);
+ otherwise,
+  error(['can''t handle pot_type ' pot_type]);
+end
+              
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+/CPD_to_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/README/1.1.1.1/Wed May 29 15:59:58 2002//
+/check_for_cd_arcs.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/determine_pot_type.m/1.1.1.1/Wed May 29 15:59:58 2002//
+/genops.c/1.1.1.1/Sat Jul 28 15:43:40 2001//
+/mk_initial_pot.m/1.1.1.1/Wed May 29 15:59:58 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+A D/@cgpot////
+A D/@cpot////
+A D/@dpot////
+A D/@mpot////
+A D/@scgcpot////
+A D/@scgpot////
+A D/@upot////
+A D/Old////
+A D/Tables////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/potentials
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Old/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+/comp_eff_node_sizes.m/1.1.1.1/Wed May 29 15:59:58 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Old/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/potentials/Old
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Old/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Old/comp_eff_node_sizes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function ens = comp_eff_node_sizes(ns, cnodes, ev, domain)
+
+dnodes = mysetdiff(1:length(ns), cnodes);
+odom = domain(~isemptycell(evidence(domain)));
+cdom = myintersect(cnodes, domain);
+ddom = myintersect(dnodes, domain);
+cobs = myintersect(cdom, odom);
+dobs = myintersect(ddom, odom);
+ens = ns; 
+ens(cobs) = 0;
+ens(dobs) = 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/README	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,100 @@
+The following kinds of potentials are supported
+- dpot: discrete
+- upot: utility
+- mpot: Gaussian in moment form
+- cpot: Gaussian in canonical form
+- cgpot: conditional (mixture) Gaussian, a list of mpots/cpot
+- scgpot: stable conditional Gaussian, a list of scgcpots
+- scgcpot: just used by scgpot
+
+Many of these are described in the following book
+
+@book{Cowell99,
+  author = "R. G. Cowell and A. P. Dawid and S. L. Lauritzen and D. J. Spiegelhalter",
+  title = "Probabilistic Networks and Expert Systems",
+  year = 1999,
+  publisher = "Springer"
+}
+
+CPD_to_pot converts P(Z|A,B,...) to phi(A,B,...,Z).
+
+A table is like a dpot, except it is a structure, not an object.
+Code that uses tables is faster but less flexible.
+
+                         -----------
+
+A potential is a joint probability distribution on a set of nodes,
+which we call the potential's domain (which is always sorted).
+A potential supports the operations of multiplication and
+marginalization.
+
+If the nodes are discrete, the potential can be represented as a table
+(multi-dimensional array). If the nodes are Gaussian, the potential
+can be represented as a quadratic form. If there are both discrete and
+Gaussian nodes, we use a table of quadratic forms. For details on the
+Gaussian case, see below.
+
+For discrete potentials, the 'sizes' field specifies the number of
+values each node in the domain can take on. For continuous potentials,
+the 'sizes' field specifies the block-size of each node.
+
+If some of the nodes are observed, extra complications arise.  We
+handle the discrete and continuous cases differently.  Suppose the
+domain is [X Y], with sizes [6 2], where X is observed to have value x.
+In the discrete case, the potential will have many zeros in it
+(T(X,:) will be 0 for all X ~= x), which can be inefficient. Instead,
+we set sizes to [1 2], to indicate that X has only one possible value
+(namely x). For continuous nodes, we set sizes = [0 2], to indicate that X no
+longer appears in the mean vector or covariance matrix (we must avoid
+0s in Sigma, lest it be uninvertible). When a potential is created, we
+assume the sizes of the nodes have been adjusted to include the
+evidence. This is so that the evidence can be incorporated at the
+outset, and thereafter the inference algorithms can ignore it.
+
+                         ------------
+
+A Gaussian potential can be represented in terms of its
+moment characteristics (mu, Sigma, logp), or in terms of its canonical
+characteristics (g, h, K). Although the moment characteristics are
+more familiar, it turns out that canonical characteristics are
+more convenient for the junction tree algorithm, for the same kinds of
+reasons why backwards inference in an LDS uses the information form of
+the Kalman filter (see Murphy (1998a) for a discussion).
+
+When working with *conditional* Gaussian potentials, the method proposed
+by Lauritzen (1992), and implemented here, requires converting from
+canonical to moment form before marginalizing the discrete variables,
+and converting back from moment to canonical form before
+multiplying/dividing. A new algorithm, due to Lauritzen and Jensen
+(1999), works exclusively in moment form, and
+hence is more numerically stable. It can also handle 0s in the
+covariance matrix, i.e., deterministic relationships between cts
+variables. However, it has not yet been implemented,
+since it requires major changes to the jtree algorithm.
+
+In Murphy (1998b) we extend Lauritzen (1992) to handle
+vector-valued nodes. This means the vectors and matrices become block
+vectors and matrices. This manifests itself in the code as in the
+following example.
+Suppose we have a potential on nodes dom=[3,4,7] with block sizes=[2,1,3].
+Then nodes 3 and 7 correspond to blocks 1,3 which correspond to indices 1,2,4,5,6.
+>> find_equiv_posns([3 7], dom)=[1,3]
+>> block([1,3],blocks)=[1,2,4,5,6].
+
+For more details, see
+
+- "Filtering and Smoothing in Linear Dynamical Systems using the Junction Tree Algorithm",
+   K. Murphy, 1998a. UCB Tech Report.
+
+- "Inference and learning in hybrid Bayesian networks",
+   K. Murphy. UCB Technical Report CSD-98-990, 1998b.
+
+- "Propagation of probabilities, means and variances in mixed
+  graphical association models", S. L. Lauritzen, 1992, JASA 87(420):1098--1108.
+
+- "Causal probabilistic networks with both discrete and continuous variables",
+  K. G. Olesen, 1993. PAMI 3(15). This discusses implementation details.
+
+- "Stable local computation with Conditional Gaussian distributions",
+  S. Lauritzen and F. Jensen, 1999. Univ. Aalborg Tech Report R-99-2014.
+  www.math.auc.dk/research/Reports.html.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+/divide_by_sparse_table.c/1.1.1.1/Wed May 29 15:59:58 2002//
+/divide_by_table.c/1.1.1.1/Wed May 29 15:59:58 2002//
+/divide_by_table.m/1.1.1.1/Thu Aug  5 15:25:54 2004//
+/extend_domain_table.m/1.1.1.1/Wed Aug  4 15:53:26 2004//
+/marg_sparse_table.c/1.1.1.1/Wed May 29 15:59:58 2002//
+/marg_table.c/1.1.1.1/Wed May 29 15:59:58 2002//
+/marg_table.m/1.1.1.1/Wed Aug  4 15:51:48 2004//
+/marg_tableC.c/1.1.1.1/Wed Oct  2 15:39:02 2002//
+/marg_tableM.m/1.1.1.1/Tue Oct  1 17:39:08 2002//
+/mult_by_sparse_table.c/1.1.1.1/Wed May 29 15:59:58 2002//
+/mult_by_table.c/1.1.1.1/Tue Oct  1 21:23:22 2002//
+/mult_by_table.m/1.1.1.1/Wed Aug  4 15:52:58 2004//
+/mult_by_table2.m/1.1.1.1/Wed Oct  2 15:30:32 2002//
+/mult_by_tableC.c/1.1.1.1/Tue Oct  1 21:33:50 2002//
+/mult_by_tableM.m/1.1.1.1/Wed Oct  2 15:28:48 2002//
+/mult_by_table_global.m/1.1.1.1/Sun Sep 29 10:21:30 2002//
+/rep_mult.c/1.1.1.1/Wed May 29 15:59:58 2002//
+/repmat_and_mult.c/1.1.1.1/Tue Oct  1 21:20:00 2002//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/BNT/potentials/Tables
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/divide_by_sparse_table.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,126 @@
+/* divide_by_sparse_table.c ../potential/tables*/
+
+/******************************************/
+/* 6 input & 1 output                     */
+/* Big table    [0]                       */
+/* Big domain   [1]                       */
+/* big sizes    [2]                       */
+/* Small table  [3]                       */
+/* small domain [4]                       */
+/* small sizes  [5]                       */
+/*                                        */
+/* New big table[0]                       */
+/******************************************/
+
+#include <math.h>
+#include <stdlib.h>
+#include "mex.h"
+
+int compare(const void* src1, const void* src2){
+	int i1 = *(int*)src1 ;
+	int i2 = *(int*)src2 ;
+	return i1-i2 ;
+}
+
+void ind_subv(int index, const int *cumprod, int n, int *bsubv){
+	int i;
+
+	for (i = n-1; i >= 0; i--) {
+		bsubv[i] = ((int)floor(index / cumprod[i]));
+		index = index % cumprod[i];
+	}
+}
+
+int subv_ind(const int n, const int *cumprod, const int *subv){
+	int i, index=0;
+
+	for(i=0; i<n; i++){
+		index += subv[i] * cumprod[i];
+	}
+	return index;
+}
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex;
+	int     *mask, *result, *bir, *sir, *bjc, *sjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, value;
+
+	plhs[0] = mxDuplicateArray(prhs[0]);
+	pbDomain = mxGetPr(prhs[1]);
+	bdim = mxGetNumberOfElements(prhs[1]);
+	psDomain = mxGetPr(prhs[4]);
+	sdim = mxGetNumberOfElements(prhs[4]);
+
+	pbSize = mxGetPr(prhs[2]);
+	psSize = mxGetPr(prhs[5]);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	bpr = mxGetPr(plhs[0]);
+	bir = mxGetIr(plhs[0]);
+	bjc = mxGetJc(plhs[0]);
+	NZB = bjc[1];
+
+	spr = mxGetPr(prhs[3]);
+	sir = mxGetIr(prhs[3]);
+	sjc = mxGetJc(prhs[3]);
+	NZS = sjc[1];
+
+	if(sdim == 0){
+		value = *spr;
+		if(value == 0)value = 1;
+		for(i=0; i<NZB; i++){
+			bpr[i] /= value;
+		}	
+		return;
+	}
+
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare);
+		if(result){
+			position = result - sir;
+			bpr[i] /= spr[position];
+		}
+	}
+
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
Binary file _FullBNT/BNT/potentials/Tables/divide_by_sparse_table.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/divide_by_table.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,120 @@
+/* divide_by_table.c  ../potential/tables  */
+
+
+/******************************************/
+/* 6 input & 1 output                     */
+/* Big table    [0]                       */
+/* Big domain   [1]                       */
+/* big sizes    [2]                       */
+/* Small table  [3]                       */
+/* small domain [4]                       */
+/* small sizes  [5]                       */
+/*                                        */
+/* New big table[0]                       */
+/******************************************/
+
+#include "mex.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, j, count, NB, NS, siz_b, siz_s, ndim, temp;
+	int     *mask, *sx, *sy, *cpsy, *subs, *s, *cpsy2;
+	double  *pbDomain, *psDomain, *sp, *zp, *bs, value;
+
+	plhs[0] = mxDuplicateArray(prhs[0]);
+	zp = mxGetPr(plhs[0]);
+
+	siz_b = mxGetNumberOfElements(prhs[1]);
+	siz_s = mxGetNumberOfElements(prhs[4]);
+	pbDomain = mxGetPr(prhs[1]);
+	psDomain = mxGetPr(prhs[4]);
+
+	NB = mxGetNumberOfElements(prhs[0]);
+	NS = mxGetNumberOfElements(prhs[3]);
+	sp = mxGetPr(prhs[3]);
+
+	bs = mxGetPr(prhs[2]);
+
+	if(NS == 1){
+		value = *sp;
+		if(value == 0) value = 1;
+		for(i=0; i<NB; i++){
+			zp[i] /= value;
+		}
+		return;
+	}
+
+	if(NS == NB){
+		for(i=0; i<NB; i++){
+			value = sp[i];
+			if(value == 0) value = 1;
+			zp[i] /= value;
+		}
+		return;
+	}
+
+	mask = malloc(siz_s * sizeof(int));
+	count = 0;
+	for(i=0; i<siz_s; i++){
+		for(j=0; j<siz_b; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	ndim = siz_b;
+	sx = (int *)malloc(sizeof(int)*ndim);
+	sy = (int *)malloc(sizeof(int)*ndim);
+	for(i=0; i<ndim; i++){
+		sx[i] = (int)bs[i];
+		sy[i] = 1;
+	}
+	for(i=0; i<count; i++){
+		temp = mask[i];
+		sy[temp] = sx[temp];
+	}
+
+	s = (int *)malloc(sizeof(int)*ndim);
+	*(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1;
+	subs =   (int *)malloc(sizeof(int)*ndim);
+	cpsy2 =  (int *)malloc(sizeof(int)*ndim);
+	for(i = 0; i < ndim; i++){
+		subs[i] = 0;
+		s[i] = sx[i] - 1;
+	}
+			
+	for(i = 0; i < ndim-1; i++){
+		cpsy[i+1] = cpsy[i]*sy[i]--;
+		cpsy2[i] = cpsy[i]*sy[i];
+	}
+	cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]);
+
+	for(j=0; j<NB; j++){
+		value = *sp;
+		if(value == 0) value = 1;
+		*zp++ /= value;
+		for(i = 0; i < ndim; i++){
+			if(subs[i] == s[i]){
+				subs[i] = 0;
+				if(sy[i])
+					sp -= cpsy2[i];
+			}
+			else{
+				subs[i]++;
+				if(sy[i])
+					sp += cpsy[i];
+				break;
+			}
+		}
+	}
+	free(sx);
+	free(sy);
+	free(s);
+	free(cpsy);
+	free(subs);
+	free(cpsy2);
+    free(mask);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/divide_by_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function bigT = divide_by_table(bigT, bigdom, bigsz, smallT, smalldom, smallsz)
+% DIVIDE_BY_TABLE 
+% bigT = divide_by_table(bigT, bigdom, bigsz, smallT, smalldom, smallsz)
+%
+
+
+Ts = extend_domain_table(smallT, smalldom, smallsz, bigdom, bigsz);
+% Replace 0s by 1s before dividing. This is valid, Ts(i)=0 iff Tbig(i)=0.
+Ts = Ts + (Ts==0);
+%Tbig.T(:) = Tbig.T(:) ./ Ts(:);
+bigT(:) = bigT(:) ./ Ts(:);
+
Binary file _FullBNT/BNT/potentials/Tables/divide_by_table.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/extend_domain_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function B = extend_domain_table(A, smalldom, smallsz, bigdom, bigsz)
+% EXTEND_DOMAIN_TABLE Expand an array so it has the desired size.
+% B = extend_domain_table(A, smalldom, smallsz, bigdom, bigsz)
+%
+% A is the array with domain smalldom and sizes smallsz.
+% bigdom is the desired domain, with sizes bigsz.
+%
+% Example:
+% smalldom = [1 3], smallsz = [2 4], bigdom = [1 2 3 4], bigsz = [2 1 4 5],
+% so B(i,j,k,l) = A(i,k) for i in 1:2, j in 1:1, k in 1:4, l in 1:5
+
+if isequal(size(A), [1 1]) % a scalar
+  B = A; % * myones(bigsz);
+  return;
+end
+
+map = find_equiv_posns(smalldom, bigdom);
+sz = ones(1, length(bigdom));
+sz(map) = smallsz;
+B = myreshape(A, sz); % add dimensions for the stuff not in A
+sz = bigsz;
+sz(map) = 1; % don't replicate along A's dimensions
+B = myrepmat(B, sz(:)');
+                           
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/marg_sparse_table.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,181 @@
+/* marg_sparse_table.c ../potential/tables*/
+
+/******************************************/
+/* 5 input & 1 output                     */
+/* Big sparse table                       */
+/* Big domain                             */
+/* Big sizes                              */
+/* onto                                   */
+/* maximize, if missed, maximize=0        */
+/*                                        */
+/* small sparse table                     */
+/******************************************/
+
+#include <math.h>
+#include <stdlib.h>
+#include "mex.h"
+
+int compare(const void* src1, const void* src2){
+	int i1 = *(int*)src1 ;
+	int i2 = *(int*)src2 ;
+	return i1-i2 ;
+}
+
+void ind_subv(int index, const int *cumprod, int n, int *bsubv){
+	int i;
+
+	for (i = n-1; i >= 0; i--) {
+		bsubv[i] = ((int)floor(index / cumprod[i]));
+		index = index % cumprod[i];
+	}
+}
+
+int subv_ind(const int n, const int *cumprod, const int *subv){
+	int i, index=0;
+
+	for(i=0; i<n; i++){
+		index += subv[i] * cumprod[i];
+	}
+	return index;
+}
+
+mxArray* convert_table_to_sparse(const double *Table, const int *sequence, const int nzCounts, const int N){
+	mxArray *spTable;
+	int     i, temp, *irs, *jcs, count=0;
+	double  *sr;
+
+	spTable = mxCreateSparse(N, 1, nzCounts, mxREAL);
+    sr  = mxGetPr(spTable);
+    irs = mxGetIr(spTable);
+    jcs = mxGetJc(spTable);
+
+	jcs[0] = 0;
+	jcs[1] = nzCounts;
+
+	for(i=0; i<nzCounts; i++){
+		irs[i] = sequence[count];
+		count++;
+		temp = sequence[count];
+		sr[i] = Table[temp];
+		count++;
+	}
+	return spTable;
+}
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int        i, j, count, bdim, sdim, NS, NZB, position, bindex, sindex, maximize, nzCounts=0;
+	int        *mask, *sequence, *result, *bir, *bjc, *ssize, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double     *sTable, *pbDomain, *psDomain, *pbSize, *bpr, *spr;
+	const char *field_names[] = {"domain", "T", "sizes"};
+
+	if(nrhs < 5) maximize = 0;
+	else maximize = (int)mxGetScalar(prhs[4]);
+
+	bdim = mxGetNumberOfElements(prhs[1]);
+	sdim = mxGetNumberOfElements(prhs[3]);
+	pbSize = mxGetPr(prhs[2]);
+	pbDomain = mxGetPr(prhs[1]);
+	psDomain = mxGetPr(prhs[3]);
+	bpr = mxGetPr(prhs[0]);
+	bir = mxGetIr(prhs[0]);
+	bjc = mxGetJc(prhs[0]);
+	NZB = bjc[1];
+
+	if(sdim == 0){
+		plhs[0] = mxCreateSparse(1, 1, 1, mxREAL);
+		spr = mxGetPr(plhs[0]);
+		bir = mxGetIr(plhs[0]);
+		bjc = mxGetJc(plhs[0]);
+		*spr = 0;
+		*bir = 0;
+		bjc[0] = 0;
+		bjc[1] = 1;
+		if(maximize){
+			for(i=0; i<NZB; i++){
+				*spr = (*spr < bpr[i])? bpr[i] : *spr;
+			}
+		}
+		else{
+			for(i=0; i<NZB; i++){
+				*spr += bpr[i];
+			}
+		}	
+		return;
+	}
+
+	mask = malloc(sdim * sizeof(int));
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+		
+	sTable = malloc(NZB * sizeof(double));
+	sequence = malloc(NZB * 2 * sizeof(double));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+	ssize = malloc(sdim * sizeof(int));
+
+	NS = 1;
+	for(i=0; i<count; i++){
+		ssize[i] = (int)pbSize[mask[i]];
+		NS *= ssize[i];
+	}
+
+	for(i=0; i<NZB; i++)sTable[i] = 0;
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * ssize[i];
+	}
+
+	count = 0;
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sequence, nzCounts, sizeof(int)*2, compare);
+		if(result){
+			position = (result - sequence) / 2;
+			if(maximize) 
+				sTable[position] = (sTable[position] < bpr[i]) ? bpr[i] : sTable[position];
+			else sTable[position] += bpr[i];
+		}
+		else {
+			if(maximize) 
+				sTable[nzCounts] = (sTable[nzCounts] < bpr[i]) ? bpr[i] : sTable[nzCounts];
+			else sTable[nzCounts] += bpr[i];
+			sequence[count] = sindex;
+			count++;
+			sequence[count] = nzCounts;
+			nzCounts++;
+			count++;
+		}
+	}
+	
+	qsort(sequence, nzCounts, sizeof(int) * 2, compare);
+	plhs[0] = convert_table_to_sparse(sTable, sequence, nzCounts, NS);
+
+	free(sTable);
+	free(sequence);
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+	free(ssize);
+}
Binary file _FullBNT/BNT/potentials/Tables/marg_sparse_table.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/marg_table.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,175 @@
+/* marg_table.c  ../potential/tables     */
+
+
+/******************************************/
+/* 5 input & 1 output                     */
+/* Big table                              */
+/* Big domain                             */
+/* Big sizes                              */
+/* onto                                   */
+/* maximize, if missed, maximize=0        */
+/*                                        */
+/* small table                            */
+/******************************************/
+
+#include "mex.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, j, count, NB, NS, siz_b, siz_s, ndim, temp, maximize;
+	int     *mask, *sx, *sy, *cpsy, *subs, *s, *cpsy2, *ssize;
+	double  *pb, *ps, *bp, *sp, *pbd;
+
+
+	siz_b = mxGetNumberOfElements(prhs[1]);
+	siz_s = mxGetNumberOfElements(prhs[3]);
+	pb = mxGetPr(prhs[1]);
+	ps = mxGetPr(prhs[3]);
+
+	NB = mxGetNumberOfElements(prhs[0]);
+	bp = mxGetPr(prhs[0]);
+
+	pbd = mxGetPr(prhs[2]);
+
+	if(nrhs < 5) maximize = 0;
+	else maximize = (int)mxGetScalar(prhs[4]);
+
+	if(siz_s == 0){
+		plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
+		sp = mxGetPr(plhs[0]);
+		if(maximize){
+			for(i=0; i<NB; i++){
+				*sp = (*sp < bp[i])? bp[i] : *sp;
+			}
+		}
+		else{
+			for(i=0; i<NB; i++){
+				*sp += bp[i];
+			}
+		}
+		return;
+	}
+
+	mask = malloc(siz_s * sizeof(int));
+	ssize = malloc(siz_s * sizeof(int));
+	count = 0;
+	for(i=0; i<siz_s; i++){
+		for(j=0; j<siz_b; j++){
+			if(ps[i] == pb[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	ndim = siz_b;
+	sx = (int *)malloc(sizeof(int)*ndim);
+	sy = (int *)malloc(sizeof(int)*ndim);
+	for(i=0; i<ndim; i++){
+		sx[i] = (int)pbd[i];
+		sy[i] = 1;
+	}
+	for(i=0; i<siz_s; i++){
+		temp = mask[i];
+		sy[temp] = sx[temp];
+		ssize[i] = sx[temp];
+	}
+
+	NS = 1;
+	for(i=0; i<ndim; i++){
+		NS *= sy[i];
+	}
+
+	plhs[0] = mxCreateNumericArray(siz_s, ssize, mxDOUBLE_CLASS, mxREAL);
+	sp = mxGetPr(plhs[0]);
+
+	if(NS == 1){
+		if(maximize){
+			for(i=0; i<NB; i++){
+				*sp = (*sp < bp[i])? bp[i] : *sp;
+			}
+		}
+		else{
+			for(i=0; i<NB; i++){
+				*sp += bp[i];
+			}
+		}
+		free(mask);
+		free(sx);
+		free(sy);
+		free(ssize);
+		return;
+	}
+
+	if(NS == NB){
+		for(i=0; i<NB; i++) *sp++ = *bp++;
+		free(mask);
+		free(sx);
+		free(sy);
+		free(ssize);
+		return;
+	}
+
+	s = (int *)malloc(sizeof(int)*ndim);
+	*(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1;
+	subs =   (int *)malloc(sizeof(int)*ndim);
+	cpsy2 =  (int *)malloc(sizeof(int)*ndim);
+	for(i = 0; i < ndim; i++){
+		subs[i] = 0;
+		s[i] = sx[i] - 1;
+	}
+			
+	for(i = 0; i < ndim-1; i++){
+		cpsy[i+1] = cpsy[i]*sy[i]--;
+		cpsy2[i] = cpsy[i]*sy[i];
+	}
+	cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]);
+
+	if(maximize){
+		for(j=0; j<NB; j++){
+			*sp = (*sp < *bp)? *bp : *sp;
+			bp++;
+			for(i = 0; i < ndim; i++){
+				if(subs[i] == s[i]){
+					subs[i] = 0;
+					if(sy[i])
+						sp -= cpsy2[i];
+				}
+				else{
+					subs[i]++;
+					if(sy[i])
+						sp += cpsy[i];
+					break;
+				}
+			}
+		}
+	}
+	else{
+		for(j=0; j<NB; j++){
+			*sp += *bp++;
+			for(i = 0; i < ndim; i++){
+				if(subs[i] == s[i]){
+					subs[i] = 0;
+					if(sy[i])
+						sp -= cpsy2[i];
+				}
+				else{
+					subs[i]++;
+					if(sy[i])
+						sp += cpsy[i];
+					break;
+				}
+			}
+		}
+	}
+
+	free(sx);
+	free(sy);
+	free(s);
+	free(cpsy);
+	free(subs);
+	free(cpsy2);
+    free(mask);
+	free(ssize);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/marg_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,27 @@
+function smallT = marg_table(bigT, bigdom, bigsz, onto, maximize)
+% MARG_TABLE Marginalize a table
+% smallT = marg_table(bigT, bigdom, bigsz, onto, maximize)
+
+if nargin < 5, maximize = 0; end
+
+
+smallT = myreshape(bigT, bigsz); % make sure it is a multi-dim array
+sum_over = mysetdiff(bigdom, onto);
+ndx = find_equiv_posns(sum_over, bigdom);
+if maximize
+  for i=1:length(ndx)
+    smallT = max(smallT, [], ndx(i));
+  end
+else
+  for i=1:length(ndx)
+    smallT = sum(smallT, ndx(i));
+  end
+end
+
+
+ns = zeros(1, max(bigdom));
+%ns(bigdom) = mysize(bigT); % ignores trailing dimensions of size 1
+ns(bigdom) = bigsz;
+
+smallT = squeeze(smallT); % remove all dimensions of size 1
+smallT = myreshape(smallT, ns(onto)); % put back relevant dims of size 1
Binary file _FullBNT/BNT/potentials/Tables/marg_table.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/marg_tableC.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,175 @@
+/* marg_table.c  ../potential/tables     */
+
+
+/******************************************/
+/* 5 input & 1 output                     */
+/* Big table                              */
+/* Big domain                             */
+/* Big sizes                              */
+/* onto                                   */
+/* maximize, if missed, maximize=0        */
+/*                                        */
+/* small table                            */
+/******************************************/
+
+#include "mex.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, j, count, NB, NS, siz_b, siz_s, ndim, temp, maximize;
+	int     *mask, *sx, *sy, *cpsy, *subs, *s, *cpsy2, *ssize;
+	double  *pb, *ps, *bp, *sp, *pbd;
+
+
+	siz_b = mxGetNumberOfElements(prhs[1]);
+	siz_s = mxGetNumberOfElements(prhs[3]);
+	pb = mxGetPr(prhs[1]);
+	ps = mxGetPr(prhs[3]);
+
+	NB = mxGetNumberOfElements(prhs[0]);
+	bp = mxGetPr(prhs[0]);
+
+	pbd = mxGetPr(prhs[2]);
+
+	if(nrhs < 5) maximize = 0;
+	else maximize = (int)mxGetScalar(prhs[4]);
+
+	if(siz_s == 0){
+		plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
+		sp = mxGetPr(plhs[0]);
+		if(maximize){
+			for(i=0; i<NB; i++){
+				*sp = (*sp < bp[i])? bp[i] : *sp;
+			}
+		}
+		else{
+			for(i=0; i<NB; i++){
+				*sp += bp[i];
+			}
+		}
+		return;
+	}
+
+	mask = malloc(siz_s * sizeof(int));
+	ssize = malloc(siz_s * sizeof(int));
+	count = 0;
+	for(i=0; i<siz_s; i++){
+		for(j=0; j<siz_b; j++){
+			if(ps[i] == pb[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	ndim = siz_b;
+	sx = (int *)malloc(sizeof(int)*ndim);
+	sy = (int *)malloc(sizeof(int)*ndim);
+	for(i=0; i<ndim; i++){
+		sx[i] = (int)pbd[i];
+		sy[i] = 1;
+	}
+	for(i=0; i<siz_s; i++){
+		temp = mask[i];
+		sy[temp] = sx[temp];
+		ssize[i] = sx[temp];
+	}
+
+	NS = 1;
+	for(i=0; i<ndim; i++){
+		NS *= sy[i];
+	}
+
+	plhs[0] = mxCreateNumericArray(siz_s, ssize, mxDOUBLE_CLASS, mxREAL);
+	sp = mxGetPr(plhs[0]);
+
+	if(NS == 1){
+		if(maximize){
+			for(i=0; i<NB; i++){
+				*sp = (*sp < bp[i])? bp[i] : *sp;
+			}
+		}
+		else{
+			for(i=0; i<NB; i++){
+				*sp += bp[i];
+			}
+		}
+		free(mask);
+		free(sx);
+		free(sy);
+		free(ssize);
+		return;
+	}
+
+	if(NS == NB){
+		for(i=0; i<NB; i++) *sp++ = *bp++;
+		free(mask);
+		free(sx);
+		free(sy);
+		free(ssize);
+		return;
+	}
+
+	s = (int *)malloc(sizeof(int)*ndim);
+	*(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1;
+	subs =   (int *)malloc(sizeof(int)*ndim);
+	cpsy2 =  (int *)malloc(sizeof(int)*ndim);
+	for(i = 0; i < ndim; i++){
+		subs[i] = 0;
+		s[i] = sx[i] - 1;
+	}
+			
+	for(i = 0; i < ndim-1; i++){
+		cpsy[i+1] = cpsy[i]*sy[i]--;
+		cpsy2[i] = cpsy[i]*sy[i];
+	}
+	cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]);
+
+	if(maximize){
+		for(j=0; j<NB; j++){
+			*sp = (*sp < *bp)? *bp : *sp;
+			bp++;
+			for(i = 0; i < ndim; i++){
+				if(subs[i] == s[i]){
+					subs[i] = 0;
+					if(sy[i])
+						sp -= cpsy2[i];
+				}
+				else{
+					subs[i]++;
+					if(sy[i])
+						sp += cpsy[i];
+					break;
+				}
+			}
+		}
+	}
+	else{
+		for(j=0; j<NB; j++){
+			*sp += *bp++;
+			for(i = 0; i < ndim; i++){
+				if(subs[i] == s[i]){
+					subs[i] = 0;
+					if(sy[i])
+						sp -= cpsy2[i];
+				}
+				else{
+					subs[i]++;
+					if(sy[i])
+						sp += cpsy[i];
+					break;
+				}
+			}
+		}
+	}
+
+	free(sx);
+	free(sy);
+	free(s);
+	free(cpsy);
+	free(subs);
+	free(cpsy2);
+    free(mask);
+	free(ssize);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/marg_tableM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function smallT = marg_tableM(bigT, bigdom, bigsz, onto, maximize)
+% MARG_TABLE Marginalize a table
+% smallT = marg_table(bigT, bigdom, bigsz, onto, maximize)
+
+  % marg_tableM is the same as marg_table.m, but we are sure
+  % it is not marg_table.c
+
+if nargin < 5, maximize = 0; end
+
+
+smallT = myreshape(bigT, bigsz); % make sure it is a multi-dim array
+sum_over = mysetdiff(bigdom, onto);
+ndx = find_equiv_posns(sum_over, bigdom);
+if maximize
+  for i=1:length(ndx)
+    smallT = max(smallT, [], ndx(i));
+  end
+else
+  for i=1:length(ndx)
+    smallT = sum(smallT, ndx(i));
+  end
+end
+
+
+ns = zeros(1, max(bigdom));
+%ns(bigdom) = mysize(bigT); % ignores trailing dimensions of size 1
+ns(bigdom) = bigsz;
+
+smallT = squeeze(smallT); % remove all dimensions of size 1
+smallT = myreshape(smallT, ns(onto)); % put back relevant dims of size 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/mult_by_sparse_table.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,155 @@
+/* mult_by_sparse_table.c ../potential/tables*/
+
+
+/******************************************/
+/* 6 input & 1 output                     */
+/* Big table    [0]                       */
+/* Big domain   [1]                       */
+/* big sizes    [2]                       */
+/* Small table  [3]                       */
+/* small domain [4]                       */
+/* small sizes  [5]                       */
+/*                                        */
+/* New big table[0]                       */
+/******************************************/
+
+#include <math.h>
+#include <stdlib.h>
+#include "mex.h"
+
+int compare(const void* src1, const void* src2){
+	int i1 = *(int*)src1 ;
+	int i2 = *(int*)src2 ;
+	return i1-i2 ;
+}
+
+void ind_subv(int index, const int *cumprod, int n, int *bsubv){
+	int i;
+
+	for (i = n-1; i >= 0; i--) {
+		bsubv[i] = ((int)floor(index / cumprod[i]));
+		index = index % cumprod[i];
+	}
+}
+
+int subv_ind(const int n, const int *cumprod, const int *subv){
+	int i, index=0;
+
+	for(i=0; i<n; i++){
+		index += subv[i] * cumprod[i];
+	}
+	return index;
+}
+
+void reset_nzmax(mxArray *spArray, const int old_nzmax, const int new_nzmax){
+	double *ptr;
+	void   *newptr;
+	int    *ir, *jc;
+	int    nbytes;
+
+	if(new_nzmax == old_nzmax) return;
+	nbytes = new_nzmax * sizeof(*ptr);
+	ptr = mxGetPr(spArray);
+	newptr = mxRealloc(ptr, nbytes);
+	mxSetPr(spArray, newptr);
+	nbytes = new_nzmax * sizeof(*ir);
+	ir = mxGetIr(spArray);
+	newptr = mxRealloc(ir, nbytes);
+	mxSetIr(spArray, newptr);
+	jc = mxGetJc(spArray);
+	jc[0] = 0;
+	jc[1] = new_nzmax;
+	mxSetNzmax(spArray, new_nzmax);
+}
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int     i, j, count, bdim, sdim, NB, NZB, NZS, position, bindex, sindex, nzCounts=0;
+	int     *mask, *result, *bir, *sir, *rir, *bjc, *sjc, *rjc, *bCumprod, *sCumprod, *bsubv, *ssubv;
+	double  *pbDomain, *psDomain, *pbSize, *psSize, *bpr, *spr, *rpr;
+
+	pbDomain = mxGetPr(prhs[1]);
+	bdim = mxGetNumberOfElements(prhs[1]);
+	psDomain = mxGetPr(prhs[4]);
+	sdim = mxGetNumberOfElements(prhs[4]);
+
+	pbSize = mxGetPr(prhs[2]);
+	psSize = mxGetPr(prhs[5]);
+
+	NB = 1;
+	for(i=0; i<bdim; i++){
+		NB *= (int)pbSize[i];
+	}
+
+	bpr = mxGetPr(prhs[0]);
+	bir = mxGetIr(prhs[0]);
+	bjc = mxGetJc(prhs[0]);
+	NZB = bjc[1];
+
+	spr = mxGetPr(prhs[3]);
+	sir = mxGetIr(prhs[3]);
+	sjc = mxGetJc(prhs[3]);
+	NZS = sjc[1];
+
+	plhs[0] = mxDuplicateArray(prhs[0]);
+	rpr = mxGetPr(plhs[0]);
+	rir = mxGetIr(plhs[0]);
+	rjc = mxGetJc(plhs[0]);
+	rjc[0] = 0;
+	rjc[1] = NZB;
+
+	if(sdim == 0){
+		for(i=0; i<NZB; i++){
+			rpr[i] *= *spr;
+		}	
+		return;
+	}
+
+	mask = malloc(sdim * sizeof(int));
+	bCumprod = malloc(bdim * sizeof(int));
+	sCumprod = malloc(sdim * sizeof(int));
+	bsubv = malloc(bdim * sizeof(int));
+	ssubv = malloc(sdim * sizeof(int));
+
+	count = 0;
+	for(i=0; i<sdim; i++){
+		for(j=0; j<bdim; j++){
+			if(psDomain[i] == pbDomain[j]){
+				mask[count] = j;
+				count++;
+				break;
+			}
+		}
+	}
+	
+	bCumprod[0] = 1;
+	for(i=0; i<bdim-1; i++){
+		bCumprod[i+1] = bCumprod[i] * (int)pbSize[i];
+	}
+	sCumprod[0] = 1;
+	for(i=0; i<sdim-1; i++){
+		sCumprod[i+1] = sCumprod[i] * (int)psSize[i];
+	}
+
+	for(i=0; i<NZB; i++){
+		bindex = bir[i];
+		ind_subv(bindex, bCumprod, bdim, bsubv);
+		for(j=0; j<sdim; j++){
+			ssubv[j] = bsubv[mask[j]];
+		}
+		sindex = subv_ind(sdim, sCumprod, ssubv);
+		result = (int *) bsearch(&sindex, sir, NZS, sizeof(int), compare);
+		if(result){
+			position = result - sir;
+			rpr[nzCounts] = bpr[i] * spr[position];
+			rir[nzCounts] = bindex;
+			nzCounts++;
+		}
+	}
+
+	reset_nzmax(plhs[0], NZB, nzCounts);
+	free(mask);
+	free(bCumprod);
+	free(sCumprod);
+	free(bsubv);
+	free(ssubv);
+}
Binary file _FullBNT/BNT/potentials/Tables/mult_by_sparse_table.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/mult_by_table.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,114 @@
+/* mult_by_table.c  ../potential/tables  */
+
+
+/******************************************/
+/* 6 input & 1 output                     */
+/* Big table    [0]                       */
+/* Big domain   [1]                       */
+/* big sizes    [2]                       */
+/* Small table  [3]                       */
+/* small domain [4]                       */
+/* small sizes  [5]                       */
+/*                                        */
+/* New big table[0]                       */
+/******************************************/
+
+#include "mex.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+  int     i, j, count, NB, NS, siz_b, siz_s, ndim, temp;
+  int     *mask, *sx, *sy, *cpsy, *subs, *s, *cpsy2;
+  double  *pbDomain, *psDomain, *sp, *zp, *bs;
+  
+  plhs[0] = mxDuplicateArray(prhs[0]);
+  zp = mxGetPr(plhs[0]);
+  
+  siz_b = mxGetNumberOfElements(prhs[1]);
+  siz_s = mxGetNumberOfElements(prhs[4]);
+  pbDomain = mxGetPr(prhs[1]);
+  psDomain = mxGetPr(prhs[4]);
+  
+  NB = mxGetNumberOfElements(prhs[0]);
+  NS = mxGetNumberOfElements(prhs[3]);
+  sp = mxGetPr(prhs[3]);
+  
+  bs = mxGetPr(prhs[2]);
+  
+  if(NS == 1){
+    for(i=0; i<NB; i++){
+      zp[i] *= *sp;
+    }
+    return;
+  }
+  
+  if(NS == NB){
+    for(i=0; i<NB; i++){
+      zp[i] *= sp[i];
+    }
+    return;
+  }
+  
+  mask = malloc(siz_s * sizeof(int));
+  count = 0;
+  for(i=0; i<siz_s; i++){
+    for(j=0; j<siz_b; j++){
+      if(psDomain[i] == pbDomain[j]){
+	mask[count] = j;
+	count++;
+	break;
+      }
+    }
+  }
+  
+  ndim = siz_b;
+  sx = (int *)malloc(sizeof(int)*ndim);
+  sy = (int *)malloc(sizeof(int)*ndim);
+  for(i=0; i<ndim; i++){
+    sx[i] = (int)bs[i];
+    sy[i] = 1;
+  }
+  for(i=0; i<count; i++){
+    temp = mask[i];
+    sy[temp] = sx[temp];
+  }
+  
+  s = (int *)malloc(sizeof(int)*ndim);
+  *(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1;
+  subs =   (int *)malloc(sizeof(int)*ndim);
+  cpsy2 =  (int *)malloc(sizeof(int)*ndim);
+  for(i = 0; i < ndim; i++){
+    subs[i] = 0;
+    s[i] = sx[i] - 1;
+  }
+  
+  for(i = 0; i < ndim-1; i++){
+    cpsy[i+1] = cpsy[i]*sy[i]--;
+    cpsy2[i] = cpsy[i]*sy[i];
+  }
+  cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]);
+  
+  for(j=0; j<NB; j++){
+    *zp++ *= *sp;
+    for(i = 0; i < ndim; i++){
+      if(subs[i] == s[i]){
+	subs[i] = 0;
+	if(sy[i])
+	  sp -= cpsy2[i];
+      }
+      else{
+	subs[i]++;
+	if(sy[i])
+	  sp += cpsy[i];
+	break;
+      }
+    }
+  }
+  free(sx);
+  free(sy);
+  free(s);
+  free(cpsy);
+  free(subs);
+  free(cpsy2);
+  free(mask);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/mult_by_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function bigT = mult_by_table(bigT, bigdom, bigsz, smallT, smalldom, smallsz)
+% MULT_BY_TABLE 
+% bigT = mult_by_table(bigT, bigdom, bigsz, smallT, smalldom, smallsz)
+%
+
+Ts = extend_domain_table(smallT, smalldom, smallsz, bigdom, bigsz);
+bigT(:) = bigT(:) .* Ts(:); % must have bigT(:) on LHS to preserve shape
Binary file _FullBNT/BNT/potentials/Tables/mult_by_table.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/mult_by_table2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function bigT = mult_by_table2(bigT, bigdom, bigsz, smallT, smalldom, smallsz)
+% MULT_BY_TABLE 
+% bigT = mult_by_table(bigT, bigdom, bigsz, smallT, smalldom, smallsz)
+%
+
+%Ts = extend_domain_table(smallT, smalldom, smallsz, bigdom, bigsz);
+%bigT(:) = bigT(:) .* Ts(:); % must have bigT(:) on LHS to preserve shape
+
+% extend_domain_table has a lot of overhead for small tables,
+% since it calls myreshape and myrepmat, which check for 1 dimensional case.
+% Here, we check up front.
+
+if length(bigdom)==1 % vector
+  bigT = bigT .* smallT; % smallT can be scalar or vector
+else
+  if (length(bigsz) == length(smallsz)) & all(bigsz == smallsz)
+    bigT = bigT .* smallT;
+  else
+    map = find_equiv_posns(smalldom, bigdom);
+    sz = ones(1, length(bigdom));
+    sz(map) = smallsz;
+    smallT = reshape(smallT, sz); % add dimensions of size 1 for missing domain
+    % we can use reshape instead of myreshape, because we know length(sz)>1
+    sz = bigsz;
+    sz(map) = 1; % don't replicate along small domain, which is shared
+    % we can use repmat instead of myrepmat, because we know length(sz)>1
+    smallT = repmat(smallT, sz(:)');
+    bigT(:) = bigT(:) .* smallT(:);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/mult_by_tableC.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,114 @@
+/* mult_by_table.c  ../potential/tables  */
+
+
+/******************************************/
+/* 6 input & 1 output                     */
+/* Big table    [0]                       */
+/* Big domain   [1]                       */
+/* big sizes    [2]                       */
+/* Small table  [3]                       */
+/* small domain [4]                       */
+/* small sizes  [5]                       */
+/*                                        */
+/* New big table[0]                       */
+/******************************************/
+
+#include "mex.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+  int     i, j, count, NB, NS, siz_b, siz_s, ndim, temp;
+  int     *mask, *sx, *sy, *cpsy, *subs, *s, *cpsy2;
+  double  *pbDomain, *psDomain, *sp, *zp, *bs;
+  
+  plhs[0] = mxDuplicateArray(prhs[0]);
+  zp = mxGetPr(plhs[0]);
+  
+  siz_b = mxGetNumberOfElements(prhs[1]);
+  siz_s = mxGetNumberOfElements(prhs[4]);
+  pbDomain = mxGetPr(prhs[1]);
+  psDomain = mxGetPr(prhs[4]);
+  
+  NB = mxGetNumberOfElements(prhs[0]);
+  NS = mxGetNumberOfElements(prhs[3]);
+  sp = mxGetPr(prhs[3]);
+  
+  bs = mxGetPr(prhs[2]);
+  
+  if(NS == 1){
+    for(i=0; i<NB; i++){
+      zp[i] *= *sp;
+    }
+    return;
+  }
+  
+  if(NS == NB){
+    for(i=0; i<NB; i++){
+      zp[i] *= sp[i];
+    }
+    return;
+  }
+  
+  mask = malloc(siz_s * sizeof(int));
+  count = 0;
+  for(i=0; i<siz_s; i++){
+    for(j=0; j<siz_b; j++){
+      if(psDomain[i] == pbDomain[j]){
+	mask[count] = j;
+	count++;
+	break;
+      }
+    }
+  }
+  
+  ndim = siz_b;
+  sx = (int *)malloc(sizeof(int)*ndim);
+  sy = (int *)malloc(sizeof(int)*ndim);
+  for(i=0; i<ndim; i++){
+    sx[i] = (int)bs[i];
+    sy[i] = 1;
+  }
+  for(i=0; i<count; i++){
+    temp = mask[i];
+    sy[temp] = sx[temp];
+  }
+  
+  s = (int *)malloc(sizeof(int)*ndim);
+  *(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1;
+  subs =   (int *)malloc(sizeof(int)*ndim);
+  cpsy2 =  (int *)malloc(sizeof(int)*ndim);
+  for(i = 0; i < ndim; i++){
+    subs[i] = 0;
+    s[i] = sx[i] - 1;
+  }
+  
+  for(i = 0; i < ndim-1; i++){
+    cpsy[i+1] = cpsy[i]*sy[i]--;
+    cpsy2[i] = cpsy[i]*sy[i];
+  }
+  cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]);
+  
+  for(j=0; j<NB; j++){
+    *zp++ *= *sp;
+    for(i = 0; i < ndim; i++){
+      if(subs[i] == s[i]){
+	subs[i] = 0;
+	if(sy[i])
+	  sp -= cpsy2[i];
+      }
+      else{
+	subs[i]++;
+	if(sy[i])
+	  sp += cpsy[i];
+	break;
+      }
+    }
+  }
+  free(sx);
+  free(sy);
+  free(s);
+  free(cpsy);
+  free(subs);
+  free(cpsy2);
+  free(mask);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/mult_by_tableM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function bigT = mult_by_table(bigT, bigdom, bigsz, smallT, smalldom, smallsz)
+% MULT_BY_TABLE 
+% bigT = mult_by_table(bigT, bigdom, bigsz, smallT, smalldom, smallsz)
+%
+
+Ts = extend_domain_table(smallT, smalldom, smallsz, bigdom, bigsz);
+bigT(:) = bigT(:) .* Ts(:); % must have bigT(:) on LHS to preserve shape
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/mult_by_table_global.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function mult_by_table_global(bigT, bigdom, bigsz, smallT, smalldom, smallsz)
+
+% all arguments are read only
+global NEWBIGT_GLOBAL
+
+Ts = extend_domain_table(smallT, smalldom, smallsz, bigdom, bigsz);
+NEWBIGT_GLOBAL = bigT(:) .* Ts(:);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/rep_mult.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,92 @@
+/* rep_mult.c  repmat first two operands to the size provided by */
+/* the third operand, then perform point multiply                */
+/* 3 input, 1 output                                             */
+/* C = rep_mult(A, B, sizes)                                     */
+
+#include "mex.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+	double		*xp, *yp, *zp, *pSizes;
+	int			xnd, ynd, numElements = 1;
+	const int	*xdim, *ydim;
+	int         i, j, ndim;
+	int			*s, *sx, *sy, *cpsx, *cpsy;
+	int			*subs, *s1, *cpsx2, *cpsy2;
+
+	if (nrhs != 3)
+		mexErrMsgTxt("Incorrect number of inputs.");
+	
+	if (nlhs > 1)
+		mexErrMsgTxt("Too many output arguments.");
+	
+	xnd = mxGetNumberOfDimensions(prhs[0]);
+	ynd = mxGetNumberOfDimensions(prhs[1]);
+	xdim = mxGetDimensions(prhs[0]);
+	ydim = mxGetDimensions(prhs[1]);
+	ndim = mxGetNumberOfElements(prhs[2]);
+
+	pSizes = mxGetPr(prhs[2]);
+
+	sx = (int *)malloc(sizeof(int)*ndim);
+	sy = (int *)malloc(sizeof(int)*ndim);
+	s =  (int *)malloc(sizeof(int)*ndim);
+	s1 = (int *)malloc(sizeof(int)*ndim);
+	*(cpsx = (int *)malloc(sizeof(int)*ndim)) = 1;
+	*(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1;
+	subs =   (int *)malloc(sizeof(int)*ndim);
+	cpsx2 =  (int *)malloc(sizeof(int)*ndim);
+	cpsy2 =  (int *)malloc(sizeof(int)*ndim);
+	for(i=0; i<ndim; i++){
+		subs[i] = 0;
+		sx[i] = (i < xnd) ? xdim[i] : 1;
+		sy[i] = (i < ynd) ? ydim[i] : 1;
+		s[i] = (int)pSizes[i];
+		s1[i] = s[i] - 1;
+		numElements *= s[i];
+	}
+				
+	for(i=0; i<ndim-1; i++){
+		cpsx[i+1] = cpsx[i]*sx[i]--;
+		cpsy[i+1] = cpsy[i]*sy[i]--;
+		cpsx2[i] = cpsx[i]*sx[i];
+		cpsy2[i] = cpsy[i]*sy[i];
+	}
+	cpsx2[ndim-1] = cpsx[ndim-1]*(--sx[ndim-1]);
+	cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]);
+	
+	plhs[0] = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxREAL);
+	zp = mxGetPr(plhs[0]);
+	xp = mxGetPr(prhs[0]);
+	yp = mxGetPr(prhs[1]);
+
+	for(j=0; j<numElements; j++){
+		*zp++ = *xp * *yp;
+		for(i=0; i<ndim; i++){
+			if(subs[i] == s1[i]){
+				subs[i] = 0;
+				if(sx[i])
+					xp -= cpsx2[i];
+				if(sy[i])
+					yp -= cpsy2[i];
+			}
+			else{
+				subs[i]++;
+				if(sx[i])
+					xp += cpsx[i];
+				if(sy[i])
+					yp += cpsy[i];
+				break;
+			}
+		}
+	}
+	free(sx);
+	free(sy);
+	free(s);
+	free(s1);
+	free(cpsx);
+	free(cpsy);
+	free(subs);
+	free(cpsx2);
+	free(cpsy2);
+}
Binary file _FullBNT/BNT/potentials/Tables/rep_mult.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/Tables/repmat_and_mult.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,97 @@
+/****************************************************
+A = mult_by_array(big, small)
+implicitely copies small |big|/|small| times 
+and then does element-wise multiplication.
+
+i.e.,
+C = repmat(small(:), 1, length(big(:))/length(small(:)))
+A = reshape(big(:) .* C(:), size(big))
+
+However, this C version avoids the expense of the repmat.
+
+Written by wei.hu@intel.com, 28 Jan 2002.
+/****************************************************/
+
+
+#include "mex.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+  double		*sp, *zp;
+  int			i, j, NB, NS, xnd, ynd, ndim;
+  const int	*xdim, *ydim;
+  int			*s, *sx, *sy, *cpsy, *subs, *cpsy2;
+  
+  if (nrhs != 2)
+    mexErrMsgTxt("Incorrect number of inputs.");
+  
+  if (nlhs > 1)
+    mexErrMsgTxt("Too many output arguments.");
+  
+  plhs[0] = mxDuplicateArray(prhs[0]);
+  zp = mxGetPr(plhs[0]);
+  sp = mxGetPr(prhs[1]);
+  
+  xnd = mxGetNumberOfDimensions(prhs[0]);
+  ynd = mxGetNumberOfDimensions(prhs[1]);
+  xdim = mxGetDimensions(prhs[0]);
+  ydim = mxGetDimensions(prhs[1]);
+  ndim = xnd;
+  
+  NB = mxGetNumberOfElements(prhs[0]);
+  NS = mxGetNumberOfElements(prhs[1]);
+  
+  if(NS == 1){
+    for(i=0; i<NB; i++){
+      *zp++ *= *sp;
+    }
+    return;
+  }
+  
+  if(NS == NB){
+    for(i=0; i<NB; i++){
+      *zp++ *= *sp++;
+    }
+    return;
+  }
+  
+  sx = (int *)malloc(sizeof(int)*ndim);
+  sy = (int *)malloc(sizeof(int)*ndim);
+  s =  (int *)malloc(sizeof(int)*ndim);
+  *(cpsy = (int *)malloc(sizeof(int)*ndim)) = 1;
+  subs =   (int *)malloc(sizeof(int)*ndim);
+  cpsy2 =  (int *)malloc(sizeof(int)*ndim);
+  for(i=0; i<ndim; i++){
+    subs[i] = 0;
+    sx[i] = xdim[i];
+    sy[i] = (i < ynd) ? ydim[i] : 1;
+    s[i] = sx[i] - 1;
+  }
+  
+  for (i = 0; i < ndim-1; i++){
+    cpsy[i+1] = cpsy[i]*sy[i]--;
+    cpsy2[i] = cpsy[i]*sy[i];
+  }
+  cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]);
+  
+  for(j=0; j<NB; j++){
+    *zp++ *= *sp;
+    for(i=0; i<ndim; i++){
+      if(subs[i] == s[i]){
+	subs[i] = 0;
+	if(sy[i]) sp -= cpsy2[i];
+      }
+      else{
+	subs[i]++;
+	if(sy[i]) sp += cpsy[i];
+	break;
+      }
+    }
+  }
+  free(sx);
+  free(sy);
+  free(s);
+  free(cpsy);
+  free(subs);
+  free(cpsy2);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/check_for_cd_arcs.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+function check_for_cd_arcs(onodes, cnodes, dag)
+% CHECK_FOR_CD_ARCS Raise an error if there are any C->D links where the C node is hidden.
+% check_for_cd_arcs(onodes, cnodes, dag)
+%
+% We cannot convert the logistic/softmax function (C->D CPD) to a Gaussian potential
+% unless we use the variational approximation discussed in 
+% "A variational approximation for Bayesian networks with discrete and continuous latent
+% variables", K. Murphy, UAI 1999.
+
+n = length(dag);
+hnodes = mysetdiff(1:n, onodes);
+chid = myintersect(cnodes, hnodes);
+dnodes = mysetdiff(1:n, cnodes);
+for i=chid(:)'
+  dcs = myintersect(children(dag, i), dnodes);
+  if ~isempty(dcs)
+    error(['hidden cts node ' num2str(i) ' has a discrete child']);
+  end
+end
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/determine_pot_type.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function pot_type = determine_pot_type(model, onodes, nodes)
+% DETERMINE_POT_TYPE Determine the type of potential based on the evidence pattern.
+% pot_type = determine_pot_type(model, onodes, nodes)
+%
+% If there are any utility nodes, pot_type = 'u'
+% else
+% If all hidden nodes are discrete, pot_type = 'd'.
+% If all hidden nodes are continuous, pot_type = 'g' (Gaussian).
+% If some hidden nodes are discrete, and some cts, pot_type = 'cg' (conditional Gaussian).
+%
+% nodes defaults to all nodes in graph
+
+nnodes = length(model.node_sizes);
+if nargin < 3, nodes = 1:nnodes; end
+
+hnodes = mysetdiff(nodes, onodes);
+if isfield(model, 'limid') %~isempty(model.utility_nodes)
+  pot_type = 'u';
+elseif isempty(myintersect(model.cnodes, hnodes))
+  pot_type = 'd';
+elseif mysubset(hnodes, model.cnodes)
+  pot_type = 'g';
+else
+  pot_type = 'cg';
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/genops.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,707 @@
+/*
+
+	GENOPS.C
+		Generalized arithmetic operators overloading built-in functions.
+
+	written by Douglas M. Schwarz
+	schwarz@servtech.com
+	26 December 1998
+	Last modified: 2 April 1999
+
+	Copyright 1998-1999 by Douglas M. Schwarz.  All rights reserved.
+
+*/
+
+
+/*
+
+Build MEX file by entering the appropriate command at the MATLAB prompt
+(-D<name> option is equivalent to #define <name> in source file):
+
+mex genops.c -DPLUS_MEX -output plus
+mex genops.c -DMINUS_MEX -output minus
+mex genops.c -DTIMES_MEX -output times
+mex genops.c -DRDIVIDE_MEX -output rdivide
+mex genops.c -DLDIVIDE_MEX -output ldivide
+mex genops.c -DPOWER_MEX -output power
+mex genops.c -DEQ_MEX -output eq
+mex genops.c -DNE_MEX -output ne
+mex genops.c -DLT_MEX -output lt
+mex genops.c -DGT_MEX -output gt
+mex genops.c -DLE_MEX -output le
+mex genops.c -DGE_MEX -output ge
+
+*/
+
+/*	This file has been formatted for a tab equal to 4 spaces. */
+
+#if defined(EQ_MEX) || defined(NE_MEX) || defined(LT_MEX) || defined(GT_MEX) \
+		|| defined(LE_MEX) || defined(GE_MEX)
+#define	RELOP_MEX
+#endif
+
+#include "mex.h"
+#include "matrix.h"
+#ifdef POWER_MEX
+#include <math.h>
+#define PI 3.141592653589793
+#endif
+
+bool allequal(int, const int *, const int *);
+void removeZeroImag(double *, double *, int, const int *, int, mxArray **);
+
+#define	xMat  prhs[0]
+#define	yMat  prhs[1]
+#define	zMat  plhs[0]
+
+#define	min(A,B)  ((A) < (B) ? (A) : (B))
+#define	max(A,B)  ((A) > (B) ? (A) : (B))
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+	double		*xrp, *xip, *yrp, *yip;
+#ifndef RELOP_MEX
+	double		*zr, *zi, *zip;
+#endif
+	double		*zrp, *zrend;
+	int			xnd, ynd, numElements = 1;
+	const int	*xdim, *ydim;
+	bool		xcmplx, ycmplx;
+	mxClassID	yclass;
+	int			*s, ndim, *sx, *sy, i, *cpsx, *cpsy;
+	int			*subs, *s1, *cpsx2, *cpsy2;
+	int			ix = 0, iy = 0;
+	mxArray		*args[3], *result[1];
+#if defined(RDIVIDE_MEX) || defined(LDIVIDE_MEX)
+	double		denom;
+#endif
+#ifdef POWER_MEX
+	double		mag, theta, phi, magx;
+	int			flops = 0;
+#endif
+	
+	
+	if (nrhs != 2)
+		mexErrMsgTxt("Incorrect number of inputs.");
+	
+	if (nlhs > 1)
+		mexErrMsgTxt("Too many output arguments.");
+	
+	xnd = mxGetNumberOfDimensions(xMat);
+	ynd = mxGetNumberOfDimensions(yMat);
+	xdim = mxGetDimensions(xMat);
+	ydim = mxGetDimensions(yMat);
+	
+	yclass = mxGetClassID(yMat);
+	
+/*	If the built-in function in MATLAB can handle the arguments
+	then use that. */
+	if (yclass != mxDOUBLE_CLASS || 
+		(xnd == 2  &&  xdim[0] == 1  &&  xdim[1] == 1) || 
+		(ynd == 2  &&  ydim[0] == 1  &&  ydim[1] == 1) || 
+		(xnd == ynd  &&  allequal(xnd,xdim,ydim)))
+	{
+#ifdef PLUS_MEX
+		args[0] = mxCreateString("plus");
+#elif defined(MINUS_MEX)
+		args[0] = mxCreateString("minus");
+#elif defined(TIMES_MEX)
+		args[0] = mxCreateString("times");
+#elif defined(RDIVIDE_MEX)
+		args[0] = mxCreateString("rdivide");
+#elif defined(LDIVIDE_MEX)
+		args[0] = mxCreateString("ldivide");
+#elif defined(POWER_MEX)
+		args[0] = mxCreateString("power");
+#elif defined(EQ_MEX)
+		args[0] = mxCreateString("eq");
+#elif defined(NE_MEX)
+		args[0] = mxCreateString("ne");
+#elif defined(LT_MEX)
+		args[0] = mxCreateString("lt");
+#elif defined(GT_MEX)
+		args[0] = mxCreateString("gt");
+#elif defined(LE_MEX)
+		args[0] = mxCreateString("le");
+#elif defined(GE_MEX)
+		args[0] = mxCreateString("ge");
+#endif
+		args[1] = (mxArray *)xMat;
+		args[2] = (mxArray *)yMat;
+		mexCallMATLAB(1, result, 3, args, "builtin");
+		mxDestroyArray(args[0]);
+		zMat = result[0];
+	}
+	else  /* X and Y are both N-D and different dimensionality. */
+	{
+		ndim = max(xnd,ynd);
+		sx = (int *)mxMalloc(sizeof(int)*ndim);
+		sy = (int *)mxMalloc(sizeof(int)*ndim);
+		s =  (int *)mxMalloc(sizeof(int)*ndim);
+		s1 = (int *)mxMalloc(sizeof(int)*ndim);
+		*(cpsx = (int *)mxMalloc(sizeof(int)*ndim)) = 1;
+		*(cpsy = (int *)mxMalloc(sizeof(int)*ndim)) = 1;
+		subs =   (int *)mxMalloc(sizeof(int)*ndim);
+		cpsx2 =  (int *)mxMalloc(sizeof(int)*ndim);
+		cpsy2 =  (int *)mxMalloc(sizeof(int)*ndim);
+		for (i = 0; i < ndim; i++)
+		{
+			subs[i] = 0;
+			sx[i] = (i < xnd) ? xdim[i] : 1;
+			sy[i] = (i < ynd) ? ydim[i] : 1;
+			if (sx[i] == sy[i])
+				s[i] = sx[i];
+			else if (sx[i] == 1)
+				s[i] = sy[i];
+			else if (sy[i] == 1)
+				s[i] = sx[i];
+			else
+			{
+				mxFree(sx);
+				mxFree(sy);
+				mxFree(s);
+				mxFree(s1);
+				mxFree(cpsx);
+				mxFree(cpsy);
+				mxFree(subs);
+				mxFree(cpsx2);
+				mxFree(cpsy2);
+				mexErrMsgTxt("Array dimensions are not appropriate.");
+			}
+			s1[i] = s[i] - 1;
+			numElements *= s[i];
+		}
+				
+		for (i = 0; i < ndim-1; i++)
+		{
+			cpsx[i+1] = cpsx[i]*sx[i]--;
+			cpsy[i+1] = cpsy[i]*sy[i]--;
+			cpsx2[i] = cpsx[i]*sx[i];
+			cpsy2[i] = cpsy[i]*sy[i];
+		}
+		cpsx2[ndim-1] = cpsx[ndim-1]*(--sx[ndim-1]);
+		cpsy2[ndim-1] = cpsy[ndim-1]*(--sy[ndim-1]);
+		
+		xcmplx = mxIsComplex(xMat);
+		ycmplx = mxIsComplex(yMat);
+		
+		if (!xcmplx && !ycmplx)  /* X and Y both N-D, both real. */
+		{
+#ifdef POWER_MEX
+			zMat = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxCOMPLEX);
+			zrp = zr = mxGetPr(zMat);
+			zip = zi = mxGetPi(zMat);
+#elif defined(RELOP_MEX)
+			zMat = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxREAL);
+			mxSetLogical(zMat);
+			zrp = mxGetPr(zMat);
+#else
+			zMat = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxREAL);
+			zrp = mxGetPr(zMat);
+#endif
+			xrp = mxGetPr(xMat);
+			yrp = mxGetPr(yMat);
+			zrend = zrp + numElements;
+			while (zrp < zrend)
+			{
+#ifdef PLUS_MEX
+				*zrp++ = *xrp + *yrp;
+#elif defined(MINUS_MEX)
+				*zrp++ = *xrp - *yrp;
+#elif defined(TIMES_MEX)
+				*zrp++ = *xrp * *yrp;
+#elif defined(RDIVIDE_MEX)
+				*zrp++ = *xrp / *yrp;
+#elif defined(LDIVIDE_MEX)
+				*zrp++ = *yrp / *xrp;
+#elif defined(POWER_MEX)
+				if (*xrp < 0.0 && *yrp != floor(*yrp))
+				{
+					mag = pow(-*xrp,*yrp);
+					theta = PI * *yrp;
+					*zrp++ = mag*cos(theta);
+					*zip++ = mag*sin(theta);
+					flops += 18;
+				}
+				else
+				{
+					*zrp++ = pow(*xrp,*yrp);
+					*zip++ = 0.0;
+					flops++;
+				}
+#elif defined(EQ_MEX)
+				*zrp++ = (*xrp == *yrp);
+#elif defined(NE_MEX)
+				*zrp++ = (*xrp != *yrp);
+#elif defined(LT_MEX)
+				*zrp++ = (*xrp < *yrp);
+#elif defined(GT_MEX)
+				*zrp++ = (*xrp > *yrp);
+#elif defined(LE_MEX)
+				*zrp++ = (*xrp <= *yrp);
+#elif defined(GE_MEX)
+				*zrp++ = (*xrp >= *yrp);
+#endif
+				for (i = 0; i < ndim; i++)
+				{
+					if (subs[i] == s1[i])
+					{
+						subs[i] = 0;
+						if (sx[i])
+							xrp -= cpsx2[i];
+						if (sy[i])
+							yrp -= cpsy2[i];
+					}
+					else
+					{
+						subs[i]++;
+						if (sx[i])
+							xrp += cpsx[i];
+						if (sy[i])
+							yrp += cpsy[i];
+						break;
+					}
+				}
+			}
+#ifdef POWER_MEX
+			mexAddFlops(flops);
+			removeZeroImag(zr, zi, ndim, (const int *)s, numElements, &zMat);
+#elif !defined(RELOP_MEX)
+			mexAddFlops(numElements);
+#endif
+		}
+		else if (!xcmplx && ycmplx)  /* X and Y both N-D, X real, Y complex. */
+		{
+#ifdef POWER_MEX
+			zMat = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxCOMPLEX);
+			zrp = zr = mxGetPr(zMat);
+			zip = zi = mxGetPi(zMat);
+#elif defined(RELOP_MEX)
+			zMat = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxREAL);
+			mxSetLogical(zMat);
+			zrp = mxGetPr(zMat);
+#else
+			zMat = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxCOMPLEX);
+			zrp = mxGetPr(zMat);
+			zip = mxGetPi(zMat);
+#endif
+			xrp = mxGetPr(xMat);
+			yrp = mxGetPr(yMat);
+			yip = mxGetPi(yMat);
+			zrend = zrp + numElements;
+			while (zrp < zrend)
+			{
+#ifdef PLUS_MEX
+				*zrp++ = *xrp + *yrp;
+				*zip++ = *yip;
+#elif defined(MINUS_MEX)
+				*zrp++ = *xrp - *yrp;
+				*zip++ = -*yip;
+#elif defined(TIMES_MEX)
+				*zrp++ = *xrp * *yrp;
+				*zip++ = *xrp * *yip;
+#elif defined(RDIVIDE_MEX)
+				denom = *yrp * *yrp + *yip * *yip;
+				*zrp++ = (*xrp * *yrp)/denom;
+				*zip++ = (-*xrp * *yip)/denom;
+#elif defined(LDIVIDE_MEX)
+				*zrp++ = *yrp / *xrp;
+				*zip++ = *yip / *xrp;
+#elif defined(POWER_MEX)
+				if (*yip == 0.0)
+				{
+					if (*xrp < 0.0 && *yrp != floor(*yrp))
+					{
+						mag = pow(-*xrp,*yrp);
+						theta = PI * *yrp;
+						*zrp++ = mag*cos(theta);
+						*zip++ = mag*sin(theta);
+						flops += 18;
+					}
+					else
+					{
+						*zrp++ = pow(*xrp,*yrp);
+						*zip++ = 0.0;
+						flops++;
+					}
+				}
+				else
+				{
+					if (*xrp < 0.0)
+					{
+						mag = pow(-*xrp,*yrp)*exp(-PI * *yip);
+						theta = *yip * log(-*xrp) + PI * *yrp;
+						*zrp++ = mag*cos(theta);
+						*zip++ = mag*sin(theta);
+						flops += 18;
+					}
+					else
+					{
+						mag = pow(*xrp,*yrp);
+						theta = *yip * log(*xrp);
+						*zrp++ = mag*cos(theta);
+						*zip++ = mag*sin(theta);
+						flops += 13;
+					}
+				}
+#elif defined(EQ_MEX)
+				*zrp++ = (*xrp == *yrp) && (*yip == 0.0);
+#elif defined(NE_MEX)
+				*zrp++ = (*xrp != *yrp) || (*yip != 0.0);
+#elif defined(LT_MEX)
+				*zrp++ = (*xrp < *yrp);
+#elif defined(GT_MEX)
+				*zrp++ = (*xrp > *yrp);
+#elif defined(LE_MEX)
+				*zrp++ = (*xrp <= *yrp);
+#elif defined(GE_MEX)
+				*zrp++ = (*xrp >= *yrp);
+#endif
+				for (i = 0; i < ndim; i++)
+				{
+					if (subs[i] == s1[i])
+					{
+						subs[i] = 0;
+						if (sx[i])
+							xrp -= cpsx2[i];
+						if (sy[i])
+						{
+							yrp -= cpsy2[i];
+							yip -= cpsy2[i];
+						}
+					}
+					else
+					{
+						subs[i]++;
+						if (sx[i])
+							xrp += cpsx[i];
+						if (sy[i])
+						{
+							yrp += cpsy[i];
+							yip += cpsy[i];
+						}
+						break;
+					}
+				}
+			}
+#if defined(PLUS_MEX) || defined(MINUS_MEX)
+			mexAddFlops(2*numElements);
+#elif defined(TIMES_MEX) || defined(RDIVIDE_MEX) || defined(LDIVIDE_MEX)
+			mexAddFlops(6*numElements);
+#elif defined(POWER_MEX)
+			mexAddFlops(flops);
+			removeZeroImag(zr, zi, ndim, (const int *)s, numElements, &zMat);
+#endif
+		}
+		else if (xcmplx && !ycmplx)  /* X and Y both N-D, X complex, Y real. */
+		{
+#ifdef POWER_MEX
+			zMat = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxCOMPLEX);
+			zrp = zr = mxGetPr(zMat);
+			zip = zi = mxGetPi(zMat);
+#elif defined(RELOP_MEX)
+			zMat = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxREAL);
+			mxSetLogical(zMat);
+			zrp = mxGetPr(zMat);
+#else
+			zMat = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxCOMPLEX);
+			zrp = mxGetPr(zMat);
+			zip = mxGetPi(zMat);
+#endif
+			xrp = mxGetPr(xMat);
+			xip = mxGetPi(xMat);
+			yrp = mxGetPr(yMat);
+			zrend = zrp + numElements;
+			while (zrp < zrend)
+			{
+#ifdef PLUS_MEX
+				*zrp++ = *xrp + *yrp;
+				*zip++ = *xip;
+#elif defined(MINUS_MEX)
+				*zrp++ = *xrp - *yrp;
+				*zip++ = *xip;
+#elif defined(TIMES_MEX)
+				*zrp++ = *xrp * *yrp;
+				*zip++ = *xip * *yrp;
+#elif defined(RDIVIDE_MEX)
+				*zrp++ = *xrp / *yrp;
+				*zip++ = *xip / *yrp;
+#elif defined(LDIVIDE_MEX)
+				denom = *xrp * *xrp + *xip * *xip;
+				*zrp++ = (*xrp * *yrp)/denom;
+				*zip++ = (-*xip * *yrp)/denom;
+#elif defined(POWER_MEX)
+				if (*xip == 0.0)
+				{
+					if (*xrp < 0.0 && *yrp != floor(*yrp))
+					{
+						mag = pow(-*xrp,*yrp);
+						theta = PI * *yrp;
+						*zrp++ = mag*cos(theta);
+						*zip++ = mag*sin(theta);
+						flops += 18;
+					}
+					else
+					{
+						*zrp++ = pow(*xrp,*yrp);
+						*zip++ = 0.0;
+						flops++;
+					}
+				}
+				else
+				{
+					mag = pow(*xrp * *xrp + *xip * *xip,0.5 * *yrp);
+					theta = *yrp*atan2(*xip,*xrp);
+					*zrp++ = mag*cos(theta);
+					*zip++ = mag*sin(theta);
+					flops += 18;
+				}
+#elif defined(EQ_MEX)
+				*zrp++ = (*xrp == *yrp) && (*xip == 0.0);
+#elif defined(NE_MEX)
+				*zrp++ = (*xrp != *yrp) || (*xip != 0.0);
+#elif defined(LT_MEX)
+				*zrp++ = (*xrp < *yrp);
+#elif defined(GT_MEX)
+				*zrp++ = (*xrp > *yrp);
+#elif defined(LE_MEX)
+				*zrp++ = (*xrp <= *yrp);
+#elif defined(GE_MEX)
+				*zrp++ = (*xrp >= *yrp);
+#endif
+				for (i = 0; i < ndim; i++)
+				{
+					if (subs[i] == s1[i])
+					{
+						subs[i] = 0;
+						if (sx[i])
+						{
+							xrp -= cpsx2[i];
+							xip -= cpsx2[i];
+						}
+						if (sy[i])
+							yrp -= cpsy2[i];
+					}
+					else
+					{
+						subs[i]++;
+						if (sx[i])
+						{
+							xrp += cpsx[i];
+							xip += cpsx[i];
+						}
+						if (sy[i])
+							yrp += cpsy[i];
+						break;
+					}
+				}
+			}
+#if defined(PLUS_MEX) || defined(MINUS_MEX)
+			mexAddFlops(2*numElements);
+#elif defined(TIMES_MEX) || defined(RDIVIDE_MEX) || defined(LDIVIDE_MEX)
+			mexAddFlops(6*numElements);
+#elif defined(POWER_MEX)
+			mexAddFlops(flops);
+			removeZeroImag(zr, zi, ndim, (const int *)s, numElements, &zMat);
+#endif
+		}
+		else if (xcmplx && ycmplx)  /* X and Y both N-D, both complex. */
+		{
+#if defined(RELOP_MEX)
+			zMat = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxREAL);
+			mxSetLogical(zMat);
+			zrp = mxGetPr(zMat);
+#else
+			zMat = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxCOMPLEX);
+			zrp = zr = mxGetPr(zMat);
+			zip = zi = mxGetPi(zMat);
+#endif
+			xrp = mxGetPr(xMat);
+			xip = mxGetPi(xMat);
+			yrp = mxGetPr(yMat);
+			yip = mxGetPi(yMat);
+			zrend = zrp + numElements;
+			while (zrp < zrend)
+			{
+#ifdef PLUS_MEX
+				*zrp++ = *xrp + *yrp;
+				*zip++ = *xip + *yip;
+#elif defined(MINUS_MEX)
+				*zrp++ = *xrp - *yrp;
+				*zip++ = *xip - *yip;
+#elif defined(TIMES_MEX)
+				*zrp++ = *xrp * *yrp - *xip * *yip;
+				*zip++ = *xip * *yrp + *xrp * *yip;
+#elif defined(RDIVIDE_MEX)
+				denom = *yrp * *yrp + *yip * *yip;
+				*zrp++ = (*xrp * *yrp + *xip * *yip)/denom;
+				*zip++ = (*xip * *yrp - *xrp * *yip)/denom;
+#elif defined(LDIVIDE_MEX)
+				denom = *xrp * *xrp + *xip * *xip;
+				*zrp++ = (*xrp * *yrp + *xip * *yip)/denom;
+				*zip++ = (*xrp * *yip - *xip * *yrp)/denom;
+#elif defined(POWER_MEX)
+				if (*xip == 0.0 && *yip == 0.0)
+				{
+					if (*xrp < 0.0 && *yrp != floor(*yrp))
+					{
+						mag = pow(-*xrp,*yrp);
+						theta = PI * *yrp;
+						*zrp++ = mag*cos(theta);
+						*zip++ = mag*sin(theta);
+						flops += 18;
+					}
+					else
+					{
+						*zrp++ = pow(*xrp,*yrp);
+						*zip++ = 0.0;
+						flops++;
+					}
+				}
+				else if (*xip == 0.0)
+				{
+					if (*xrp < 0.0)
+					{
+						mag = pow(-*xrp,*yrp)*exp(-PI * *yip);
+						theta = *yip * log(-*xrp) + PI * *yrp;
+						*zrp++ = mag*cos(theta);
+						*zip++ = mag*sin(theta);
+						flops += 18;
+					}
+					else
+					{
+						mag = pow(*xrp,*yrp);
+						theta = *yip * log(*xrp);
+						*zrp++ = mag*cos(theta);
+						*zip++ = mag*sin(theta);
+						flops += 13;
+					}
+				}
+				else if (*yip == 0.0)
+				{
+					mag = pow(*xrp * *xrp + *xip * *xip,0.5 * *yrp);
+					theta = *yrp * atan2(*xip,*xrp);
+					*zrp++ = mag*cos(theta);
+					*zip++ = mag*sin(theta);
+					flops += 18;
+				}
+				else
+				{
+					magx = sqrt(*xrp * *xrp + *xip * *xip);
+					phi = atan2(*xip,*xrp);
+					mag = pow(magx,*yrp)*exp(-*yip * phi);
+					theta = *yip * log(magx) + *yrp * phi;
+					*zrp++ = mag*cos(theta);
+					*zip++ = mag*sin(theta);
+					flops += 18;
+				}
+#elif defined(EQ_MEX)
+				*zrp++ = (*xrp == *yrp) && (*xip == *yip);
+#elif defined(NE_MEX)
+				*zrp++ = (*xrp != *yrp) || (*xip != *yip);
+#elif defined(LT_MEX)
+				*zrp++ = (*xrp < *yrp);
+#elif defined(GT_MEX)
+				*zrp++ = (*xrp > *yrp);
+#elif defined(LE_MEX)
+				*zrp++ = (*xrp <= *yrp);
+#elif defined(GE_MEX)
+				*zrp++ = (*xrp >= *yrp);
+#endif
+				for (i = 0; i < ndim; i++)
+				{
+					if (subs[i] == s1[i])
+					{
+						subs[i] = 0;
+						if (sx[i])
+						{
+							xrp -= cpsx2[i];
+							xip -= cpsx2[i];
+						}
+						if (sy[i])
+						{
+							yrp -= cpsy2[i];
+							yip -= cpsy2[i];
+						}
+					}
+					else
+					{
+						subs[i]++;
+						if (sx[i])
+						{
+							xrp += cpsx[i];
+							xip += cpsx[i];
+						}
+						if (sy[i])
+						{
+							yrp += cpsy[i];
+							yip += cpsy[i];
+						}
+						break;
+					}
+				}
+			}
+#if defined(PLUS_MEX) || defined(MINUS_MEX)
+			mexAddFlops(2*numElements);
+#elif defined(TIMES_MEX) || defined(RDIVIDE_MEX) || defined(LDIVIDE_MEX)
+			mexAddFlops(6*numElements);
+#elif defined(POWER_MEX)
+			mexAddFlops(flops);
+#endif
+#ifndef RELOP_MEX
+			removeZeroImag(zr, zi, ndim, (const int *)s, numElements, &zMat);
+#endif
+		}
+	}
+}
+
+
+/***********************************************************
+*                                                          *
+*   Tests to see if the vectors xdim and ydim are equal.   *
+*                                                          *
+***********************************************************/
+bool allequal(int ndim, const int *xdim, const int *ydim)
+{
+	int		i;
+	bool	result = true;
+	
+	for (i = 0; i < ndim; i++)
+		result = result && (xdim[i] == ydim[i]);
+	
+	return(result);
+}
+
+
+/******************************************************************************
+*                                                                             *
+*   Tests to see if every imaginary element is identically zero and, if so,   *
+*   creates a new array which is real and copies the real elements to it.     *
+*                                                                             *
+******************************************************************************/
+void removeZeroImag(double *zr, double *zi, int ndim, const int *s,
+					int numElements, mxArray *plhs[])
+{
+	double			*zrend, *ziend, *zip, *z1p, *z2p;
+	bool			allImZero = true;
+	mxArray			*temp;
+	
+	zip = zi;
+	ziend = zi + numElements;
+	while (zip < ziend)
+	{
+		allImZero = allImZero && (*zip++ == 0.0);
+		if (!allImZero)
+			return;
+	}
+	
+	temp = mxCreateNumericArray(ndim, s, mxDOUBLE_CLASS, mxREAL);
+	z1p = zr;
+	z2p = mxGetPr(temp);
+	zrend = z1p + numElements;
+	while (z1p < zrend)
+		*z2p++ = *z1p++;
+	mxDestroyArray(plhs[0]);
+	plhs[0] = temp;
+	return;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/potentials/mk_initial_pot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+function pot = mk_initial_pot(pot_type, dom, ns, cnodes, onodes)
+% MK_INITIAL_POT A "initial" potential is one which has not had any evidence entered into it.
+% pot = mk_initial_pot(pot_type, domain, node_sizes, cnodes, onodes)
+%
+% pot_type is one of 'd', 'g', 'cg' or 'u'
+% domain is the set of nodes to be included in the potential.
+% node_sizes(i) is the size of node i.
+
+switch pot_type 
+ case 'd',
+  ns(onodes) = 1;
+  pot = dpot(dom, ns(dom));
+ case 'u',
+  ns(onodes) = 1;
+  pot = upot(dom, ns(dom));
+ case 'g',
+  ns(onodes) = 0;
+  pot = cpot(dom, ns(dom));
+ case 'cg',
+  dnodes = mysetdiff(1:length(ns), cnodes);
+  ddom = myintersect(dnodes, dom);
+  cdom = myintersect(cnodes, dom);
+  dobs = myintersect(dnodes, onodes);
+  cobs = myintersect(cnodes, onodes);
+  ns(dobs) = 1;
+  ns(cobs) = 0;
+  pot = cgpot(ddom, cdom, ns);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/test_BNT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,108 @@
+% If all is well, all of these scripts should run without errors.
+
+
+% bnets
+cg1
+cg2
+discrete1
+fa1
+gaussian1
+gaussian2
+if exist('@gibbs_sampling_inf_engine/private/compute_posterior','file')
+  % only exists if installC has been run
+  gibbs_test1
+end
+learn1
+lw1
+mfa1
+mixexp1
+mixexp2
+mixexp3
+mog1
+mpe1
+mpe2
+qmr1
+qmr2
+sample1
+softev1
+softmax1
+sprinkler1
+
+
+% belief propagation
+belprop_polytree_discrete
+belprop_polytree_gauss % alag
+belprop_polytree_cg
+belprop_loop1_discrete
+belprop_loop1_gauss
+belprop_loopy_discrete
+belprop_loopy_gauss
+belprop_loopy_cg % like cg1
+
+
+% factor graphs
+%fg1   failed since marginals were not exact
+
+fg2
+fg3
+fg_mrf1
+fg_mrf2
+
+
+% Structure learning
+bic1
+cooper_yoo
+k2demo1
+mcmc1
+model_select1
+pc1
+%pc2   failed due to numerical problems in KPMstats/cond_indep_fisher_z
+
+
+
+
+% limids
+asia_dt1
+id1
+oil1
+pigs1
+
+
+% dbns
+arhmm1
+bat1
+bkff1
+chmm1
+dhmm1
+filter_test1
+ghmm1
+kalman1
+kjaerulff1
+loopy_dbn1
+mhmm1
+mildew1
+reveal1
+viterbi1
+water1
+
+
+% HHMMs
+abcd_hhmm
+sample_square_hhmm_discrete
+%learn_square_hhmm_cts
+sample_motif_hhmm
+
+%sparse jtree engine & ndx 2TBN engine
+if exist('@jtree_sparse_inf_engine/init_pot','file')
+  % only exists if installC has been run
+  discrete2
+  discrete3 
+  filter_test1
+  water2
+end
+
+%find . -path '*.m' -exec wc -l {} \; | ~/count.pl
+
+% we cannot use tic;toc to time test_BNT, since functions within this script
+% reset the tic;toc timer. Hence we use the following:
+%clock0=clock; cpu0 = cputime; test_BNT; cpu=cputime-cpu0; elapsed=etime(clock, clock0)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/BNT/uninstallC_BNT.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+dirs = {'potentials/Tables', ...
+	'CPDs/@discrete_CPD', ...
+      'inference/static/@jtree_sparse_inf_engine', ...
+      'inference/static/@gibbs_sampling_inf_engine/private'};
+
+BNT_HOME = '/home/ai2/murphyk/matlab/FullBNT'; % edit this
+%global BNT_HOME
+
+for d=1:length(dirs)
+  f = fullfile(BNT_HOME, 'BNT', dirs{d});
+  fprintf('removing Cmex files from %s\n', f);
+  cd(f)
+  delete *.mex*
+  delete *.dll
+  delete *.obj
+  delete *.o
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,80 @@
+/KLgauss.m/1.1.1.1/Tue Apr 26 02:29:16 2005//
+/README.txt/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/beta_sample.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/chisquared_histo.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/chisquared_prob.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/chisquared_readme.txt/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/chisquared_table.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/clg_Mstep.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/clg_Mstep_simple.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/clg_prob.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/condGaussToJoint.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/cond_indep_fisher_z.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/condgaussTrainObserved.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/condgauss_sample.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/convertBinaryLabels.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/cwr_demo.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/cwr_em.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/cwr_predict.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/cwr_prob.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/cwr_readme.txt/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/cwr_test.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/dirichlet_sample.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/dirichletpdf.m/1.1.1.1/Sun May 22 23:32:18 2005//
+/dirichletrnd.m/1.1.1.1/Sun May 22 23:32:12 2005//
+/distchck.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/eigdec.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/est_transmat.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/fit_paritioned_model_testfn.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/fit_partitioned_model.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/gamma_sample.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/gaussian_prob.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/gaussian_sample.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/histCmpChi2.m/1.1.1.1/Tue May  3 20:18:16 2005//
+/linear_regression.m/1.1.1.1/Tue Apr 26 02:29:18 2005//
+/logist2.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/logist2Apply.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/logist2ApplyRegularized.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/logist2Fit.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/logist2FitRegularized.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/logistK.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/logistK_eval.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/marginalize_gaussian.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/matrix_T_pdf.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/matrix_normal_pdf.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/mc_stat_distrib.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/mixgauss_Mstep.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/mixgauss_classifier_apply.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/mixgauss_classifier_train.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/mixgauss_em.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/mixgauss_init.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/mixgauss_prob.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/mixgauss_prob_test.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/mixgauss_sample.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/mkPolyFvec.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/mk_unit_norm.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/multinomial_prob.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/multinomial_sample.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/multipdf.m/1.1.1.1/Sun May 22 23:32:42 2005//
+/multirnd.m/1.1.1.1/Sun May 22 23:32:38 2005//
+/normal_coef.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/partial_corr_coef.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/parzen.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/parzenC.c/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/parzenC.dll/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/parzenC.mexglx/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/parzenC_test.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/parzen_fit_select_unif.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/pca.m/1.1.1.1/Tue Apr 26 02:29:20 2005//
+/rndcheck.m/1.1.1.1/Tue Apr 26 02:29:22 2005//
+/sample.m/1.1.1.1/Tue Apr 26 02:29:22 2005//
+/sample_discrete.m/1.1.1.1/Tue Apr 26 02:29:22 2005//
+/sample_gaussian.m/1.1.1.1/Tue Apr 26 02:29:22 2005//
+/standardize.m/1.1.1.1/Wed May  4 04:35:36 2005//
+/student_t_logprob.m/1.1.1.1/Tue Apr 26 02:29:22 2005//
+/student_t_prob.m/1.1.1.1/Tue Apr 26 02:29:22 2005//
+/test_dir.m/1.1.1.1/Sun May 22 23:32:20 2005//
+/unidrndKPM.m/1.1.1.1/Tue May 31 18:19:24 2005//
+/unif_discrete_sample.m/1.1.1.1/Tue Apr 26 02:29:22 2005//
+/weightedRegression.m/1.1.1.1/Tue Apr 26 02:29:22 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/KPMstats
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/KLgauss.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function kl = KLgauss(P, Q)
+%The following computes D(P||Q), the KL divergence between two zero-mean
+%Gaussians with covariance P and Q:
+%  klDiv = -0.5*(log(det(P*inv(Q))) + trace(eye(N)-P*inv(Q)));
+
+R = P*inv(Q);
+kl = -0.5*(log(det(R))) + trace(eye(length(P))-R);
+
+%To get MI, just set P=cov(X,Y) and Q=blockdiag(cov(X),cov(Y)).  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/README.txt	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+KPMstats is a directory of miscellaneous statistics functions written by
+Kevin Patrick Murphy and various other people (see individual file headers).
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/beta_sample.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,76 @@
+function r = betarnd(a,b,m,n);
+%BETARND Random matrices from beta distribution.
+%   R = BETARND(A,B) returns a matrix of random numbers chosen   
+%   from the beta distribution with parameters A and B.
+%   The size of R is the common size of A and B if both are matrices.
+%   If either parameter is a scalar, the size of R is the size of the other
+%   parameter. Alternatively, R = BETARND(A,B,M,N) returns an M by N matrix. 
+
+%   Reference:
+%      [1]  L. Devroye, "Non-Uniform Random Variate Generation", 
+%      Springer-Verlag, 1986
+
+%   Copyright (c) 1993-98 by The MathWorks, Inc.
+%   $Revision: 1.1.1.1 $  $Date: 2005/04/26 02:29:18 $
+
+if nargin < 2, 
+    error('Requires at least two input arguments'); 
+end 
+
+if nargin == 2
+    [errorcode rows columns] = rndcheck(2,2,a,b);
+end
+
+if nargin == 3
+    [errorcode rows columns] = rndcheck(3,2,a,b,m);
+end
+
+if nargin == 4
+    [errorcode rows columns] = rndcheck(4,2,a,b,m,n);
+end
+
+if errorcode > 0
+    error('Size information is inconsistent.');
+end
+
+r = zeros(rows,columns);
+
+% Use Theorem 4.1, case A (Devroye, page 430) to derive beta
+%   random numbers as a ratio of gamma random numbers.
+if prod(size(a)) == 1
+    a1 = a(ones(rows,1),ones(columns,1));
+    g1 = gamrnd(a1,1);
+else
+    g1 = gamrnd(a,1);
+end
+if prod(size(b)) == 1
+    b1 = b(ones(rows,1),ones(columns,1));
+    g2 = gamrnd(b1,1);
+else
+    g2 = gamrnd(b,1);
+end
+r = g1 ./ (g1 + g2);
+
+% Return NaN if b is not positive.
+if any(any(b <= 0));
+    if prod(size(b) == 1)
+        tmp = NaN;
+        r = tmp(ones(rows,columns));
+    else
+        k = find(b <= 0);
+        tmp = NaN;
+        r(k) = tmp(ones(size(k)));
+    end
+end
+
+% Return NaN if a is not positive.
+if any(any(a <= 0));
+    if prod(size(a) == 1)
+        tmp = NaN;
+        r = tmp(ones(rows,columns));
+    else
+        k = find(a <= 0);
+        tmp = NaN;
+        r(k) = tmp(ones(size(k)));
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/chisquared_histo.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function s = chisquared_histo(h1, h2)
+% Measure distance between 2 histograms (small numbers means more similar)
+denom = h1 + h2;
+denom = denom + (denom==0);
+s = sum(((h1 - h2) .^ 2) ./ denom);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/chisquared_prob.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,35 @@
+function P = chisquared_prob(X2,v)
+%CHISQUARED_PROB computes the chi-squared probability function.
+%   P = CHISQUARED_PROB( X2, v ) returns P(X2|v), the probability
+%   of observing a chi-squared value <= X2 with v degrees of freedom.
+%   This is the probability that the sum of squares of v unit-variance
+%   normally-distributed random variables is <= X2.
+%   X2 and v may be matrices of the same size size, or either 
+%   may be a scalar.
+%   
+%   e.g., CHISQUARED_PROB(5.99,2) returns 0.9500, verifying the
+%   95% confidence bound for 2 degrees of freedom. This is also
+%   cross-checked in, e.g., Abramowitz & Stegun Table 26.8
+%
+%   See also CHISQUARED_TABLE
+%
+%Peter R. Shaw, WHOI
+
+% References: Press et al., Numerical Recipes, Cambridge, 1986;
+% Abramowitz & Stegun, Handbook of Mathematical Functions, Dover, 1972.
+
+% Peter R. Shaw, Woods Hole Oceanographic Institution
+% Woods Hole, MA 02543
+% (508) 457-2000 ext. 2473  pshaw@whoi.edu
+% March, 1990; fixed Oct 1992 for version 4
+
+% Computed using the Incomplete Gamma function,
+% as given by Press et al. (Recipes) eq. (6.2.17)
+
+% Following nonsense is necessary from Matlab version 3 -> version 4
+versn_str=version; eval(['versn=' versn_str(1) ';']);
+if versn<=3, %sigh
+ P = gamma(v/2, X2/2);
+else
+ P = gammainc(X2/2, v/2);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/chisquared_readme.txt	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+From ftp://ftp.mathworks.com/pub/contrib/v4/stats/chisquared/
+
+Chi-squared probability function.
+
+Abstract 
+m-files to compute the Chi-squared probability function, and
+the percentage points of the probability function.
+
+P = CHISQUARED_PROB( X2, v ) returns P(X2|v), the probability
+of observing a chi-squared value <= X2 with v degrees of freedom.
+This is the probability that the sum of squares of v unit-variance
+normally-distributed random variables is <= X2.
+
+Conversely:
+X2 = CHISQUARED_TABLE( P, v ) returns the X2, the value of
+chi-squared corresponding to v degrees of freedom and probability P.
+
+In reference textbooks, what is normally tabulated are the
+percentage points of the chi-squared distribution; thus, one
+would use CHISQUARED_TABLE rather than interpolate such a table.
+
+References: Press et al., Numerical Recipes, Cambridge, 1986;
+Abramowitz & Stegun, Handbook of Mathematical Functions,
+Dover, 1972;  Table 26.8
+
+Peter R. Shaw
+Woods Hole Oceanographic Institution, Woods Hole, MA 02543
+(508) 457-2000 ext. 2473
+pshaw@whoi.edu
+
+--FILES GENERATED--
+README_chisq
+chisquared_prob.m  (function) -- chi-squared probability function
+chisquared_table.m  (function) -- "percentage points" (i.e., inverse)
+                                   of chi-squared probability function
+chiaux.m (function) -- auxiliary fn. used by chisquared_table
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/chisquared_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,63 @@
+function X2 = chisquared_table(P,v)
+%CHISQUARED_TABLE computes the "percentage points" of the
+%chi-squared distribution, as in Abramowitz & Stegun Table 26.8
+%   X2 = CHISQUARED_TABLE( P, v ) returns the value of chi-squared 
+%   corresponding to v degrees of freedom and probability P.
+%   P is the probability that the sum of squares of v unit-variance
+%   normally-distributed random variables is <= X2.
+%   P and v may be matrices of the same size size, or either 
+%   may be a scalar.
+%
+%   e.g., to find the 95% confidence interval for 2 degrees
+%   of freedom, use CHISQUARED_TABLE( .95, 2 ), yielding 5.99,
+%   in agreement with Abramowitz & Stegun's Table 26.8
+%
+%   This result can be checked through the function
+%   CHISQUARED_PROB( 5.99, 2 ), yielding 0.9500
+%
+%   The familiar 1.96-sigma confidence bounds enclosing 95% of
+%   a 1-D gaussian is found through 
+%   sqrt( CHISQUARED_TABLE( .95, 1 )), yielding 1.96
+%
+%   See also CHISQUARED_PROB
+%
+%Peter R. Shaw, WHOI
+%Leslie Rosenfeld, MBARI
+
+% References: Press et al., Numerical Recipes, Cambridge, 1986;
+% Abramowitz & Stegun, Handbook of Mathematical Functions, Dover, 1972.
+
+% Peter R. Shaw, Woods Hole Oceanographic Institution
+% Woods Hole, MA 02543  pshaw@whoi.edu
+% Leslie Rosenfeld, MBARI
+% Last revision: Peter Shaw, Oct 1992: fsolve with version 4
+
+% ** Calls function CHIAUX  **
+% Computed using the Incomplete Gamma function,
+% as given by Press et al. (Recipes) eq. (6.2.17)
+
+[mP,nP]=size(P);
+[mv,nv]=size(v);
+if mP~=mv | nP~=nv, 
+  if mP==1 & nP==1,
+    P=P*ones(mv,nv);
+  elseif mv==1 & nv==1,
+    v=v*ones(mP,nP);
+  else
+    error('P and v must be the same size')
+  end
+end
+[m,n]=size(P);  X2 = zeros(m,n);
+for i=1:m,
+ for j=1:n,
+  if v(i,j)<=10, 
+   x0=P(i,j)*v(i,j);
+  else
+   x0=v(i,j);
+  end
+% Note: "old" and "new" calls to fsolve may or may not follow 
+% Matlab version 3.5 -> version 4 (so I'm keeping the old call around...)
+%   X2(i,j) = fsolve('chiaux',x0,zeros(16,1),[v(i,j),P(i,j)]); %(old call)
+   X2(i,j) = fsolve('chiaux',x0,zeros(16,1),[],[v(i,j),P(i,j)]);
+ end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/clg_Mstep.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,203 @@
+function [mu, Sigma, B] = clg_Mstep(w, Y, YY, YTY, X, XX, XY, varargin)
+% MSTEP_CLG Compute ML/MAP estimates for a conditional linear Gaussian
+% [mu, Sigma, B] = Mstep_clg(w, Y, YY, YTY, X, XX, XY, varargin)
+%
+% We fit P(Y|X,Q=i) = N(Y; B_i X + mu_i, Sigma_i) 
+% and w(i,t) = p(M(t)=i|y(t)) = posterior responsibility
+% See www.ai.mit.edu/~murphyk/Papers/learncg.pdf.
+%
+% See process_options for how to specify the input arguments.
+%
+% INPUTS:
+% w(i) = sum_t w(i,t) = responsibilities for each mixture component
+%  If there is only one mixture component (i.e., Q does not exist),
+%  then w(i) = N = nsamples,  and 
+%  all references to i can be replaced by 1.
+% Y(:,i) = sum_t w(i,t) y(:,t) = weighted observations
+% YY(:,:,i) = sum_t w(i,t) y(:,t) y(:,t)' = weighted outer product
+% YTY(i) = sum_t w(i,t) y(:,t)' y(:,t) = weighted inner product
+%   You only need to pass in YTY if Sigma is to be estimated as spherical.
+%
+% In the regression context, we must also pass in the following
+% X(:,i) = sum_t w(i,t) x(:,t) = weighted inputs
+% XX(:,:,i) = sum_t w(i,t) x(:,t) x(:,t)' = weighted outer product
+% XY(i) = sum_t w(i,t) x(:,t) y(:,t)' = weighted outer product
+%
+% Optional inputs (default values in [])
+%
+% 'cov_type' - 'full', 'diag' or 'spherical' ['full']
+% 'tied_cov' - 1 (Sigma) or 0 (Sigma_i) [0]
+% 'clamped_cov' - pass in clamped value, or [] if unclamped [ [] ]
+% 'clamped_mean' - pass in clamped value, or [] if unclamped [ [] ]
+% 'clamped_weights' - pass in clamped value, or [] if unclamped [ [] ]
+% 'cov_prior' - added to Sigma(:,:,i) to ensure psd [0.01*eye(d,d,Q)]
+%
+% If cov is tied, Sigma has size d*d.
+% But diagonal and spherical covariances are represented in full size.
+
+[cov_type, tied_cov, ...
+ clamped_cov, clamped_mean, clamped_weights,  cov_prior, ...
+ xs, ys, post] = ...
+    process_options(varargin, ...
+		    'cov_type', 'full', 'tied_cov', 0,  'clamped_cov', [], 'clamped_mean', [], ...
+		    'clamped_weights', [], 'cov_prior', [], ...
+		    'xs', [], 'ys', [], 'post', []);
+
+[Ysz Q] = size(Y);
+
+if isempty(X) % no regression
+  %B = [];
+  B2 = zeros(Ysz, 1, Q);
+  for i=1:Q
+    B(:,:,i) = B2(:,1:0,i); % make an empty array of size Ysz x 0 x Q
+  end
+  [mu, Sigma] = mixgauss_Mstep(w, Y, YY, YTY, varargin{:});
+  return;
+end
+
+
+N = sum(w);
+if isempty(cov_prior)
+  cov_prior = 0.01*repmat(eye(Ysz,Ysz), [1 1 Q]);
+end
+%YY = YY + cov_prior; % regularize the scatter matrix
+
+% Set any zero weights to one before dividing
+% This is valid because w(i)=0 => Y(:,i)=0, etc
+w = w + (w==0);
+
+Xsz = size(X,1);
+% Append 1 to X to get Z
+ZZ = zeros(Xsz+1, Xsz+1, Q);
+ZY = zeros(Xsz+1, Ysz, Q);
+for i=1:Q
+  ZZ(:,:,i) = [XX(:,:,i)  X(:,i);
+	       X(:,i)'    w(i)];
+  ZY(:,:,i) = [XY(:,:,i);
+	       Y(:,i)'];
+end
+
+
+%%% Estimate mean and regression 
+
+if ~isempty(clamped_weights) & ~isempty(clamped_mean)
+  B = clamped_weights;
+  mu = clamped_mean;
+end
+if ~isempty(clamped_weights) & isempty(clamped_mean)
+  B = clamped_weights;
+  % eqn 5
+  mu = zeros(Ysz, Q);
+  for i=1:Q
+    mu(:,i) = (Y(:,i) - B(:,:,i)*X(:,i)) / w(i);
+  end
+end
+if isempty(clamped_weights) & ~isempty(clamped_mean)
+  mu = clamped_mean;
+  % eqn 3
+  B = zeros(Ysz, Xsz, Q);
+  for i=1:Q
+    tmp = XY(:,:,i)' - mu(:,i)*X(:,i)';
+    %B(:,:,i) = tmp * inv(XX(:,:,i));
+    B(:,:,i) = (XX(:,:,i) \ tmp')';
+  end
+end
+if isempty(clamped_weights) & isempty(clamped_mean)
+  mu = zeros(Ysz, Q);
+  B = zeros(Ysz, Xsz, Q);
+  % Nothing is clamped, so we must estimate B and mu jointly
+  for i=1:Q
+    % eqn 9
+    if rcond(ZZ(:,:,i)) < 1e-10
+      sprintf('clg_Mstep warning: ZZ(:,:,%d) is ill-conditioned', i);
+      % probably because there are too few cases for a high-dimensional input
+      ZZ(:,:,i) = ZZ(:,:,i) + 1e-5*eye(Xsz+1);
+    end
+    %A = ZY(:,:,i)' * inv(ZZ(:,:,i));
+    A = (ZZ(:,:,i) \ ZY(:,:,i))';
+    B(:,:,i) = A(:, 1:Xsz);
+    mu(:,i) = A(:, Xsz+1);
+  end
+end
+
+if ~isempty(clamped_cov)
+  Sigma = clamped_cov;
+  return;
+end
+
+
+%%% Estimate covariance
+
+% Spherical
+if cov_type(1)=='s'
+  if ~tied_cov
+    Sigma = zeros(Ysz, Ysz, Q);
+    for i=1:Q
+      % eqn 16
+      A = [B(:,:,i) mu(:,i)];
+      %s = trace(YTY(i) + A'*A*ZZ(:,:,i) - 2*A*ZY(:,:,i)) / (Ysz*w(i)); % wrong!
+      s = (YTY(i) + trace(A'*A*ZZ(:,:,i)) - trace(2*A*ZY(:,:,i))) / (Ysz*w(i));
+      Sigma(:,:,i) = s*eye(Ysz,Ysz);
+
+      %%%%%%%%%%%%%%%%%%% debug
+      if ~isempty(xs)
+	[nx T] = size(xs);
+	zs = [xs; ones(1,T)];
+	yty = 0;
+	zAAz = 0;
+	yAz = 0;
+	for t=1:T
+	  yty = yty + ys(:,t)'*ys(:,t) * post(i,t);
+	  zAAz = zAAz + zs(:,t)'*A'*A*zs(:,t)*post(i,t);
+	  yAz = yAz + ys(:,t)'*A*zs(:,t)*post(i,t);
+	end
+	assert(approxeq(yty, YTY(i)))
+	assert(approxeq(zAAz, trace(A'*A*ZZ(:,:,i))))
+	assert(approxeq(yAz, trace(A*ZY(:,:,i))))
+	s2 = (yty + zAAz - 2*yAz) / (Ysz*w(i));
+	assert(approxeq(s,s2))
+      end
+      %%%%%%%%%%%%%%% end debug
+      
+    end
+  else
+    S = 0;
+    for i=1:Q
+      % eqn 18
+      A = [B(:,:,i) mu(:,i)];
+      S = S + trace(YTY(i) + A'*A*ZZ(:,:,i) - 2*A*ZY(:,:,i));
+    end
+    Sigma = repmat(S / (N*Ysz), [1 1 Q]);
+  end
+else % Full/diagonal
+  if ~tied_cov
+    Sigma = zeros(Ysz, Ysz, Q);
+    for i=1:Q
+      A = [B(:,:,i) mu(:,i)];
+      % eqn 10
+      SS = (YY(:,:,i) - ZY(:,:,i)'*A' - A*ZY(:,:,i) + A*ZZ(:,:,i)*A') / w(i);
+      if cov_type(1)=='d'
+	Sigma(:,:,i) = diag(diag(SS));
+      else
+	Sigma(:,:,i) = SS;
+      end
+    end
+  else % tied
+    SS = zeros(Ysz, Ysz);
+    for i=1:Q
+      A = [B(:,:,i) mu(:,i)];
+      % eqn 13
+      SS = SS + (YY(:,:,i) - ZY(:,:,i)'*A' - A*ZY(:,:,i) + A*ZZ(:,:,i)*A');
+    end
+    SS = SS / N;
+    if cov_type(1)=='d'
+      Sigma = diag(diag(SS));
+    else
+      Sigma = SS;
+    end
+    Sigma = repmat(Sigma, [1 1 Q]);
+  end
+end
+
+Sigma = Sigma + cov_prior;
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/clg_Mstep_simple.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+function [mu, B] = clg_Mstep_simple(w, Y, YY, YTY, X, XX, XY)
+% CLG_MSTEP_SIMPLE Same as CLG_MSTEP, but doesn;t estimate Sigma,  so is slightly faster
+% function [mu, B] = clg_Mstep_simple(w, Y, YY, YTY, X, XX, XY)
+%
+% See clg_Mstep for details.
+% Unlike clg_Mstep, there are no optional arguments, which are slow to process
+% if this function is inside a tight loop.
+
+[Ysz Q] = size(Y);
+
+if isempty(X) % no regression
+  %B = [];
+  B2 = zeros(Ysz, 1, Q);
+  for i=1:Q
+    B(:,:,i) = B2(:,1:0,i); % make an empty array of size Ysz x 0 x Q
+  end
+  [mu, Sigma] = mixgauss_Mstep(w, Y, YY, YTY);
+  return;
+end
+
+N = sum(w);
+%YY = YY + cov_prior; % regularize the scatter matrix
+
+% Set any zero weights to one before dividing
+% This is valid because w(i)=0 => Y(:,i)=0, etc
+w = w + (w==0);
+
+Xsz = size(X,1);
+% Append 1 to X to get Z
+ZZ = zeros(Xsz+1, Xsz+1, Q);
+ZY = zeros(Xsz+1, Ysz, Q);
+for i=1:Q
+  ZZ(:,:,i) = [XX(:,:,i)  X(:,i);
+	       X(:,i)'    w(i)];
+  ZY(:,:,i) = [XY(:,:,i);
+	       Y(:,i)'];
+end
+
+mu = zeros(Ysz, Q);
+B = zeros(Ysz, Xsz, Q);
+for i=1:Q
+  % eqn 9
+  if rcond(ZZ(:,:,i)) < 1e-10
+    sprintf('clg_Mstep warning: ZZ(:,:,%d) is ill-conditioned', i);
+    %probably because there are too few cases for a high-dimensional input
+    ZZ(:,:,i) = ZZ(:,:,i) + 1e-5*eye(Xsz+1);
+  end
+  %A = ZY(:,:,i)' * inv(ZZ(:,:,i));
+  A = (ZZ(:,:,i) \ ZY(:,:,i))';
+  B(:,:,i) = A(:, 1:Xsz);
+  mu(:,i) = A(:, Xsz+1);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/clg_prob.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+function p = eval_pdf_clg(X,Y,mu,Sigma,W)
+% function p = eval_pdf_clg(X,Y,mu,Sigma,W)
+%
+% p(c,t) = N(Y(:,t); mu(:,c) + W(:,:,c)*X(:,t), Sigma(:,:,c))
+
+[d T] = size(Y);
+[d nc] = size(mu);
+p = zeros(nc,T);
+for c=1:nc
+  denom = (2*pi)^(d/2)*sqrt(abs(det(Sigma(:,:,c))));
+  M = repmat(mu(:,c), 1, T) + W(:,:,c)*X;
+  mahal = sum(((Y-M)'*inv(Sigma(:,:,c))).*(Y-M)',2); 
+  p(c,:) = (exp(-0.5*mahal) / denom)';
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/condGaussToJoint.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function [muXY, SigmaXY] = condGaussToJoint(muX, SigmaX, muY, SigmaY, WYgivenX)
+
+% Compute P(X,Y) from P(X) * P(Y|X) where P(X)=N(X;muX,SigmaX) 
+% and P(Y|X) = N(Y; WX + muY, SigmaY)
+
+% For details on how to compute a Gaussian from a Bayes net
+% - "Gaussian Influence Diagrams", R. Shachter and C. R. Kenley, Management Science, 35(5):527--550, 1989.
+
+% size(W) = dy x dx
+dx = length(muX);
+dy = length(muY);
+muXY = [muX(:); WYgivenX*muX(:) + muY];
+
+W = [zeros(dx,dx) WYgivenX';
+     zeros(dy,dx) zeros(dy,dy)];
+D = [SigmaX       zeros(dx,dy);
+     zeros(dy,dx) SigmaY];
+
+U = inv(eye(size(W)) - W')';
+SigmaXY = U' * D * U;
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/cond_indep_fisher_z.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,142 @@
+function [CI, r, p] = cond_indep_fisher_z(X, Y, S, C, N, alpha)
+% COND_INDEP_FISHER_Z Test if X indep Y given Z using Fisher's Z test
+% CI = cond_indep_fisher_z(X, Y, S, C, N, alpha)
+%
+% C is the covariance (or correlation) matrix
+% N is the sample size
+% alpha is the significance level (default: 0.05)
+%
+% See p133 of T. Anderson, "An Intro. to Multivariate Statistical Analysis", 1984
+
+if nargin < 6, alpha = 0.05; end
+
+r = partial_corr_coef(C, X, Y, S);
+z = 0.5*log( (1+r)/(1-r) );
+z0 = 0;
+W = sqrt(N - length(S) - 3)*(z-z0); % W ~ N(0,1)
+cutoff = norminv(1 - 0.5*alpha); % P(|W| <= cutoff) = 0.95
+%cutoff = mynorminv(1 - 0.5*alpha); % P(|W| <= cutoff) = 0.95
+if abs(W) < cutoff
+  CI = 1;
+else % reject the null hypothesis that rho = 0
+  CI = 0;
+end
+p = normcdf(W);
+%p = mynormcdf(W);
+
+%%%%%%%%%
+
+function p = normcdf(x,mu,sigma)
+%NORMCDF Normal cumulative distribution function (cdf).
+%   P = NORMCDF(X,MU,SIGMA) computes the normal cdf with mean MU and
+%   standard deviation SIGMA at the values in X.
+%
+%   The size of P is the common size of X, MU and SIGMA. A scalar input  
+%   functions as a constant matrix of the same size as the other inputs.    
+%
+%   Default values for MU and SIGMA are 0 and 1 respectively.
+
+%   References:
+%      [1]  M. Abramowitz and I. A. Stegun, "Handbook of Mathematical
+%      Functions", Government Printing Office, 1964, 26.2.
+
+%   Copyright (c) 1993-98 by The MathWorks, Inc.
+%   $Revision: 1.1.1.1 $  $Date: 2005/04/26 02:29:18 $
+
+if nargin < 3, 
+    sigma = 1;
+end
+
+if nargin < 2;
+    mu = 0;
+end
+
+[errorcode x mu sigma] = distchck(3,x,mu,sigma);
+
+if errorcode > 0
+    error('Requires non-scalar arguments to match in size.');
+end
+
+%   Initialize P to zero.
+p = zeros(size(x));
+
+% Return NaN if SIGMA is not positive.
+k1 = find(sigma <= 0);
+if any(k1)
+    tmp   = NaN;
+    p(k1) = tmp(ones(size(k1))); 
+end
+
+% Express normal CDF in terms of the error function.
+k = find(sigma > 0);
+if any(k)
+    p(k) = 0.5 * erfc( - (x(k) - mu(k)) ./ (sigma(k) * sqrt(2)));
+end
+
+% Make sure that round-off errors never make P greater than 1.
+k2 = find(p > 1);
+if any(k2)
+    p(k2) = ones(size(k2));
+end
+
+%%%%%%%%
+
+function x = norminv(p,mu,sigma);
+%NORMINV Inverse of the normal cumulative distribution function (cdf).
+%   X = NORMINV(P,MU,SIGMA) finds the inverse of the normal cdf with
+%   mean, MU, and standard deviation, SIGMA.
+%
+%   The size of X is the common size of the input arguments. A scalar input  
+%   functions as a constant matrix of the same size as the other inputs.    
+%
+%   Default values for MU and SIGMA are 0 and 1 respectively.
+
+%   References:
+%      [1]  M. Abramowitz and I. A. Stegun, "Handbook of Mathematical
+%      Functions", Government Printing Office, 1964, 7.1.1 and 26.2.2
+
+%   Copyright (c) 1993-98 by The MathWorks, Inc.
+%   $Revision: 1.1.1.1 $  $Date: 2005/04/26 02:29:18 $
+
+if nargin < 3, 
+    sigma = 1;
+end
+
+if nargin < 2;
+    mu = 0;
+end
+
+[errorcode p mu sigma] = distchck(3,p,mu,sigma);
+
+if errorcode > 0
+    error('Requires non-scalar arguments to match in size.');
+end
+
+% Allocate space for x.
+x = zeros(size(p));
+
+% Return NaN if the arguments are outside their respective limits.
+k = find(sigma <= 0 | p < 0 | p > 1);
+if any(k)
+    tmp  = NaN;
+    x(k) = tmp(ones(size(k))); 
+end
+
+% Put in the correct values when P is either 0 or 1.
+k = find(p == 0);
+if any(k)
+    tmp  = Inf;
+    x(k) = -tmp(ones(size(k)));
+end
+
+k = find(p == 1);
+if any(k)
+    tmp  = Inf;
+    x(k) = tmp(ones(size(k))); 
+end
+
+% Compute the inverse function for the intermediate values.
+k = find(p > 0  &  p < 1 & sigma > 0);
+if any(k),
+    x(k) = sqrt(2) * sigma(k) .* erfinv(2 * p(k) - 1) + mu(k);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/condgaussTrainObserved.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,27 @@
+function [mu, Sigma] = mixgaussTrainObserved(obsData, hiddenData, nstates, varargin);
+% mixgaussTrainObserved Max likelihood estimates of conditional Gaussian from raw data
+% function [mu, Sigma] = mixgaussTrainObserved(obsData, hiddenData, nstates, ...);
+%
+% Input:
+% obsData(:,i)
+% hiddenData(i)  - this is the mixture component label for example i
+% Optional arguments - same as mixgauss_Mstep
+%
+% Output:
+% mu(:,q)
+% Sigma(:,:,q) - same as mixgauss_Mstep
+
+[D numex] = size(obsData);
+Y = zeros(D, nstates);
+YY = zeros(D,D,nstates);
+YTY = zeros(nstates,1);
+w = zeros(nstates, 1);
+for q=1:nstates
+  ndx = find(hiddenData==q);
+  w(q) = length(ndx); % each data point has probability 1 of being in this cluster
+  data = obsData(:,ndx);
+  Y(:,q) = sum(data,2);
+  YY(:,:,q) = data*data';
+  YTY(q) = sum(diag(data'*data));
+end
+[mu, Sigma] = mixgauss_Mstep(w, Y, YY, YTY, varargin{:});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/condgauss_sample.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function x = mixgauss_sample(mu, Sigma, labels)
+% MIXGAUSS_SAMPLE Sample from a mixture of Gaussians given known mixture labels
+% function x = mixgauss_sample(mu, Sigma, labels)
+
+T = length(labels);
+[D Q] = size(mu);
+x = zeros(D,T);
+for q=1:Q
+  ndx = find(labels==q);
+  x(:,ndx) = gaussian_sample(mu(:,q)', Sigma(:,:,q), length(ndx))';
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/convertBinaryLabels.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+% labels01 = (labelsPM+1)/2; % maps -1->0, +1->1
+% labelsPM = (2*labels01)-1; % maps 0,1 -> -1,1
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/cwr_demo.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,124 @@
+% Compare my code with
+% http://www.media.mit.edu/physics/publications/books/nmm/files/index.html
+%
+% cwm.m
+% (c) Neil Gershenfeld  9/1/97
+% 1D Cluster-Weighted Modeling example
+%
+clear all
+figure;
+seed = 0;
+rand('state', seed);
+randn('state', seed);
+x = (-10:10)';
+y = (x > 0);
+npts = length(x);
+plot(x,y,'+')
+xlabel('x')
+ylabel('y')
+nclusters = 4;
+nplot = 100;
+xplot = 24*(1:nplot)'/nplot - 12;
+
+mux = 20*rand(1,nclusters) - 10;
+muy = zeros(1,nclusters);
+varx = ones(1,nclusters);
+vary = ones(1,nclusters);
+pc = 1/nclusters * ones(1,nclusters);
+niterations = 5;
+eps = 0.01;
+  
+
+I = repmat(eye(1,1), [1 1 nclusters]);
+O = repmat(zeros(1,1), [1 1 nclusters]);
+X = x(:)';
+Y = y(:)';
+
+cwr = cwr_em(X, Y, nclusters, 'muX', mux, 'muY', muy,  'SigmaX', I, ...
+	     'cov_typeX', 'spherical', 'SigmaY', I, 'cov_typeY', 'spherical', ...
+	     'priorC', pc, 'weightsY', O,  'create_init_params', 0, ...
+	     'clamp_weights', 1, 'max_iter', niterations, ...
+	     'cov_priorX', eps*ones(1,1,nclusters), ...
+	     'cov_priorY', eps*ones(1,1,nclusters));
+
+
+% Gershenfeld's EM code
+for step = 1:niterations
+    pplot = exp(-(kron(xplot,ones(1,nclusters)) ...
+		  - kron(ones(nplot,1),mux)).^2 ...
+		./ (2*kron(ones(nplot,1),varx))) ...
+	    ./ sqrt(2*pi*kron(ones(nplot,1),varx)) ...
+	    .* kron(ones(nplot,1),pc);
+    plot(xplot,pplot,'k');
+    pause(0);
+    px = exp(-(kron(x,ones(1,nclusters)) ...
+	       - kron(ones(npts,1),mux)).^2 ...
+	     ./ (2*kron(ones(npts,1),varx))) ...
+	 ./ sqrt(2*pi*kron(ones(npts,1),varx));
+    py = exp(-(kron(y,ones(1,nclusters)) ...
+	       - kron(ones(npts,1),muy)).^2 ...
+	     ./ (2*kron(ones(npts,1),vary))) ...
+	 ./ sqrt(2*pi*kron(ones(npts,1),vary));
+    p = px .* py .* kron(ones(npts,1),pc);
+    pp = p ./ kron(sum(p,2),ones(1,nclusters));
+    pc = sum(pp)/npts;
+    yfit = sum(kron(ones(npts,1),muy) .* p,2) ...
+	   ./ sum(p,2);
+    mux = sum(kron(x,ones(1,nclusters)) .* pp) ...
+	  ./ (npts*pc);
+    varx = eps + sum((kron(x,ones(1,nclusters)) ...
+		      - kron(ones(npts,1),mux)).^2 .* pp) ...
+	   ./ (npts*pc);
+    muy = sum(kron(y,ones(1,nclusters)) .* pp) ...
+	  ./ (npts*pc);
+    vary = eps + sum((kron(y,ones(1,nclusters)) ...
+		      - kron(ones(npts,1),muy)).^2 .* pp) ...
+	   ./ (npts*pc);
+end
+
+
+% Check equal
+cwr_pc = cwr.priorC';
+assert(approxeq(cwr_pc, pc))
+cwr_mux = cwr.muX;
+assert(approxeq(mux, cwr_mux))
+cwr_SigmaX = squeeze(cwr.SigmaX)';
+assert(approxeq(varx, cwr_SigmaX))
+cwr_muy = cwr.muY;
+assert(approxeq(muy, cwr_muy))
+cwr_SigmaY = squeeze(cwr.SigmaY)';
+assert(approxeq(vary, cwr_SigmaY))
+
+
+% Prediction
+
+X = xplot(:)';
+[cwr_mu, Sigma, post] = cwr_predict(cwr, X);
+cwr_ystd = squeeze(Sigma)';
+
+% pplot(t,c)
+pplot = exp(-(kron(xplot,ones(1,nclusters)) ...
+   - kron(ones(nplot,1),mux)).^2 ...
+   ./ (2*kron(ones(nplot,1),varx))) ...
+   ./ sqrt(2*pi*kron(ones(nplot,1),varx)) ...
+   .* kron(ones(nplot,1),pc);
+yplot = sum(kron(ones(nplot,1),muy) .* pplot,2) ...
+   ./ sum(pplot,2);
+ystdplot = sum(kron(ones(nplot,1),(muy.^2+vary)) .* pplot,2) ...
+   ./ sum(pplot,2) - yplot.^2;
+
+
+% Check equal
+assert(approxeq(yplot(:)', cwr_mu(:)'))
+assert(approxeq(ystdplot, cwr_ystd))
+assert(approxeq(pplot ./ repmat(sum(pplot,2), 1, nclusters),post') )
+
+plot(xplot,yplot,'k');
+hold on
+plot(xplot,yplot+ystdplot,'k--');
+plot(xplot,yplot-ystdplot,'k--');
+plot(x,y,'k+');
+axis([-12 12 -1 1.1]);
+plot(xplot,.8*pplot/max(max(pplot))-1,'k')
+hold off
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/cwr_em.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,161 @@
+function cwr  = cwr_em(X, Y, nc, varargin)
+% CWR_LEARN Fit the parameters of a cluster weighted regression model using EM
+% function cwr  = cwr_learn(X, Y, ...)
+%
+% X(:, t) is the t'th input example
+% Y(:, t) is the t'th output example
+% nc is the number of clusters
+%
+% Kevin Murphy, May 2003
+
+[max_iter, thresh, cov_typeX, cov_typeY, clamp_weights, ...
+ muX, muY, SigmaX, SigmaY, weightsY, priorC, create_init_params, ...
+cov_priorX, cov_priorY, verbose, regress, clamp_covX, clamp_covY] = process_options(...
+    varargin, 'max_iter', 10, 'thresh', 1e-2, 'cov_typeX', 'full', ...
+     'cov_typeY', 'full', 'clamp_weights', 0, ...
+     'muX', [], 'muY', [], 'SigmaX', [], 'SigmaY', [], 'weightsY', [], 'priorC', [], ...
+     'create_init_params', 1, 'cov_priorX', [], 'cov_priorY', [], 'verbose', 0, ...
+    'regress', 1, 'clamp_covX', 0, 'clamp_covY', 0);
+     
+[nx N] = size(X);
+[ny N2] = size(Y);
+if N ~= N2
+  error(sprintf('nsamples X (%d) ~= nsamples Y (%d)', N, N2));
+end
+%if N < nx 
+%  fprintf('cwr_em warning: dim X (%d) > nsamples X (%d)\n', nx, N);
+%end
+if (N < nx) & regress
+  fprintf('cwr_em warning: dim X = %d, nsamples X = %d\n', nx, N);
+end
+if (N < ny) 
+  fprintf('cwr_em warning: dim Y = %d, nsamples Y = %d\n', ny, N);
+end
+if (nc > N) 
+  error(sprintf('cwr_em: more centers (%d) than data', nc))
+end
+
+if nc==1
+  % No latent variable, so there is a closed-form solution
+  w = 1/N;
+  WYbig = Y*w;
+  WYY = WYbig * Y'; 
+  WY = sum(WYbig, 2);
+  WYTY = sum(diag(WYbig' * Y));
+  cwr.priorC = 1;
+  cwr.SigmaX = [];
+  if ~regress
+    % This is just fitting an unconditional Gaussian
+    cwr.weightsY = [];
+    [cwr.muY, cwr.SigmaY] = ...
+	mixgauss_Mstep(1, WY, WYY, WYTY, ...
+		       'cov_type', cov_typeY, 'cov_prior', cov_priorY);
+    % There is a much easier way...
+    assert(approxeq(cwr.muY, mean(Y')))
+    assert(approxeq(cwr.SigmaY, cov(Y') + 0.01*eye(ny)))
+  else
+    % This is just linear regression
+    WXbig = X*w;
+    WXX = WXbig * X';
+   WX = sum(WXbig, 2);
+    WXTX = sum(diag(WXbig' * X));
+    WXY = WXbig * Y';
+    [cwr.muY, cwr.SigmaY, cwr.weightsY] = ...
+	clg_Mstep(1, WY, WYY, WYTY, WX, WXX, WXY, ...
+		  'cov_type', cov_typeY, 'cov_prior', cov_priorY);
+  end
+  if clamp_covY, cwr.SigmaY = SigmaY; end
+  if clamp_weights,  cwr.weightsY = weightsY; end
+  return;
+end
+
+
+if create_init_params
+  [cwr.muX, cwr.SigmaX] = mixgauss_init(nc, X, cov_typeX);
+  [cwr.muY, cwr.SigmaY] = mixgauss_init(nc, Y, cov_typeY);
+  cwr.weightsY = zeros(ny, nx, nc);
+  cwr.priorC = normalize(ones(nc,1));
+else
+  cwr.muX = muX;  cwr.muY = muY; cwr.SigmaX = SigmaX; cwr.SigmaY = SigmaY;
+  cwr.weightsY = weightsY; cwr.priorC = priorC;
+end
+
+
+if clamp_covY, cwr.SigmaY = SigmaY; end
+if clamp_covX,  cwr.SigmaX = SigmaX; end
+if clamp_weights,  cwr.weightsY = weightsY; end
+
+previous_loglik = -inf;
+num_iter = 1;
+converged = 0;
+
+while (num_iter <= max_iter) & ~converged
+
+  % E step
+  
+  [likXandY, likYgivenX, post] = cwr_prob(cwr, X, Y);
+  loglik = sum(log(likXandY));
+  % extract expected sufficient statistics
+  w = sum(post,2);  % post(c,t)
+  WYY = zeros(ny, ny, nc);
+  WY = zeros(ny, nc);
+  WYTY = zeros(nc,1);
+  
+  WXX = zeros(nx, nx, nc);
+  WX = zeros(nx, nc);
+  WXTX = zeros(nc, 1);
+  WXY = zeros(nx,ny,nc);
+  %WYY = repmat(reshape(w, [1 1 nc]), [ny ny 1]) .*  repmat(Y*Y', [1 1 nc]);
+  for c=1:nc
+    weights = repmat(post(c,:), ny, 1);
+    WYbig = Y .* weights;
+    WYY(:,:,c) = WYbig * Y'; 
+    WY(:,c) = sum(WYbig, 2);
+    WYTY(c) = sum(diag(WYbig' * Y));
+
+    weights = repmat(post(c,:), nx, 1); % weights(nx, nsamples)
+    WXbig = X .* weights;
+    WXX(:,:,c) = WXbig * X';
+    WX(:,c) = sum(WXbig, 2);
+    WXTX(c) = sum(diag(WXbig' * X));
+    WXY(:,:,c) = WXbig * Y';
+  end
+
+  % M step
+  % Q -> X is called Q->Y in Mstep_clg
+  [cwr.muX, cwr.SigmaX] = mixgauss_Mstep(w, WX, WXX, WXTX, ...
+			    'cov_type', cov_typeX, 'cov_prior', cov_priorX);
+  for c=1:nc
+    assert(is_psd(cwr.SigmaX(:,:,c)))
+  end
+  
+  if clamp_weights % affects estimate of mu and Sigma
+    W = cwr.weightsY;
+  else
+    W = [];
+  end
+  [cwr.muY, cwr.SigmaY, cwr.weightsY] = ...
+      clg_Mstep(w, WY, WYY, WYTY, WX, WXX, WXY, ...
+		'cov_type', cov_typeY, 'clamped_weights', W, ...
+		'cov_prior', cov_priorY);
+  %'xs', X, 'ys', Y, 'post', post); % debug
+  %a = linspace(min(Y(2,:)), max(Y(2,:)), nc+2);
+  %cwr.muY(2,:) = a(2:end-1);
+
+  cwr.priorC = normalize(w);
+
+  for c=1:nc
+    assert(is_psd(cwr.SigmaY(:,:,c)))
+  end
+
+  if clamp_covY, cwr.SigmaY = SigmaY; end
+  if clamp_covX,  cwr.SigmaX = SigmaX; end
+  if clamp_weights,  cwr.weightsY = weightsY; end
+
+  if verbose, fprintf(1, 'iteration %d, loglik = %f\n', num_iter, loglik); end
+  num_iter =  num_iter + 1;
+  converged = em_converged(loglik, previous_loglik, thresh);
+  previous_loglik = loglik;
+  
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/cwr_predict.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+function  [mu, Sigma, weights, mask] = cwr_predict(cwr, X, mask_data)
+% CWR_PREDICT cluster weighted regression: predict Y given X 
+% function  [mu, Sigma] = cwr_predict(cwr, X)
+% 
+% mu(:,t) = E[Y|X(:,t)] = sum_c P(c | X(:,t)) E[Y|c, X(:,t)]
+% Sigma(:,:,t) = Cov[Y|X(:,t)]
+%
+% [mu, Sigma, weights, mask] = cwr_predict(cwr, X, mask_data)
+% mask(i) = sum_t sum_c p(mask_data(:,i) | X(:,t), c) P(c|X(:,t))
+% This evaluates the predictive density on a set of points
+% (This is only sensible if T=1, ie. X is a single vector)
+
+[nx T] = size(X);
+[ny nx nc] = size(cwr.weightsY);
+mu = zeros(ny, T);
+Sigma = zeros(ny, ny, T);
+
+if nargout == 4
+  comp_mask = 1;
+  N = size(mask_data,2);
+  mask = zeros(N,1);
+else
+  comp_mask = 0;
+end
+
+if nc==1
+  if isempty(cwr.weightsY)
+    mu = repmat(cwr.muY, 1, T);
+    Sigma = repmat(cwr.SigmaY, [1 1 T]);
+  else
+    mu = repmat(cwr.muY, 1, T) + cwr.weightsY * X;
+    Sigma = repmat(cwr.SigmaY, [1 1 T]);
+    %for t=1:T
+    %  mu(:,t) = cwr.muY + cwr.weightsY*X(:,t);
+    %  Sigma(:,:,t) = cwr.SigmaY;
+    %end
+  end
+  if comp_mask, mask = gaussian_prob(mask_data, mu, Sigma); end
+  weights = [];
+  return;
+end
+
+
+% likX(c,t) = p(x(:,t) | c)
+likX = mixgauss_prob(X, cwr.muX, cwr.SigmaX);
+weights = normalize(repmat(cwr.priorC, 1, T) .* likX, 1);
+for t=1:T
+  mut = zeros(ny, nc);
+  for c=1:nc
+    mut(:,c) = cwr.muY(:,c) + cwr.weightsY(:,:,c)*X(:,t);
+    if comp_mask
+      mask = mask + gaussian_prob(mask_data, mut(:,c), cwr.SigmaY(:,:,c)) * weights(c);
+    end
+  end
+  %w = normalise(cwr.priorC(:)  .* likX(:,t));
+  [mu(:,t), Sigma(:,:,t)] = collapse_mog(mut, cwr.SigmaY, weights(:,t));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/cwr_prob.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,39 @@
+function  [likXandY, likYgivenX, post] = cwr_prob(cwr, X, Y);
+% CWR_EVAL_PDF cluster weighted regression: evaluate likelihood of Y given X 
+% function  [likXandY, likYgivenX, post] = cwr_prob(cwr, X, Y);
+% 
+% likXandY(t) = p(x(:,t), y(:,t))
+% likXgivenY(t) = p(x(:,t)| y(:,t))
+% post(c,t) = p(c | x(:,t), y(:,t))
+
+[nx N] = size(X);
+nc = length(cwr.priorC);
+
+if nc == 1
+  [mu, Sigma] = cwr_predict(cwr, X);
+  likY = gaussian_prob(Y, mu, Sigma);
+  likXandY = likY;
+  likYgivenX = likY;
+  post = ones(1,N);
+  return;
+end
+
+
+% likY(c,t) = p(y(:,t) | c)
+likY = clg_prob(X, Y, cwr.muY, cwr.SigmaY, cwr.weightsY);
+
+% likX(c,t) = p(x(:,t) | c)
+[junk, likX] = mixgauss_prob(X, cwr.muX, cwr.SigmaX);
+likX = squeeze(likX);
+
+% prior(c,t) = p(c)
+prior = repmat(cwr.priorC(:), 1, N);
+
+post = likX .* likY .* prior;
+likXandY = sum(post, 1);
+post = post ./ repmat(likXandY, nc, 1);
+%loglik = sum(log(lik));
+%loglik = log(lik);
+
+likX = sum(likX .* prior, 1);
+likYgivenX = likXandY ./ likX;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/cwr_readme.txt	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,20 @@
+This directory implements Cluster Weighted Regression, as described in
+Neil Gershenfeld, "The nature of mathematical modelling", p182.
+(See also http://www.media.mit.edu/physics/publications/books/nmm/files/index.html)
+
+Written by K. Murphy, 2 May 2003
+
+The model is as follows:
+
+X<--|
+|   Q
+v   |
+Y<--
+
+where Q is a discrete latent mixture variable.
+
+A mixture of experts has an X->Q arc instead of a Q->X arc;
+the X->Q arc is modelled by a softmax, which is slightly harder to fit than a
+mixture of Gaussians.
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/cwr_test.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,80 @@
+% Verify that my code gives the same results as the 1D example at
+% http://www.media.mit.edu/physics/publications/books/nmm/files/cwm.m
+
+seed = 0;
+rand('state', seed);
+randn('state', seed);
+x = (-10:10)';
+y = double(x > 0);
+npts = length(x);
+plot(x,y,'+')
+
+nclusters = 4;
+nplot = 100;
+xplot = 24*(1:nplot)'/nplot - 12;
+
+mux = 20*rand(1,nclusters) - 10;
+muy = zeros(1,nclusters);
+varx = ones(1,nclusters);
+vary = ones(1,nclusters);
+pc = 1/nclusters * ones(1,nclusters);
+
+
+I = repmat(eye(1,1), [1 1 nclusters]);
+O = repmat(zeros(1,1), [1 1 nclusters]);
+X = x(:)';
+Y = y(:)';
+
+% Do 1 iteration of EM
+
+%cwr = cwr_em(X, Y, nclusters, 'muX', mux, 'muY', muy,  'SigmaX', I, 'cov_typeX', 'spherical', 'SigmaY', I, 'cov_typeY', 'spherical', 'priorC', pc, 'weightsY', O,  'init_params', 0, 'clamp_weights', 1, 'max_iter', 1, 'cov_priorX', zeros(1,1,nclusters), 'cov_priorY', zeros(1,1,nclusters));
+
+cwr = cwr_em(X, Y, nclusters, 'muX', mux, 'muY', muy,  'SigmaX', I, 'cov_typeX', 'spherical', 'SigmaY', I, 'cov_typeY', 'spherical', 'priorC', pc, 'weightsY', O,  'create_init_params', 0, 'clamp_weights', 1, 'max_iter', 1);
+
+
+% Check this matches Gershenfeld's code
+
+% E step
+% px(t,c) = prob(x(t) | c)
+px = exp(-(kron(x,ones(1,nclusters)) ...
+	   - kron(ones(npts,1),mux)).^2 ...
+	 ./ (2*kron(ones(npts,1),varx))) ...
+     ./ sqrt(2*pi*kron(ones(npts,1),varx));
+py = exp(-(kron(y,ones(1,nclusters)) ...
+	   - kron(ones(npts,1),muy)).^2 ...
+	 ./ (2*kron(ones(npts,1),vary))) ...
+     ./ sqrt(2*pi*kron(ones(npts,1),vary));
+p = px .* py .* kron(ones(npts,1),pc);
+pp = p ./ kron(sum(p,2),ones(1,nclusters));
+
+% M step
+eps = 0.01;
+pc2 = sum(pp)/npts;
+
+mux2 = sum(kron(x,ones(1,nclusters)) .* pp) ...
+      ./ (npts*pc2);
+varx2 = eps + sum((kron(x,ones(1,nclusters)) ...
+		  - kron(ones(npts,1),mux2)).^2 .* pp) ...
+       ./ (npts*pc2);
+muy2 = sum(kron(y,ones(1,nclusters)) .* pp) ...
+      ./ (npts*pc2);
+vary2 = eps + sum((kron(y,ones(1,nclusters)) ...
+		  - kron(ones(npts,1),muy2)).^2 .* pp) ...
+       ./ (npts*pc2);
+
+
+denom = (npts*pc2);
+% denom(c) = N*pc(c) = w(c) = sum_t pp(c,t)
+% since pc(c) = sum_t pp(c,t) / N
+
+cwr_mux = cwr.muX;
+assert(approxeq(mux2, cwr_mux))
+cwr_SigmaX = squeeze(cwr.SigmaX)';
+assert(approxeq(varx2, cwr_SigmaX))
+
+cwr_muy = cwr.muY;
+assert(approxeq(muy2, cwr_muy))
+cwr_SigmaY = squeeze(cwr.SigmaY)';
+assert(approxeq(vary2, cwr_SigmaY))
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/dirichlet_sample.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function theta = dirichlet_sample(alpha, N)
+% SAMPLE_DIRICHLET Sample N vectors from Dir(alpha(1), ..., alpha(k))
+% theta = sample_dirichlet(alpha, N)
+% theta(i,j) = i'th sample of theta_j, where theta ~ Dir
+
+% We use the method from p. 482 of "Bayesian Data Analysis", Gelman et al.
+
+assert(alpha > 0);
+k = length(alpha);
+theta = zeros(N, k);
+scale = 1; % arbitrary
+for i=1:k
+  %theta(:,i) = gamrnd(alpha(i), scale, N, 1);
+  theta(:,i) = gamma_sample(alpha(i), scale, N, 1);
+end
+%theta = mk_stochastic(theta);
+S = sum(theta,2); 
+theta = theta ./ repmat(S, 1, k);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/dirichletpdf.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,39 @@
+function p = dirichletpdf(x, alpha)
+%DIRICHLETPDF Dirichlet probability density function.
+%   p = dirichletpdf(x, alpha) returns the probability of vector
+%   x under the Dirichlet distribution with parameter vector
+%   alpha.
+%
+%   Author: David Ross
+
+%-------------------------------------------------
+% Check the input
+%-------------------------------------------------
+error(nargchk(2,2,nargin));
+
+% enusre alpha is a vector
+if min(size(alpha)) ~= 1 | ndims(alpha) > 2 | length(alpha) == 1
+    error('alpha must be a vector');
+end
+
+% ensure x is is a vector of the same size as alpha
+if any(size(x) ~= size(alpha))
+    error('x and alpha must be the same size');
+end
+
+
+%-------------------------------------------------
+% Main
+%-------------------------------------------------
+if any(x < 0)
+    p = 0;
+elseif sum(x) ~= 1
+    disp(['dirichletpdf warning: sum(x)~=1, but this may be ' ...
+        'due to numerical issues']);
+    p = 0;
+else
+    z = gammaln(sum(alpha)) - sum(gammaln(alpha)); 
+    z = exp(z);
+
+    p = z * prod(x.^(alpha-1));
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/dirichletrnd.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function x = dirichletrnd(alpha)
+%DIRICHLETRND Random vector from a dirichlet distribution.
+%   x = dirichletrnd(alpha) returns a vector randomly selected
+%   from the Dirichlet distribution with parameter vector alpha.
+%
+%   The algorithm used is the following:
+%   For each alpha(i), generate a value s(i) with distribution
+%   Gamma(alpha(i),1).  Now x(i) = s(i) / sum_j s(j).
+%   
+%   The above algorithm was recounted to me by Radford Neal, but
+%   a reference would be appreciated...
+%   Do the gamma parameters always have to be 1?
+%
+%   Author: David Ross
+%   $Id: dirichletrnd.m,v 1.1.1.1 2005/05/22 23:32:12 yozhik Exp $
+
+%-------------------------------------------------
+% Check the input
+%-------------------------------------------------
+error(nargchk(1,1,nargin));
+
+if min(size(alpha)) ~= 1 | length(alpha) < 2
+    error('alpha must be a vector of length at least 2');
+end
+
+
+%-------------------------------------------------
+% Main
+%-------------------------------------------------
+gamma_vals = gamrnd(alpha, ones(size(alpha)), size(alpha));
+denom = sum(gamma_vals);
+x = gamma_vals / denom;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/distchck.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,173 @@
+function [errorcode,out1,out2,out3,out4] = distchck(nparms,arg1,arg2,arg3,arg4)
+%DISTCHCK Checks the argument list for the probability functions.
+
+%   B.A. Jones  1-22-93
+%   Copyright (c) 1993-98 by The MathWorks, Inc.
+%   $Revision: 1.1.1.1 $  $Date: 2005/04/26 02:29:18 $
+
+errorcode = 0;
+
+if nparms == 1
+    out1 = arg1;
+    return;
+end
+    
+if nparms == 2
+    [r1 c1] = size(arg1);
+    [r2 c2] = size(arg2);
+    scalararg1 = (prod(size(arg1)) == 1);
+    scalararg2 = (prod(size(arg2)) == 1);
+    if ~scalararg1 & ~scalararg2
+        if r1 ~= r2 | c1 ~= c2
+            errorcode = 1;
+            return;         
+        end     
+    end
+    if scalararg1
+        out1 = arg1(ones(r2,1),ones(c2,1));
+    else
+        out1 = arg1;
+    end
+    if scalararg2
+        out2 = arg2(ones(r1,1),ones(c1,1));
+    else
+        out2 = arg2;
+    end
+end
+    
+if nparms == 3
+    [r1 c1] = size(arg1);
+    [r2 c2] = size(arg2);
+    [r3 c3] = size(arg3);
+    scalararg1 = (prod(size(arg1)) == 1);
+    scalararg2 = (prod(size(arg2)) == 1);
+    scalararg3 = (prod(size(arg3)) == 1);
+
+    if ~scalararg1 & ~scalararg2
+        if r1 ~= r2 | c1 ~= c2
+            errorcode = 1;
+            return;         
+        end
+    end
+
+    if ~scalararg1 & ~scalararg3
+        if r1 ~= r3 | c1 ~= c3
+            errorcode = 1;
+            return;                 
+        end
+    end
+
+    if ~scalararg3 & ~scalararg2
+        if r3 ~= r2 | c3 ~= c2
+            errorcode = 1;
+            return;         
+        end
+    end
+
+    if ~scalararg1
+      out1 = arg1;
+    end
+    if ~scalararg2
+      out2 = arg2;
+    end
+    if ~scalararg3
+      out3 = arg3;
+    end
+    rows = max([r1 r2 r3]);
+   columns = max([c1 c2 c3]);  
+       
+    if scalararg1
+        out1 = arg1(ones(rows,1),ones(columns,1));
+    end
+   if scalararg2
+        out2 = arg2(ones(rows,1),ones(columns,1));
+   end
+   if scalararg3
+       out3 = arg3(ones(rows,1),ones(columns,1));
+   end
+     out4 =[];
+    
+end
+
+if nparms == 4
+    [r1 c1] = size(arg1);
+    [r2 c2] = size(arg2);
+    [r3 c3] = size(arg3);
+    [r4 c4] = size(arg4);
+    scalararg1 = (prod(size(arg1)) == 1);
+    scalararg2 = (prod(size(arg2)) == 1);
+    scalararg3 = (prod(size(arg3)) == 1);
+    scalararg4 = (prod(size(arg4)) == 1);
+
+    if ~scalararg1 & ~scalararg2
+        if r1 ~= r2 | c1 ~= c2
+            errorcode = 1;
+            return;         
+        end
+    end
+
+    if ~scalararg1 & ~scalararg3
+        if r1 ~= r3 | c1 ~= c3
+            errorcode = 1;
+            return;                 
+        end
+    end
+
+    if ~scalararg1 & ~scalararg4
+        if r1 ~= r4 | c1 ~= c4
+            errorcode = 1;
+            return;                 
+        end
+    end
+
+    if ~scalararg3 & ~scalararg2
+        if r3 ~= r2 | c3 ~= c2
+            errorcode = 1;
+            return;         
+        end
+    end
+
+    if ~scalararg4 & ~scalararg2
+        if r4 ~= r2 | c4 ~= c2
+            errorcode = 1;
+            return;         
+        end
+    end
+
+    if ~scalararg3 & ~scalararg4
+        if r3 ~= r4 | c3 ~= c4
+            errorcode = 1;
+            return;         
+        end
+    end
+
+
+    if ~scalararg1
+       out1 = arg1;
+    end
+    if ~scalararg2
+       out2 = arg2;
+    end
+    if ~scalararg3
+      out3 = arg3;
+    end
+    if ~scalararg4
+      out4 = arg4;
+    end
+ 
+   rows = max([r1 r2 r3 r4]);
+   columns = max([c1 c2 c3 c4]);     
+    if scalararg1
+       out1 = arg1(ones(rows,1),ones(columns,1));
+   end
+   if scalararg2
+       out2 = arg2(ones(rows,1),ones(columns,1));
+   end
+   if scalararg3
+       out3 = arg3(ones(rows,1),ones(columns,1));
+   end
+   if scalararg4
+       out4 = arg4(ones(rows,1),ones(columns,1));
+   end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/eigdec.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function [evals, evec] = eigdec(x, N)
+%EIGDEC	Sorted eigendecomposition
+%
+%	Description
+%	 EVALS = EIGDEC(X, N computes the largest N eigenvalues of the
+%	matrix X in descending order.  [EVALS, EVEC] = EIGDEC(X, N) also
+%	computes the corresponding eigenvectors.
+%
+%	See also
+%	PCA, PPCA
+%
+
+%	Copyright (c) Ian T Nabney (1996-2001)
+
+if nargout == 1
+   evals_only = logical(1);
+else
+   evals_only = logical(0);
+end
+
+if N ~= round(N) | N < 1 | N > size(x, 2)
+   error('Number of PCs must be integer, >0, < dim');
+end
+
+% Find the eigenvalues of the data covariance matrix
+if evals_only
+   % Use eig function as always more efficient than eigs here
+   temp_evals = eig(x);
+else
+   % Use eig function unless fraction of eigenvalues required is tiny
+   if (N/size(x, 2)) > 0.04
+     fprintf('netlab pca: using eig\n');
+      [temp_evec, temp_evals] = eig(x);
+   else
+      options.disp = 0;
+      fprintf('netlab pca: using eigs\n');
+      [temp_evec, temp_evals] = eigs(x, N, 'LM', options);
+   end
+   temp_evals = diag(temp_evals);
+end
+
+% Eigenvalues nearly always returned in descending order, but just
+% to make sure.....
+[evals perm] = sort(-temp_evals);
+evals = -evals(1:N);
+%evec=temp_evec(:,1:N);
+if ~evals_only
+  if evals == temp_evals(1:N)
+    % Originals were in order
+    evec = temp_evec(:, 1:N);
+    return
+  else
+    fprintf('netlab pca: sorting evec\n');
+    % Need to reorder the eigenvectors
+    for i=1:N
+      evec(:,i) = temp_evec(:,perm(i));
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/est_transmat.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function [A,C] = est_transmat(seq)
+% ESTIMATE_TRANSMAT Max likelihood of a Markov chain transition matrix
+% [A,C] = estimate_transmat(seq)
+%
+% seq is a vector of positive integers
+%
+% e.g., seq = [1 2 1 2 3], C(1,2)=2, C(2,1)=1, C(2,3)=1, so
+% A(1,:)=[0 1 0], A(2,:) = [0.5 0 0.5],
+% all other entries are 0
+
+% Use a trick with sparse matrices to count the number of each transition.
+% From http://www.mathworks.com/company/newsletter/may03/dna.shtml
+
+C = full(sparse(seq(1:end-1), seq(2:end),1));
+A = mk_stochastic(C);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/fit_paritioned_model_testfn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function model = foo(inputs, outputs, varargin)
+
+model.inputs = inputs;
+model.outputs = outputs;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/fit_partitioned_model.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function [model, partition_size] = fit_partitioned_model(...
+    inputs, outputs, selectors, sel_sizes, min_size, partition_names, fn_name, varargin)
+%function [models, partition_sizes] = fit_partitioned_model(...
+%    inputs, outputs, selectors, sel_sizes, min_size, partition_names, fn_name, varargin)
+%
+% Fit models to different subsets (columns)  of the input/output data, 
+% as chosen by the selectors matrix. If there is only output data, set input=[].
+% If there is less than min_size data in partition i, 
+% we set model{i} = []
+%
+% Example:
+% selectors = [1 2 1 1 1
+%              1 2 2 1 2]
+% sel_sizes = [2 2] so there are 4 models: (1,1), (2,1), (1,2), (2,2)
+% We fit model{1} to data from columns 1,4
+% We fit model{2} to no data
+% We fit model{3} to data from column 3,5
+% We fit model{4} to data from column 2 (assuming min_size <= 1)
+%
+% For each partition, we call the specified function with the specified arguments
+% as follows:
+%  model{i}  = fn(input(:,cols{i}), output(:,cols{i}), args)
+% (We omit input if [])
+% partition_size(i) is the amount of data in the i'th partition.
+%
+% Example use: row 1 of selectors is whether an object is present/absent
+% and row 2 is the location.
+%
+% Demo:
+% inputs = 1:5; outputs = 6:10; selectors = as above
+% fn = 'fit_partitioned_model_testfn';
+% [model, partition_size] = fit_partitioned_model(inputs, outputs, selectors, [2 2], fn)
+% should produce
+% model{1}.input = [1 4], model{1}.output = [6 9]
+% model{2} = []
+% model{3}.input = [3 5], model{3}.output = [8 10], 
+% model{4}.input = [2], model{3}.output = [7], 
+% partition_size = [2 0 2 1]
+
+
+sel_ndx = subv2ind(sel_sizes, selectors');
+Nmodels = prod(sel_sizes);
+model = cell(1, Nmodels);
+partition_size = zeros(1, Nmodels);
+for m=1:Nmodels
+  ndx = find(sel_ndx==m);
+  partition_size(m) = length(ndx);
+  if ~isempty(partition_names) % & (partition_size(m) < min_size)
+    fprintf('partition %s has size %d, min size = %d\n', ...
+	    partition_names{m}, partition_size(m), min_size);
+  end
+  if partition_size(m) >= min_size
+    if isempty(inputs)
+      model{m} = feval(fn_name, outputs(:, ndx), varargin{:});
+    else
+      model{m} = feval(fn_name, inputs(:,ndx), outputs(:, ndx), varargin{:});
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/gamma_sample.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,126 @@
+function r = gamrnd(a,b,m,n);
+%GAMRND Random matrices from gamma distribution.
+%   R = GAMRND(A,B) returns a matrix of random numbers chosen   
+%   from the gamma distribution with parameters A and B.
+%   The size of R is the common size of A and B if both are matrices.
+%   If either parameter is a scalar, the size of R is the size of the other
+%   parameter. Alternatively, R = GAMRND(A,B,M,N) returns an M by N matrix. 
+%
+%   Some references refer to the gamma distribution
+%   with a single parameter. This corresponds to GAMRND
+%   with B = 1. (See Devroye, pages 401-402.)
+
+%   GAMRND uses a rejection or an inversion method depending on the
+%   value of A. 
+
+%   References:
+%      [1]  L. Devroye, "Non-Uniform Random Variate Generation", 
+%      Springer-Verlag, 1986
+
+%   B.A. Jones 2-1-93
+%   Copyright (c) 1993-98 by The MathWorks, Inc.
+%   $Revision: 1.1.1.1 $  $Date: 2005/04/26 02:29:18 $
+
+if nargin < 2, 
+   error('Requires at least two input arguments.'); 
+end
+
+
+if nargin == 2
+   [errorcode rows columns] = rndcheck(2,2,a,b);
+end
+
+if nargin == 3
+   [errorcode rows columns] = rndcheck(3,2,a,b,m);
+end
+
+if nargin == 4
+   [errorcode rows columns] = rndcheck(4,2,a,b,m,n);
+end
+
+if errorcode > 0
+   error('Size information is inconsistent.');
+end
+
+% Initialize r to zero.
+lth = rows*columns;
+r = zeros(lth,1);
+a = a(:); b = b(:);
+
+scalara = (length(a) == 1);
+if scalara 
+   a = a*ones(lth,1);
+end
+
+scalarb = (length(b) == 1);
+if scalarb 
+   b = b*ones(lth,1);
+end
+
+% If a == 1, then gamma is exponential. (Devroye, page 405).
+k = find(a == 1);
+if any(k)
+   r(k) = -b(k) .* log(rand(size(k)));
+end 
+
+
+k = find(a < 1 & a > 0);
+% (Devroye, page 418 Johnk's generator)
+if any(k)
+  c = zeros(lth,1);
+  d = zeros(lth,1);
+  c(k) = 1 ./ a(k);
+  d(k) = 1 ./ (1 - a(k));
+  accept = k;
+  while ~isempty(accept)
+    u = rand(size(accept));
+    v = rand(size(accept));
+    x = u .^ c(accept);
+    y = v .^ d(accept);
+    k1 = find((x + y) <= 1); 
+    if ~isempty(k1)
+      e = -log(rand(size(k1))); 
+      r(accept(k1)) = e .* x(k1) ./ (x(k1) + y(k1));
+      accept(k1) = [];
+    end
+  end
+  r(k) = r(k) .* b(k);
+end
+
+% Use a rejection method for a > 1.
+k = find(a > 1);
+% (Devroye, page 410 Best's algorithm)
+bb = zeros(size(a));
+c  = bb;
+if any(k)
+  bb(k) = a(k) - 1;
+  c(k) = 3 * a(k) - 3/4;
+  accept = k; 
+  count = 1;
+  while ~isempty(accept)
+    m = length(accept);
+    u = rand(m,1);
+    v = rand(m,1);
+    w = u .* (1 - u);
+    y = sqrt(c(accept) ./ w) .* (u - 0.5);
+    x = bb(accept) + y;
+    k1 = find(x >= 0);
+    if ~isempty(k1)
+      z = 64 * (w .^ 3) .* (v .^ 2);
+      k2 = (z(k1) <= (1 - 2 * (y(k1) .^2) ./ x(k1)));
+      k3 = k1(find(k2));
+      r(accept(k3)) = x(k3); 
+      k4 = k1(find(~k2));
+      k5 = k4(find(log(z(k4)) <= (2*(bb(accept(k4)).*log(x(k4)./bb(accept(k4)))-y(k4)))));
+      r(accept(k5)) = x(k5);
+      omit = [k3; k5];
+      accept(omit) = [];
+    end
+  end
+  r(k) = r(k) .* b(k);
+end
+
+% Return NaN if a or b is not positive.
+r(b <= 0 | a <= 0) = NaN;
+
+r = reshape(r,rows,columns);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/gaussian_prob.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function p = gaussian_prob(x, m, C, use_log)
+% GAUSSIAN_PROB Evaluate a multivariate Gaussian density.
+% p = gaussian_prob(X, m, C)
+% p(i) = N(X(:,i), m, C) where C = covariance matrix and each COLUMN of x is a datavector
+
+% p = gaussian_prob(X, m, C, 1) returns log N(X(:,i), m, C) (to prevents underflow).
+%
+% If X has size dxN, then p has size Nx1, where N = number of examples
+
+if nargin < 4, use_log = 0; end
+
+if length(m)==1 % scalar
+  x = x(:)';
+end
+[d N] = size(x);
+%assert(length(m)==d); % slow
+m = m(:);
+M = m*ones(1,N); % replicate the mean across columns
+denom = (2*pi)^(d/2)*sqrt(abs(det(C)));
+mahal = sum(((x-M)'*inv(C)).*(x-M)',2);   % Chris Bregler's trick
+if any(mahal<0)
+  warning('mahal < 0 => C is not psd')
+end
+if use_log
+  p = -0.5*mahal - log(denom);
+else
+  p = exp(-0.5*mahal) / (denom+eps);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/gaussian_sample.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function x = gsamp(mu, covar, nsamp)
+%GSAMP	Sample from a Gaussian distribution.
+%
+%	Description
+%
+%	X = GSAMP(MU, COVAR, NSAMP) generates a sample of size NSAMP from a
+%	D-dimensional Gaussian distribution. The Gaussian density has mean
+%	vector MU and covariance matrix COVAR, and the matrix X has NSAMP
+%	rows in which each row represents a D-dimensional sample vector.
+%
+%	See also
+%	GAUSS, DEMGAUSS
+%
+
+%	Copyright (c) Ian T Nabney (1996-2001)
+
+d = size(covar, 1);
+
+mu = reshape(mu, 1, d);   % Ensure that mu is a row vector
+
+[evec, eval] = eig(covar);
+
+coeffs = randn(nsamp, d)*sqrt(eval);
+
+x = ones(nsamp, 1)*mu + coeffs*evec';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/histCmpChi2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function d = histCmpChi2(h1, h2)
+% Compare two histograms using chi-squared
+% function d = histCmpChi2(h1, h2)
+%
+% d(i,j) = chi^2(h1(i,:), h2(j,:)) = sum_b  (h1(i,b)-h2(j,b)^2 / (h1(i,b) + h2(j,b))
+
+[N B] = size(h1);
+d = zeros(N,N);
+for i=1:N
+  h1i = repmat(h1(i,:), N, 1);
+  numer = (h1i - h2).^2;
+  denom = h1i + h2 + eps; % if denom=0, then numer=0
+  d(i,:) = sum(numer ./ denom, 2);
+end
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/linear_regression.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,68 @@
+function [muY, SigmaY, weightsY]  = linear_regression(X, Y, varargin)
+% LINEAR_REGRESSION Fit params for P(Y|X) = N(Y;  W X + mu, Sigma) 
+%
+% X(:, t) is the t'th input example
+% Y(:, t) is the t'th output example
+%
+% Kevin Murphy, August 2003
+%
+% This is a special case of cwr_em with 1 cluster.
+% You can also think of it as a front end to clg_Mstep.
+
+[cov_typeY, clamp_weights,  muY, SigmaY, weightsY,...
+ cov_priorY,  regress, clamp_covY] = process_options(...
+    varargin, ...
+     'cov_typeY', 'full', 'clamp_weights', 0, ...
+     'muY', [], 'SigmaY', [], 'weightsY', [], ...
+     'cov_priorY', [], 'regress', 1,  'clamp_covY', 0);
+     
+[nx N] = size(X);
+[ny N2] = size(Y);
+if N ~= N2
+  error(sprintf('nsamples X (%d) ~= nsamples Y (%d)', N, N2));
+end
+
+w = 1/N;
+WYbig = Y*w;
+WYY = WYbig * Y'; 
+WY = sum(WYbig, 2);
+WYTY = sum(diag(WYbig' * Y));
+if ~regress
+  % This is just fitting an unconditional Gaussian
+  weightsY = [];
+  [muY, SigmaY] = ...
+      mixgauss_Mstep(1, WY, WYY, WYTY, ...
+		     'cov_type', cov_typeY, 'cov_prior', cov_priorY);
+  % There is a much easier way...
+  assert(approxeq(muY, mean(Y')))
+  assert(approxeq(SigmaY, cov(Y') + 0.01*eye(ny)))
+else
+  % This is just linear regression
+  WXbig = X*w;
+  WXX = WXbig * X';
+  WX = sum(WXbig, 2);
+  WXTX = sum(diag(WXbig' * X));
+  WXY = WXbig * Y';
+  [muY, SigmaY, weightsY] = ...
+      clg_Mstep(1, WY, WYY, WYTY, WX, WXX, WXY, ...
+		'cov_type', cov_typeY, 'cov_prior', cov_priorY);
+end
+if clamp_covY, SigmaY = SigmaY; end
+if clamp_weights,  weightsY = weightsY; end
+
+if nx==1 & ny==1 & regress
+  P = polyfit(X,Y); % Y = P(1) X^1 + P(2) X^0 = ax + b
+  assert(approxeq(muY, P(2)))
+  assert(approxeq(weightsY, P(1)))
+end
+
+%%%%%%%% Test
+if 0 
+  c1 = randn(2,100);   c2 = randn(2,100);
+  y = c2(1,:); X = [ones(size(c1,2),1) c1'];
+  b = regress(y(:), X); % stats toolbox
+  [m,s,w] = linear_regression(c1, y);
+  assert(approxeq(b(1),m))
+  assert(approxeq(b(2), w(1)))
+  assert(approxeq(b(3), w(2)))
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/logist2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,115 @@
+function [beta,p,lli] = logist2(y,x,w)
+% [beta,p,lli] = logist2(y,x) 
+%
+% 2-class logistic regression.  
+%
+% INPUT
+% 	y 	Nx1 colum vector of 0|1 class assignments
+% 	x 	NxK matrix of input vectors as rows
+% 	[w]	Nx1 vector of sample weights 
+%
+% OUTPUT
+% 	beta 	Kx1 column vector of model coefficients
+% 	p 	Nx1 column vector of fitted class 1 posteriors
+% 	lli 	log likelihood
+%
+% Class 1 posterior is 1 / (1 + exp(-x*beta))
+%
+% David Martin <dmartin@eecs.berkeley.edu> 
+% April 16, 2002
+
+% Copyright (C) 2002 David R. Martin <dmartin@eecs.berkeley.edu>
+%
+% This program 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 2 of the
+% License, or (at your option) any later version.
+% 
+
+% This program 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
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+% 02111-1307, USA, or see http://www.gnu.org/copyleft/gpl.html.
+
+error(nargchk(2,3,nargin));
+
+% check inputs
+if size(y,2) ~= 1,
+  error('Input y not a column vector.');
+end
+if size(y,1) ~= size(x,1), 
+  error('Input x,y sizes mismatched.'); 
+end
+
+% get sizes
+[N,k] = size(x);
+
+% if sample weights weren't specified, set them to 1
+if nargin < 3, 
+  w = 1;
+end
+
+% normalize sample weights so max is 1
+w = w / max(w);
+
+% initial guess for beta: all zeros
+beta = zeros(k,1);
+
+% Newton-Raphson via IRLS,
+% taken from Hastie/Tibshirani/Friedman Section 4.4.
+iter = 0;
+lli = 0;
+while 1==1,
+  iter = iter + 1;
+  
+  % fitted probabilities
+  p = 1 ./ (1 + exp(-x*beta));	
+  
+  % log likelihood
+  lli_prev = lli;
+  lli = sum( w .* (y.*log(p+eps) + (1-y).*log(1-p+eps)) );
+
+  % least-squares weights
+  wt = w .* p .* (1-p);		
+
+  % derivatives of likelihood w.r.t. beta
+  deriv = x'*(w.*(y-p));
+
+  % Hessian of likelihood w.r.t. beta
+  % hessian = x'Wx, where W=diag(w)
+  % Do it this way to be memory efficient and fast.
+  hess = zeros(k,k);
+  for i = 1:k,
+    wxi = wt .* x(:,i);
+    for j = i:k,
+      hij = wxi' * x(:,j);
+      hess(i,j) = -hij;
+      hess(j,i) = -hij;
+    end
+  end
+
+  % make sure Hessian is well conditioned
+  if (rcond(hess) < eps), 
+    error(['Stopped at iteration ' num2str(iter) ...
+           ' because Hessian is poorly conditioned.']);
+    break; 
+  end;
+
+  % Newton-Raphson update step
+  step = hess\deriv;
+  beta = beta - step;
+
+  % termination criterion based on derivatives
+  tol = 1e-6;
+  if abs(deriv'*step/k) < tol, break; end;
+
+  % termination criterion based on log likelihood
+%   tol = 1e-4;
+%   if abs((lli-lli_prev)/(lli+lli_prev)) < 0.5*tol, break; end;
+end;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/logist2Apply.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function p = logist2Apply(beta, x)
+% LOGIST2APPLY 2 class logistic regression: compute posterior prob of class 1
+% function p = logist2Apply(beta, x)
+%
+% x(:,i) - each COLUMN is a test case; we append 1s automatically, if appropriate
+
+[D Ncases] = size(x);
+if length(beta)==D+1
+  F = [x; ones(1,Ncases)];
+else
+  F = x;
+end
+p = 1./(1+exp(-beta(:)'*F));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/logist2ApplyRegularized.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+function prob = logist2ApplyRegularized(net, features)
+
+prob = glmfwd(net, features')';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/logist2Fit.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function [beta, p] = logist2Fit(y, x, addOne, w)
+% LOGIST2FIT 2 class logsitic classification
+% function beta = logist2Fit(y,x, addOne)
+%
+% y(i) = 0/1
+% x(:,i) = i'th input - we optionally append 1s to last dimension
+% w(i) = optional weight
+%
+% beta(j)- regression coefficient
+
+if nargin < 3, addOne = 1; end
+if nargin < 4, w = 1; end
+
+Ncases = size(x,2);
+if Ncases ~= length(y)
+  error(sprintf('size of data = %dx%d, size of labels=%d', size(x,1), size(x,2), length(y)))
+end
+if addOne
+  x = [x; ones(1,Ncases)];
+end
+[beta, p] = logist2(y(:), x', w(:));
+beta = beta(:);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/logist2FitRegularized.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function [net, niter] = logist2FitRegularized(labels, features, maxIter)
+
+if nargin < 3, maxIter = 100; end
+
+[D  N] = size(features);
+weightPrior = 0.5;
+net = glm(D, 1, 'logistic', weightPrior);
+options = foptions;
+options(14) = maxIter;
+[net, options] = glmtrain(net, options, features', labels(:));
+niter = options(14);
+%w = logist2Fit(labelsPatches(jValidPatches), features(:, jValidPatches));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/logistK.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,287 @@
+function [beta,post,lli] = logistK(x,y,w,beta)
+% [beta,post,lli] = logistK(x,y,beta,w) 
+%
+% k-class logistic regression with optional sample weights
+%
+% k = number of classes
+% n = number of samples
+% d = dimensionality of samples
+%
+% INPUT
+% 	x 	dxn matrix of n input column vectors
+% 	y 	kxn vector of class assignments
+% 	[w]	1xn vector of sample weights 
+%	[beta]	dxk matrix of model coefficients
+%
+% OUTPUT
+% 	beta 	dxk matrix of fitted model coefficients 
+%		(beta(:,k) are fixed at 0) 
+% 	post 	kxn matrix of fitted class posteriors
+% 	lli 	log likelihood
+%
+% Let p(i,j) = exp(beta(:,j)'*x(:,i)),
+% Class j posterior for observation i is:
+%	post(j,i) = p(i,j) / (p(i,1) + ... p(i,k))
+%
+% See also logistK_eval.
+%
+% David Martin <dmartin@eecs.berkeley.edu> 
+% May 3, 2002
+
+% Copyright (C) 2002 David R. Martin <dmartin@eecs.berkeley.edu>
+%
+% This program 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 2 of the
+% License, or (at your option) any later version.
+% 
+% This program 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
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+% 02111-1307, USA, or see http://www.gnu.org/copyleft/gpl.html.
+
+% TODO - this code would be faster if x were transposed
+
+error(nargchk(2,4,nargin));
+
+debug = 0;
+if debug>0,
+  h=figure(1);
+  set(h,'DoubleBuffer','on');
+end
+
+% get sizes
+[d,nx] = size(x);
+[k,ny] = size(y);
+
+% check sizes
+if k < 2,
+  error('Input y must encode at least 2 classes.');
+end
+if nx ~= ny,
+  error('Inputs x,y not the same length.'); 
+end
+
+n = nx;
+
+% make sure class assignments have unit L1-norm
+sumy = sum(y,1);
+if abs(1-sumy) > eps,
+  sumy = sum(y,1);
+  for i = 1:k, y(i,:) = y(i,:) ./ sumy; end
+end
+clear sumy;
+
+% if sample weights weren't specified, set them to 1
+if nargin < 3, 
+  w = ones(1,n);
+end
+
+% normalize sample weights so max is 1
+w = w / max(w);
+
+% if starting beta wasn't specified, initialize randomly
+if nargin < 4,
+  beta = 1e-3*rand(d,k);
+  beta(:,k) = 0;	% fix beta for class k at zero
+else
+  if sum(beta(:,k)) ~= 0,
+    error('beta(:,k) ~= 0');
+  end
+end
+
+stepsize = 1;
+minstepsize = 1e-2;
+
+post = computePost(beta,x);
+lli = computeLogLik(post,y,w);
+
+for iter = 1:100,
+  %disp(sprintf('  logist iter=%d lli=%g',iter,lli));
+  vis(x,y,beta,lli,d,k,iter,debug);
+
+  % gradient and hessian
+  [g,h] = derivs(post,x,y,w);
+
+  % make sure Hessian is well conditioned
+  if rcond(h) < eps, 
+    % condition with Levenberg-Marquardt method
+    for i = -16:16,
+      h2 = h .* ((1 + 10^i)*eye(size(h)) + (1-eye(size(h))));
+      if rcond(h2) > eps, break, end
+    end
+    if rcond(h2) < eps,
+      warning(['Stopped at iteration ' num2str(iter) ...
+               ' because Hessian can''t be conditioned']);
+      break 
+    end
+    h = h2;
+  end
+
+  % save lli before update
+  lli_prev = lli;
+
+  % Newton-Raphson with step-size halving
+  while stepsize >= minstepsize,
+    % Newton-Raphson update step
+    step = stepsize * (h \ g);
+    beta2 = beta;
+    beta2(:,1:k-1) = beta2(:,1:k-1) - reshape(step,d,k-1);
+
+    % get the new log likelihood
+    post2 = computePost(beta2,x);
+    lli2 = computeLogLik(post2,y,w);
+
+    % if the log likelihood increased, then stop
+    if lli2 > lli, 
+      post = post2; lli = lli2; beta = beta2;
+      break
+    end
+
+    % otherwise, reduce step size by half
+    stepsize = 0.5 * stepsize;
+  end
+
+  % stop if the average log likelihood has gotten small enough
+  if 1-exp(lli/n) < 1e-2, break, end
+
+  % stop if the log likelihood changed by a small enough fraction
+  dlli = (lli_prev-lli) / lli;
+  if abs(dlli) < 1e-3, break, end
+
+  % stop if the step size has gotten too small
+  if stepsize < minstepsize, brea, end
+
+  % stop if the log likelihood has decreased; this shouldn't happen
+  if lli < lli_prev,
+    warning(['Stopped at iteration ' num2str(iter) ...
+             ' because the log likelihood decreased from ' ...
+             num2str(lli_prev) ' to ' num2str(lli) '.' ...
+            ' This may be a bug.']);
+    break
+  end
+end
+
+if debug>0, 
+  vis(x,y,beta,lli,d,k,iter,2); 
+end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% class posteriors
+function post = computePost(beta,x)
+  [d,n] = size(x);
+  [d,k] = size(beta);
+  post = zeros(k,n);
+  bx = zeros(k,n);
+  for j = 1:k, 
+    bx(j,:) = beta(:,j)'*x; 
+  end
+  for j = 1:k, 
+    post(j,:) = 1 ./ sum(exp(bx - repmat(bx(j,:),k,1)),1);
+  end
+  
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% log likelihood
+function lli = computeLogLik(post,y,w)
+  [k,n] = size(post);
+  lli = 0;
+  for j = 1:k,
+    lli = lli + sum(w.*y(j,:).*log(post(j,:)+eps));
+  end
+  if isnan(lli), 
+    error('lli is nan'); 
+  end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% gradient and hessian
+%% These are computed in what seems a verbose manner, but it is
+%% done this way to use minimal memory.  x should be transposed
+%% to make it faster.
+function [g,h] = derivs(post,x,y,w)
+
+  [k,n] = size(post);
+  [d,n] = size(x);
+
+  % first derivative of likelihood w.r.t. beta
+  g = zeros(d,k-1);
+  for j = 1:k-1,
+    wyp = w .* (y(j,:) - post(j,:));
+    for ii = 1:d, 
+      g(ii,j) = x(ii,:) * wyp'; 
+    end
+  end
+  g = reshape(g,d*(k-1),1);
+
+  % hessian of likelihood w.r.t. beta
+  h = zeros(d*(k-1),d*(k-1)); 
+  for i = 1:k-1,	% diagonal
+    wt = w .* post(i,:) .* (1 - post(i,:));
+    hii = zeros(d,d);
+    for a = 1:d,
+      wxa = wt .* x(a,:);
+      for b = a:d,
+        hii_ab = wxa * x(b,:)';
+        hii(a,b) = hii_ab;
+        hii(b,a) = hii_ab;
+      end
+    end
+    h( (i-1)*d+1 : i*d , (i-1)*d+1 : i*d ) = -hii;
+  end
+  for i = 1:k-1,	% off-diagonal
+    for j = i+1:k-1,
+      wt = w .* post(j,:) .* post(i,:);
+      hij = zeros(d,d);
+      for a = 1:d,
+        wxa = wt .* x(a,:);
+        for b = a:d,
+          hij_ab = wxa * x(b,:)';
+          hij(a,b) = hij_ab;
+          hij(b,a) = hij_ab;
+        end
+      end
+      h( (i-1)*d+1 : i*d , (j-1)*d+1 : j*d ) = hij;
+      h( (j-1)*d+1 : j*d , (i-1)*d+1 : i*d ) = hij;
+    end
+  end
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% debug/visualization
+function vis (x,y,beta,lli,d,k,iter,debug)
+
+  if debug<=0, return, end
+
+  disp(['iter=' num2str(iter) ' lli=' num2str(lli)]);
+  if debug<=1, return, end
+
+  if d~=3 | k>10, return, end
+
+  figure(1);
+  res = 100;
+  r = abs(max(max(x)));
+  dom = linspace(-r,r,res);
+  [px,py] = meshgrid(dom,dom);
+  xx = px(:); yy = py(:);
+  points = [xx' ; yy' ; ones(1,res*res)];
+  func = zeros(k,res*res);
+  for j = 1:k,
+    func(j,:) = exp(beta(:,j)'*points);
+  end
+  [mval,ind] = max(func,[],1);
+  hold off; 
+  im = reshape(ind,res,res);
+  imagesc(xx,yy,im);
+  hold on;
+  syms = {'w.' 'wx' 'w+' 'wo' 'w*' 'ws' 'wd' 'wv' 'w^' 'w<'};
+  for j = 1:k,
+    [mval,ind] = max(y,[],1);
+    ind = find(ind==j);
+    plot(x(1,ind),x(2,ind),syms{j});
+  end
+  pause(0.1);
+
+% eof
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/logistK_eval.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,83 @@
+function [post,lik,lli] = logistK_eval(beta,x,y)
+% [post,lik,lli] = logistK_eval(beta,x,y)
+%
+% Evaluate logistic regression model.
+% 
+% INPUT
+% 	beta 	dxk model coefficients (as returned by logistK)
+% 	x 	dxn matrix of n input column vectors
+% 	[y] 	kxn vector of class assignments
+%
+% OUTPUT
+% 	post 	kxn fitted class posteriors
+% 	lik 	1xn vector of sample likelihoods
+%	lli	log likelihood
+%
+% Let p(i,j) = exp(beta(:,j)'*x(:,i)),
+% Class j posterior for observation i is:
+%	post(j,i) = p(i,j) / (p(i,1) + ... p(i,k))
+% The likelihood of observation i given soft class assignments
+% y(:,i) is: 
+%	lik(i) = prod(post(:,i).^y(:,i))
+% The log-likelihood of the model given the labeled samples is:
+%	lli = sum(log(lik))
+% 
+% See also logistK.
+%
+% David Martin <dmartin@eecs.berkeley.edu> 
+% May 7, 2002
+
+% Copyright (C) 2002 David R. Martin <dmartin@eecs.berkeley.edu>
+%
+% This program 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 2 of the
+% License, or (at your option) any later version.
+% 
+% This program 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
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+% 02111-1307, USA, or see http://www.gnu.org/copyleft/gpl.html.
+
+error(nargchk(2,3,nargin));
+
+% check sizes
+if size(beta,1) ~= size(x,1),
+  error('Inputs beta,x not the same height.');
+end
+if nargin > 3 & size(y,2) ~= size(x,2), 
+  error('Inputs x,y not the same length.'); 
+end
+
+% get sizes
+[d,k] = size(beta);
+[d,n] = size(x);
+
+% class posteriors
+post = zeros(k,n);
+bx = zeros(k,n);
+for j = 1:k, 
+  bx(j,:) = beta(:,j)'*x; 
+end
+for j = 1:k, 
+  post(j,:) = 1 ./ sum(exp(bx - repmat(bx(j,:),k,1)),1);
+end
+clear bx;
+
+% likelihood of each sample
+if nargout > 1,
+  y = y ./ repmat(sum(y,1),k,1); % L1-normalize class assignments
+  lik = prod(post.^y,1);
+end
+
+% total log likelihood
+if nargout > 2,
+  lli = sum(log(lik+eps));
+end;
+
+% eof
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/marginalize_gaussian.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function [muX, SXX] = marginalize_gaussian(mu, Sigma, X, Y, ns)
+% MARGINALIZE_GAUSSIAN Compute Pr(X) from Pr(X,Y) where X and Y are jointly Gaussian.
+% [muX, SXX] = marginalize_gaussian(mu, Sigma, X, Y, ns)
+
+[muX, muY, SXX, SXY, SYX, SYY] = partition_matrix_vec(mu, Sigma, X, Y, ns);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/matrix_T_pdf.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function p = matrix_T_pdf(A, M, V, K, n)
+% MATRIX_T_PDF Evaluate the density of a matrix under a Matrix-T distribution
+% p = matrix_T_pdf(A, M, V, K, n)
+
+% See "Bayesian Linear Regression", T. Minka, MIT Tech Report, 2001
+
+[d m] = size(K);
+is = 1:d;
+c1 = prod(gamma((n+1-is)/2)) / prod(gamma((n-m+1-is)/2));
+c2 = det(K)^(d/2) / det(pi*V)^(m/2); %% pi or 2pi?
+p = c1 * c2 * det((A-M)'*inv(V)*(A-M)*K + eye(m))^(-n/2);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/matrix_normal_pdf.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function p = matrix_normal_pdf(A, M, V, K)
+% MATRIX_NORMAL_PDF Evaluate the density of a matrix under a Matrix-Normal distribution
+% p = matrix_normal_pdf(A, M, V, K)
+
+% See "Bayesian Linear Regression", T. Minka, MIT Tech Report, 2001
+
+[d m] = size(K);
+c = det(K)^(d/2) / det(2*pi*V)^(m/2);
+p = c * exp(-0.5*tr((A-M)'*inv(V)*(A-M)*K));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/mc_stat_distrib.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function pi = mc_stat_distrib(P)
+% MC_STAT_DISTRIB Compute stationary distribution of a Markov chain
+% function pi = mc_stat_distrib(P)
+% 
+% Each row of P should sum to one; pi is a column vector
+
+% Kevin Murphy, 16 Feb 2003
+
+% The stationary distribution pi satisfies pi P = pi
+% subject to sum_i pi(i) = 1,  0 <= pi(i) <= 1
+% Hence
+% (P'  0n   (pi  = (pi 
+%  1n  0)    1)     1)
+% or P2 pi2 = pi2.
+% Naively we can solve this using (P2 - I(n+1)) pi2 = 0(n+1)
+% or P3 pi2 = 0(n+1), i.e., pi2 = P3 \ zeros(n+1,1)
+% but this is singular (because of the sum-to-one constraint).
+% Hence we replace the last row of P' with 1s instead of appending ones to create P2, 
+% and similarly for pi.
+
+n = length(P);
+P4 = P'-eye(n);
+P4(end,:) = 1;
+pi = P4 \ [zeros(n-1,1);1];
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/mixgauss_Mstep.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,106 @@
+function [mu, Sigma] = mixgauss_Mstep(w, Y, YY, YTY, varargin)
+% MSTEP_COND_GAUSS Compute MLEs for mixture of Gaussians given expected sufficient statistics
+% function [mu, Sigma] = Mstep_cond_gauss(w, Y, YY, YTY, varargin)
+%
+% We assume P(Y|Q=i) = N(Y; mu_i, Sigma_i)
+% and w(i,t) = p(Q(t)=i|y(t)) = posterior responsibility
+% See www.ai.mit.edu/~murphyk/Papers/learncg.pdf.
+%
+% INPUTS:
+% w(i) = sum_t w(i,t) = responsibilities for each mixture component
+%  If there is only one mixture component (i.e., Q does not exist),
+%  then w(i) = N = nsamples,  and 
+%  all references to i can be replaced by 1.
+% YY(:,:,i) = sum_t w(i,t) y(:,t) y(:,t)' = weighted outer product
+% Y(:,i) = sum_t w(i,t) y(:,t) = weighted observations
+% YTY(i) = sum_t w(i,t) y(:,t)' y(:,t) = weighted inner product
+%   You only need to pass in YTY if Sigma is to be estimated as spherical.
+%
+% Optional parameters may be passed as 'param_name', param_value pairs.
+% Parameter names are shown below; default values in [] - if none, argument is mandatory.
+%
+% 'cov_type' - 'full', 'diag' or 'spherical' ['full']
+% 'tied_cov' - 1 (Sigma) or 0 (Sigma_i) [0]
+% 'clamped_cov' - pass in clamped value, or [] if unclamped [ [] ]
+% 'clamped_mean' - pass in clamped value, or [] if unclamped [ [] ]
+% 'cov_prior' - Lambda_i, added to YY(:,:,i) [0.01*eye(d,d,Q)]
+%
+% If covariance is tied, Sigma has size d*d.
+% But diagonal and spherical covariances are represented in full size.
+
+[cov_type, tied_cov,  clamped_cov, clamped_mean, cov_prior, other] = ...
+    process_options(varargin,...
+		    'cov_type', 'full', 'tied_cov', 0,  'clamped_cov', [], 'clamped_mean', [], ...
+		    'cov_prior', []);
+
+[Ysz Q] = size(Y);
+N = sum(w);
+if isempty(cov_prior)
+  %cov_prior = zeros(Ysz, Ysz, Q);
+  %for q=1:Q
+  %  cov_prior(:,:,q) = 0.01*cov(Y(:,q)');
+  %end
+  cov_prior = repmat(0.01*eye(Ysz,Ysz), [1 1 Q]);
+end
+%YY = reshape(YY, [Ysz Ysz Q]) + cov_prior; % regularize the scatter matrix
+YY = reshape(YY, [Ysz Ysz Q]);
+
+% Set any zero weights to one before dividing
+% This is valid because w(i)=0 => Y(:,i)=0, etc
+w = w + (w==0);
+		    
+if ~isempty(clamped_mean)
+  mu = clamped_mean;
+else
+  % eqn 6
+  %mu = Y ./ repmat(w(:)', [Ysz 1]);% Y may have a funny size
+  mu = zeros(Ysz, Q);
+  for i=1:Q
+    mu(:,i) = Y(:,i) / w(i);
+  end
+end
+
+if ~isempty(clamped_cov)
+  Sigma = clamped_cov;
+  return;
+end
+
+if ~tied_cov
+  Sigma = zeros(Ysz,Ysz,Q);
+  for i=1:Q
+    if cov_type(1) == 's'
+      % eqn 17
+      s2 = (1/Ysz)*( (YTY(i)/w(i)) - mu(:,i)'*mu(:,i) );
+      Sigma(:,:,i) = s2 * eye(Ysz);
+    else
+      % eqn 12
+      SS = YY(:,:,i)/w(i)  - mu(:,i)*mu(:,i)';
+      if cov_type(1)=='d'
+	SS = diag(diag(SS));
+      end
+      Sigma(:,:,i) = SS;
+    end
+  end
+else % tied cov
+  if cov_type(1) == 's'
+    % eqn 19
+    s2 = (1/(N*Ysz))*(sum(YTY,2) + sum(diag(mu'*mu) .* w));
+    Sigma = s2*eye(Ysz);
+  else
+    SS = zeros(Ysz, Ysz);
+    % eqn 15
+    for i=1:Q % probably could vectorize this...
+      SS = SS + YY(:,:,i)/N - mu(:,i)*mu(:,i)';
+    end
+    if cov_type(1) == 'd'
+      Sigma = diag(diag(SS));
+    else
+      Sigma = SS;
+    end
+  end
+end
+
+if tied_cov
+  Sigma =  repmat(Sigma, [1 1 Q]);
+end
+Sigma = Sigma + cov_prior;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/mixgauss_classifier_apply.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function [classHatTest, probPos] = mixgauss_classifier_apply(mixgauss, testFeatures)
+
+Bpos = mixgauss_prob(testFeatures, mixgauss.pos.mu, mixgauss.pos.Sigma, mixgauss.pos.prior);
+Bneg = mixgauss_prob(testFeatures, mixgauss.neg.mu, mixgauss.neg.Sigma,  mixgauss.neg.prior);
+prior_pos = mixgauss.priorC(1);
+prior_neg = mixgauss.priorC(2);
+post = normalize([Bpos * prior_pos; Bneg * prior_neg], 1);
+probPos = post(1,:)';
+[junk, classHatTest] = max(post);
+classHatTest(find(classHatTest==2))=0;
+classHatTest = classHatTest(:);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/mixgauss_classifier_train.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,33 @@
+function mixgauss = mixgauss_classifier_train(trainFeatures, trainLabels, nc, varargin)
+% function mixgauss = mixgauss_classifier_train(trainFeatures, trainLabels, nclusters, varargin)
+% trainFeatures(:,i) for i'th example
+% trainLabels should be 0,1
+% To evaluate performance on a tets set, use
+% mixgauss = mixgauss_classifier_train(trainFeatures, trainLabels, nc, 'testFeatures', tf, 'testLabels', tl)
+
+[testFeatures, testLabels, max_iter, thresh, cov_type, mu, Sigma, priorC, method, ...
+ cov_prior, verbose, prune_thresh] = process_options(...
+    varargin, 'testFeatures', [], 'testLabels', [], ...
+     'max_iter', 10, 'thresh', 0.01, 'cov_type', 'diag', ...
+    'mu', [], 'Sigma', [], 'priorC', [], 'method', 'kmeans', ...
+    'cov_prior', [], 'verbose', 0, 'prune_thresh', 0);
+
+Nclasses = 2; % max([trainLabels testLabels]) + 1;
+
+pos = find(trainLabels == 1);
+neg = find(trainLabels == 0);
+
+if verbose, fprintf('fitting pos\n'); end
+[mixgauss.pos.mu, mixgauss.pos.Sigma, mixgauss.pos.prior] = ...
+    mixgauss_em(trainFeatures(:, pos), nc, varargin{:});
+
+if verbose, fprintf('fitting neg\n'); end
+[mixgauss.neg.mu, mixgauss.neg.Sigma, mixgauss.neg.prior] = ...
+    mixgauss_em(trainFeatures(:, neg), nc, varargin{:});
+
+
+if ~isempty(priorC)
+  mixgauss.priorC = priorC;
+else
+  mixgauss.priorC = normalize([length(pos) length(neg)]);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/mixgauss_em.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,74 @@
+function [mu, Sigma, prior] = mixgauss_em(Y, nc, varargin)
+% MIXGAUSS_EM Fit the parameters of a mixture of Gaussians using EM
+% function [mu, Sigma, prior] = mixgauss_em(data, nc, varargin)
+%
+% data(:, t) is the t'th data point
+% nc is the number of clusters
+
+% Kevin Murphy, 13 May 2003
+
+[max_iter, thresh, cov_type, mu, Sigma, method, ...
+ cov_prior, verbose, prune_thresh] = process_options(...
+    varargin, 'max_iter', 10, 'thresh', 1e-2, 'cov_type', 'full', ...
+    'mu', [], 'Sigma', [],  'method', 'kmeans', ...
+    'cov_prior', [], 'verbose', 0, 'prune_thresh', 0);
+
+[ny T] = size(Y);
+
+if nc==1
+  % No latent variable, so there is a closed-form solution
+  mu = mean(Y')';
+  Sigma = cov(Y');
+  if strcmp(cov_type, 'diag')
+    Sigma = diag(diag(Sigma));
+  end
+  prior = 1;
+  return;
+end
+
+if isempty(mu)
+  [mu, Sigma, prior] = mixgauss_init(nc, Y, cov_type, method);
+end
+
+previous_loglik = -inf;
+num_iter = 1;
+converged = 0;
+
+%if verbose, fprintf('starting em\n'); end
+
+while (num_iter <= max_iter) & ~converged
+  % E step
+  probY = mixgauss_prob(Y, mu, Sigma, prior); % probY(q,t)
+  [post, lik] = normalize(probY .* repmat(prior, 1, T), 1); % post(q,t)
+  loglik = log(sum(lik));
+ 
+  % extract expected sufficient statistics
+  w = sum(post,2);  % w(c) = sum_t post(c,t)
+  WYY = zeros(ny, ny, nc);  % WYY(:,:,c) = sum_t post(c,t) Y(:,t) Y(:,t)'
+  WY = zeros(ny, nc);  % WY(:,c) = sum_t post(c,t) Y(:,t)
+  WYTY = zeros(nc,1); % WYTY(c) = sum_t post(c,t) Y(:,t)' Y(:,t)
+  for c=1:nc
+    weights = repmat(post(c,:), ny, 1); % weights(:,t) = post(c,t)
+    WYbig = Y .* weights; % WYbig(:,t) = post(c,t) * Y(:,t)
+    WYY(:,:,c) = WYbig * Y';
+    WY(:,c) = sum(WYbig, 2); 
+    WYTY(c) = sum(diag(WYbig' * Y)); 
+  end
+  
+  % M step
+  prior = normalize(w);
+  [mu, Sigma] = mixgauss_Mstep(w, WY, WYY, WYTY, 'cov_type', cov_type, 'cov_prior', cov_prior);
+  
+  if verbose, fprintf(1, 'iteration %d, loglik = %f\n', num_iter, loglik); end
+  num_iter =  num_iter + 1;
+  converged = em_converged(loglik, previous_loglik, thresh);
+  previous_loglik = loglik;
+  
+end
+
+if prune_thresh > 0
+  ndx = find(prior < prune_thresh);
+  mu(:,ndx) = [];
+  Sigma(:,:,ndx) = [];
+  prior(ndx) = [];
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/mixgauss_init.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,49 @@
+function [mu, Sigma, weights] = mixgauss_init(M, data, cov_type, method)
+% MIXGAUSS_INIT Initial parameter estimates for a mixture of Gaussians
+% function [mu, Sigma, weights] = mixgauss_init(M, data, cov_type. method)
+%
+% INPUTS:
+% data(:,t) is the t'th example
+% M = num. mixture components
+% cov_type = 'full', 'diag' or 'spherical'
+% method = 'rnd' (choose centers randomly from data) or 'kmeans' (needs netlab)
+%
+% OUTPUTS:
+% mu(:,k) 
+% Sigma(:,:,k) 
+% weights(k)
+
+if nargin < 4, method = 'kmeans'; end
+
+[d T] = size(data);
+data = reshape(data, d, T); % in case it is data(:, t, sequence_num)
+
+switch method
+ case 'rnd', 
+  C = cov(data');
+  Sigma = repmat(diag(diag(C))*0.5, [1 1 M]);
+  % Initialize each mean to a random data point
+  indices = randperm(T);
+  mu = data(:,indices(1:M));
+  weights = normalise(ones(M,1));
+ case 'kmeans',
+  mix = gmm(d, M, cov_type);
+  options = foptions;
+  max_iter = 5;
+  options(1) = -1; % be quiet!
+  options(14) = max_iter;
+  mix = gmminit(mix, data', options);
+  mu = reshape(mix.centres', [d M]);
+  weights = mix.priors(:);
+  for m=1:M
+    switch cov_type
+     case 'diag',
+      Sigma(:,:,m) = diag(mix.covars(m,:));
+     case 'full',
+      Sigma(:,:,m) = mix.covars(:,:,m);
+     case 'spherical',
+      Sigma(:,:,m) = mix.covars(m) * eye(d);
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/mixgauss_prob.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,133 @@
+function [B, B2] = mixgauss_prob(data, mu, Sigma, mixmat, unit_norm)
+% EVAL_PDF_COND_MOG Evaluate the pdf of a conditional mixture of Gaussians
+% function [B, B2] = eval_pdf_cond_mog(data, mu, Sigma, mixmat, unit_norm)
+%
+% Notation: Y is observation, M is mixture component, and both may be conditioned on Q.
+% If Q does not exist, ignore references to Q=j below.
+% Alternatively, you may ignore M if this is a conditional Gaussian.
+%
+% INPUTS:
+% data(:,t) = t'th observation vector 
+%
+% mu(:,k) = E[Y(t) | M(t)=k] 
+% or mu(:,j,k) = E[Y(t) | Q(t)=j, M(t)=k]
+%
+% Sigma(:,:,j,k) = Cov[Y(t) | Q(t)=j, M(t)=k]
+% or there are various faster, special cases:
+%   Sigma() - scalar, spherical covariance independent of M,Q.
+%   Sigma(:,:) diag or full, tied params independent of M,Q. 
+%   Sigma(:,:,j) tied params independent of M. 
+%
+% mixmat(k) = Pr(M(t)=k) = prior
+% or mixmat(j,k) = Pr(M(t)=k | Q(t)=j) 
+% Not needed if M is not defined.
+%
+% unit_norm - optional; if 1, means data(:,i) AND mu(:,i) each have unit norm (slightly faster)
+%
+% OUTPUT:
+% B(t) = Pr(y(t)) 
+% or
+% B(i,t) = Pr(y(t) | Q(t)=i) 
+% B2(i,k,t) = Pr(y(t) | Q(t)=i, M(t)=k) 
+%
+% If the number of mixture components differs depending on Q, just set the trailing
+% entries of mixmat to 0, e.g., 2 components if Q=1, 3 components if Q=2,
+% then set mixmat(1,3)=0. In this case, B2(1,3,:)=1.0.
+
+
+
+
+if isvector(mu) & size(mu,2)==1
+  d = length(mu);
+  Q = 1; M = 1;
+elseif ndims(mu)==2
+  [d Q] = size(mu);
+  M = 1;
+else
+  [d Q M] = size(mu);
+end
+[d T] = size(data);
+
+if nargin < 4, mixmat = ones(Q,1); end
+if nargin < 5, unit_norm = 0; end
+
+%B2 = zeros(Q,M,T); % ATB: not needed allways
+%B = zeros(Q,T);
+
+if isscalar(Sigma)
+  mu = reshape(mu, [d Q*M]);
+  if unit_norm % (p-q)'(p-q) = p'p + q'q - 2p'q = n+m -2p'q since p(:,i)'p(:,i)=1
+    %avoid an expensive repmat
+    disp('unit norm')
+    %tic; D = 2 -2*(data'*mu)'; toc 
+    D = 2 - 2*(mu'*data);
+    tic; D2 = sqdist(data, mu)'; toc
+    assert(approxeq(D,D2)) 
+  else
+    D = sqdist(data, mu)';
+  end
+  clear mu data % ATB: clear big old data
+  % D(qm,t) = sq dist between data(:,t) and mu(:,qm)
+  logB2 = -(d/2)*log(2*pi*Sigma) - (1/(2*Sigma))*D; % det(sigma*I) = sigma^d
+  B2 = reshape(exp(logB2), [Q M T]);
+  clear logB2 % ATB: clear big old data
+  
+elseif ndims(Sigma)==2 % tied full
+  mu = reshape(mu, [d Q*M]);
+  D = sqdist(data, mu, inv(Sigma))';
+  % D(qm,t) = sq dist between data(:,t) and mu(:,qm)
+  logB2 = -(d/2)*log(2*pi) - 0.5*logdet(Sigma) - 0.5*D;
+  %denom = sqrt(det(2*pi*Sigma));
+  %numer = exp(-0.5 * D);
+  %B2 = numer/denom;
+  B2 = reshape(exp(logB2), [Q M T]);
+  
+elseif ndims(Sigma)==3 % tied across M
+  B2 = zeros(Q,M,T);
+  for j=1:Q
+    % D(m,t) = sq dist between data(:,t) and mu(:,j,m)
+    if isposdef(Sigma(:,:,j))
+      D = sqdist(data, permute(mu(:,j,:), [1 3 2]), inv(Sigma(:,:,j)))';
+      logB2 = -(d/2)*log(2*pi) - 0.5*logdet(Sigma(:,:,j)) - 0.5*D;
+      B2(j,:,:) = exp(logB2);
+    else
+      error(sprintf('mixgauss_prob: Sigma(:,:,q=%d) not psd\n', j));
+    end
+  end
+  
+else % general case
+  B2 = zeros(Q,M,T);
+  for j=1:Q
+    for k=1:M
+      %if mixmat(j,k) > 0
+      B2(j,k,:) = gaussian_prob(data, mu(:,j,k), Sigma(:,:,j,k));
+      %end
+    end
+  end
+end
+
+% B(j,t) = sum_k B2(j,k,t) * Pr(M(t)=k | Q(t)=j) 
+
+% The repmat is actually slower than the for-loop, because it uses too much memory
+% (this is true even for small T).
+
+%B = squeeze(sum(B2 .* repmat(mixmat, [1 1 T]), 2));
+%B = reshape(B, [Q T]); % undo effect of squeeze in case Q = 1
+  
+B = zeros(Q,T);
+if Q < T
+  for q=1:Q
+    %B(q,:) = mixmat(q,:) * squeeze(B2(q,:,:)); % squeeze chnages order if M=1
+    B(q,:) = mixmat(q,:) * permute(B2(q,:,:), [2 3 1]); % vector * matrix sums over m
+  end
+else
+  for t=1:T
+    B(:,t) = sum(mixmat .* B2(:,:,t), 2); % sum over m
+  end
+end
+%t=toc;fprintf('%5.3f\n', t)
+
+%tic
+%A = squeeze(sum(B2 .* repmat(mixmat, [1 1 T]), 2));
+%t=toc;fprintf('%5.3f\n', t)
+%assert(approxeq(A,B)) % may be false because of round off error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/mixgauss_prob_test.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,111 @@
+function test_eval_pdf_cond_mixgauss()
+
+%Q = 10; M = 100; d = 20; T = 500;
+Q = 2; M = 3; d = 4; T = 5;
+
+mu = rand(d,Q,M);
+data = randn(d,T);
+%mixmat = mk_stochastic(rand(Q,M));
+mixmat = mk_stochastic(ones(Q,M));
+
+% tied scalar
+Sigma = 0.01;
+
+mu = rand(d,M,Q);
+weights = mixmat';
+N = M*ones(1,Q);
+tic; [B, B2, D] = parzen(data, mu, Sigma, N, weights); toc
+tic; [BC, B2C, DC] = parzenC(data, mu, Sigma, N); toc
+approxeq(B,BC)
+B2C = reshape(B2C,[M Q T]);
+approxeq(B2,B2C)
+DC = reshape(DC,[M Q T]);
+approxeq(D,DC)
+
+
+return
+
+tic; [B, B2] = eval_pdf_cond_mixgauss(data, mu, Sigma, mixmat); toc
+tic; C = eval_pdf_cond_parzen(data, mu, Sigma); toc
+approxeq(B,C)
+
+return;
+
+
+mu = reshape(mu, [d Q*M]);
+
+data = mk_unit_norm(data);
+mu = mk_unit_norm(mu);
+tic; D = 2 -2*(data'*mu); toc % avoid an expensive repmat
+tic; D2 = sqdist(data, mu); toc
+approxeq(D,D2)
+
+
+% D(t,m) = sq dist between data(:,t) and mu(:,m)
+mu = reshape(mu, [d Q*M]);
+D = dist2(data', mu');
+%denom = (2*pi)^(d/2)*sqrt(abs(det(C)));
+denom = (2*pi*Sigma)^(d/2); % sqrt(det(2*pi*Sigma))
+numer = exp(-0.5/Sigma  * D');
+B2 = numer / denom;
+B2 = reshape(B2, [Q M T]);
+
+tic; B = squeeze(sum(B2 .* repmat(mixmat, [1 1 T]), 2)); toc
+
+tic
+A = zeros(Q,T);
+for q=1:Q
+  A(q,:) = mixmat(q,:) * squeeze(B2(q,:,:)); % sum over m
+end
+toc
+assert(approxeq(A,B))
+
+tic
+A = zeros(Q,T);
+for t=1:T
+  A(:,t) = sum(mixmat .* B2(:,:,t), 2); % sum over m
+end
+toc
+assert(approxeq(A,B))
+
+    
+
+
+mu = reshape(mu, [d Q M]);
+B3 = zeros(Q,M,T);
+for j=1:Q
+  for k=1:M
+    B3(j,k,:) = gaussian_prob(data, mu(:,j,k), Sigma*eye(d));
+  end
+end
+assert(approxeq(B2, B3))
+
+logB4 = -(d/2)*log(2*pi*Sigma) - (1/(2*Sigma))*D; % det(sigma*I) = sigma^d
+B4 = reshape(exp(logB4), [Q M T]);
+assert(approxeq(B4, B3))
+
+
+
+  
+% tied cov matrix
+
+Sigma = rand_psd(d,d);
+mu = reshape(mu, [d Q*M]);
+D = sqdist(data, mu, inv(Sigma))';
+denom = sqrt(det(2*pi*Sigma));
+numer = exp(-0.5 * D);
+B2 = numer / denom;
+B2 = reshape(B2, [Q M T]);
+
+mu = reshape(mu, [d Q M]);
+B3 = zeros(Q,M,T);
+for j=1:Q
+  for k=1:M
+    B3(j,k,:) = gaussian_prob(data, mu(:,j,k), Sigma);
+  end
+end
+assert(approxeq(B2, B3))
+
+logB4 = -(d/2)*log(2*pi) - 0.5*logdet(Sigma) - 0.5*D;
+B4 = reshape(exp(logB4), [Q M T]);
+assert(approxeq(B4, B3))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/mixgauss_sample.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function [data, indices] = mixgauss_sample(mu, Sigma, mixweights, Nsamples)
+%  mixgauss_sample Sample data from a mixture of Gaussians
+% function [data, indices] = mixgauss_sample(mu, Sigma, mixweights, Nsamples)
+%
+% Model is P(X) = sum_k mixweights(k) N(X; mu(:,k), Sigma(:,:,k)) or Sigma(k) for scalar
+% data(:,i) is the i'th sample from P(X)
+% indices(i) is the component from which sample i was drawn
+
+[D K] = size(mu);
+data = zeros(D, Nsamples);
+indices = sample_discrete(mixweights, 1, Nsamples);
+for k=1:K
+  if ndims(Sigma) < 3
+    sig = Sigma(k);
+  else
+    sig = Sigma(:,:,k);
+  end
+  ndx = find(indices==k);
+  if length(ndx) > 0
+    data(:,ndx) = sample_gaussian(mu(:,k), sig, length(ndx))';
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/mkPolyFvec.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function p = mkPolyFvec(x)
+% MKPOLYFVEC Make feature vector by constructing 2nd order polynomial from input data
+% function p = mkPolyFvec(x)
+%
+% x(:,i) for example i
+% p(:,i) = [x(1,i) x(2,i) x(3,i) x(1,i)^2 x(2,i)^2 x(3,i)^2 ..
+%           x(1,i)*x(2,i) x(1,i)*x(3,i) x(2,i)*x(3,i)]'
+%
+% Example
+% x = [4 5 6]'
+% p = [4 5 6  16 25 36  20 24 30]'
+
+fvec = x;
+fvecSq = x.*x;
+[D N] = size(x);
+fvecCross = zeros(D*(D-1)/2, N);
+i = 1;
+for d=1:D
+  for d2=d+1:D
+    fvecCross(i,:) = x(d,:) .* x(d2,:);
+    i = i + 1;
+  end
+end
+p = [fvec; fvecSq; fvecCross];
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/mk_unit_norm.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function B = mk_unit_norm(A)
+% MK_UNIT_NORM Make each column be a unit norm vector
+% function B = mk_unit_norm(A)
+% 
+% We divide each column by its magnitude
+
+
+[nrows ncols] = size(A);
+s = sum(A.^2);
+ndx = find(s==0);
+s(ndx)=1; 
+B = A ./ repmat(sqrt(s), [nrows 1]);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/multinomial_prob.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,20 @@
+function B = eval_pdf_cond_multinomial(data, obsmat)
+% EVAL_PDF_COND_MULTINOMIAL Evaluate pdf of conditional multinomial 
+% function B = eval_pdf_cond_multinomial(data, obsmat)
+%
+% Notation: Y = observation (O values), Q = conditioning variable (K values)
+%
+% Inputs:
+% data(t) = t'th observation - must be an integer in {1,2,...,K}: cannot be 0!
+% obsmat(i,o) = Pr(Y(t)=o | Q(t)=i)
+%
+% Output:
+% B(i,t) = Pr(y(t) | Q(t)=i)
+
+[Q O] = size(obsmat);
+T = prod(size(data)); % length(data);
+B = zeros(Q,T);
+
+for t=1:T
+  B(:,t) = obsmat(:, data(t));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/multinomial_sample.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function Y = sample_cond_multinomial(X, M)
+% SAMPLE_MULTINOMIAL Sample Y(i) ~ M(X(i), :)
+% function Y = sample_multinomial(X, M)
+%
+% X(i) = i'th sample
+% M(i,j) = P(Y=j | X=i) = noisy channel model
+%
+% e.g., if X is a binary image,
+% Y = sample_multinomial(softeye(2, 0.9), X)
+% will create a noisy version of X, where bits are flipped with probability 0.1
+
+if any(X(:)==0)
+  error('data must only contain positive integers')
+end
+
+Y = zeros(size(X));
+for i=min(X(:)):max(X(:))
+  ndx = find(X==i);
+  Y(ndx) = sample_discrete(M(i,:), length(ndx), 1);
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/multipdf.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+function p = multipdf(x,theta)
+%MULTIPDF Multinomial probability density function.
+%   p = multipdf(x,theta) returns the probabilities of 
+%   vector x, under the multinomial distribution
+%   with parameter vector theta.
+%
+%   Author: David Ross
+
+%--------------------------------------------------------
+% Check the arguments.
+%--------------------------------------------------------
+error(nargchk(2,2,nargin));
+
+% make sure theta is a vector
+if ndims(theta) > 2 | all(size(theta) > 1)
+    error('theta must be a vector');
+end
+
+% make sure x is of the appropriate size
+if ndims(x) > 2 | any(size(x) ~= size(theta))
+    error('columns of X must have same length as theta');
+end
+
+
+%--------------------------------------------------------
+% Main...
+%--------------------------------------------------------
+p = prod(theta .^ x);
+p = p .* factorial(sum(x)) ./ prod(factorial_v(x));
+
+
+%--------------------------------------------------------
+% Function factorial_v(x): computes the factorial function
+% on each element of x
+%--------------------------------------------------------
+function r = factorial_v(x)
+
+if size(x,2) == 1
+    x = x';
+end
+
+r = [];
+for y = x
+    r = [r factorial(y)];
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/multirnd.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,48 @@
+function r = multirnd(theta,k)
+%MULTIRND - Random vector from multinomial distribution.
+%   r = multirnd(theta,k) returns a vector randomly selected
+%   from the multinomial distribution with parameter vector
+%   theta, and count k (i.e. sum(r) = k).
+%
+%   Note: if k is unspecified, then it is assumed k=1.
+%
+%   Author: David Ross
+%
+
+%--------------------------------------------------------
+% Check the arguments.
+%--------------------------------------------------------
+error(nargchk(1,2,nargin));
+
+% make sure theta is a vector
+if ndims(theta) > 2 | all(size(theta) > 1)
+    error('theta must be a vector');
+end
+
+% if theta is a row vector, convert it to a column vector
+if size(theta,1) == 1
+    theta = theta';
+end
+
+% make sure k is a scalar?
+
+% if the number of samples has not been provided, set
+% it to one
+if nargin == 1
+    k = 1;
+end
+
+
+%--------------------------------------------------------
+% Main...
+%--------------------------------------------------------
+n = length(theta);
+theta_cdf = cumsum(theta);
+
+r = zeros(n,1);
+random_vals = rand(k,1);
+
+for j = 1:k
+    index = min(find(random_vals(j) <= theta_cdf));
+    r(index) = r(index) + 1;
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/normal_coef.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function c = normal_coef (Sigma)
+% NORMAL_COEF Compute the normalizing coefficient for a multivariate gaussian.
+% c = normal_coef (Sigma)
+
+n = length(Sigma);
+c = (2*pi)^(-n/2) * det(Sigma)^(-0.5);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/partial_corr_coef.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function [r, c] = partial_corr_coef(S, i, j, Y)
+% PARTIAL_CORR_COEF Compute a partial correlation coefficient
+% [r, c] = partial_corr_coef(S, i, j, Y)
+%
+% S is the covariance (or correlation) matrix for X, Y, Z
+% where X=[i j], Y is conditioned on, and Z is marginalized out.
+% Let S2 = Cov[X | Y] be the partial covariance matrix.
+% Then c = S2(i,j) and r = c / sqrt( S2(i,i) * S2(j,j) ) 
+%
+
+% Example: Anderson (1984) p129
+% S = [1.0 0.8 -0.4;
+%     0.8 1.0 -0.56;
+%     -0.4 -0.56 1.0];
+% r(1,3 | 2) = 0.0966 
+%
+% Example: Van de Geer (1971) p111
+%S = [1     0.453 0.322;
+%     0.453 1.0   0.596;
+%     0.322 0.596 1];
+% r(2,3 | 1) = 0.533
+
+X = [i j];
+i2 = 1; % find_equiv_posns(i, X);
+j2 = 2; % find_equiv_posns(j, X);
+S2 = S(X,X) - S(X,Y)*inv(S(Y,Y))*S(Y,X);
+c = S2(i2,j2);
+r = c / sqrt(S2(i2,i2) * S2(j2,j2));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/parzen.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,88 @@
+function [B,B2,dist] = parzen(data, mu, Sigma, N)
+% EVAL_PDF_COND_PARZEN Evaluate the pdf of a conditional Parzen window
+% function B = eval_pdf_cond_parzen(data, mu, Sigma, N)
+%
+% B(q,t) = Pr(data(:,t) | Q=q) = sum_{m=1}^{N(q)} w(m,q)*K(data(:,t) - mu(:,m,q); sigma)
+% where K() is a Gaussian kernel with spherical variance sigma,
+% and w(m,q) = 1/N(q) if m<=N(q) and = 0 otherwise
+% where N(q) is the number of mxiture components for q 
+%
+% B2(m,q,t) =  K(data(:,t) - mu(:,m,q); sigma) for m=1:max(N)
+
+% This is like eval_pdf_cond_parzen, except mu is mu(:,m,q) instead of mu(:,q,m)
+% and we use 1/N(q) instead of mixmat(q,m)
+
+if nargout >= 2
+  keep_B2 = 1;
+else
+  keep_B2 = 0;
+end
+
+if nargout >= 3
+  keep_dist = 1;
+else
+  keep_dist = 0;
+end
+
+[d M Q] = size(mu);
+[d T] = size(data);
+
+M = max(N(:));
+
+B = zeros(Q,T);
+const1 = (2*pi*Sigma)^(-d/2);
+const2 = -(1/(2*Sigma));
+if T*Q*M>20000000 % not enough memory to call sqdist
+  disp('eval parzen for loop')
+  if keep_dist,
+    dist = zeros(M,Q,T);
+  end
+  if keep_B2
+    B2 = zeros(M,Q,T);
+  end
+  for q=1:Q
+    D = sqdist(mu(:,1:N(q),q), data); % D(m,t)
+    if keep_dist
+      dist(:,q,:) = D;
+    end
+    tmp = const1 * exp(const2*D);
+    if keep_B2,
+      B2(:,q,:) = tmp;
+    end
+    if N(q) > 0
+      %B(q,:) = (1/N(q)) * const1 * sum(exp(const2*D), 2);
+      B(q,:) = (1/N(q)) * sum(tmp,1);
+    end
+  end
+else
+  %disp('eval parzen vectorized')
+  dist = sqdist(reshape(mu(:,1:M,:), [d M*Q]), data); % D(mq,t)
+  dist = reshape(dist, [M Q T]);
+  B2 = const1 * exp(const2*dist); % B2(m,q,t)
+  if ~keep_dist
+    clear dist
+  end
+  
+  % weights(m,q) is the weight of mixture component m for q  
+  %    = 1/N(q) if m<=N(q) and = 0 otherwise
+  % e.g., N = [2   3   1], M = 3,
+  % weights = [1/2 1/3 1   = 1/2 1/3 1/1      2 3 1     1 1 1
+  %            1/2 1/3 0     1/2 1/3 1/1 .*   2 3 1 <=  2 2 2
+  %            0   1/3 0]    1/2 1/3 1/1      2 3 1     3 3 3
+   
+  Ns = repmat(N(:)', [M 1]);
+  ramp = 1:M;
+  ramp = repmat(ramp(:), [1 Q]);
+  n = N + (N==0); % avoid 1/0 by replacing with 0* 1/1m where 0 comes from mask
+  N1 = repmat(1 ./ n(:)', [M 1]);
+  mask = (ramp <= Ns);
+  weights = N1 .* mask;
+  B2 = B2 .* repmat(mask, [1 1 T]);
+  
+  % B(q,t) = sum_m B2(m,q,t) * P(m|q) = sum_m B2(m,q,t) * weights(m,q)
+  B = squeeze(sum(B2 .* repmat(weights, [1 1 T]), 1)); 
+  B = reshape(B, [Q T]); % undo effect of squeeze in case Q = 1
+end
+
+  
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/parzenC.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,116 @@
+/* C mex version of parzen.m
+[B,B2] = parzen(feat, mu,  Sigma, Nproto); 
+*/
+#include "mex.h"
+#include <stdio.h>
+#include <math.h>
+
+#define PI 3.141592654
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+  int    D, M, Q, T, d, m, q, t;
+  double *data, *mu, *SigmaPtr, *N, Sigma;
+  double *B, *dist, *B2, tmp;
+  const int* dim_mu;
+  double const1, const2, sum_m, sum_d, diff;
+  int Dt, DMq, Dm, MQt, Mq;
+  int dims_B2[3];
+
+  int ndim_mu, i, save_B2;
+  
+  data = mxGetPr(prhs[0]);
+  mu = mxGetPr(prhs[1]);
+  SigmaPtr = mxGetPr(prhs[2]);
+  Sigma = *SigmaPtr;
+  N = mxGetPr(prhs[3]);
+  
+  D = mxGetM(prhs[0]);
+  T = mxGetN(prhs[0]);
+
+  ndim_mu = mxGetNumberOfDimensions(prhs[1]);
+  dim_mu = mxGetDimensions(prhs[1]);
+  D = dim_mu[0];
+  M = dim_mu[1];
+  /* printf("parzenC: nlhs=%d, D=%d, M=%d, T=%d\n", nlhs, D, M, T);  */
+
+  /* If mu is mu(d,m,o,p), then [d M Q] = size(mu) in matlab sets Q=o*p,
+     i.e.. the size of all conditioning variabeles */
+  Q = 1;
+  for (i = 2; i < ndim_mu; i++) {
+    /* printf("dim_mu[%d]=%d\n", i, dim_mu[i]); */
+    Q = Q*dim_mu[i];
+  }
+
+  /* M = max(N) */
+  M = -1000000;
+  for (i=0; i < Q; i++) {
+    /* printf("N[%d]=%d\n", i, (int) N[i]); */
+    if (N[i] > M) {
+      M = (int) N[i];
+    }
+  }
+
+  /*  printf("parzenC: nlhs=%d, D=%d, Q=%d, M=%d, T=%d\n", nlhs, D, Q, M, T); */
+
+  plhs[0] = mxCreateDoubleMatrix(Q,T, mxREAL);
+  B = mxGetPr(plhs[0]);
+
+  if (nlhs >= 2)
+    save_B2 = 1;
+  else
+    save_B2 = 0;
+  
+  if (save_B2) {
+    /* printf("parzenC saving B2\n");  */
+    /*plhs[1] = mxCreateDoubleMatrix(M*Q*T,1, mxREAL);*/
+    dims_B2[0] = M;
+    dims_B2[1] = Q;
+    dims_B2[2] = T;
+    plhs[1] = mxCreateNumericArray(3, dims_B2, mxDOUBLE_CLASS, mxREAL);
+    B2 = mxGetPr(plhs[1]);
+  } else {
+    /* printf("parzenC not saving B2\n"); */
+  }
+  /*
+  plhs[2] = mxCreateDoubleMatrix(M*Q*T,1, mxREAL);
+  dist = mxGetPr(plhs[2]);
+  */
+  const1 = pow(2*PI*Sigma, -D/2.0);
+  const2 = -(1/(2*Sigma));
+ 
+  for (t=0; t < T; t++) {
+    /* printf("t=%d!\n",t); */
+    Dt  = D*t;
+    MQt = M*Q*t;
+    for (q=0; q < Q; q++) {
+      sum_m = 0;
+      DMq = D*M*q;
+      Mq = M*q;
+
+      for (m=0; m < (int)N[q]; m++) {
+	sum_d = 0;
+	Dm = D*m;
+	for (d=0; d < D; d++) {
+	  /* diff = data(d,t) - mu(d,m,q) */
+	  /*diff = data[d + D*t] - mu[d + D*m + D*M*q]; */
+	  diff = data[d + Dt] - mu[d + Dm + DMq];
+	  sum_d = sum_d + diff*diff;
+	}
+	/* dist[m,q,t] = dist[m + M*q + M*Q*t] = dist[m + Mq + MQt] = sum_d */
+	tmp = const1 * exp(const2*sum_d);
+	sum_m = sum_m + tmp;
+	if (save_B2)
+	  B2[m + Mq + MQt] = tmp;
+      }
+
+      if (N[q]>0) {
+	B[q + Q*t] = (1.0/N[q]) *  sum_m;
+      } else {
+	B[q + Q*t] = 0.0;
+      }
+    }
+  }
+}
+
+
+
Binary file _FullBNT/KPMstats/parzenC.dll has changed
Binary file _FullBNT/KPMstats/parzenC.mexglx has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/parzenC_test.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+d = 2; M = 3; Q = 4; T = 5; Sigma = 10;
+N = sample_discrete(normalize(ones(1,M)), 1, Q);
+data = randn(d,T);
+mu = randn(d,M,Q);
+
+[BM, B2M] = parzen(data, mu, Sigma, N);
+[B, B2] = parzenC(data, mu, Sigma, N);
+
+approxeq(B,BM)
+approxeq(B2,B2M)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/parzen_fit_select_unif.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+function [mu, N, pick] = parzen_fit_select_unif(data, labels, max_proto, varargin)
+% PARZEN_FIT_SELECT_UNIF Fit a parzen density estimator by selecting prototypes uniformly from data
+% [mu, N, pick] = parzen_fit_select_unif(data, max_proto, labels, ...)
+%
+% We partition the data into different subsets based on the labels.
+% We then choose up to max_proto columns from each subset, chosen uniformly.
+%
+% INPUTS
+% data(:,t)
+% labels(t) - should be in {1,2,..,Q}
+% max_proto - max number of prototypes per partition
+%
+% Optional args
+% partition_names{m} - for debugging
+% boundary - do not choose prototypes which are within 'boundary' of the label transition
+%
+% OUTPUTS
+% mu(:, m, q) for label q, prototype m for 1 <= m <= N(q)
+% N(q) = number of prototypes for label q
+% pick{q} = identity of the prototypes
+
+nclasses = max(labels);
+[boundary, partition_names] = process_options(...
+    varargin, 'boundary', 0, 'partition_names', []);
+
+[D T] = size(data);
+mu = zeros(D, 1, nclasses); % dynamically determine num prototypes (may be less than K)
+mean_feat = mean(data,2);
+pick = cell(1,nclasses);
+for c=1:nclasses
+  ndx = find(labels==c);
+  if isempty(ndx)
+    %fprintf('no training images have label %d (%s)\n', c, partition_names{c})
+    fprintf('no training images have label %d\n', c);
+    nviews = 1;
+    mu(:,1,c) = mean_feat;
+  else
+    foo = linspace(boundary+1, length(ndx-boundary), max_proto);
+    pick{c} = ndx(unique(floor(foo)));
+    nviews = length(pick{c});
+    %fprintf('picking %d views for class %d=%s\n', nviews, c, class_names{c});
+    mu(:,1:nviews,c) = data(:, pick{c});
+  end
+  N(c) = nviews;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/pca.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,42 @@
+function [PCcoeff, PCvec] = pca(data, N)
+%PCA	Principal Components Analysis
+%
+%	Description
+%	 PCCOEFF = PCA(DATA) computes the eigenvalues of the covariance
+%	matrix of the dataset DATA and returns them as PCCOEFF.  These
+%	coefficients give the variance of DATA along the corresponding
+%	principal components.
+%
+%	PCCOEFF = PCA(DATA, N) returns the largest N eigenvalues.
+%
+%	[PCCOEFF, PCVEC] = PCA(DATA) returns the principal components as well
+%	as the coefficients.  This is considerably more computationally
+%	demanding than just computing the eigenvalues.
+%
+%	See also
+%	EIGDEC, GTMINIT, PPCA
+%
+
+%	Copyright (c) Ian T Nabney (1996-2001)
+
+if nargin == 1
+   N = size(data, 2);
+end
+
+if nargout == 1
+   evals_only = logical(1);
+else
+   evals_only = logical(0);
+end
+
+if N ~= round(N) | N < 1 | N > size(data, 2)
+   error('Number of PCs must be integer, >0, < dim');
+end
+
+% Find the sorted eigenvalues of the data covariance matrix
+if evals_only
+   PCcoeff = eigdec(cov(data), N);
+else
+  [PCcoeff, PCvec] = eigdec(cov(data), N);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/rndcheck.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,294 @@
+function [errorcode, rows, columns] = rndcheck(nargs,nparms,arg1,arg2,arg3,arg4,arg5)
+%RNDCHECK error checks the argument list for the random number generators.
+
+%   B.A. Jones  1-22-93
+%   Copyright (c) 1993-98 by The MathWorks, Inc.
+%   $Revision: 1.1.1.1 $  $Date: 2005/04/26 02:29:22 $
+
+sizeinfo = nargs - nparms;
+errorcode = 0;
+
+if nparms == 3
+    [r1 c1] = size(arg1);
+    [r2 c2] = size(arg2);
+    [r3 c3] = size(arg3);
+end
+
+if nparms == 2
+    [r1 c1] = size(arg1);
+    [r2 c2] = size(arg2);
+end 
+
+if sizeinfo == 0        
+    if nparms == 1
+        [rows columns] = size(arg1);
+    end
+    
+    if nparms == 2
+        scalararg1 = (prod(size(arg1)) == 1);
+        scalararg2 = (prod(size(arg2)) == 1);
+        if ~scalararg1 & ~scalararg2
+            if r1 ~= r2 | c1 ~= c2
+                errorcode = 1;
+                return;         
+            end
+        end
+        if ~scalararg1
+            [rows columns] = size(arg1);
+        elseif ~scalararg2
+            [rows columns] = size(arg2);
+        else
+            [rows columns] = size(arg1);
+        end
+    end
+    
+    if nparms == 3
+        scalararg1 = (prod(size(arg1)) == 1);
+        scalararg2 = (prod(size(arg2)) == 1);
+        scalararg3 = (prod(size(arg3)) == 1);
+
+        if ~scalararg1 & ~scalararg2
+            if r1 ~= r2 | c1 ~= c2
+                errorcode = 1;
+                return;         
+            end
+        end
+
+        if ~scalararg1 & ~scalararg3
+            if r1 ~= r3 | c1 ~= c3
+                errorcode = 1;
+                return;                 
+            end
+        end
+
+        if ~scalararg3 & ~scalararg2
+            if r3 ~= r2 | c3 ~= c2
+                errorcode = 1;
+                return;         
+            end
+        end
+            if ~scalararg1
+                [rows columns] = size(arg1);
+            elseif ~scalararg2
+            [rows columns] = size(arg2);
+            else
+                [rows columns] = size(arg3);
+            end
+    end 
+end
+
+if sizeinfo == 1
+    scalararg1 = (prod(size(arg1)) == 1);
+    if nparms == 1
+        if prod(size(arg2)) ~= 2
+            errorcode = 2;
+            return;
+        end
+        if  ~scalararg1 & arg2 ~= size(arg1)
+            errorcode = 3;
+            return;
+        end
+        if (arg2(1) < 0 | arg2(2) < 0 | arg2(1) ~= round(arg2(1)) | arg2(2) ~= round(arg2(2))),
+            errorcode = 4;
+            return;
+        end 
+        rows    = arg2(1);
+        columns = arg2(2);
+    end
+    
+    if nparms == 2
+        if prod(size(arg3)) ~= 2
+            errorcode = 2;
+            return;
+        end
+        scalararg2 = (prod(size(arg2)) == 1);
+        if ~scalararg1 & ~scalararg2
+            if r1 ~= r2 | c1 ~= c2
+                errorcode = 1;
+                return;         
+            end
+        end
+        if (arg3(1) < 0 | arg3(2) < 0 | arg3(1) ~= round(arg3(1)) | arg3(2) ~= round(arg3(2))),
+            errorcode = 4;
+            return;
+        end 
+        if ~scalararg1
+            if any(arg3 ~= size(arg1))
+                errorcode = 3;
+                return;
+            end
+            [rows columns] = size(arg1);
+        elseif ~scalararg2
+            if any(arg3 ~= size(arg2))
+                errorcode = 3;
+                return;
+            end
+            [rows columns] = size(arg2);
+        else
+            rows    = arg3(1);
+            columns = arg3(2);
+        end
+    end
+    
+    if nparms == 3
+        if prod(size(arg4)) ~= 2
+            errorcode = 2;
+            return;
+        end
+        scalararg1 = (prod(size(arg1)) == 1);
+        scalararg2 = (prod(size(arg2)) == 1);
+        scalararg3 = (prod(size(arg3)) == 1);
+
+        if (arg4(1) < 0 | arg4(2) < 0 | arg4(1) ~= round(arg4(1)) | arg4(2) ~= round(arg4(2))),
+            errorcode = 4;
+            return;
+        end 
+
+        if ~scalararg1 & ~scalararg2
+            if r1 ~= r2 | c1 ~= c2
+                errorcode = 1;
+                return;         
+            end
+        end
+
+        if ~scalararg1 & ~scalararg3
+            if r1 ~= r3 | c1 ~= c3
+                errorcode = 1;
+                return;                 
+            end
+        end
+
+        if ~scalararg3 & ~scalararg2
+            if r3 ~= r2 | c3 ~= c2
+                errorcode = 1;
+                return;         
+            end
+        end
+        if ~scalararg1
+            if any(arg4 ~= size(arg1))
+                errorcode = 3;
+                return;
+            end
+            [rows columns] = size(arg1);
+        elseif ~scalararg2
+            if any(arg4 ~= size(arg2))
+                errorcode = 3;
+                return;
+            end
+            [rows columns] = size(arg2);
+        elseif ~scalararg3
+            if any(arg4 ~= size(arg3))
+                errorcode = 3;
+                return;
+            end
+            [rows columns] = size(arg3);
+        else
+            rows    = arg4(1);
+            columns = arg4(2);
+        end
+    end 
+end
+
+if sizeinfo == 2
+    if nparms == 1
+        scalararg1 = (prod(size(arg1)) == 1);
+        if ~scalararg1
+            [rows columns] = size(arg1);
+            if rows ~= arg2 | columns ~= arg3 
+                errorcode = 3;
+                return;
+            end
+        end
+    if (arg2 < 0 | arg3 < 0 | arg2 ~= round(arg2) | arg3 ~= round(arg3)),
+        errorcode = 4;
+        return;
+    end 
+        rows = arg2;
+        columns = arg3;
+    end
+    
+    if nparms == 2
+        scalararg1 = (prod(size(arg1)) == 1);
+        scalararg2 = (prod(size(arg2)) == 1);
+        if ~scalararg1 & ~scalararg2
+            if r1 ~= r2 | c1 ~= c2
+                errorcode = 1;
+                return;         
+            end
+        end
+        if ~scalararg1
+            [rows columns] = size(arg1);
+            if rows ~= arg3 | columns ~= arg4 
+                errorcode = 3;
+                return;
+            end     
+        elseif ~scalararg2
+            [rows columns] = size(arg2);
+            if rows ~= arg3 | columns ~= arg4 
+                errorcode = 3;
+                return;
+            end     
+        else
+            if (arg3 < 0 | arg4 < 0 | arg3 ~= round(arg3) | arg4 ~= round(arg4)),
+                errorcode = 4;
+                return;
+            end 
+            rows = arg3;
+            columns = arg4;
+        end
+    end
+    
+    if nparms == 3
+        scalararg1 = (prod(size(arg1)) == 1);
+        scalararg2 = (prod(size(arg2)) == 1);
+        scalararg3 = (prod(size(arg3)) == 1);
+
+        if ~scalararg1 & ~scalararg2
+            if r1 ~= r2 | c1 ~= c2
+                errorcode = 1;
+                return;         
+            end
+        end
+
+        if ~scalararg1 & ~scalararg3
+            if r1 ~= r3 | c1 ~= c3
+                errorcode = 1;
+                return;                 
+            end
+        end
+
+        if ~scalararg3 & ~scalararg2
+            if r3 ~= r2 | c3 ~= c2
+                errorcode = 1;
+                return;         
+            end
+        end
+        
+        if ~scalararg1
+            [rows columns] = size(arg1);
+            if rows ~= arg4 | columns ~= arg5 
+                errorcode = 3;
+                return;
+            end     
+        elseif ~scalararg2
+            [rows columns] = size(arg2);
+            if rows ~= arg4 | columns ~= arg5 
+                errorcode = 3;
+                return;
+            end
+        elseif ~scalararg3
+            [rows columns] = size(arg3);
+            if rows ~= arg4 | columns ~= arg5 
+                errorcode = 3;
+                return;
+            end     
+        else
+            if (arg4 < 0 | arg5 < 0 | arg4 ~= round(arg4) | arg5 ~= round(arg5)),
+                errorcode = 4;
+                return;
+            end 
+            rows    = arg4;
+            columns = arg5;
+        end
+    end 
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/sample.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function x = sample(p, n)
+% SAMPLE    Sample from categorical distribution.
+% Returns a row vector of integers, sampled according to the probability
+% distribution p.
+% Uses the stick-breaking algorithm.
+% Much faster algorithms are also possible.
+
+if nargin < 2
+  n = 1;
+end
+
+cdf = cumsum(p(:));
+for i = 1:n
+  x(i) = sum(cdf < rand) + 1;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/sample_discrete.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+function M = sample_discrete(prob, r, c)
+% SAMPLE_DISCRETE Like the built in 'rand', except we draw from a non-uniform discrete distrib.
+% M = sample_discrete(prob, r, c)
+%
+% Example: sample_discrete([0.8 0.2], 1, 10) generates a row vector of 10 random integers from {1,2},
+% where the prob. of being 1 is 0.8 and the prob of being 2 is 0.2.
+
+n = length(prob);
+
+if nargin == 1
+  r = 1; c = 1;
+elseif nargin == 2
+  c == r;
+end
+
+R = rand(r, c);
+M = ones(r, c);
+cumprob = cumsum(prob(:));
+
+if n < r*c
+  for i = 1:n-1
+    M = M + (R > cumprob(i));
+  end
+else
+  % loop over the smaller index - can be much faster if length(prob) >> r*c
+  cumprob2 = cumprob(1:end-1);
+  for i=1:r
+    for j=1:c
+      M(i,j) = sum(R(i,j) > cumprob2)+1;
+    end
+  end
+end
+
+
+% Slower, even though vectorized
+%cumprob = reshape(cumsum([0 prob(1:end-1)]), [1 1 n]);
+%M = sum(R(:,:,ones(n,1)) > cumprob(ones(r,1),ones(c,1),:), 3);
+
+% convert using a binning algorithm
+%M=bindex(R,cumprob);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/sample_gaussian.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function M = sample_gaussian(mu, Sigma, N)
+% SAMPLE_GAUSSIAN Draw N random row vectors from a Gaussian distribution
+% samples = sample_gaussian(mean, cov, N)
+
+if nargin==2
+  N = 1;
+end
+
+% If Y = CX, Var(Y) = C Var(X) C'.
+% So if Var(X)=I, and we want Var(Y)=Sigma, we need to find C. s.t. Sigma = C C'.
+% Since Sigma is psd, we have Sigma = U D U' = (U D^0.5) (D'^0.5 U').
+
+mu = mu(:);
+n=length(mu);
+[U,D,V] = svd(Sigma);
+M = randn(n,N);
+M = (U*sqrt(D))*M + mu*ones(1,N); % transform each column
+M = M';
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/standardize.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function [S, mu, sigma2] = standardize(M, mu, sigma2)
+% function S = standardize(M, mu, sigma2)
+% Make each column of M be zero mean, std 1.
+% Thus each row is scaled separately.
+%
+% If mu, sigma2 are omitted, they are computed from M
+
+M = double(M);
+if nargin < 2
+  mu = mean(M,2);
+  sigma2 = std(M,0,2);
+  sigma2 = sigma2 + eps*(sigma2==0);
+end
+
+[nrows ncols] = size(M);
+S = M - repmat(mu(:), [1 ncols]);
+S = S ./ repmat(sigma2, [1 ncols]);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/student_t_logprob.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function L = log_student_pdf(X, mu, lambda, alpha)
+% LOG_STUDENT_PDF Evaluate the log of the multivariate student-t distribution at a point
+% L = log_student_pdf(X, mu, lambda, alpha)
+%
+% Each column of X is evaluated.
+% See Bernardo and Smith p435.
+
+k = length(mu);
+assert(size(X,1) == k);
+[k N] = size(X);
+logc = gammaln(0.5*(alpha+k)) - gammaln(0.5*alpha) - (k/2)*log(alpha*pi) + 0.5*log(det(lambda));
+middle = (1 + (1/alpha)*(X-mu)'*lambda*(X-mu)); % scalar version
+L = logc - ((alpha+k)/2)*log(middle);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/student_t_prob.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function p = student_t_pdf(X, mu, lambda, alpha)
+% STUDENT_T_PDF Evaluate the multivariate student-t distribution at a point
+% p = student_t_pdf(X, mu, lambda, alpha)
+%
+% Each column of X is evaluated.
+% See Bernardo and Smith p435.
+
+k = length(mu);
+assert(size(X,1) == k);
+[k N] = size(X);
+numer = gamma(0.5*(alpha+k));
+denom = gamma(0.5*alpha) * (alpha*pi)^(k/2);
+c = (numer/denom) * det(lambda)^(0.5);
+p = c*(1 + (1/alpha)*(X-mu)'*lambda*(X-mu))^(-(alpha+k)/2); % scalar version
+%m = repmat(mu(:), 1, N);
+%exponent = sum((X-m)'*lambda*(X-m), 2); % column vector
+%p = c*(1 + (1/alpha)*exponent).^(-(alpha+k)/2);
+
+keyboard
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/test_dir.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+% # of sample points
+n_samples = 1000;
+
+p = ones(3,1)/3;
+
+% Low Entropy
+alpha = 0.5*p;
+
+% High Entropy
+%alpha = 10*p;
+
+% draw n_samples random points from the 3-d dirichlet(alpha),
+% and plot the results
+points = zeros(3,n_samples);
+for i = 1:n_samples
+    points(:,i) = dirichletrnd(alpha);
+end
+
+scatter3(points(1,:)', points(2,:)', points(3,:)', 'r', '.', 'filled');
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/unidrndKPM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function R = unidrndKPM(min, max, nr, nc)
+
+if nargin < 3
+  nr = 1; nc = 1;
+end
+
+R = unidrnd(max-min+1, nr, nc) + (min-1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/unif_discrete_sample.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function r = unif_discrete_sample(n, nrows, ncols)
+% UNIF_DISCRETE_SAMPLE Generate random numbers uniformly from {1,2,..,n}
+% function r = unif_discrete_sample(n, nrows, ncols)
+% Same as unidrnd in the stats toolbox.
+
+r = ceil(n .* rand(nrows,ncols));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMstats/weightedRegression.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+function [a, b, error] = weightedRegression(x, z, w)
+% [a , b, error] = fitRegression(x, z, w);
+% % Weighted scalar linear regression
+%
+% Find a,b to minimize
+% error = sum(w * |z - (a*x + b)|^2) 
+% and x(i) is a scalar
+
+if nargin < 3, w = ones(1,length(x)); end
+
+w = w(:)';
+x = x(:)';
+z = z(:)';
+
+W = sum(w);
+Y = sum(w .* z);
+YY = sum(w .* z .* z);
+YTY = sum(w .* z .* z);
+X = sum(w .* x);
+XX = sum(w .* x .* x);
+XY = sum(w .* x .* z);
+
+[b, a] = clg_Mstep_simple(W, Y, YY, YTY, X, XX, XY);
+error = sum(w .* (z - (a*x + b)).^2 );
+
+if 0
+  % demo
+  seed = 1;
+  rand('state', seed);   randn('state', seed);
+  x = -10:10;
+  N = length(x);
+  noise = randn(1,N);
+  aTrue = rand(1,1);
+  bTrue = rand(1,1);
+  z = aTrue*x + bTrue + noise;
+  
+  w = ones(1,N);
+  [a, b, err] = weightedRegression(x, z, w);
+  
+  b2=regress(z(:), [x(:) ones(N,1)]);
+  assert(approxeq(b,b2(2)))
+  assert(approxeq(a,b2(1)))
+
+  % Make sure we go through x(15) perfectly
+  w(15) = 1000;
+  [aW, bW, errW] = weightedRegression(x, z, w);
+
+  figure;
+  plot(x, z, 'ro')
+  hold on
+  plot(x, a*x+b, 'bx-')
+  plot(x, aW*x+bW, 'gs-')
+  title(sprintf('a=%5.2f, aHat=%5.2f, aWHat=%5.3f, b=%5.2f, bHat=%5.2f, bWHat=%5.3f, err=%5.3f, errW=%5.3f', ...
+		aTrue, a, aW, bTrue, b, bW, err, errW))
+  legend('truth', 'ls', 'wls')
+  
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,176 @@
+/README.txt/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/approx_unique.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/approxeq.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/argmax.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/argmin.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/asdemo.html/1.1.1.1/Wed Mar 30 19:59:00 2005//
+/asdemo.m/1.1.1.1/Sun Mar 27 02:51:24 2005//
+/asort.m/1.1.1.1/Fri May 13 20:52:22 2005//
+/assert.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/assignEdgeNums.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/assign_cols.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/axis_pct.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/bipartiteMatchingDemo.m/1.1.1.1/Mon May  9 16:47:32 2005//
+/bipartiteMatchingDemoPlot.m/1.1.1.1/Mon May  9 04:45:10 2005//
+/bipartiteMatchingHungarian.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/bipartiteMatchingIntProg.m/1.1.1.1/Mon May  9 05:25:10 2005//
+/block.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/cell2matPad.m/1.1.1.1/Tue Jun 28 01:30:44 2005//
+/cell2num.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/centeringMatrix.m/1.1.1.1/Sun May  8 22:48:48 2005//
+/checkpsd.m/1.1.1.1/Fri Feb  7 02:25:30 2003//
+/chi2inv.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/choose.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/collapse_mog.m/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/colmult.c/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/colmult.mexglx/1.1.1.1/Tue Apr 26 02:30:30 2005//
+/computeROC.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/compute_counts.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/conf2mahal.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/cross_entropy.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/dirKPM.m/1.1.1.1/Fri May 13 20:52:22 2005//
+/div.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/draw_circle.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/draw_ellipse.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/draw_ellipse_axes.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/em_converged.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/entropy.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/exportfig.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/extend_domain_table.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/factorial.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/filepartsLast.m/1.1.1.1/Mon May 30 22:08:06 2005//
+/find_equiv_posns.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/fullfileKPM.m/1.1.1.1/Sat Aug 27 01:08:50 2005//
+/genpathKPM.m/1.1.1.1/Wed May 25 19:11:42 2005//
+/hash_add.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/hash_del.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/hash_lookup.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/hsvKPM.m/1.1.1.1/Mon May  2 20:19:00 2005//
+/hungarian.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/image_rgb.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/imresizeAspect.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/ind2subv.c/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/ind2subv.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/initFigures.m/1.1.1.1/Wed Jun  1 04:49:22 2005//
+/installC_KPMtools.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/is_psd.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/is_stochastic.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/isemptycell.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/isposdef.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/isscalar.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/isvector.m/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/junk.c/1.1.1.1/Tue Apr 26 02:30:32 2005//
+/loadcell.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/logb.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/logdet.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/logsum.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/logsum_simple.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/logsum_test.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/logsumexp.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/logsumexpv.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/mahal2conf.m/1.1.1.1/Wed Apr 27 17:58:32 2005//
+/marg_table.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/marginalize_table.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/matprint.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/max_mult.c/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/max_mult.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/mexutil.c/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/mexutil.h/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/mk_multi_index.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/mk_stochastic.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/mkdirKPM.m/1.1.1.1/Mon May  9 22:20:22 2005//
+/montageKPM.m/1.1.1.1/Wed Jun  1 19:39:54 2005//
+/montageKPM2.m/1.1.1.1/Wed Jul  6 19:32:54 2005//
+/montageKPM3.m/1.1.1.1/Tue Jun 28 01:35:44 2005//
+/mult_by_table.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/myintersect.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/myismember.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/myones.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/myplot.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/myrand.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/myrepmat.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/myreshape.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/mysetdiff.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/mysize.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/mysubset.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/mysymsetdiff.m/1.1.1.1/Tue Apr 26 02:30:34 2005//
+/myunion.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/nchoose2.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/ncols.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/nonmaxsup.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/normalise.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/normaliseC.c/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/normaliseC.dll/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/normalize.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/nrows.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/num2strcell.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/optimalMatching.m/1.1.1.1/Mon May  9 22:20:22 2005//
+/optimalMatchingTest.m/1.1.1.1/Mon May  9 22:20:22 2005//
+/partitionData.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/partition_matrix_vec.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/pca_kpm.m/1.1.1.1/Tue Sep 13 05:18:28 2005//
+/pca_netlab.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/pick.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/plotBox.m/1.1.1.1/Mon May 30 06:01:56 2005//
+/plotColors.m/1.1.1.1/Thu May 26 01:31:22 2005//
+/plotROC.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/plotROCkpm.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/plot_axis_thru_origin.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/plot_ellipse.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/plot_matrix.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/plot_polygon.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/plotcov2.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/plotcov2New.m/1.1.1.1/Mon Jul 11 19:07:28 2005//
+/plotcov3.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/plotgauss1d.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/plotgauss2d.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/plotgauss2d_old.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/polygon_area.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/polygon_centroid.m/1.1.1.1/Tue Apr 26 02:30:36 2005//
+/polygon_intersect.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/previewfig.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/process_options.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/rand_psd.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/rectintC.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/rectintLoopC.c/1.1.1.1/Sun Jun  5 18:46:40 2005//
+/rectintLoopC.dll/1.1.1.1/Sun Jun  5 18:46:40 2005//
+/rectintLoopC.mexglx/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/rectintSparse.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/rectintSparseC.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/rectintSparseLoopC.c/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/rectintSparseLoopC.dll/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/repmatC.c/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/repmatC.dll/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/repmatC.mexglx/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/rgb2grayKPM.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/rnd_partition.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/rotate_xlabel.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/safeStr.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/sampleUniformInts.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/sample_discrete.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/set_xtick_label.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/set_xtick_label_demo.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/setdiag.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/softeye.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/sort_evec.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/splitLongSeqIntoManyShort.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/sprintf_intvec.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/sqdist.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/strmatch_multi.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/strmatch_substr.m/1.1.1.1/Tue Apr 26 02:30:38 2005//
+/strsplit.m/1.1.1.1/Tue May  3 19:01:46 2005//
+/subplot2.m/1.1.1.1/Tue Apr 26 02:30:40 2005//
+/subplot3.m/1.1.1.1/Tue Apr 26 02:30:40 2005//
+/subsets.m/1.1.1.1/Tue Apr 26 02:30:40 2005//
+/subsets1.m/1.1.1.1/Mon May  9 22:20:22 2005//
+/subsetsFixedSize.m/1.1.1.1/Mon May  9 02:55:36 2005//
+/subv2ind.c/1.1.1.1/Tue Apr 26 02:30:40 2005//
+/subv2ind.m/1.1.1.1/Tue Apr 26 02:30:40 2005//
+/sumv.m/1.1.1.1/Tue Apr 26 02:30:40 2005//
+/suptitle.m/1.1.1.1/Tue Apr 26 02:30:40 2005//
+/unaryEncoding.m/1.1.1.1/Tue Apr 26 02:30:40 2005//
+/wrap.m/1.1.1.1/Tue Apr 26 02:30:40 2005//
+/xticklabel_rotate90.m/1.1.1.1/Tue Apr 26 02:30:40 2005//
+/zipload.m/1.1.1.1/Tue Apr 26 02:30:40 2005//
+/zipsave.m/1.1.1.1/Tue Apr 26 02:30:40 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+FullBNT/KPMtools
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:nsaunier@bnt.cvs.sourceforge.net:/cvsroot/bnt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/README.txt	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+KPMtools is a directory of miscellaneous matlab functions written by
+Kevin Patrick Murphy and various other people (see individual file headers).
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/approx_unique.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,41 @@
+function [B, keep] = approx_unique(A, thresh, flag)
+% APPROX_UNIQUE Return elements of A that differ from the rest by less than thresh
+% B = approx_unique(A, thresh)
+% B = approx_unique(A, thresh, 'rows')
+
+keep = [];
+
+if nargin < 3 | isempty(flag)
+  A = sort(A)
+  B = A(1);
+  for i=2:length(A)
+    if ~approxeq(A(i), A(i-1), thresh)
+      B = [B A(i)];
+      keep = [keep i];
+    end
+  end
+else
+%   A = sortrows(A);
+%   B = A(1,:);
+%   for i=2:size(A,1)
+%     if ~approxeq(A(i,:), A(i-1,:), thresh)
+%       B = [B; A(i,:)];
+%       keep = [keep i];
+%     end
+%   end
+  B = [];
+  for i=1:size(A,1)
+    duplicate = 0;
+    for j=i+1:size(A,1)
+      if approxeq(A(i,:), A(j,:), thresh)
+	duplicate = 1;
+	break;
+      end
+    end
+    if ~duplicate    
+      B = [B; A(i,:)];
+      keep = [keep i];
+    end
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/approxeq.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function p = approxeq(a, b, tol, rel)
+% APPROXEQ Are a and b approximately equal (to within a specified tolerance)?
+% p = approxeq(a, b, thresh)
+% 'tol' defaults to 1e-3.
+% p(i) = 1 iff abs(a(i) - b(i)) < thresh
+%
+% p = approxeq(a, b, thresh, 1)
+% p(i) = 1 iff abs(a(i)-b(i))/abs(a(i)) < thresh
+
+if nargin < 3, tol = 1e-2; end
+if nargin < 4, rel = 0; end
+
+a = a(:);
+b = b(:);
+d = abs(a-b);
+if rel
+  p = ~any( (d ./ (abs(a)+eps)) > tol);
+else
+  p = ~any(d > tol);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/argmax.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function indices = argmax(v)
+% ARGMAX Return as a subscript vector the location of the largest element of a multidimensional array v.
+% indices = argmax(v)
+%
+% Returns the first maximum in the case of ties.
+% Example:
+% X = [2 8 4; 7 3 9];
+% argmax(X) = [2 3], i.e., row 2 column 3
+
+[m i] = max(v(:));
+indices = ind2subv(mysize(v), i);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/argmin.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function indices = argmin(v)
+% ARGMIN Return as a subscript vector the location of the smallest element of a multidimensional array v.
+% indices = argmin(v)
+%
+% Returns the first minimum in the case of ties.
+% Example:
+% X = [2 8 4; 7 3 9];
+% argmin(X) = [1 1], i.e., row 1 column 1
+
+[m i] = min(v(:));
+indices = ind2subv(mysize(v), i);
+%indices = ind2subv(size(v), i);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/asdemo.html	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,690 @@
+<html xmlns:v="urn:schemas-microsoft-com:vml"
+xmlns:o="urn:schemas-microsoft-com:office:office"
+xmlns:w="urn:schemas-microsoft-com:office:word"
+xmlns:st1="urn:schemas-microsoft-com:office:smarttags"
+xmlns:mwsh="http://www.mathworks.com/namespace/mcode/v1/syntaxhighlight.dtd"
+xmlns="http://www.w3.org/TR/REC-html40">
+
+<head>
+<meta http-equiv=Content-Type content="text/html; charset=utf-8">
+<meta name=ProgId content=Word.Document>
+<meta name=Generator content="Microsoft Word 10">
+<meta name=Originator content="Microsoft Word 10">
+<link rel=File-List href="asdemo_files/filelist.xml">
+<title>asdemo</title>
+<o:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags"
+ name="time"/>
+<o:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags"
+ name="date"/>
+<o:SmartTagType namespaceuri="urn:schemas-microsoft-com:office:smarttags"
+ name="place"/>
+<!--[if gte mso 9]><xml>
+ <o:DocumentProperties>
+  <o:Author>Caroline Schwarz</o:Author>
+  <o:Template>Normal</o:Template>
+  <o:LastAuthor>us</o:LastAuthor>
+  <o:Revision>33</o:Revision>
+  <o:TotalTime>0</o:TotalTime>
+  <o:Created>2005-03-26T16:20:00Z</o:Created>
+  <o:LastSaved>2005-03-30T09:58:00Z</o:LastSaved>
+  <o:Pages>1</o:Pages>
+  <o:Words>1062</o:Words>
+  <o:Characters>6055</o:Characters>
+  <o:Company>office</o:Company>
+  <o:Lines>50</o:Lines>
+  <o:Paragraphs>14</o:Paragraphs>
+  <o:CharactersWithSpaces>7103</o:CharactersWithSpaces>
+  <o:Version>10.3501</o:Version>
+ </o:DocumentProperties>
+ <o:OfficeDocumentSettings>
+  <o:RelyOnVML/>
+  <o:AllowPNG/>
+  <o:TargetScreenSize>1280x1024</o:TargetScreenSize>
+ </o:OfficeDocumentSettings>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <w:WordDocument>
+  <w:SpellingState>Clean</w:SpellingState>
+  <w:GrammarState>Clean</w:GrammarState>
+  <w:Compatibility>
+   <w:UseFELayout/>
+  </w:Compatibility>
+  <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
+ </w:WordDocument>
+</xml><![endif]--><!--[if !mso]><object
+ classid="clsid:38481807-CA0E-42D2-BF39-B33AF135CC4D" id=ieooui></object>
+<style>
+st1\:*{behavior:url(#ieooui) }
+</style>
+<![endif]-->
+<style>
+<!--p
+	{max-width: 600px;
+	width:expression(document.body.clientWidth > 620 ? "600px": "auto" );}
+h1
+	{max-width: 600px;
+	width:expression(document.body.clientWidth > 620 ? "600px": "auto" );}
+h2
+	{max-width: 600px;
+	width:expression(document.body.clientWidth > 620 ? "600px": "auto" );}
+div
+	{max-width: 600px;
+	width:expression(document.body.clientWidth > 620 ? "600px": "auto" );}
+
+ /* Font Definitions */
+ @font-face
+	{font-family:"MS Mincho";
+	panose-1:2 2 6 9 4 2 5 8 3 4;
+	mso-font-alt:"ï¼­ï¼³ 明æœ";
+	mso-font-charset:128;
+	mso-generic-font-family:modern;
+	mso-font-pitch:fixed;
+	mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
+@font-face
+	{font-family:"\@MS Mincho";
+	panose-1:2 2 6 9 4 2 5 8 3 4;
+	mso-font-charset:128;
+	mso-generic-font-family:modern;
+	mso-font-pitch:fixed;
+	mso-font-signature:-1610612033 1757936891 16 0 131231 0;}
+ /* Style Definitions */
+ p.MsoNormal, li.MsoNormal, div.MsoNormal
+	{mso-style-parent:"";
+	margin:0cm;
+	margin-bottom:.0001pt;
+	mso-pagination:widow-orphan;
+	font-size:10.0pt;
+	font-family:Arial;
+	mso-fareast-font-family:"Times New Roman";
+	mso-believe-normal-left:yes;}
+h1
+	{mso-margin-top-alt:auto;
+	margin-right:0cm;
+	mso-margin-bottom-alt:auto;
+	margin-left:0cm;
+	mso-pagination:widow-orphan;
+	mso-outline-level:1;
+	font-size:24.0pt;
+	font-family:Arial;
+	mso-fareast-font-family:"MS Mincho";
+	color:#990000;
+	font-weight:bold;}
+h2
+	{mso-margin-top-alt:auto;
+	margin-right:0cm;
+	mso-margin-bottom-alt:auto;
+	margin-left:0cm;
+	mso-pagination:widow-orphan;
+	mso-outline-level:2;
+	font-size:13.5pt;
+	font-family:Arial;
+	mso-fareast-font-family:"MS Mincho";
+	color:#990000;
+	font-weight:bold;}
+p
+	{mso-margin-top-alt:auto;
+	margin-right:0cm;
+	mso-margin-bottom-alt:auto;
+	margin-left:0cm;
+	mso-pagination:widow-orphan;
+	font-size:10.0pt;
+	font-family:Arial;
+	mso-fareast-font-family:"Times New Roman";}
+pre
+	{margin:0cm;
+	margin-bottom:.0001pt;
+	mso-pagination:widow-orphan;
+	tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt;
+	font-size:10.0pt;
+	font-family:"Courier New";
+	mso-fareast-font-family:"Times New Roman";}
+p.footer, li.footer, div.footer
+	{mso-style-name:footer;
+	mso-margin-top-alt:auto;
+	margin-right:0cm;
+	mso-margin-bottom-alt:auto;
+	margin-left:0cm;
+	text-align:right;
+	mso-pagination:widow-orphan;
+	font-size:7.5pt;
+	font-family:Arial;
+	mso-fareast-font-family:"Times New Roman";
+	color:gray;
+	font-style:italic;}
+span.keyword
+	{mso-style-name:keyword;
+	color:blue;}
+span.comment
+	{mso-style-name:comment;
+	color:forestgreen;}
+span.string
+	{mso-style-name:string;
+	color:#A020F0;}
+span.untermstring
+	{mso-style-name:untermstring;
+	color:#B20000;}
+span.syscmd
+	{mso-style-name:syscmd;
+	color:#B28C00;}
+span.SpellE
+	{mso-style-name:"";
+	mso-spl-e:yes;}
+span.GramE
+	{mso-style-name:"";
+	mso-gram-e:yes;}
+@page Section1
+	{size:612.0pt 792.0pt;
+	margin:72.0pt 90.0pt 72.0pt 90.0pt;
+	mso-header-margin:36.0pt;
+	mso-footer-margin:36.0pt;
+	mso-paper-source:0;}
+div.Section1
+	{page:Section1;}
+-->
+</style>
+<!--[if gte mso 10]>
+<style>
+ /* Style Definitions */
+ table.MsoNormalTable
+	{mso-style-name:"Table Normal";
+	mso-tstyle-rowband-size:0;
+	mso-tstyle-colband-size:0;
+	mso-style-noshow:yes;
+	mso-style-parent:"";
+	mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
+	mso-para-margin:0cm;
+	mso-para-margin-bottom:.0001pt;
+	mso-pagination:widow-orphan;
+	font-size:10.0pt;
+	font-family:"Times New Roman";}
+</style>
+<![endif]--><![if mso 9]>
+<style>
+p.MsoNormal
+	{margin-left:7.5pt;}
+</style>
+<![endif]><!--
+This HTML is auto-generated from an M-file.
+To make changes, update the M-file and republish this document.
+      -->
+<meta name=date content=2005-03-26>
+<meta name=m-file content=asdemo>
+<!--[if gte mso 9]><xml>
+ <o:shapedefaults v:ext="edit" spidmax="5122"/>
+</xml><![endif]--><!--[if gte mso 9]><xml>
+ <o:shapelayout v:ext="edit">
+  <o:idmap v:ext="edit" data="1"/>
+ </o:shapelayout></xml><![endif]-->
+</head>
+
+<body bgcolor=white lang=EN-US style='tab-interval:36.0pt;margin-left:7.5pt;
+margin-top:7.5pt;margin-right:7.5pt;margin-bottom:7.5pt'>
+
+<div class=Section1><pre style='margin-left:22.5pt'><span class=comment>% <b
+style='mso-bidi-font-weight:normal'>ASORT</b></span></pre><pre
+style='margin-left:22.5pt'><span class=comment>% a pedestrian <b
+style='mso-bidi-font-weight:normal'>NUMERICAL SORTER</b> of <b
+style='mso-bidi-font-weight:normal'>ALPHANUMERIC</b> data</span></pre><pre
+style='margin-left:22.5pt'><o:p>&nbsp;</o:p></pre><pre style='margin-left:22.5pt'><span
+class=comment>% - create some data</span></pre><pre style='margin-left:22.5pt'><b
+style='mso-bidi-font-weight:normal'><span style='mso-tab-count:2'>          </span>d = {<o:p></o:p></b></pre><pre
+style='margin-left:22.5pt'><span class=comment>%<span style='mso-tab-count:
+2'>         </span>strings with one valid alphanumeric number</span></pre><pre
+style='margin-left:22.5pt'><span class=comment>%<span style='mso-tab-count:
+2'>         </span>sorted <b style='mso-bidi-font-weight:normal'>numerically</b></span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'-<span class=SpellE><span class=GramE>inf</span></span>'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'<span class=GramE>x-3.2e4y</span>'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'<span class=GramE>f-1.4</span>'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'-.1'</span></pre><pre style='margin-left:22.5pt'><span
+style='mso-tab-count:3'>                  </span><span class=string>'+ <span
+class=GramE>.1d-2</span>'</span></pre><pre style='margin-left:22.5pt'><span
+style='mso-tab-count:3'>                  </span><span class=string>'.1'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'f.1'</span></pre><pre style='margin-left:22.5pt'><span
+style='mso-tab-count:3'>                  </span><span class=string>'f -+1.4'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'f.2'</span></pre><pre style='margin-left:22.5pt'><span
+style='mso-tab-count:3'>                  </span><span class=string>'f.3'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'f.10'</span></pre><pre style='margin-left:22.5pt'><span
+style='mso-tab-count:3'>                  </span><span class=string>'f.11'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'+<span class=SpellE>inf</span>'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=GramE><span class=string>' -</span></span><span class=SpellE><span
+class=string>nan</span></span><span class=string>'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'+ <span class=SpellE><span class=GramE>nan</span></span>'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'<span class=SpellE><span class=GramE>nan</span></span>'</span></pre><pre
+style='margin-left:22.5pt'><span class=comment>%<span style='mso-tab-count:
+2'>         </span>strings with many numbers or invalid/ambiguous numbers</span></pre><pre
+style='margin-left:22.5pt'><span class=comment>%<span style='mso-tab-count:
+2'>         </span>sorted in <span class=SpellE><span class=GramE><b
+style='mso-bidi-font-weight:normal'>ascii</b></span></span><b style='mso-bidi-font-weight:
+normal'> dictionary order</b></span></pre><pre style='margin-left:22.5pt'><span
+style='mso-tab-count:3'>                  </span><span class=GramE><span
+class=string>' <span class=SpellE>nan</span></span></span><span class=string> <span
+class=SpellE>nan</span>'</span></pre><pre style='margin-left:22.5pt'><span
+style='mso-tab-count:3'>                  </span><span class=string>'+ .1e-.2'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'-1 2'</span></pre><pre style='margin-left:22.5pt'><span
+style='mso-tab-count:3'>                  </span><span class=string>'Z12e12ez'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'<span class=SpellE><span class=GramE>inf</span></span> -<span
+class=SpellE>inf</span>'</span></pre><pre style='margin-left:22.5pt'><span
+style='mso-tab-count:3'>                  </span><span class=string>'s.3TT.4'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'z12e12ez'</span></pre><pre style='margin-left:22.5pt'><span
+class=comment>%<span style='mso-tab-count:2'>         </span>strings without numbers</span></pre><pre
+style='margin-left:22.5pt'><span class=comment>%<span style='mso-tab-count:
+2'>         </span>sorted in <span class=SpellE><span class=GramE><b
+style='mso-bidi-font-weight:normal'>ascii</b></span></span><b style='mso-bidi-font-weight:
+normal'> dictionary order</b></span></pre><pre style='margin-left:22.5pt'><span
+style='mso-tab-count:3'>                  </span><span class=string>' . .. '</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'.'</span></pre><pre style='margin-left:22.5pt'><span
+style='mso-tab-count:3'>                  </span><span class=string>'...'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=GramE><span class=string>'.b a.'</span></span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'<span class=GramE>a</span> string'</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:3'>                  </span><span
+class=string>'a. .b'</span></pre><pre style='margin-left:22.5pt'><b
+style='mso-bidi-font-weight:normal'><span style='mso-tab-count:2'>          </span>};<o:p></o:p></b></pre><pre
+style='margin-left:22.5pt'><span class=comment>%<span style='mso-spacerun:yes'>   </span>... and scramble it...</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:2'>          </span><span
+class=GramE>rand(</span><span class=string>'seed'</span>,10);</pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:2'>          </span>d=<span
+class=GramE>d(</span><span class=SpellE>randperm</span>(<span class=SpellE>numel</span>(d)));</pre><pre
+style='margin-left:22.5pt'><o:p>&nbsp;</o:p></pre><pre style='margin-left:22.5pt'><span
+class=comment>% - run <b style='mso-bidi-font-weight:normal'>ASORT</b> with<o:p></o:p></span></pre><pre
+style='margin-left:22.5pt'><span class=comment>%<span style='mso-spacerun:yes'>   </span><b
+style='mso-bidi-font-weight:normal'>verbose output</b>:<span style='mso-tab-count:
+2'>              </span>&lt;-v&gt;</span></pre><pre style='margin-left:22.5pt'><span
+class=comment>%<span style='mso-spacerun:yes'>   </span><span class=GramE><b
+style='mso-bidi-font-weight:normal'>keep</b></span><b style='mso-bidi-font-weight:
+normal'> additional results</b>:<span style='mso-tab-count:1'>     </span>&lt;-d&gt;</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:2'>          </span>o=<span
+class=SpellE><span class=GramE>asort</span></span><span class=GramE>(</span>d,<span
+class=string>'-v'</span>,<span class=string>'-d'</span>);</pre><pre
+style='margin-left:22.5pt'><span class=comment>% - or</span></pre><pre
+style='margin-left:22.5pt'><span class=comment>%<span style='mso-tab-count:
+2'>         </span>p=<span class=SpellE><span class=GramE>asort</span></span><span
+class=GramE>(</span>char(d),</span><span class=string>'-v'</span>,<span
+class=string>'-d'</span>);</pre><pre style='margin-left:7.5pt'><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'INPUT'<span style='mso-spacerun:yes'>       </span>'ASCII SORT'<span style='mso-spacerun:yes'>    </span>'NUM SORT'<span style='mso-spacerun:yes'>             </span>'NUM READ'<span style='mso-spacerun:yes'>         </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'...'<span style='mso-spacerun:yes'>         </span><span
+class=SpellE><span class=GramE>'</span></span><span class=GramE> -</span><span
+class=SpellE>nan</span>'<span style='mso-spacerun:yes'>         </span>'--- NUMERICAL'<span style='mso-spacerun:yes'>        </span>'--- NUMBERS'<span style='mso-spacerun:yes'>      </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'+ .1e-.2'<span style='mso-spacerun:yes'>    </span><span
+class=GramE>' .</span> .. '<span style='mso-spacerun:yes'>        </span>'-<span
+class=SpellE><span class=GramE>inf</span></span>'<span style='mso-spacerun:yes'>         </span><span style='mso-spacerun:yes'>        </span>[<span style='mso-spacerun:yes'>             </span>-<span
+class=SpellE>Inf</span>]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'.1'<span style='mso-spacerun:yes'>          </span>' <span
+class=SpellE>nan</span> <span class=SpellE>nan</span>'<span style='mso-spacerun:yes'>      </span>'x-3.2e4y'<span style='mso-spacerun:yes'>             </span>[<span style='mso-spacerun:yes'>           </span>-32000]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'.b a.'<span style='mso-spacerun:yes'>       </span>'+ .1d-2'<span style='mso-spacerun:yes'>       </span>'f-1.4'<span style='mso-spacerun:yes'>                </span>[<span style='mso-spacerun:yes'>             </span>-1.4]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'-<span
+class=SpellE>inf</span>'<span style='mso-spacerun:yes'>        </span>'+ .1e-.2'<span style='mso-spacerun:yes'>      </span>'-.1'<span style='mso-spacerun:yes'>                  </span>[<span style='mso-spacerun:yes'>             </span>-0.1]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'f.1'<span style='mso-spacerun:yes'>         </span>'+ <span
+class=SpellE><span class=GramE>nan</span></span>'<span style='mso-spacerun:yes'>         </span>'+ .1d-2'<span style='mso-spacerun:yes'>              </span>[<span style='mso-spacerun:yes'>            </span>0.001]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span class=GramE>' -</span><span
+class=SpellE>nan</span>'<span style='mso-spacerun:yes'>       </span>'+<span
+class=SpellE>inf</span>'<span style='mso-spacerun:yes'>          </span>'.1'<span style='mso-spacerun:yes'>                   </span>[<span style='mso-spacerun:yes'>              </span>0.1]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'-1 2'<span style='mso-spacerun:yes'>        </span>'-.1'<span style='mso-spacerun:yes'>           </span>'f.1'<span style='mso-spacerun:yes'>                  </span>[<span style='mso-spacerun:yes'>                </span>1]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'<span
+class=SpellE><span class=GramE>nan</span></span>'<span style='mso-spacerun:yes'>         </span>'-1 2'<span style='mso-spacerun:yes'>          </span>'f -+1.4'<span style='mso-spacerun:yes'>              </span>[<span style='mso-spacerun:yes'>              </span>1.4]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'<span
+class=GramE>a</span> string'<span style='mso-spacerun:yes'>    </span>'-<span
+class=SpellE>inf</span>'<span style='mso-spacerun:yes'>          </span>'f.2'<span style='mso-spacerun:yes'>                  </span>[<span style='mso-spacerun:yes'>                </span>2]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span class=GramE>'f.3'<span style='mso-spacerun:yes'>         </span>'.'</span><span style='mso-spacerun:yes'>             </span>'f.3'<span style='mso-spacerun:yes'>                  </span>[<span style='mso-spacerun:yes'>                </span>3]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'+ <span
+class=GramE>.1d-2</span>'<span style='mso-spacerun:yes'>     </span>'...'<span style='mso-spacerun:yes'>           </span>'f.10'<span style='mso-spacerun:yes'>   </span><span style='mso-spacerun:yes'>              </span>[<span style='mso-spacerun:yes'>               </span>10]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'a. .b'<span style='mso-spacerun:yes'>       </span>'.1'<span style='mso-spacerun:yes'>            </span>'f.11'<span style='mso-spacerun:yes'>                 </span>[<span style='mso-spacerun:yes'>     </span><span style='mso-spacerun:yes'>          </span>11]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'s.3TT.4'<span style='mso-spacerun:yes'>     </span>'.b a.'<span style='mso-spacerun:yes'>     </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>   </span>'+<span
+class=SpellE>inf</span>'<span style='mso-spacerun:yes'>                 </span>[<span style='mso-spacerun:yes'>              </span><span
+class=SpellE><span class=GramE>Inf</span></span>]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span>'+<span
+class=SpellE>inf</span>'<span style='mso-spacerun:yes'>        </span>'Z12e12ez'<span style='mso-spacerun:yes'>      </span>' -<span
+class=SpellE>nan</span>'<span style='mso-spacerun:yes'>                </span>[<span style='mso-spacerun:yes'>          </span><span style='mso-spacerun:yes'>    </span></span></i><st1:place><span
+ class=SpellE><i><span style='color:gray'>NaN</span></i></span></st1:place><i><span
+style='color:gray'>]<o:p></o:p></span></i></pre><pre><i><span style='color:
+gray'> <span style='mso-spacerun:yes'>   </span><span class=GramE>' <span
+class=SpellE>nan</span></span> <span class=SpellE>nan</span>'<span style='mso-spacerun:yes'>    </span>'a string'<span style='mso-spacerun:yes'>      </span>'+ <span
+class=SpellE>nan</span>'<span style='mso-spacerun:yes'>                </span>[<span style='mso-spacerun:yes'>              </span></span></i><st1:place><span
+ class=SpellE><i><span style='color:gray'>NaN</span></i></span></st1:place><i><span
+style='color:gray'>]<o:p></o:p></span></i></pre><pre><i><span style='color:
+gray'><span style='mso-spacerun:yes'>    </span>'<span class=GramE>f-1.4</span>'<span style='mso-spacerun:yes'>       </span>'a. .<span
+class=GramE>b</span>'<span style='mso-spacerun:yes'>    </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>    </span>'<span
+class=SpellE>nan</span>'<span style='mso-spacerun:yes'>                  </span>[<span style='mso-spacerun:yes'>              </span></span></i><st1:place><span
+ class=SpellE><i><span style='color:gray'>NaN</span></i></span></st1:place><i><span
+style='color:gray'>]<o:p></o:p></span></i></pre><pre><i><span style='color:
+gray'><span style='mso-spacerun:yes'>    </span>'x-3.2e4y'<span style='mso-spacerun:yes'>    </span>'f -+1.4'<span style='mso-spacerun:yes'>     </span><span style='mso-spacerun:yes'>  </span>'--- ASCII NUMBERS'<span style='mso-spacerun:yes'>    </span>'--- ASCII NUMBERS'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'<span
+class=SpellE><span class=GramE>inf</span></span> -<span class=SpellE>inf</span>'<span style='mso-spacerun:yes'>  </span><span style='mso-spacerun:yes'>  </span>'f-1.4'<span style='mso-spacerun:yes'>         </span>' <span
+class=SpellE>nan</span> <span class=SpellE>nan</span>'<span style='mso-spacerun:yes'>             </span>' <span
+class=SpellE>nan</span> <span class=SpellE>nan</span>'<span style='mso-spacerun:yes'>         </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'+ <span
+class=SpellE><span class=GramE>nan</span></span>'<span style='mso-spacerun:yes'>       </span>'f.1'<span style='mso-spacerun:yes'>           </span>'+ .1e-.2'<span style='mso-spacerun:yes'>             </span>'+ .1e-.2'<span style='mso-spacerun:yes'>         </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'f.2'<span style='mso-spacerun:yes'>         </span>'f.10'<span style='mso-spacerun:yes'>          </span>'-1 2'<span style='mso-spacerun:yes'>                 </span>'-1 2'<span style='mso-spacerun:yes'>             </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'f.11'<span style='mso-spacerun:yes'>  </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>     </span><span
+class=SpellE>'f.11'</span><span style='mso-spacerun:yes'>          </span>'Z12e12ez'<span style='mso-spacerun:yes'>             </span><span
+class=SpellE>'Z12e12ez'</span><span style='mso-spacerun:yes'>         </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'Z12e12ez'<span style='mso-spacerun:yes'>    </span>'f.2'<span style='mso-spacerun:yes'>      </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>    </span>'<span
+class=SpellE>inf</span> -<span class=SpellE>inf</span>'<span style='mso-spacerun:yes'>             </span>'<span
+class=SpellE>inf</span> -<span class=SpellE>inf</span>'<span style='mso-spacerun:yes'>         </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'z12e12ez'<span style='mso-spacerun:yes'>    </span>'f.3'<span style='mso-spacerun:yes'>           </span>'s.3TT.4'<span style='mso-spacerun:yes'>              </span><span
+class=SpellE>'s.3TT.4'</span><span style='mso-spacerun:yes'>          </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'f -+1.4'<span style='mso-spacerun:yes'>     </span>'<span
+class=SpellE>inf</span> -<span class=SpellE>inf</span>'<span style='mso-spacerun:yes'>      </span>'z12e12ez'<span style='mso-spacerun:yes'>             </span><span
+class=SpellE>'z12e12ez'</span><span style='mso-spacerun:yes'>         </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>' . .. '<span style='mso-spacerun:yes'>      </span>'<span
+class=SpellE><span class=GramE>nan</span></span>'<span style='mso-spacerun:yes'>           </span>'--- ASCII STRINGS'<span style='mso-spacerun:yes'>    </span>'--- ASCII STRINGS'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'f.10'<span style='mso-spacerun:yes'>        </span>'s.3TT.4'<span style='mso-spacerun:yes'>       </span><span
+class=GramE>' .</span> .. '<span style='mso-spacerun:yes'>         </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>     </span><span
+class=SpellE>'</span> . .. '<span style='mso-spacerun:yes'>           </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'.'<span style='mso-spacerun:yes'>           </span><span
+class=GramE>'x-3.2e4y'<span style='mso-spacerun:yes'>      </span>'.'</span><span style='mso-spacerun:yes'>                    </span><span
+class=SpellE>'.'</span><span style='mso-spacerun:yes'>                </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'-.1'<span style='mso-spacerun:yes'>     </span><span style='mso-spacerun:yes'>    </span>'z12e12ez'<span style='mso-spacerun:yes'>      </span>'...'<span style='mso-spacerun:yes'>                  </span><span
+class=SpellE>'</span>...'<span style='mso-spacerun:yes'>              </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>           </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span>'.b a.'<span style='mso-spacerun:yes'>                </span>'.b a.'<span style='mso-spacerun:yes'>            </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>   </span><span
+class=GramE>' <span class=SpellE>'</span></span><span style='mso-spacerun:yes'>           </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span>'a string'<span style='mso-spacerun:yes'>             </span>'a string'<span style='mso-spacerun:yes'>         </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>   </span><span
+class=GramE>' <span class=SpellE>'</span></span><span style='mso-spacerun:yes'>           </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span>'a. .b'<span style='mso-spacerun:yes'>                </span>'a. .<span
+class=GramE>b</span>'<span style='mso-spacerun:yes'>            </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre style='margin-left:
+22.5pt'><span class=comment>% - show results</span></pre><pre style='margin-left:
+22.5pt'><span style='mso-tab-count:2'>          </span><span class=GramE>o</span></pre><pre><i><span
+style='color:gray'>o = <o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>          </span><span
+class=GramE>magic</span>: 'ASORT'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>      </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>     </span><span
+class=SpellE><span class=GramE>ver</span></span>: '</span></i><st1:date
+Year="2005" Day="30" Month="3"><i><span style='color:gray'>30-Mar-2005</span></i></st1:date><i><span
+style='color:gray'> </span></i><st1:time Minute="57" Hour="11"><i><span
+ style='color:gray'>11:57:07</span></i></st1:time><i><span style='color:gray'>'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>           </span>time: '30-Mar-2005 11:57:17'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>        </span><span
+class=GramE>runtime</span>: 0.047<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span
+class=SpellE>input_class</span>: 'cell'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span
+class=SpellE>input_msize</span>: [29 1]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span
+class=SpellE>input_bytes</span>: 2038<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span
+class=SpellE>strng_class</span>: 'char'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span
+class=SpellE>strng_msize</span>: [29 8]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span
+class=SpellE>strng_bytes</span>: 464<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>            </span><span
+class=SpellE><span class=GramE>anr</span></span>: {16x1 cell}<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>      </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>     </span><span
+class=SpellE><span class=GramE>snr</span></span>: {7x1 cell}<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>      </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>     </span><span
+class=SpellE><span class=GramE>str</span></span>: {6x1 cell}<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>              </span><span
+class=GramE>c</span>: [29x12 char]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>              </span><span
+class=GramE>t</span>: [29x12 logical]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>              </span><span
+class=GramE>n</span>: [16x12 char]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>  </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>           </span><span
+class=GramE>d</span>: [16x1 double]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre style='margin-left:
+22.5pt'><span style='mso-tab-count:2'>          </span><span class=SpellE>o.anr</span></pre><pre><span
+class=SpellE><span class=GramE><i><span style='color:gray'>ans</span></i></span></span><i><span
+style='color:gray'> = <o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>   </span>'-<span
+class=SpellE><span class=GramE>inf</span></span>'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'<span
+class=GramE>x-3.2e4y</span>'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'<span
+class=GramE>f-1.4</span>'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'-.1'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'+ <span
+class=GramE>.1d-2</span>'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'.1'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'f.1'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'f -+1.4'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'f.2'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'f.3'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'f.10'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'f.11'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span>'+<span
+class=SpellE>inf</span>'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span class=GramE>' -</span><span
+class=SpellE>nan</span>'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>  </span>'+ <span
+class=SpellE><span class=GramE>nan</span></span>'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'<span
+class=SpellE><span class=GramE>nan</span></span>'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre style='margin-left:
+22.5pt'><span class=comment>% - run <b style='mso-bidi-font-weight:normal'>ASORT</b> with <b
+style='mso-bidi-font-weight:normal'>no-space</b>/<b style='mso-bidi-font-weight:
+normal'>template</b> options</span></pre><pre style='margin-left:22.5pt'><span
+class=comment>%<span style='mso-spacerun:yes'>   </span><span class=GramE>NOTE</span> the impact of -w/-t order!</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:2'>          </span>s<span
+class=GramE>={</span><span class=string>'ff - 1'</span>,<span class=string>'ff + 1'</span>,<span
+class=string>'- 12'</span>};</pre><pre><i><span style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre
+style='margin-left:22.5pt'><span class=comment>%<span style='mso-spacerun:yes'>   </span>RAW</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:2'>          </span>o=<span
+class=SpellE>asort</span>(s,<span class=string>'-v'</span>);</pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'INPUT'<span style='mso-spacerun:yes'>     </span>'ASCII SORT'<span style='mso-spacerun:yes'>    </span>'NUM SORT'<span style='mso-spacerun:yes'>             </span>'NUM READ'<span style='mso-spacerun:yes'>         </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'<span
+class=GramE>ff</span> - 1'<span style='mso-spacerun:yes'>    </span>'- 12'<span style='mso-spacerun:yes'>          </span>'--- NUMERICAL'<span style='mso-spacerun:yes'>        </span>'--- NUMBERS'<span style='mso-spacerun:yes'>      </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'<span
+class=GramE>ff</span> + 1'<span style='mso-spacerun:yes'>    </span>'ff + 1'<span style='mso-spacerun:yes'>        </span>'ff + 1'<span style='mso-spacerun:yes'>               </span>[<span style='mso-spacerun:yes'>                </span>1]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'- 12'<span style='mso-spacerun:yes'>      </span>'ff - 1'<span style='mso-spacerun:yes'>        </span>'ff - 1'<span style='mso-spacerun:yes'>               </span>[<span style='mso-spacerun:yes'>                </span>1]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>         </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span><span
+class=SpellE>'</span>- 12'<span style='mso-spacerun:yes'>                 </span>[<span style='mso-spacerun:yes'>               </span>12]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>         </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>    </span><span style='mso-spacerun:yes'>   </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>     </span><span
+class=SpellE>'</span>--- ASCII NUMBERS'<span style='mso-spacerun:yes'>    </span>'--- ASCII NUMBERS'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>         </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span><span
+class=SpellE>'</span>--- ASCII STRINGS'<span style='mso-spacerun:yes'>    </span>'--- ASCII STRINGS'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre style='margin-left:
+22.5pt'><span class=comment>%<span style='mso-spacerun:yes'>   </span><span
+class=GramE>remove</span> <span class=SpellE><b style='mso-bidi-font-weight:
+normal'>SPACE</b>s</span></span></pre><pre style='margin-left:22.5pt'><span
+style='mso-tab-count:2'>          </span>o=<span class=SpellE>asort</span>(s,<span
+class=string>'-v'</span>,<span class=string>'-w'</span>);</pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'INPUT'<span style='mso-spacerun:yes'>    </span>'ASCII SORT'<span style='mso-spacerun:yes'>    </span>'NUM SORT'<span style='mso-spacerun:yes'>             </span>'NUM READ'<span style='mso-spacerun:yes'>         </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'ff-1' <span style='mso-spacerun:yes'>    </span>'-12'<span style='mso-spacerun:yes'>           </span>'--- NUMERICAL'<span style='mso-spacerun:yes'>        </span>'--- NUMBERS'<span style='mso-spacerun:yes'>      </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'<span
+class=GramE>ff+</span>1'<span style='mso-spacerun:yes'>     </span><span
+class=SpellE>'ff+1'</span><span style='mso-spacerun:yes'>          </span>'-12'<span style='mso-spacerun:yes'>                  </span>[<span style='mso-spacerun:yes'>              </span>-12]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'-12'<span style='mso-spacerun:yes'>      </span>'ff-1'<span style='mso-spacerun:yes'>    </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>     </span><span
+class=SpellE>'ff-1'</span><span style='mso-spacerun:yes'>                 </span>[<span style='mso-spacerun:yes'>               </span>-1]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>        </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span>'ff+1'<span style='mso-spacerun:yes'>        </span><span style='mso-spacerun:yes'>         </span>[<span style='mso-spacerun:yes'>                </span>1]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>        </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span><span
+class=SpellE>'</span>--- ASCII NUMBERS'<span style='mso-spacerun:yes'>    </span>'--- ASCII NUMBERS'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>        </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span><span
+class=SpellE>'</span>--- ASCII STRINGS'<span style='mso-spacerun:yes'>    </span>'--- ASCII STRINGS'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre style='margin-left:
+22.5pt'><span class=comment>%<span style='mso-spacerun:yes'>   </span><span
+class=GramE>remove</span> <b style='mso-bidi-font-weight:normal'>TEMPLATE</b>(s)</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:2'>          </span>o=<span
+class=SpellE>asort</span>(s,<span class=string>'-v'</span>,<span class=string>'-t'</span><span
+class=GramE>,{</span><span class=string>'ff'</span>,<span class=string>'1'</span>});</pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'INPUT'<span style='mso-spacerun:yes'>    </span>'ASCII SORT'<span style='mso-spacerun:yes'>    </span>'NUM SORT'<span style='mso-spacerun:yes'>             </span>'NUM READ'<span style='mso-spacerun:yes'>         </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span class=GramE>' -</span> ' <span style='mso-spacerun:yes'>     </span><span
+class=SpellE>'</span> + '<span style='mso-spacerun:yes'>           </span><span
+class=SpellE>'</span>--- NUMERICAL'<span style='mso-spacerun:yes'>        </span>'--- NUMBERS'<span style='mso-spacerun:yes'>      </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span class=GramE>' +</span> ' <span style='mso-spacerun:yes'>     </span><span
+class=SpellE>'</span> - '<span style='mso-spacerun:yes'>           </span><span
+class=SpellE>'</span>- 2'<span style='mso-spacerun:yes'>                  </span>[<span style='mso-spacerun:yes'>                </span>2]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'- 2'<span style='mso-spacerun:yes'>      </span>'- 2'<span style='mso-spacerun:yes'>           </span>'--- ASCII NUMBERS'<span style='mso-spacerun:yes'>   </span><span style='mso-spacerun:yes'> </span>'--- ASCII NUMBERS'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>        </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span><span
+class=SpellE>'</span>--- ASCII STRINGS'<span style='mso-spacerun:yes'>    </span>'--- ASCII STRINGS'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span>' <span
+class=SpellE>'</span><span style='mso-spacerun:yes'>        </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span><span
+class=SpellE>'</span> + '<span style='mso-spacerun:yes'>                  </span><span
+class=SpellE>'</span> + '<span style='mso-spacerun:yes'>              </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>   </span>' <span
+class=SpellE>'</span><span style='mso-spacerun:yes'>        </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span><span
+class=SpellE>'</span> - '<span style='mso-spacerun:yes'>                  </span><span
+class=SpellE>'</span> - '<span style='mso-spacerun:yes'>              </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre style='margin-left:
+22.5pt'><span class=comment>%<span style='mso-spacerun:yes'>   </span><span
+class=GramE>remove</span> <b style='mso-bidi-font-weight:normal'>TEMPLATE</b>(s) than <span
+class=SpellE><b style='mso-bidi-font-weight:normal'>SPACE</b>s</span></span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:2'>          </span>o=<span
+class=SpellE>asort</span>(s,<span class=string>'-v'</span>,<span class=string>'-t'</span>,<span
+class=string>'1'</span>,<span class=string>'-w'</span>);</pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'INPUT'<span style='mso-spacerun:yes'>    </span>'ASCII SORT'<span style='mso-spacerun:yes'>    </span>'NUM SORT'<span style='mso-spacerun:yes'>             </span>'NUM READ'<span style='mso-spacerun:yes'>         </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'ff-'<span style='mso-spacerun:yes'>      </span>'-2'<span style='mso-spacerun:yes'>            </span>'--- NUMERICAL'<span style='mso-spacerun:yes'>        </span>'--- NUMBERS'<span style='mso-spacerun:yes'>      </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'ff+' <span style='mso-spacerun:yes'>     </span><span
+class=SpellE>'ff+'</span><span style='mso-spacerun:yes'>           </span>'-2'<span style='mso-spacerun:yes'>                </span><span style='mso-spacerun:yes'>   </span>[<span style='mso-spacerun:yes'>               </span>-2]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'-2'<span style='mso-spacerun:yes'>       </span>'ff-'<span style='mso-spacerun:yes'>           </span>'--- ASCII NUMBERS'<span style='mso-spacerun:yes'>    </span>'--- ASCII NUMBERS'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>        </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span><span
+class=SpellE>'</span>--- ASCII STRINGS'<span style='mso-spacerun:yes'>    </span>'--- ASCII STRINGS'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>        </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span>'ff+'<span style='mso-spacerun:yes'>                  </span><span
+class=SpellE>'ff+'</span><span style='mso-spacerun:yes'>              </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>    </span><span style='mso-spacerun:yes'>    </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span>'ff-'<span style='mso-spacerun:yes'>                  </span><span
+class=SpellE>'ff-'</span><span style='mso-spacerun:yes'>              </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre style='margin-left:
+22.5pt'><span class=comment>%<span style='mso-spacerun:yes'>   </span><span
+class=GramE>remove</span> <span class=SpellE><b style='mso-bidi-font-weight:
+normal'>SPACE</b>s</span> than <b style='mso-bidi-font-weight:normal'>TEMPLATE</b>(s)</span></pre><pre
+style='margin-left:22.5pt'><span style='mso-tab-count:2'>          </span>o=<span
+class=SpellE>asort</span>(s,<span class=string>'-v'</span>,<span class=string>'-w'</span>,<span
+class=string>'-t'</span>,<span class=string>'1'</span>);</pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'INPUT'<span style='mso-spacerun:yes'>    </span>'ASCII SORT'<span style='mso-spacerun:yes'>    </span>'NUM SORT'<span style='mso-spacerun:yes'>             </span>'NUM READ'<span style='mso-spacerun:yes'>         </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'ff- '<span style='mso-spacerun:yes'>     </span><span
+class=SpellE>'</span>- 2'<span style='mso-spacerun:yes'>           </span>'--- NUMERICAL'<span style='mso-spacerun:yes'>   </span><span style='mso-spacerun:yes'>     </span>'--- NUMBERS'<span style='mso-spacerun:yes'>      </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'ff+ '<span style='mso-spacerun:yes'>     </span>'ff+ '<span style='mso-spacerun:yes'>    </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>     </span><span
+class=SpellE>'</span>- 2'<span style='mso-spacerun:yes'>                  </span>[<span style='mso-spacerun:yes'>                </span>2]<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'>    </span>'- 2'<span style='mso-spacerun:yes'>      </span>'ff- '<span style='mso-spacerun:yes'>    </span><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>     </span><span
+class=SpellE>'</span>--- ASCII NUMBERS'<span style='mso-spacerun:yes'>    </span>'--- ASCII NUMBERS'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>        </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span><span
+class=SpellE>'</span>--- ASCII STRINGS'<span style='mso-spacerun:yes'>    </span>'--- ASCII STRINGS'<o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'> <span style='mso-spacerun:yes'>   </span><span class=GramE>' <span
+class=SpellE>'</span></span><span style='mso-spacerun:yes'>  </span><span style='mso-spacerun:yes'>      </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span>'ff+ '<span style='mso-spacerun:yes'>                 </span>'ff+ '<span style='mso-spacerun:yes'>             </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><span style='mso-spacerun:yes'> </span><span style='mso-spacerun:yes'>   </span><span
+class=GramE>' <span class=SpellE>'</span></span><span style='mso-spacerun:yes'>        </span><span
+class=SpellE>'</span> <span class=SpellE>'</span><span style='mso-spacerun:yes'>             </span>'ff- '<span style='mso-spacerun:yes'>                 </span>'ff- '<span style='mso-spacerun:yes'>             </span><o:p></o:p></span></i></pre><pre><i><span
+style='color:gray'><o:p>&nbsp;</o:p></span></i></pre>
+
+<p class=footer style='tab-stops:45.8pt 91.6pt 137.4pt 183.2pt 229.0pt 274.8pt 320.6pt 366.4pt 412.2pt 458.0pt 503.8pt 549.6pt 595.4pt 641.2pt 687.0pt 732.8pt'><br>
+Published with MATLAB® 7.0.4<o:p></o:p></p>
+
+</div>
+
+<!--
+##### SOURCE BEGIN #####
+% ASORT
+% a pedestrian NUMERICAL SORTER of ALPHANUMERIC data
+
+% - create some data
+		d = {
+%	strings with one valid alphanumeric number
+%	sorted numerically
+			'-inf'
+			'x-3.2e4y'
+			'f-1.4'
+			'-.1'
+			'+ .1d-2'
+			'.1'
+			'f.1'
+			'f -+1.4'
+			'f.2'
+			'f.3'
+			'f.10'
+			'f.11'
+			'+inf'
+			' -nan'
+			'+ nan'
+			'nan'
+%	strings with many numbers or invalid/ambiguous numbers
+%	sorted in ascii dictionary order
+			' nan nan'
+			'+ .1e-.2'
+			'-1 2'
+			'Z12e12ez'
+			'inf -inf'
+			's.3TT.4'
+			'z12e12ez'
+%	strings without numbers
+%	sorted in ascii dictionary order
+			' . .. '
+			'.'
+			'...'
+			'.b a.'
+			'a string'
+			'a. .b'
+		};
+%   ... and scramble it...
+		rand('seed',10);
+		d=d(randperm(numel(d)));
+
+% - run ASORT with verbose output
+%   and keep additional results
+		o=asort(d,'-v','-d');
+% - or
+%		p=asort(char(d));
+
+% - show results
+		o
+		o.anr
+
+% - run ASORT with no-space/template options
+%   NOTE the impact of -t/-w order!
+		s={'ff - 1','ff + 1','- 12'};
+%   RAW
+		o=asort(s,'-v');
+%   remove SPACEs
+		o=asort(s,'-v','-w');
+%   remove TEMPLATE(s)
+		o=asort(s,'-v','-t',{'ff','1'});
+%   remove TEMPLATE(s) than SPACEs
+		o=asort(s,'-v','-t','1','-w');
+%   remove SPACEs than TEMPLATE(s)
+		o=asort(s,'-v','-w','-t','1');
+
+
+##### SOURCE END #####
+-->
+</body>
+
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/asdemo.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,70 @@
+% ASORT
+% a pedestrian NUMERICAL SORTER of ALPHANUMERIC data
+
+% - create some data
+		d = {
+%		strings with one valid alphanumeric number
+%		sorted numerically
+			'-inf'
+			'x-3.2e4y'
+			'f-1.4'
+			'-.1'
+			'+ .1d-2'
+			'.1'
+			'f.1'
+			'f -+1.4'
+			'f.2'
+			'f.3'
+			'f.10'
+			'f.11'
+			'+inf'
+			' -nan'
+			'+ nan'
+			'nan'
+%		strings with many numbers or invalid/ambiguous numbers
+%		sorted in ascii dictionary order
+			' nan nan'
+			'+ .1e-.2'
+			'-1 2'
+			'Z12e12ez'
+			'inf -inf'
+			's.3TT.4'
+			'z12e12ez'
+%		strings without numbers
+%		sorted in ascii dictionary order
+			' . .. '
+			'.'
+			'...'
+			'.b a.'
+			'a string'
+			'a. .b'
+		};
+%   ... and scramble it...
+		rand('seed',10);
+		d=d(randperm(numel(d)));
+
+% - run ASORT with
+%   verbose output:		<-v>
+%   keep additional results:	<-d>
+		o=asort(d,'-v','-d');
+% - or
+%		p=asort(char(d),'-v','-d');
+
+% - show results
+		o
+		o.anr
+
+% - run ASORT with no-space/template options
+%   NOTE the impact of -w/-t order!
+		s={'ff - 1','ff + 1','- 12'};
+%   RAW
+		o=asort(s,'-v');
+%   remove SPACEs
+		o=asort(s,'-v','-w');
+%   remove TEMPLATE(s)
+		o=asort(s,'-v','-t',{'ff','1'});
+%   remove TEMPLATE(s) than SPACEs
+		o=asort(s,'-v','-t','1','-w');
+%   remove SPACEs than TEMPLATE(s)
+		o=asort(s,'-v','-w','-t','1');
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/asort.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,376 @@
+%[ANR,SNR,STR]	=  ASORT(INP,'OPT',...);
+% S		=  ASORT(INP,'OPT',...);
+%		   to sort alphanumeric strings numerically if
+%		   they contain one properly formatted number
+%		   otherwise, ascii dictionary sorting is applied
+%
+% INP	unsorted input:
+%	- a char array
+%	- a cell array of strings
+% OPT	options
+%  -s	- sorting option
+%	  '-s','ascend'					[def]
+%	  '-s','descend'
+%  -st	- force output form S				[def: nargout dependent]
+%  -t	- replace matching template(s) with one space
+%	  prior to sorting
+%	  '-t','template'
+%	  '-t',{'template1','template2',...}
+%  -w	- remove space(s) prior to sorting
+%
+%	  NOTE	-t/-w options are processed in the
+%		      order that they appear in
+%		      the command line
+%
+%  -v	- verbose output				[def: quiet]
+%  -d	- debug mode
+%	  save additional output in S
+%	  .c:	lex parser input
+%	  .t:	lex parser table
+%	  .n:	lex parser output
+%	  .d:	numbers read from .n
+%
+% ANR	numerically sorted alphanumeric strings		[eg, 'f.-1.5e+2x.x']
+%	- contain one number that can be read by
+%	  <strread> | <sscanf>
+% SNR	ascii dict  sorted alphanumeric strings
+% http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=7212#
+%
+%	- contain more than one number			[eg, 'f.-1.5e +2.x']
+%	- contain incomplete|ambiguous numbers		[eg, 'f.-1.5e+2.x']
+% STR	ascii dict  sorted strings
+%	- contain no numbers				[eg, 'a test']
+%
+% S	structure with fields
+%	.anr
+%	.srn
+%	.str
+
+% created:
+%	us	03-Mar-2002
+% modified:
+%	us	30-Mar-2005 11:57:07 	/ TMW R14.sp2
+
+%--------------------------------------------------------------------------------
+function	varargout=asort(inp,varargin)
+
+varargout(1:nargout)={[]};
+if	~nargin
+	help(mfilename);
+	return;
+end
+
+% - common parameters/options
+n=[];
+ds=[];
+anr={};
+snr={};
+str={};
+smod='ascend';	% sorting option
+tmpl={};	% template(s)
+sflg=false;	% output  mode: structure
+tflg=false;	% remove  template(s)
+dflg=false;	% debug   mode
+vflg=false;	% verbose output
+wflg=false;	% remove  spaces
+
+if	nargin > 1
+	ix=find(strcmp('-s',varargin));
+	if	~isempty(ix) && nargin > ix(end)+1
+		smod=varargin{ix(end)+1};
+	end
+	ix=find(strcmp('-t',varargin));
+	if	~isempty(ix) && nargin > ix(end)+1
+		tflg=ix(end);
+		tmpl=varargin{ix(end)+1};
+	end
+	if	find(strcmp('-d',varargin));
+		dflg=true;
+	end
+	if	find(strcmp('-st',varargin));
+		sflg=true;
+	end
+	if	find(strcmp('-v',varargin));
+		vflg=true;
+	end
+	ix=find(strcmp('-w',varargin));
+	if	~isempty(ix)
+		wflg=ix(end);
+	end
+end
+%   spec numbers
+ntmpl={
+	' inf '
+	'+inf '
+	'-inf '
+	' nan '
+	'+nan '
+	'-nan '
+	};
+%   spec chars
+ctmpl={
+	'.'	% decimal point
+	'd'	% exponent
+	'e'	% exponent
+	};
+
+if	nargout <= 3
+	varargout{1}=inp;
+else
+	disp(sprintf('ASORT> too many output args [%-1d/%-1d]\n',nargout,3));
+	help(mfilename);
+	return;
+end
+if	isempty(inp)
+	disp(sprintf('ASORT> input is empty'));
+	return;
+end
+
+ti=clock;
+winp=whos('inp');
+switch	winp.class
+	case	'cell'
+		if	~iscellstr(inp)
+			disp(sprintf('ASORT> cell is not an array of strings'));
+			return;
+		end
+		inp=inp(:);
+		[ins,inx]=sort(inp);
+	case	'char'
+		%		[ins,inx]=sortrows(inp);
+		inp=cstr(inp);
+	otherwise
+		disp(sprintf('ASORT> does not sort input of class <%s>',winp.class));
+		return;
+end
+
+inp=inp(:);
+inp=setinp(inp,tmpl,[tflg wflg]);
+[ins,inx]=sort(inp);
+if	strcmp(smod,'descend')
+	ins=ins(end:-1:1,:);
+	inx=inx(end:-1:1);
+end
+ins=inp(inx);
+c=lower(char(ins));
+wins=whos('c');
+[cr,cc]=size(c);
+
+% - LEXICAL PARSER
+%--------------------------------------------------------------------------------
+% - extend input on either side for search
+c=[' '*ones(cr,2) c ' '*ones(cr,2)];
+
+% - search for valid alphanumeric items in strings
+%   numbers/signs
+t=(c>='0'&c<='9');
+t=t|c=='-';
+t=t|c=='+';
+[tr,tc]=size(t);
+%   decimal points
+%   note: valid numbers with dec points must follow these templates
+%         nr.nr
+%	  sign.nr
+%         nr.<SPACE>
+%         <SPACE>.nr
+ix1=	 t(:,1:end-2) & ...
+	~isletter(c(:,1:end-2)) & ...
+	c(:,2:end-1)=='.';
+t(:,2:end-1)=t(:,2:end-1)|ix1;
+ix1=	(t(:,3:end) & ...
+	(~isletter(c(:,3:end)) & ...
+	~isletter(c(:,1:end-2))) | ...
+	(c(:,3:end)=='e' | ...
+	c(:,3:end)=='d')) & ...
+	c(:,2:end-1)=='.';
+t(:,2:end-1)=t(:,2:end-1)|ix1;
+%		t(:,3:end)=t(:,3:end)|ix1;
+%   signs
+t(c=='-')=false;
+t(c=='+')=false;
+ix1=	 t(:,3:end) & ...
+	(c(:,2:end-1)=='-' | ...
+	c(:,2:end-1)=='+');
+t(:,2:end-1)=t(:,2:end-1)|ix1;
+%   exponents
+ix1=	 t(:,1:end-2) & ...
+	(c(:,2:end-1)=='e' | ...
+	c(:,2:end-1)=='d');
+t(:,2:end-1)=t(:,2:end-1)|ix1;
+%   spec numbers
+c=reshape(c.',1,[]);
+t=t';
+ic=[];
+for	j=1:numel(ntmpl)
+	ic=[ic,strfind(c,ntmpl{j})];
+end
+ic=sort(ic);
+for	i=1:numel(ic)
+	ix=ic(i)+0:ic(i)+4;
+	t(ix)=true;
+end
+t=t';
+c=reshape(c.',[tc,tr]).';
+t(c==' ')=false;
+%--------------------------------------------------------------------------------
+
+% - only allow one number per string
+il=~any(t,2);
+ib=strfind(reshape(t.',1,[]),[0 1]);
+if	~isempty(ib)
+	ixe=cell(3,1);
+	n=reshape(char(t.*c).',1,[]);
+	for	i=1:numel(ctmpl)
+		id=strfind(n,ctmpl{i});
+		if	~isempty(id)
+			[dum,dum,ixu{i},ixe{i}]=dupinx(id,tc);
+		end
+	end
+	in=false(tr,1);
+	im=in;
+	%   must check for anomalous cases like <'.d'>
+	id=sort(...
+		[find(n>='0' & n<='9'),...
+		strfind(n,'inf'),...
+		strfind(n,'nan')]);
+	%		[ibu,ibd,ixbu,ixe{i+1}]=dupinx(id,tc);
+	[ibu,ibd,ixbu,ixbd]=dupinx(id,tc);
+	in(ixbu)=true;
+	in(ixbd)=true;
+	[ibu,ibd,ixbu,ixbd]=dupinx(ib,tc);
+	im(ixbu)=true;
+	in=in&im;
+	in([ixe{:}])=false;
+	il=~any(t,2);
+	ia=~(in|il);
+
+	% - read valid strings
+	n=t(in,:).*c(in,:);
+	n(n==0)=' ';
+	n=char(n);
+	dn=strread(n.','%n');
+	if	numel(dn) ~= numel(find(in))
+		%disp(sprintf('ASORT> unexpected fatal error reading input!'));
+		if	nargout
+			s.c=c;
+			s.t=t;
+			s.n=n;
+			s.d=dn;
+			varargout{1}=s;
+		end
+		return;
+	end
+
+	% - sort numbers
+	[ds,dx]=sort(dn,1,smod);
+	in=find(in);
+	anr=ins(in(dx));
+	snr=ins(ia);
+end
+str=ins(il);
+to=clock;
+
+% - prepare output
+if	nargout < 3 || sflg
+	s.magic='ASORT';
+	s.ver='30-Mar-2005 11:57:07';
+	s.time=datestr(clock);
+	s.runtime=etime(to,ti);
+	s.input_class=winp.class;
+	s.input_msize=winp.size;
+	s.input_bytes=winp.bytes;
+	s.strng_class=wins.class;
+	s.strng_msize=wins.size;
+	s.strng_bytes=wins.bytes;
+	s.anr=anr;
+	s.snr=snr;
+	s.str=str;
+	if	dflg
+		s.c=c;
+		s.t=t;
+		s.n=n;
+		s.d=ds;
+	end
+	varargout{1}=s;
+else
+	s={anr,snr,str};
+	for	i=1:nargout
+		varargout{i}=s{i};
+	end
+end
+
+if	vflg
+	inp=cstr(inp);
+	an=[{'--- NUMERICAL'};		anr];
+	as=[{'--- ASCII NUMBERS'};	snr];
+	at=[{'--- ASCII STRINGS'};	str];
+	nn=[{'--- NUMBERS'};		num2cell(ds)];
+	ag={' ';' ';' '};
+	u=[{'INPUT'};			inp;ag];
+	v=[{'ASCII SORT'};		ins;ag];
+	w=[{'NUM SORT'};		an;as;at];
+	x=[{'NUM READ'};		nn;as;at];
+	w=[u,v,w,x];
+	disp(w);
+end
+
+return;
+%--------------------------------------------------------------------------------
+function	c=cstr(s)
+% - bottleneck waiting for a good <cellstr> replacement
+%   it consumes ~75% of <asort>'s processing time!
+
+c=s;
+if	ischar(s)
+	sr=size(s,1);
+	c=cell(sr,1);
+	for	i=1:sr
+		c{i}=s(i,:);	% no deblanking!
+	end
+end
+return;
+%--------------------------------------------------------------------------------
+function	[idu,idd,ixu,ixd]=dupinx(ix,nc)
+% - check for more than one entry/row in a matrix of column size <nc>
+%   unique    indices:	idu / ixu
+%   duplicate indices:	idd / ixd
+
+if	isempty(ix)
+	idu=[];
+	idd=[];
+	ixu=[];
+	ixd=[];
+	return;
+end
+id=fix(ix/nc)+1;
+idi=diff(id)~=0;
+ide=[true idi];
+idb=[idi true];
+idu=idb & ide;
+idd=idb==1 & ide==0;
+ixu=id(idu);
+ixd=id(idd);
+return;
+%--------------------------------------------------------------------------------
+function	inp=setinp(inp,tmpl,flg)
+% - remove space(s) and/or templates
+
+if	isempty(inp) || ~any(flg)
+	return;
+end
+
+for	i=sort(flg)
+	switch	i
+		case	flg(1)
+			if	ischar(tmpl)
+				tmpl={tmpl};
+			end
+			for	i=1:numel(tmpl)
+				inp=strrep(inp,tmpl{i},' ');
+			end
+		case	flg(2)
+			inp=strrep(inp,' ','');
+	end
+end
+return;
+%--------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/assert.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function assert(pred, str)
+% ASSERT Raise an error if the predicate is not true.
+% assert(pred, string)
+
+if nargin<2, str = ''; end
+
+if ~pred
+  s = sprintf('assertion violated: %s', str);
+  error(s);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/assignEdgeNums.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function [edge_id, nedges] = assignEdgeNums(adj_mat)
+% give each edge a unique number
+% we number (i,j) for j>i first, in row, column order.
+% Then we number the reverse links
+
+nnodes = length(adj_mat);
+edge_id = zeros(nnodes);
+e = 1;
+for i=1:nnodes
+  for j=i+1:nnodes
+    if adj_mat(i,j)
+      edge_id(i,j) = e;
+      e = e+1;
+    end
+  end
+end
+
+nedges = e-1;
+tmp = edge_id;
+ndx = find(tmp);
+tmp(ndx) = tmp(ndx)+nedges;
+edge_id = edge_id + triu(tmp)';
+
+
+if 0
+ndx = find(adj_mat);
+nedges = length(ndx);
+nnodes = length(adj_mat);
+edge_id = zeros(1, nnodes*nnodes);
+edge_id(ndx) = 1:nedges; 
+edge_id = reshape(edge_id, nnodes, nnodes);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/assign_cols.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+function M = assign_cols(cols, vals, M)
+% ASSIGN_COLS Assign values to columns of a matrix
+% function M = assign_cols(M, cols, vals, M)
+%
+% Example:
+% M = assign_cols(data, ones(1,N))
+% will construct a 1-of-K encoding of the data, where K=ncols=max(data) and N=nrows=length(data)
+%
+% Example:
+% M = zeros(3,2);
+% M = assign_cols([1 2 1], [10 20 30], M)
+% is equivalent to
+% M(1, 1) = 10
+% M(2, 2) = 20
+% M(3, 1) = 30
+%
+
+if nargin < 3
+  nr = length(cols);
+  nc = max(cols);
+  M = zeros(nr, nc);
+else
+  [nr nc] = size(M);
+end
+
+if 0
+for r=1:nr
+  M(r, cols(r)) = vals(r);
+end
+end
+
+if 1
+rows = 1:nr;
+ndx = subv2ind([nr nc], [rows(:) cols(:)]);
+M(ndx) = vals;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/axis_pct.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,70 @@
+function ax = axis_pct(pct)
+% AXIS_PCT       Set reasonable axis limits.
+% AXIS_PCT(pct) sets axis limits to extend pct% beyond limits of plotted 
+% objects.  Default is 5%.
+% Works for linear or log scale.
+% Unfortunately, the axes won't change when new points are plotted.
+
+if nargin < 1
+  pct = 0.05;
+end
+ax = [Inf -Inf Inf -Inf Inf -Inf];
+
+% find bounding box of plotted objects
+children = get(gca,'children');
+for child = children'
+  if strcmp(get(child,'type'),'text')
+    xyz = get(child,'position');
+    % need to determine bounding box of the text
+    c([1 2]) = xyz(1);
+    c([3 4]) = xyz(2);
+    c([5 6]) = xyz(3);
+  else
+    x = get(child,'xdata');
+    c(1) = min(x);
+    c(2) = max(x);
+    y = get(child,'ydata');
+    c(3) = min(y);
+    c(4) = max(y);
+    z = get(child,'zdata');
+    if isempty(z)
+      c([5 6]) = 0;
+    else
+      c(5) = min(z);
+      c(6) = max(z);
+    end
+  end
+  ax([1 3 5]) = min(ax([1 3 5]), c([1 3 5]));
+  ax([2 4 6]) = max(ax([2 4 6]), c([2 4 6]));
+end
+if strcmp(get(gca,'xscale'), 'log')
+  ax([1 2]) = log(ax([1 2]));
+end
+if strcmp(get(gca,'yscale'), 'log')
+  ax([3 4]) = log(ax([3 4]));
+end
+dx = ax(2)-ax(1);
+if dx == 0
+  dx = 1;
+end
+dy = ax(4)-ax(3);
+if dy == 0
+  dy = 1;
+end
+dz = ax(6)-ax(5);
+if dz == 0
+  dz = 1;
+end
+ax = ax + [-dx dx -dy dy -dz dz]*pct;
+if strcmp(get(gca,'xscale'), 'log')
+  ax([1 2]) = exp(ax([1 2]));
+end
+if strcmp(get(gca,'yscale'), 'log')
+  ax([3 4]) = exp(ax([3 4]));
+end
+% clip for 2D
+ax = ax(1:length(axis));
+axis(ax);
+if nargout < 1
+  clear ax
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/bipartiteMatchingDemo.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,112 @@
+% Consider matching sources to detections
+
+%  s1 d2  
+%         s2 d3
+%  d1
+
+%a  = bipartiteMatchingHungarian([52;0.01])
+
+% sources(:,i) = [x y] coords
+sources = [0.1 0.7; 0.6 0.4]';
+detections = [0.2 0.2; 0.2 0.8; 0.7 0.1]';
+dst = sqdist(sources, detections);
+
+% a = [2 3] which means s1-d2, s2-d3
+a = bipartiteMatchingHungarian(dst);
+a2 = bipartiteMatchingIntProg(dst);
+assert(isequal(a(:),a2(:)))
+
+
+figure(1); clf
+bipartiteMatchingDemoPlot(sources, detections, a)
+
+
+
+
+%%%% Flip roles of sources and detections
+
+%dst  = dst';
+dst = sqdist(detections, sources);
+% a = [0 1 2] which means d1-0, d2-s1, d3-s2
+a = bipartiteMatchingHungarian(dst);
+
+a2 = bipartiteMatchingIntProg(dst);
+assert(isequal(a(:),a2(:)))
+
+figure(2); clf
+bipartiteMatchingDemoPlot(detections, sources, a) % swapped args
+
+
+
+
+%%%%%%%%%% Move s1 nearer to d1
+%  d2  
+%         s2 d3
+%  s1 d1
+
+sources = [0.1 0.3; 0.6 0.4]';
+detections = [0.2 0.2; 0.2 0.8; 0.7 0.1]';
+dst = sqdist(sources, detections);
+
+% a = [2 3] which means s1-d2, s2-d3
+a = bipartiteMatchingHungarian(dst);
+[a2, ass] = bipartiteMatchingIntProg(dst);
+assert(isequal(a(:),a2(:)))
+
+
+figure(3); clf
+bipartiteMatchingDemoPlot(sources, detections, a)
+
+
+
+%%%%%%%%%%
+
+% Use random points
+
+% Generate 2D data from a mixture of 2 Gaussians (from netlab demgmm1)
+randn('state', 0); rand('state', 0);
+gmix = gmm(2, 2, 'spherical');
+ndat1 = 10; ndat2 = 10; ndata = ndat1+ndat2;
+%gmix.centres =  [0.3 0.3; 0.7 0.7]; 
+%gmix.covars = [0.01 0.01];
+gmix.centres =  [0.5 0.5; 0.5 0.5];
+gmix.covars = [0.1 0.01];
+[x, label] = gmmsamp(gmix, ndata);
+
+ndx = find(label==1);
+sources = x(ndx,:)';
+ndx = find(label==2);
+detections = x(ndx,:)';
+dst = sqdist(sources, detections);
+
+[a, ass] = bipartiteMatchingIntProg(dst);
+[a2] = bipartiteMatchingHungarian(dst);
+assert(isequal(a(:), a2(:)))
+
+figure(4); clf
+bipartiteMatchingDemoPlot(sources, detections, a)
+
+% only match 80% of points
+p1 = size(sources, 2);
+p2 = size(detections, 2);
+nmatch = ceil(0.8*min(p1,p2));
+a2 = bipartiteMatchingIntProg(dst, nmatch);
+figure(5); clf
+bipartiteMatchingDemoPlot(sources, detections, a2)
+
+
+%%% swap roles
+
+ndx = find(label==2);
+sources = x(ndx,:)';
+ndx = find(label==1);
+detections = x(ndx,:)';
+dst = sqdist(sources, detections);
+
+% only match 80% of points
+p1 = size(sources, 2);
+p2 = size(detections, 2);
+nmatch = ceil(0.8*min(p1,p2));
+a2 = bipartiteMatchingIntProg(dst, nmatch);
+figure(6); clf
+bipartiteMatchingDemoPlot(sources, detections, a2)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/bipartiteMatchingDemoPlot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function bipartiteMatchingDemoPlot(sources, detections, a)
+
+hold on
+p1 = size(sources,2);
+p2 = size(detections,2);
+for i=1:p1
+  h=text(sources(1,i), sources(2,i), sprintf('s%d', i));
+  set(h, 'color', 'r');
+end
+for i=1:p2
+  h=text(detections(1,i), detections(2,i), sprintf('d%d', i));
+  set(h, 'color', 'b');
+end
+
+if nargin < 3, return; end
+
+for i=1:p1
+  j = a(i);
+  if j==0 % i not matched to anything
+    continue
+  end
+  line([sources(1,i) detections(1,j)], [sources(2,i) detections(2,j)])
+end
+axis_pct;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/bipartiteMatchingHungarian.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,90 @@
+% MATCH - Solves the weighted bipartite matching (or assignment)
+%         problem.
+%
+% Usage:  a = match(C);
+%
+% Arguments:   
+%         C     - an m x n cost matrix; the sets are taken to be
+%                 1:m and 1:n; C(i, j) gives the cost of matching
+%                 items i (of the first set) and j (of the second set)
+%
+% Returns:
+%
+%         a     - an m x 1 assignment vector, which gives the
+%                 minimum cost assignment.  a(i) is the index of
+%                 the item of 1:n that was matched to item i of
+%                 1:m.  If item i (of 1:m) was not matched to any 
+%                 item of 1:n, then a(i) is zero.
+
+% Copyright (C) 2002 Mark A. Paskin
+%
+% This program 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 2 of the License, or
+% (at your option) any later version.
+%
+% This program 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
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+% USA.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function [a] = optimalMatching(C)
+
+% Trivial cases:
+[p, q] = size(C);
+if (p == 0)
+  a = []; 
+  return;
+elseif (q == 0)
+  a = zeros(p, 1);
+  return;
+end
+
+
+if  0
+% First, reduce the problem by making easy optimal matches.  If two
+% elements agree that they are the best match, then match them up.
+[x, a] = min(C, [], 2);
+[y, b] = min(C, [], 1);
+u = find(1:p ~= b(a(:)));
+a(u) = 0;
+v = find(1:q ~= a(b(:))');
+C = C(u, v);
+if (isempty(C)) return; end
+end
+
+% Get the (new) size of the two sets, u and v.
+[m, n] = size(C);
+
+%mx = realmax;
+mx = 2*max(C(:));
+mn = -2*min(C(:));
+% Pad the affinity matrix to be square
+if (m < n)
+  C = [C; mx * ones(n - m, n)];
+elseif (n < m)
+  C = [C, mx * ones(m, m - n)];
+end
+
+% Run the Hungarian method.  First replace infinite values by the
+% largest (or smallest) finite values.
+C(find(isinf(C) & (C > 0))) = mx;
+C(find(isinf(C) & (C < 0))) = mn;
+%fprintf('running hungarian\n');
+[b, cost] = hungarian(C');
+
+% Extract only the real assignments
+ap = b(1:m)';
+ap(find(ap > n)) = 0;
+
+a = ap; 
+%% Incorporate this sub-assignment into the complete assignment
+%  k = find(ap);
+%  a(u(k)) = v(ap(k));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/bipartiteMatchingIntProg.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,69 @@
+function [a,ass] = bipartiteMatchingIntProg(dst, nmatches)
+% BIPARTITEMATCHINGINTPROG Use binary integer programming (linear objective) to solve for optimal linear assignment
+% function a = bipartiteMatchingIntProg(dst)
+% a(i) = best matching column for row i
+% 
+% This gives the same result as bipartiteMatchingHungarian.
+%
+% function a = bibpartiteMatchingIntProg(dst, nmatches)
+% only matches the specified number (must be <= min(size(dst))).
+% This can be used to allow outliers in both source and target.
+%
+% For details, see Marciel & Costeira, "A global solution to sparse correspondence
+% problems", PAMI 25(2), 2003
+
+if nargin < 2, nmatches = []; end
+
+[p1 p2] = size(dst);
+p1orig = p1; p2orig = p2;
+dstorig = dst;
+
+if isempty(nmatches) % no outliers allowed  (modulo size difference)
+  % ensure matrix is square
+  m = max(dst(:));
+  if p1<p2
+    dst = [dst; m*ones(p2-p1, p2)];
+  elseif p1>p2
+    dst = [dst  m*ones(p1, p1-p2)];
+  end
+end
+[p1 p2] = size(dst);
+
+
+c = dst(:); % vectorize cost matrix
+
+% row-sum: ensure each column sums to 1
+A2 = kron(eye(p2), ones(1,p1));
+b2 = ones(p2,1);
+
+% col-sum: ensure each row sums to 1
+A3 = kron(ones(1,p2), eye(p1));
+b3 = ones(p1,1);
+
+if isempty(nmatches)
+  % enforce doubly  stochastic
+  A = [A2; A3];
+  b = [b2; b3];
+  Aineq = zeros(1, p1*p2);
+  bineq = 0;
+else
+  nmatches = min([nmatches, p1, p2]);
+  Aineq = [A2; A3];
+  bineq = [b2; b3]; % row and col sums <= 1
+  A = ones(1,p1*p2);
+  b = nmatches; % total num matches = b (otherwise get degenerate soln)
+end
+
+
+ass = bintprog(c, Aineq, bineq, A, b);
+ass = reshape(ass, p1, p2);
+
+a = zeros(1, p1orig);
+for i=1:p1orig
+  ndx = find(ass(i,:)==1);
+  if ~isempty(ndx) & (ndx <= p2orig)
+    a(i) = ndx;
+  end
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/block.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function sub = block(blocks, block_sizes)
+% BLOCK Return a vector of subscripts corresponding to the specified blocks.
+% sub = block(blocks, block_sizes)
+% 
+% e.g., block([2 5], [2 1 2 1 2]) = [3 7 8].
+
+blocks = blocks(:)';
+block_sizes = block_sizes(:)';
+skip = [0 cumsum(block_sizes)];
+start = skip(blocks)+1;
+fin = start + block_sizes(blocks) - 1;
+sub = [];
+for j=1:length(blocks)
+  sub = [sub start(j):fin(j)];
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/cell2matPad.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function data2 = cell2matPad(data)
+% data{f}(y,x,b) - each frame can have a different size (can can even be empty)
+% data2(y,x,b,f) = zero padded version
+
+Nframes = length(data);
+Nbands = -inf;
+nr = -inf; nc = -inf;
+for f=1:Nframes
+  if isempty(data{f}), continue; end
+  nr = max(nr, size(data{f},1));
+  nc = max(nc, size(data{f},2));
+  Nbands = max(Nbands, size(data{f},3));
+end    
+data2 = zeros(nr, nc, Nbands, Nframes);
+for f=1:Nframes
+  if isempty(data{f}), continue; end
+  data2(1:size(data{f},1), 1:size(data{f},2), :, f) = data{f};
+end
+if Nbands == 1
+  data2 = squeeze(data2); % reshape(data2, [size(data2,1), size(data2,2), Nframes]);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/cell2num.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+function N = cell2num(C)
+% CELL2NUM Convert a 2D cell array to a 2D numeric array 
+% N = cell2num(C)
+% If the cells contain column vectors, they must have the same number of rows in each row of C.
+% Each column will be concatenated.
+%
+% Example 1:
+% C = num2cell(rand(2,2))
+%    [0.4565]    [0.8214]
+%    [0.0185]    [0.4447]
+% N = cell2num(C)
+%     0.4565    0.8214
+%     0.0185    0.4447
+%
+% Example 2:
+% C = cell(2, 3);
+% for i=1:2
+%   for j=1:3
+%     C{i,j} = rand(i, 1);
+%   end
+% end
+% C = 
+%     [    0.8998]    [    0.8216]    [    0.6449]
+%     [2x1 double]    [2x1 double]    [2x1 double]
+% C{2,1} = 
+%     0.8180
+%     0.6602
+% N=cell2num(C)
+%     0.8998    0.8216    0.6449
+%     0.8180    0.3420    0.3412
+%     0.6602    0.2897    0.5341
+
+
+%  error('use cell2mat in matlab 7')
+
+
+if isempty(C)
+  N = [];
+  return;
+end
+
+if any(cellfun('isempty', C)) %any(isemptycell(C))
+  error('can''t convert cell array with empty cells to matrix')
+end
+
+[nrows ncols] = size(C);
+%N = reshape(cat(1, C{:}), [nrows ncols]); % this only works if C only contains scalars
+r = 0;
+for i=1:nrows
+  r = r + size(C{i,1}, 1);
+end
+c = 0;
+for j=1:ncols
+  c = c + size(C{1,j}, 2);
+end
+N = reshape(cat(1, C{:}), [r c]);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/centeringMatrix.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+N = 3;
+x = rand(N,2); % each row is a feature vector 
+m = mean(x,1);
+xc = x-repmat(m, N, 1);
+
+C = eye(N) - (1/N)*ones(N,N);
+xc2 = C*x;
+assert(approxeq(xc, xc2))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/checkpsd.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function s = checkpsd(s)
+
+if (any(isnan(s) | isinf(s) | ~isreal(s)))
+  warning('S contains complex numbers, Inf, or NaN'); 
+end
+% Drop any negative eigenvalues.
+[V, D] = eig(full(s));
+d = real(diag(D));
+if (any(d < 0))
+  warning(sprintf(['S is not positive semidefinite (min. eig. =' ...
+		   ' %0.5g); projecting.'], min(d)));
+  d(find(d < 0)) = 0;
+  D = diag(d);
+  s = V * D * V';
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/chi2inv.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+function x = chi2inv(p,v);
+%CHI2INV Inverse of the chi-square cumulative distribution function (cdf).
+%   X = CHI2INV(P,V)  returns the inverse of the chi-square cdf with V  
+%   degrees of freedom at the values in P. The chi-square cdf with V 
+%   degrees of freedom, is the gamma cdf with parameters V/2 and 2.   
+%
+%   The size of X is the common size of P and V. A scalar input
+%   functions as a constant matrix of the same size as the other input.   
+
+%   References:
+%      [1]  M. Abramowitz and I. A. Stegun, "Handbook of Mathematical
+%      Functions", Government Printing Office, 1964, 26.4.
+%      [2] E. Kreyszig, "Introductory Mathematical Statistics",
+%      John Wiley, 1970, section 10.2 (page 144)
+
+%   Copyright 1993-2002 The MathWorks, Inc. 
+%   $Revision: 1.1.1.1 $  $Date: 2005/04/26 02:30:30 $
+
+if nargin < 2, 
+    error('Requires two input arguments.');
+end
+
+[errorcode p v] = distchck(2,p,v);
+
+if errorcode > 0
+    error('Requires non-scalar arguments to match in size.');
+end
+
+% Call the gamma inverse function. 
+x = gaminv(p,v/2,2);
+
+% Return NaN if the degrees of freedom is not positive.
+k = (v <= 0);
+if any(k(:))
+    x(k) = NaN;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/choose.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function c = choose(n,k)
+% CHOOSE The number of ways of choosing k things from n 
+% c = choose(n,k)
+
+c = factorial(n)/(factorial(k) * factorial(n-k));      
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/collapse_mog.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function [new_mu, new_Sigma, new_Sigma2] = collapse_mog(mu, Sigma, coefs)
+% COLLAPSE_MOG Collapse a mixture of Gaussians to a single Gaussian by moment matching
+% [new_mu, new_Sigma] = collapse_mog(mu, Sigma, coefs)
+%
+% coefs(i) - weight of i'th mixture component
+% mu(:,i), Sigma(:,:,i) - params of i'th mixture component
+
+% S = sum_c w_c (S_c + m_c m_c' + m m' - 2 m_c m') 
+%   = sum_c w_c (S_c + m_c m_c') + m m' - 2 (sum_c m_c) m'
+%   = sum_c w_c (S_c + m_c m_c') - m m'
+
+new_mu = sum(mu * diag(coefs), 2); % weighted sum of columns
+
+n = length(new_mu);
+new_Sigma = zeros(n,n);
+new_Sigma2 = zeros(n,n);
+for j=1:length(coefs)
+  m = mu(:,j) - new_mu;
+  new_Sigma = new_Sigma + coefs(j) * (Sigma(:,:,j) + m*m');
+  new_Sigma2 = new_Sigma2 + coefs(j) * (Sigma(:,:,j) + mu(:,j)*mu(:,j)');
+end
+%assert(approxeq(new_Sigma, new_Sigma2 - new_mu*new_mu'))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/colmult.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,62 @@
+#include <stdio.h>
+#include "mex.h"
+
+/*
+out = colop(M, v)
+
+Apply binary operator to a vector v and to each column of M in turn
+to produce a matrix the same size as M.
+
+This is equivalent to
+
+out = zeros(size(M));
+for col=1:size(M,2)
+  out(:,col) = op(M(:,col), v);
+end
+
+The code needs to be modified for each different operator 'op'.
+eg op = '.*'
+
+In vectorized form:
+
+out = M .* repmat(v(:), 1, size(M,2))
+
+(This function was formerly called repmat_and_mult.c)
+
+*/
+
+/* M(i,j) = M(i + nrows*j) since Matlab uses Fortran layout. */
+
+ 
+#define INMAT(i,j) M[(i)+nrows*(j)]
+#define OUTMAT(i,j) out[(i)+nrows*(j)]
+
+void mexFunction(
+                 int nlhs,       mxArray *plhs[],
+                 int nrhs, const mxArray *prhs[]
+		 )
+{
+  double *out, *M, *v;
+  int nrows, ncols, r, c;
+  
+  /* read the input args */
+  M = mxGetPr(prhs[0]);
+  nrows = mxGetM(prhs[0]);
+  ncols = mxGetN(prhs[0]);
+
+  v = mxGetPr(prhs[1]);
+
+  plhs[0] = mxCreateDoubleMatrix(nrows, ncols, mxREAL);
+  out = mxGetPr(plhs[0]); 
+
+  for (c=0; c < ncols; c++) {
+    for (r=0; r < nrows; r++) {
+      OUTMAT(r,c) = INMAT(r,c) * v[r]; 
+      /* printf("r=%d, c=%d, M=%f, v=%f\n", r, c, INMAT(r,c), v[r]);  */
+    }
+  }
+
+}
+
+
+
Binary file _FullBNT/KPMtools/colmult.mexglx has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/computeROC.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+function [FPrate, TPrate, AUC, thresholds] = computeROC(confidence, testClass)
+% function [FPrate, TPrate, AUC, thresholds] = computeROC(confidence, testClass)
+%
+% computeROC computes the data for an ROC curve based on a classifier's confidence output.
+% It returns the false positive rate and the true positive rate along with
+% the area under the ROC curve, and the list of thresholds.
+%
+% Inputs: 
+%           - confidence(i) is proportional to the probability that
+%             testClass(i) is positive
+%
+% testClass = 0 => target absent
+% testClass = 1 => target present
+%
+% Based on algorithms 2 and 4 from Tom Fawcett's paper "ROC Graphs: Notes and
+% Practical Considerations for Data Mining Researchers" (2003)
+% http://www.hpl.hp.com/techreports/2003/HPL-2003-4.pdf"
+%
+% Vlad Magdin, 21 Feb 2005
+
+% break ties in scores
+S = rand('state');
+rand('state',0);
+confidence = confidence + rand(size(confidence))*10^(-10);
+rand('state',S)
+[thresholds order] = sort(confidence, 'descend');
+testClass = testClass(order);
+
+%%% -- calculate TP/FP rates and totals -- %%%
+AUC = 0;
+faCnt = 0;
+tpCnt = 0;
+falseAlarms = zeros(1,size(thresholds,2));
+detections = zeros(1,size(thresholds,2));
+fPrev = -inf;
+faPrev = 0;
+tpPrev = 0;
+
+P = max(size(find(testClass==1)));
+N = max(size(find(testClass==0)));
+
+for i=1:length(thresholds)
+    if thresholds(i) ~= fPrev
+        falseAlarms(i) = faCnt;
+        detections(i) = tpCnt;
+
+        AUC = AUC + polyarea([faPrev faPrev faCnt/N faCnt/N],[0 tpPrev tpCnt/P 0]);
+
+        fPrev = thresholds(i);
+        faPrev = faCnt/N;
+        tpPrev = tpCnt/P;
+    end
+    
+    if testClass(i) == 1
+        tpCnt = tpCnt + 1;
+    else
+        faCnt = faCnt + 1;
+    end
+end
+
+AUC = AUC + polyarea([faPrev faPrev 1 1],[0 tpPrev 1 0]);
+
+FPrate = falseAlarms/N;
+TPrate = detections/P;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/compute_counts.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function count = compute_counts(data, sz)
+% COMPUTE_COUNTS Count the number of times each combination of discrete assignments occurs
+% count = compute_counts(data, sz)
+%
+% data(i,t) is the value of variable i in case t
+% sz(i) : values for variable i are assumed to be in [1:sz(i)]
+%
+% Example: to compute a transition matrix for an HMM from a sequence of labeled states:
+% transmat = mk_stochastic(compute_counts([seq(1:end-1); seq(2:end)], [nstates nstates]));
+
+assert(length(sz) == size(data, 1));
+P = prod(sz);
+indices = subv2ind(sz, data'); % each row of data' is a case 
+%count = histc(indices, 1:P);
+count = hist(indices, 1:P);
+count = myreshape(count, sz);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/conf2mahal.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,62 @@
+% CONF2MAHAL - Translates a confidence interval to a Mahalanobis
+%              distance.  Consider a multivariate Gaussian
+%              distribution of the form
+%
+%   p(x) = 1/sqrt((2 * pi)^d * det(C)) * exp((-1/2) * MD(x, m, inv(C)))
+%
+%              where MD(x, m, P) is the Mahalanobis distance from x
+%              to m under P:
+%
+%                 MD(x, m, P) = (x - m) * P * (x - m)'
+%
+%              A particular Mahalanobis distance k identifies an
+%              ellipsoid centered at the mean of the distribution.
+%              The confidence interval associated with this ellipsoid
+%              is the probability mass enclosed by it.  Similarly,
+%              a particular confidence interval uniquely determines
+%              an ellipsoid with a fixed Mahalanobis distance.
+%
+%              If X is an d dimensional Gaussian-distributed vector,
+%              then the Mahalanobis distance of X is distributed
+%              according to the Chi-squared distribution with d
+%              degrees of freedom.  Thus, the Mahalanobis distance is
+%              determined by evaluating the inverse cumulative
+%              distribution function of the chi squared distribution
+%              up to the confidence value.
+%
+% Usage:
+% 
+%   m = conf2mahal(c, d);
+%
+% Inputs:
+%
+%   c    - the confidence interval
+%   d    - the number of dimensions of the Gaussian distribution
+%
+% Outputs:
+%
+%   m    - the Mahalanobis radius of the ellipsoid enclosing the
+%          fraction c of the distribution's probability mass
+%
+% See also: MAHAL2CONF
+
+% Copyright (C) 2002 Mark A. Paskin
+%
+% This program 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 2 of the License, or
+% (at your option) any later version.
+%
+% This program 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
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+% USA.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function m = conf2mahal(c, d)
+
+m = chi2inv(c, d);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/cross_entropy.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function kl = cross_entropy(p, q, symmetric)
+% CROSS_ENTROPY Compute the Kullback-Leibler divergence between two discrete prob. distributions
+% kl = cross_entropy(p, q, symmetric)
+%
+% If symmetric = 1, we compute the symmetric version. Default: symmetric = 0;
+
+tiny = exp(-700);
+if nargin < 3, symmetric = 0; end
+p = p(:);
+q = q(:);
+if symmetric
+  kl  = (sum(p .* log((p+tiny)./(q+tiny))) + sum(q .* log((q+tiny)./(p+tiny))))/2;
+else
+  kl  = sum(p .* log((p+tiny)./(q+tiny)));
+end                                           
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/dirKPM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,98 @@
+function filenames = dirKPM(dirname, ext, varargin)
+% dirKPM Like the built-in dir command, but returns filenames as a cell array instead of a struct
+%
+% filenames = dirKPM(dirname)
+% returns all files, except '.' and '..'
+%
+% filenames = dirKPM('images', '*.jpg')
+% returns files with this extension
+%   eg filenames{1} = 'foo.jpg' etc
+%
+% OPTIONAL ARGUMENTS [default in brackets]
+% filenames = dirKPM('images', '', param1, val1, param2, val2, ...)
+%
+% 'fileType'='image' ['all'] means return files with extension .jpg, .png, .bmp
+%
+% 'prepend'=1 [0] means preprend folder name to filename
+%    eg filenames{1} = 'images/foo.jpg'
+%
+% 'doSort'=1 [1] means sort filenames in ascending alphanumerical order (where possible)
+%
+% 'doRecurse'=1 [0] recursive dir, apply the same dirKPM call on all
+% subfolders (decrease MAXDEPTH option to prevent recursion from branching
+% too explosively)
+
+if nargin < 1, dirname = '.'; end
+
+if nargin < 2, ext = ''; end
+
+[fileType, prepend, doSort, doRecurse, MAXDEPTH, DEPTH] = process_options(...
+	varargin, 'fileType', 'all', 'prepend', 0, 'doSort', 1, 'doRecurse', 0,...
+	'MAXDEPTH', 3, 'DEPTH', 0);
+
+tmp = dir(fullfile(dirname, ext));
+[filenames I] = setdiff({tmp.name}, {'.', '..'});
+tmp = tmp(I);
+
+if doRecurse && sum([tmp.isdir])>0 && DEPTH<MAXDEPTH
+	for fi=1:length(tmp)
+		subDirFilenames = {};
+
+		if tmp(fi).isdir
+			varargin = change_option( varargin, 'prepend', false );
+			varargin = change_option( varargin, 'doSort', false );
+			varargin = change_option( varargin, 'DEPTH', DEPTH+1 );
+			subDirFilenames = dirKPM( fullfile(dirname,tmp(fi).name), ext, varargin{:} );
+
+			for sdfi=1:length(subDirFilenames)
+				subDirFilenames{sdfi} = fullfile(tmp(fi).name, subDirFilenames{sdfi});
+			end
+		end
+
+
+		nfilenames = length(filenames);
+		if length(subDirFilenames)>0
+			filenames(nfilenames+1:nfilenames+length(subDirFilenames)) = subDirFilenames;
+		end
+	end
+end
+
+nfiles = length(filenames);
+if nfiles==0 return; end
+
+switch fileType
+	case 'image',
+		for fi=1:nfiles
+			good(fi) = isImage(filenames{fi});
+		end
+		filenames = filenames(find(good));
+	case 'all',
+		% no-op
+	otherwise
+		error(sprintf('unrecognized file type %s', fileType));
+end
+
+if doSort
+% 	% sort filenames alphanumerically (if possible)
+%  DJE, buggy, MUST save tmp.anr/snr/str or else we potentially lose
+%  filenames
+% 	tmp = asort(filenames, '-s', 'ascend');
+% 	if ~isempty(tmp.anr)
+% 		filenames = tmp.anr';
+% 	else
+% 		filenames = tmp.str';
+% 	end
+	% if names could not be sorted, return original order
+
+	filenames=sort(filenames);
+	
+end
+
+
+if prepend
+	nfiles = length(filenames);
+	for fi=1:nfiles
+		filenames{fi} = fullfile(dirname, filenames{fi});
+	end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/div.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function d = div(a,b)
+% DIV Integer division
+% d = div(a,b)
+
+d = floor(a / b);        
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/draw_circle.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function h = draw_circle(x, r, outline_color, fill_color)
+% draw filled circles at centers x with radii r.
+% x is a matrix of columns.  r is a row vector.
+
+n = 40;					% resolution
+radians = [0:(2*pi)/(n-1):2*pi];
+unitC = [sin(radians); cos(radians)];
+
+% extend r if necessary
+if length(r) < cols(x)
+  r = [r repmat(r(length(r)), 1, cols(x)-length(r))];
+end
+
+h = [];
+% hold is needed for fill()
+held = ishold;
+hold on
+for i=1:cols(x)
+  y = unitC*r(i) + repmat(x(:, i), 1, n);
+  if nargin < 4
+    h = [h line(y(1,:), y(2,:), 'Color', outline_color)];
+  else
+    h = [h fill(y(1,:), y(2,:), fill_color, 'EdgeColor', outline_color)];
+  end
+end
+if ~held
+  hold off
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/draw_ellipse.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function h = draw_ellipse(x, c, outline_color, fill_color)
+% DRAW_ELLIPSE(x, c, outline_color, fill_color)
+%   Draws ellipses at centers x with covariance matrix c.
+%   x is a matrix of columns.  c is a positive definite matrix.
+%   outline_color and fill_color are optional.
+
+n = 40;					% resolution
+radians = [0:(2*pi)/(n-1):2*pi];
+unitC = [sin(radians); cos(radians)];
+r = chol(c)';
+
+if nargin < 3
+  outline_color = 'g';
+end
+
+h = [];
+for i=1:cols(x)
+  y = r*unitC + repmat(x(:, i), 1, n);
+  if nargin < 4
+    h = [h line(y(1,:), y(2,:), 'Color', outline_color)];
+  else
+    h = [h fill(y(1,:), y(2,:), fill_color, 'EdgeColor', outline_color)];
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/draw_ellipse_axes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function h = draw_ellipse_axes(x, c, linespec)
+% DRAW_ELLIPSE_AXES(x, c, linespec)
+%   Draws the major and minor axes of ellipses.
+%   Ellipses are centered at x with covariance matrix c.
+%   x is a matrix of columns.  c is a positive definite matrix.
+%   linespec is optional.
+
+[v,e] = eig(c);
+v = v*sqrt(e);
+
+h = [];
+for j = 1:cols(v)
+  x1 = repmat(x(1,:),2,1) + repmat([-1;1]*v(1,j),1,cols(x));
+  x2 = repmat(x(2,:),2,1) + repmat([-1;1]*v(2,j),1,cols(x));
+  h = [h line(x1,x2)];
+end
+if nargin > 2
+  set_linespec(h,linespec);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/em_converged.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function [converged, decrease] = em_converged(loglik, previous_loglik, threshold, check_increased)
+% EM_CONVERGED Has EM converged?
+% [converged, decrease] = em_converged(loglik, previous_loglik, threshold)
+%
+% We have converged if the slope of the log-likelihood function falls below 'threshold', 
+% i.e., |f(t) - f(t-1)| / avg < threshold,
+% where avg = (|f(t)| + |f(t-1)|)/2 and f(t) is log lik at iteration t.
+% 'threshold' defaults to 1e-4.
+%
+% This stopping criterion is from Numerical Recipes in C p423
+%
+% If we are doing MAP estimation (using priors), the likelihood can decrase,
+% even though the mode of the posterior is increasing.
+
+if nargin < 3, threshold = 1e-4; end
+if nargin < 4, check_increased = 1; end
+
+converged = 0;
+decrease = 0;
+
+if check_increased
+  if loglik - previous_loglik < -1e-3 % allow for a little imprecision
+    fprintf(1, '******likelihood decreased from %6.4f to %6.4f!\n', previous_loglik, loglik);
+    decrease = 1;
+converged = 0;
+return;
+  end
+end
+
+delta_loglik = abs(loglik - previous_loglik);
+avg_loglik = (abs(loglik) + abs(previous_loglik) + eps)/2;
+if (delta_loglik / avg_loglik) < threshold, converged = 1; end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/entropy.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function H = entropy(v, scale)
+% ENTROPY Entropy log base 2
+% H = entropy(v)
+% If v is a matrix, we compute the entropy of each column
+%
+% % H = entropy(v,1) means we scale the result so that it lies in [0,1]
+
+if nargin < 2, scale = 0; end
+
+v = v + (v==0);
+H = -1 * sum(v .* log2(v), 1); % sum the rows
+
+if scale
+  n = size(v, 1);
+  unif = normalise(ones(n,1));
+  H = H / entropy(unif);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/exportfig.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,991 @@
+function varargout = exportfig(varargin)
+%EXPORTFIG  Export a figure.
+%   EXPORTFIG(H, FILENAME) writes the figure H to FILENAME.  H is
+%   a figure handle and FILENAME is a string that specifies the
+%   name of the output file.
+%
+%   EXPORTFIG(H, FILENAME, OPTIONS) writes the figure H to FILENAME
+%   with options initially specified by the structure OPTIONS. The
+%   field names of OPTIONS must be legal parameters listed below
+%   and the field values must be legal values for the corresponding
+%   parameter. Default options can be set in releases prior to R12
+%   by storing the OPTIONS structure in the root object's appdata
+%   with the command 
+%      setappdata(0,'exportfigdefaults', OPTIONS) 
+%   and for releases after R12 by setting the preference with the
+%   command 
+%      setpref('exportfig', 'defaults', OPTIONS) 
+%
+%   EXPORTFIG(...,PARAM1,VAL1,PARAM2,VAL2,...) specifies
+%   parameters that control various characteristics of the output
+%   file. Any parameter value can be the string 'auto' which means
+%   the parameter uses the default factory behavior, overriding
+%   any other default for the parameter.
+%
+%   Format Paramter:
+%     'Format'  a string
+%          specifies the output format. Defaults to 'eps'. For a
+%          list of export formats type 'help print'.
+%     'Preview' one of the strings 'none', 'tiff'
+%          specifies a preview for EPS files. Defaults to 'none'.
+%
+%   Size Parameters:
+%     'Width'   a positive scalar
+%          specifies the width in the figure's PaperUnits
+%     'Height'  a positive scalar
+%          specifies the height in the figure's PaperUnits
+%     'Bounds' one of the strings 'tight', 'loose'
+%          specifies a tight or loose bounding box. Defaults to 'tight'.
+%     'Reference' an axes handle or a string
+%          specifies that the width and height parameters
+%          are relative to the given axes. If a string is
+%          specified then it must evaluate to an axes handle.
+%
+%     Specifying only one dimension sets the other dimension
+%     so that the exported aspect ratio is the same as the
+%     figure's or reference axes' current aspect ratio. 
+%     If neither dimension is specified the size defaults to 
+%     the width and height from the figure's or reference
+%     axes' size. Tight bounding boxes are only computed for
+%     2-D views and in that case the computed bounds enclose all
+%     text objects.
+%           
+%   Rendering Parameters:
+%     'Color'     one of the strings 'bw', 'gray', 'cmyk'
+%         'bw'    specifies that lines and text are exported in
+%                 black and all other objects in grayscale
+%         'gray'  specifies that all objects are exported in grayscale
+%         'rgb'   specifies that all objects are exported in color
+%                 using the RGB color space
+%         'cmyk'  specifies that all objects are exported in color
+%                 using the CMYK color space
+%     'Renderer'  one of 'painters', 'zbuffer', 'opengl'
+%         specifies the renderer to use
+%     'Resolution'   a positive scalar
+%         specifies the resolution in dots-per-inch.
+%     'LockAxes'  one of 0 or 1
+%         specifies that all axes limits and ticks should be fixed
+%         while exporting.
+%     
+%     The default color setting is 'bw'.
+%
+%   Font Parameters:
+%     'FontMode'     one of the strings 'scaled', 'fixed'
+%     'FontSize'     a positive scalar
+%          in 'scaled' mode multiplies with the font size of each
+%          text object to obtain the exported font size
+%          in 'fixed' mode specifies the font size of all text
+%          objects in points
+%     'DefaultFixedFontSize' a positive scalar
+%          in 'fixed' mode specified the default font size in
+%          points
+%     'FontSizeMin' a positive scalar
+%          specifies the minimum font size allowed after scaling
+%     'FontSizeMax' a positive scalar
+%          specifies the maximum font size allowed after scaling
+%     'FontEncoding' one of the strings 'latin1', 'adobe'
+%          specifies the character encoding of the font
+%     'SeparateText' one of 0 or 1
+%          specifies that the text objects are stored in separate
+%          file as EPS with the base filename having '_t' appended.
+%
+%     If FontMode is 'scaled' but FontSize is not specified then a
+%     scaling factor is computed from the ratio of the size of the
+%     exported figure to the size of the actual figure.
+%
+%     The default 'FontMode' setting is 'scaled'.
+%
+%   Line Width Parameters:
+%     'LineMode'     one of the strings 'scaled', 'fixed'
+%     'LineWidth'    a positive scalar
+%     'DefaultFixedLineWidth' a positive scalar
+%     'LineWidthMin' a positive scalar
+%          specifies the minimum line width allowed after scaling
+%     'LineWidthMax' a positive scalar
+%          specifies the maximum line width allowed after scaling
+%     The semantics of 'Line' parameters are exactly the
+%     same as the corresponding 'Font' parameters, except that
+%     they apply to line widths instead of font sizes.
+%
+%   Style Map Parameter:
+%     'LineStyleMap'    one of [], 'bw', or a function name or handle
+%          specifies how to map line colors to styles. An empty
+%          style map means styles are not changed. The style map
+%          'bw' is a built-in mapping that maps lines with the same
+%          color to the same style and otherwise cycles through the
+%          available styles. A user-specified map is a function
+%          that takes as input a cell array of line objects and
+%          outputs a cell array of line style strings. The default
+%          map is [].
+%      
+%   Examples:
+%     exportfig(gcf,'fig1.eps','height',3);
+%       Exports the current figure to the file named 'fig1.eps' with
+%       a height of 3 inches (assuming the figure's PaperUnits is 
+%       inches) and an aspect ratio the same as the figure's aspect
+%       ratio on screen.
+%
+%     opts = struct('FontMode','fixed','FontSize',10,'height',3);
+%     exportfig(gcf, 'fig2.eps', opts, 'height', 5);
+%       Exports the current figure to 'fig2.eps' with all
+%       text in 10 point fonts and with height 5 inches.
+%
+%   See also PREVIEWFIG, APPLYTOFIG, RESTOREFIG, PRINT.
+
+%  Copyright 2000 Ben Hinkle
+%  Email bug reports and comments to bhinkle@mathworks.com
+
+if (nargin < 2)
+  error('Too few input arguments');
+end
+
+% exportfig(H, filename, [options,] ...)
+H = varargin{1};
+if ~LocalIsHG(H,'figure')
+  error('First argument must be a handle to a figure.');
+end
+filename = varargin{2};
+if ~ischar(filename)
+  error('Second argument must be a string.');
+end
+paramPairs = {varargin{3:end}};
+if nargin > 2
+  if isstruct(paramPairs{1})
+    pcell = LocalToCell(paramPairs{1});
+    paramPairs = {pcell{:}, paramPairs{2:end}};
+  end
+end
+verstr = version;
+majorver = str2num(verstr(1));
+defaults = [];
+if majorver > 5
+  if ispref('exportfig','defaults')
+    defaults = getpref('exportfig','defaults');
+  end
+elseif exist('getappdata')
+  defaults = getappdata(0,'exportfigdefaults');
+end
+if ~isempty(defaults)
+  dcell = LocalToCell(defaults);
+  paramPairs = {dcell{:}, paramPairs{:}};
+end
+
+% Do some validity checking on param-value pairs
+if (rem(length(paramPairs),2) ~= 0)
+  error(['Invalid input syntax. Optional parameters and values' ...
+	 ' must be in pairs.']);
+end
+
+auto.format = 'eps';
+auto.preview = 'none';
+auto.width = -1;
+auto.height = -1;
+auto.color = 'bw';
+auto.defaultfontsize=10;
+auto.fontsize = -1;
+auto.fontmode='scaled';
+auto.fontmin = 8;
+auto.fontmax = 60;
+auto.defaultlinewidth = 1.0;
+auto.linewidth = -1;
+auto.linemode=[];
+auto.linemin = 0.5;
+auto.linemax = 100;
+auto.fontencoding = 'latin1';
+auto.renderer = [];
+auto.resolution = [];
+auto.stylemap = [];
+auto.applystyle = 0;
+auto.refobj = -1;
+auto.bounds = 'tight';
+explicitbounds = 0;
+auto.lockaxes = 1;
+auto.separatetext = 0;
+opts = auto;
+
+% Process param-value pairs
+args = {};
+for k = 1:2:length(paramPairs)
+  param = lower(paramPairs{k});
+  if ~ischar(param)
+    error('Optional parameter names must be strings');
+  end
+  value = paramPairs{k+1};
+  
+  switch (param)
+   case 'format'
+    opts.format = LocalCheckAuto(lower(value),auto.format);
+    if strcmp(opts.format,'preview')
+      error(['Format ''preview'' no longer supported. Use PREVIEWFIG' ...
+	     ' instead.']);
+    end
+   case 'preview'
+    opts.preview = LocalCheckAuto(lower(value),auto.preview);
+    if ~strcmp(opts.preview,{'none','tiff'})
+      error('Preview must be ''none'' or ''tiff''.');
+    end
+   case 'width'
+    opts.width = LocalToNum(value, auto.width);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.width)
+	error('Width must be a numeric scalar > 0');
+      end
+    end
+   case 'height'
+    opts.height = LocalToNum(value, auto.height);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if(~LocalIsPositiveScalar(opts.height))
+	error('Height must be a numeric scalar > 0');
+      end
+    end
+   case 'color'
+    opts.color = LocalCheckAuto(lower(value),auto.color);
+    if ~strcmp(opts.color,{'bw','gray','rgb','cmyk'})
+      error('Color must be ''bw'', ''gray'',''rgb'' or ''cmyk''.');
+    end
+   case 'fontmode'
+    opts.fontmode = LocalCheckAuto(lower(value),auto.fontmode);
+    if ~strcmp(opts.fontmode,{'scaled','fixed'})
+      error('FontMode must be ''scaled'' or ''fixed''.');
+    end
+   case 'fontsize'
+    opts.fontsize = LocalToNum(value,auto.fontsize);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.fontsize)
+	error('FontSize must be a numeric scalar > 0');
+      end
+    end
+   case 'defaultfixedfontsize'
+    opts.defaultfontsize = LocalToNum(value,auto.defaultfontsize);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.defaultfontsize)
+	error('DefaultFixedFontSize must be a numeric scalar > 0');
+      end
+    end
+   case 'fontsizemin'
+    opts.fontmin = LocalToNum(value,auto.fontmin);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.fontmin)
+	error('FontSizeMin must be a numeric scalar > 0');
+      end
+    end
+   case 'fontsizemax'
+    opts.fontmax = LocalToNum(value,auto.fontmax);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.fontmax)
+	error('FontSizeMax must be a numeric scalar > 0');
+      end
+    end
+   case 'fontencoding'
+    opts.fontencoding = LocalCheckAuto(lower(value),auto.fontencoding);
+    if ~strcmp(opts.fontencoding,{'latin1','adobe'})
+      error('FontEncoding must be ''latin1'' or ''adobe''.');
+    end
+   case 'linemode'
+    opts.linemode = LocalCheckAuto(lower(value),auto.linemode);
+    if ~strcmp(opts.linemode,{'scaled','fixed'})
+      error('LineMode must be ''scaled'' or ''fixed''.');
+    end
+   case 'linewidth'
+    opts.linewidth = LocalToNum(value,auto.linewidth);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.linewidth)
+	error('LineWidth must be a numeric scalar > 0');
+      end
+    end
+   case 'defaultfixedlinewidth'
+    opts.defaultlinewidth = LocalToNum(value,auto.defaultlinewidth);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.defaultlinewidth)
+	error(['DefaultFixedLineWidth must be a numeric scalar >' ...
+	       ' 0']);
+      end
+    end
+   case 'linewidthmin'
+    opts.linemin = LocalToNum(value,auto.linemin);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.linemin)
+	error('LineWidthMin must be a numeric scalar > 0');
+      end
+    end
+   case 'linewidthmax'
+    opts.linemax = LocalToNum(value,auto.linemax);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.linemax)
+	error('LineWidthMax must be a numeric scalar > 0');
+      end
+    end
+   case 'linestylemap'
+    opts.stylemap = LocalCheckAuto(value,auto.stylemap);
+   case 'renderer'
+    opts.renderer = LocalCheckAuto(lower(value),auto.renderer);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~strcmp(opts.renderer,{'painters','zbuffer','opengl'})
+	error(['Renderer must be ''painters'', ''zbuffer'' or' ...
+	       ' ''opengl''.']);
+      end
+    end
+   case 'resolution'
+    opts.resolution = LocalToNum(value,auto.resolution);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~(isnumeric(value) & (prod(size(value)) == 1) & (value >= 0));
+	error('Resolution must be a numeric scalar >= 0');
+      end
+    end
+   case 'applystyle' % means to apply the options and not export
+    opts.applystyle = 1;
+   case 'reference'
+    if ischar(value)
+      if strcmp(value,'auto')
+	opts.refobj = auto.refobj;
+      else
+	opts.refobj = eval(value);
+      end
+    else
+      opts.refobj = value;
+    end
+    if ~LocalIsHG(opts.refobj,'axes')
+      error('Reference object must evaluate to an axes handle.');
+    end
+   case 'bounds'
+    opts.bounds = LocalCheckAuto(lower(value),auto.bounds);
+    explicitbounds = 1;
+    if ~strcmp(opts.bounds,{'tight','loose'})
+      error('Bounds must be ''tight'' or ''loose''.');
+    end
+   case 'lockaxes'
+    opts.lockaxes = LocalToNum(value,auto.lockaxes);
+   case 'separatetext'
+    opts.separatetext = LocalToNum(value,auto.separatetext);
+   otherwise
+    error(['Unrecognized option ' param '.']);
+  end
+end
+
+% make sure figure is up-to-date
+drawnow;
+
+allLines  = findall(H, 'type', 'line');
+allText   = findall(H, 'type', 'text');
+allAxes   = findall(H, 'type', 'axes');
+allImages = findall(H, 'type', 'image');
+allLights = findall(H, 'type', 'light');
+allPatch  = findall(H, 'type', 'patch');
+allSurf   = findall(H, 'type', 'surface');
+allRect   = findall(H, 'type', 'rectangle');
+allFont   = [allText; allAxes];
+allColor  = [allLines; allText; allAxes; allLights];
+allMarker = [allLines; allPatch; allSurf];
+allEdge   = [allPatch; allSurf];
+allCData  = [allImages; allPatch; allSurf];
+
+old.objs = {};
+old.prop = {};
+old.values = {};
+
+% Process format
+if strncmp(opts.format,'eps',3) & ~strcmp(opts.preview,'none')
+  args = {args{:}, ['-' opts.preview]};
+end
+
+hadError = 0;
+oldwarn = warning;
+try
+
+  % lock axes limits, ticks and labels if requested
+  if opts.lockaxes
+    old = LocalManualAxesMode(old, allAxes, 'TickMode');
+    old = LocalManualAxesMode(old, allAxes, 'TickLabelMode');
+    old = LocalManualAxesMode(old, allAxes, 'LimMode');
+  end  
+
+  % Process size parameters
+  figurePaperUnits = get(H, 'PaperUnits');
+  oldFigureUnits = get(H, 'Units');
+  oldFigPos = get(H,'Position');
+  set(H, 'Units', figurePaperUnits);
+  figPos = get(H,'Position');
+  refsize = figPos(3:4);
+  if opts.refobj ~= -1
+    oldUnits = get(opts.refobj, 'Units');
+    set(opts.refobj, 'Units', figurePaperUnits);
+    r = get(opts.refobj, 'Position');
+    refsize = r(3:4);
+    set(opts.refobj, 'Units', oldUnits);
+  end
+  aspectRatio = refsize(1)/refsize(2);
+  if (opts.width == -1) & (opts.height == -1)
+    opts.width = refsize(1);
+    opts.height = refsize(2);
+  elseif (opts.width == -1)
+    opts.width = opts.height * aspectRatio;
+  elseif (opts.height == -1)
+    opts.height = opts.width / aspectRatio;
+  end
+  wscale = opts.width/refsize(1);
+  hscale = opts.height/refsize(2);
+  sizescale = min(wscale,hscale);
+  old = LocalPushOldData(old,H,'PaperPositionMode', ...
+			 get(H,'PaperPositionMode'));
+  set(H, 'PaperPositionMode', 'auto');
+  newPos = [figPos(1) figPos(2)+figPos(4)*(1-hscale) ...
+	    wscale*figPos(3) hscale*figPos(4)];
+  set(H, 'Position', newPos);
+  set(H, 'Units', oldFigureUnits);
+  
+  % process line-style map
+  if ~isempty(opts.stylemap) & ~isempty(allLines)
+    oldlstyle = LocalGetAsCell(allLines,'LineStyle');
+    old = LocalPushOldData(old, allLines, {'LineStyle'}, ...
+			   oldlstyle);
+    newlstyle = oldlstyle;
+    if ischar(opts.stylemap) & strcmpi(opts.stylemap,'bw')
+      newlstyle = LocalMapColorToStyle(allLines);
+    else
+      try
+	newlstyle = feval(opts.stylemap,allLines);
+      catch
+	warning(['Skipping stylemap. ' lasterr]);
+      end
+    end
+    set(allLines,{'LineStyle'},newlstyle);
+  end
+
+  % Process rendering parameters
+  switch (opts.color)
+   case {'bw', 'gray'}
+    if ~strcmp(opts.color,'bw') & strncmp(opts.format,'eps',3)
+      opts.format = [opts.format 'c'];
+    end
+    args = {args{:}, ['-d' opts.format]};
+    
+    %compute and set gray colormap
+    oldcmap = get(H,'Colormap');
+    newgrays = 0.30*oldcmap(:,1) + 0.59*oldcmap(:,2) + 0.11*oldcmap(:,3);
+    newcmap = [newgrays newgrays newgrays];
+    old = LocalPushOldData(old, H, 'Colormap', oldcmap);
+    set(H, 'Colormap', newcmap);
+
+    %compute and set ColorSpec and CData properties
+    old = LocalUpdateColors(allColor, 'color', old);
+    old = LocalUpdateColors(allAxes, 'xcolor', old);
+    old = LocalUpdateColors(allAxes, 'ycolor', old);
+    old = LocalUpdateColors(allAxes, 'zcolor', old);
+    old = LocalUpdateColors(allMarker, 'MarkerEdgeColor', old);
+    old = LocalUpdateColors(allMarker, 'MarkerFaceColor', old);
+    old = LocalUpdateColors(allEdge, 'EdgeColor', old);
+    old = LocalUpdateColors(allEdge, 'FaceColor', old);
+    old = LocalUpdateColors(allCData, 'CData', old);
+    
+   case {'rgb','cmyk'}
+    if strncmp(opts.format,'eps',3)
+      opts.format = [opts.format 'c'];
+      args = {args{:}, ['-d' opts.format]};
+      if strcmp(opts.color,'cmyk')
+	args = {args{:}, '-cmyk'};
+      end
+    else
+      args = {args{:}, ['-d' opts.format]};
+    end
+   otherwise
+    error('Invalid Color parameter');
+  end
+  if (~isempty(opts.renderer))
+    args = {args{:}, ['-' opts.renderer]};
+  end
+  if (~isempty(opts.resolution)) | ~strncmp(opts.format,'eps',3)
+    if isempty(opts.resolution)
+      opts.resolution = 0;
+    end
+    args = {args{:}, ['-r' int2str(opts.resolution)]};
+  end
+
+  % Process font parameters
+  if ~isempty(opts.fontmode)
+    oldfonts = LocalGetAsCell(allFont,'FontSize');
+    oldfontunits = LocalGetAsCell(allFont,'FontUnits');
+    set(allFont,'FontUnits','points');
+    switch (opts.fontmode)
+     case 'fixed'
+      if (opts.fontsize == -1)
+	set(allFont,'FontSize',opts.defaultfontsize);
+      else
+	set(allFont,'FontSize',opts.fontsize);
+      end
+     case 'scaled'
+      if (opts.fontsize == -1)
+	scale = sizescale;
+      else
+	scale = opts.fontsize;
+      end
+      newfonts = LocalScale(oldfonts,scale,opts.fontmin,opts.fontmax);
+      set(allFont,{'FontSize'},newfonts);
+     otherwise
+      error('Invalid FontMode parameter');
+    end
+    old = LocalPushOldData(old, allFont, {'FontSize'}, oldfonts);
+    old = LocalPushOldData(old, allFont, {'FontUnits'}, oldfontunits);
+  end
+  if strcmp(opts.fontencoding,'adobe') & strncmp(opts.format,'eps',3)
+    args = {args{:}, '-adobecset'};
+  end
+
+  % Process line parameters
+  if ~isempty(opts.linemode)
+    oldlines = LocalGetAsCell(allMarker,'LineWidth');
+    old = LocalPushOldData(old, allMarker, {'LineWidth'}, oldlines);
+    switch (opts.linemode)
+     case 'fixed'
+      if (opts.linewidth == -1)
+	set(allMarker,'LineWidth',opts.defaultlinewidth);
+      else
+	set(allMarker,'LineWidth',opts.linewidth);
+      end
+     case 'scaled'
+      if (opts.linewidth == -1)
+	scale = sizescale;
+      else
+	scale = opts.linewidth;
+      end
+      newlines = LocalScale(oldlines, scale, opts.linemin, opts.linemax);
+      set(allMarker,{'LineWidth'},newlines);
+    end
+  end
+
+  % adjust figure bounds to surround axes
+  if strcmp(opts.bounds,'tight')
+    if (~strncmp(opts.format,'eps',3) & LocalHas3DPlot(allAxes)) | ...
+	  (strncmp(opts.format,'eps',3) & opts.separatetext)
+      if (explicitbounds == 1)
+	warning(['Cannot compute ''tight'' bounds. Using ''loose''' ...
+		 ' bounds.']);
+      end
+      opts.bounds = 'loose';
+    end
+  end
+  warning('off');
+  if ~isempty(allAxes)
+    if strncmp(opts.format,'eps',3)
+      if strcmp(opts.bounds,'loose')
+	args = {args{:}, '-loose'};
+      end
+      old = LocalPushOldData(old,H,'Position', oldFigPos);
+    elseif strcmp(opts.bounds,'tight')
+      oldaunits = LocalGetAsCell(allAxes,'Units');
+      oldapos = LocalGetAsCell(allAxes,'Position');
+      oldtunits = LocalGetAsCell(allText,'units');
+      oldtpos = LocalGetAsCell(allText,'Position');
+      set(allAxes,'units','points');
+      apos = LocalGetAsCell(allAxes,'Position');
+      oldunits = get(H,'Units');
+      set(H,'units','points');
+      origfr = get(H,'position');
+      fr = [];
+      for k=1:length(allAxes)
+	if ~strcmpi(get(allAxes(k),'Tag'),'legend')
+	  axesR = apos{k};
+	  r = LocalAxesTightBoundingBox(axesR, allAxes(k));
+	  r(1:2) = r(1:2) + axesR(1:2);
+	  fr = LocalUnionRect(fr,r);
+	end
+      end
+      if isempty(fr)
+	fr = [0 0 origfr(3:4)];
+      end
+      for k=1:length(allAxes)
+	ax = allAxes(k);
+	r = apos{k};
+	r(1:2) = r(1:2) - fr(1:2);
+	set(ax,'Position',r);
+      end
+      old = LocalPushOldData(old, allAxes, {'Position'}, oldapos);
+      old = LocalPushOldData(old, allText, {'Position'}, oldtpos);
+      old = LocalPushOldData(old, allText, {'Units'}, oldtunits);
+      old = LocalPushOldData(old, allAxes, {'Units'}, oldaunits);
+      old = LocalPushOldData(old, H, 'Position', oldFigPos);
+      old = LocalPushOldData(old, H, 'Units', oldFigureUnits);
+      r = [origfr(1) origfr(2)+origfr(4)-fr(4) fr(3:4)];
+      set(H,'Position',r);
+    else
+      args = {args{:}, '-loose'};
+      old = LocalPushOldData(old,H,'Position', oldFigPos);
+    end
+  end
+  
+  % Process text in a separate file if needed
+  if opts.separatetext & ~opts.applystyle
+    % First hide all text and export
+    oldtvis = LocalGetAsCell(allText,'visible');
+    set(allText,'visible','off');
+    oldax = LocalGetAsCell(allAxes,'XTickLabel',1);
+    olday = LocalGetAsCell(allAxes,'YTickLabel',1);
+    oldaz = LocalGetAsCell(allAxes,'ZTickLabel',1);
+    null = cell(length(oldax),1);
+    [null{:}] = deal([]);
+    set(allAxes,{'XTickLabel'},null);
+    set(allAxes,{'YTickLabel'},null);
+    set(allAxes,{'ZTickLabel'},null);
+    print(H, filename, args{:});
+    set(allText,{'Visible'},oldtvis);
+    set(allAxes,{'XTickLabel'},oldax);
+    set(allAxes,{'YTickLabel'},olday);
+    set(allAxes,{'ZTickLabel'},oldaz);
+    % Now hide all non-text and export as eps in painters
+    [path, name, ext] = fileparts(filename);
+    tfile = fullfile(path,[name '_t.eps']);
+    tfile2 = fullfile(path,[name '_t2.eps']);
+    foundRenderer = 0;
+    for k=1:length(args)
+      if strncmp('-d',args{k},2)
+	args{k} = '-deps';
+      elseif strncmp('-zbuffer',args{k},8) | ...
+	    strncmp('-opengl', args{k},6)
+	args{k} = '-painters';
+	foundRenderer = 1;
+      end
+    end
+    if ~foundRenderer
+      args = {args{:}, '-painters'};
+    end
+    allNonText = [allLines; allLights; allPatch; ...
+		  allImages; allSurf; allRect];
+    oldvis = LocalGetAsCell(allNonText,'visible');
+    oldc = LocalGetAsCell(allAxes,'color');
+    oldaxg = LocalGetAsCell(allAxes,'XGrid');
+    oldayg = LocalGetAsCell(allAxes,'YGrid');
+    oldazg = LocalGetAsCell(allAxes,'ZGrid');
+    [null{:}] = deal('off');
+    set(allAxes,{'XGrid'},null);
+    set(allAxes,{'YGrid'},null);
+    set(allAxes,{'ZGrid'},null);
+    set(allNonText,'Visible','off');
+    set(allAxes,'Color','none');
+    print(H, tfile2, args{:});
+    set(allNonText,{'Visible'},oldvis);
+    set(allAxes,{'Color'},oldc);
+    set(allAxes,{'XGrid'},oldaxg);
+    set(allAxes,{'YGrid'},oldayg);
+    set(allAxes,{'ZGrid'},oldazg);
+    %hack up the postscript file
+    fid1 = fopen(tfile,'w');
+    fid2 = fopen(tfile2,'r');
+    line = fgetl(fid2);
+    while ischar(line)
+      if strncmp(line,'%%Title',7)
+	fprintf(fid1,'%s\n',['%%Title: ', tfile]);
+      elseif (length(line) < 3) 
+	fprintf(fid1,'%s\n',line);
+      elseif ~strcmp(line(end-2:end),' PR') & ...
+	    ~strcmp(line(end-1:end),' L')
+	fprintf(fid1,'%s\n',line);
+      end
+      line = fgetl(fid2);
+    end
+    fclose(fid1);
+    fclose(fid2);
+    delete(tfile2);
+    
+  elseif ~opts.applystyle
+    drawnow;
+    print(H, filename, args{:});
+  end
+  warning(oldwarn);
+  
+catch
+  warning(oldwarn);
+  hadError = 1;
+end
+
+% Restore figure settings
+if opts.applystyle
+  varargout{1} = old;
+else
+  for n=1:length(old.objs)
+    if ~iscell(old.values{n}) & iscell(old.prop{n})
+      old.values{n} = {old.values{n}};
+    end
+    set(old.objs{n}, old.prop{n}, old.values{n});
+  end
+end
+
+if hadError
+  error(deblank(lasterr));
+end
+
+%
+%  Local Functions
+%
+
+function outData = LocalPushOldData(inData, objs, prop, values)
+outData.objs = {objs, inData.objs{:}};
+outData.prop = {prop, inData.prop{:}};
+outData.values = {values, inData.values{:}};
+
+function cellArray = LocalGetAsCell(fig,prop,allowemptycell);
+cellArray = get(fig,prop);
+if nargin < 3
+  allowemptycell = 0;
+end
+if ~iscell(cellArray) & (allowemptycell | ~isempty(cellArray))
+  cellArray = {cellArray};
+end
+
+function newArray = LocalScale(inArray, scale, minv, maxv)
+n = length(inArray);
+newArray = cell(n,1);
+for k=1:n
+  newArray{k} = min(maxv,max(minv,scale*inArray{k}(1)));
+end
+
+function gray = LocalMapToGray1(color)
+gray = color;
+if ischar(color)
+  switch color(1)
+   case 'y'
+    color = [1 1 0];
+   case 'm'
+    color = [1 0 1];
+   case 'c'
+    color = [0 1 1];
+   case 'r'
+    color = [1 0 0];
+   case 'g'
+    color = [0 1 0];
+   case 'b'
+    color = [0 0 1];
+   case 'w'
+    color = [1 1 1];
+   case 'k'
+    color = [0 0 0];
+  end
+end
+if ~ischar(color)
+  gray = 0.30*color(1) + 0.59*color(2) + 0.11*color(3);
+end
+
+function newArray = LocalMapToGray(inArray);
+n = length(inArray);
+newArray = cell(n,1);
+for k=1:n
+  color = inArray{k};
+  if ~isempty(color)
+    color = LocalMapToGray1(color);
+  end
+  if isempty(color) | ischar(color)
+    newArray{k} = color;
+  else
+    newArray{k} = [color color color];
+  end
+end
+
+function newArray = LocalMapColorToStyle(inArray);
+inArray = LocalGetAsCell(inArray,'Color');
+n = length(inArray);
+newArray = cell(n,1);
+styles = {'-','--',':','-.'};
+uniques = [];
+nstyles = length(styles);
+for k=1:n
+  gray = LocalMapToGray1(inArray{k});
+  if isempty(gray) | ischar(gray) | gray < .05
+    newArray{k} = '-';
+  else
+    if ~isempty(uniques) & any(gray == uniques)
+      ind = find(gray==uniques);
+    else
+      uniques = [uniques gray];
+      ind = length(uniques);
+    end
+    newArray{k} = styles{mod(ind-1,nstyles)+1};
+  end
+end
+
+function newArray = LocalMapCData(inArray);
+n = length(inArray);
+newArray = cell(n,1);
+for k=1:n
+  color = inArray{k};
+  if (ndims(color) == 3) & isa(color,'double')
+    gray = 0.30*color(:,:,1) + 0.59*color(:,:,2) + 0.11*color(:,:,3);
+    color(:,:,1) = gray;
+    color(:,:,2) = gray;
+    color(:,:,3) = gray;
+  end
+  newArray{k} = color;
+end
+
+function outData = LocalUpdateColors(inArray, prop, inData)
+value = LocalGetAsCell(inArray,prop);
+outData.objs = {inData.objs{:}, inArray};
+outData.prop = {inData.prop{:}, {prop}};
+outData.values = {inData.values{:}, value};
+if (~isempty(value))
+  if strcmp(prop,'CData') 
+    value = LocalMapCData(value);
+  else
+    value = LocalMapToGray(value);
+  end
+  set(inArray,{prop},value);
+end
+
+function bool = LocalIsPositiveScalar(value)
+bool = isnumeric(value) & ...
+       prod(size(value)) == 1 & ...
+       value > 0;
+
+function value = LocalToNum(value,auto)
+if ischar(value)
+  if strcmp(value,'auto')
+    value = auto;
+  else
+    value = str2num(value);
+  end
+end
+
+%convert a struct to {field1,val1,field2,val2,...}
+function c = LocalToCell(s)
+f = fieldnames(s);
+v = struct2cell(s);
+opts = cell(2,length(f));
+opts(1,:) = f;
+opts(2,:) = v;
+c = {opts{:}};
+
+function c = LocalIsHG(obj,hgtype)
+c = 0;
+if (length(obj) == 1) & ishandle(obj) 
+  c = strcmp(get(obj,'type'),hgtype);
+end
+
+function c = LocalHas3DPlot(a)
+zticks = LocalGetAsCell(a,'ZTickLabel');
+c = 0;
+for k=1:length(zticks)
+  if ~isempty(zticks{k})
+    c = 1;
+    return;
+  end
+end
+
+function r = LocalUnionRect(r1,r2)
+if isempty(r1)
+  r = r2;
+elseif isempty(r2)
+  r = r1;
+elseif max(r2(3:4)) > 0
+  left = min(r1(1),r2(1));
+  bot = min(r1(2),r2(2));
+  right = max(r1(1)+r1(3),r2(1)+r2(3));
+  top = max(r1(2)+r1(4),r2(2)+r2(4));
+  r = [left bot right-left top-bot];
+else
+  r = r1;
+end
+
+function c = LocalLabelsMatchTicks(labs,ticks)
+c = 0;
+try
+  t1 = num2str(ticks(1));
+  n = length(ticks);
+  tend = num2str(ticks(n));
+  c = strncmp(labs(1),t1,length(labs(1))) & ...
+      strncmp(labs(n),tend,length(labs(n)));
+end
+
+function r = LocalAxesTightBoundingBox(axesR, a)
+r = [];
+atext = findall(a,'type','text','visible','on');
+if ~isempty(atext)
+  set(atext,'units','points');
+  res=LocalGetAsCell(atext,'extent');
+  for n=1:length(atext)
+    r = LocalUnionRect(r,res{n});
+  end
+end
+if strcmp(get(a,'visible'),'on')
+  r = LocalUnionRect(r,[0 0 axesR(3:4)]);
+  oldunits = get(a,'fontunits');
+  set(a,'fontunits','points');
+  label = text(0,0,'','parent',a,...
+	       'units','points',...
+	       'fontsize',get(a,'fontsize'),...
+	       'fontname',get(a,'fontname'),...
+	       'fontweight',get(a,'fontweight'),...
+	       'fontangle',get(a,'fontangle'),...
+	       'visible','off');
+  fs = get(a,'fontsize');
+
+  % handle y axis tick labels
+  ry = [0 -fs/2 0 axesR(4)+fs];
+  ylabs = get(a,'yticklabels');
+  yticks = get(a,'ytick');
+  maxw = 0;
+  if ~isempty(ylabs)
+    for n=1:size(ylabs,1)
+      set(label,'string',ylabs(n,:));
+      ext = get(label,'extent');
+      maxw = max(maxw,ext(3));
+    end
+    if ~LocalLabelsMatchTicks(ylabs,yticks) & ...
+	  strcmp(get(a,'xaxislocation'),'bottom')
+      ry(4) = ry(4) + 1.5*ext(4);
+    end
+    if strcmp(get(a,'yaxislocation'),'left')
+      ry(1) = -(maxw+5);
+    else
+      ry(1) = axesR(3);
+    end
+    ry(3) = maxw+5;
+    r = LocalUnionRect(r,ry);
+  end
+
+  % handle x axis tick labels
+  rx = [0 0 0 fs+5];
+  xlabs = get(a,'xticklabels');
+  xticks = get(a,'xtick');
+  if ~isempty(xlabs)
+    if strcmp(get(a,'xaxislocation'),'bottom')
+      rx(2) = -(fs+5);
+      if ~LocalLabelsMatchTicks(xlabs,xticks);
+	rx(4) = rx(4) + 2*fs;
+	rx(2) = rx(2) - 2*fs;
+      end
+    else
+      rx(2) = axesR(4);
+      % exponent is still below axes
+      if ~LocalLabelsMatchTicks(xlabs,xticks);
+	rx(4) = rx(4) + axesR(4) + 2*fs;
+	rx(2) = -2*fs;
+      end
+    end
+    set(label,'string',xlabs(1,:));
+    ext1 = get(label,'extent');
+    rx(1) = -ext1(3)/2;
+    set(label,'string',xlabs(size(xlabs,1),:));
+    ext2 = get(label,'extent');
+    rx(3) = axesR(3) + (ext2(3) + ext1(3))/2;
+    r = LocalUnionRect(r,rx);
+  end
+  set(a,'fontunits',oldunits);
+  delete(label);
+end
+
+function c = LocalManualAxesMode(old, allAxes, base)
+xs = ['X' base];
+ys = ['Y' base];
+zs = ['Z' base];
+oldXMode = LocalGetAsCell(allAxes,xs);
+oldYMode = LocalGetAsCell(allAxes,ys);
+oldZMode = LocalGetAsCell(allAxes,zs);
+old = LocalPushOldData(old, allAxes, {xs}, oldXMode);
+old = LocalPushOldData(old, allAxes, {ys}, oldYMode);
+old = LocalPushOldData(old, allAxes, {zs}, oldZMode);
+set(allAxes,xs,'manual');
+set(allAxes,ys,'manual');
+set(allAxes,zs,'manual');
+c = old;
+
+function val = LocalCheckAuto(val, auto)
+if ischar(val) & strcmp(val,'auto')
+  val = auto;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/extend_domain_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function B = extend_domain_table(A, smalldom, smallsz, bigdom, bigsz)
+% EXTEND_DOMAIN_TABLE Expand an array so it has the desired size.
+% B = extend_domain_table(A, smalldom, smallsz, bigdom, bigsz)
+%
+% A is the array with domain smalldom and sizes smallsz.
+% bigdom is the desired domain, with sizes bigsz.
+%
+% Example:
+% smalldom = [1 3], smallsz = [2 4], bigdom = [1 2 3 4], bigsz = [2 1 4 5],
+% so B(i,j,k,l) = A(i,k) for i in 1:2, j in 1:1, k in 1:4, l in 1:5
+
+if isequal(size(A), [1 1]) % a scalar
+  B = A; % * myones(bigsz);
+  return;
+end
+
+map = find_equiv_posns(smalldom, bigdom);
+sz = ones(1, length(bigdom));
+sz(map) = smallsz;
+B = myreshape(A, sz); % add dimensions for the stuff not in A
+sz = bigsz;
+sz(map) = 1; % don't replicate along A's dimensions
+B = myrepmat(B, sz(:)');
+                           
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/factorial.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function x = factorial(n)
+% FACTORIAL Compute n!
+% x = factorial(n)
+
+if n == 0
+  x = 1;
+else
+  x = n*factorial(n-1);
+end    
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/filepartsLast.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function [last] = filepartsLast(fname)
+% filepartsLast Return the last part of a filename (strip off directory and suffix)
+% function filepartsLast(fname)
+%
+% Examples
+% filepartsLast('C:/foo/bar') = 'bar'
+% filepartsLast('C:/foo/bar.mat') = 'bar'
+% filepartsLast('C:/foo/bar.mat.gz') = 'bar.mat'
+% filepartsLast('bar.mat') = 'bar'
+
+[pathstr,name,ext,versn] = fileparts(fname);
+last = name;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/find_equiv_posns.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function p = find_equiv_posns(vsmall, vlarge)
+% FIND_EQUIV_POSNS p[i] = the place where vsmall[i] occurs in vlarge.
+% p = find_equiv_posns(vsmall, vlarge)
+% THE VECTORS ARE ASSUMED TO BE SORTED.
+%
+% e.g., vsmall=[2,8], vlarge=[2,7,8,4], p=[1,3]
+%
+% In R/S, this function is called 'match'
+ 
+%if ~mysubset(vsmall, vlarge)
+%  error('small domain must occur in large domain');
+%end
+
+if isempty(vsmall) | isempty(vlarge)
+  p = [];
+  return;
+end
+  
+bitvec = sparse(1, max(vlarge)); 
+%bitvec = zeros(1, max(vlarge));
+bitvec(vsmall) = 1;
+p = find(bitvec(vlarge));
+
+%p = find(ismember(vlarge, vsmall)); % slower
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/fullfileKPM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function f = fullfileKPM(varargin)
+% fullfileKPM Concatenate strings with file separator, then convert it to a/b/c
+% function f = fullfileKPM(varargin)
+
+f = fullfile(varargin{:});
+f = strrep(f, '\', '/');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/genpathKPM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+function p = genpathKPM(d)
+% genpathKPM Like built-in genpath, but omits directories whose name is 'Old', 'old' or 'CVS'
+% function p = genpathKPM(d)
+
+if nargin==0,
+  p = genpath(fullfile(matlabroot,'toolbox'));
+  if length(p) > 1, p(end) = []; end % Remove trailing pathsep
+  return
+end
+
+% initialise variables
+methodsep = '@';  % qualifier for overloaded method directories
+p = '';           % path to be returned
+
+% Generate path based on given root directory
+files = dir(d);
+if isempty(files)
+  return
+end
+
+% Add d to the path even if it is empty.
+p = [p d pathsep];
+
+% set logical vector for subdirectory entries in d
+isdir = logical(cat(1,files.isdir));
+%
+% Recursively descend through directories which are neither
+% private nor "class" directories.
+%
+dirs = files(isdir); % select only directory entries from the current listing
+
+for i=1:length(dirs)
+   dirname = dirs(i).name;
+   if    ~strcmp( dirname,'.')         & ...
+         ~strcmp( dirname,'..')        & ...
+         ~strncmp( dirname,methodsep,1)& ...
+         ~strcmp( dirname,'private') & ...
+	 ~strcmp( dirname, 'old') & ...      % KPM
+	 ~strcmp( dirname, 'Old') & ... % KPM
+     	 ~strcmp( dirname, 'CVS')            % KPM
+      p = [p genpathKPM(fullfile(d,dirname))]; % recursive calling of this function.
+   end
+end
+
+%------------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/hash_add.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function hash_add(key, val, fname)
+% HASH_ADD Append key,value pair to end of hashtable stored in a file
+% function hash_add(key, val, filename)
+%
+% See hash_lookup for an example
+
+if ~exist(fname, 'file')
+  % new hashtable
+  hashtable.key{1} = key;
+  hashtable.value{1} = val;
+else
+  %hashtable = importdata(fname);
+  %hashtable = load(fname, '-mat');
+  load(fname, '-mat');
+  Nentries = length(hashtable.key);
+  hashtable.key{Nentries+1} = key;
+  hashtable.value{Nentries+1} = val;
+end
+save(fname, 'hashtable', '-mat');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/hash_del.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function ndx = hash_del(key, fname)
+% HASH_DEL Remove all entries that match key  from hashtable stored in a file
+% ndx = hash_del(key, fname)
+%
+% Returns indices of matching entries (if any)
+% See hash_lookup for an example
+
+ndx = [];
+
+if ~exist(fname, 'file')
+  % new hashtable - no op
+else
+  %hashtable = importdata(fname);
+  %hashtable = load(fname, '-mat');
+  load(fname, '-mat');
+  Nentries = length(hashtable.key);
+  for i=1:Nentries
+    if isequal(hashtable.key{i}, key)
+      ndx = [ndx i];
+    end
+  end
+  hashtable.key(ndx) = [];
+  hashtable.value(ndx) = [];
+  save(fname, 'hashtable', '-mat');
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/hash_lookup.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,34 @@
+function [val, found, Nentries] = hash_lookup(key, fname)
+% HASH_LOOKUP Lookup a key in a hash table stored in a file using linear search
+% function [val, found, Nentries] = hash_lookup(key, filename)
+%
+% Example:
+% If htbl.mat does not exist,
+%   [val,found,N] = hash_lookup('foo', 'htbl')
+% returns found val = [], found = 0, N = 0
+%   hash_add('foo', 42, 'htbl')
+%   hash_add('bar', [1:10], 'htbl')
+%   [val,found,N] = hash_lookup('foo', 'htbl')
+% now returns val = 42, found = 1, N = 2
+%
+% Type 'delete htbl' to delete the file/ reset the hashtable
+
+
+val = [];
+found = 0;
+
+if exist(fname, 'file')==0
+  % new hashtable
+  Nentries = 0;
+else
+  %hashtable = importdata(fname);
+  load(fname);
+  Nentries = length(hashtable.key);
+  for i=1:Nentries
+    if isequal(hashtable.key{i}, key)
+      val = hashtable.value{i};
+      found = 1;
+      break;
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/hsvKPM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function colors = hsvKPM(N)
+% hsvKPM Like built-in HSV, except it randomizes the order, so that adjacent colors are dis-similar
+% function colors = hsvKPM(N)
+
+colors = hsv(N);
+perm = randperm(N);
+colors = colors(perm,:);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/hungarian.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,464 @@
+function [C,T]=hungarian(A)
+%HUNGARIAN Solve the Assignment problem using the Hungarian method.
+%
+%[C,T]=hungarian(A)
+%A - a square cost matrix.
+%C - the optimal assignment.
+%T - the cost of the optimal assignment.
+
+% Adapted from the FORTRAN IV code in Carpaneto and Toth, "Algorithm 548:
+% Solution of the assignment problem [H]", ACM Transactions on
+% Mathematical Software, 6(1):104-111, 1980.
+
+% v1.0  96-06-14. Niclas Borlin, niclas@cs.umu.se.
+%                 Department of Computing Science, Umeå University,
+%                 Sweden. 
+%                 All standard disclaimers apply.
+
+% A substantial effort was put into this code. If you use it for a
+% publication or otherwise, please include an acknowledgement or at least
+% notify me by email. /Niclas
+
+[m,n]=size(A);
+
+if (m~=n)
+    error('HUNGARIAN: Cost matrix must be square!');
+end
+
+% Save original cost matrix.
+orig=A;
+
+% Reduce matrix.
+A=hminired(A);
+
+% Do an initial assignment.
+[A,C,U]=hminiass(A);
+
+% Repeat while we have unassigned rows.
+while (U(n+1))
+    % Start with no path, no unchecked zeros, and no unexplored rows.
+    LR=zeros(1,n);
+    LC=zeros(1,n);
+    CH=zeros(1,n);
+    RH=[zeros(1,n) -1];
+    
+    % No labelled columns.
+    SLC=[];
+    
+    % Start path in first unassigned row.
+    r=U(n+1);
+    % Mark row with end-of-path label.
+    LR(r)=-1;
+    % Insert row first in labelled row set.
+    SLR=r;
+    
+    % Repeat until we manage to find an assignable zero.
+    while (1)
+        % If there are free zeros in row r
+        if (A(r,n+1)~=0)
+            % ...get column of first free zero.
+            l=-A(r,n+1);
+            
+            % If there are more free zeros in row r and row r in not
+            % yet marked as unexplored..
+            if (A(r,l)~=0 & RH(r)==0)
+                % Insert row r first in unexplored list.
+                RH(r)=RH(n+1);
+                RH(n+1)=r;
+                
+                % Mark in which column the next unexplored zero in this row
+                % is.
+                CH(r)=-A(r,l);
+            end
+        else
+            % If all rows are explored..
+            if (RH(n+1)<=0)
+                % Reduce matrix.
+                [A,CH,RH]=hmreduce(A,CH,RH,LC,LR,SLC,SLR);
+            end
+            
+            % Re-start with first unexplored row.
+            r=RH(n+1);
+            % Get column of next free zero in row r.
+            l=CH(r);
+            % Advance "column of next free zero".
+            CH(r)=-A(r,l);
+            % If this zero is last in the list..
+            if (A(r,l)==0)
+                % ...remove row r from unexplored list.
+                RH(n+1)=RH(r);
+                RH(r)=0;
+            end
+        end
+        
+        % While the column l is labelled, i.e. in path.
+        while (LC(l)~=0)
+            % If row r is explored..
+            if (RH(r)==0)
+                % If all rows are explored..
+                if (RH(n+1)<=0)
+                    % Reduce cost matrix.
+                    [A,CH,RH]=hmreduce(A,CH,RH,LC,LR,SLC,SLR);
+                end
+                
+                % Re-start with first unexplored row.
+                r=RH(n+1);
+            end
+            
+            % Get column of next free zero in row r.
+            l=CH(r);
+            
+            % Advance "column of next free zero".
+            CH(r)=-A(r,l);
+            
+            % If this zero is last in list..
+            if(A(r,l)==0)
+                % ...remove row r from unexplored list.
+                RH(n+1)=RH(r);
+                RH(r)=0;
+            end
+        end
+        
+        % If the column found is unassigned..
+        if (C(l)==0)
+            % Flip all zeros along the path in LR,LC.
+            [A,C,U]=hmflip(A,C,LC,LR,U,l,r);
+            % ...and exit to continue with next unassigned row.
+            break;
+        else
+            % ...else add zero to path.
+            
+            % Label column l with row r.
+            LC(l)=r;
+            
+            % Add l to the set of labelled columns.
+            SLC=[SLC l];
+            
+            % Continue with the row assigned to column l.
+            r=C(l);
+            
+            % Label row r with column l.
+            LR(r)=l;
+            
+            % Add r to the set of labelled rows.
+            SLR=[SLR r];
+        end
+    end
+end
+
+% Calculate the total cost.
+T=sum(orig(logical(sparse(C,1:size(orig,2),1))));
+
+
+function A=hminired(A)
+%HMINIRED Initial reduction of cost matrix for the Hungarian method.
+%
+%B=assredin(A)
+%A - the unreduced cost matris.
+%B - the reduced cost matrix with linked zeros in each row.
+
+% v1.0  96-06-13. Niclas Borlin, niclas@cs.umu.se.
+
+[m,n]=size(A);
+
+% Subtract column-minimum values from each column.
+colMin=min(A);
+A=A-colMin(ones(n,1),:);
+
+% Subtract row-minimum values from each row.
+rowMin=min(A')';
+A=A-rowMin(:,ones(1,n));
+
+% Get positions of all zeros.
+[i,j]=find(A==0);
+
+% Extend A to give room for row zero list header column.
+A(1,n+1)=0;
+for k=1:n
+    % Get all column in this row. 
+    cols=j(k==i)';
+    % Insert pointers in matrix.
+    A(k,[n+1 cols])=[-cols 0];
+end
+
+
+function [A,C,U]=hminiass(A)
+%HMINIASS Initial assignment of the Hungarian method.
+%
+%[B,C,U]=hminiass(A)
+%A - the reduced cost matrix.
+%B - the reduced cost matrix, with assigned zeros removed from lists.
+%C - a vector. C(J)=I means row I is assigned to column J,
+%              i.e. there is an assigned zero in position I,J.
+%U - a vector with a linked list of unassigned rows.
+
+% v1.0  96-06-14. Niclas Borlin, niclas@cs.umu.se.
+
+[n,np1]=size(A);
+
+% Initalize return vectors.
+C=zeros(1,n);
+U=zeros(1,n+1);
+
+% Initialize last/next zero "pointers".
+LZ=zeros(1,n);
+NZ=zeros(1,n);
+
+for i=1:n
+    % Set j to first unassigned zero in row i.
+	lj=n+1;
+	j=-A(i,lj);
+
+    % Repeat until we have no more zeros (j==0) or we find a zero
+	% in an unassigned column (c(j)==0).
+    
+	while (C(j)~=0)
+		% Advance lj and j in zero list.
+		lj=j;
+		j=-A(i,lj);
+	
+		% Stop if we hit end of list.
+		if (j==0)
+			break;
+		end
+	end
+
+	if (j~=0)
+		% We found a zero in an unassigned column.
+		
+		% Assign row i to column j.
+		C(j)=i;
+		
+		% Remove A(i,j) from unassigned zero list.
+		A(i,lj)=A(i,j);
+
+		% Update next/last unassigned zero pointers.
+		NZ(i)=-A(i,j);
+		LZ(i)=lj;
+
+		% Indicate A(i,j) is an assigned zero.
+		A(i,j)=0;
+	else
+		% We found no zero in an unassigned column.
+
+		% Check all zeros in this row.
+
+		lj=n+1;
+		j=-A(i,lj);
+		
+		% Check all zeros in this row for a suitable zero in another row.
+		while (j~=0)
+			% Check the in the row assigned to this column.
+			r=C(j);
+			
+			% Pick up last/next pointers.
+			lm=LZ(r);
+			m=NZ(r);
+			
+			% Check all unchecked zeros in free list of this row.
+			while (m~=0)
+				% Stop if we find an unassigned column.
+				if (C(m)==0)
+					break;
+				end
+				
+				% Advance one step in list.
+				lm=m;
+				m=-A(r,lm);
+			end
+			
+			if (m==0)
+				% We failed on row r. Continue with next zero on row i.
+				lj=j;
+				j=-A(i,lj);
+			else
+				% We found a zero in an unassigned column.
+			
+				% Replace zero at (r,m) in unassigned list with zero at (r,j)
+				A(r,lm)=-j;
+				A(r,j)=A(r,m);
+			
+				% Update last/next pointers in row r.
+				NZ(r)=-A(r,m);
+				LZ(r)=j;
+			
+				% Mark A(r,m) as an assigned zero in the matrix . . .
+				A(r,m)=0;
+			
+				% ...and in the assignment vector.
+				C(m)=r;
+			
+				% Remove A(i,j) from unassigned list.
+				A(i,lj)=A(i,j);
+			
+				% Update last/next pointers in row r.
+				NZ(i)=-A(i,j);
+				LZ(i)=lj;
+			
+				% Mark A(r,m) as an assigned zero in the matrix . . .
+				A(i,j)=0;
+			
+				% ...and in the assignment vector.
+				C(j)=i;
+				
+				% Stop search.
+				break;
+			end
+		end
+	end
+end
+
+% Create vector with list of unassigned rows.
+
+% Mark all rows have assignment.
+r=zeros(1,n);
+rows=C(C~=0);
+r(rows)=rows;
+empty=find(r==0);
+
+% Create vector with linked list of unassigned rows.
+U=zeros(1,n+1);
+U([n+1 empty])=[empty 0];
+
+
+function [A,C,U]=hmflip(A,C,LC,LR,U,l,r)
+%HMFLIP Flip assignment state of all zeros along a path.
+%
+%[A,C,U]=hmflip(A,C,LC,LR,U,l,r)
+%Input:
+%A   - the cost matrix.
+%C   - the assignment vector.
+%LC  - the column label vector.
+%LR  - the row label vector.
+%U   - the 
+%r,l - position of last zero in path.
+%Output:
+%A   - updated cost matrix.
+%C   - updated assignment vector.
+%U   - updated unassigned row list vector.
+
+% v1.0  96-06-14. Niclas Borlin, niclas@cs.umu.se.
+
+n=size(A,1);
+
+while (1)
+    % Move assignment in column l to row r.
+    C(l)=r;
+    
+    % Find zero to be removed from zero list..
+    
+    % Find zero before this.
+    m=find(A(r,:)==-l);
+    
+    % Link past this zero.
+    A(r,m)=A(r,l);
+    
+    A(r,l)=0;
+    
+    % If this was the first zero of the path..
+    if (LR(r)<0)
+        ...remove row from unassigned row list and return.
+        U(n+1)=U(r);
+        U(r)=0;
+        return;
+    else
+        
+        % Move back in this row along the path and get column of next zero.
+        l=LR(r);
+        
+        % Insert zero at (r,l) first in zero list.
+        A(r,l)=A(r,n+1);
+        A(r,n+1)=-l;
+        
+        % Continue back along the column to get row of next zero in path.
+        r=LC(l);
+    end
+end
+
+
+function [A,CH,RH]=hmreduce(A,CH,RH,LC,LR,SLC,SLR)
+%HMREDUCE Reduce parts of cost matrix in the Hungerian method.
+%
+%[A,CH,RH]=hmreduce(A,CH,RH,LC,LR,SLC,SLR)
+%Input:
+%A   - Cost matrix.
+%CH  - vector of column of 'next zeros' in each row.
+%RH  - vector with list of unexplored rows.
+%LC  - column labels.
+%RC  - row labels.
+%SLC - set of column labels.
+%SLR - set of row labels.
+%
+%Output:
+%A   - Reduced cost matrix.
+%CH  - Updated vector of 'next zeros' in each row.
+%RH  - Updated vector of unexplored rows.
+
+% v1.0  96-06-14. Niclas Borlin, niclas@cs.umu.se.
+
+n=size(A,1);
+
+% Find which rows are covered, i.e. unlabelled.
+coveredRows=LR==0;
+
+% Find which columns are covered, i.e. labelled.
+coveredCols=LC~=0;
+
+r=find(~coveredRows);
+c=find(~coveredCols);
+
+% Get minimum of uncovered elements.
+m=min(min(A(r,c)));
+
+% Subtract minimum from all uncovered elements.
+A(r,c)=A(r,c)-m;
+
+% Check all uncovered columns..
+for j=c
+    % ...and uncovered rows in path order..
+    for i=SLR
+        % If this is a (new) zero..
+        if (A(i,j)==0)
+            % If the row is not in unexplored list..
+            if (RH(i)==0)
+                % ...insert it first in unexplored list.
+                RH(i)=RH(n+1);
+                RH(n+1)=i;
+                % Mark this zero as "next free" in this row.
+                CH(i)=j;
+            end
+            % Find last unassigned zero on row I.
+            row=A(i,:);
+            colsInList=-row(row<0);
+            if (length(colsInList)==0)
+                % No zeros in the list.
+                l=n+1;
+            else
+                l=colsInList(row(colsInList)==0);
+            end
+            % Append this zero to end of list.
+            A(i,l)=-j;
+        end
+    end
+end
+
+% Add minimum to all doubly covered elements.
+r=find(coveredRows);
+c=find(coveredCols);
+
+% Take care of the zeros we will remove.
+[i,j]=find(A(r,c)<=0);
+
+i=r(i);
+j=c(j);
+
+for k=1:length(i)
+    % Find zero before this in this row.
+    lj=find(A(i(k),:)==-j(k));
+    % Link past it.
+    A(i(k),lj)=A(i(k),j(k));
+    % Mark it as assigned.
+    A(i(k),j(k))=0;
+end
+
+A(r,c)=A(r,c)+m;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/image_rgb.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+function image_rgb(M)
+% Show a matrix of integers as a color image.
+% This is like imagesc, except we know what the mapping is from integer to color.
+% If entries of M contain integers in {1,2,3}, we map
+% this to red/green/blue 
+
+cmap = [1 0 0; % red
+	0 1 0; % green
+	0 0 1; % blue
+	127/255 1 212/255]; % aquamarine
+image(M)
+set(gcf,'colormap', cmap);
+
+if 1
+  % make dummy handles, one per object type, for the legend
+  str = {};
+  for i=1:size(cmap,1)
+    dummy_handle(i) = line([0 0.1], [0 0.1]);
+    set(dummy_handle(i), 'color', cmap(i,:));
+    set(dummy_handle(i), 'linewidth', 2);
+    str{i} = num2str(i);
+  end
+  legend(dummy_handle, str, -1);
+end
+
+if 0
+[nrows ncols] = size(M);
+img = zeros(nrows, ncols, 3);
+for r=1:nrows
+  for c=1:ncols
+    q = M(r,c);
+    img(r,c,q) = 1;
+  end
+end
+image(img)
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/imresizeAspect.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,44 @@
+function img = imresizeAspect(img, maxSize)
+% function img = imresizeAspect(img, maxSize)
+% If image is larger than max size, reduce size, preserving aspect ratio of input.
+%
+% If size(input) = [y x] and maxSize = [yy xx],
+% then size(output) is given by the following (where a=y/x)
+%  if y<yy & x<xx  then [y x] 
+%  else if a<1 then [a*xx xx] 
+%  else [yy yy/a] 
+
+% For why we use bilinear,
+% See http://nickyguides.digital-digest.com/bilinear-vs-bicubic.htm
+
+if isempty(maxSize), return; end
+
+[y x c] = size(img);
+a= y/x;
+yy = maxSize(1); xx = maxSize(2); 
+if y <= yy & x <= xx
+  % no-op
+else
+  if a < 1
+    img = imresize(img, ceil([a*xx xx]), 'bilinear');
+  else
+    img = imresize(img, ceil([yy yy/a]), 'bilinear');
+  end
+  fprintf('resizing from %dx%d to %dx%d\n', y, x, size(img,1), size(img,2));
+end
+
+
+%test
+if 0
+  maxSize = [240 320];
+  %img = imread('C:\Images\Wearables\web_static_office\8.jpg'); 
+  %img = imread('C:\Images\Wearables\web_static_office\billandkirsten.jpg'); 
+  %img = imread('C:\Images\Wearables\web_static_street_april\p5.jpg'); 
+  img = imread('C:\Images\Wearables\Database_static_street\art11.jpg'); 
+  img2 = imresizeAspect(img, maxSize);
+  figure(1); clf; imshow(img)
+  figure(2); clf; imshow(img2)
+  fprintf('%dx%d (%5.3f) to %dx%d (%5.3f)\n', ...
+	  size(img,1), size(img,2), size(img,1)/size(img,2), ...
+	  size(img2,1), size(img2,2), size(img2,1)/size(img2,2));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/ind2subv.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function sub = ind2subv(siz,index)
+%IND2SUBV   Subscript vector from linear index.
+% IND2SUBV(SIZ,IND) returns a vector of the equivalent subscript values 
+% corresponding to a single index into an array of size SIZ.
+% If IND is a vector, then the result is a matrix, with subscript vectors
+% as rows.
+
+%sub = ind2subvTest(siz, index);
+n = length(siz);
+if n==0, sub = index; return; end % added by KPM 17 Nov 07
+cum_size = cumprod(siz(:)');
+prev_cum_size = [1 cum_size(1:end-1)];
+index = index(:) - 1;
+sub = rem(repmat(index,1,n),repmat(cum_size,length(index),1));
+sub = floor(sub ./ repmat(prev_cum_size,length(index),1))+1;
+
+% slow way
+%for dim = n:-1:1
+%  sub(:,dim) = floor(index/cum_size(dim))+1;
+%  index = rem(index,cum_size(dim));
+%end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/ind2subvKPM.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,176 @@
+/* C mex version of ind2subv.m in misc directory */
+/* 2 input, 1 output         */
+/* siz, ndx                  */
+/* sub                       */
+
+#include "mex.h"
+#include <math.h>
+
+void rbinary(int num, int n, double *rbits){
+	int i, mask;
+	num = num - 1;
+
+	mask = 1 << (n-1); /* mask = 00100...0 , where the 1 is in column n (rightmost = col 1) */
+	for (i = 0; i < n; i++) {
+		rbits[n-i-1] = ((num & mask) == 0) ? 1 : 2;
+		num <<= 1;
+	}
+}
+
+void ind_subv(int num, const double *sizes, int n, double *rbits){
+	int i;
+	int *cumprod;
+
+	cumprod  = malloc(n * sizeof(int));
+	num = num - 1;
+	cumprod[0] = 1;
+	for (i = 0; i < n-1; i++)
+	cumprod[i+1] = cumprod[i] * (int)sizes[i];
+	for (i = n-1; i >= 0; i--) {
+		rbits[i] = ((int)floor(num / cumprod[i])) + 1;
+		num = num % cumprod[i];
+	}
+	free(cumprod);
+}
+
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int    i, j, k, nCol, nRow, nnRow, binary, count, temp, temp1, start;
+	double *pSize, *pNdx, *pr;
+	double ndx;
+	int    *subv, *cumprod, *templai;
+
+	pSize = mxGetPr(prhs[0]);
+	pNdx = mxGetPr(prhs[1]);
+	nCol = mxGetNumberOfElements(prhs[0]);
+	nnRow = mxGetNumberOfElements(prhs[1]);
+
+	nRow = 1;
+	for(i=0; i<nCol; i++){
+		nRow *= (int)pSize[i];
+	}
+
+	if(nCol == 0){
+		plhs[0] = mxDuplicateArray(prhs[1]);
+		return;
+	}
+
+	binary = 2;
+	for (i = 0; i < nCol; i++){
+		if (pSize[i] > 2.0){
+			binary = 0;
+			break;
+		}
+		else if((int)pSize[i] == 1){
+			binary = 1;
+		}
+	}
+
+	if(nnRow == 1){
+		ndx = mxGetScalar(prhs[1]);
+		plhs[0] = mxCreateDoubleMatrix(1, nCol, mxREAL);
+		pr = mxGetPr(plhs[0]);
+		if(binary == 2)rbinary((int)ndx, nCol, pr);
+		else ind_subv((int)ndx, pSize, nCol, pr);
+		return;
+	}
+
+	plhs[0] = mxCreateDoubleMatrix(nnRow, nCol, mxREAL);
+	pr = mxGetPr(plhs[0]);
+
+	subv = malloc(nRow * nCol * sizeof(int));
+
+	if (binary == 2) {
+		for(j=0; j<nCol; j++){
+			temp = (1 << j);
+			temp1 = j * nRow;
+			for(i=0; i<nRow; i++){
+				subv[temp1 + i] = ((i & temp) == 0) ? 1 : 2;
+			}
+		}
+	}
+	else if(binary == 1){
+		cumprod = (int *)malloc(nCol * sizeof(int));
+		templai = (int *)malloc(nCol * sizeof(int));
+		cumprod[0] = 1;
+		templai[0] = nRow;
+		for(i=1; i<nCol; i++){
+			k = (int)pSize[i-1] - 1;
+			cumprod[i] = cumprod[i-1] << k;
+			templai[i] = templai[i-1] >> k;
+		}
+		for(j=0; j<nCol; j++){
+			temp1 = j * nRow;
+			if(pSize[j] == 1.0){
+				for(i=0; i<nRow; i++){
+					subv[temp1 + i] = 1;
+				}
+			}
+			else{
+				temp = 1;
+				count = 0;
+				for(i=0; i<templai[j]; i++){
+					if(temp > 2) temp = 1;
+					for(k=0; k<cumprod[j]; k++){
+						subv[temp1 + count] = temp;
+                        count++;
+					}
+					temp++;
+				}
+			}
+		}
+		free(templai);
+		free(cumprod);
+	}
+	else {
+		cumprod = (int *)malloc(nCol * sizeof(int));
+		templai = (int *)malloc(nCol * sizeof(int));
+		cumprod[0] = 1;
+		for(i=1; i<nCol; i++){
+			cumprod[i] = (int)(cumprod[i-1] * pSize[i-1]);
+		}
+		templai[0] = nRow;
+		for(i=1; i<nCol; i++){
+			templai[i] = nRow / cumprod[i];
+		}
+		for(j=0; j<nCol; j++){
+			temp1 = j * nRow;
+			if(pSize[j] == 1.0){
+				for(i=0; i<nRow; i++){
+					subv[temp1 + i] = 1;
+				}
+			}
+			else{
+				temp = 1;
+				count = 0;
+				for(i=0; i<templai[j]; i++){
+					if(temp > (int)pSize[j]) temp = 1;
+					for(k=0; k<cumprod[j]; k++){
+						subv[temp1 + count] = temp;
+						count++;
+					}
+					temp++;
+				}
+			}
+		}
+		free(cumprod);
+		free(templai);
+	}
+
+	count = 0;
+	for(j=0; j<nCol; j++){
+		temp1 = j * nRow;
+		for(i=0; i<nnRow; i++){
+			start = (int)pNdx[i] - 1;
+			pr[count] = subv[temp1 + start];
+			count++;
+		}
+	}
+	free(subv);
+}
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/ind2subvKPM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+function sub = ind2subvKPM(siz, ndx)
+% IND2SUBV Like the built-in ind2sub, but returns the answer as a row vector.
+% sub = ind2subv(siz, ndx)
+%
+% siz and ndx can be row or column vectors.
+% sub will be of size length(ndx) * length(siz).
+%
+% Example
+% ind2subv([2 2 2], 1:8) returns
+%  [1 1 1
+%   2 1 1
+%   ...
+%   2 2 2]
+% That is, the leftmost digit toggle fastest.
+%
+% See also SUBV2IND
+
+n = length(siz);
+
+
+if  n==0
+  sub = ndx;
+  return;
+end  
+
+if all(siz==2)
+  sub = dec2bitv(ndx-1, n);
+  sub = sub(:,n:-1:1)+1;
+  return;
+end
+
+cp = [1 cumprod(siz(:)')];
+ndx = ndx(:) - 1;
+sub = zeros(length(ndx), n);
+for i = n:-1:1 % i'th digit
+  sub(:,i) = floor(ndx/cp(i))+1;
+  ndx = rem(ndx,cp(i));
+end
+
+
+
+%%%%%%%%%%
+
+function bits = dec2bitv(d,n)
+% DEC2BITV Convert a decimal integer to a bit vector.
+% bits = dec2bitv(d,n) is just like the built-in dec2bin, except the answer is a vector, not a string.
+% n is an optional minimum length on the bit vector.
+% If d is a vector,  each row of the output array will be a bit vector.
+
+
+if (nargin<2)
+  n=1; % Need at least one digit even for 0.
+end
+d = d(:);
+
+[f,e]=log2(max(d)); % How many digits do we need to represent the numbers?
+bits=rem(floor(d*pow2(1-max(n,e):0)),2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/ind2subvMinka.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+function sub = ind2subvMinka(siz,index)
+%IND2SUBV   Subscript vector from linear index.
+% IND2SUBV(SIZ,IND) returns a vector of the equivalent subscript values 
+% corresponding to a single index into an array of size SIZ.
+% If IND is a vector, then the result is a matrix, with subscript vectors
+% as rows.
+
+% Written by Tom Minka
+% (c) Microsoft Corporation. All rights reserved.
+
+n = length(siz);
+if n==0, sub = index; return; end % added by KPM 17 Nov 07
+cum_size = cumprod(siz(:)');
+prev_cum_size = [1 cum_size(1:end-1)];
+index = index(:) - 1;
+sub = rem(repmat(index,1,n),repmat(cum_size,length(index),1));
+sub = floor(sub ./ repmat(prev_cum_size,length(index),1))+1;
+
+% slow way
+%for dim = n:-1:1
+%  sub(:,dim) = floor(index/cum_size(dim))+1;
+%  index = rem(index,cum_size(dim));
+%end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/ind2subvTest.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function sub = ind2subvTest(siz,index)
+%IND2SUBV   Subscript vector from linear index.
+% IND2SUBV(SIZ,IND) returns a vector of the equivalent subscript values 
+% corresponding to a single index into an array of size SIZ.
+% If IND is a vector, then the result is a matrix, with subscript vectors
+% as rows.
+
+sub = ind2subvMinka(siz, index);
+subKPM = ind2subvKPM(siz, index);
+assert(isequal(sub, subKPM))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/initFigures.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,48 @@
+% initFigures
+% Position 6 figures on the edges of the screen.
+% [xmin ymin w h] where (0,0) = bottom left
+% Numbers assume screen resolution is 1024 x 1280
+
+global FIGNUM NUMFIGS
+FIGNUM = 1; NUMFIGS = 6;
+
+screenMain = true; % set to false if initializing figures for second screen
+%screenMain = false;
+
+if screenMain
+  xoff = 0; 
+else
+  %xoff = 1280;
+  xoff = -1280;
+end
+
+% 2 x 3 design
+w = 400; h = 300;
+xs = [10 450 875] + xoff;
+ys = [650 40];
+
+if 0
+% 3x3 design
+w = 350; h = 250;
+xs = [10 380 750]+xoff;
+ys = [700 350 10];
+end
+
+
+Nfigs = length(xs)*length(ys);
+if screenMain
+  fig = 1; 
+else
+  fig = Nfigs + 1;
+end
+
+for yi=1:length(ys)
+  for xi=1:length(xs)
+    figure(fig);
+    set(gcf, 'position', [xs(xi) ys(yi) w h]);
+    fig = fig + 1;
+  end
+end
+
+% To plot something on the next available figure (with wrap around), use
+% sfigure(FIGNUM); clf; FIGNUM = wrap(FIGNUM+1, NUMFIGS); 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/installC_KPMtools.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+mex ind2subv.c
+mex subv2ind.c
+mex normalise.c
+mex -c mexutil.c
+if ~isunix 
+  mex repmatC.c mexutil.obj
+else
+  mex repmatC.c mexutil.o
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/is_psd.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function b = positive_semidefinite(M)
+%
+% Return true iff v M v' >= 0 for any vector v.
+% We do this by checking that all the eigenvalues are non-negative.
+
+E = eig(M);
+if length(find(E>=0)) == length(E)
+  b = 1;
+else
+  b = 0;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/is_stochastic.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function p = is_stochastic(T)
+% IS_STOCHASTIC Is the argument a stochastic matrix, i.e., the sum over the last dimension is 1.
+% p = is_stochastic(T)
+
+p = approxeq(T, mk_stochastic(T));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/isemptycell.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function E = isemptycell(C)
+% ISEMPTYCELL Apply the isempty function to each element of a cell array
+% E = isemptycell(C)
+%
+% This is equivalent to E = cellfun('isempty', C),
+% where cellfun is a function built-in to matlab version 5.3 or newer.
+
+if 0 % all(version('-release') >= 12)
+  E = cellfun('isempty', C);
+else
+  E = zeros(size(C));
+  for i=1:prod(size(C))
+    E(i) = isempty(C{i});
+  end
+  E = logical(E);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/isequalKPM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function p = isequalKPM(a,b)
+
+if isempty(a) & isempty(b)
+  p = 1;
+else
+  p = isequal(a,b);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/isposdef.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function b = isposdef(a)
+% ISPOSDEF   Test for positive definite matrix.
+%    ISPOSDEF(A) returns 1 if A is positive definite, 0 otherwise.
+%    Using chol is much more efficient than computing eigenvectors.
+
+%  From Tom Minka's lightspeed toolbox
+
+[R,p] = chol(a);
+b = (p == 0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/isscalar.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function p = isscalar(v)
+% ISSCALAR Returns 1 if all dimensions have size 1.
+% p = isscalar(v)
+
+p = (prod(size(v))==1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/isvector.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function p = isvector(v)
+% ISVECTOR Returns 1 if all but one dimension have size 1.
+% p = isvector(v)
+%
+% Example: isvector(rand(1,2,1)) = 1, isvector(rand(2,2)) = 0.
+
+s=size(v);
+p = (ndims(v)<=2) & (s(1) == 1 | s(2) == 1);
+%p = sum( size(v) > 1) <= 1; % Peter Acklam's solution
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/junk.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,67 @@
+
+  m  = mxGetM(prhs[0]);
+  n  = mxGetN(prhs[0]);
+  pr = mxGetPr(prhs[0]);
+  pi = mxGetPi(prhs[0]);
+  cmplx = (pi == NULL ? 0 : 1);
+
+  /* Allocate space for sparse matrix. 
+   * NOTE:  Assume at most 20% of the data is sparse.  Use ceil
+   * to cause it to round up. 
+   */
+
+  percent_sparse = 0.2;
+  nzmax = (int)ceil((double)m*(double)n*percent_sparse);
+
+  plhs[0] = mxCreateSparse(m,n,nzmax,cmplx);
+  sr  = mxGetPr(plhs[0]);
+  si  = mxGetPi(plhs[0]);
+  irs = mxGetIr(plhs[0]);
+  jcs = mxGetJc(plhs[0]);
+    
+  /* Copy nonzeros. */
+  k = 0; 
+  isfull = 0;
+  for (j = 0; (j < n); j++) {
+    int i;
+    jcs[j] = k;
+    for (i = 0; (i < m); i++) {
+      if (IsNonZero(pr[i]) || (cmplx && IsNonZero(pi[i]))) {
+
+        /* Check to see if non-zero element will fit in 
+         * allocated output array.  If not, increase
+         * percent_sparse by 10%, recalculate nzmax, and augment
+         * the sparse array.
+         */
+        if (k >= nzmax) {
+          int oldnzmax = nzmax;
+          percent_sparse += 0.1;
+          nzmax = (int)ceil((double)m*(double)n*percent_sparse);
+
+          /* Make sure nzmax increases atleast by 1. */
+          if (oldnzmax == nzmax) 
+            nzmax++;
+
+          mxSetNzmax(plhs[0], nzmax); 
+          mxSetPr(plhs[0], mxRealloc(sr, nzmax*sizeof(double)));
+          if (si != NULL)
+          mxSetPi(plhs[0], mxRealloc(si, nzmax*sizeof(double)));
+          mxSetIr(plhs[0], mxRealloc(irs, nzmax*sizeof(int)));
+
+          sr  = mxGetPr(plhs[0]);
+          si  = mxGetPi(plhs[0]);
+          irs = mxGetIr(plhs[0]);
+        }
+        sr[k] = pr[i];
+        if (cmplx) {
+          si[k] = pi[i];
+        }
+        irs[k] = i;
+        k++;
+      }
+    }
+    pr += m;
+    pi += m;
+  }
+  jcs[n] = k;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/loadcell.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,153 @@
+function [lc,dflag,dattype]=loadcell(fname,delim,exclusions,options);
+%function [lc,dflag,numdata]=loadcell(fname,delim,exclusions);
+%  
+%  loadcell loads a cell array with character delimited
+%  data, which can have variable length lines and content.
+%  Numeric values are converted from string to double 
+%  unless options is a string containing 'string'.
+%  
+%  loadcell is for use with small datasets. It is not optimised
+%  for large datasets.
+% 
+%  fname is the filename to be loaded
+%
+%  delim is/are the relevant delimiter(s). If char(10) is included
+%  newlines are simply treated as delimiters and a 1-d array is created.
+%
+%  exclusions  are the set of characters to be treated as paired
+%    braces: line ends or delimiters within braces are ignored.
+%    braces are single characters and any brace can pair with 
+%    any other brace: no type pair checking is done.
+%
+%  options can be omitted or can contain 'string' if no numeric
+%    conversion is required, 'single' if multiple adjacent seperators
+%    should not be treated as one, 'free' if all linefeeds should be stripped
+%    first and 'empty2num' if empty fields are to be treated as numeric 
+%    zeros rather than an empty character set. Combine options using 
+%    concatenation.
+%
+%  lc is a cell array containing the loaded data.
+%
+%  dflag is a set of flags denoting the (i,j) values where data was entered
+%  dflag(i,j)=1 implies lc(i,j) was loaded from the data, and not just set
+%  to empty, say, by default.
+%
+%  numdata is an array  numdata(i,j)=NaN implies
+%    lc(i,j) is a string, otherwise it stores the number at i,j.
+%    This will occur regardless of whether the 'string' option is set.
+%
+%  lc will return -1 if the file is not found or could not be
+%  opened.
+%
+%  Hint: numdata+(1/dflag-1) provides a concise descriptor for the numeric data
+%  Inf=not loaded
+%  NaN=was string or empty set.
+%  otherwise numeric
+%
+%  EXAMPLE
+%
+%[a,b]=loadcell('resultsfile',[',' char(9)],'"','single-string');
+%   will load file 'resultsfile' into variable a, treating any of tab or 
+%   comma as delimiters. Delimiters or carriage returns lying 
+%   between two double inverted commas will be ignored. Two adjacent delimiters
+%   will count twice, and all data will be kept as a string.
+%
+%   Note: in space-separated data 'single' would generally be omitted,
+%   wheras in comma-seperated data it would be included.
+%  
+%   Note the exclusion characters will remain in the final data, and any data
+%   contained within or containing exclusion characters will not be 
+%   converted to numerics.
+%
+%   (c) Amos Storkey 2002
+%    v b160702
+
+% MATLAB is incapable of loading variable length lines or variable type values
+% with a whole file command under the standard library sets. This mfile 
+% fills that gap.
+if (nargin<4) 
+    options=' ';
+end;
+dflag = [];
+%Open file
+fid=fopen(fname,'rt');
+%Cannot open: return -1
+if (fid<0)
+  lc=-1;
+else
+  fullfile=fread(fid,'uchar=>char')';
+  %Strip LF if free is set
+  if ~isempty(findstr(options,'free'))
+      fullfile=strrep(fullfile,char(10),'');
+  end;
+  %Find all delimiters
+  delimpos=[];
+  for s=1:length(delim)
+    delimpos=[delimpos find(fullfile==delim(s))];
+  end
+  %Find all eol
+  endpos=find(fullfile==char(10));
+  endpos=setdiff(endpos,delimpos);
+  %find all exclusions
+  xclpos=[];
+  for s=1:length(exclusions);
+    xclpos=[xclpos find(fullfile==exclusions(s))];
+  end
+  sort(xclpos);
+  xclpos=[xclpos(1:2:end-1);xclpos(2:2:end)];
+  %Combine eol and delimiters
+  jointpos=union(delimpos,endpos);
+  t=1;
+  %Remove delim/eol within exclusion pairs
+  removedelim=[];
+  for s=1:length(jointpos)
+    if any((jointpos(s)>xclpos(1,:)) & (jointpos(s)<xclpos(2,:)))
+      removedelim(t)=jointpos(s);
+      t=t+1;
+    end;
+
+  end
+  %and add start point
+  jointpos=[0 setdiff(jointpos,removedelim)];
+  i=1;
+  j=1;
+  posind=1;
+  multflag=isempty(findstr(options,'single'));
+  stringflag=~isempty(findstr(options,'string'));
+  emptnum=~isempty(findstr(options,'empty2num'));
+  %Run through
+  while (posind<(length(jointpos)))
+    %Get current field
+    tempstr=fullfile(jointpos(posind)+1:jointpos(posind+1)-1);
+    %If empty only continue if adjacent delim count.
+    if ~(isempty(tempstr) & multflag);
+      %This ij is set
+      dflag(i,j)=1;
+      %Convert to num
+      tempno=str2double([tempstr]);
+      %If emptystring convert to zero if emptnum set
+      if (isempty(tempstr) & emptnum)
+          tempno=0;
+      end;
+      %Set dattype to no (or NaN if not a num
+      dattype(i,j)=tempno;
+      %If NaN set lc to string else to num if stringflag not set
+      if (isnan(tempno) |  stringflag) 
+        lc{i,j}=tempstr;
+      else
+        lc{i,j}=tempno;
+      end;
+      %Next j
+      j=j+1;
+    end;
+    %If eol inc i and reset j
+    if ismember(jointpos(posind+1),endpos)
+        i=i+1;
+        j=1;
+    end;
+    %Inc to next delim
+    posind=posind+1;      
+  end;
+end;
+%Logicalise dflag
+dflag=logical(dflag);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/logb.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function x = logb(y, base)
+% logb - logarithm to base b
+% function x = logb(y, base)
+
+x = log(y) ./ log(base);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/logdet.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function y = logdet(A)
+% log(det(A)) where A is positive-definite.
+% This is faster and more stable than using log(det(A)).
+
+%  From Tom Minka's lightspeed toolbox
+
+U = chol(A);
+y = 2*sum(log(diag(U)));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/logsum.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function y=logsum(x,d)
+%LOGSUM logsum(x,d)=log(sum(exp(x),d))
+%  d gives dimension to sum along
+
+%      Copyright (C) Mike Brookes 1998
+%
+%      Last modified Mon Oct 12 15:47:25 1998
+%
+%   VOICEBOX is a MATLAB toolbox for speech processing. Home page is at
+%   http://www.ee.ic.ac.uk/hp/staff/dmb/voicebox/voicebox.html
+%
+
+if nargin==1
+   d=[find(size(x)-1) 1];
+   d=d(1);
+end
+n=size(x,d);
+if n<=1, y=x; return; end
+s=size(x);
+p=[d:ndims(x) 1:d-1];
+z=reshape(permute(x,p),n,prod(s)/n);
+
+y=max(z);
+y=y+log(sum(exp(z-y(ones(n,1),:))));
+
+s(d)=1;
+y=ipermute(reshape(y,s(p)),p);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/logsum_simple.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+function result = logsum(logv)
+
+len = length(logv);
+if (len<2);
+  error('Subroutine logsum cannot sum less than 2 terms.');
+end;
+
+% First two terms
+if (logv(2)<logv(1)),
+  result = logv(1) + log( 1 + exp( logv(2)-logv(1) ) );
+else,
+  result = logv(2) + log( 1 + exp( logv(1)-logv(2) ) );
+end;
+
+% Remaining terms
+for (i=3:len),
+  term = logv(i);
+  if (result<term),
+    result = term   + log( 1 + exp( result-term ) );
+  else,
+    result = result + log( 1 + exp( term-result ) );
+  end;    
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/logsum_test.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+p1 = log(1e-5);
+p2 = log(5*1e-6);
+p3 = log(sum(exp([p1 p2])))
+p4 = logsumexp([p1 p2],2)
+p5 = logsum([p1 p2])
+p6 = logsum([p1 p2])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/logsumexp.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function s = logsumexp(a, dim)
+% Returns log(sum(exp(a),dim)) while avoiding numerical underflow.
+% Default is dim = 1 (rows) or dim=2 for a row vector
+% logsumexp(a, 2) will sum across columns instead of rows
+
+% Written by Tom Minka, modified by Kevin Murphy
+
+if nargin < 2
+  dim = 1;
+  if ndims(a) <= 2 & size(a,1)==1
+    dim = 2;
+  end
+end
+
+% subtract the largest in each column
+[y, i] = max(a,[],dim);
+dims = ones(1,ndims(a));
+dims(dim) = size(a,dim);
+a = a - repmat(y, dims);
+s = y + log(sum(exp(a),dim));
+%i = find(~finite(y));
+%if ~isempty(i)
+%  s(i) = y(i);
+%end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/logsumexpv.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function s = logsumexpv(a)
+% Returns log(sum(exp(a)))  while avoiding numerical underflow.
+%
+% e.g., log(e^a1 + e^a2) = a1 + log(1 + e^(a2-a1)) if a1>a2
+% If a1 ~ a2, and a1>a2, then e^(a2-a1) is exp(small negative number),
+% which can be computed without underflow.
+
+% Same as logsumexp, except we assume a is a vector.
+% This avoids a call to repmat, which takes 50% of the time!
+
+a = a(:)'; % make row vector
+m = max(a);
+b = a - m*ones(1,length(a));
+s = m + log(sum(exp(b)));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/mahal2conf.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,60 @@
+% MAHAL2CONF - Translates a Mahalanobis distance into a confidence
+%              interval.  Consider a multivariate Gaussian
+%              distribution of the form
+%
+%   p(x) = 1/sqrt((2 * pi)^d * det(C)) * exp((-1/2) * MD(x, m, inv(C)))
+%
+%              where MD(x, m, P) is the Mahalanobis distance from x
+%              to m under P:
+%
+%                 MD(x, m, P) = (x - m) * P * (x - m)'
+%
+%              A particular Mahalanobis distance k identifies an
+%              ellipsoid centered at the mean of the distribution.
+%              The confidence interval associated with this ellipsoid
+%              is the probability mass enclosed by it.
+%
+%              If X is an d dimensional Gaussian-distributed vector,
+%              then the Mahalanobis distance of X is distributed
+%              according to the Chi-squared distribution with d
+%              degrees of freedom.  Thus, the confidence interval is
+%              determined by integrating the chi squared distribution
+%              up to the Mahalanobis distance of the measurement.
+%
+% Usage:
+% 
+%   c = mahal2conf(m, d);
+%
+% Inputs:
+%
+%   m    - the Mahalanobis radius of the ellipsoid
+%   d    - the number of dimensions of the Gaussian distribution
+%
+% Outputs:
+%
+%   c    - the confidence interval, i.e., the fraction of
+%          probability mass enclosed by the ellipsoid with the
+%          supplied Mahalanobis distance
+%
+% See also: CONF2MAHAL
+
+% Copyright (C) 2002 Mark A. Paskin
+%
+% This program 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 2 of the License, or
+% (at your option) any later version.
+%
+% This program 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
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+% USA.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function c = mahal2conf(m, d)
+
+c = chi2cdf(m, d);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/marg_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,27 @@
+function smallT = marg_table(bigT, bigdom, bigsz, onto, maximize)
+% MARG_TABLE Marginalize a table
+% smallT = marg_table(bigT, bigdom, bigsz, onto, maximize)
+
+if nargin < 5, maximize = 0; end
+
+
+smallT = myreshape(bigT, bigsz); % make sure it is a multi-dim array
+sum_over = mysetdiff(bigdom, onto);
+ndx = find_equiv_posns(sum_over, bigdom);
+if maximize
+  for i=1:length(ndx)
+    smallT = max(smallT, [], ndx(i));
+  end
+else
+  for i=1:length(ndx)
+    smallT = sum(smallT, ndx(i));
+  end
+end
+
+
+ns = zeros(1, max(bigdom));
+%ns(bigdom) = mysize(bigT); % ignores trailing dimensions of size 1
+ns(bigdom) = bigsz;
+
+smallT = squeeze(smallT); % remove all dimensions of size 1
+smallT = myreshape(smallT, ns(onto)); % put back relevant dims of size 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/marginalize_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,50 @@
+function smallT = marginalize_table(bigT, bigdom, bigsz, onto, maximize)
+% MARG_TABLE Marginalize a table
+% function smallT = marginalize_table(bigT, bigdom, bigsz, onto, maximize)
+
+% Like marg_table in BNT, except we do not assume the domains are sorted
+
+if nargin < 5, maximize = 0; end
+
+
+smallT = myreshape(bigT, bigsz); % make sure it is a multi-dim array
+sum_over = mysetdiff(bigdom, onto);
+ndx = find_equiv_posns(sum_over, bigdom);
+if maximize
+  for i=1:length(ndx)
+    smallT = max(smallT, [], ndx(i));
+  end
+else
+  for i=1:length(ndx)
+    smallT = sum(smallT, ndx(i));
+  end
+end
+
+
+ns = zeros(1, max(bigdom));
+%ns(bigdom) = mysize(bigT); % ignores trailing dimensions of size 1
+ns(bigdom) = bigsz;
+
+% If onto has a different ordering than bigdom, the following
+% will produce the wrong results
+
+%smallT = squeeze(smallT); % remove all dimensions of size 1
+%smallT = myreshape(smallT, ns(onto)); % put back relevant dims of size 1
+
+% so permute dimensions to match desired ordering (as specified by onto)
+
+
+% like find_equiv_posns, but keeps ordering
+outdom = [onto sum_over];
+for i=1:length(outdom)
+  j = find(bigdom==outdom(i));
+  match(i) = j;
+end
+outdom = [onto sum_over];
+for i=1:length(outdom)
+  j = find(bigdom==outdom(i));
+  match(i) = j;
+end
+if match ~= 1
+  smallT = permute(smallT, match);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/matprint.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+% MATPRINT - prints a matrix with specified format string
+%
+% Usage: matprint(a, fmt, fid)
+%
+%                 a   - Matrix to be printed.
+%                 fmt - C style format string to use for each value.
+%                 fid - Optional file id.
+%
+% Eg. matprint(a,'%3.1f') will print each entry to 1 decimal place
+
+% Peter Kovesi
+% School of Computer Science & Software Engineering
+% The University of Western Australia
+% pk @ csse uwa edu au
+% http://www.csse.uwa.edu.au/~pk
+%
+% March 2002
+
+function matprint(a, fmt, fid)
+    
+    if nargin < 3
+	fid = 1;
+    end
+    
+    [rows,cols] = size(a);
+    
+    % Construct a format string for each row of the matrix consisting of
+    % 'cols' copies of the number formating specification
+    fmtstr = [];
+    for c = 1:cols
+      fmtstr = [fmtstr, ' ', fmt];
+    end
+    fmtstr = [fmtstr '\n'];    % Add a line feed
+    
+    fprintf(fid, fmtstr, a');  % Print the transpose of the matrix because
+                               % fprintf runs down the columns of a matrix.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/max_mult.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,46 @@
+/* C mex version of max_mult.m in BPMRF2 directory  */
+/* gcc -Wall -I/mit/matlab_v6.5/distrib/bin/glnx86 -c max_mult.c */
+
+#include <math.h>
+#include "mex.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+  int rows,cols,common,m,n,p;
+  double y1, y2;
+  double *arr1, *arr2, *arr3;
+
+
+  if (nrhs!=2 || nlhs>1)
+    mexErrMsgTxt("max_mult requires two inputs and one output");
+  if (mxIsChar(prhs[0]) || mxIsClass(prhs[0], "sparse") || mxIsComplex(prhs[0])
+      || mxIsChar(prhs[1]) || mxIsClass(prhs[1], "sparse") || mxIsComplex(prhs[1]))
+    mexErrMsgTxt("Inputs must be real, full, and nonstring");
+  if (mxGetN(prhs[0])!=mxGetM(prhs[1]))
+    mexErrMsgTxt("The number of columns of A must be the same as the number of rows of x");
+  
+
+  arr1=mxGetPr(prhs[0]);
+  arr2=mxGetPr(prhs[1]);
+  p=mxGetN(prhs[0]);
+  m=mxGetM(prhs[0]);
+  n=mxGetN(prhs[1]);
+  plhs[0]=mxCreateDoubleMatrix(m, n, mxREAL);
+  arr3=mxMalloc(m*n*sizeof(double));
+
+  for (rows=0; rows<m ; rows++)
+    for (cols=0; cols<n ; cols++)
+    {
+      y1=arr1[rows]*arr2[cols*p];  
+      for (common=1; common<p; common++)
+      {
+	y2=arr1[rows+common*m]*arr2[common+cols*p];
+        if (y2>y1)
+          y1=y2;
+      }
+      arr3[rows+cols*m]=y1;
+    }
+
+  mxSetPr(plhs[0], arr3);
+	 
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/max_mult.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function y=max_mult(A,x)
+% MAX_MULT Like matrix multiplication, but sum gets replaced by max
+% function y=max_mult(A,x) y(i) = max_j A(i,j) x(j)
+
+%X=ones(size(A,1),1) * x(:)'; % X(j,i) = x(i)
+%y=max(A.*X, [], 2);
+
+% This is faster
+if size(x,2)==1
+  X=x*ones(1,size(A,1)); % X(i,j) = x(i)
+  y=max(A'.*X)';
+else
+%this works for arbitrarily sized A and x (but is ugly, and slower than above)
+  X=repmat(x, [1 1 size(A,1)]);
+  B=repmat(A, [1 1 size(x,2)]);
+  C=permute(B,[2 3 1]);
+  y=permute(max(C.*X),[3 2 1]);
+%  this is even slower, as is using squeeze instead of permute
+%  Y=permute(X, [3 1 2]);
+%  y=permute(max(Y.*B, [], 2), [1 3 2]);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/mexutil.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,43 @@
+#include "mexutil.h"
+
+/* Functions to create uninitialized arrays. */
+
+mxArray *mxCreateNumericArrayE(int ndim, const int *dims, 
+         mxClassID class, mxComplexity ComplexFlag)
+{
+  mxArray *a;
+  int i, *dims1 = mxMalloc(ndim*sizeof(int));
+  size_t sz = 1;
+  for(i=0;i<ndim;i++) {
+    sz *= dims[i];
+    dims1[i] = 1;
+  }
+  a = mxCreateNumericArray(ndim,dims1,class,ComplexFlag);
+  sz *= mxGetElementSize(a);
+  mxSetDimensions(a, dims, ndim);
+  mxFree(dims1);
+  mxSetData(a, mxRealloc(mxGetData(a), sz));
+  if(ComplexFlag == mxCOMPLEX) {
+    mxSetPi(a, mxRealloc(mxGetPi(a),sz));
+  }
+  return a;
+}
+mxArray *mxCreateNumericMatrixE(int m, int n, mxClassID class, 
+				mxComplexity ComplexFlag)
+{
+  size_t sz = m*n*sizeof(double);
+  mxArray *a = mxCreateNumericMatrix(1, 1, class, ComplexFlag);
+  mxSetM(a,m);
+  mxSetN(a,n);
+  mxSetPr(a, mxRealloc(mxGetPr(a),sz));
+  if(ComplexFlag == mxCOMPLEX) {
+    mxSetPi(a, mxRealloc(mxGetPi(a),sz));
+  }
+  return a;
+}
+mxArray *mxCreateDoubleMatrixE(int m, int n, 
+			       mxComplexity ComplexFlag)
+{
+  return mxCreateNumericMatrixE(m,n,mxDOUBLE_CLASS,ComplexFlag);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/mexutil.h	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+#include "mex.h"
+
+mxArray *mxCreateNumericArrayE(int ndim, const int *dims, 
+			       mxClassID class, mxComplexity ComplexFlag);
+mxArray *mxCreateNumericMatrixE(int m, int n, mxClassID class, 
+				mxComplexity ComplexFlag);
+mxArray *mxCreateDoubleMatrixE(int m, int n, 
+			       mxComplexity ComplexFlag);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/mk_multi_index.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+function index = mk_multi_index(n, dims, vals)
+% MK_MULTI_INDEX Compute the indices of the submatrix where dims(i)=vals(i).
+% index = mk_multi_index(n, dims, vals)
+% 
+% Example:
+% index = mk_multi_index(3, [1 3], [3 2])
+% gives index = {3, ':', 2}, which will select out dim 1 = 3 and dim 3 = 2
+% So if A(:,:,1)=[1 2;3 4; 5 6]; A(:,:,2)=[7 8; 9 10; 11 12]
+% then A(index{:}) = [11 12]: 
+
+if n==0
+  index = { 1 };
+  return;
+end
+
+index = cell(1,n);
+for i=1:n
+  index{i} = ':';
+end
+for i=1:length(dims)
+  index{dims(i)} = vals(i);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/mk_stochastic.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,27 @@
+function [T,Z] = mk_stochastic(T)
+% MK_STOCHASTIC Ensure the argument is a stochastic matrix, i.e., the sum over the last dimension is 1.
+% [T,Z] = mk_stochastic(T)
+%
+% If T is a vector, it will sum to 1.
+% If T is a matrix, each row will sum to 1.
+% If T is a 3D array, then sum_k T(i,j,k) = 1 for all i,j.
+
+% Set zeros to 1 before dividing
+% This is valid since S(j) = 0 iff T(i,j) = 0 for all j
+
+if (ndims(T)==2) & (size(T,1)==1 | size(T,2)==1) % isvector
+  [T,Z] = normalise(T);
+elseif ndims(T)==2 % matrix
+  Z = sum(T,2); 
+  S = Z + (Z==0);
+  norm = repmat(S, 1, size(T,2));
+  T = T ./ norm;
+else % multi-dimensional array
+  ns = size(T);
+  T = reshape(T, prod(ns(1:end-1)), ns(end));
+  Z = sum(T,2);
+  S = Z + (Z==0);
+  norm = repmat(S, 1, ns(end));
+  T = T ./ norm;
+  T = reshape(T, ns);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/mkdirKPM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function mkdirKPM(dname)
+% function mkdirKPM(dname)
+% If directory does not exist, make it
+% 
+% mkdirKPM('foo\bar\baz') makes subdirectories bar and baz
+% mkdirKPM('foo\bar\baz.txt') makes subdirectories bar 
+
+% convert foo\bar\baz to pathstr=foo\bar, name=baz
+% convert foo\bar\baz.txt to pathstr=foo\bar, name=baz
+[pathstr, name, ext, versn] = fileparts(dname);
+if ~isempty(ext) % we stripped off something after final period
+  % convert foo\bar to pathstr=foo, name=bar
+  % convert foo\bar.bad to pathstr=foo, name=bar.bad
+  [pathstr, name, ext, versn] = fileparts(pathstr);
+  name = sprintf('%s%s', name, ext); % in case there is a period in the directory name
+end
+
+dname = fullfile(pathstr, name);
+if ~exist(dname, 'dir')
+  %fprintf('mkdirKPM: making %s, %s \n', pathstr, name);
+  mkdir(pathstr, name)
+else
+  %fprintf('mkdirKPM: %s already exists\n', dname)
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/montageKPM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,102 @@
+function h = montageKPM(arg)
+% montageKPM is like the built-in montage, but assumes input is MxNxK or filenames
+%
+% Converts patches (y,x,i) into patches(y,x,1,i)
+% Also, adds a black border aroudn them
+
+if iscell(arg)
+  h= montageFilenames(arg);
+else
+  nr = size(arg,1); nc = size(arg,2); Npatches = size(arg,3);
+  patchesColor = reshape(arg, [nr nc 1 Npatches]);
+  patchesColor = patchesColor ./ max(patchesColor(:));
+  
+  if 1
+    %put a black border around them for display purposes
+    border = 5;
+    bgColor = ones(1,1,class(patchesColor));
+    patchesColorBig = bgColor*ones(nr+2*border, nc+2*border, 1, Npatches, class(patchesColor));
+    %patchesColorBig = zeros(nr+2*border, nc+2*border, 1, Npatches, class(patchesColor));
+    patchesColorBig(border+1:end-border, border+1:end-border, :, :) = patchesColor;
+  else
+    patchesColorBig = patchesColor;
+  end
+  montage(patchesColorBig)
+
+end
+
+%%%%%%%%%%%%%
+
+function h = montageFilenames(filenames)
+
+%[nRows, nCols, nBands, nFrames] = size(a);
+
+% Estimate nMontageColumns and nMontageRows given the desired ratio of
+% Columns to Rows to be one (square montage).
+aspectRatio = 1; 
+nMontageCols = sqrt(aspectRatio * nRows * nFrames / nCols);
+
+% Make sure montage rows and columns are integers. The order in the adjustment
+% matters because the montage image is created horizontally across columns.
+nMontageCols = ceil(nMontageCols); 
+nMontageRows = ceil(nFrames / nMontageCols);
+
+% Create the montage image.
+b = a(1,1); % to inherit type 
+b(1,1) = 0; % from a
+b = repmat(b, [nMontageRows*nRows, nMontageCols*nCols, nBands, 1]);
+
+rows = 1 : nRows; 
+cols = 1 : nCols;
+
+for i = 0:nMontageRows-1
+  for j = 0:nMontageCols-1,
+    k = j + i * nMontageCols + 1;
+    if k <= nFrames
+      b(rows + i * nRows, cols + j * nCols, :) = a(:,:,:,k);
+    else
+      break;
+    end
+  end
+end
+
+if isempty(cm)
+  hh = imshow(b);
+else
+  hh = imshow(b,cm);
+end
+
+if nargout > 0
+    h = hh;
+end
+
+%--------------------------------------------------------------
+%Parse Inputs Function
+
+function [I,map] = parse_inputs(varargin)
+
+% initialize variables
+map = [];
+
+iptchecknargin(1,2,nargin,mfilename);
+iptcheckinput(varargin{1},{'uint8' 'double' 'uint16' 'logical' 'single' ...
+                    'int16'},{},mfilename, 'I, BW, or RGB',1);
+I = varargin{1};
+
+if nargin==2
+  if isa(I,'int16')
+    eid = sprintf('Images:%s:invalidIndexedImage',mfilename);
+    msg1 = 'An indexed image can be uint8, uint16, double, single, or ';
+    msg2 = 'logical.';
+    error(eid,'%s %s',msg1, msg2);
+  end
+  map = varargin{2};
+  iptcheckinput(map,{'double'},{},mfilename,'MAP',1);
+  if ((size(map,1) == 1) && (prod(map) == numel(I)))
+    % MONTAGE(D,[M N P]) OBSOLETE
+    eid = sprintf('Images:%s:obsoleteSyntax',mfilename);
+    msg1 = 'MONTAGE(D,[M N P]) is an obsolete syntax.';
+    msg2 = 'Use multidimensional arrays to represent multiframe images.';
+    error(eid,'%s\n%s',msg1,msg2);    
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/montageKPM2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,69 @@
+function montageKPM2(data)
+% data(y,x,b,f) or data(y,x,f)
+% can be double - uses imagesc to display, not imshow
+% based on imaqmontage
+
+if ndims(data)==3
+  nr = size(data,1); nc = size(data,2); Npatches = size(data,3); Nbands = 1;
+  data = reshape(data, [nr nc Nbands Npatches]);
+else
+  nr = size(data,1); nc = size(data,2); Nbands = size(data,3); Npatches = size(data,4);
+end
+nativeVal = data(1, 1);
+dataOrig = data;
+
+%put a black border around them for display purposes
+border = 5;
+bgColor = min(data(:));
+%bgColor = max(data(:));
+data = bgColor*ones(nr+2*border, nc+2*border, Nbands, Npatches, class(data));
+data(border+1:end-border, border+1:end-border, :, :) = dataOrig;
+
+[width, height, bands, nFrames] = size(data);
+
+% Determine the number of axis rows and columns.
+axCols = sqrt(nFrames);
+if (axCols<1)
+    % In case we have a slim image.
+    axCols = 1;
+end
+axRows = nFrames/axCols;
+if (ceil(axCols)-axCols) < (ceil(axRows)-axRows),
+    axCols = ceil(axCols);
+    axRows = ceil(nFrames/axCols);
+else
+    axRows = ceil(axRows); 
+    axCols = ceil(nFrames/axRows);
+end
+
+% Size the storage to hold all frames.
+storage = repmat(nativeVal, [axRows*width, axCols*height, bands, 1]);
+
+% Fill the storage up with data pixels.
+rows = 1:width; 
+cols = 1:height;
+for i=0:axRows-1,
+  for j=0:axCols-1,
+    k = j+i*axCols+1;
+    if k<=nFrames,
+      storage(rows+i*width, cols+j*height, :) = data(:,:,:,k);
+    else
+      break;
+    end
+  end
+end
+
+
+% Display the tiled frames nicely and 
+% pop the window forward.
+im = imagesc(storage);
+
+ax = get(im, 'Parent');
+fig = get(ax, 'Parent');
+set(ax, 'XTick', [], 'YTick', [])
+figure(fig)
+
+% If working with single band images, update the colormap.
+if 0 % bands==1,
+    colormap(gray);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/montageKPM3.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function montageKPM3(data)
+% data{f}(y,x,b) - each frame can have a different size (can can even be empty)
+
+data2 = cell2matPad(data);
+montageKPM2(data2)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/mult_by_table.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function bigT = mult_by_table(bigT, bigdom, bigsz, smallT, smalldom, smallsz)
+% MULT_BY_TABLE 
+% bigT = mult_by_table(bigT, bigdom, bigsz, smallT, smalldom, smallsz)
+%
+
+Ts = extend_domain_table(smallT, smalldom, smallsz, bigdom, bigsz);
+bigT(:) = bigT(:) .* Ts(:); % must have bigT(:) on LHS to preserve shape
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/myintersect.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function C = myintersect(A,B)
+% MYINTERSECT Intersection of two sets of positive integers (much faster than built-in intersect)
+% C = myintersect(A,B)
+
+A = A(:)'; B = B(:)';
+
+if isempty(A)
+  ma = 0;
+else
+  ma = max(A);
+end
+
+if isempty(B)
+  mb = 0;
+else
+  mb = max(B);
+end
+
+if ma==0 | mb==0
+  C = [];
+else
+  %bits = sparse(1, max(ma,mb));
+  bits = zeros(1, max(ma,mb));
+  bits(A) = 1;
+  C = B(logical(bits(B)));  
+end
+
+%sum( bitget( bitand( cliquesb(i), cliquesb(j) ), 1:52 ) ); 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/myismember.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function p = myismember(a,A)
+% MYISMEMBER Is 'a' an element of a set of positive integers? (much faster than built-in ismember)
+% p = myismember(a,A)
+
+%if isempty(A) | a < min(A) | a > max(A)  % slow
+
+if length(A)==0
+  p = 0;
+elseif a < min(A)
+  p = 0;
+elseif a > max(A)
+  p = 0;
+else
+  bits = zeros(1, max(A));
+  bits(A) = 1;
+  p = bits(a);
+end
+p = logical(p);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/myones.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function T = myones(sizes)
+% MYONES Like the built-in ones, except myones(k) produces a k*1 vector instead of a k*k matrix,
+% T = myones(sizes)
+
+if length(sizes)==0
+  T = 1;
+elseif length(sizes)==1
+  T = ones(sizes, 1);
+else
+  T = ones(sizes(:)');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/myplot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+colors =  ['r' 'b' 'k' 'g' 'c' 'y' 'm' ...
+	   'r' 'b' 'k' 'g' 'c' 'y' 'm'];
+symbols = ['o' 'x' 's' '>' '<' '^' 'v' ...
+	   '*' 'p' 'h' '+' 'd' 'o' 'x'];
+for i=1:length(colors)
+  styles{i} = sprintf('-%s%s', colors(i), symbols(i));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/myrand.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function T = myrand(sizes)
+% MYRAND Like the built-in rand, except myrand(k) produces a k*1 vector instead of a k*k matrix,
+% T = myrand(sizes)
+
+if length(sizes)==0
+  warning('myrand[]');
+  T = rand(1,1);
+elseif length(sizes)==1
+  T = rand(sizes, 1);
+else
+  T = rand(sizes);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/myrepmat.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function T = myrepmat(T, sizes)
+% MYREPMAT Like the built-in repmat, except myrepmat(T,n) == repmat(T,[n 1])
+% T = myrepmat(T, sizes)
+
+if length(sizes)==1
+  T = repmat(T, [sizes 1]);
+else
+  T = repmat(T, sizes(:)');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/myreshape.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function T = myreshape(T, sizes)
+% MYRESHAPE Like the built-in reshape, except myreshape(T,n) == reshape(T,[n 1])
+% T = myreshape(T, sizes)
+
+if length(sizes)==0
+  return;
+elseif length(sizes)==1
+  T = reshape(T, [sizes 1]);
+else
+  T = reshape(T, sizes(:)');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/mysetdiff.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function C = mysetdiff(A,B)
+% MYSETDIFF Set difference of two sets of positive integers (much faster than built-in setdiff)
+% C = mysetdiff(A,B)
+% C = A \ B = { things in A that are not in B }
+%
+% Original by Kevin Murphy, modified by Leon Peshkin
+
+if isempty(A)
+    C = [];
+    return;
+elseif isempty(B)
+    C = A;
+    return; 
+else % both non-empty
+    bits = zeros(1, max(max(A), max(B)));
+    bits(A) = 1;
+    bits(B) = 0;
+    C = A(logical(bits(A)));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/mysize.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function sz = mysize(M)
+% MYSIZE Like the built-in size, except it returns n if M is a vector of length n, and 1 if M is a scalar.
+% sz = mysize(M)
+% 
+% The behavior is best explained by examples
+% - M = rand(1,1),   mysize(M) = 1,      size(M) = [1 1]
+% - M = rand(2,1),   mysize(M) = 2,      size(M) = [2 1]
+% - M = rand(1,2),   mysize(M) = 2,      size(M) = [1 2]
+% - M = rand(2,2,1), mysize(M) = [2 2],  size(M) = [2 2]
+% - M = rand(1,2,1), mysize(M) = 2,      size(M) = [1 2]
+
+if isvector(M)
+  sz = length(M);
+else
+  sz = size(M);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/mysubset.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function p=mysubset(small,large)
+% MYSUBSET Is the small set of +ve integers a subset of the large set?
+% p = mysubset(small, large)
+
+% Surprisingly, this is not built-in.
+
+if isempty(small)
+  p = 1; % isempty(large);
+else
+  p = length(myintersect(small,large)) == length(small);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/mysymsetdiff.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+function C = mysymsetdiff(A,B)
+% MYSYMSETDIFF Symmetric set difference of two sets of positive integers (much faster than built-in setdiff)
+% C = mysetdiff(A,B)
+% C = (A\B) union (B\A) = { things that A and B don't have in common }
+
+if isempty(A)
+  ma = 0;
+else
+  ma = max(A);
+end
+
+if isempty(B)
+  mb = 0;
+else
+  mb = max(B);
+end
+
+if ma==0 
+  C = B;
+elseif mb==0
+  C = A;
+else % both non-empty
+  m = max(ma,mb);
+  bitsA = sparse(1, m);
+  bitsA(A) = 1;
+  bitsB = sparse(1, m);
+  bitsB(B) = 1;
+  C = find(xor(bitsA, bitsB));
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/myunion.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+function C = myunion(A,B)
+% MYUNION Union of two sets of positive integers (much faster than built-in union)
+% C = myunion(A,B)
+
+if isempty(A)
+  ma = 0;
+else
+  ma = max(A);
+end
+
+if isempty(B)
+  mb = 0;
+else
+  mb = max(B);
+end
+
+if ma==0 & mb==0
+  C = [];
+elseif ma==0 & mb>0
+  C = B;
+elseif ma>0 & mb==0
+  C = A;
+else
+  %bits = sparse(1, max(ma,mb));
+  bits = zeros(1, max(ma,mb));
+  bits(A) = 1;
+  bits(B) = 1;
+  C = find(bits);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/nchoose2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,35 @@
+function c = nchoose2(v, f)
+%NCHOOSE2 All combinations of N elements taken two at a time.
+%
+%   NCHOOSE2(1:N) or NCHOOSEK(V) where V is a vector of length N,
+%   produces a matrix with N*(N-1)/2 rows and K columns. Each row of
+%   the result has K of the elements in the vector V.
+%
+%   NCHOOSE2(N,FLAG) is the same as NCHOOSE2(1:N) but faster.
+%
+%   NCHOOSE2(V) is much faster than NCHOOSEK(V,2).
+%
+%   See also NCHOOSEK, PERMS.
+
+%   Author:      Peter J. Acklam
+%   Time-stamp:  2000-03-03 13:03:59
+%   E-mail:      jacklam@math.uio.no
+%   URL:         http://www.math.uio.no/~jacklam
+
+   nargs = nargin;
+   if nargs < 1
+      error('Not enough input arguments.');
+   elseif nargs == 1
+      v = v(:);
+      n = length(v);
+   elseif nargs == 2
+      n = v;
+   else
+      error('Too many input arguments.');
+   end
+
+   [ c(:,2), c(:,1) ] = find( tril( ones(n), -1 ) );
+
+   if nargs == 1
+      c = v(c);
+   end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/ncols.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function c = cols(x)
+% COLS    The number of columns.
+% COLS is a more readable alternative to size(x,2).
+c = size(x,2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/nonmaxsup.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,42 @@
+% NONMAXSUP - Non-maximal Suppression
+%
+% Usage:  cim = nonmaxsup(im, radius)
+%
+% Arguments:   
+%            im     - image to be processed.
+%            radius - radius of region considered in non-maximal
+%                     suppression (optional). Typical values to use might
+%                     be 1-3.  Default is 1.
+%
+% Returns:
+%            cim    - image with pixels that are not maximal within a 
+%                     square neighborhood zeroed out.
+
+% Copyright (C) 2002 Mark A. Paskin
+%
+% This program 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 2 of the License, or
+% (at your option) any later version.
+%
+% This program 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
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+% USA.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function cim = nonmaxsup(m, radius)
+  if (nargin == 1) radius = 1; end
+  % Extract local maxima by performing a grey scale morphological
+  % dilation and then finding points in the corner strength image that
+  % match the dilated image and are also greater than the threshold.
+  sze = 2 * radius + 1;                   % Size of mask.
+  mx = ordfilt2(m, sze^2, ones(sze));   % Grey-scale dilate.
+  cim = sparse(m .* (m == mx));
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/normalise.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function [M, z] = normalise(A, dim)
+% NORMALISE Make the entries of a (multidimensional) array sum to 1
+% [M, c] = normalise(A)
+% c is the normalizing constant
+%
+% [M, c] = normalise(A, dim)
+% If dim is specified, we normalise the specified dimension only,
+% otherwise we normalise the whole array.
+
+if nargin < 2
+  z = sum(A(:));
+  % Set any zeros to one before dividing
+  % This is valid, since c=0 => all i. A(i)=0 => the answer should be 0/1=0
+  s = z + (z==0);
+  if ~(s == 1)
+    M = A / s;
+  else
+    M = A; % by matthiasm (saving memory)
+  end
+elseif dim==1 % normalize each column
+  z = sum(A);
+  s = z + (z==0);
+  %M = A ./ (d'*ones(1,size(A,1)))';
+  M = A ./ repmatC(s, size(A,1), 1);
+else
+  % Keith Battocchi - v. slow because of repmat
+  z=sum(A,dim);
+  s = z + (z==0);
+  L=size(A,dim);
+  d=length(size(A));
+  v=ones(d,1);
+  v(dim)=L;
+  %c=repmat(s,v);
+  c=repmat(s,v');
+  M=A./c;
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/normaliseC.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+/* C mex version of normalise.m in misc directory  */
+
+#include "mex.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+  double *T, *sum_ptr, sum;
+  int i, N;  
+
+  plhs[0] = mxDuplicateArray(prhs[0]);
+  T = mxGetPr(plhs[0]);
+  if(mxIsSparse(plhs[0])) N = mxGetJc(plhs[0])[mxGetN(plhs[0])];
+  else N = mxGetNumberOfElements(plhs[0]);
+
+  plhs[1] = mxCreateDoubleMatrix(1, 1, mxREAL);
+  sum_ptr = mxGetPr(plhs[1]);
+
+  sum = 0;
+  for (i = 0; i < N; i++) {
+    sum += *T++;
+  }
+  T = mxGetPr(plhs[0]);
+  if (sum > 0) {
+    for (i = 0; i < N; i++) {
+      *T++ /= sum;
+    }
+  } 
+  *sum_ptr = sum;
+}
Binary file _FullBNT/KPMtools/normaliseC.dll has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/normalize.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,34 @@
+function [M, z] = normalise(A, dim)
+% NORMALISE Make the entries of a (multidimensional) array sum to 1
+% [M, c] = normalise(A)
+% c is the normalizing constant
+%
+% [M, c] = normalise(A, dim)
+% If dim is specified, we normalise the specified dimension only,
+% otherwise we normalise the whole array.
+
+if nargin < 2
+  z = sum(A(:));
+  % Set any zeros to one before dividing
+  % This is valid, since c=0 => all i. A(i)=0 => the answer should be 0/1=0
+  s = z + (z==0);
+  M = A / s;
+elseif dim==1 % normalize each column
+  z = sum(A);
+  s = z + (z==0);
+  %M = A ./ (d'*ones(1,size(A,1)))';
+  M = A ./ repmatC(s, size(A,1), 1);
+else
+  % Keith Battocchi - v. slow because of repmat
+  z=sum(A,dim);
+  s = z + (z==0);
+  L=size(A,dim);
+  d=length(size(A));
+  v=ones(d,1);
+  v(dim)=L;
+  %c=repmat(s,v);
+  c=repmat(s,v');
+  M=A./c;
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/nrows.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,4 @@
+function r = rows(x)
+% ROWS      The number of rows.
+% ROWS is a more readable alternative to size(x,1).
+r = size(x,1);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/num2strcell.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function c = num2strcell(n, format)
+% num2strcell Convert vector of numbers to cell array of strings
+% function c = num2strcell(n, format)
+%
+% If format is omitted, we use
+% c{i} = sprintf('%d', n(i))
+
+if nargin < 2, format = '%d'; end
+
+N = length(n);
+c = cell(1,N);
+for i=1:N
+  c{i} = sprintf(format, n(i));
+end
+  
+  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/optimalMatching.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,90 @@
+% MATCH - Solves the weighted bipartite matching (or assignment)
+%         problem.
+%
+% Usage:  a = match(C);
+%
+% Arguments:   
+%         C     - an m x n cost matrix; the sets are taken to be
+%                 1:m and 1:n; C(i, j) gives the cost of matching
+%                 items i (of the first set) and j (of the second set)
+%
+% Returns:
+%
+%         a     - an m x 1 assignment vector, which gives the
+%                 minimum cost assignment.  a(i) is the index of
+%                 the item of 1:n that was matched to item i of
+%                 1:m.  If item i (of 1:m) was not matched to any 
+%                 item of 1:n, then a(i) is zero.
+
+% Copyright (C) 2002 Mark A. Paskin
+%
+% This program 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 2 of the License, or
+% (at your option) any later version.
+%
+% This program 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
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+% USA.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function [a] = optimalMatching(C)
+
+% Trivial cases:
+[p, q] = size(C);
+if (p == 0)
+  a = []; 
+  return;
+elseif (q == 0)
+  a = zeros(p, 1);
+  return;
+end
+
+
+if  0
+% First, reduce the problem by making easy optimal matches.  If two
+% elements agree that they are the best match, then match them up.
+[x, a] = min(C, [], 2);
+[y, b] = min(C, [], 1);
+u = find(1:p ~= b(a(:)));
+a(u) = 0;
+v = find(1:q ~= a(b(:))');
+C = C(u, v);
+if (isempty(C)) return; end
+end
+
+% Get the (new) size of the two sets, u and v.
+[m, n] = size(C);
+
+%mx = realmax;
+mx = 2*max(C(:));
+mn = -2*min(C(:));
+% Pad the affinity matrix to be square
+if (m < n)
+  C = [C; mx * ones(n - m, n)];
+elseif (n < m)
+  C = [C, mx * ones(m, m - n)];
+end
+
+% Run the Hungarian method.  First replace infinite values by the
+% largest (or smallest) finite values.
+C(find(isinf(C) & (C > 0))) = mx;
+C(find(isinf(C) & (C < 0))) = mn;
+%fprintf('running hungarian\n');
+[b, cost] = hungarian(C');
+
+% Extract only the real assignments
+ap = b(1:m)';
+ap(find(ap > n)) = 0;
+
+a = ap; 
+%% Incorporate this sub-assignment into the complete assignment
+%  k = find(ap);
+%  a(u(k)) = v(ap(k));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/optimalMatchingTest.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+% Consider matching sources to detections
+
+%  s1 d2  
+%         s2 d3
+%  d1
+
+a  = optimalMatching([52;0.01])
+
+% sources(:,i) = [x y] coords
+sources = [0.1 0.7; 0.6 0.4]';
+detections = [0.2 0.2; 0.2 0.8; 0.7 0.1]';
+dst = sqdist(sources, detections)
+
+% a = [2 3] which means s1-d2, s2-d3
+a = optimalMatching(dst)
+
+% a = [0 1 2] which means d1-0, d2-s1, d3-s2
+a = optimalMatching(dst')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/partitionData.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function  varargout = partitionData(Ndata, varargin)
+% PARTITIONDATA Partition a vector of indices into random sets
+% [a,b,c,...] = partitionData(N, 0.3, 0.2, 0.5, ...)
+%
+% Examples:
+% [a,b,c]=partitionData(105,0.3,0.2,0.5);
+% a= 1:30, b=32:52, c=52:105 (last bin gets all the left over)
+
+Npartitions = length(varargin);
+perm = randperm(Ndata);
+%perm = 1:Ndata;
+ndx = 1;
+for i=1:Npartitions
+  pc(i) = varargin{i};
+  Nbin(i) = fix(Ndata*pc(i));
+  low(i) = ndx;
+  if i==Npartitions
+    high(i) = Ndata;
+  else
+    high(i) = low(i)+Nbin(i)-1;
+  end
+  varargout{i} = perm(low(i):high(i));
+  ndx = ndx+Nbin(i);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/partition_matrix_vec.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function [m1, m2, K11, K12, K21, K22] = partition_matrix_vec(m, K, n1, n2, bs)
+% PARTITION_MATRIX_VEC Partition a vector and matrix into blocks.
+% [m1, m2, K11, K12, K21, K22] = partition_matrix_vec(m, K, blocks1, blocks2, bs)
+%
+% bs(i) = block size of i'th node
+%
+% Example:
+% n1 = [6 8], n2 = [5], bs = [- - - - 2 1 - 2], where - = don't care
+% m = [0.1 0.2   0.3   0.4 0.5], K = some 5*5 matrix,
+% So E[X5] = [0.1 0.2], E[X6] = [0.3], E[X8] = [0.4 0.5]
+% m1 = [0.3 0.4 0.5], m2 = [0.1 0.2];
+
+dom = myunion(n1, n2);
+n1i = block(find_equiv_posns(n1, dom), bs(dom));
+n2i = block(find_equiv_posns(n2, dom), bs(dom));
+m1 = m(n1i);
+m2 = m(n2i);
+K11 = K(n1i, n1i);
+K12 = K(n1i, n2i);
+K21 = K(n2i, n1i);
+K22 = K(n2i, n2i);  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/pca_kpm.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function [pc_vec]=pca_kpm(features,N, method);
+% PCA_KPM Compute top N principal components using eigs or svd.
+% [pc_vec]=pca_kpm(features,N) 
+%
+% features(:,i) is the i'th example - each COLUMN is an observation
+% pc_vec(:,j) is the j'th basis function onto which you should project the data
+% using pc_vec' * features
+
+[d ncases] = size(features);
+fm=features-repmat(mean(features,2), 1, ncases);
+
+
+if method==1 % d*d < d*ncases
+  fprintf('pca_kpm eigs\n');
+  options.disp = 0;
+  C = cov(fm'); % d x d matrix
+  [pc_vec, evals] = eigs(C, N, 'LM', options);
+else 
+  % [U,D,V] = SVD(fm), U(:,i)=evec of fm fm', V(:,i) = evec of fm' fm
+  fprintf('pca_kpm svds\n');
+  [U,D,V] = svds(fm', N);
+  pc_vec = V;
+end
+
+if 0
+X = randn(5,3);
+X = X-repmat(mean(X),5,1);
+C = X'*X;
+C2=cov(X)
+[U,D,V]=svd(X);
+[V2,D2]=eig(X)
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/pca_netlab.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,42 @@
+function [PCcoeff, PCvec] = pca(data, N)
+%PCA	Principal Components Analysis
+%
+%	Description
+%	 PCCOEFF = PCA(DATA) computes the eigenvalues of the covariance
+%	matrix of the dataset DATA and returns them as PCCOEFF.  These
+%	coefficients give the variance of DATA along the corresponding
+%	principal components.
+%
+%	PCCOEFF = PCA(DATA, N) returns the largest N eigenvalues.
+%
+%	[PCCOEFF, PCVEC] = PCA(DATA) returns the principal components as well
+%	as the coefficients.  This is considerably more computationally
+%	demanding than just computing the eigenvalues.
+%
+%	See also
+%	EIGDEC, GTMINIT, PPCA
+%
+
+%	Copyright (c) Ian T Nabney (1996-2001)
+
+if nargin == 1
+   N = size(data, 2);
+end
+
+if nargout == 1
+   evals_only = logical(1);
+else
+   evals_only = logical(0);
+end
+
+if N ~= round(N) | N < 1 | N > size(data, 2)
+   error('Number of PCs must be integer, >0, < dim');
+end
+
+% Find the sorted eigenvalues of the data covariance matrix
+if evals_only
+   PCcoeff = eigdec(cov(data), N);
+else
+  [PCcoeff, PCvec] = eigdec(cov(data), N);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/pick.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function [i,j] = pick(ndx)
+% PICK Pick an entry at random from a vector
+% function [i,j] = pick(ndx)
+%
+% i = ndx(j) for j ~ U(1:length(ndx))
+
+dist = normalize(ones(1,length(ndx)));
+j = sample_discrete(dist);
+i = ndx(j);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plotBox.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function [h, ht] =plotBox(box, col, str)
+% function h=plotBox(box, col, str)
+%
+% box = [xlow xhigh ylow yhigh]
+% col = color (default - red)
+% str = string printed at center (default '')
+
+if nargin < 2, col = 'r'; end
+if nargin < 3, str = ''; end
+
+box = double(box); % fails on single
+
+h = plot([box(1) box(2) box(2) box(1) box(1)], [ box(3) box(3) box(4) box(4) box(3)]);
+set(h, 'color', col);
+set(h, 'linewidth', 2);
+if ~isempty(str)
+  xc = mean(box(1:2));
+  yc = mean(box(3:4));
+  ht = text(xc, yc, str);
+else
+  ht = [];
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plotColors.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,10 @@
+function styles =  plotColors()
+
+colors =  ['r' 'b' 'k' 'g' 'c' 'y' 'm' ...
+	   'r' 'b' 'k' 'g' 'c' 'y' 'm'];
+symbols = ['o' 'x' '+' '>' '<' '^' 'v' ...
+	   '*' 'p' 'h' 's' 'd' 'o' 'x'];
+for i=1:length(colors)
+  styles{i} = sprintf('-%s%s', colors(i), symbols(i));
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plotROC.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function [falseAlarmRate, detectionRate, area, th] = plotROC(confidence, testClass, col, varargin)
+% function [falseAlarmRate, detectionRate, area, th] = plotroc(confidence, testClass, color)
+
+if nargin < 3, col = []; end
+
+[scale01] = process_options(varargin, 'scale01', 1);
+
+[falseAlarmRate detectionRate area th] = computeROC(confidence, testClass);
+
+if ~isempty(col)
+    h=plot(falseAlarmRate, detectionRate, [col '-']);
+    %set(h, 'linewidth', 2);
+    ex = 0.05*max(falseAlarmRate);
+    ey = 0.05;
+    if scale01
+      axis([0-ex max(falseAlarmRate)+ex 0-ey 1+ey])
+    else
+      % zoom in on the top left corner
+      axis([0-ex max(falseAlarmRate)*0.5+ex 0.5-ey 1+ey])
+    end
+    grid on
+    ylabel('detection rate')
+    %xlabel('# false alarms')
+    xlabel('false alarm rate')
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plotROCkpm.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,69 @@
+function [falseAlarmRate, detectionRate, area, th] = plotROC(confidence, testClass, col, varargin)
+% You pass the scores and the classes, and the function returns the false
+% alarm rate and the detection rate for different points across the ROC.
+%
+% [faR, dR] = plotROC(score, class)
+%
+%  faR (false alarm rate) is uniformly sampled from 0 to 1
+%  dR (detection rate) is computed using the scores.
+%
+% class = 0 => target absent
+% class = 1 => target present
+%
+% score is the output of the detector, or any other measure of detection.
+% There is no plot unless you add a third parameter that is the color of
+% the graph. For instance:
+% [faR, dR] = plotROC(score, class, 'r')
+%
+% faR, dR are size 1x1250
+
+if nargin < 3, col = []; end
+[scale01] = process_options(varargin, 'scale01', 1);
+
+S = rand('state');
+rand('state',0);
+confidence = confidence + rand(size(confidence))*10^(-10);
+rand('state',S)
+
+ndxAbs = find(testClass==0); % absent
+ndxPres = find(testClass==1); % present
+
+[th, j] = sort(confidence(ndxAbs));
+th = th(fix(linspace(1, length(th), 1250))); 
+
+cAbs = confidence(ndxAbs);
+cPres = confidence(ndxPres);
+for t=1:length(th)
+  if length(ndxPres) == 0
+    detectionRate(t) = 0;
+  else
+    detectionRate(t)  = sum(cPres>=th(t)) / length(ndxPres);
+  end
+  if length(ndxAbs) == 0
+    falseAlarmRate(t) = 0;
+  else
+    falseAlarmRate(t) = sum(cAbs>=th(t)) / length(ndxAbs);
+  end
+  
+  %detectionRate(t)  = sum(confidence(ndxPres)>=th(t)) / length(ndxPres);
+  %falseAlarmRate(t) = sum(confidence(ndxAbs)>=th(t)) / length(ndxAbs);
+  %detections(t)     = sum(confidence(ndxPres)>=th(t));
+  %falseAlarms(t)    = sum(confidence(ndxAbs)>=th(t));
+end
+
+area = sum(abs(falseAlarmRate(2:end) - falseAlarmRate(1:end-1)) .* detectionRate(2:end));
+
+if ~isempty(col)
+    h=plot(falseAlarmRate, detectionRate, [col '-']);
+    %set(h, 'linewidth', 2);
+    e = 0.05;
+    if scale01
+      axis([0-e 1+e 0-e 1+e])
+    else
+      % zoom in on the top left corner
+      axis([0-e 0.5+e 0.5-e 1+e])
+    end
+    grid on
+    ylabel('detection rate')
+    xlabel('false alarm rate')
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plot_axis_thru_origin.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+function plot_axis_thru_origin()
+
+lnx=line(get(gca,'xlim'),[0 0]); lny=line([0 0],get(gca,'ylim'));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plot_ellipse.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+% PLOT_ELLIPSE
+% h=plot_ellipse(x,y,theta,a,b)
+%
+% This routine plots an ellipse with centre (x,y), axis lengths a,b
+% with major axis at an angle of theta radians from the horizontal.
+
+%
+% Author: P. Fieguth
+%         Jan. 98
+%
+%http://ocho.uwaterloo.ca/~pfieguth/Teaching/372/plot_ellipse.m
+
+function h=plot_ellipse(x,y,theta,a,b)
+
+np = 100;
+ang = [0:np]*2*pi/np;
+R = [cos(theta) -sin(theta); sin(theta) cos(theta)];
+pts = [x;y]*ones(size(ang)) + R*[cos(ang)*a; sin(ang)*b];
+h=plot( pts(1,:), pts(2,:) );
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plot_matrix.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,48 @@
+function plot_matrix(G, bw)
+% PLOT_MATRIX Plot a 2D matrix as a grayscale image, and label the axes
+%
+% plot_matrix(M)
+%
+% For 0/1 matrices (eg. adjacency matrices), use
+% plot_matrix(M,1)
+
+if nargin < 2, bw = 0; end
+
+if 0
+  imagesc(G)
+  %image(G)
+  %colormap([1 1 1; 0 0 0]); % black squares on white background
+  %colormap(gray)
+  grid on
+  n = length(G);
+  
+  % shift the grid lines so they don't intersect the squares
+  set(gca,'xtick',1.5:1:n);
+  set(gca,'ytick',1.5:1:n);
+  
+  % Turn off the confusing labels, which are fractional
+  % Ideally we could shift the labels to lie between the axis lines...
+%  set(gca,'xticklabel', []);
+%  set(gca,'yticklabel', []);
+else
+  % solution provided by Jordan Rosenthal <jr@ece.gatech.edu>
+  % You can plot the grid lines manually:
+  % This uses the trick that a point with a value nan does not get plotted.
+  imagesc(G);
+  if bw
+    colormap([1 1 1; 0 0 0]);
+  end
+  n = length(G);
+  x = 1.5:1:n;
+  x = [ x; x; repmat(nan,1,n-1) ];
+  y = [ 0.5 n+0.5 nan ].';
+  y = repmat(y,1,n-1);
+  x = x(:);
+  y = y(:);
+  line(x,y,'linestyle',':','color','k');
+  line(y,x,'linestyle',':','color','k');
+  set(gca,'xtick',1:n)
+  set(gca,'ytick',1:n)
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plot_polygon.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+function out=plot_polygon(p, args, close_loop)
+% PLOT_POLYGON
+% function handle=plot_polygon(p, args, close_loop)
+% p(1,i), p(2,i) are the x/y coords of point i.
+% If non-empty, args are passed thru to the plot command.
+% If close_loop = 1, connect the last point to the first 
+
+% All rights reserved. Documentation updated April 1999.
+% Matt Kawski. http://math.la.asu.edu/~kawski
+% He calls it pplot
+
+if nargin < 2, args = []; end
+if nargin < 3, close_loop = 0; end
+
+if close_loop
+  p = [p p(:,1)];
+end
+
+if isempty(args)
+   out=plot(p(1,:),p(2,:));
+else   
+   out=plot(p(1,:),p(2,:),args);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plotcov2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,86 @@
+% PLOTCOV2 - Plots a covariance ellipse with major and minor axes
+%            for a bivariate Gaussian distribution.
+%
+% Usage:
+%   h = plotcov2(mu, Sigma[, OPTIONS]);
+% 
+% Inputs:
+%   mu    - a 2 x 1 vector giving the mean of the distribution.
+%   Sigma - a 2 x 2 symmetric positive semi-definite matrix giving
+%           the covariance of the distribution (or the zero matrix).
+%
+% Options:
+%   'conf'    - a scalar between 0 and 1 giving the confidence
+%               interval (i.e., the fraction of probability mass to
+%               be enclosed by the ellipse); default is 0.9.
+%   'num-pts' - the number of points to be used to plot the
+%               ellipse; default is 100.
+%
+% This function also accepts options for PLOT.
+%
+% Outputs:
+%   h     - a vector of figure handles to the ellipse boundary and
+%           its major and minor axes
+%
+% See also: PLOTCOV3
+
+% Copyright (C) 2002 Mark A. Paskin
+%
+% This program 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 2 of the License, or
+% (at your option) any later version.
+%
+% This program 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
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+% USA.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function h = plotcov2(mu, Sigma, varargin)
+
+if size(Sigma) ~= [2 2], error('Sigma must be a 2 by 2 matrix'); end
+if length(mu) ~= 2, error('mu must be a 2 by 1 vector'); end
+
+[p, ...
+ n, ...
+ plot_opts] = process_options(varargin, 'conf', 0.9, ...
+					'num-pts', 100);
+h = [];
+holding = ishold;
+if (Sigma == zeros(2, 2))
+  z = mu;
+else
+  % Compute the Mahalanobis radius of the ellipsoid that encloses
+  % the desired probability mass.
+  k = conf2mahal(p, 2);
+  % The major and minor axes of the covariance ellipse are given by
+  % the eigenvectors of the covariance matrix.  Their lengths (for
+  % the ellipse with unit Mahalanobis radius) are given by the
+  % square roots of the corresponding eigenvalues.
+  if (issparse(Sigma))
+    [V, D] = eigs(Sigma);
+  else
+    [V, D] = eig(Sigma);
+  end
+  % Compute the points on the surface of the ellipse.
+  t = linspace(0, 2*pi, n);
+  u = [cos(t); sin(t)];
+  w = (k * V * sqrt(D)) * u;
+  z = repmat(mu, [1 n]) + w;
+  % Plot the major and minor axes.
+  L = k * sqrt(diag(D));
+  h = plot([mu(1); mu(1) + L(1) * V(1, 1)], ...
+	   [mu(2); mu(2) + L(1) * V(2, 1)], plot_opts{:});
+  hold on;
+  h = [h; plot([mu(1); mu(1) + L(2) * V(1, 2)], ...
+	       [mu(2); mu(2) + L(2) * V(2, 2)], plot_opts{:})];
+end
+
+h = [h; plot(z(1, :), z(2, :), plot_opts{:})];
+if (~holding) hold off; end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plotcov2New.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,119 @@
+% PLOTCOV2 - Plots a covariance ellipsoid with axes for a bivariate
+%            Gaussian distribution.
+%
+% Usage:
+%   [h, s] = plotcov2(mu, Sigma[, OPTIONS]);
+% 
+% Inputs:
+%   mu    - a 2 x 1 vector giving the mean of the distribution.
+%   Sigma - a 2 x 2 symmetric positive semi-definite matrix giving
+%           the covariance of the distribution (or the zero matrix).
+%
+% Options:
+%   'conf'      - a scalar between 0 and 1 giving the confidence
+%                 interval (i.e., the fraction of probability mass to
+%                 be enclosed by the ellipse); default is 0.9.
+%   'num-pts'   - if the value supplied is n, then (n + 1)^2 points
+%                 to be used to plot the ellipse; default is 20.
+%   'label'     - if non-empty, a string that will label the
+%                 ellipsoid (default: [])
+%   'plot-axes' - a 0/1 flag indicating if the ellipsoid's axes
+%                 should be plotted (default: 1)
+%   'plot-opts' - a cell vector of arguments to be handed to PLOT3
+%                 to contol the appearance of the axes, e.g., 
+%                 {'Color', 'g', 'LineWidth', 1}; the default is {}
+%   'fill-color' - a color specifier; is this is not [], the
+%                  covariance ellipse is filled with this color
+%                  (default: [])
+% 
+% Outputs:
+%   h     - a vector of handles on the axis lines
+%
+% See also: PLOTCOV3
+
+% Copyright (C) 2002 Mark A. Paskin
+%
+% This program 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 2 of the License, or
+% (at your option) any later version.
+%
+% This program 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
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+% USA.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function [h, s] = plotcov2New(mu, Sigma, varargin)
+
+h = [];
+s = [];
+
+if size(Sigma) ~= [2 2], error('Sigma must be a 2 by 2 matrix'); end
+if length(mu) ~= 2, error('mu must be a 2 by 1 vector'); end
+
+Sigma = checkpsd(Sigma);
+
+[p, ...
+ n, ...
+ label, ...
+ plot_axes, ...
+ plot_opts, ...
+ fill_color] = process_options(varargin, 'conf', 0.9, ...
+			       'num-pts', 20, ...
+			       'label', [], ...
+			       'plot-axes', 1, ...
+			       'plot-opts', {}, ...
+			       'fill-color', []);
+holding = ishold;
+% Compute the Mahalanobis radius of the ellipsoid that encloses
+% the desired probability mass.
+k = conf2mahal(p, 2);
+% Scale the covariance matrix so the confidence region has unit
+% Mahalanobis distance.
+Sigma = Sigma * k;
+% The axes of the covariance ellipse are given by the eigenvectors of
+% the covariance matrix.  Their lengths (for the ellipse with unit
+% Mahalanobis radius) are given by the square roots of the
+% corresponding eigenvalues.
+[V, D] = eig(full(Sigma));
+V = real(V);
+D = real(D);
+D = abs(D);
+
+% Compute the points on the boundary of the ellipsoid.
+t = linspace(0, 2*pi, n);
+u = [cos(t(:))'; sin(t(:))'];
+w = (V * sqrt(D)) * u;
+z = repmat(mu(:), [1 n]) + w;
+h = [h; plot(z(1, :), z(2, :), plot_opts{:})];
+if (~isempty(fill_color))
+  s = patch(z(1, :), z(2, :), fill_color);
+end
+
+% Plot the axes.
+if (plot_axes)
+  hold on;
+  L = sqrt(diag(D));
+  h = plot([mu(1); mu(1) + L(1) * V(1, 1)], ...
+	   [mu(2); mu(2) + L(1) * V(2, 1)], plot_opts{:});
+  h = [h; plot([mu(1); mu(1) + L(2) * V(1, 2)], ...
+	       [mu(2); mu(2) + L(2) * V(2, 2)], plot_opts{:})];
+end
+
+
+if (~isempty(label))
+  th = text(mu(1), mu(2), label);
+  set(th, 'FontSize', 18);
+  set(th, 'FontName', 'Times');
+  set(th, 'FontWeight', 'bold');
+  set(th, 'FontAngle', 'italic');
+  set(th, 'HorizontalAlignment', 'center');
+end
+
+if (~holding & plot_axes) hold off; end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plotcov3.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,109 @@
+% PLOTCOV3 - Plots a covariance ellipsoid with axes for a trivariate
+%            Gaussian distribution.
+%
+% Usage:
+%   [h, s] = plotcov3(mu, Sigma[, OPTIONS]);
+% 
+% Inputs:
+%   mu    - a 3 x 1 vector giving the mean of the distribution.
+%   Sigma - a 3 x 3 symmetric positive semi-definite matrix giving
+%           the covariance of the distribution (or the zero matrix).
+%
+% Options:
+%   'conf'      - a scalar between 0 and 1 giving the confidence
+%                 interval (i.e., the fraction of probability mass to
+%                 be enclosed by the ellipse); default is 0.9.
+%   'num-pts'   - if the value supplied is n, then (n + 1)^2 points
+%                 to be used to plot the ellipse; default is 20.
+%   'plot-opts' - a cell vector of arguments to be handed to PLOT3
+%                 to contol the appearance of the axes, e.g., 
+%                 {'Color', 'g', 'LineWidth', 1}; the default is {}
+%   'surf-opts' - a cell vector of arguments to be handed to SURF
+%                 to contol the appearance of the ellipsoid
+%                 surface; a nice possibility that yields
+%                 transparency is: {'EdgeAlpha', 0, 'FaceAlpha',
+%                 0.1, 'FaceColor', 'g'}; the default is {}
+% 
+% Outputs:
+%   h     - a vector of handles on the axis lines
+%   s     - a handle on the ellipsoid surface object
+%
+% See also: PLOTCOV2
+
+% Copyright (C) 2002 Mark A. Paskin
+%
+% This program 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 2 of the License, or
+% (at your option) any later version.
+%
+% This program 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
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+% USA.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function [h, s] = plotcov3(mu, Sigma, varargin)
+
+if size(Sigma) ~= [3 3], error('Sigma must be a 3 by 3 matrix'); end
+if length(mu) ~= 3, error('mu must be a 3 by 1 vector'); end
+
+[p, ...
+ n, ...
+ plot_opts, ...
+ surf_opts] = process_options(varargin, 'conf', 0.9, ...
+					'num-pts', 20, ...
+			                'plot-opts', {}, ...
+			                'surf-opts', {});
+h = [];
+holding = ishold;
+if (Sigma == zeros(3, 3))
+  z = mu;
+else
+  % Compute the Mahalanobis radius of the ellipsoid that encloses
+  % the desired probability mass.
+  k = conf2mahal(p, 3);
+  % The axes of the covariance ellipse are given by the eigenvectors of
+  % the covariance matrix.  Their lengths (for the ellipse with unit
+  % Mahalanobis radius) are given by the square roots of the
+  % corresponding eigenvalues.
+  if (issparse(Sigma))
+    [V, D] = eigs(Sigma);
+  else
+    [V, D] = eig(Sigma);
+  end
+  if (any(diag(D) < 0))
+    error('Invalid covariance matrix: not positive semi-definite.');
+  end
+  % Compute the points on the surface of the ellipsoid.
+  t = linspace(0, 2*pi, n);
+  [X, Y, Z] = sphere(n);
+  u = [X(:)'; Y(:)'; Z(:)'];
+  w = (k * V * sqrt(D)) * u;
+  z = repmat(mu(:), [1 (n + 1)^2]) + w;
+
+  % Plot the axes.
+  L = k * sqrt(diag(D));
+  h = plot3([mu(1); mu(1) + L(1) * V(1, 1)], ...
+	    [mu(2); mu(2) + L(1) * V(2, 1)], ...
+	    [mu(3); mu(3) + L(1) * V(3, 1)], plot_opts{:});
+  hold on;
+  h = [h; plot3([mu(1); mu(1) + L(2) * V(1, 2)], ...
+		[mu(2); mu(2) + L(2) * V(2, 2)], ...
+		[mu(3); mu(3) + L(2) * V(3, 2)], plot_opts{:})];
+  h = [h; plot3([mu(1); mu(1) + L(3) * V(1, 3)], ...
+		[mu(2); mu(2) + L(3) * V(2, 3)], ...
+		[mu(3); mu(3) + L(3) * V(3, 3)], plot_opts{:})];
+end
+
+s = surf(reshape(z(1, :), [(n + 1) (n + 1)]), ...
+	 reshape(z(2, :), [(n + 1) (n + 1)]), ...
+	 reshape(z(3, :), [(n + 1) (n + 1)]), ...
+	 surf_opts{:});
+
+if (~holding) hold off; end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plotgauss1d.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function h = plotgauss1d(mu, sigma2)
+% function h = plotgauss1d(mu, sigma^2)
+% Example
+% plotgauss1d(0,5); hold on; h=plotgauss1d(0,2);set(h,'color','r')
+
+sigma = sqrt(sigma2);
+x = linspace(mu-3*sigma, mu+3*sigma, 100);
+p = gaussian_prob(x, mu, sigma2);
+h = plot(x, p, '-');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plotgauss2d.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,130 @@
+function h=plotgauss2d(mu, Sigma)
+% PLOTGAUSS2D Plot a 2D Gaussian as an ellipse with optional cross hairs
+% h=plotgauss2(mu, Sigma)
+%
+
+h = plotcov2(mu, Sigma);
+return;
+
+%%%%%%%%%%%%%%%%%%%%%%%%
+
+% PLOTCOV2 - Plots a covariance ellipse with major and minor axes
+%            for a bivariate Gaussian distribution.
+%
+% Usage:
+%   h = plotcov2(mu, Sigma[, OPTIONS]);
+% 
+% Inputs:
+%   mu    - a 2 x 1 vector giving the mean of the distribution.
+%   Sigma - a 2 x 2 symmetric positive semi-definite matrix giving
+%           the covariance of the distribution (or the zero matrix).
+%
+% Options:
+%   'conf'    - a scalar between 0 and 1 giving the confidence
+%               interval (i.e., the fraction of probability mass to
+%               be enclosed by the ellipse); default is 0.9.
+%   'num-pts' - the number of points to be used to plot the
+%               ellipse; default is 100.
+%
+% This function also accepts options for PLOT.
+%
+% Outputs:
+%   h     - a vector of figure handles to the ellipse boundary and
+%           its major and minor axes
+%
+% See also: PLOTCOV3
+
+% Copyright (C) 2002 Mark A. Paskin
+
+function h = plotcov2(mu, Sigma, varargin)
+
+if size(Sigma) ~= [2 2], error('Sigma must be a 2 by 2 matrix'); end
+if length(mu) ~= 2, error('mu must be a 2 by 1 vector'); end
+
+[p, ...
+ n, ...
+ plot_opts] = process_options(varargin, 'conf', 0.9, ...
+					'num-pts', 100);
+h = [];
+holding = ishold;
+if (Sigma == zeros(2, 2))
+  z = mu;
+else
+  % Compute the Mahalanobis radius of the ellipsoid that encloses
+  % the desired probability mass.
+  k = conf2mahal(p, 2);
+  % The major and minor axes of the covariance ellipse are given by
+  % the eigenvectors of the covariance matrix.  Their lengths (for
+  % the ellipse with unit Mahalanobis radius) are given by the
+  % square roots of the corresponding eigenvalues.
+  if (issparse(Sigma))
+    [V, D] = eigs(Sigma);
+  else
+    [V, D] = eig(Sigma);
+  end
+  % Compute the points on the surface of the ellipse.
+  t = linspace(0, 2*pi, n);
+  u = [cos(t); sin(t)];
+  w = (k * V * sqrt(D)) * u;
+  z = repmat(mu, [1 n]) + w;
+  % Plot the major and minor axes.
+  L = k * sqrt(diag(D));
+  h = plot([mu(1); mu(1) + L(1) * V(1, 1)], ...
+	   [mu(2); mu(2) + L(1) * V(2, 1)], plot_opts{:});
+  hold on;
+  h = [h; plot([mu(1); mu(1) + L(2) * V(1, 2)], ...
+	       [mu(2); mu(2) + L(2) * V(2, 2)], plot_opts{:})];
+end
+
+h = [h; plot(z(1, :), z(2, :), plot_opts{:})];
+if (~holding) hold off; end
+
+%%%%%%%%%%%%
+
+% CONF2MAHAL - Translates a confidence interval to a Mahalanobis
+%              distance.  Consider a multivariate Gaussian
+%              distribution of the form
+%
+%   p(x) = 1/sqrt((2 * pi)^d * det(C)) * exp((-1/2) * MD(x, m, inv(C)))
+%
+%              where MD(x, m, P) is the Mahalanobis distance from x
+%              to m under P:
+%
+%                 MD(x, m, P) = (x - m) * P * (x - m)'
+%
+%              A particular Mahalanobis distance k identifies an
+%              ellipsoid centered at the mean of the distribution.
+%              The confidence interval associated with this ellipsoid
+%              is the probability mass enclosed by it.  Similarly,
+%              a particular confidence interval uniquely determines
+%              an ellipsoid with a fixed Mahalanobis distance.
+%
+%              If X is an d dimensional Gaussian-distributed vector,
+%              then the Mahalanobis distance of X is distributed
+%              according to the Chi-squared distribution with d
+%              degrees of freedom.  Thus, the Mahalanobis distance is
+%              determined by evaluating the inverse cumulative
+%              distribution function of the chi squared distribution
+%              up to the confidence value.
+%
+% Usage:
+% 
+%   m = conf2mahal(c, d);
+%
+% Inputs:
+%
+%   c    - the confidence interval
+%   d    - the number of dimensions of the Gaussian distribution
+%
+% Outputs:
+%
+%   m    - the Mahalanobis radius of the ellipsoid enclosing the
+%          fraction c of the distribution's probability mass
+%
+% See also: MAHAL2CONF
+
+% Copyright (C) 2002 Mark A. Paskin
+
+function m = conf2mahal(c, d)
+
+m = chi2inv(c, d); % matlab stats toolbox
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/plotgauss2d_old.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+function h=plotgauss2d_old(mu, Sigma, plot_cross)
+% PLOTGAUSS2D Plot a 2D Gaussian as an ellipse with optional cross hairs
+% h=plotgauss2(mu, Sigma)
+% 
+% h=plotgauss2(mu, Sigma, 1) also plots the major and minor axes
+%
+% Example
+% clf; S=[2 1; 1 2]; plotgauss2d([0;0], S, 1); axis equal
+
+if nargin < 3, plot_cross = 0; end
+[V,D]=eig(Sigma);
+lam1 = D(1,1);
+lam2 = D(2,2);
+v1 = V(:,1);
+v2 = V(:,2);
+%assert(approxeq(v1' * v2, 0))
+if v1(1)==0
+  theta = 0; % horizontal
+else
+  theta = atan(v1(2)/v1(1));
+end
+a = sqrt(lam1);
+b = sqrt(lam2);
+h=plot_ellipse(mu(1), mu(2), theta, a,b);
+
+if plot_cross
+  mu = mu(:);
+  held = ishold;
+  hold on
+  minor1 = mu-a*v1; minor2 = mu+a*v1;
+  hminor = line([minor1(1) minor2(1)], [minor1(2) minor2(2)]);
+  
+  major1 = mu-b*v2; major2 = mu+b*v2;
+  hmajor = line([major1(1) major2(1)], [major1(2) major2(2)]);
+  %set(hmajor,'color','r')
+  if ~held
+    hold off
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/polygon_area.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function  a = polygon_area(x,y)
+% AREA  Area of a planar polygon.
+%	AREA(X,Y) Calculates the area of a 2-dimensional
+%	polygon formed by vertices with coordinate vectors
+%	X and Y. The result is direction-sensitive: the
+%	area is positive if the bounding contour is counter-
+%	clockwise and negative if it is clockwise.
+%
+%	See also TRAPZ.
+
+%  Copyright (c) 1995 by Kirill K. Pankratov,
+%	kirill@plume.mit.edu.
+%	04/20/94, 05/20/95  
+
+ % Make polygon closed .............
+x = [x(:); x(1)];
+y = [y(:); y(1)];
+
+ % Calculate contour integral Int -y*dx  (same as Int x*dy).
+lx = length(x);
+a = -(x(2:lx)-x(1:lx-1))'*(y(1:lx-1)+y(2:lx))/2;
+a = abs(a);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/polygon_centroid.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,79 @@
+function [x0,y0] = centroid(x,y)
+% CENTROID Center of mass of a polygon.
+%	[X0,Y0] = CENTROID(X,Y) Calculates centroid 
+%	(center of mass) of planar polygon with vertices 
+%	coordinates X, Y.
+%	Z0 = CENTROID(X+i*Y) returns Z0=X0+i*Y0 the same
+%	as CENTROID(X,Y).
+
+%  Copyright (c) 1995 by Kirill K. Pankratov,
+%       kirill@plume.mit.edu.
+%       06/01/95, 06/07/95
+
+% Algorithm:
+%  X0 = Int{x*ds}/Int{ds}, where ds - area element
+%  so that Int{ds} is total area of a polygon.
+%    Using Green's theorem the area integral can be 
+%  reduced to a contour integral:
+%  Int{x*ds} = -Int{x^2*dy}, Int{ds} = Int{x*dy} along
+%  the perimeter of a polygon.
+%    For a polygon as a sequence of line segments
+%  this can be reduced exactly to a sum:
+%  Int{x^2*dy} = Sum{ (x_{i}^2+x_{i+1}^2+x_{i}*x_{i+1})*
+%  (y_{i+1}-y_{i})}/3;
+%  Int{x*dy} = Sum{(x_{i}+x_{i+1})(y_{i+1}-y_{i})}/2.
+%    Similarly
+%  Y0 = Int{y*ds}/Int{ds}, where
+%  Int{y*ds} = Int{y^2*dx} = 
+%  = Sum{ (y_{i}^2+y_{i+1}^2+y_{i}*y_{i+1})*
+%  (x_{i+1}-x_{i})}/3.
+
+ % Handle input ......................
+if nargin==0, help centroid, return, end
+if nargin==1
+  sz = size(x);
+  if sz(1)==2      % Matrix 2 by n
+    y = x(2,:); x = x(1,:);
+  elseif sz(2)==2  % Matrix n by 2
+    y = x(:,2); x = x(:,1);
+  else
+    y = imag(x);
+    x = real(x);
+  end
+end 
+
+ % Make a polygon closed ..............
+x = [x(:); x(1)];
+y = [y(:); y(1)];
+
+ % Check length .......................
+l = length(x);
+if length(y)~=l
+  error(' Vectors x and y must have the same length')
+end
+
+ % X-mean: Int{x^2*dy} ................
+del = y(2:l)-y(1:l-1);
+v = x(1:l-1).^2+x(2:l).^2+x(1:l-1).*x(2:l);
+x0 = v'*del;
+
+ % Y-mean: Int{y^2*dx} ................
+del = x(2:l)-x(1:l-1);
+v = y(1:l-1).^2+y(2:l).^2+y(1:l-1).*y(2:l);
+y0 = v'*del;
+
+ % Calculate area: Int{y*dx} ..........
+a = (y(1:l-1)+y(2:l))'*del;
+tol= 2*eps;
+if abs(a)<tol
+  disp(' Warning: area of polygon is close to 0')
+  a = a+sign(a)*tol+(~a)*tol;
+end
+ % Multiplier
+a = 1/3/a;
+
+ % Divide by area .....................
+x0 = -x0*a;
+y0 =  y0*a;
+
+if nargout < 2, x0 = x0+i*y0; end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/polygon_intersect.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,60 @@
+function [is,S] = isintpl(x1,y1,x2,y2)
+% ISINTPL Check for intersection of polygons.
+%	[IS,S] = ISINTPL(X1,Y1,X2,Y2) Accepts coordinates
+%	X1,Y1 and X2, Y2 of two polygons. Returns scalar
+%	IS equal to 1 if these polygons intersect each other
+%	and 0 if they do not.
+%	Also returns Boolean matrix S of the size length(X1)
+%	by length(X2) so that {ij} element of which is 1 if 
+%	line segments i to i+1 of the first polygon and 
+%	j to j+1 of the second polygon intersect each other,
+%	0 if they don't and .5 if they "touch" each other.
+
+%  Copyright (c) 1995 by Kirill K. Pankratov,
+%       kirill@plume.mit.edu.
+%       06/20/95, 08/25/95
+
+
+ % Handle input ...................................
+if nargin==0, help isintpl, return, end
+if nargin<4
+  error(' Not enough input arguments ')
+end
+
+ % Make column vectors and check sizes ............
+x1 = x1(:); y1 = y1(:);
+x2 = x2(:); y2 = y2(:);
+l1 = length(x1);
+l2 = length(x2);
+if length(y1)~=l1 | length(y2)~=l2
+  error('(X1,Y1) and (X2,Y2) must pair-wise have the same length.')
+end
+
+ % Quick exit if empty
+if l1<1 | l2<1, is = []; S = []; return, end
+
+ % Check if their ranges are intersecting .........
+lim1 = [min(x1) max(x1)]';
+lim2 = [min(x2) max(x2)]';
+isx = interval(lim1,lim2);  % X-ranges
+lim1 = [min(y1) max(y1)]';
+lim2 = [min(y2) max(y2)]';
+isy = interval(lim1,lim2);  % Y-ranges
+is = isx & isy;
+S = zeros(l2,l1);
+
+if ~is, return, end  % Early exit if disparate limits
+
+ % Indexing .......................................
+[i11,i12] = meshgrid(1:l1,1:l2);
+[i21,i22] = meshgrid([2:l1 1],[2:l2 1]);
+i11 = i11(:); i12 = i12(:);
+i21 = i21(:); i22 = i22(:);
+
+ % Calculate matrix of intersections ..............
+S(:) = iscross([x1(i11) x1(i21)]',[y1(i11) y1(i21)]',...
+               [x2(i12) x2(i22)]',[y2(i12) y2(i22)]')';
+
+S = S';
+is  = any(any(S));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/previewfig.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,49 @@
+function f = previewfig(h,varargin)
+%PREVIEWFIG  Preview a figure to be exported using EXPORTFIG.
+%   F = PREVIEWFIG(H) creates a preview of H with the default
+%   EXPORTFIG options and returns the preview's figure handle in F.
+%   F = PREVIEWFIG(H,OPTIONS) creates a preview with OPTIONS as
+%   described in EXPORTFIG.
+%   PREVIEWFIG(...,PARAM1,VAL1,PARAM2,VAL2,...) creates a preview
+%   with the specified parameter-value pairs to H as described in
+%   EXPORTFIG. 
+%
+%   See also EXPORTFIG, APPLYTOFIG, RESTOREFIG.
+
+%  Copyright 2000 Ben Hinkle
+%  Email bug reports and comments to bhinkle@mathworks.com
+
+filename = [tempname, '.png'];
+args = {'resolution',0,'format','png'};
+if nargin > 1
+  exportfig(h, filename, varargin{:}, args{:});
+else
+  exportfig(h, filename, args{:});
+end
+
+X = imread(filename,'png');
+height = size(X,1);
+width = size(X,2);
+delete(filename);
+f = figure( 'Name', 'Preview', ...
+	    'Menubar', 'none', ...
+	    'NumberTitle', 'off', ...
+	    'Visible', 'off');
+image(X);
+axis image;
+ax = findobj(f, 'type', 'axes');
+axesPos = [0 0 width height];
+set(ax, 'Units', 'pixels', ...
+	'Position', axesPos, ...
+	'Visible', 'off');
+figPos = get(f,'Position');
+rootSize = get(0,'ScreenSize');
+figPos(3:4) = axesPos(3:4);
+if figPos(1) + figPos(3) > rootSize(3)
+  figPos(1) = rootSize(3) - figPos(3) - 50;
+end
+if figPos(2) + figPos(4) > rootSize(4)
+  figPos(2) = rootSize(4) - figPos(4) - 50;
+end
+set(f, 'Position',figPos, ...
+       'Visible', 'on');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/process_options.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,132 @@
+% PROCESS_OPTIONS - Processes options passed to a Matlab function.
+%                   This function provides a simple means of
+%                   parsing attribute-value options.  Each option is
+%                   named by a unique string and is given a default
+%                   value.
+%
+% Usage:  [var1, var2, ..., varn[, unused]] = ...
+%           process_options(args, ...
+%                           str1, def1, str2, def2, ..., strn, defn)
+%
+% Arguments:   
+%            args            - a cell array of input arguments, such
+%                              as that provided by VARARGIN.  Its contents
+%                              should alternate between strings and
+%                              values.
+%            str1, ..., strn - Strings that are associated with a 
+%                              particular variable
+%            def1, ..., defn - Default values returned if no option
+%                              is supplied
+%
+% Returns:
+%            var1, ..., varn - values to be assigned to variables
+%            unused          - an optional cell array of those 
+%                              string-value pairs that were unused;
+%                              if this is not supplied, then a
+%                              warning will be issued for each
+%                              option in args that lacked a match.
+%
+% Examples:
+%
+% Suppose we wish to define a Matlab function 'func' that has
+% required parameters x and y, and optional arguments 'u' and 'v'.
+% With the definition
+%
+%   function y = func(x, y, varargin)
+%
+%     [u, v] = process_options(varargin, 'u', 0, 'v', 1);
+%
+% calling func(0, 1, 'v', 2) will assign 0 to x, 1 to y, 0 to u, and 2
+% to v.  The parameter names are insensitive to case; calling 
+% func(0, 1, 'V', 2) has the same effect.  The function call
+% 
+%   func(0, 1, 'u', 5, 'z', 2);
+%
+% will result in u having the value 5 and v having value 1, but
+% will issue a warning that the 'z' option has not been used.  On
+% the other hand, if func is defined as
+%
+%   function y = func(x, y, varargin)
+%
+%     [u, v, unused_args] = process_options(varargin, 'u', 0, 'v', 1);
+%
+% then the call func(0, 1, 'u', 5, 'z', 2) will yield no warning,
+% and unused_args will have the value {'z', 2}.  This behaviour is
+% useful for functions with options that invoke other functions
+% with options; all options can be passed to the outer function and
+% its unprocessed arguments can be passed to the inner function.
+
+% Copyright (C) 2002 Mark A. Paskin
+%
+% This program 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 2 of the License, or
+% (at your option) any later version.
+%
+% This program 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
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+% USA.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+function [varargout] = process_options(args, varargin)
+
+% Check the number of input arguments
+n = length(varargin);
+if (mod(n, 2))
+  error('Each option must be a string/value pair.');
+end
+
+% Check the number of supplied output arguments
+if (nargout < (n / 2))
+  error('Insufficient number of output arguments given');
+elseif (nargout == (n / 2))
+  warn = 1;
+  nout = n / 2;
+else
+  warn = 0;
+  nout = n / 2 + 1;
+end
+
+% Set outputs to be defaults
+varargout = cell(1, nout);
+for i=2:2:n
+  varargout{i/2} = varargin{i};
+end
+
+% Now process all arguments
+nunused = 0;
+for i=1:2:length(args)
+  found = 0;
+  for j=1:2:n
+    if strcmpi(args{i}, varargin{j})
+      varargout{(j + 1)/2} = args{i + 1};
+      found = 1;
+      break;
+    end
+  end
+  if (~found)
+    if (warn)
+      warning(sprintf('Option ''%s'' not used.', args{i}));
+      args{i}
+    else
+      nunused = nunused + 1;
+      unused{2 * nunused - 1} = args{i};
+      unused{2 * nunused} = args{i + 1};
+    end
+  end
+end
+
+% Assign the unused arguments
+if (~warn)
+  if (nunused)
+    varargout{nout} = unused;
+  else
+    varargout{nout} = cell(0);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/rand_psd.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function M = rand_psd(d, d2, k)
+% Create a random positive definite matrix of size d by d by k (k defaults to 1)
+% M = rand_psd(d, d2, k)   default: d2 = d, k = 1
+
+if nargin<2, d2 = d; end
+if nargin<3, k = 1; end
+if d2 ~= d, error('must be square'); end
+
+M = zeros(d,d,k);
+for i=1:k
+  A = rand(d);
+  M(:,:,i) = A*A';
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/rectintC.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function [overlap, normoverlap] = rectintC(A,B)
+%
+% A(i,:) = [x y w h]
+% B(j,:) = [x y w h]
+% overlap(i,j) = area of intersection
+% normoverlap(i,j) = overlap(i,j) / min(area(i), area(j))
+%
+% Same as built-in rectint, but faster and uses less memory (since avoids repmat).
+
+
+leftA = A(:,1);
+bottomA = A(:,2);
+rightA = leftA + A(:,3);
+topA = bottomA + A(:,4);
+
+leftB = B(:,1)';
+bottomB = B(:,2)';
+rightB = leftB + B(:,3)';
+topB = bottomB + B(:,4)';
+
+verbose = 0;
+[overlap, normoverlap] = rectintLoopC(leftA, rightA, topA, bottomA, leftB, rightB, topB, bottomB, verbose);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/rectintLoopC.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,71 @@
+
+#include "mex.h"
+#include <stdio.h>
+
+#define MAX(x,y)  ((x)>(y) ? (x) : (y))
+#define MIN(x,y)  ((x)<(y) ? (x) : (y))
+
+void mexFunction(
+        int nlhs,       mxArray *plhs[],
+        int nrhs, const mxArray *prhs[]
+        )
+{
+  int j,k,m,n,nzmax,*irs,*jcs, *irs2, *jcs2;
+  double *overlap, *overlap2, tmp, areaA, areaB;
+  double *leftA, *rightA, *topA, *bottomA;
+  double *leftB, *rightB, *topB, *bottomB;
+  double *verbose;
+
+  m = MAX(mxGetM(prhs[0]), mxGetN(prhs[0]));
+  n = MAX(mxGetM(prhs[4]), mxGetN(prhs[4]));
+  /* printf("A=%d, B=%d\n", m, n); */
+
+  leftA = mxGetPr(prhs[0]);
+  rightA = mxGetPr(prhs[1]);
+  topA = mxGetPr(prhs[2]);
+  bottomA = mxGetPr(prhs[3]);
+
+  leftB = mxGetPr(prhs[4]);
+  rightB = mxGetPr(prhs[5]);
+  topB = mxGetPr(prhs[6]);
+  bottomB = mxGetPr(prhs[7]);
+
+  verbose = mxGetPr(prhs[8]);
+
+  plhs[0] = mxCreateDoubleMatrix(m,n, mxREAL);
+  overlap  = mxGetPr(plhs[0]);
+
+  plhs[1] = mxCreateDoubleMatrix(m,n, mxREAL);
+  overlap2  = mxGetPr(plhs[1]);
+
+  k = 0; 
+  for (j = 0; (j < n); j++) {
+    int i;
+    for (i = 0; (i < m); i++) {
+      tmp = (MAX(0, MIN(rightA[i], rightB[j]) - MAX(leftA[i], leftB[j]) )) * 
+	(MAX(0, MIN(topA[i], topB[j]) - MAX(bottomA[i], bottomB[j]) ));
+
+      if (tmp > 0) {
+	overlap[k] = tmp;
+	
+	areaA = (rightA[i]-leftA[i])*(topA[i]-bottomA[i]);
+	areaB = (rightB[j]-leftB[j])*(topB[j]-bottomB[j]);
+	overlap2[k] = tmp/MIN(areaA, areaB);
+	
+	if (*verbose) {
+	  printf("j=%d,i=%d,overlap=%5.3f, norm=%5.3f\n", j,i, overlap[k], overlap2[k]);
+	}
+      }
+
+      k++;
+    }
+  }
+}
+
+
+
+
+
+
+
+
Binary file _FullBNT/KPMtools/rectintLoopC.dll has changed
Binary file _FullBNT/KPMtools/rectintLoopC.mexglx has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/rectintSparse.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function [overlap, normoverlap] = rectintSparse(A,B)
+%
+% A(i,:) = [x y w h]
+% B(j,:) = [x y w h]
+% overlap(i,j) = area of intersection
+% normoverla(i,j)
+%
+% Same as built-in rectint, but uses less memory.
+% Use rectintSparseC for a faster version.
+%
+
+leftA = A(:,1);
+bottomA = A(:,2);
+rightA = leftA + A(:,3);
+topA = bottomA + A(:,4);
+
+leftB = B(:,1)';
+bottomB = B(:,2)';
+rightB = leftB + B(:,3)';
+topB = bottomB + B(:,4)';
+
+numRectA = size(A,1);
+numRectB = size(B,1);
+
+%out = rectintSparseLoopC(leftA, rightA, topA, bottomA, leftB, rightB, topB, bottomB);
+
+nnz = ceil(0.2*numRectA*numRectB); % guess of number of non-zeroes
+overlap = sparse([], [], [], numRectA, numRectB, nnz);
+normoverlap = sparse([], [], [], numRectA, numRectB, nnz);
+for j=1:numRectB
+  for i=1:numRectA
+    tmp = (max(0, min(rightA(i), rightB(j)) - max(leftA(i), leftB(j)) ) ) .* ...
+	(max(0, min(topA(i), topB(j)) - max(bottomA(i), bottomB(j)) ) );
+    if tmp>0
+      overlap(i,j) = tmp;
+      areaA = (rightA(i)-leftA(i))*(topA(i)-bottomA(i));
+      areaB = (rightB(j)-leftB(j))*(topB(j)-bottomB(j));
+      normoverlap(i,j) = min(tmp/areaA, tmp/areaB);
+    end
+    %fprintf('j=%d, i=%d, overlap=%5.3f, norm=%5.3f\n',...
+    %	    j, i, overlap(i,j), normoverlap(i,j));
+  end
+end
+
+
+if 0
+N = size(bboxDense01,2); % 1000;
+rect = bboxToRect(bboxDense01)';
+A = rect(1:2,:);
+B = rect(1:N,:);
+
+tic; out1 = rectint(A, B); toc
+tic; out2 = rectintSparse(A, B); toc
+tic; out3 = rectintSparseC(A, B); toc
+tic; out4 = rectintC(A, B); toc
+assert(approxeq(out1, out2))
+assert(approxeq(out1, full(out3)))
+assert(approxeq(out1, out4))
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/rectintSparseC.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+function [overlap, normoverlap] = rectintSparseC(A,B)
+%
+% function [area, normarea] = rectintSparseC(A,B)
+% A(i,:) = [x y w h]
+% B(j,:) = [x y w h]
+% out(i,j) = area of intersection
+%
+% Same as built-in rectint, but uses less memory.
+% Also, returns area of overlap normalized by area of patch.
+% See rectintSparse
+
+if isempty(A) | isempty(B)
+  overlap = [];
+  normoverlap = [];
+  return;
+end
+
+leftA = A(:,1);
+bottomA = A(:,2);
+rightA = leftA + A(:,3);
+topA = bottomA + A(:,4);
+
+leftB = B(:,1)';
+bottomB = B(:,2)';
+rightB = leftB + B(:,3)';
+topB = bottomB + B(:,4)';
+
+numRectA = size(A,1);
+numRectB = size(B,1);
+
+verbose = 0;
+[overlap, normoverlap] = rectintSparseLoopC(leftA, rightA, topA, bottomA, leftB, rightB, topB, bottomB, verbose);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/rectintSparseLoopC.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,147 @@
+/* This is based on
+http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_external/ch04cr12.shtml
+
+See rectintSparse.m for the matlab version of this code.
+
+*/
+
+#include <math.h> /* Needed for the ceil() prototype. */
+#include "mex.h"
+#include <stdio.h>
+
+/* If you are using a compiler that equates NaN to be zero, you 
+ * must compile this example using the flag  -DNAN_EQUALS_ZERO.
+ * For example:
+ *
+ *     mex -DNAN_EQUALS_ZERO fulltosparse.c
+ *
+ * This will correctly define the IsNonZero macro for your C
+ * compiler.
+ */
+
+#if defined(NAN_EQUALS_ZERO)
+#define IsNonZero(d) ((d) != 0.0 || mxIsNaN(d))
+#else
+#define IsNonZero(d) ((d) != 0.0)
+#endif
+
+#define MAX(x,y)  ((x)>(y) ? (x) : (y))
+#define MIN(x,y)  ((x)<(y) ? (x) : (y))
+
+void mexFunction(
+        int nlhs,       mxArray *plhs[],
+        int nrhs, const mxArray *prhs[]
+        )
+{
+  /* Declare variables. */
+  int j,k,m,n,nzmax,*irs,*jcs, *irs2, *jcs2;
+  double *overlap, *overlap2, tmp, areaA, areaB;
+  double percent_sparse;
+  double *leftA, *rightA, *topA, *bottomA;
+  double *leftB, *rightB, *topB, *bottomB;
+  double *verbose;
+
+  /* Get the size and pointers to input data. */
+  m = MAX(mxGetM(prhs[0]), mxGetN(prhs[0]));
+  n = MAX(mxGetM(prhs[4]), mxGetN(prhs[4]));
+  /* printf("A=%d, B=%d\n", m, n); */
+
+  leftA = mxGetPr(prhs[0]);
+  rightA = mxGetPr(prhs[1]);
+  topA = mxGetPr(prhs[2]);
+  bottomA = mxGetPr(prhs[3]);
+
+  leftB = mxGetPr(prhs[4]);
+  rightB = mxGetPr(prhs[5]);
+  topB = mxGetPr(prhs[6]);
+  bottomB = mxGetPr(prhs[7]);
+
+  verbose = mxGetPr(prhs[8]);
+
+    /* Allocate space for sparse matrix. 
+     * NOTE:  Assume at most 20% of the data is sparse.  Use ceil
+     * to cause it to round up. 
+     */
+
+  percent_sparse = 0.01;
+  nzmax = (int)ceil((double)m*(double)n*percent_sparse);
+
+  plhs[0] = mxCreateSparse(m,n,nzmax,0);
+  overlap  = mxGetPr(plhs[0]);
+  irs = mxGetIr(plhs[0]);
+  jcs = mxGetJc(plhs[0]);
+
+  plhs[1] = mxCreateSparse(m,n,nzmax,0);
+  overlap2  = mxGetPr(plhs[1]);
+  irs2 = mxGetIr(plhs[1]);
+  jcs2 = mxGetJc(plhs[1]);
+
+    
+  /* Assign nonzeros. */
+  k = 0; 
+  for (j = 0; (j < n); j++) {
+    int i;
+    jcs[j] = k; 
+    jcs2[j] = k; 
+    for (i = 0; (i < m); i++) {
+      tmp = (MAX(0, MIN(rightA[i], rightB[j]) - MAX(leftA[i], leftB[j]) )) * 
+	(MAX(0, MIN(topA[i], topB[j]) - MAX(bottomA[i], bottomB[j]) ));
+      
+      if (*verbose) {
+	printf("j=%d,i=%d,tmp=%5.3f\n", j,i,tmp);
+      }
+
+      if (IsNonZero(tmp)) {
+
+        /* Check to see if non-zero element will fit in 
+         * allocated output array.  If not, increase
+         * percent_sparse by 20%, recalculate nzmax, and augment
+         * the sparse array.
+         */
+        if (k >= nzmax) {
+          int oldnzmax = nzmax;
+          percent_sparse += 0.2;
+          nzmax = (int)ceil((double)m*(double)n*percent_sparse);
+
+          /* Make sure nzmax increases atleast by 1. */
+          if (oldnzmax == nzmax) 
+            nzmax++;
+	  printf("reallocating from %d to %d\n", oldnzmax, nzmax);
+
+          mxSetNzmax(plhs[0], nzmax); 
+          mxSetPr(plhs[0], mxRealloc(overlap, nzmax*sizeof(double)));
+          mxSetIr(plhs[0], mxRealloc(irs, nzmax*sizeof(int)));
+          overlap  = mxGetPr(plhs[0]);
+          irs = mxGetIr(plhs[0]);
+
+          mxSetNzmax(plhs[1], nzmax); 
+          mxSetPr(plhs[1], mxRealloc(overlap2, nzmax*sizeof(double)));
+          mxSetIr(plhs[1], mxRealloc(irs2, nzmax*sizeof(int)));
+          overlap2  = mxGetPr(plhs[1]);
+          irs2 = mxGetIr(plhs[1]);
+        }
+
+        overlap[k] = tmp;
+        irs[k] = i;
+	
+	areaA = (rightA[i]-leftA[i])*(topA[i]-bottomA[i]);
+	areaB = (rightB[j]-leftB[j])*(topB[j]-bottomB[j]);
+	overlap2[k] = MIN(tmp/areaA, tmp/areaB);
+	irs2[k] = i;
+
+        k++;
+      } /* IsNonZero */
+    } /* for i */
+  }
+  jcs[n] = k;
+  jcs2[n] = k;
+  
+}
+
+
+
+
+
+
+
+
Binary file _FullBNT/KPMtools/rectintSparseLoopC.dll has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/repmatC.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,149 @@
+/*
+mex -c mexutil.c
+mex repmat.c mexutil.obj
+to check for warnings:
+gcc -Wall -I/cygdrive/c/MATLAB6p1/extern/include -c repmat.c
+*/
+#include "mexutil.h"
+#include <string.h>
+
+/* repeat a block of memory rep times */
+void memrep(char *dest, size_t chunk, int rep)
+{
+#if 0
+  /* slow way */
+  int i;
+  char *p = dest;
+  for(i=1;i<rep;i++) {
+    p += chunk;
+    memcpy(p, dest, chunk);
+  }
+#else
+  /* fast way */
+  if(rep == 1) return;
+  memcpy(dest + chunk, dest, chunk); 
+  if(rep & 1) {
+    dest += chunk;
+    memcpy(dest + chunk, dest, chunk);
+  }
+  /* now repeat using a block twice as big */
+  memrep(dest, chunk<<1, rep>>1);
+#endif
+}
+
+void repmat(char *dest, const char *src, int ndim, int *destdimsize, 
+	    int *dimsize, const int *dims, int *rep) 
+{
+  int d = ndim-1;
+  int i, chunk;
+  /* copy the first repetition into dest */
+  if(d == 0) {
+    chunk = dimsize[0];
+    memcpy(dest,src,chunk);
+  }
+  else {
+    /* recursively repeat each slice of src */
+    for(i=0;i<dims[d];i++) {
+      repmat(dest + i*destdimsize[d-1], src + i*dimsize[d-1], 
+	     ndim-1, destdimsize, dimsize, dims, rep);
+    }
+    chunk = destdimsize[d-1]*dims[d];
+  }
+  /* copy the result rep-1 times */
+  memrep(dest,chunk,rep[d]);
+}
+
+void mexFunction(int nlhs, mxArray *plhs[],
+                 int nrhs, const mxArray *prhs[])
+{
+  const mxArray *srcmat;
+  int ndim, *dimsize, eltsize;
+  const int *dims;
+  int ndimdest, *destdims, *destdimsize;
+  char *src, *dest;
+  int *rep;
+  int i,nrep;
+  int extra_rep = 1;
+  int empty;
+
+  if(nrhs < 2) mexErrMsgTxt("Usage: xrepmat(A, [N M ...])");
+  srcmat = prhs[0];
+  if(mxIsSparse(srcmat)) {
+    mexErrMsgTxt("Sorry, can't handle sparse matrices yet.");
+  }
+  if(mxIsCell(srcmat)) {
+    mexErrMsgTxt("Sorry, can't handle cell arrays yet.");
+  }
+  ndim = mxGetNumberOfDimensions(srcmat);
+  dims = mxGetDimensions(srcmat);
+  eltsize = mxGetElementSize(srcmat);
+
+  /* compute dimension sizes */
+  dimsize = mxCalloc(ndim, sizeof(int));
+  dimsize[0] = eltsize*dims[0];
+  for(i=1;i<ndim;i++) dimsize[i] = dimsize[i-1]*dims[i];
+
+  /* determine repetition vector */
+  ndimdest = ndim;
+  if(nrhs == 2) {
+    nrep = mxGetN(prhs[1]);
+    if(nrep > ndimdest) ndimdest = nrep;
+    rep = mxCalloc(ndimdest, sizeof(int));
+    for(i=0;i<nrep;i++) {
+      double repv = mxGetPr(prhs[1])[i];
+      rep[i] = (int)repv;
+    }
+    if(nrep == 1) {
+      /* special behavior */
+      nrep = 2;
+      rep[1] = rep[0];
+    }
+  }
+  else {
+    nrep = nrhs-1;
+    if(nrep > ndimdest) ndimdest = nrep;
+    rep = mxCalloc(ndimdest, sizeof(int));
+    for(i=0;i<nrep;i++) {
+      rep[i] = (int)*mxGetPr(prhs[i+1]);
+    }
+  }
+  for(i=nrep;i<ndimdest;i++) rep[i] = 1;
+
+  /* compute output size */
+  destdims = mxCalloc(ndimdest, sizeof(int));
+  for(i=0;i<ndim;i++) destdims[i] = dims[i]*rep[i];
+  for(;i<ndimdest;i++) { 
+    destdims[i] = rep[i];
+    extra_rep *= rep[i];
+  }
+  destdimsize = mxCalloc(ndim, sizeof(int));
+  destdimsize[0] = eltsize*destdims[0];
+  for(i=1;i<ndim;i++) destdimsize[i] = destdimsize[i-1]*destdims[i];
+
+    
+  /* for speed, array should be uninitialized */
+  plhs[0] = mxCreateNumericArray(ndimdest, destdims, mxGetClassID(srcmat), 
+				  mxIsComplex(srcmat)?mxCOMPLEX:mxREAL);
+
+  /* if any rep[i] == 0, output should be empty array.
+     Added by KPM 11/13/02.
+  */
+  empty = 0;
+  for (i=0; i < nrep; i++) {
+    if (rep[i]==0) 
+      empty = 1;
+  }
+  if (empty) 
+    return;
+
+  src = (char*)mxGetData(srcmat);
+  dest = (char*)mxGetData(plhs[0]);
+  repmat(dest,src,ndim,destdimsize,dimsize,dims,rep);
+  if(ndimdest > ndim) memrep(dest,destdimsize[ndim-1],extra_rep);
+  if(mxIsComplex(srcmat)) {
+    src = (char*)mxGetPi(srcmat);
+    dest = (char*)mxGetPi(plhs[0]);
+    repmat(dest,src,ndim,destdimsize,dimsize,dims,rep);
+    if(ndimdest > ndim) memrep(dest,destdimsize[ndim-1],extra_rep);
+  }
+}
Binary file _FullBNT/KPMtools/repmatC.dll has changed
Binary file _FullBNT/KPMtools/repmatC.mexglx has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/rgb2grayKPM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function g = rgb2grayKPM(rgb)
+% function g = rgb2grayKPM(rgb)
+% rgb2grayKPM Like the built-in function, but if r is already gray, does not cause an error
+
+[nr nc ncolors] = size(rgb);
+if ncolors > 1
+  g = rgb2gray(rgb);
+else
+  g = rgb;
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/rnd_partition.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function [train, test] = rnd_partition(data, train_percent);
+% function [train, test] = rnd_partition(data, train_percent);
+%
+% data(:,i) is the i'th example
+% train_percent of these columns get put into train, the rest into test
+
+N = size(data, 2);
+ndx = randperm(N);
+k = ceil(N*train_percent);
+train_ndx = ndx(1:k);
+test_ndx = ndx(k+1:end);
+train =  data(:, train_ndx);
+test = data(:, test_ndx);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/rotate_xlabel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,37 @@
+function hText = rotate_xlabel(degrees, newlabels)
+
+% Posted to comp.soft-sys.matlab on 2003-05-01 13:45:36 PST 
+% by David Borger (borger@ix.netcom.com)
+
+xtl = get(gca,'XTickLabel');
+set(gca,'XTickLabel','');
+lxtl = length(xtl);
+xtl = newlabels;
+if 0 % nargin>1
+    lnl = length(newlabels);
+    if lnl~=lxtl
+        error('Number of new labels must equal number of old');
+    end;
+    xtl = newlabels;
+end;
+
+
+hxLabel=get(gca,'XLabel');
+xLP=get(hxLabel,'Position');
+y=xLP(2);
+XTick=get(gca,'XTick');
+y=repmat(y,length(XTick),1);
+%fs=get(gca,'fontsize');
+fs = 12;
+hText=text(XTick,y,xtl,'fontsize',fs);
+set(hText,'Rotation',degrees,'HorizontalAlignment','right');
+
+% Modifications by KPM
+
+ylim = get(gca,'ylim');
+height = ylim(2)-ylim(1);
+N = length(hText);
+for i=1:N
+  voffset = ylim(2) - 0*height;
+  set(hText(i), 'position', [i voffset 0]);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/safeStr.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function s = safeStr(s)
+% Change punctuation characters to they print properly
+
+s = strrep(s, '\', '/');
+s = strrep(s, '_', '-');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/sampleUniformInts.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function M = sampleUniformInts(N, r, c)
+
+% M is an rxc matrix of integers in 1..N
+
+prob = normalize(ones(N,1));
+M = sample_discrete(prob, r, c);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/sample_discrete.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+function M = sample_discrete(prob, r, c)
+% SAMPLE_DISCRETE Like the built in 'rand', except we draw from a non-uniform discrete distrib.
+% M = sample_discrete(prob, r, c)
+%
+% Example: sample_discrete([0.8 0.2], 1, 10) generates a row vector of 10 random integers from {1,2},
+% where the prob. of being 1 is 0.8 and the prob of being 2 is 0.2.
+
+n = length(prob);
+
+if nargin == 1
+  r = 1; c = 1;
+elseif nargin == 2
+  c == r;
+end
+
+R = rand(r, c);
+M = ones(r, c);
+cumprob = cumsum(prob(:));
+
+if n < r*c
+  for i = 1:n-1
+    M = M + (R > cumprob(i));
+  end
+else
+  % loop over the smaller index - can be much faster if length(prob) >> r*c
+  cumprob2 = cumprob(1:end-1);
+  for i=1:r
+    for j=1:c
+      M(i,j) = sum(R(i,j) > cumprob2)+1;
+    end
+  end
+end
+
+
+% Slower, even though vectorized
+%cumprob = reshape(cumsum([0 prob(1:end-1)]), [1 1 n]);
+%M = sum(R(:,:,ones(n,1)) > cumprob(ones(r,1),ones(c,1),:), 3);
+
+% convert using a binning algorithm
+%M=bindex(R,cumprob);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/set_xtick_label.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,51 @@
+function set_xtick_label(tick_labels, angle, axis_label)
+% SET_XTICK_LABEL Print the xtick labels at an angle instead of horizontally
+% set_xtick_label(tick_labels, angle, axis_label)
+%
+% angle default = 90
+% axis_label default = ''
+%
+% This is derived from Solution Number: 5375 on mathworks.com
+% See set_xtick_label_demo for an example
+
+if nargin < 2, angle = 90; end
+if nargin < 3, axis_label = []; end
+
+% Reduce the size of the axis so that all the labels fit in the figure.
+pos = get(gca,'Position');
+%set(gca,'Position',[pos(1), .2, pos(3) .65])
+%set(gca,'Position',[pos(1), 0, pos(3) .45])
+%set(gca,'Position',[pos(1), 0.1, pos(3) 0.5])
+
+ax = axis;    % Current axis limits
+axis(axis);    % Fix the axis limits
+Yl = ax(3:4);  % Y-axis limits
+
+%set(gca, 'xtick', 1:length(tick_labels));
+set(gca, 'xtick', 0.7:1:length(tick_labels));
+Xt = get(gca, 'xtick');
+
+% Place the text labels
+t = text(Xt,Yl(1)*ones(1,length(Xt)),tick_labels);
+set(t,'HorizontalAlignment','right','VerticalAlignment','top', 'Rotation', angle);
+
+% Remove the default labels
+set(gca,'XTickLabel','')
+
+% Get the Extent of each text object.  This
+% loop is unavoidable.
+for i = 1:length(t)
+  ext(i,:) = get(t(i),'Extent');
+end
+
+% Determine the lowest point.  The X-label will be
+% placed so that the top is aligned with this point.
+LowYPoint = min(ext(:,2));
+
+% Place the axis label at this point
+if ~isempty(axis_label)
+  Xl = get(gca, 'Xlim');
+  XMidPoint = Xl(1)+abs(diff(Xl))/2;
+  tl = text(XMidPoint,LowYPoint, axis_label, 'VerticalAlignment','top', ...
+	    'HorizontalAlignment','center');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/set_xtick_label_demo.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+
+% Generate some test data.  Assume that the X-axis represents months.
+x = 1:12;
+y = 10*rand(1,length(x));
+
+% Plot the data.
+h = plot(x,y,'+');
+
+% Add a title.
+title('This is a title')
+
+% Set the X-Tick locations so that every other month is labeled.
+Xt = 1:2:11;
+Xl = [1 12];
+set(gca,'XTick',Xt,'XLim',Xl);
+
+% Add the months as tick labels.
+months = ['Jan';
+	  'Feb';
+	  'Mar';
+	  'Apr';
+	  'May';
+	  'Jun';
+	  'Jul';
+	  'Aug';
+	  'Sep';
+	  'Oct';
+	  'Nov';
+	  'Dec'];
+
+set_xtick_label(months(1:2:12, :), 90, 'xaxis label');
+
+
+
+if 0
+
+
+% Generate some test data.  Assume that the X-axis represents months.
+x = 1:8;
+y = 10*rand(1,length(x));
+
+% Plot the data.
+h = plot(x,y,'+');
+
+S = subsets(1:3);
+str = cell(1,8);
+for i=1:2^3
+  str{i} = num2str(S{i});
+end
+set_xtick_label(str);
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/setdiag.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+function M = setdiag(M, v)
+% SETDIAG Set the diagonal of a matrix to a specified scalar/vector.
+% M = set_diag(M, v)
+
+n = length(M);
+if length(v)==1
+  v = repmat(v, 1, n);
+end
+
+% e.g., for 3x3 matrix,  elements are numbered
+% 1 4 7 
+% 2 5 8 
+% 3 6 9
+% so diagnoal = [1 5 9]
+
+
+J = 1:n+1:n^2;
+M(J) = v;
+
+%M = triu(M,1) + tril(M,-1) + diag(v);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/softeye.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function M = softeye(K, p)
+% SOFTEYE Make a stochastic matrix with p on the diagonal, and the remaining mass distributed uniformly
+% M = softeye(K, p)
+%
+% M is a K x K matrix.
+
+M = p*eye(K);
+q = 1-p;
+for i=1:K
+  M(i, [1:i-1  i+1:K]) = q/(K-1);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/sort_evec.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,22 @@
+function [evec, evals] = sort_evec(temp_evec, temp_evals, N)
+
+if ~isvector(temp_evals)
+  temp_evals = diag(temp_evals);
+end
+
+% Eigenvalues nearly always returned in descending order, but just
+% to make sure.....
+[evals perm] = sort(-temp_evals);
+evals = -evals(1:N);
+if evals == temp_evals(1:N)
+  % Originals were in order
+  evec = temp_evec(:, 1:N);
+  return
+else
+  fprintf('sorting evec\n');
+  % Need to reorder the eigenvectors
+  for i=1:N
+    evec(:,i) = temp_evec(:,perm(i));
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/splitLongSeqIntoManyShort.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function short = splitLongSeqIntoManyShort(long, Tsmall)
+% splitLongSeqIntoManyShort Put groups of columns  into a cell array of narrower matrices
+% function short = splitLongSeqIntoManyShort(long, Tsmall)
+%
+% long(:,t)
+% short{i} = long(:,ndx1:ndx2) where each segment (except maybe the last) is of length Tsmall
+
+T = length(long);
+Nsmall = ceil(T/Tsmall);
+short = cell(Nsmall,1);
+
+t = 1;
+for i=1:Nsmall
+  short{i} = long(:,t:min(T,t+Tsmall-1));
+  t = t+Tsmall;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/sprintf_intvec.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+function s = sprintf_intvec(v)
+% SPRINTF_INTVEC Print a vector of ints as comma separated string, with no trailing comma
+% function s = sprintf_intvec(v)
+%
+% e.g., sprintf_intvec(1:3) returns '1,2,3' 
+
+s = sprintf('%d,', v);
+s = s(1:end-1);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/sqdist.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,29 @@
+function m = sqdist(p, q, A)
+% SQDIST      Squared Euclidean or Mahalanobis distance.
+% SQDIST(p,q)   returns m(i,j) = (p(:,i) - q(:,j))'*(p(:,i) - q(:,j)).
+% SQDIST(p,q,A) returns m(i,j) = (p(:,i) - q(:,j))'*A*(p(:,i) - q(:,j)).
+
+%  From Tom Minka's lightspeed toolbox
+
+[d, pn] = size(p);
+[d, qn] = size(q);
+
+if nargin == 2
+  
+  pmag = sum(p .* p, 1);
+  qmag = sum(q .* q, 1);
+  m = repmat(qmag, pn, 1) + repmat(pmag', 1, qn) - 2*p'*q;
+  %m = ones(pn,1)*qmag + pmag'*ones(1,qn) - 2*p'*q;
+  
+else
+
+  if isempty(A) | isempty(p)
+    error('sqdist: empty matrices');
+  end
+  Ap = A*p;
+  Aq = A*q;
+  pmag = sum(p .* Ap, 1);
+  qmag = sum(q .* Aq, 1);
+  m = repmat(qmag, pn, 1) + repmat(pmag', 1, qn) - 2*p'*Aq;
+  
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/strmatch_multi.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+function [posns] = strmatch_multi(keys, strs)
+% STRMATCH_MULTI Find where each key occurs in list of strings.
+% [pos] = strmatch_multi(key, strs) where key is a string and strs is a cell array of strings
+% works like the built-in command sequence pos = strmatch(key, strs, 'exact'),
+% except that pos is the first occurrence of key in strs; if there is no occurence, pos is 0.
+%
+% [posns] = strmatch_multi(keys, strs), where keys is a cell array of strings, 
+% matches each element of keys. It loops over whichever is shorter, keys or strs.
+
+if ~iscell(keys), keys = {keys}; end
+nkeys = length(keys);
+posns = zeros(1, nkeys);
+if length(keys) < length(strs)
+  for i=1:nkeys
+    %pos = strmatch(keys{i}, strs, 'exact');
+    ndx = strcmp(keys{i}, strs); % faster
+    pos = find(ndx);
+    if ~isempty(pos)
+      posns(i) = pos(1);
+    end
+  end
+else
+  for s=1:length(strs)
+    %ndx = strmatch(strs{s}, keys, 'exact');
+    ndx = strcmp(strs{s}, keys);
+    ndx = find(ndx);
+    posns(ndx) = s;
+  end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/strmatch_substr.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,28 @@
+function ndx = strmatch_substr(str, strs)
+% STRMATCH_SUBSTR Like strmatch, except str can match any part of strs{i}, not just prefix.
+% ndx = strmatch_substr(str, strs)
+%
+% Example:
+% i = strmatch('max', {'max','minimax','maximum'})
+%  returns i = [1; 3] since only 1 and 3 begin with max, but
+% i = strmatch_substr('max', {'max','minimax','maximum'})
+%  returns i = [1;2;3];
+%
+% If str is also a cell array, it is like calling strmatch_substr several times
+% and concatenating the results. 
+% Example:
+% 
+% i = strmatch_substr({'foo', 'dog'}, {'foo', 'hoofoo', 'dog'}) 
+%   returns i = [1;2;3]
+
+ndx = [];
+if ~iscell(str), str = {str}; end
+for j=1:length(str)
+  for i=1:length(strs)
+    %ind = strfind(strs{i}, str{j}); % not supported in 6.0
+    ind = findstr(strs{i}, str{j});
+    if ~isempty(ind)
+      ndx = [ndx; i];
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/strsplit.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,53 @@
+function parts = strsplit(splitstr, str, option)
+%STRSPLIT Split string into pieces.
+%
+%   STRSPLIT(SPLITSTR, STR, OPTION) splits the string STR at every occurrence
+%   of SPLITSTR and returns the result as a cell array of strings.  By default,
+%   SPLITSTR is not included in the output.
+%
+%   STRSPLIT(SPLITSTR, STR, OPTION) can be used to control how SPLITSTR is
+%   included in the output.  If OPTION is 'include', SPLITSTR will be included
+%   as a separate string.  If OPTION is 'append', SPLITSTR will be appended to
+%   each output string, as if the input string was split at the position right
+%   after the occurrence SPLITSTR.  If OPTION is 'omit', SPLITSTR will not be
+%   included in the output.
+
+%   Author:      Peter J. Acklam
+%   Time-stamp:  2004-09-22 08:48:01 +0200
+%   E-mail:      pjacklam@online.no
+%   URL:         http://home.online.no/~pjacklam
+
+   nargsin = nargin;
+   error(nargchk(2, 3, nargsin));
+   if nargsin < 3
+      option = 'omit';
+   else
+      option = lower(option);
+   end
+
+   splitlen = length(splitstr);
+   parts = {};
+
+   while 1
+
+      k = strfind(str, splitstr);
+      if isempty(k)
+         parts{end+1} = str;
+         break
+      end
+
+      switch option
+         case 'include'
+            parts(end+1:end+2) = {str(1:k(1)-1), splitstr};
+         case 'append'
+            parts{end+1} = str(1 : k(1)+splitlen-1);
+         case 'omit'
+            parts{end+1} = str(1 : k(1)-1);
+         otherwise
+            error(['Invalid option string -- ', option]);
+      end
+
+
+      str = str(k(1)+splitlen : end);
+
+   end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/subplot2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function subplot2(nrows, ncols, i, j)
+% function subplot2(nrows, ncols, i, j)
+
+
+sz = [nrows ncols];
+%k = sub2ind(sz, i, j)
+k = sub2ind(sz(end:-1:1), j, i);
+subplot(nrows, ncols, k);
+
+if 0
+  ncols_plot = ceil(sqrt(Nplots));
+  nrows_plot = ceil(Nplots/ncols_plot);
+  Nplots = nrows_plot*ncols_plot;
+  for p=1:Nplots
+    subplot(nrows_plot, ncols_plot, p);
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/subplot3.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+function fignum = subplot3(nrows, ncols, fignumBase, plotnumBase)
+% function subplot3(nrows, ncols, fignumBase, plotnumBase)
+% Choose a subplot number, opening a new figure if necessary
+% eg nrows=2, ncols = 2, we plot on (fignum, plotnum) = (1,1), (1,2), (1,3), (1,4), (2,1), ...
+
+nplotsPerFig = nrows*ncols;
+fignum = fignumBase + div(plotnumBase-1, nplotsPerFig);
+plotnum = wrap(plotnumBase, nplotsPerFig);
+figure(fignum);
+if plotnum==1, clf; end
+subplot(nrows, ncols, plotnum);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/subsets.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+function [T, bitv] = subsets(S, U, L, sorted, N)
+% SUBSETS Create a set of all the subsets of S which have cardinality <= U and >= L
+% T = subsets(S, U, L)
+% U defaults to length(S), L defaults to 0.
+% So subsets(S) generates the powerset of S.
+%
+% Example:
+% T = subsets(1:4, 2, 1) 
+% T{:} = 1, 2, [1 2], 3, [1 3], [2 3], 4, [1 4], [2 4], [3 4]
+%
+% T = subsets(S, U, L, sorted)
+% If sorted=1, return the subsets in increasing size
+%
+% Example:
+% T = subsets(1:4, 2, 1, 1) 
+% T{:} = 1, 2, 3, 4, [1 2], [1 3], [2 3], [1 4], [2 4], [3 4]
+%
+% [T, bitv] = subsets(S, U, L, sorted, N)
+% Row i of bitv is a bit vector representation of T{i},
+% where bitv has N columns (representing 1:N).
+% N defaults to max(S).
+%
+% Example:
+% [T,bitv] = subsets(2:4, 2^3, 0, 0, 5)
+% T{:} = [], 2, 3, [2 3], 4, [2 4], [3 4], [2 3 4]
+% bitv=
+%     0     0     0     0     0
+%     0     1     0     0     0
+%     0     0     1     0     0
+%     0     1     1     0     0
+%     0     0     0     1     0
+%     0     1     0     1     0
+%     0     0     1     1     0
+%     0     1     1     1     0
+
+n = length(S);
+
+if nargin < 2, U = n; end
+if nargin < 3, L = 0; end
+if nargin < 4, sorted = 0; end
+if nargin < 5, N = max(S); end
+
+bits = ind2subv(2*ones(1,n), 1:2^n)-1;
+sm = sum(bits,2);
+masks = bits((sm <= U) & (sm >= L), :);
+m = size(masks, 1);
+T = cell(1, m);
+for i=1:m
+  s = S(find(masks(i,:)));
+  T{i} = s;
+end
+
+if sorted 
+  T = sortcell(T);
+end
+
+bitv = zeros(m, N);
+bitv(:, S) = masks;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/subsets1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+function sub_s=subsets1(s,k)
+% SUBSETS1 creates sub-sets of a specific from a given set
+% SS = subsets1(S, k)
+% 
+% S is the given set
+% k is the required sub-sets size
+% 
+% Example:
+% 
+% >> ss=subsets1([1:4],3);
+% >> ss{:}
+% ans =
+%      1     2     3
+% ans =
+%      1     2     4
+% ans =
+%      1     3     4
+% ans =
+%      2     3     4
+% 
+% Written by Raanan Yehezkel, 2004
+
+if k<0 % special case
+    error('subset size must be positive');
+elseif k==0 % special case
+    sub_s={[]};
+else
+    l=length(s);
+    ss={};
+    if l>=k
+        if k==1 % Exit condition
+            for I=1:l
+                ss{I}=s(I);
+            end
+        else
+            for I=1:l
+                ss1=subsets1(s([(I+1):l]),k-1);
+                for J=1:length(ss1)
+                    ss{end+1}=[s(I),ss1{J}];
+                end
+            end
+        end
+    end
+    sub_s=ss;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/subsetsFixedSize.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+function sub_s=subsets1(s,k)
+% SUBSETS1 creates sub-sets of a specific size from a given set
+% SS = subsets1(S, k)
+% 
+% S is the given set
+% k is the required sub-sets size
+% 
+% Example:
+% 
+% >> ss=subsets1([1:4],3);
+% >> ss{:}
+% ans =
+%      1     2     3
+% ans =
+%      1     2     4
+% ans =
+%      1     3     4
+% ans =
+%      2     3     4
+% 
+% Written by Raanan Yehezkel, 2004
+
+if k<0 % special case
+    error('subset size must be positive');
+elseif k==0 % special case
+    sub_s={[]};
+else
+    l=length(s);
+    ss={};
+    if l>=k
+        if k==1 % Exit condition
+            for I=1:l
+                ss{I}=s(I);
+            end
+        else
+            for I=1:l
+                ss1=subsets1(s([(I+1):l]),k-1);
+                for J=1:length(ss1)
+                    ss{end+1}=[s(I),ss1{J}];
+                end
+            end
+        end
+    end
+    sub_s=ss;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/subv2ind.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function index = subv2ind(siz,sub)
+%SUBV2IND   Linear index from subscript vector.
+% SUBV2IND(SIZ,SUB) returns an equivalent single index corresponding to a
+% subscript vector for an array of size SIZ.
+% If SUB is a matrix, with subscript vectors as rows, then the result is a 
+% column vector.
+%
+% This is the opposite of IND2SUBV, so that
+%   SUBV2IND(SIZ,IND2SUBV(SIZ,IND)) == IND.
+%
+% See also IND2SUBV, SUB2IND.
+
+%index = subv2indTest(siz,sub);
+prev_cum_size = [1 cumprod(siz(1:end-1))];
+%index = (sub-1)*prev_cum_size' + 1;
+index = sub*prev_cum_size' - sum(prev_cum_size) + 1;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/subv2indKPM.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,89 @@
+/* C mex version of subv2ind*/
+/* 2 inputs, 1 output       */
+/* siz, subv                */
+/* ndx                      */
+#include "mex.h"
+
+void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
+	int    i, j, k, nCol, nRow, binary, temp;
+	double *pSize, *pSubv, *pr;
+	int    *cumprod;
+
+	pSize = mxGetPr(prhs[0]);
+	pSubv = mxGetPr(prhs[1]);
+	nCol  = mxGetNumberOfElements(prhs[0]);
+	nRow  = mxGetM(prhs[1]);
+
+	
+	if(mxIsEmpty(prhs[1])){
+		plhs[0] = mxCreateDoubleMatrix(0, 0, mxREAL);
+		return;
+	}
+
+	if(mxIsEmpty(prhs[0])){
+		plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
+		*mxGetPr(plhs[0]) = 1;
+		return;
+	}
+
+	binary = 2;
+	for (i = 0; i < nCol; i++){
+		if (pSize[i] > 2.0){
+			binary = 0;
+			break;
+		}
+		else if(pSize[i] == 1.0){
+			binary = 1;
+		}
+	}
+
+	plhs[0] = mxCreateDoubleMatrix(nRow, 1, mxREAL);
+	pr = mxGetPr(plhs[0]);
+	for(i=0; i<nRow; i++){
+		pr[i] = 1.0;
+	}
+
+	if (binary == 2){
+		for(j=0; j<nCol; j++){
+			temp = j * nRow;
+			for(i=0; i<nRow; i++){
+				pr[i] += ((int)pSubv[temp + i] - 1) << j;
+			}
+		}
+	}
+	else if(binary == 1){	
+		cumprod = malloc(nCol * sizeof(int));
+		cumprod[0] = 1;
+		for(i=1; i<nCol; i++){
+			k = (int)pSize[i-1] - 1;
+			cumprod[i] = cumprod[i-1] << k;
+		}
+		for(j=0; j<nCol; j++){
+			temp = j * nRow;
+			for(i=0; i<nRow; i++){
+				k = (int)pSubv[temp + i] - 1;
+				if(k)pr[i] += cumprod[j];
+			}
+		}
+		free(cumprod);
+	}
+	else {
+		cumprod = malloc(nCol * sizeof(int));
+		cumprod[0] = 1;
+		for(i=1; i<nCol; i++){
+			k = (int)pSize[i-1];
+			cumprod[i] = cumprod[i-1] * k;
+		}
+		for(j=0; j<nCol; j++){
+			temp = j * nRow;
+			for(i=0; i<nRow; i++){
+				k = (int)pSubv[temp + i] - 1;
+				pr[i] += cumprod[j] * k;
+			}
+		}
+		free(cumprod);
+	}
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/subv2indKPM.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,66 @@
+function ndx = subv2indKPM(siz, subv)
+% SUBV2IND Like the built-in sub2ind, but the subscripts are given as row vectors.
+% ind = subv2ind(siz,subv)
+%
+% siz can be a row or column vector of size d.
+% subv should be a collection of N row vectors of size d.
+% ind will be of size N * 1.
+%
+% Example:
+% subv = [1 1 1;
+%         2 1 1;
+%         ...
+%         2 2 2];
+% subv2ind([2 2 2], subv) returns [1 2 ... 8]'
+% i.e., the leftmost digit toggles fastest.
+%
+% See also IND2SUBV.
+
+
+if isempty(subv)
+  ndx = [];
+  return;
+end
+
+if isempty(siz)
+  ndx = 1;
+  return;
+end
+
+[ncases ndims] = size(subv);
+
+%if length(siz) ~= ndims
+%  error('length of subscript vector and sizes must be equal');
+%end
+
+if all(siz==2)
+  %rbits = subv(:,end:-1:1)-1; % read from right to left, convert to 0s/1s
+  %ndx = bitv2dec(rbits)+1; 
+  twos = pow2(0:ndims-1);
+  ndx = ((subv-1) * twos(:)) + 1;
+  %ndx = sum((subv-1) .* twos(ones(ncases,1), :), 2) + 1; % equivalent to matrix * vector
+  %ndx = sum((subv-1) .* repmat(twos, ncases, 1), 2) + 1; % much slower than ones
+  %ndx = ndx(:)';
+else
+  %siz = siz(:)';
+  cp = [1 cumprod(siz(1:end-1))]';
+  %ndx = ones(ncases, 1);
+  %for i = 1:ndims
+  %  ndx = ndx + (subv(:,i)-1)*cp(i);
+  %end
+  ndx = (subv-1)*cp + 1;
+end
+
+%%%%%%%%%%%
+
+function d = bitv2dec(bits)
+% BITV2DEC Convert a bit vector to a decimal integer
+% d = butv2dec(bits)
+%
+% This is just like the built-in bin2dec, except the argument is a vector, not a string.
+% If bits is an array, each row will be converted.
+
+[m n] = size(bits);
+twos = pow2(n-1:-1:0);
+d = sum(bits .* twos(ones(m,1),:),2);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/subv2indMinka.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function index = subv2indMinka(siz,sub)
+%SUBV2IND   Linear index from subscript vector.
+% SUBV2IND(SIZ,SUB) returns an equivalent single index corresponding to a
+% subscript vector for an array of size SIZ.
+% If SUB is a matrix, with subscript vectors as rows, then the result is a 
+% column vector.
+%
+% This is the opposite of IND2SUBV, so that
+%   SUBV2IND(SIZ,IND2SUBV(SIZ,IND)) == IND.
+%
+% See also IND2SUBV, SUB2IND.
+
+% Written by Tom Minka
+
+prev_cum_size = [1 cumprod(siz(1:end-1))];
+%index = (sub-1)*prev_cum_size' + 1;
+index = sub*prev_cum_size' - sum(prev_cum_size) + 1;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/subv2indTest.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function ndx = subv2indTest(siz,sub)
+%SUBV2IND   Linear index from subscript vector.
+% SUBV2IND(SIZ,SUB) returns an equivalent single index corresponding to a
+% subscript vector for an array of size SIZ.
+% If SUB is a matrix, with subscript vectors as rows, then the result is a 
+% column vector.
+%
+% This is the opposite of IND2SUBV, so that
+%   SUBV2IND(SIZ,IND2SUBV(SIZ,IND)) == IND.
+%
+% See also IND2SUBV, SUB2IND.
+
+ndx = subv2indMinka(siz,sub);
+ndx2 = subv2indKPM(siz,sub);
+assert(isequalKPM(ndx,ndx2))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/sumv.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function T2 = sumv(T1, sum_over)
+%
+% Like the built in sum, but will sum over several dimensions and then squeeze the result.
+
+T2 = T1;
+for i=1:length(sum_over)
+  if sum_over(i) <= ndims(T2) % prevent summing over non-existent dimensions
+    T2=sum(T2, sum_over(i));
+  end
+end
+T2 = squeeze(T2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/suptitle.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,105 @@
+function hout=suptitle(str, fs)
+%SUPTITLE Puts a title above all subplots.
+%	SUPTITLE('text') adds text to the top of the figure
+%	above all subplots (a "super title"). Use this function
+%	after all subplot commands.
+
+% Drea Thomas 6/15/95 drea@mathworks.com
+
+% Warning: If the figure or axis units are non-default, this
+% will break.
+
+% Parameters used to position the supertitle.
+
+% Amount of the figure window devoted to subplots
+plotregion = .92;
+
+% Y position of title in normalized coordinates
+titleypos  = .95;
+
+% Fontsize for supertitle
+if nargin < 2
+  fs = get(gcf,'defaultaxesfontsize')+4;
+end
+
+% Fudge factor to adjust y spacing between subplots
+fudge=1;
+
+haold = gca;
+figunits = get(gcf,'units');
+
+% Get the (approximate) difference between full height (plot + title
+% + xlabel) and bounding rectangle.
+
+	if (~strcmp(figunits,'pixels')),
+		set(gcf,'units','pixels');
+		pos = get(gcf,'position');
+		set(gcf,'units',figunits);
+	else,
+		pos = get(gcf,'position');
+	end
+	ff = (fs-4)*1.27*5/pos(4)*fudge;
+
+        % The 5 here reflects about 3 characters of height below
+        % an axis and 2 above. 1.27 is pixels per point.
+
+% Determine the bounding rectange for all the plots
+
+% h = findobj('Type','axes');   
+
+% findobj is a 4.2 thing.. if you don't have 4.2 comment out
+% the next line and uncomment the following block.
+	
+h = findobj(gcf,'Type','axes');  % Change suggested by Stacy J. Hills
+
+% If you don't have 4.2, use this code instead
+%ch = get(gcf,'children');
+%h=[];
+%for i=1:length(ch),
+%  if strcmp(get(ch(i),'type'),'axes'),
+%    h=[h,ch(i)];
+%  end
+%end
+
+	
+
+
+max_y=0;
+min_y=1;
+
+oldtitle =0;
+for i=1:length(h),
+	if (~strcmp(get(h(i),'Tag'),'suptitle')),
+		pos=get(h(i),'pos');
+		if (pos(2) < min_y), min_y=pos(2)-ff/5*3;end;
+		if (pos(4)+pos(2) > max_y), max_y=pos(4)+pos(2)+ff/5*2;end;
+	else,
+		oldtitle = h(i);
+	end
+end
+
+if max_y > plotregion,
+	scale = (plotregion-min_y)/(max_y-min_y);
+	for i=1:length(h),
+		pos = get(h(i),'position');
+		pos(2) = (pos(2)-min_y)*scale+min_y;
+		pos(4) = pos(4)*scale-(1-scale)*ff/5*3;
+		set(h(i),'position',pos);
+	end
+end
+
+np = get(gcf,'nextplot');
+set(gcf,'nextplot','add');
+if (oldtitle),
+	delete(oldtitle);
+end
+ha=axes('pos',[0 1 1 1],'visible','off','Tag','suptitle');
+ht=text(.5,titleypos-1,str);set(ht,'horizontalalignment','center','fontsize',fs);
+set(gcf,'nextplot',np);
+axes(haold);
+if nargout,
+	hout=ht;
+end
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/unaryEncoding.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+function U = unaryEncoding(data, K)
+% unaryEncoding Encode data(s) as a 1-of-K column vector
+% function U = unaryEncoding(data, K)
+%
+% eg.
+% If data = [3 2 2] and K=3,
+% then U = [0 0 0
+%           0 1 1
+%           1 0 0]
+
+if nargin < 2, K = max(data); end
+N = length(data);
+U = zeros(K,N);
+ndx = subv2ind([K N], [data(:)'; 1:N]');
+U(ndx) = 1;
+U = reshape(U, [K N]);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/wrap.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function v = wrap(u,N)
+% WRAP Wrap a vector of indices around a torus.
+% v = wrap(u,N)
+%
+% e.g., wrap([-1 0 1 2 3 4], 3)   =   2 3 1 2 3 1
+
+v = mod(u-1,N)+1;       
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/xticklabel_rotate90.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,68 @@
+function xticklabel_rotate90(XTick,varargin)
+%XTICKLABEL_ROTATE90 - Rotate numeric Xtick labels by 90 degrees
+%
+% Syntax: xticklabel_rotate90(XTick)
+%
+% Input:  XTick - vector array of XTick positions & values (numeric)
+%
+% Output:  none
+%
+% Example 1:  Set the positions of the XTicks and rotate them
+%    figure;  plot([1960:2004],randn(45,1)); xlim([1960 2004]);
+%    xticklabel_rotate90([1960:2:2004]);
+%    %If you wish, you may set a few text "Property-value" pairs
+%    xticklabel_rotate90([1960:2:2004],'Color','m','Fontweight','bold');
+%
+% Example 2:  %Rotate XTickLabels at their current position
+%    XTick = get(gca,'XTick');
+%    xticklabel_rotate90(XTick);
+%
+% Other m-files required: none
+% Subfunctions: none
+% MAT-files required: none
+%
+% See also: TEXT,  SET
+
+% Author: Denis Gilbert, Ph.D., physical oceanography
+% Maurice Lamontagne Institute, Dept. of Fisheries and Oceans Canada
+% email: gilbertd@dfo-mpo.gc.ca  Web: http://www.qc.dfo-mpo.gc.ca/iml/
+% February 1998; Last revision: 24-Mar-2003
+
+if ~isnumeric(XTick)
+   error('XTICKLABEL_ROTATE90 requires a numeric input argument');
+end
+
+%Make sure XTick is a column vector
+XTick = XTick(:);
+
+%Set the Xtick locations and set XTicklabel to an empty string
+set(gca,'XTick',XTick,'XTickLabel','')
+
+% Define the xtickLabels
+xTickLabels = num2str(XTick);
+
+% Determine the location of the labels based on the position
+% of the xlabel
+hxLabel = get(gca,'XLabel');  % Handle to xlabel
+xLabelString = get(hxLabel,'String');
+
+if ~isempty(xLabelString)
+   warning('You may need to manually reset the XLABEL vertical position')
+end
+
+set(hxLabel,'Units','data');
+xLabelPosition = get(hxLabel,'Position');
+y = xLabelPosition(2);
+
+%CODE below was modified following suggestions from Urs Schwarz
+y=repmat(y,size(XTick,1),1);
+% retrieve current axis' fontsize
+fs = get(gca,'fontsize');
+
+% Place the new xTickLabels by creating TEXT objects
+hText = text(XTick, y, xTickLabels,'fontsize',fs);
+
+% Rotate the text objects by 90 degrees
+set(hText,'Rotation',90,'HorizontalAlignment','right',varargin{:})
+
+%------------- END OF CODE --------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/zipload.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,47 @@
+%ZIPLOAD   Load compressed data file created with ZIPSAVE
+%
+%	[data] = zipload( filename )
+%	filename: string variable that contains the name of the 
+%	compressed file (do not include '.zip' extension)
+%	Use only with files created with 'zipsave'
+%	pkzip25.exe has to be in the matlab path. This file is a compression utility 
+%	made by Pkware, Inc. It can be dowloaded from:	http://www.pkware.com
+%	Or directly from ftp://ftp.pkware.com/pk250c32.exe, for the Windows 95/NT version.
+%	This function was tested using 'PKZIP 2.50 Command Line for Windows 9x/NT'
+%	It is important to use version 2.5 of the utility. Otherwise the command line below
+%	has to be changed to include the proper options of the compression utility you 
+%	wish to use.
+%	This function was tested in MATLAB Version 5.3 under Windows NT.
+%	Fernando A. Brucher - May/25/1999
+%	
+%	Example:
+%		[loadedData] = zipload('testfile');
+%--------------------------------------------------------------------
+
+function [data] = zipload( filename )
+
+%--- Decompress data file by calling pkzip (comand line command) ---
+% 	Options used: 
+%	'extract' = decompress file
+%	'silent' = no console output 
+%	'over=all' = overwrite files
+
+%eval( ['!pkzip25 -extract -silent -over=all ', filename, '.zip'] )
+eval( ['!pkzip25 -extract -silent -over=all ', filename, '.zip'] )
+
+
+%--- Load data from decompressed file ---
+%	try, catch takes care of cases when pkzip fails to decompress a 
+%	valid matlab format file
+
+try
+   tmpStruc = load( filename );
+   data = tmpStruc.data;
+catch, return, end
+
+
+%--- Delete decompressed file ---
+
+delete( [filename,'.mat'] )
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_FullBNT/KPMtools/zipsave.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,42 @@
+%ZIPSAVE   Save data in compressed format
+%
+%	zipsave( filename, data )
+%	filename: string variable that contains the name of the resulting 
+%	compressed file (do not include '.zip' extension)
+%	pkzip25.exe has to be in the matlab path. This file is a compression utility 
+%	made by Pkware, Inc. It can be dowloaded from: http://www.pkware.com
+%	This function was tested using 'PKZIP 2.50 Command Line for Windows 9x/NT'
+%	It is important to use version 2.5 of the utility. Otherwise the command line below
+%	has to be changed to include the proper options of the compression utility you 
+%	wish to use.
+%	This function was tested in MATLAB Version 5.3 under Windows NT.
+%	Fernando A. Brucher - May/25/1999
+%	
+%	Example:
+%		testData = [1 2 3; 4 5 6; 7 8 9];
+%		zipsave('testfile', testData);
+%
+% Modified by Kevin Murphy, 26 Feb 2004, to use winzip
+%------------------------------------------------------------------------
+
+function zipsave( filename, data )
+
+%--- Save data in a temporary file in matlab format (.mat)---
+
+eval( ['save ''', filename, ''' data'] )
+
+
+%--- Compress data by calling pkzip (comand line command) ---
+% 	Options used: 
+%	'add' = add compressed files to the resulting zip file
+%	'silent' = no console output 
+%	'over=all' = overwrite files
+
+%eval( ['!pkzip25 -silent -add -over=all ', filename, '.zip ', filename,'.mat'] )
+eval( ['!zip ', filename, '.zip ', filename,'.mat'] )
+
+%--- Delete temporary matlab format file ---
+
+delete( [filename,'.mat'] )
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/README	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+To perform the analysis call:
+
+out = getmeasures2(fname,ts);
+ts is an optional input parameter to specify the number of beats per bar
+
+out is a struct with the following data
+
+out.beats - beat times in seconds
+out.measures - bar boundaries in seconds
+out.timesig - estimate of the number of beats per bar (will = ts if specified)
+out.df - the onset detection function
+
+
+The code is set to downsample the audio file to 11025Hz before processing
+This speeds up the calculation of the onset detection function but has
+negligible effect on the output of the beat tracker.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/adapt_thresh.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+function [dfout,m] = adapt_thresh(df,pre,post);
+
+
+
+
+df = df(:)';
+% uses juan's adaptive median threshold
+
+alpha = 9;
+thresh=0.033;
+fn = @mean;
+
+if(nargin<2)
+    pre = 8;
+    post = 7;
+end
+
+%df = df-min(df);
+%alpha norm
+%df = df/real(mean(abs(df+eps).^alpha).^(1/alpha));   
+
+
+
+
+% low pass filtering
+
+%[b,a]=butter(2,0.28);
+
+%b = [0.1600 0.3200 0.1600];
+%a = [1.0000 -0.5949 0.2348];
+
+
+%df=filtfilt(b,a,df);
+
+
+% median threshold
+
+N=length(df);
+
+for i=1:min(post,N)
+	k=min(i+pre,N);
+	m(i)=feval(fn,df(1:k));
+  %  m2(i) = feval(@mean,df(1:k));
+end
+
+if N>(post+pre)
+	m=[m feval(fn,buffer(df,post+pre+1,post+pre,'nodelay'))];
+end
+
+% if N>(post+pre)
+% 	m2=[m2 feval(@mean,buffer(df,post+pre+1,post+pre,'nodelay'))];
+% end
+
+for i=N+(1-pre:0)
+	j=max(i-post,1);
+	m(i)=feval(fn,df(j:end));
+%    m2(i)=feval(@mean,df(j:end));
+end
+
+%df = (df- m*thresh);
+df = df-m;
+
+dfout = (df>0).*df;
+%dfout = df;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/bcfm.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,96 @@
+function [measures,db] = bcfm(bcf,beats,timesig)
+
+
+if timesig == 0
+	timesig =4;
+end
+% extract measures from bcf and timesig.
+
+for k=1:timesig,
+    db(k) = mean(bcf(k:timesig:end));
+end
+
+[val,downbeat] = max(db);
+
+
+
+if(downbeat ==timesig),
+    downbeat = 0;
+end
+
+downbeat = downbeat+1;
+
+measures = beats(downbeat:timesig:end);
+
+
+if 0
+
+    % for extracting batchwise measures...
+    for i=1:222,
+        meas{1,i} = bcfm(bcfs{i}.spec,anns.beats{i},anns.timesig{i});
+        %  meas{2,i} = bcfm(bcf{i}.specs,anns.beats{i},anns.timesig{i});
+        meas{2,i} = bcfm(bcfs{i}.cq,anns.beats{i},anns.timesig{i});
+        %  meas{4,i} = bcfm(bcf{i}.cqs,anns.beats{i},anns.timesig{i});
+        meas{3,i} = bcfm(bcfs{i}.hpcp,anns.beats{i},anns.timesig{i});
+        %  meas{6,i} = bcfm(bcf{i}.hpcps,anns.beats{i},anns.timesig{i});
+        meas{4,i} = bcfm(bcfs{i}.chroma,anns.beats{i},anns.timesig{i});
+        %  meas{8,i} = bcfm(bcf{i}.chromas,anns.beats{i},anns.timesig{i});
+        meas{5,i} =  bcfm(bcfs{i}.mfcc,anns.beats{i},anns.timesig{i});
+       % y = bcfs{i}.spec+bcfs{i}.cq+bcfs{i}.hpcp+bcfs{i}.chroma+bcfs{i}.mfcc;
+      %  meas{6,i} =  bcfm(y,anns.beats{i},anns.timesig{i});
+
+%         % voting mechanism.. find which measures are the same...
+%         zz = zeros(5);
+%         for k=1:5, 
+%             for j=1:5,
+%                 zz(k,j) = double(~~sum(meas{k,i}==meas{j,i})); 
+%             end
+%         end
+%         
+%         for p=1:5, zz(p,p) = 0; end
+%         % find which is similar to another        
+%         [val,ind] = max(sum(zz));
+%         % and put these in place...
+%         meas{6,i} = meas{ind,i};
+%         
+        
+    end
+    % and their evaluation
+    for j=1:5
+        for i=1:222,
+            % only need rcl
+            [m.rcl(j,i), m.rtot(j,i), m.acl(j,i), m.atot(j,i)]  = cont_eval(anns.actmeasures{i},meas{j,i},0.1);
+        end
+    end
+end
+
+if 0
+
+    % for extracting batchwise measures...
+    for i=1:222,
+        meas{1,i} = bcfm(bcf{i}.spec,beats{i},timesig{i});
+      %  meas{2,i} = bcfm(bcf{i}.specs,anns.beats{i},anns.timesig{i});
+        meas{2,i} = bcfm(bcf{i}.cq,beats{i},timesig{i});
+      %  meas{4,i} = bcfm(bcf{i}.cqs,anns.beats{i},anns.timesig{i});
+        meas{3,i} = bcfm(bcf{i}.hpcp,beats{i},timesig{i});
+      %  meas{6,i} = bcfm(bcf{i}.hpcps,anns.beats{i},anns.timesig{i});
+        meas{4,i} = bcfm(bcf{i}.chroma,beats{i},timesig{i});
+      %  meas{8,i} = bcfm(bcf{i}.chromas,anns.beats{i},anns.timesig{i});
+    end
+    % and their evaluation
+    for j=1:4
+        for i=1:222,
+            % only need rcl
+            [m.rcl(j,i), m.rtot(j,i), m.acl(j,i), m.atot(j,i)]  = cont_eval(anns.actmeasures{i},meas{j,i},0.1);
+        end
+    end
+end
+
+%new classification approach
+if 0
+fname = '95_HipHopFatty';
+[bcf,frame,beats] = getbcfs2(fname); y = kmeans(frame.spec,4);
+measures = bcfm(~~abs(diff(y)),beats,4);
+figure(1);subplot(311); imagesc(10*log(1+abs(frame.spec'))); axis xy; colormap('hot'); subplot(312); stem(y); axis tight; subplot(313); stem(~~abs(diff(y))); axis tight;
+out = playbeats(measures,wavread(fname),44100); wavwrite(out,44100,'~/Desktop/z2.wav');
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/bt_parms.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function p = bt_parms(res)
+
+if nargin<1
+    res = 0.01161;
+end
+
+p.fs = 44100;
+
+p.timeres = round(p.fs * res);
+
+p.winlen = round(512^2/p.timeres);
+
+p.step = round(p.winlen/4);
+
+p.bwinlen = 512; % always!
+p.bstep = 128; % for the beat tracker!
+
+% step and consistency thresholds from beat tracker
+p.stepthresh = round(8*(512/p.timeres));
+p.constthresh  = round(p.stepthresh/2);
+
+% parameter for rayleigh distribution weighting
+% p.rayparam = round(43*(512/p.timeres));
+p.rayparam = round(33*(512/p.timeres));
+
+% minimum and maximum periodicities for comb filterbank
+p.pmax = round(80*(512/p.timeres));
+p.pmin = round(4*(512/p.timeres));
+p.lowest = round(21*(512/p.timeres)); % dixon upper limit of 247 bpm
+
+%parameters for adaptive movingm mean threshold
+p.pre = round(8*(512/p.timeres));
+% p.post = round(7*(512/p.timeres));
+p.post = p.pre-1;
+
+% factor for converting between beat period and tempo
+p.fact = 60*p.fs/p.timeres;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/chromaframe.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,112 @@
+function [spec] = chromaframe(x,spark);
+%  function [spec,mfcc,cq,hpcp,chroma] = chromaframe(x,spark);
+
+% function to return spectrogram, constq, hpcp and chromagram
+% for one single frame of arbitrary length
+% with the possible inclusion of an adaptive thresholding stage.
+
+fmin = 110; 
+fmax = 880;
+
+if nargin<2
+    spark = sparsekernel(fmin, fmax, 36, 44100/16, 0.054);
+    spark(1025:end,:) = [];
+end
+
+
+% make x a row vector
+x = x(:)';
+x2 = x;
+fs = 44100;
+% downsample by a factor of 16.
+%x = x(1:16:end);
+% x = resample(x,11025,44100);
+ x = resample(x,2756,11024);
+%  x = resample(x,11024,44096);
+
+len = length(x);
+
+
+% make windowing function
+w = hanningz(len);
+w = w(:)';
+%  w = ones(1,length(x)); % or no windowing... shouldn't be better..
+% take fft
+spec = abs(fft(w.*x,2048));
+spec = adapt_thresh(spec(1:1024),16,15);
+
+%  %spec = spec(1:1024);
+%  
+%  %cq = adapt_thresh(abs(spec*spark));   
+%  cq = abs(spec*spark);
+%  hpcp = zeros(1,36);
+%  
+%  for k=1:36 
+%      hpcp(k) =  sum(abs(cq(k:36:end)));
+%  end
+%  
+%  %hpcp = adapt_thresh(hpcp,2,3);
+%  
+%  % for k=1:round(abs(log2(fmax/fmin))),
+%  %     l(k) = sum(hpcp(k:3:end));
+%  % end
+%  % 
+%  % [val,ind] = max(l);
+%  % 
+%  % chroma = hpcp(ind:3:end);
+%  % 
+%  for i=1:12 % sum bins.. 
+%      chroma(i) = sum(hpcp((i-1)*3+1:3*i));
+%  end
+
+
+%chroma = adapt_thresh(chroma,3,2);
+
+%  % modulated complex lapped transform
+%  % spec = abs(fmclt(x',1024)');
+%  % spec = adapt_thresh(spec);
+%  
+%  % % try to treat everything as gaussians
+%  % n = 1:length(cq);
+%  % mu = sum(n.*cq)/sum(cq);
+%  % sigma = sqrt(sum((n-mu).^2)/sum(cq));
+%  % cq = exp(-0.5 * ((n - mu)./sigma).^2) ./ (sqrt(2*pi) .* sigma);
+%  % 
+%  % n = 1:length(hpcp);
+%  % mu = sum(n.*hpcp)/sum(hpcp);
+%  % sigma = sqrt(sum((n-mu).^2)/sum(hpcp));
+%  % hpcp = exp(-0.5 * ((n - mu)./sigma).^2) ./ (sqrt(2*pi) .* sigma);
+%  % 
+%  % n = 1:length(chroma);
+%  % mu = sum(n.*chroma)/sum(chroma);
+%  % sigma = sqrt(sum((n-mu).^2)/sum(chroma));
+%  % chroma = exp(-0.5 * ((n - mu)./sigma).^2) ./ (sqrt(2*pi) .* sigma);
+%  % 
+%  % n = 1:length(spec);
+%  % mu = sum(n.*spec)/sum(spec);
+%  % sigma = sqrt(sum((n-mu).^2)/sum(spec));
+%  % spec = exp(-0.5 * ((n - mu)./sigma).^2) ./ (sqrt(2*pi) .* sigma);
+%  
+%  %x2 = resample(x2,8000,44100);
+%  %spec = mfcc(x',8000,100);
+%  %spec = abs(sum(spec'))';
+%  
+% x2 = x2(1:4:end);
+% spec2 = abs(fft(hanning(length(x2))'.*x2,2048));
+% spec2 = spec2(1:1024);
+%  mlmx = fft2melmx(1024,round(44100/16),40);
+% [size(mlmx) size(spec2)];
+%  mfcc = 20*log10(1+spec*mlmx');
+%  spec = 20*log10(1+spec*mlmx');
+
+%  spec = adapt_thresh(mfcc,2,3);
+%  x2 = resample(x2,1378,44096);
+%  len = length(x2);
+%  w = hanningz(len);
+%  w = w(:)';
+%  % take fft
+%  spec = abs(fft(w.*x2,1024));
+%  spec = adapt_thresh(spec(1:512),16,15);
+  spec = spec(1:512);
+%  mlmx = fft2melmx(512,round(44100),40);
+%  spec = spec*mlmx';
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/dojsdiv2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function sd = dojsdiv2(pre,post);
+
+pre = pre-min(pre);
+post = post-min(post);
+pre = pre(:)';
+post = post(:)';
+pre = pre+eps;
+post = post+eps;
+pre = pre/sum(pre);
+
+pi1 = 0.5;
+pi2 = 0.5;
+
+% normalise to sum to unity
+pre = pre/(sum(pre)+eps);
+post = post/(sum(post)+eps);
+
+% combined distribution
+a1 = pi1*pre + pi2*post;
+
+%sd = -sum(a1.*log(a1)) + pi1*sum(pre.*log(pre)) + pi2*sum(post.*log(post));
+
+
+sd = sum((-a1.*log(a1)) + pi1*(pre.*log(pre)) + pi2*(post.*log(post)));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/findmeter.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,62 @@
+function [timesig,three_energy,four_energy] = findmeter_mm(acf,period,thresh);
+
+% a simple enegy test with current period value, where energy is evaluated
+% at small regions at double and four times the period, to be compared with
+% energy at 3 and 6 times the beat period, to decide if the time signature
+% of the current frame is duple or triple.
+
+if nargin<3
+	thresh = 0;
+%default state
+end
+
+
+acf = acf/sum(acf);
+
+period = round(period);
+
+sw= 2;
+
+
+%  % new approach - LESS GOOD than the old approach
+%  
+%  numperiods = floor(length(acf)/period);
+%  num4multiples = floor(numperiods/4);
+%  %  % just check we haven't gone over the end of the acf
+%  num4multiples = num4multiples- double((period*num4multiples*4+sw) > length(acf));
+%  
+%  % initialize;
+%  three_energy = 0;
+%  four_energy = 0;
+%  
+%  for i=1:length(num4multiples)
+%  
+%  	three_energy = three_energy + sum(acf(3*i*period-sw:1:3*i*period+sw));
+%  	four_energy = four_energy + sum(acf(4*i*period-sw:1:4*i*period+sw));
+%  
+%  end
+
+
+% old approach... 
+
+if(length(acf)<6*period+sw)
+    
+
+    three_energy = sum(acf(3*period-sw:1:3*period+sw));
+
+    four_energy = sum(acf(4*period-sw:1:4*period+sw));
+
+else
+
+    three_energy = sum(acf(3*period-sw:1:3*period+sw)) + sum(acf(6*period-sw:1:6*period+sw));
+
+    four_energy = sum(acf(4*period-sw:1:4*period+sw)) + sum(acf(2*period-sw:1:2*period+sw));
+
+end
+
+
+if ( (four_energy - three_energy) >= thresh )
+    timesig = 4;
+else
+    timesig = 3;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/findmeter_mm.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,62 @@
+function [timesig,three_energy,four_energy] = findmeter_mm(acf,period,thresh);
+
+% a simple enegy test with current period value, where energy is evaluated
+% at small regions at double and four times the period, to be compared with
+% energy at 3 and 6 times the beat period, to decide if the time signature
+% of the current frame is duple or triple.
+
+if nargin<3
+	thresh = 0;
+%default state
+end
+
+
+acf = acf/sum(acf);
+
+period = round(period);
+
+sw= 2;
+
+
+%  % new approach - LESS GOOD than the old approach
+%  
+%  numperiods = floor(length(acf)/period);
+%  num4multiples = floor(numperiods/4);
+%  %  % just check we haven't gone over the end of the acf
+%  num4multiples = num4multiples- double((period*num4multiples*4+sw) > length(acf));
+%  
+%  % initialize;
+%  three_energy = 0;
+%  four_energy = 0;
+%  
+%  for i=1:length(num4multiples)
+%  
+%  	three_energy = three_energy + sum(acf(3*i*period-sw:1:3*i*period+sw));
+%  	four_energy = four_energy + sum(acf(4*i*period-sw:1:4*i*period+sw));
+%  
+%  end
+
+
+% old approach... 
+
+if(length(acf)<6*period+sw)
+    
+
+    three_energy = sum(acf(3*period-sw:1:3*period+sw));
+
+    four_energy = sum(acf(4*period-sw:1:4*period+sw));
+
+else
+
+    three_energy = sum(acf(3*period-sw:1:3*period+sw)) + sum(acf(6*period-sw:1:6*period+sw));
+
+    four_energy = sum(acf(4*period-sw:1:4*period+sw)) + sum(acf(2*period-sw:1:2*period+sw));
+
+end
+
+
+if ( (four_energy - three_energy) >= thresh )
+    timesig = 4;
+else
+    timesig = 3;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/ftacf.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function acf = ftacf(x)
+
+
+x = x(:);
+
+[M,N] = size(x);
+
+X = fft(x,2^nextpow2(2*M-1));
+acf = ifft(X.*conj(X));
+
+acf = acf(1:M)./[M:-1:1]';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/get_dfs.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,90 @@
+function df = get_dfs(x,p)
+
+% function to calculate the following onset detection functions
+% df{1} = complex spectral difference
+% df{2} = spectral difference
+% df{3} = phase deviation
+x = mean(x,2);
+
+% onset analysis step increment
+o_step = p.winlen*2; % should be 1024
+% onset analysis winlen
+o_winlen = o_step*2; % should be 2048
+
+hlfwin = o_winlen/2; % will be half fft size
+
+% formulate hanningz window function
+win = hanningz(o_winlen);
+%  win = tukeywin(o_winlen,0.5);
+
+% loop parameters
+N = length(x);
+pin = 0;
+pend = N - o_winlen;
+
+% vectors to store phase and magnitude calculations
+theta1 = zeros(hlfwin,1);
+theta2 = zeros(hlfwin,1);
+oldmag = zeros(hlfwin,1);
+
+% output onset detection functions
+df = {};
+
+% df sample number
+k = 0;
+while pin<pend
+    
+    k=k+1;
+    % calculate windowed fft frame
+    segment = x(pin+1:pin+o_winlen);
+    X = fft(fftshift(win.*segment));
+    %X = X.*fftshift(hanningz(length(X)));
+    X = X(floor(length(X)/2)+1:length(X),:);
+  %  X = X.*[length(X):-1:1]';
+    % separate into magnitude
+    mag = (abs(X));
+	
+%  	mag = [0 abs(diff(log(eps+mag)))']';
+    % and phase
+    theta = angle(X);
+    
+    % complexsd part
+        dev=princarg(theta-2*theta1+theta2);
+%  		keyboard
+        meas=oldmag - (mag.*exp(i.*dev));
+        df{1}(k) = sum(sqrt((real(meas)).^2+(imag(meas)).^2));
+        
+%      % spectral difference part    
+%          dev2=sqrt(mag.^2-oldmag.^2);
+%          df{2}(k) = sum(abs(dev2(mag>0.1)));
+%      
+%      
+%      % phase deviation part
+%          df{3}(k) = sum(abs(dev((mag>0.1))));
+%  %        df{3}(k) = sum(abs(dev(end-5:end)));
+%          
+%      % energy part
+%          df{4}(k) = sum(abs(segment));
+%          
+%      % hfc part    
+%          df{5}(k) = sum(mag.*(length(mag):-1:1)');
+%      %    df{5}(k) = sum(mag.*rand(hlfwin,1));
+%          
+    % update vectors
+    theta2 = theta1;
+    theta1 = theta;
+    oldmag = mag;
+    pin = pin+o_step;
+end
+
+% now interpolate each detection function by a factor of 2,
+% to get resolution of 11.6ms
+
+for j=1:1,%5
+    df{j} = interp(df{j},2);
+    % also check there are no negative elements
+    df{j}(df{j}<0) = 0;
+    % and scale to sum to unity
+%    df{j} = (df{j}+eps)/sum(df{j}+eps);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/getalignment2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,60 @@
+function [alignment] = getalignment2(dfframe,phwv,period,timesig)
+
+
+period = round(period);
+
+
+
+%normalise and linearly weight most recent strongest
+%dfframe = dfframe.*([1:length(dfframe)]);
+
+% reverse 
+dfframe = dfframe(end:-1:1); 
+
+% output of alignment comb filter
+phcf = zeros(1,period);
+
+numelem = floor((length(dfframe)-0)/period);
+
+%dfframe = [dfframe' zeros(1,length(dfframe))]';
+%this line is neeeded for using commented part below
+
+if (~timesig) % initial state
+
+   
+
+    % fit as many as possible
+    for i=1:period
+        for b = 1:numelem, 
+                phcf(i) = phcf(i) + dfframe(( b-1)*period+i) * phwv(i); %+ ...
+%  			dfframe(( b-1)*period+i+1) * phwv(i) + ...
+%    				dfframe(( b-1)*period+i+2) * phwv(i);% + ...
+%    				dfframe(( b-1)*period+i+3) * phwv(i) + ...
+%  				dfframe(( b-1)*period+i+4) * phwv(i);
+         end
+    end
+
+else
+
+    numelem = timesig; 
+    for i=1:period
+        for b = 1:numelem, 
+         %   for a = 1-b:b-1
+            phcf(i) = phcf(i) + dfframe(( b-1)*period+i) * phwv(i) + ...
+			dfframe(( b-1)*period+i+1) * phwv(i) + ...
+				dfframe(( b-1)*period+i+2) * phwv(i) + ...
+				dfframe(( b-1)*period+i+3) * phwv(i) + ...
+				dfframe(( b-1)*period+i+4) * phwv(i);
+          %  end
+        end
+    end
+
+end
+
+
+[val,alignment] = max(phcf);
+[val2,bestguess] = max(phwv);
+
+if alignment>=2,
+alignment = alignment-1;
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/getbcfs2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,88 @@
+function [bcf,frame,beats] = getbcfs2(fname,beats);
+
+
+
+if nargin<2
+
+    [x fs] = wavread(fname);
+    x = mean(x,2);
+    if fs~=44100
+        x = resample(x,44100,fs);
+    end
+    p = bt_parms;
+
+    df = get_dfs(x(1:4:end),bt_parms(0.01161*4));
+    [beats,timesig] = newtt_mm(df{1},p);
+    beats = beatadjust(beats,df{1});
+end
+
+
+
+beats = beats(:)';
+
+
+siz = wavread(fname,'size');
+[x fs] = wavread(fname);
+x = mean(x,2);
+%  if siz(2)>1
+%      x = mean(x')';
+%  end
+
+if fs ~= 44100
+    x = resample(x,44100,fs);
+end
+
+beats = round(beats);
+beats(beats>length(x)) = [];
+beats = sort(beats);
+%beats = beats - 4096;
+%beats(beats<1) = 1;
+
+%  
+%  spark = sparsekernel(110, 880, 36, 44100/16, 0.054);
+%  spark(1025:end,:) = [];
+spark = 1;
+
+for k=1:length(beats)-1
+%      [spec(k,:),mfcc(k,:), cq(k,:),hpcp(k,:),chroma(k,:)] = chromaframe(x(beats(k):beats(k+1)),spark);
+    [spec(k,:)] = chromaframe(x(beats(k):beats(k+1)),spark);
+
+end
+
+
+
+for k=1:size(spec,1)-1,
+
+%     bcf.spec(k) = dobeatkl(spec(k,:),spec(k+1,:));
+%     bcf.cq(k) = dobeatkl(cq(k,:).^2,cq(k+1,:).^2);
+%     bcf.hpcp(k) = dobeatkl(hpcp(k,:).^2,hpcp(k+1,:).^2);
+%     bcf.chroma(k) = dobeatkl(chroma(k,:).^2,chroma(k+1,:).^2);
+%     bcf.mfcc(k) = dobeatkl(mfcc(k,:).^2,mfcc(k+1,:).^2);
+    bcf.spec(k) = dojsdiv2(spec(k,:),spec(k+1,:));
+%      bcf.cq(k) = dojsdiv2(cq(k,:),cq(k+1,:));
+%      bcf.hpcp(k) = dojsdiv2(hpcp(k,:),hpcp(k+1,:));
+%      bcf.chroma(k) = dojsdiv2(chroma(k,:),chroma(k+1,:));
+%      bcf.mfcc(k) = dojsdiv2(mfcc(k,:),mfcc(k+1,:));
+
+end
+
+
+%  bcf.spec=adapt_thresh(bcf.spec,2,1);
+
+frame.spec = spec;
+
+%  % my added bit
+%  temp = 0*spec;
+%  for i=1:length(temp)-1
+%  	temp(i)=spec(i)+0.2/spec(i+1);
+%  end
+%  frame.spec = temp;
+
+
+
+%  frame.cq = cq;
+%  frame.hpcp = hpcp;
+%  frame.chroma = chroma;
+%  frame.mfcc = mfcc;
+
+% for i=1:222, [c,n] = meterTracker(wavread(files(i+2).name),44100); kc{i} = round(44100*c.measures); kn{i} = round(44100*n.measures); if~mod(i,10),i,end; clear c; clear n; end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/getmeasures2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function out = getmeasures2(fname,ts);
+
+if nargin<2
+	% optional argument to hand label the timesignature
+    ts = 0;
+end
+
+
+[x fs] = wavread(fname);
+x = mean(x,2);
+
+if fs~=11025,
+    x = resample(x,11025,fs);
+end
+
+x = x + randn(length(x),1) * 0.0000001;
+
+df = get_dfs(x,bt_parms(0.01161*4));
+disp 'onset detection function'
+
+[beats,localscore,timesig] = newtt_hmm_dp(df{1});
+disp 'beats'
+
+[bcf,frame] = getbcfs2(fname,beats);
+if~timesig, timesig = 4; end
+
+if ts
+    measures = bcfm(bcf.spec,beats,ts);
+else
+    measures = bcfm(bcf.spec,beats,timesig);
+end
+
+
+
+out.beats = beats/44100;
+out.measures = measures/44100;
+out.timesig = timesig;
+out.df = df{1};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/getmeasures3	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,39 @@
+function out = getmeasures4(fname,ts);
+
+if nargin<2
+	% optional argument to hand label the timesignature
+    ts = 0;
+end
+
+sz = wavread(fn,'size');
+
+[x fs] = wavread(fname,round([0.5 0.7]*sz(1)));
+x = mean(x,2);
+
+if fs~=11025,
+    x = resample(x,11025,fs);
+end
+
+x = x + randn(length(x),1) * 0.0000001;
+
+df = get_dfs(x,bt_parms(0.01161*4));
+disp 'onset detection function'
+
+[beats,localscore,timesig] = newtt_hmm_dp(df{1});
+disp 'beats'
+
+[bcf,frame] = getbcfs2(fname,beats);
+if~timesig, timesig = 4; end
+
+if ts
+    measures = bcfm(bcf.spec,beats,ts);
+else
+    measures = bcfm(bcf.spec,beats,timesig);
+end
+
+
+
+out.beats = beats/44100;
+out.measures = measures/44100;
+out.timesig = timesig;
+out.df = df{1};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/getmeasures3.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,38 @@
+function out = getmeasures3(x,fs,ts);
+
+if nargin<2
+	% optional argument to hand label the timesignature
+    ts = 0;
+end
+
+
+% [x fs] = wavread(fname);
+% x = mean(x,2);
+
+if fs~=11025,
+    x = resample(x,11025,fs);
+end
+
+x = x + randn(length(x),1) * 0.0000001;
+
+df = get_dfs(x,bt_parms(0.01161*4));
+disp 'onset detection function'
+
+[beats,localscore,timesig] = newtt_hmm_dp(df{1});
+disp 'beats'
+
+% [bcf,frame] = getbcfs2(fname,beats);
+% if~timesig, timesig = 4; end
+% 
+% if ts
+%     measures = bcfm(bcf.spec,beats,ts);
+% else
+%     measures = bcfm(bcf.spec,beats,timesig);
+% end
+
+
+
+out.beats = beats/44100;
+% out.measures = measures/44100;
+% out.timesig = timesig;
+% out.df = df{1};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/getmeasures4.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+function out = getmeasures4(fname,ts);
+
+if nargin<2
+	% optional argument to hand label the timesignature
+    ts = 0;
+end
+
+sz = wavread(fname,'size');
+
+[x fs] = wavread(fname);
+x = mean(x,2);
+
+if fs~=11025,
+    x = resample(x,11025,fs);
+end
+
+x = x + randn(length(x),1) * 0.0000001;
+
+df = get_dfs(x,bt_parms(0.01161*4));
+disp 'onset detection function'
+
+[beats,localscore,timesig] = newtt_hmm_dp(df{1});
+disp 'beats'
+
+% [bcf,frame] = getbcfs2(fname,beats);
+% if~timesig, timesig = 4; end
+% 
+% if ts
+%     measures = bcfm(bcf.spec,beats,ts);
+% else
+%     measures = bcfm(bcf.spec,beats,timesig);
+% end
+reduced_fs = 86.12;
+% x = resample(x,reduced_fs,11025);
+% x = abs(x);
+winlength = round(reduced_fs/10/2)*2;
+win = gausswin(winlength);
+earlybeats = [0 mean([beats(2:end);beats(1:end-1)])];
+
+
+
+
+% for iBeat = 1:length(beats)
+%     beatindex = max(round(beats(iBeat)/(44100/reduced_fs)),winlength/2+1);
+%     earlybeatindex = max(round(earlybeats(iBeat)/(44100/reduced_fs)),winlength/2+1);
+% %     beatstrength = sum(x(beatindex-winlength/2+(1:winlength)) .* win);
+%     beatstrength = sum(localscore(beatindex-winlength/2+(1:winlength))' .* win);
+% %     earlybeatstrength = sum(x(earlybeatindex-winlength/2+(1:winlength))
+% %     .* win);
+%     earlybeatstrength = sum(localscore(earlybeatindex-winlength/2+(1:winlength))' .* win);    
+%     if earlybeatstrength > 1.5 * beatstrength
+%         beats(iBeat) = earlybeats(iBeat);
+%     end
+% end
+
+out.beats = beats/44100;
+% out.measures = measures/44100;
+% out.timesig = timesig;
+% out.df = df{1};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/getperiod.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,56 @@
+function [period,rcf,period2] = getperiod(acf,wv,timesig,pmax,pmin,lowest)
+
+
+% using for loop approach to extract beat period
+
+pmax = round(pmax);
+pmin = round(pmin);
+
+rcf = zeros(1,pmax);
+
+
+if(~timesig) % timesig unknown, must be general state
+    numelem = 4;
+
+    for i=pmin:pmax-1, % maximum beat period
+        for a=1:numelem, % number of comb elements
+            for b=1-a:a-1, % gs using normalization of comb elements
+                rcf(i) = rcf(i) + (acf(a*i+b)*wv(i))/(2*a-1);
+            end
+        end
+    end
+
+else
+    numelem = timesig; % timesig known must be context dependent state
+
+    for i=pmin:pmax-1, % maximum beat period
+        for a=1:numelem, % number of comb elements
+            for b=1-a:a-1, % cds not normalizing comb elements
+                rcf(i) = rcf(i) + acf(a*i+b)*wv(i);
+            end
+        end
+    end
+
+end
+
+
+[val, period] = max(rcf); 
+
+
+
+
+period = refineperiod(period,acf,timesig);
+
+
+ while(period<lowest)
+     period = period*2;
+ end
+%period
+
+if (~sum(abs(wv))) % i.e. using cds_wv before initialised
+    period = 0;
+end
+
+% not important... just here to prevent an error in the number of outputs
+period2 = period*2;
+%figure(1); plot(rcf); pause
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/hanningz.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+function w=hanningz(n)
+w=.5*(1-cos(2*pi*(0:n-1)'/(n)));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/newtt_hmm_dp.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,162 @@
+function [beats,localscore,timesig,ppath] = newtt_hmm_dp(df,tempo)
+
+if nargin<2
+	tempo = 0;
+end
+
+beats = [];
+
+p = bt_parms;
+
+df = df(:)';
+%  
+% df = df/alpha_norm(9,df);
+df = qnormalise(df,9,2);
+
+% work out period track with viterbi decoding
+[ppath,obs,prob,wv]= tempo_hmm(df,p.step,tempo);
+
+%  ppp=textread('home/studio/Desktop/path.txt');
+%  ppp = [ppp(:)' ppp(end)*ones(1,2)];
+%  ppath = ppp;
+
+ppath(ppath<20) = 20;
+dp = abs(diff(ppath));
+dp = [0 dp(:)'];
+dp(dp>16) = 16; 
+%  plot(dp),pause(0.01);
+% now incorporate ellis' dynamic programming,
+% but for time-varying period....! 
+
+
+tempmat = (ppath'*ones(1,p.step))';
+pd = round(tempmat(:));
+%  length(pd)
+
+
+%  df = abs(diff(df));
+% prob = 0.5+0.5*prob/max(prob);
+% prob = 4*prob;
+
+%  prob = 4*prob/max(prob);
+
+
+%  a=ftacf(adapt_thresh(df));
+%  a=a(1:512);
+%  [tmp,r]=getperiod(a,wv,0,128,1,0);
+%  r=sunity(r);
+%  val=max(r);
+%  tightness = 100*val;
+tightness= [4]; % want to try and get a tightness out of the signal automatically...
+
+	
+alpha=0.8;
+mpd = round(median(ppath));
+templt = exp(-0.5*(([-mpd:mpd]/(mpd/32)).^2));
+localscore = conv(templt,df);
+% this removes the offset imposed by the filtering...
+
+localscore = localscore(round(length(templt)/2)+[1:length(df)]);
+localscore = localscore/sum(localscore);
+
+
+aacf = ftacf(localscore);
+[timesig] = findmeter_mm(aacf(1:512),mpd);
+
+%  %  subplot(311); plot(localscore);
+%  %  al = localscore;
+%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%  %%%% little bootstrap on phase
+%  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%  apin = 0;
+%  awinlen=512;
+%  astep = 128;
+%  apend = length(localscore)-2*awinlen;
+%  ak = 0;
+%  while (apin<apend)
+%  	ak = ak+1;
+%  	align = getalignment2(localscore(apin+1:apin+awinlen),ones(1,pd(ak)),pd(ak),0);
+%  	try
+%  		localscore(apin+align-4:apin+align+4) = (1+gausswin(9)').*localscore(apin+align-4:apin+align+4);
+%  	catch
+%  		temp_a = 1;
+%  	end	
+%  	apin=apin+astep;
+%  end
+%  
+%  %  subplot(312); plot(localscore);
+%  %  subplot(313); plot(al-localscore);
+backlink = zeros(1,length(localscore));
+cumscore = zeros(1,length(localscore));
+
+starting = 1;
+for i = 1:length(localscore)
+%  	pause;
+%  	i
+% search range for previous beat
+	prange = round(-2*pd(i)):-round(pd(i))/2;
+
+%   want to update tightness based on periodicity change..
+	% or as andrew does.. whether it's an important beat.
+	% Skewed window
+	mu = -pd(i);
+%  	tightness = prob(ceil(i/128));
+%  	sigma = pd(i)/4;
+%  	txwt = exp(-0.5 * ((prange - mu)./sigma).^2) ./ (sqrt(2*pi) .* sigma);
+	txwt = exp( -0.5*  (  (  ( tightness    - 1* log(1+dp(ceil(i/128))) )   *   log(prange/-pd(i))).^2)  );
+%  	txwt = -(prange ./ mu.^ 2) .* exp(-prange .^ 2 ./ (2*mu .^ 2));
+%  	txwt = txwt.^2;
+%  	keyboard
+	timerange = i + prange;
+
+% Are we reaching back before time zero?
+	zpad = max(0, min(1-timerange(1),length(prange)));
+% Search over all possible predecessors and apply transition 
+% weighting
+	scorecands = txwt .* [zeros(1,zpad),cumscore(timerange(zpad+1:end))];
+% Find best predecessor beat
+	[vv,xx] = max(scorecands);
+% Add on local score
+	cumscore(i) = alpha*vv + (1-alpha)*localscore(i);
+
+% special case to catch first onset
+%  if starting == 1 & localscore(i) > 100*abs(vv)
+	if starting == 1 & localscore(i) < 0.01*max(localscore);
+		backlink(i) = -1;
+	else
+		backlink(i) = timerange(xx);
+		% prevent it from resetting, even through a stretch of silence
+		starting = 0;
+	end
+
+end
+
+
+%try
+%	align = getalignment2(localscore(end-1024:end),ones(1,2*pd(end)),2*pd(end),0);
+%catch
+	align = getalignment2(localscore(end-512:end),ones(1,1*pd(end)),1*pd(end),0);
+%end
+
+b = [];
+b = length(df) - align;
+
+%  b = bestendx;
+
+while backlink(b(end)) > 0
+b = [b,backlink(b(end))];
+end
+
+
+b = fliplr(b);
+
+% return beat times in secs
+beats = (b*512); % seems to be an offset.
+beats(beats<1) = [];
+%  
+%  otherbeats{kk} = b;
+%  score(kk) = dfscore(b,df);		
+%  [val,ind] = max(score);
+%  beats = otherbeats{ind};
+%  beats = 512*(length(df)-beats/512); 
+%  beats = sort(beats);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/princarg.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+function phase=princarg(phasein)
+%phase=princarg(phasein) maps phasein into the [-pi:pi] range
+    phase=mod(phasein+pi,-2*pi)+pi;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/refineperiod.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,65 @@
+function period = refineperiod(period,acf,timesig);
+
+
+if ~timesig, timesig=4; end
+
+% peaks = zeros(1,timesig);
+% ind = period;
+% for i=1:timesig
+%     segment = acf(ind*i-(i-1):ind*i+(i-1));
+%     [val,loc] = max(segment);
+%     peaks(i) = loc + ind*i-(i-1)-1;
+% end
+% 
+% 
+% for i=1:timesig
+%     peaks(i) = (peaks(i)-1)/i;
+% end
+% 
+% period = mean(peaks);
+% 
+% 
+
+
+
+
+
+% 
+% 
+if ~timesig
+    timesig =4;
+end
+
+ind = period;
+
+if (timesig==4)
+    peak = zeros(1,4);
+
+    peak(1) = ind;
+
+    [val2,ind2] = max(acf(2*ind-1:2*ind+1));
+    peak(2) = ind2 + 2*ind-2;
+
+    [val3,ind3] = max(acf(3*ind-2:3*ind+2));
+    peak(3) = ind3 + 3*ind-4;
+
+    [val4,ind4] = max(acf(4*ind-3:4*ind+3));
+    peak(4) = ind4 + 4*ind-9;
+
+    period = mean([ peak(1) peak(2)/2 peak(3)/3 peak(4)/4 ]);
+
+else
+
+    peak = zeros(1,3);
+
+    peak(1) = ind;
+
+    [val2,ind2] = max(acf(2*ind-1:2*ind+1));
+    peak(2) = ind2 +2*ind-2;
+
+    [val3,ind3] = max(acf(3*ind-2:3*ind+2));
+    peak(3) = ind3 + 3*ind-4;
+
+    period = mean([ peak(1) peak(2)/2 peak(3)/3 ]);
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/sunity.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+function out =sunity(in);
+
+out = in/sum(eps+in);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/tempo_hmm.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,148 @@
+function [path,obs,prob,wv,tmat,posterior]= tempo_hmm(df,step,tempo,tightness)
+
+
+%  if nargin<4
+%  	step = 128;
+%  	tempo = 0;
+%  	tightness = 8;
+%  end
+
+if nargin<3
+	step = 128;
+	tempo = 0;
+end
+
+% df = df/alpha_norm(9,df);
+df = qnormalise(df,9,2);
+p = bt_parms;
+winlen = 512;
+
+
+
+df = [df(:)' zeros(1,winlen/2)]; % add half a frame... then fix last 2 values
+% try using matlab hmm to do tempo tracking...
+df = df(:)';
+
+pin = 0;
+pend = length(df) - winlen;
+n = [1:128];
+%  p.rayparam = 33;
+
+if tempo
+	mu = p.fact/tempo;
+	sigma = mu/4;
+	wv = exp(-0.5 * ((n - mu)./sigma).^2) ./ (sqrt(2*pi) .* sigma);
+else
+	wv = (n ./ p.rayparam .^ 2) .* exp(-n .^ 2 ./ (2*p.rayparam .^ 2));
+end
+
+wv = sunity(wv);
+lenwv = length(wv);
+%  wv = ~~wv;
+
+ct = 0;
+while(pin<pend)
+
+
+	ct = ct+1;
+	segment = adapt_thresh(df(pin+1:pin+winlen));
+%  	acf(:,ct) = (ftacf(segment));
+	acf(:,ct) = [ ftacf(segment(:))' zeros(1,512-winlen)]';
+
+	[temp,rcf] = getperiod(acf(:,ct),wv,0,128,1,p.lowest);
+	temp2 = adapt_thresh(rcf);
+%  	st = sum(temp2);
+%  	temp3 = zeros(1,lenwv);
+%  	tempmat = zeros(lenwv);
+%  	for i=1:lenwv,
+%  		for j=1:lenwv,
+%  			tempmat(i,j) = (temp2(i)+temp2(j));
+%  		end
+%  		tempmat(i,i) = 0;
+%  	end;	
+%  	temp3 = sum(tempmat); %plot(temp3); pause;
+	temp3=temp2;
+	temp3 = temp3'.*(acf(1:length(temp3),ct));
+%  	temp3 = acf(1:length(wv),ct);
+%  	temp(1:10) = 0;
+%  	temp(118:end) = 0;
+%  	temp3(1:10) = 0;
+
+%  	for i=1:lenwv,
+%  		temp4(i) = temp2(i)+st;
+%  	end
+%  	keyboard
+% 	obs(:,ct) = sunity(temp3(:)); %% WAS NOT COMMENTED WHEN MATTHEW GAVE IT
+% 	TO ME.
+    obs(:,ct) = sunity(rcf) + 0.001*rand(1,length(rcf));
+%  	obs(:,ct) = (temp3(:));
+%  	keyboard
+%  	obs(:,ct) = sunity(adapt_thresh(rcf(:)));
+
+
+	pin = pin+step;
+end
+
+
+
+tmat = zeros(128);
+% make transition matrix
+for i=20:118, tmat(:,i) = sunity(normpdf(n,i,8))'; end;
+%  %  [alpha, beta, gamma] = fwdback(wv,tmat,obs);
+%  figure; mesh(tmat); 
+
+%  t = textread('/home/studio/Desktop/tmat.txt');
+%  
+%  tmat = reshape(t,128,128);
+%  %  figure(1); mesh(tmat);
+%  
+%  for i=1:size(tmat,1)
+%  	tmat(i,:) = 1/128+filtfilt(gausswin(9),1,tmat(i,:));
+%  end
+%  
+%  for i=1:size(tmat,2)
+%  	tmat(:,i) = 1/128+filtfilt(gausswin(9),1,tmat(:,i));
+%  end
+%  for i=1:size(tmat,2)
+%  	tmat(:,i) = sunity(tmat(:,i));
+%  end
+%  %  figure; mesh(tmat); 
+%  tmat(1:20,:) = 0;
+%  tmat(:,1:20) = 0;
+%  tmat(120:128,:) = 0;
+%  tmat(:,120:128) = 0;
+
+
+
+%  figure(2);  mesh(tmat);
+
+%  keyboard
+% [path,posterior] = viterbi_path(wv,tmat,obs);
+path = viterbi_path(wv,tmat,obs);
+% try tracking backwards.. probably doesn't matter
+%% FIXME - forwards backwards?
+%  [path,posterior] = viterbi_path(wv,tmat,fliplr(obs));
+%  path = fliplr(path);
+%  path
+
+%  obs = obs/sum(sum(obs));
+
+% 
+% for i=1:length(path),
+% % 	prob(i) = sum(obs(path(i)-2:path(i)+2,i));
+% 
+%     prob(i) = sum(obs(path(i)-2:path(i)+2,i));
+% 
+% %     range = max(min(size(obs,1),path(i)-2:path(i)+2),1);
+% %     prob(i) = sum(obs(range,i));
+% 
+% 	%path(i)= refineperiod(path(i),acf(:,i),0);
+% end
+
+path = [path path(end)*ones(1,2)];
+prob = 1;
+
+
+%  path = interp(path,2);
+
+% for i=1:222, [r(1,i),r(2,i),r(3,i),r(4,i)]=cont_eval(anns.beats{i},beats{i},0.175);end; mean(r')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_beattracker/viterbi_path.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+function [path,p] = viterbi_path(prior, transmat, obslik)
+% VITERBI Find the most-probable (Viterbi) path through the HMM state trellis.
+% path = viterbi(prior, transmat, obslik)
+%
+% Inputs:
+% prior(i) = Pr(Q(1) = i)
+% transmat(i,j) = Pr(Q(t+1)=j | Q(t)=i)
+% obslik(i,t) = Pr(y(t) | Q(t)=i)
+%
+% Outputs:
+% path(t) = q(t), where q1 ... qT is the argmax of the above expression.
+
+
+% delta(j,t) = prob. of the best sequence of length t-1 and then going to state j, and O(1:t)
+% psi(j,t) = the best predecessor state, given that we ended up in state j at t
+
+scaled = 1;
+
+T = size(obslik, 2);
+prior = prior(:);
+Q = length(prior);
+
+delta = zeros(Q,T);
+psi = zeros(Q,T);
+path = zeros(1,T);
+scale = ones(1,T);
+
+
+t=1;
+delta(:,t) = prior .* obslik(:,t);
+if scaled
+  [delta(:,t), n] = normalise(delta(:,t));
+  scale(t) = 1/n;
+end
+psi(:,t) = 0; % arbitrary value, since there is no predecessor to t=1
+for t=2:T
+  for j=1:Q
+    [delta(j,t), psi(j,t)] = max(delta(:,t-1) .* transmat(:,j));
+    delta(j,t) = delta(j,t) * obslik(j,t);
+  end
+  if scaled
+    [delta(:,t), n] = normalise(delta(:,t));
+    scale(t) = 1/n;
+  end
+end
+[p(T), path(T)] = max(delta(:,T));
+for t=T-1:-1:1
+  path(t) = psi(path(t+1),t+1);
+end
+
+%  keyboard
+
+% If scaled==0, p = prob_path(best_path)
+% If scaled==1, p = Pr(replace sum with max and proceed as in the scaled forwards algo)
+% Both are different from p(data) as computed using the sum-product (forwards) algorithm
+
+if 0
+if scaled
+  loglik = -sum(log(scale));
+  %loglik = prob_path(prior, transmat, obslik, path);
+else
+  loglik = log(p);
+end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+/.DS_Store/1.1.1.1/Wed Aug 31 15:49:35 2005//
+/addshort2list.m/1.6/Mon Oct 10 16:52:44 2005//
+/checklabs.m/1.4/Wed Sep 28 10:35:25 2005//
+/checklabsyntax.m/1.6/Wed Sep 28 10:39:46 2005//
+/chord2fifthpositions.m/1.1/Mon Oct  3 11:39:41 2005//
+/chord2midinotes.m/1.7/Thu Aug  3 12:10:47 2006//
+/chord2notes.m/1.9/Mon Oct 31 17:22:10 2005//
+/chord2pitchclasses.m/1.1/Mon Oct  3 11:39:17 2005//
+/chord2quality.m/1.1/Thu Nov  3 15:12:50 2005//
+/contents.m/1.11/Wed Nov 30 15:40:00 2005//
+/degree2note.m/1.5/Wed Sep 28 13:52:52 2005//
+/degree2semitone.m/1.4/Wed Sep 28 10:50:50 2005//
+/degrees2notes.m/1.4/Wed Sep 28 10:45:41 2005//
+/degrees2quality.m/1.1/Thu Nov  3 15:13:53 2005//
+/degrees2semitones.m/1.5/Mon Oct  3 11:27:47 2005//
+/getchordinfo.m/1.5/Mon Oct 31 16:22:10 2005//
+/interval2degree.m/1.5/Wed Sep 28 13:14:17 2005//
+/interval2semitone.m/1.4/Wed Sep 28 13:15:45 2005//
+/labread.m/1.4/Wed Sep 28 13:17:04 2005//
+/labwrite.m/1.4/Wed Sep 28 13:18:21 2005//
+/mlf2lab.m/1.4/Wed Sep 28 13:26:11 2005//
+/note2degree.m/1.1/Fri Sep 30 11:41:14 2005//
+/note2fifthinfo.m/1.3/Fri Sep 30 11:50:33 2005//
+/note2fifthposition.m/1.3/Fri Sep 30 11:50:51 2005//
+/note2pitchclass.m/1.5/Mon Oct 31 16:21:33 2005//
+/notes2fifthpositions.m/1.1/Mon Oct  3 11:40:29 2005//
+/notes2pitchclasses.m/1.1/Mon Oct  3 11:40:08 2005//
+/parsechord.m/1.5/Mon Oct 31 16:23:03 2005//
+/parsedegree.m/1.5/Mon Oct 10 15:39:17 2005//
+/parsedegreelist.m/1.4/Wed Sep 28 13:38:53 2005//
+/parsenote.m/1.4/Wed Sep 28 13:40:10 2005//
+/short2quality.m/1.2/Tue Nov  8 14:19:42 2005//
+/shorthand2degrees.m/1.6/Tue Aug  1 20:52:51 2006//
+/syntaxcheck.m/1.8/Mon Oct 31 16:07:36 2005//
+/types.m/1.5/Wed Nov 30 15:33:10 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/chordtools
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/addshort2list.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,178 @@
+%
+%ADDSHORT2LIST Combine degrees of a shorthand with another degree list
+% 
+% [fulldegreelist, success, errormessage] = addshort2list(shorthand, degreelist, {verbose})
+% 
+% Combine shorthand and degreelist to form full degree list for a chord.  
+% Takes into account the omit degree character '*' in producing final list.
+% 
+% Success = 1 if shorthand and degreelist combined correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% returns:  fulldegreelist (string)
+%           success (boolean)
+%           errormessage (string)
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [fulldegreelist, success, errormessage] = addshort2list(shorthand, degreelist, verbose)
+
+% set verbose default to 0
+if nargin < 3
+    verbose = 0;
+end
+
+errormessage = '';
+
+% initialise variables
+fulldegreelist = '';
+shortintervals = [];
+degreeintervals = [];
+addlist = [];
+success = 1;
+
+% convert shorthand string to list of degrees
+[shortdegrees, ok, errors]  = shorthand2degrees(shorthand);
+
+if ok
+    % if that works convert the shorthand degrees and degreelist to
+    % intervals and accidentals
+    
+    % add the implied 1 interval to the shorthand list
+    if isempty(shortdegrees)
+        rootinterval = '1'; % no comma if shorthand is empty
+    else
+        rootinterval = '1,'; % comma shows that there are further degrees after this one
+    end
+        
+    
+    [shortintervals, ok, errors] = parsedegreelist([rootinterval shortdegrees]); 
+
+    if (ok)
+
+      
+      % this part of the algorithm finds all the present intervals and sorts
+      % them into ascending numeric order
+  
+      % First put the shorthand intervals into the full list
+      
+      [ilength,y] = size(shortintervals);
+   
+      for index = 1:ilength
+          % convert interval to a semitone value  
+          semitone = interval2semitone(shortintervals(index,1),shortintervals(index,2));
+          
+          % Using the semitone value as an index will find redundant
+          % degrees and also sort them in number order. Multiplying the interval by its
+          % presence value leaves either the interval value or 0. Any element 
+          % in the array with interval of 0 will be discarded later
+          % We add 1 to the semitone value to handle the '1'  or 'unity'
+          % interval that would return a 0 semitone value
+          
+          % record the interval 
+          addlist(semitone+1,1) = shortintervals(index,1) .* shortintervals(index,3);
+          % record the accidentals as well
+          addlist(semitone+1,2) = shortintervals(index,2);
+          
+      end
+    else
+        success = 0;
+    end
+
+    [degreeintervals, ok2, errors] = parsedegreelist(degreelist);
+    ok = ok && ok2;
+    
+    if ok
+      % Now add the degrees from the degreelist taking redundant and 
+      % ommitted degrees into account 
+      
+      [ilength,y] = size(degreeintervals);
+   
+      for index = 1:ilength
+          % convert interval to a semitone value  
+          [semitone, ok, errors] = interval2semitone(degreeintervals(index,1),degreeintervals(index,2));
+          
+          if ok && semitone >= 0
+          % record the interval 
+          addlist(semitone+1,1) = degreeintervals(index,1) .* degreeintervals(index,3);
+          % record the accidentals as well
+          addlist(semitone+1,2) = degreeintervals(index,2);
+          
+          else
+             success = 0; 
+          end
+          
+      end
+    else
+        success=0;
+    end
+    
+    
+    % now create fulldegreelist
+    if ok
+
+        [ilength,y] = size(addlist);
+
+        for index = 1:ilength
+
+            % if there is a non zero interval in this element, convert 
+            % it to a degree symbol and add it to the output list
+            if(addlist(index,1) ~=0)
+
+                degreesymbol = interval2degree(addlist(index,1),addlist(index,2));
+
+                if isempty(fulldegreelist)
+                    % if this is the first degree then start list
+                    fulldegreelist = degreesymbol; 
+                else
+                    % add to list with a separating comma
+                    fulldegreelist = [fulldegreelist ',' degreesymbol];
+                end
+            end
+        end
+    else
+
+        success = 0;
+        
+    end
+    
+else
+    
+    success = 0;
+    
+end
+
+
+if success == 0
+    errormessage = [errors sprintf(['Error in addshort2list: unsuccessful '...
+                    'combination  "' shorthand '" and "' degreelist '"\n'])];
+    
+    if verbose ==1
+       fprintf(1,errormessage);
+    end
+       
+       
+end   
+
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/checklabs.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+%
+% CHECKLABS check chord syntax in all lab files in a directory
+% 
+% success = checklabs(directory, logfile)
+% 
+% Check the syntax of chord symbols in every lab file in the target
+% directory.  A log of syntax errors is created in the text file logfile
+% 
+% Success = 1 if all symbols have correct syntax, 0 otherwise.
+%
+% returns:  success (boolean)
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [success] = checklabs(directory, logfile)
+
+olddir = cd;
+
+cd(directory);
+
+files = dir('*.lab');
+
+ilength = length(files);
+
+success = 1;
+
+fid = fopen(logfile, 'a');
+
+for index = 1:ilength
+    
+    ok = checklabsyntax(files(index).name,fid);
+
+    success = success && ok;
+
+end
+
+fclose(fid);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/checklabsyntax.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,70 @@
+%
+% CHECKLABSYNTAX Check the syntax of all chords in a lab file
+% 
+% [success] = checklabsyntax(labfile, {fid})
+% 	
+% Checks syntax of all chord symbols in a lab file. Any incorrect chords 
+% will produce syntax errors and be quoted with time of chord from the 
+% labfile given for inspection.
+% 
+% fid is the file id of the output log file.  If not given, the error log 
+% will be printed to the screen
+% 
+% Success = 1 if all symbols have correct syntax, 0 otherwise.
+%
+% Returns: success (boolean)
+% 
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [success] = checklabsyntax(labfile,fid)
+
+if nargin < 2
+       fid = 1;
+end
+
+success = 1;
+
+[times1,t2,symbols] = labread(labfile);
+
+ilength = length(symbols);
+
+% new file
+fprintf(fid, ['*** File: ' labfile ' ***\n\n']);
+
+errormessage = '';
+
+for index = 1:ilength
+    
+    [ok, errormessage] = syntaxcheck(char(symbols(index)));
+    
+    
+    if ok == 0
+        
+        success = 0;
+        
+        fprintf(fid,['Time: %f seconds\n' errormessage '\n\n'], times1(index));
+        
+    end
+end
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/chord2fifthpositions.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,82 @@
+%
+%CHORD2FIFTHPOSITIONS Convert chord symbol to pitch positions on line of fifths
+% 
+% [fifthpostions, bass, success, errormessage] = chord2fifthpostions(chordsymbol, {verbose})
+% 
+% Converts a chord symbol to an array of integer positions on the line of fifths.
+% C is the reference position 0.
+%
+% In the case of the 'no chord' symbol 'N' function returns an empty array
+%
+% Success = 1 if notes extracted from chordsymbol correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls:    chord2notes
+%           notes2fifthpositions
+% 
+% returns:  fifthpostions (array of integers)           
+%           success (boolean)
+%           errormessage (string)
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%             
+function [fifthpostions, bass, success, errormessage] = chord2fifthpostions(chordsymbol, verbose)
+
+% set verbose default to 0
+if nargin < 2
+    verbose = 0;
+end
+
+errormessage = '';
+mainlist = '';
+success = 1;
+fifthpostions = [];
+bass = '';
+
+% get constituent notes
+[chordnotes, bassnote, success, errormessage] = chord2notes(chordsymbol);
+
+if success && ~isempty(chordnotes)
+% find fifthpostions of notes
+[fifthpostions, success, errormessage] = notes2fifthpositions(chordnotes);
+end
+
+if success && ~isempty(bassnote)
+[bass, success, errormessage] = note2fifthposition(char(bassnote));
+end
+
+
+
+if success == 0
+    errormessage = [errormessage sprintf(['Error in chord2fifthpostions: Couldn''t convert chord"' chordsymbol '"\n'])];   
+    if verbose ==1
+       fprintf(1,errormessage);
+    end
+       
+       
+end  
+    
+    
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/chord2midinotes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,148 @@
+%
+%CHORD2MIDINOTES Generate MIDI note values for a given chord symbol
+% 
+% [midinotes, success, errormessage] = chord2midinotes(chordsymbol, {verbose})
+% 
+% Obtains a set of midi note values for notes present in chord "chordsymbol".
+% The voicing is built on the rootnote with all other degrees occuring 
+% above in number order unless a bass degree is specified.
+%
+% In the case of the 'no chord' symbol 'N' function returns midinote -1
+%
+% Success = 1 if chord is converted correctly else 0.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+%
+% Returns:  midinotes (array of integers)
+%           success (boolean)
+%           errormessage (string)
+%
+%
+% % Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [midinotes, success,errormessage] = chord2midinotes(chordsymbol, verbose)
+
+% set verbose default to 0
+if nargin < 2
+    verbose = 0;
+end
+
+errormessage = '';
+mainlist = '';
+success = 1;
+midinotes = 0;
+
+% parse the chordsymbol
+[rootnote,shorthand,degreelist,bass, success, errormessage] = getchordinfo(chordsymbol);
+
+if success
+
+
+    %if 'no chord' then return -1
+    if rootnote == 'N'
+
+        midinotes = -1;
+    else
+
+        % get root's pitchclass with respect to middle C and calculate absolute
+        % pitch of root in that octave   
+        if success
+
+        [rootpitchclass, success, errormessage] = note2pitchclass(rootnote);
+
+        % midinote C4 = 60 so add pitchclass to calculate rootpitch
+        rootpitch = 60 + rootpitchclass;
+
+        end
+
+
+        % combine shorthand and degreelist and obtain semitone values for each
+        % degree
+        if success
+
+            [mainlist, success, errormessage] = addshort2list(shorthand, degreelist);
+
+            if success
+
+                [semitones,success,errormessage] = degrees2semitones(mainlist);
+
+                % add rootpitch to obtain midinotes
+                chordpitches = semitones + rootpitch;
+
+            end
+
+        end
+
+        % Now find the bass note
+
+        if success
+
+            % if we haven't got a bass degree then play the rootnote as the
+            % bassnote
+            if isempty(bass)
+                basspitchclass = rootpitchclass;
+            else
+                % otherwise convert the bassdegree to a note
+                [bassnote,success,errormessage] = degree2note(bass, rootnote);
+
+                if success
+
+                    [basspitchclass, success, errormessage] = note2pitchclass(char(bassnote));
+
+                end
+            end
+
+            if success
+                % calculate bass note so that it is in the octave below the
+                % rest of the chord i.e. add to C3 midinote 48
+                basspitch = basspitchclass + 48;
+
+                % Put midinote list together
+                midinotes = [basspitch, rootpitch];
+                
+                for index = 1:length(chordpitches)
+                    if chordpitches(index) ~= rootpitch
+                       midinotes = [midinotes, chordpitches(index)];
+                    end
+                end
+            end
+
+        end
+    end
+
+%alter pitches for chords with high roots
+if rootpitchclass > 6
+    midinotes = midinotes-12;
+end
+
+end
+    
+if success == 0
+    errormessage = [errormessage sprintf(['Error in chord2midinotes: Couldn''t convert chord"' chordsymbol '"\n'])];   
+    if verbose ==1
+       fprintf(1,errormessage);
+    end
+end  
+    
+    
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/chord2notes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,138 @@
+%
+%CHORD2NOTES Convert chord symbol to list of constituent notes
+% 
+% [chordnotes, bassnote, success, errormessage] = chord2notes(chordsymbol, {verbose})
+% 
+% Converts a chord symbol to a cell array of note strings and a bassnote string.
+%
+% In the case of the 'no chord' symbol 'N' function returns an empty array
+%
+% Success = 1 if notes extracted from chordsymbol correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls:    getnoteinfo
+%           parsenote
+%           addshort2list
+%           degree2note
+% 
+% returns:  chordnotes  (cell array of note strings)
+%           bassnote (string)           
+%           success (boolean)
+%           errormessage (string)
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%             
+function [chordnotes, bassnote, success, errormessage] = chord2notes(chordsymbol, verbose)
+
+% set verbose default to 0
+if nargin < 2
+    verbose = 0;
+end
+
+errormessage = '';
+mainlist = '';
+success = 1;
+chordnotes = [];
+bassnote = '';
+
+% parse the chordsymbol
+[rootnote,shorthand,degreelist,bass, success, errormessage] = getchordinfo(chordsymbol);
+
+
+
+
+%if 'no chord' then return N
+if (success == 1)
+    
+
+    
+    if rootnote == 'N'
+        
+        chordnotes = [];
+    else
+
+
+        % combine shorthand and degreelist and obtain note names for each
+        % degree
+        if success
+
+            [mainlist, success, errormessage] = addshort2list(shorthand, degreelist);
+
+            if success
+
+                % convert list of degrees to list of notes 
+                [chordnotes,success,errormessage] = degrees2notes(mainlist,rootnote);
+                 
+            end
+
+        end
+
+        % Now find the bass note
+
+        if success
+
+            if ~isempty(bass)
+
+                [bassnote,success,errormessage] = degree2note(bass, rootnote);
+
+                if success
+                    
+                    ilength = length(chordnotes);
+                    index = 1;
+                    while index<=ilength
+                        if char(bassnote) == char(chordnotes(index))
+                            index = ilength +1;
+                            contains = 1;
+                        else
+                            contains = 0;
+                            index = index +1;
+                        end
+                    end
+                    
+                    if contains == 0
+                        
+                        chordnotes = [bassnote; chordnotes];
+                    end
+                end
+            else
+                bassnote = rootnote;
+            end
+
+
+        end
+    end
+end
+
+if success == 0
+    errormessage = [errormessage sprintf(['Error in chord2notes: Couldn''t convert chord"' chordsymbol '"\n'])];   
+    if verbose ==1
+       fprintf(1,errormessage);
+    end
+       
+       
+end  
+    
+    
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/chord2pitchclasses.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,81 @@
+%
+%CHORD2PITCHCLASSES Convert chord symbol to array of pitch classes
+% 
+% [pitchclasses, bassclass, success, errormessage] = chord2pitchclasses(chordsymbol, {verbose})
+% 
+% Converts a chord symbol to an array of integer pitch class values and a
+% bass pitch class value. Pitch class values are referenced w.r.t. C = 0.
+%
+% In the case of the 'no chord' symbol 'N' function returns an empty array
+%
+% Success = 1 if notes extracted from chordsymbol correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls:    chord2notes
+%           notes2pitchclasses
+% 
+% returns:  pitchclasses (array of integers)
+%           bassclass (integer)           
+%           success (boolean)
+%           errormessage (string)
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%             
+function [pitchclasses, bassclass, success, errormessage] = chord2pitchclasses(chordsymbol, verbose)
+
+% set verbose default to 0
+if nargin < 2
+    verbose = 0;
+end
+
+errormessage = '';
+mainlist = '';
+success = 1;
+pitchclasses = [];
+bassclass = '';
+
+% get constituent notes
+[chordnotes, bassnote, success, errormessage] = chord2notes(chordsymbol);
+
+if success && ~isempty(chordnotes)
+% find pitchclasses of notes
+[pitchclasses, success, errormessage] = notes2pitchclasses(chordnotes);
+end
+
+if success && ~isempty(bassnote)
+[bassclass, success, errormessage] = note2pitchclass(char(bassnote));
+end
+
+if success == 0
+    errormessage = [errormessage sprintf(['Error in chord2pitchclasses: Couldn''t convert chord"' chordsymbol '"\n'])];   
+    if verbose ==1
+       fprintf(1,errormessage);
+    end
+       
+       
+end  
+    
+    
+    
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/chord2quality.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,85 @@
+%
+% CHORD2QUALITY return the chord quality of a given chord symbol
+% 
+% [quality,success, errormessage] = chord2quality(chordsymbol, {verbose})
+% 
+% Returns the chord quality of a given chord symbol. Quality values are from 
+% the enumeration:
+%
+% 0   Major
+% 1   Minor
+% 2   Diminished
+% 3   Augmented
+% 4   Suspended
+%
+% Success = 1 if symbols parsed correctly, 0 otherwise. 
+%
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls:    getchordinfo
+%           short2quality
+%           degrees2quality
+% 
+% returns:  quality (integer)
+%           success  (boolean)  
+%           errormessage (string)
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+
+function [quality, success, errormessage] = chord2quality(chordsymbol,verbose)
+
+quality = '';
+errormessage = '';
+
+if nargin < 2
+    verbose = 0;
+end
+
+[rootnote,shorthand,degreelist,bassdegree,success,error] = getchordinfo(chordsymbol);
+
+if success
+    
+    if ~isempty(shorthand)
+    
+        [quality, success, error] = short2quality(shorthand);
+        
+    else
+   
+        [quality, success, error] = degrees2quality(degreelist);
+        
+    end
+    
+end
+
+
+
+if(success==0) 
+
+    errormessage = sprintf([error 'Error in Chord2quality: Chord "' chordsymbol '"\n']);
+    
+    if verbose == 1
+        fprintf(1, errormessage);
+    end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/contents.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+% C4DM Chord Symbols Toolkit 
+%
+% Version 1.0 November 05
+% 
+%TYPES
+% types - help describes types, structures and enumerations used in toolbox
+% 
+%SYMBOL MANIPULATION FUNCTIONS
+% parsechord           - Parse chord symbol to its constituent string elements
+% parsenote            - Parse a note string to a natural plus accidentals
+% parsedegree          - Parse a degree to an interval plus accidentals
+% parsedegreelist      - Parse a degree list to intervals and accidentals 
+% degree2semitone      - Convert a degree to equivalent number of semitones
+% interval2semitone    - Convert interval + accidentals to semitone value
+% interval2degree      - Convert interval + accidentals to a degree string
+% degrees2semitones    - Convert a degree list to an array of semitone values
+% degree2note          - Convert a degree to correctly spelled note w.r.t. a root
+% degrees2quality      - Return the quality of a given degreelist
+% note2pitchclass      - Convert a note to a pitchclass value w.r.t middle C
+% notes2pitchclasses   - Convert a note list to an array pitchclasses
+% note2fifthinfo       - Find line of fifths natural-position and accidentals  
+% note2fifthposition   - Find note position on the line of fifths w.r.t. C=0
+% notes2fifthpositions - Convert notes list to positions on line of fifths
+% note2degree          - Convert a note to a degree w.r.t. a given root
+% shorthand2degrees    - Convert a shorthand string to equivalent degreelist
+% short2quality        - Return the quality of a given shorthand string
+% 
+% 
+%HIGHER LEVEL FUNCTIONS
+% getchordinfo         - Check chord symbol validity and return constituent parts
+% syntaxcheck          - Check the syntax and validity of a chord symbol 
+% addshort2list        - Combine degrees of a shorthand with another degree list
+% chord2quality        - Returns the chord quality of a given chord symbol
+% chord2notes          - Convert chord symbol to list of constituent notes
+% chord2midinotes      - Generate MIDI note values for a given chord symbol
+% chord2pitchclasses   - Convert chord symbol to array of pitch classes
+% chord2fifthpositions - Convert chord symbol to pitch positions on line of fifths 
+%
+%LAB FILE FUNCTIONS
+% labread              - Read in times and symbols from a lab file
+% labwrite             - Write times and symbols to a lab file
+% mlf2lab              - Convert an mlf transcription file to a lab file
+% checklabsyntax       - Check the syntax of all chords in a lab file
+% checklabs            - Check chord syntax in all lab files in a directory
+% 
+% Author: Christopher Harte, September 05 
+%
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/degree2note.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,157 @@
+%
+%DEGREE2NOTE convert a degree to correctly spelled note w.r.t. a root
+% 
+% [note,success,errormessage] = degree2note(degree, root {verbose})
+% 
+% Converts a degree to a note (string) with root as reference note 
+% for degree interval.
+% 
+% Success = 1 if degree is converted correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+%
+% returns:  note (string)
+%           success (boolean)
+%           errormessage (string)
+%
+% See also degrees2notes, parsenote.
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [note,success,errormessage] = degree2note(degree, root,verbose)
+
+if nargin < 3
+    verbose = 0;
+end
+errormessage = '';
+
+error1 = '';
+error2 = '';
+
+note = [];
+
+intervaltranslation = [5,0,2,4,-1,1,3,5]; % scale degree translations on line of fifths 
+
+fifthpositions = {'F','C','G','D','A','E','B'}; %order of naturals on line of fifths
+
+success = 1;
+
+% parse the root note
+[rootnatural,rootaccs, rsuccess, error1] = parsenote(root);
+
+%parse the degree
+[interval, degreeaccs, present, dsuccess, error2] = parsedegree(degree);
+
+% if parsing symbols was successful
+if(rsuccess && dsuccess);
+
+    switch(rootnatural) % find root natural position on line of fifths
+
+        case 'F'
+            fifthindex = 0;        
+        case 'C'
+            fifthindex = 1;
+        case 'G'
+            fifthindex = 2;
+        case 'D'
+            fifthindex = 3;
+        case 'A'
+            fifthindex = 4;
+        case 'E'
+            fifthindex = 5;
+        case 'B'
+            fifthindex = 6;
+
+    end
+
+    %locate enharmonic root on line of fifths (modulo 6 arithmetic)   
+    
+    fifthoffset = rootaccs*7;
+    
+    fifthindex = fifthindex + fifthoffset;
+    
+    
+    % calculate interval translation on line of fifths (add 1 to account
+    % for matlab referencing of array elements... 
+    intervaloffset = intervaltranslation(mod(interval,7)+1); 
+    finalposition = fifthindex + intervaloffset;
+    
+    
+    naturalvalue = mod(finalposition,7);
+    
+    
+    % calculate number of accidentals
+    if finalposition <0 
+        %if final position is negative then calculate number of flats
+        % remembering to include the extra first flat (-1)
+        accidentals = fix((finalposition+1)/7) + degreeaccs -1;
+    
+    else
+        % note is a natural or has a number of sharps
+        accidentals = fix(finalposition/7) + degreeaccs;
+    end
+    
+    note = fifthpositions(naturalvalue+1);
+    
+    if accidentals > 0
+        
+        for i=1:accidentals
+            
+            note = strcat(note, '#');
+            
+        end
+        
+    elseif accidentals <=0
+        
+        for i=1:abs(accidentals)
+            
+            note = strcat(note, 'b');
+            
+        end
+    end
+        
+else
+ 
+    success=0;
+    
+end
+
+if(success==0) % correct degree therefore return success = 1 
+    % if not an integer then the degree string is incorrect
+    errormessage = [error1 error2 sprintf(['Error in degree2note: Unrecognised degree "' degree '" or root "' root '"\n'])]; 
+    
+    if verbose == 1
+       fprintf(1,errormessage); 
+    end
+    
+end
+    
+    
+    
+    
+
+    
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/degree2semitone.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,76 @@
+%
+% DEGREE2SEMITONE convert a degree to equivalent number of semitones
+% 
+% [semitone,success, errormessage] = degree2semitone(degree, {verbose})
+% 
+% Converts a degree string to equivalent number of semitones.
+%
+% Success = 1 if symbols parsed correctly, 0 otherwise. 
+%
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls:    parsedegree
+%           interval2semitone
+% 
+% returns:  semitone (integer)
+%           success  (boolean)  
+%           errormessage (string)
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%		
+function  [semitone, success, errormessage] = degree2semitone(degree, verbose)
+    
+if nargin <2 
+    % verbose defaults 0
+    verbose = 0;
+end
+
+errormessage = '';
+
+ilength = length(degree);
+
+success=0;
+semitone = 0;
+
+% parse the degree string
+
+[interval, accidentals, present, ok] = parsedegree(degree);
+
+if (ok == 1)
+    
+    % convert interval and accidentals to equivalent number of semitones 
+    [semitone, ok, errors] = interval2semitone(interval,accidentals);
+    
+    success = 1;
+    
+else
+    
+    errormessage = sprintf(['Error in degree2semitone: incorrect degree "' degree '"\n']);
+
+end
+
+if (verbose ==1) && (success ==0)
+    fprintf(1,errormessage); 
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/degrees2notes.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,111 @@
+%
+%DEGREES2NOTES Convert a degreelist to an array of notes w.r.t. a root
+% 
+% [notes, success, errormessage] = degrees2notes(degreelist, root, {verbose})
+% 
+% Converts the degrees in degreelist to correctly spelled notes with 
+% respect to the root note.
+% 
+% Success = 1 if degrees converted correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+%
+% returns: notes (cell array of strings)
+%          success (boolean)
+%          errormessage (string)
+% 
+% See also degree2note
+%
+%
+%% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [notes, success, errormessage] = degrees2notes(degreelist, root, verbose)
+
+% set verbose default to 0
+if nargin < 3
+    verbose = 0;
+end
+
+errormessage = '';
+
+ilength = length(degreelist);
+
+index = 1;
+
+tempindex = 1;
+
+tempstring = '';
+
+success = 1;
+
+notes = {};
+
+
+while index <= ilength
+    
+   
+    while (degreelist(index) ~= ',')  
+        
+        tempstring(tempindex) = degreelist(index);
+        tempindex = tempindex +1;
+        index = index + 1;
+        
+        if(index > ilength)
+            break;
+        end
+        
+        if (degreelist(index) == ',') && (index == ilength)
+            success = 0;
+            errormessage = sprintf(['Error in degrees2notes: degree list finishes with a comma "' degreelist '"\n']);
+        end
+            
+            
+    end
+    
+        [newnote,ok, error] = degree2note(tempstring,root);
+        % concatenate error messages if there are any...
+        errormessage = [errormessage error];
+        
+        if(ok == 1)
+            tempstring = '';
+            tempindex = 1;
+            notes = [notes; cellstr(newnote)];
+            
+            index = index + 1;
+        else
+
+            errormessage = [errormessage sprintf(['Error in degrees2notes: incorrect degree in list "' degreelist '"\n'])];
+            success = 0;
+            index = ilength +1;            
+        end
+    
+    
+end
+
+if (success == 0) && (verbose == 1)
+
+    fprintf(1,errormessage)
+    
+end    
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/degrees2quality.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,115 @@
+%
+%DEGREES2QUALITY convert a degreelist to chord quality enumeration
+% 
+% [quality,success, errormessage] = degrees2quality(degreelist, {verbose})
+% 
+% Converts a list of degree strings to an integer value denoting the
+% chord's quality. Quality values are from the enumeration:
+%
+% 0   Major
+% 1   Minor
+% 2   Diminished
+% 3   Augmented
+% 4   Suspended
+%
+% Success = 1 if symbols parsed correctly, 0 otherwise. 
+%
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls:    degrees2semitones
+% 
+% returns:  quality (integer)
+%           success  (boolean)  
+%           errormessage (string)
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [quality,success,errormessage] = degrees2quality(degreelist,verbose)
+
+
+
+
+quality = '';
+errormessage = '';
+
+if nargin < 2
+    verbose = 0;
+end
+
+% define templates for the 5 different triad chords (four quality families
+% plus suspension) - weights mean maj thirds will have more effect than min
+% 3rds which in turn have more effect than 5ths and then 2nds and 4ths
+
+templates = [[1,0,0,0,6,0,0,4,0,0,0,0]; ... % maj
+             [1,0,0,5,0,0,0,4,0,0,0,0]; ... % min
+             [1,0,0,5,0,0,4,0,0,0,0,0]; ... % dim
+             [1,0,0,0,6,0,0,0,4,0,0,0]; ... % aug
+             [1,0,2,0,0,2,0,4,0,0,0,0]];    % sus
+             
+         
+% get the semitone equivalents of the degrees in the degree list             
+[semitones,success,error] = degrees2semitones(degreelist);
+
+indexa = 1;
+
+% initialise a binary vector showing which semitones are present 
+present = zeros(1,12);
+
+while indexa <= 3 && indexa <= length(semitones) 
+    
+    % for each of the first three semitones in the list make its position a
+    % one in the vector 'present' 
+    
+    if semitones(indexa) < 12
+    
+        present(semitones(indexa)+1) = 1;
+    
+    end
+    indexa = indexa +1;
+    
+end
+
+% multiply present by the templates matrix to give a vector of scores for
+% the possible qualities
+qvector = templates * present';
+
+
+% find maximum value from the qualities vector
+% this function benfits from the max function's picking of the first
+% maximum value if there are several equal ones so is predisposed toward 
+% major if the quality is not obvious from the input. (e.g. C:(1) returns major)  
+[value,index] = max(qvector);
+
+% take 1 from index to give correct enumeration
+quality = index-1;
+
+
+if(success==0) 
+
+    errormessage = sprintf([error 'Error in degrees2quality: incorrect degree in list "' degreelist '"\n']);
+    
+    if verbose == 1
+        fprintf(1, errormessage);
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/degrees2semitones.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,117 @@
+%
+%DEGREES2SEMITONES convert a degree list to an array of semitone values
+% 
+% [semitones, success, errormessage] = degrees2semitones(degreelist, {verbose})
+% 
+% Converts a list of degrees to corresponding semitone intervals 
+% 
+% Success = 1 if symbols parsed correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls degree2semitone
+% 
+% returns:  semitones (array of integers)
+%           success (boolean)
+%           errormessage (string)
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+%
+
+function [semitones, success, errormessage] = degrees2semitones(degreelist, verbose)
+
+% set verbose default to 0
+if nargin < 2
+    verbose = 0;
+end
+
+errormessage = '';
+
+ilength = length(degreelist);
+
+index = 1;
+
+tempindex = 1;
+
+tempstring = '';
+
+success = 1;
+
+parindex  = 1;
+
+semitones = [];
+
+
+while index <= ilength
+    
+   
+    while (degreelist(index) ~= ',')  
+        
+        tempstring(tempindex) = degreelist(index);
+        tempindex = tempindex +1;
+        index = index + 1;
+        
+        if(index > ilength)
+            break;
+        end
+        
+        if (degreelist(index) == ',') && (index == ilength)
+            success = 0;
+            errormessage = sprintf(['Error in degrees2semitones: degree list finishes with a comma "' degreelist '"\n']);
+        end
+            
+            
+    end
+    
+        [semitones(parindex),ok, error] = degree2semitone(tempstring);
+        % concatenate error messages if there are any...
+        errormessage = [errormessage error];
+        
+        if(ok == 1)
+            tempstring = '';
+            tempindex = 1;
+            parindex = parindex + 1;
+            index = index + 1;
+        else
+
+            errormessage = [errormessage sprintf(['Error in degrees2semitones: incorrect degree in list "' degreelist '"\n'])];
+            success = 0;
+            index = ilength +1;            
+        end
+    
+    
+end
+
+if (success == 0) && (verbose == 1)
+
+    fprintf(1,errormessage)
+    
+end    
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/getchordinfo.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,91 @@
+%
+% GETCHORDINFO Check chord symbol validity and return constituent parts
+% 
+% [rootnote, shorthand,degreelist,bassdegree, success, errormessage] = getchordinfo(chordsymbol, {verbose})
+% 
+% Checks symbol for correct syntax and returns chord information  Differs 
+% from parsechord in that notes, shorthands, degrees and bass values are all 
+% checked for validity in the process.
+% 
+% Success = 1 if all symbols have correct syntax, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% Returns:	rootnote   (string)
+%           shorthand  (string)
+%           degreelist (string)
+%           bassdegree (string)
+%           success (boolean) true or false for correct syntax 
+%           errormessage (string)  
+%
+% See also: syntaxcheck
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%		
+function [rootnote, shorthand,degreelist,bassdegree, success, errormessage] = getchordinfo(chordsymbol, verbose)
+
+if nargin < 2
+    verbose = 0;
+end
+    
+errormessage = '';
+rootnote = '';
+shorthand =  '';
+degrees = '';
+bassdegreel = '';
+
+
+success = 0;
+
+% parse the chord symbol into its constituent parts
+[rootnote,shorthand, degreelist,bassdegree, success, errormessage] = parsechord(chordsymbol);
+
+if success == 1
+    
+    if rootnote ~= 'N'
+        
+        % check validity of rootnote
+        [temp, temp2, success, errormessage] = parsenote(rootnote);
+
+        %check validity of shorthand list
+        if ((success == 1) && ~(isempty(shorthand)))
+           [temp, success, errormessage] = shorthand2degrees(shorthand);
+        end        
+        
+        % check validity of degreelist
+        if (success == 1) && ~(isempty(degreelist))
+            [temp, success, errormessage] = parsedegreelist(degreelist);
+        end
+    
+        % check validity of bass degree
+        if (success == 1) && ~(isempty(bassdegree))
+           [temp,temp2,temp3, success, errormessage] = parsedegree(bassdegree); 
+        end
+          
+    end
+
+end
+
+if (success ==0) && (verbose == 1)
+    fprintf(1,errormessage);
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/interval2degree.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,84 @@
+%
+% INTERVAL2DEGREE
+% 
+% [degree,success,errormessage] = interval2degree(interval,accidentals,{verbose})
+% 
+% Converts an interval and accidental pair to a degree string.
+% 
+% Success = 1 if interval converted correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% returns:  degree (string)
+%           success (boolean)
+%           errormessage (string)
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%		
+function [degree,success,errormessage] = interval2degree(interval,accidentals, verbose)
+
+% set verbose default to 0
+if nargin < 3
+    verbose = 0;
+end
+
+errormessage = '';
+
+
+success = 1;
+degree = '';
+
+
+if accidentals >=1
+   % then the interval is either a natural or has a number of sharps 
+    if accidentals ~= 0
+        for index = 1:accidentals 
+            degree = [degree '#'];
+        end
+    end
+    
+else
+    % then the interval has a number of flats
+    
+    for index = 1:abs(accidentals) 
+   
+        degree = [degree 'b'];
+    end
+    
+end
+
+if isnumeric(interval)
+    
+    intervalstring = num2str(interval);
+    degree = [degree intervalstring];
+    
+else
+   success = 0;
+   errormessage = 'Error in interval2degree: incorrect interval';
+end
+    
+if (success == 0) && (verbose == 1)   
+    fprintf(1,errormessage);
+end  
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/interval2semitone.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,73 @@
+%
+% INTERVAL2SEMITONE
+% 
+% [semitone, success, errormessage] = interval2semitone(interval, accidental, {verbose})
+% 
+% Convert an interval and accidentals pair to a semitone value
+% 
+% Success = 1 if interval converted correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% returns:  semitone (string)
+%           success (boolean)
+%           errormessage (string)
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%		
+function [semitone, success, errormessage] = interval2semitone(interval, accidentals, verbose)
+
+if nargin < 3 
+    % verbose defaults 0
+    verbose = 0;
+end
+
+errormessage = '';
+
+% semitone equivalents for intervals
+%           interval   1,2,3,4,5,6,7         
+semitonetranslation = [0,2,4,5,7,9,11];
+
+semitone = 0;
+
+success = 1;
+
+if (interval > 0) && (interval < 50)
+
+% semitone value is the number of semitones equivalent to the interval
+% added to the number of accidentals (sharps are positive, flats are
+% negative) and the number of octaves above the reference note to
+% account for extensions 
+
+semitone = semitonetranslation(mod(interval,8) + fix(interval/8)) + accidentals + 12*fix(interval/8);
+
+else
+    success = 0;
+    
+    errormessage = sprintf('Error in interval2semitone: out of range interval "%d"\n', interval);
+    
+    if verbose == 1
+        fprintf(1,errormessage);
+    end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/labread.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,39 @@
+%
+%LABREAD read lab file
+%
+% [times1, times2, labels] = labread(labfile);
+% 
+% read times and labels from a wavesurfer lab file
+% 
+% 
+% returns: times1 (array of segment start-times)  
+%          times2 (array of segment end-times)
+%          labels (cell array of label strings)
+%
+% See also labwrite, mlf2lab, checklabsyntax.
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+%
+		
+function [times1, times2, labels] = labread(labfile);
+
+[times1,times2, labels] = textread(labfile, '%f %f %s');
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/labwrite.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+%
+%LABWRITE write a labfile to disk
+%
+% labwrite(times1, times2, labels, labfile, {protect})
+%
+% Write time indices and labels to a wavesurfer .lab transcription file
+% with file name labfile
+%  
+% If optional argument 'protect' is 1 then if a lab file of the given name 
+% already exists it will be copied to a backup file with extension '.labx' 
+% before writing new data to the lab file   
+%
+% See also labread, mlf2lab, checklabsyntax.
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+%
+		
+function labwrite(times1, times2, labels, labfile, protect)
+
+if nargin<5
+    protect = 0;
+end
+
+if (protect == 1)
+   check = copyfile(labfile, [labfile 'x']);
+end
+
+fid = fopen(labfile, 'w');
+
+for i = 1:length(times1)
+    
+    outtext = ['%f %f ' char(labels(i)) '\n'];
+    
+    fprintf(fid, outtext, times1(i), times2(i));
+    
+end
+
+fclose(fid);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/mlf2lab.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,54 @@
+%
+% MLF2LAB Convert mlf file to lab file
+% 
+% mlf2lab(inputfile, labfile)
+% 
+% Converts a '.mlf' transcription file "inputfile" to a wavesurfer '.lab' 
+% transcription file "labfile".
+% 
+% See also labread, labwrite, checklabsyntax.
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+		
+%
+function mlf2lab(inputfile, labfile)
+
+
+[timestamps, timestamps2, stamps] = textread(inputfile, '%f %f %s');
+
+
+newtimes = timestamps./10000000;
+newtimes2 = timestamps2./10000000;
+
+
+fid = fopen(labfile, 'w');
+
+for i = 1:length(newtimes)
+    
+    outtext = ['%f %f ' char(stamps(i)) '\n'];
+    
+    fprintf(fid, outtext, newtimes(i), newtimes2(i));
+    
+end
+
+fclose(fid);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/note2degree.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,136 @@
+%
+%NOTE2DEGREE convert a note to a degree w.r.t. a given root
+% 
+% [degree,success,errormessage] = note2degree(note,root,{octave},{verbose})
+% 
+% Converts a note string to a degree with respect to a given root note.
+% Optional value octave gives octave offset to account for extended
+% intervals.
+% 
+% Success = 1 if note converted correctly, 0 otherwise.
+% 
+% Optional argument octave defaults to 0.  
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls: note2fifthposition
+%
+% returns:  degree (string)
+%           success (boolean)
+%           errormessage (string)
+% 
+%
+% Author: Christopher Harte,  September 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%		
+function [degree,success,errormessage] = note2degree(note, root,octave, verbose)
+
+% set verbose default to 0
+if nargin < 3
+   octave = 0; 
+   verbose = 0;
+
+elseif nargin < 4
+   verbose = 0;
+end
+
+errormessage = '';
+success = 1;
+degree = '';
+
+% interval translations on the line of fifths
+fifthtranslations = [1,5,2,6,3,7,4];
+
+
+% get note and root natural position and accidentals on line of fifths 
+[noteposition, success1,error1] = note2fifthposition(note);
+  
+[rootposition, success2,error2] = note2fifthposition(root);
+
+if success1 && success2
+
+    % take the difference between the two note positions for relative positions
+    % of notes with respect to one and other
+    fifthsdifference = noteposition - rootposition + 1;
+
+    % natural difference on line of fifths
+    fifthsinterval = mod((fifthsdifference-1),7);
+
+    i=0;
+
+    % find number of accidentals apart on line of fifths
+    if fifthsdifference < 0 % if above 0 then either natural or sharp
+
+      %if final position is negative then calculate number of flats
+        % remembering to include the extra first flat (-1)
+        accidentals = fix((fifthsdifference+1)/7) -1;
+    
+    else
+        % note is a natural or has a number of sharps
+        accidentals = fix(fifthsdifference/7);
+
+    end
+
+
+    % put the required number of sharps or flats into the output string
+    if accidentals > 0
+        
+        for i=1:accidentals
+            
+           degree = ['#' degree];
+            
+        end
+        
+    elseif accidentals <=0
+        
+        for i=1:abs(accidentals)
+            
+           degree = ['b' degree];
+            
+        end
+    end    
+    
+    
+    % find interval value from translation array
+    interval = fifthtranslations(fifthsinterval+1);
+
+    if octave >= 0
+        interval = interval + 7.*octave;
+    else
+        success = 0;
+        errormessage = 'Error in note2degree: Octave argument is negative';
+    end
+
+
+
+    degree = [degree num2str(interval)];
+
+else
+    success = 0;
+    errormessage = [error1 error2];
+end
+    
+if (success == 0) && (verbose == 1)   
+    fprintf(1,errormessage);
+end  
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/note2fifthinfo.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,94 @@
+%
+%NOTE2FIFTHINFO find line of fifths natural-position and accidentals
+% 
+% [position, accidentals, success,errormessage] = note2fifthinfo(note,{verbose})
+% 
+% Converts a note string to a natural position on the line of fifths and its 
+% corresponding number of sharps or flats. 
+%
+% *** NOTE! *** 
+% Reference for natural positions on line of fifths for this function is F = 0.
+% 
+% Success = 1 if note converted correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls: parsenote
+%
+% returns:  position (integer)
+%           accidentals (integer)
+%           success (boolean)
+%           errormessage (string)
+% 
+%
+% Author: Christopher Harte,  September 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%		
+function [position,accidentals, success, errormessage] = note2fifthinfo(note, verbose)
+
+% set verbose default to 0
+if nargin < 3
+   verbose = 0;
+end
+
+errormessage = '';
+success = 1;
+position = '';
+accidentals = '';
+
+
+[natural, accidentals, success, errormessage] = parsenote(note);
+
+if success
+    switch(natural)
+        case 'F' 
+            position = 0;
+
+        case 'C' 
+            position = 1;
+
+        case 'G' 
+            position = 2;
+
+        case 'D' 
+            position = 3;
+
+        case 'A' 
+            position = 4;
+
+        case 'E' 
+            position = 5;
+
+        case 'B' 
+            position = 6;
+
+        otherwise
+            errormessage = 'Error in note2fifthinfo: unrecognised natural';
+            success=0;
+    end
+end
+        
+            
+if (success == 0) && (verbose == 1)   
+    fprintf(1,errormessage);
+end  
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/note2fifthposition.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,62 @@
+%
+%NOTE2FIFTHPOSITION find note position on the line of fifths w.r.t. C=0
+% 
+% [noteposition, success, errormessage] = note2fifthposition(note,{verbose})
+% 
+% Converts a note string to a natural position on the line of fifths and its 
+% corresponding number of sharps or flats. Reference on line of fifths is C = 0.
+% 
+% Success = 1 if note converted correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls: 	note2fifthinfo
+%
+% returns:  noteposistion (integer)
+%           success (boolean)
+%           errormessage (string)
+% 
+%
+% Author: Christopher Harte,  September 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%		
+function [noteposition, success, errormessage] = note2fifthposition(note, verbose)
+
+% set verbose default to 0
+if nargin < 3
+   verbose = 0;
+end
+
+errormessage = '';
+success = 1;
+noteposition = '';
+
+[notenatural, noteaccidentals, success1,errormessage] = note2fifthinfo(note);
+
+if success
+    noteposition = notenatural + 7.*noteaccidentals -1;
+end        
+            
+if (success == 0) && (verbose == 1)   
+    fprintf(1,errormessage);
+end  
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/note2pitchclass.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,126 @@
+%
+%NOTE2PITCHCLASS convert a note to a pitchclass value w.r.t middle C
+% 
+% [pitchclass, success, errormessage] = note2pitchclass(note, {verbose})
+% 
+% Converts a note string to a pitch class (integer) with C as reference 
+% pitch class 0
+% 
+% Success = 1 if symbols parsed correctly, 0 otherwise.
+%
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% returns:  pitchclass (integer)
+%           success (boolean)
+%           errormessage (string)
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [pitchclass, success, errormessage] = note2pitchclass(note, verbose)
+
+if nargin < 2
+    verbose = 0;
+end
+
+errormessage = '';
+
+ilength = length(note);
+
+index = 1;
+success = 1;
+
+
+% first char should be a natural name A-G
+switch note(index)
+
+    case 'C' % natural C
+            pitchclass = 0; 
+            index = index + 1;
+
+    case 'D' % natural D
+            pitchclass = 2; 
+            index = index + 1;
+    
+    case 'E' % natural E
+            pitchclass = 4; 
+            index = index + 1;
+    
+    case 'F' % natural F
+            pitchclass = 5; 
+            index = index + 1;
+    
+    case 'G' % natural G
+            pitchclass = 7; 
+            index = index + 1;
+    
+    case 'A' % natural A
+            pitchclass = 9; 
+            index = index + 1;
+    
+    case 'B' % natural B
+            pitchclass = 11; 
+            index = index + 1;
+            
+    otherwise %Unrecognised character
+            errormessage = sprintf(['Error in Note2PitchClass: Unrecognised note "' note '"\n']);
+            index = ilength + 1;
+            pitchclass=-1;
+            success = 0;
+         
+end
+
+% any other characters should be either flats or sharps
+while index <= ilength
+           
+    switch(note(index))
+        
+        case 'b' % FLAT
+            pitchclass = pitchclass - 1; %decrement pitchclass value
+            index = index + 1;
+            
+        case '#' % SHARP
+            pitchclass = pitchclass + 1; %increment pitchclass value
+            index = index + 1;
+        
+        otherwise % Unrecognised character
+            errormessage = sprintf(['Error in Note2PitchClass: Unrecognised note "' note '"\n']);
+            index = ilength + 1;
+            pitchclass=-1;
+            success = 0;
+    end        
+            
+end
+
+% Use modulo command to make sure that we are back within range 0-12
+if(success == 1)
+    
+    pitchclass = mod(pitchclass,12);
+    
+else
+   if(verbose == 1)
+      fprintf(1,errormessage); 
+   end
+end
+
+            
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/notes2fifthpositions.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,80 @@
+%
+%NOTES2FIFTHPOSITIONS convert notes list to positions on line of fifths
+% 
+% [pitchclasses, success, errormessage] = notes2fifthpostions(notes, {verbose})
+% 
+% Converts a cell array of note strings to an array of integers denoting 
+% positions on the line of fifths with C as reference position 0.
+% 
+% Success = 1 if symbols converted correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls:    note2pitchclass
+% 
+% returns:  pitchclasses (array of integers)
+%           success (boolean)
+%           errormessage (string)
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+%
+
+function [fifthpositions, success, errormessage] = notes2fifthpostions(notes, verbose)
+
+% set verbose default to 0
+if nargin < 2
+    verbose = 0;
+end
+
+errormessage = '';
+
+ilength = length(notes);
+
+index = 1;
+
+success = 1;
+
+fifthpositions = [];
+
+while index <= ilength
+    
+        [fifthpositions(index), success, errormessage] = note2fifthposition(char(notes(index)));
+    
+        if success
+            index=index+1;
+        else
+            errormessage = [errormessage sprintf(['Error in notes2fifthpostions: couldn''t convert notes "' notes '"\n'])];
+            index = ilength +1;            
+        end
+    
+    
+end
+
+if (success == 0) && (verbose == 1)
+
+    fprintf(1,errormessage)
+    
+end    
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/notes2pitchclasses.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,80 @@
+%
+%NOTES2PITCHCLASSES convert a note list to an array pitchclasses
+% 
+% [pitchclasses, success, errormessage] = notes2pitchclasses(notes, {verbose})
+% 
+% Converts a cell array of note strings to an array of pitch class integer 
+% values. Pitch class values are referenced w.r.t. C = 0. 
+% 
+% Success = 1 if symbols converted correctly, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls note2pitchclass
+% 
+% returns:  pitchclasses (array of integers)
+%           success (boolean)
+%           errormessage (string)
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+%
+
+function [pitchclasses, success, errormessage] = notes2pitchclasses(notes, verbose)
+
+% set verbose default to 0
+if nargin < 2
+    verbose = 0;
+end
+
+errormessage = '';
+
+ilength = length(notes);
+
+index = 1;
+
+success = 1;
+
+pitchclasses = [];
+
+while index <= ilength
+    
+        [pitchclasses(index), success, errormessage] = note2pitchclass(char(notes(index)));
+    
+        if success
+            index=index+1;
+        else
+            errormessage = [errormessage sprintf(['Error in notes2pitchclasses: couldn''t convert notes "' notes '"\n'])];
+            index = ilength +1;            
+        end
+    
+    
+end
+
+if (success == 0) && (verbose == 1)
+
+    fprintf(1,errormessage)
+    
+end    
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/parsechord.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,274 @@
+%
+%PARSECHORD parse chord symbol to its constituent string elements
+% 
+% [rootnote, shorthand, degreelist,
+%              bass, success, errormessage] = parsechord(chord, {verbose})
+% 	
+% Parses the chord symbol string "chord" into its separate string elements. 
+% 
+% NOTE: This function does not check validity of the chord elements, it
+% merely separates them according to the chord syntax. 
+% To obtain chord elements with included validity check use GETCHORDINFO.
+%
+% Success = 1 if symbols parsed correctly, 0 otherwise.
+%
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 	
+% returns:  rootnote        (note string)
+%           shorthand       (shorthand string)
+%           degreelist      (degree-list string)
+%           bass            (degree string)
+%           success         (boolean)
+%           errormessage    (string)
+%
+% See also: getchordinfo                     
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%		
+function  [rootnote, shorthand, degrees, bass, success, errormessage] = parsechord(chord, verbose)
+	
+% set verbose default to 0
+if nargin <2
+    verbose = 0;
+end
+
+ilength = length(chord);
+
+% initialise variables
+errormessage = '';
+rootnote = '';
+shorthand = '';
+degrees = '';
+bass = '';
+
+success = 1;
+index = 1;
+
+
+% check for 'no chord' symbol
+if chord(index) == 'N'
+    rootnote = chord(index);
+    index = index +1;
+    % check to see there are no further characters
+    if(index<=ilength)
+        errormessage = sprintf(['Error in parsechord: \nExtra characters after "no chord" symbol "' chord '"\n']); 
+        success = 0;
+    end
+else
+% parse thechord symbol
+
+    % the first part of the symbol before a switch character should be the root note
+    while ((index <=ilength ))
+    
+        if (chord(index) ==  ':') || (chord(index) ==  '/') || ...
+           (chord(index) ==  '(') || (chord(index) ==  ')')
+            
+            break
+        end
+
+        rootnote(index) = chord(index);
+        index = index+1;
+    
+        if(index > ilength) || (chord(index) == '/')
+            % if chord is a rootnote on its own or with just a bass note 
+            % then it is a major chord therefore set shorthand to 'maj'
+            shorthand = 'maj';
+        end
+    end
+    
+    % initialise booleans to record which switch characters we have found
+    colon = 0;
+    openbracket = 0;
+    closebracket = 0;
+    slash = 0;
+    
+    % parse the rest of the chord symbol
+    while(index <= ilength)
+        
+        % reset temporary index 
+        tempindex = 1;
+        
+       switch(chord(index))
+       
+           case ':'  
+                        
+               % if we find a colon after any switch characters have 
+               % already occured then the symbol is incorrect 
+               if (colon || openbracket || closebracket || slash)
+                    errormessage = sprintf(['Error in parsechord: \nIncorrect character sequence in chord "' chord '"\n']); 
+                    success = 0;
+                    index = ilength+1;
+               else
+                
+                   % found the first instance of a colon character
+                   colon = 1;
+                   
+                   index = index +1;
+                   
+                   if(index > ilength)
+                        errormessage = sprintf(['Error in parsechord: \nFound ":" at end of chord string "' chord '"\n']); 
+                        success = 0; 
+                   end
+                   % colon should be followed by a shorthand string or
+                   % a degree list contained in brackets
+                   while (index <= ilength)
+                       
+                       if (chord(index) ==  ':') || (chord(index) ==  '/') || ...
+                          (chord(index) ==  '(') || (chord(index) ==  ')')
+
+                           break
+                       end
+
+                       % copy character into shorthand
+                       shorthand(tempindex) = chord(index);
+                       index = index +1;
+                       tempindex = tempindex +1;
+
+                   end
+               
+               end
+               
+           case '('
+               
+               % if we have had a colon but no other switch charaters then
+               % an open bracket signifies the start of the degree list
+               if (colon && ~slash && ~closebracket && ~openbracket) 
+                   
+                   openbracket = 1;
+                   
+                   index = index +1;
+                   
+                   while (index <= ilength)
+
+                       if (chord(index) ==  ':') || (chord(index) ==  '/') || ...
+                          (chord(index) ==  '(') || (chord(index) ==  ')')
+
+                           break
+                       end
+                       
+                       % copy character into degrees
+                       degrees(tempindex) = chord(index);
+                       index = index +1;
+                       tempindex = tempindex +1;
+
+                   end
+                   
+                   if(index > ilength)
+                        errormessage = sprintf(['Error in parsechord: \nDegree list brackets not closed in chord "' chord '"\n']); 
+                        success = 0; 
+                   end
+                   
+               else
+                   errormessage = sprintf(['Error in parsechord: \nIncorrect character sequence in chord "' chord '"\n']); 
+                   success = 0;
+                   index = ilength +1;
+               end
+               
+           case ')'
+               
+               
+               % if we find a closing bracket then we should either be at
+               % the end of the symbol or there should be a slash to follow
+               if (colon && openbracket && ~slash && ~closebracket) 
+                   
+                   closebracket = 1;
+                   index = index +1;
+                   
+               else
+                   errormessage = sprintf(['Error in parsechord: \nIncorrect character sequence in chord "' chord '"\n']); 
+                   success = 0;
+                   index = ilength +1;
+               end
+               
+               % check to see that the brackets contained something
+               if isempty(degrees)
+                   errormessage = sprintf(['Error in parsechord: \nBrackets contain no degrees in chord "' chord '"\n']); 
+                   success = 0;
+                   index = ilength +1;
+               end
+               
+               
+           case '/'
+               % forward slash should be followed by a degree string
+              
+                   slash = 1;
+
+                   % move on to next character to process the expected bass degree
+                   index = index +1;
+                                     
+                   % check that we haven't overun the end of the symbol string
+                   if(index > ilength)
+                        errormessage = sprintf(['Error in parsechord: \nNo bass degree "/" at end of chord "' chord '"\n']); 
+                        success = 0; 
+                   end
+                   
+                   % check that if we have had an open bracket that it also
+                   % had a closed bracket
+                   if(xor(openbracket,closebracket))
+                        errormessage = sprintf(['Error in parsechord: \nFound "/" before closing bracket in chord "' chord '"\n']); 
+                        success = 0; 
+                        index = ilength +1;
+                   end
+
+                   % check that the previous character was not a ':'
+                   if(chord(index-2) == ':')
+                        errormessage = sprintf(['Error in parsechord: \nFound "/" directly after ":" in chord "' chord '"\n']); 
+                        success = 0; 
+                        index = ilength +1;
+                   end
+
+                   
+                   while( index <= ilength )
+                       
+                       % if we find a switch character after a slash then
+                       % the symbol is incorrect
+                       if (chord(index) ==  ':') || (chord(index) ==  '/') || ...
+                          (chord(index) ==  '(') || (chord(index) ==  ')')
+         
+                           errormessage = sprintf(['Error in parsechord: \nIncorrect character sequence in chord "' chord '"\n']); 
+                           success = 0;
+                           index = ilength +1;
+                       
+                       else
+
+                           % copy remaining characters into bass
+                           bass(tempindex) = chord(index);
+                           index = index +1;
+                           tempindex = tempindex +1;
+                       end
+                   end
+                            
+           otherwise
+                errormessage = sprintf(['Error in parsechord: \nUnrecognised chord "' chord '"\n']); 
+                success = 0;
+                index = ilength + 1;
+       end
+            
+    end
+end            
+            
+if (verbose == 1) && (success == 0)
+    fprintf(1,errormessage);
+end
+        
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/parsedegree.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,123 @@
+%
+% PARSEDEGREE
+% 
+% [interval, accidentals, success, errormessage] = parsedegree(degree, {verbose})
+% 
+% Parse a degree to an interval value and a number of accidentals
+% if accidentals is positive it denotes number of sharps,
+% if it is negative it denotes number of flats.
+% If the omit degree character '*' is found then present is returned as 0 
+% otherwise it is 1. 
+%
+% Success = 1 if symbols parsed correctly, 0 otherwise.
+%
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% returns:  interval    (integer)
+%           accidentals (integer) 
+%           present     (boolean)
+%           success     (boolean)
+%           errormessage (string)  
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [interval,accidentals,present,success, errormessage] = parsedegree(degree, verbose)
+
+if nargin < 2
+    verbose = 0;
+end
+
+ilength = length(degree);
+
+errormessage = '';
+accidentals = 0;
+interval = 0;
+success=1;
+present = 1;
+
+index = 1;
+ 
+% if the input string is not empty   
+if (isempty(degree) == 0)
+
+    
+    % check for omit degree '*'
+    if degree(index) == '*' 
+        present = 0;
+        index = index +1;
+    end
+
+
+    tempstring = '';
+    tempindex = 1;
+    % parse the degree string
+    while index <= ilength
+
+        switch degree(index)
+
+            case 'b' % FLAT
+                accidentals = accidentals - 1; %decrement accidental count
+                index = index + 1;
+
+            case '#' % SHARP
+                accidentals = accidentals + 1; %increment accidental count
+                index = index + 1;
+             
+            case {'1','2','3','4','5','6','7','8','9'}
+                % if neither of the above then remaining string should be
+                % an integer interval value
+                tempstring(tempindex) = degree(index);
+                
+                tempindex = tempindex+1;
+                index = index+1;
+                
+            otherwise
+                % unrecognised symbol
+                success=0;
+                index = ilength+1;
+        end
+    end
+else
+    success=0;
+end
+
+if success
+
+% convert the interval string to an integer
+    [interval, success] = str2num(tempstring); 
+
+    % check it worked and that the interval is valid
+    if isempty(interval) || (interval <= 0) 
+        success = 0; 
+    end
+end            
+
+if(success==0) % correct degree therefore return success = 1 
+    % if not an integer then the degree string is incorrect
+    errormessage = sprintf(['Error in parsedegree: Unrecognised degree "' degree '"\n']);
+    interval = 0;
+    if verbose == 1
+        fprintf(1, errormessage);
+    end
+    
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/parsedegreelist.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,121 @@
+%
+% PARSEDEGREELIST
+% 
+% [pardegrees, success, errormessage] = parsedegreelist(degreelist, {verbose})
+% 
+% Parses a comma delimited list of degrees to an array of intervals, their 
+% associated accidentals and whether or not they are present (presence 
+% denoted by a '*' in front of a degree in the input degreelist). 
+%
+% Success = 1 if symbols parsed correctly, 0 otherwise.
+%
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls parsedegree
+% 
+% returns:  degrees       (array of int: [interval,accidental,present])
+%           success       (boolean)
+%           errormessage  (string) 
+% 
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [pardegrees, success, errormessage] = parsedegreelist(degreelist, verbose)
+
+% set verbose default to 0
+if nargin < 2
+    verbose = 0;
+end
+
+errormessage = '';
+
+ilength = length(degreelist);
+
+index = 1;
+
+tempindex = 1;
+
+tempstring = '';
+
+success = 1;
+
+parindex  = 1;
+
+pardegrees = [];
+
+
+while index <= ilength
+    
+   
+    while (degreelist(index) ~= ',')  
+        
+        tempstring(tempindex) = degreelist(index);
+        tempindex = tempindex +1;
+        index = index + 1;
+        
+        if(index > ilength)
+            break;
+        end
+        
+        if (degreelist(index) == ',') && (index == ilength)
+            success = 0;
+            errormessage = sprintf(['Error in parsedegreelist: degree list finishes with a comma "' degreelist '"\n']);
+        end
+            
+            
+    end
+    
+        [pardegrees(parindex,1),pardegrees(parindex,2),pardegrees(parindex,3),ok, error] = parsedegree(tempstring);
+        % concatenate error messages if there are any...
+        errormessage = [errormessage error];
+        
+        if(ok == 1)
+            tempstring = '';
+            tempindex = 1;
+            parindex = parindex + 1;
+            index = index + 1;
+        else
+
+            errormessage = [errormessage sprintf(['Error in parsedegreelist: incorrect degree in list "' degreelist '"\n'])];
+            success = 0;
+            index = ilength +1;            
+        end
+    
+    
+end
+
+if (success == 0) && (verbose == 1)
+
+    fprintf(1,errormessage)
+    
+end    
+
+
+    
+              
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/parsenote.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,102 @@
+%
+% PARSENOTE
+% 
+% [natural, accidentals, success, errormessage] = parsenote(note, {verbose})
+% 
+% Parse a note to a natural character value and a number of accidentals
+% if accidentals is positive it denotes number of sharps,
+% if it is negative it denotes number of flats.
+%
+% Success = 1 if symbols parsed correctly, 0 otherwise.
+%
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% returns:  natural     (char)
+%           accidentals (integer) 
+%           success     (boolean)
+%           errormessage (string)
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [natural,accidentals,success, errormessage] = parsenote(note, verbose)
+
+if nargin < 2
+    verbose = 0;
+end
+
+errormessage = '';
+
+ilength = length(note);
+
+accidentals = 0;
+natural = [];
+success=1;
+
+index = 1;
+
+if (isempty(note))  % if we have been passed an empty string
+    success=0;
+
+else  % parse the note string
+  
+    switch(note(index))
+
+        case {'A','B','C','D','E','F','G'}
+
+            %first character should be a natural
+            natural = note(index);
+            index= index+1;
+
+            %remaining characters should be sharps or flats
+            while index <= ilength
+
+                switch note(index)
+
+                    case 'b' % FLAT
+                        accidentals = accidentals - 1; %decrement accidental count
+                        index = index + 1;
+
+                    case '#' % SHARP
+                        accidentals = accidentals + 1; %increment accidental count
+                        index = index + 1;
+
+                    otherwise
+                        % if neither of the above then the note is incorrect
+                        success=0;
+                        index = ilength+1;
+                end
+            end
+
+        otherwise
+            success=0;        
+    end
+end
+    
+if(success==0) % correct note therefore return success = 1 
+    % if not an integer then the note string is incorrect
+    errormessage = sprintf(['Error in parsenote: Unrecognised note "' note '"\n']); 
+    
+    if verbose ==1
+        fprintf(1,errormessage);
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/short2quality.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,115 @@
+%
+%SHORT2QUALITY return the quality of a given shorthand string
+% 
+% [quality,success, errormessage] = short2quality(shorthand, {verbose})
+% 
+% Returns the quality of a given shorthand string. Quality values are from 
+% the enumeration:
+%
+% 0   Major
+% 1   Minor
+% 2   Diminished
+% 3   Augmented
+% 4   Suspended
+% 
+%
+% Success = 1 if symbols parsed correctly, 0 otherwise. 
+%
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% calls:   
+% 
+% returns:  quality (integer)
+%           success  (boolean)  
+%           errormessage (string)
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [quality,success,errormessage] = short2quality(shorthand,verbose)
+
+if nargin < 2
+    verbose = 0;
+end
+
+success = 1;
+errormessage = '';
+quality = '';
+
+switch shorthand
+    
+        
+    % triads
+    case 'maj'
+        quality = 0;        
+    case 'min' 
+        quality = 1;        
+    case 'dim' 
+        quality = 2;    
+    case 'aug' 
+        quality = 3;
+        
+    % sevenths    
+    case 'maj7' 
+        quality = 0;
+    case 'min7' 
+        quality = 1;
+    case '7' 
+        quality = 0;        
+    case 'minmaj7' 
+        quality = 1;        
+    case 'dim7' 
+        quality = 2;
+    case 'hdim7'
+        quality = 2;
+ 
+    % sixths
+    case 'maj6'
+        quality = 0;        
+    case 'min6' 
+        quality = 1;
+
+    % ninths 
+ 
+    case '9'
+        quality = 0;          
+    case 'maj9'
+        quality = 0;    
+    case 'min9'
+        quality = 1;    
+
+    % suspended
+    case 'sus4'
+        quality = 4;
+    case 'sus2'
+        quality = 4;
+        
+    otherwise
+        success = 0;
+        errormessage = ['Error in short2quality: unrecognised shorthand: ' shorthand];
+end
+
+        
+if (success ==0) && (verbose == 1)
+    fprintf(1,errormessage);
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/shorthand2degrees.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,114 @@
+%
+% SHORTHAND2DEGREES
+% 
+% [degreelist, success, errormessage] = shorthand2degrees(shorthand, {verbose})
+% 
+% Converts a shorthand string to a degree-list
+% 
+% Success = 1 if shorthand is recognised, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% returns:  degreelist (string)
+%           success (boolean)
+%           errormessage (string)
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%
+function [degreelist, success, errormessage] = shorthand2degrees(shorthand, verbose)
+
+%set verbose to default to 0;;
+if nargin <2
+    verbose = 0;
+end
+
+degreelist = '';
+errormessage = '';
+
+success = 1;
+
+switch(shorthand)
+    
+    % Empty:
+    case ''
+        degreelist = ''; %empty degreelist
+        
+    % Triad chords:
+    case 'maj'
+        degreelist = '1,3,5'; % major
+    case 'min'
+        degreelist = '1,b3,5'; % minor
+    case 'dim'
+        degreelist = '1,b3,b5'; % diminished  
+    case 'aug'
+        degreelist = '1,3,#5'; % augmented
+    
+    % Seventh chords:
+    case 'maj7'
+        degreelist = '1,3,5,7'; %major seventh
+    case 'min7'
+        degreelist = '1,b3,5,b7'; % minor seventh
+    case '7'
+        degreelist = '1,3,5,b7'; % seventh
+    case 'dim7'
+        degreelist = '1,b3,b5,bb7'; % diminished seventh
+    case 'hdim7'
+        degreelist = '1,b3,b5,b7'; % half diminished seventh
+    case 'minmaj7'
+        degreelist = '1,b3,5,7'; % minor (major seventh)
+        
+    % Sixth Chords:    
+    case 'maj6'
+        degreelist = '1,3,5,6'; % major sixth
+    case 'min6'
+        degreelist = '1,b3,5,6'; % minor sixth
+        
+    % Ninth chords:
+    case 'maj9'
+        degreelist = '1,3,5,7,9'; % major ninth
+    case 'min9'
+        degreelist = '1,b3,5,b7,9'; % minor ninth
+    case '9'
+        degreelist = '1,3,5,b7,9'; % ninth
+
+    case 'sus2'
+        degreelist = '1,2,5'; % suspended second        
+    case 'sus4'
+        degreelist = '1,4,5'; % suspended fourth
+    case 'fullsus'
+        degreelist = '1,2,4,5'; % fully suspended chord
+            
+        
+    otherwise
+        errormessage = sprintf(['Error in shorthand2degrees: Unrecognised shorthand string "' shorthand '"\n']);
+        if verbose == 1
+            fprintf(1,errormessage);
+        end
+        success = 0;
+        
+end
+
+
+   
+    
+        
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/syntaxcheck.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+%
+%SYNTAXCHECK Checks symbol for correct syntax. 
+% 
+% [success, errormessage] = syntaxcheck(chordsymbol, {verbose})
+% 
+% Checks symbol for correct syntax and checks for valid note, shorthand 
+% and interval values. 
+%
+% calls getchordinfo
+% 
+% Success = 1 if symbol has correct syntax, 0 otherwise.
+% 
+% If optional argument 'verbose' is 1, function prints any errormessage to 
+% the screen.
+% 
+% Returns:  chordinfo (struct)
+%           success (boolean) true or false for correct syntax 
+%           errormessage (string)  
+%     
+% See also: getchordinfo
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+%		
+function [success, errormessage] = syntaxcheck(chordsymbol, verbose)
+
+if nargin < 2
+    verbose = 0;
+end
+    
+errormessage = '';
+chordinfo = [];
+
+success = 0;
+
+[root,short,degrees,bass, success, errormessage] = getchordinfo(chordsymbol,verbose);
+
+if (success ==0) && (verbose == 1)
+    fprintf(1,errormessage);
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/01_-_I_Saw_Her_Standing_There.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,61 @@
+0.0000000 2.6122670 N
+2.6122670 11.4590700 E
+11.4590700 12.9219270 A
+12.9219270 17.4434738 E
+17.4434738 20.4103620 B
+20.4103620 21.9080490 E
+21.9080490 23.3709070 E:7/3
+23.3709070 24.8569840 A
+24.8569840 26.3430610 A:min/b3
+26.3430610 27.8407480 E
+27.8407480 29.3500450 B
+29.3500450 35.3059630 E
+35.3059630 36.8036500 A
+36.8036500 41.2631021 E
+41.2631021 44.2456460 B
+44.2456460 45.7201130 E
+45.7201130 47.2061900 E:7/3
+47.2061900 48.6922670 A
+48.6922670 50.1551240 A:min/b3
+50.1551240 51.6528110 E
+51.6528110 53.1388880 B
+53.1388880 56.1110430 E
+56.1110430 65.1319950 A
+65.1319950 68.1505890 B
+68.1505890 71.1924030 A
+71.1924030 74.1993870 E
+74.1993870 75.6970740 A
+75.6970740 80.2365750 E
+80.2365750 83.2087300 B
+83.2087300 86.2216932 E
+86.2216932 87.7366210 A
+87.7366210 89.2575280 A:min/b3
+89.2575280 90.7203850 E
+90.7203850 92.1574527 B
+92.1574527 104.1066890 E
+104.1066890 107.1252830 B
+107.1252830 110.1787070 E
+110.1787070 113.1240869 A
+113.1240869 114.6137180 E
+114.6137180 116.0997950 B
+116.0997950 118.9449608 E
+118.9449608 128.0464620 A
+128.0464620 131.0534460 B
+131.0534460 134.0372100 A
+134.0372100 137.0441950 E
+137.0441950 138.4755242 A
+138.4755242 143.0581630 E
+143.0581630 146.0419270 B
+146.0419270 147.5512240 E
+147.5512240 149.0605210 E:7/3
+149.0605210 150.5117680 A
+150.5117680 152.0210650 A:min/b3
+152.0210650 153.5303620 E
+153.5303620 155.0628790 B
+155.0628790 159.5327210 E
+159.5327210 161.0652380 B
+161.0652380 165.5815190 E
+165.5815190 167.1140360 B
+167.1140360 168.6465530 A
+168.6465530 169.7374090 E
+169.7374090 171.6871730 E:9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/02_-_Misery.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+0.0000000 0.4141790 N
+0.4141790 4.3656554 F
+4.3656554 6.6905920 G
+6.6905920 8.7806060 C
+8.7806060 9.7172890 A:min
+9.7172890 10.6347610 G
+10.6347610 12.3762580 C
+12.3762580 14.1990240 F
+14.1990240 15.9869610 C
+15.9869610 19.5976640 F
+19.5976640 21.3391600 G
+21.3391600 23.1154870 C
+23.1154870 24.9382530 A:min
+24.9382530 26.7261900 C
+26.7261900 28.5257360 F
+28.5257360 30.2672330 C
+30.2672330 33.9127660 F
+33.9127660 35.6895300 G
+35.6895300 39.2514740 C
+39.2514740 42.8524480 A:min
+42.8524480 46.4283210 C
+46.4283210 50.0622440 A:min
+50.0622440 53.6845570 G
+53.6845570 55.4841040 C
+55.4841040 57.2372100 F
+57.2372100 59.0599770 C
+59.0599770 62.6126300 F
+62.6126300 64.4121760 G
+64.4121760 68.0273920 C
+68.0273920 71.5987520 A:min
+71.5987520 75.2326750 C
+75.2326750 78.8898180 A:min
+78.8898180 82.5353510 G
+82.5353510 84.3142050 C
+84.3142050 86.1228340 F
+86.1228340 87.8875510 C
+87.8875510 91.5209280 F
+91.5209280 93.3560620 G
+93.3560620 95.1553960 C
+95.1553960 97.0129930 A:min
+97.0129930 98.8125390 C
+98.8125390 100.6353060 A:min
+100.6353060 102.4696820 C
+102.4696820 104.2692290 A:min
+104.2692290 106.1616550 C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/03_-_Anna_(Go_To_Him).lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,73 @@
+0.0000000 0.7084620 N
+0.7084620 2.9678800 D
+2.9678800 5.1890030 B:min
+5.1890030 7.4292730 D
+7.4292730 9.6695440 B:min
+9.6695440 11.8523710 D
+11.8523710 14.0351990 B:min
+14.0351990 16.2754690 D
+16.2754690 18.5348880 B:min
+18.5348880 20.6411250 D
+20.6411250 22.8622478 B:min
+22.8622478 23.6472998 D
+23.6472998 25.0067802 B:min
+25.0067802 25.8875700 E:min
+25.8875700 27.2661980 A
+27.2661980 29.4107310 D
+29.4107310 31.6127060 B:min
+31.6127060 33.8338290 D
+33.8338290 36.0358040 B:min
+36.0358040 38.2760750 D
+38.2760750 40.4206070 B:min
+40.4206070 42.6417300 D
+42.6417300 44.8820010 B:min
+44.8820010 47.0265330 D
+47.0265330 49.0561800 B:min
+49.0561800 49.9369700 D
+49.9369700 51.3155980 B:min
+51.3155980 52.1963880 E:min
+52.1963880 53.5941640 A
+53.5941640 56.7535200 D
+56.7535200 57.2513570 D/2
+57.2513570 57.7109000 D/3
+57.7109000 66.4805060 G
+66.4805060 73.9097790 D
+73.9097790 74.3884690 D/2
+74.3884690 74.9437500 D/3
+74.9437500 83.5027320 G
+83.5027320 87.7535020 E:7
+87.7535020 91.9659770 A
+91.9659770 94.1679520 D
+94.1679520 96.2550420 B:min
+96.2550420 98.5144600 D
+98.5144600 100.5632540 B:min
+100.5632540 101.5589300 D
+101.5589300 102.9950010 B:min
+102.9950010 103.7992000 E:min
+103.7992000 105.1969760 A
+105.1969760 108.3563320 D
+108.3563320 108.9882030 D/2
+108.9882030 109.5626310 D/3
+109.5626310 118.2556470 G
+118.2556470 125.7806580 D
+125.7806580 126.3359387 D/2
+126.3359387 126.8720718 D/3
+126.8720718 131.1611370 G
+131.1611370 135.5459400 G:min
+135.5459400 139.7967090 E:7
+139.7967090 144.2006600 A
+144.2006600 146.2111590 D
+146.2111590 148.4514300 B:min
+148.4514300 150.6151100 D
+150.6151100 152.8362330 B:min
+152.8362330 153.6595800 D
+153.6595800 155.0382080 B:min
+155.0382080 155.8615550 E:min
+155.8615550 157.2401830 A
+157.2401830 159.4804540 D
+159.4804540 161.6249860 B:min
+161.6249860 163.9418470 D
+163.9418470 165.9906420 B:min
+165.9906420 168.1734690 D
+168.1734690 170.5286250 B:min
+170.5286250 174.5304760 D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/04_-_Chains.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,42 @@
+0.000000 0.459543 N
+0.459543 7.639897 Bb
+7.639897 14.977403 Bb
+14.977403 18.646156 Eb:7
+18.646156 22.338129 Bb
+22.338129 24.184115 F:9
+24.184115 26.041712 Eb:9
+26.041712 27.910918 Bb
+27.910918 29.780124 F
+29.780124 37.106020 Bb
+37.106020 40.797993 Eb:7
+40.797993 44.466746 Bb
+44.466746 46.324342 F:9
+46.324342 48.170328 Eb:9
+48.170328 49.981485 Bb
+49.981485 51.839081 Bb:7
+51.839081 55.589104 Eb
+55.589104 59.292687 Bb
+59.292687 63.042709 Eb
+63.042709 66.734682 F
+66.734682 74.118628 Bb
+74.118628 77.857040 Eb:7
+77.857040 81.525793 Bb
+81.525793 83.395000 F:9
+83.395000 85.252596 Eb:9
+85.252596 87.110192 Bb
+87.110192 88.944569 Bb:7
+88.944569 92.659761 Eb
+92.659761 96.363344 Bb
+96.363344 100.113367 Eb
+100.113367 103.793730 F
+103.793730 111.224115 Bb
+111.224115 114.927698 Eb:7
+114.927698 118.642891 Bb
+118.642891 120.512097 F:9
+120.512097 122.369693 Eb:9
+122.369693 124.536063 Bb
+124.536063 126.050056 F
+126.050056 137.230929 Bb
+137.230929 139.011657 Eb
+139.011657 139.773049 Eb:min
+139.773049 141.769966 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/05_-_Boys.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,51 @@
+0.0000000 1.0731190 N
+1.0731190 2.5127560 B
+2.5127560 4.1033230 A
+4.1033230 5.6822800 E
+5.6822800 7.2844570 B
+7.2844570 13.8905340 E
+13.8905340 17.1064980 A
+17.1064980 20.4385610 E
+20.4385610 22.0987880 B
+22.0987880 23.7590150 A
+23.7590150 25.5054710 E
+25.5054710 27.0678580 B
+27.0678580 33.6855460 E
+33.6855460 36.9479490 A
+36.9479490 40.2567930 E
+40.2567930 41.9054090 B
+41.9054090 43.6004660 A
+43.6004660 45.3032481 E
+45.3032481 46.8860900 B
+46.8860900 53.6547070 E
+53.6547070 57.0099900 A
+57.0099900 60.3768830 E
+60.3768830 62.0138900 B
+62.0138900 63.7205570 A
+63.7205570 65.5622730 E
+65.5622730 67.0526200 B
+67.0526200 73.6006480 E
+73.6006480 76.9094910 A
+76.9094910 80.2647750 E
+80.2647750 82.0062710 B
+82.0062710 83.6664980 A
+83.6664980 85.4544340 E
+85.4544340 87.0566110 B
+87.0566110 93.9297180 E
+93.9297180 97.3082210 A
+97.3082210 100.7099450 E
+100.7099450 102.4398310 B
+102.4398310 104.1464980 A
+104.1464980 105.8996040 E
+105.8996040 107.5830510 B
+107.5830510 114.3981080 E
+114.3981080 117.8230510 A
+117.8230510 121.2015550 E
+121.2015550 122.9082210 B
+122.9082210 124.6148880 A
+124.6148880 126.6814480 E
+126.6814480 128.0862710 B
+128.0862710 134.9245480 E
+134.9245480 138.3378810 A
+138.3378810 141.7163850 E
+141.7163850 143.4930510 B
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/06_-_Ask_Me_Why.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,96 @@
+0.0000000 0.4786900 N
+0.4786900 3.0253230 E
+3.0253230 3.5139090 E:maj7
+3.5139090 3.9666980 F#:min7
+3.9666980 5.7081940 G#:min7
+5.7081940 7.0201220 F#:min7
+7.0201220 7.4845210 B:7
+7.4845210 10.0619360 E
+10.0619360 10.1484390 E:maj7
+10.5031150 11.0023440 F#:min7
+11.0023440 12.7438410 G#:min7
+12.7438410 14.0325480 F#:min7
+14.0325480 14.5085570 B:7
+14.5085570 16.2152240 E
+16.2152240 17.9799400 G#
+17.9799400 21.4629340 C#:min
+21.4629340 23.2392600 A
+23.2392600 25.0504170 F#:9
+25.0504170 25.9792150 B
+25.9792150 26.4436140 E:maj7
+26.4436140 26.9312330 F#:min7
+26.9312330 28.7075590 G#:min7
+28.7075590 29.9993710 F#:min7
+29.9993710 30.4838860 B:7
+30.4838860 33.1018750 E
+33.1018750 33.5605300 E:maj7
+33.5605300 34.0249290 F#:min7
+34.0249290 35.7896460 G#:min7
+35.7896460 37.5311420 F#:min7
+37.5311420 39.3074690 E
+39.3074690 41.0837950 G#
+41.0837950 44.6364480 C#:min
+44.6364480 46.4165250 A
+46.4165250 48.2007110 E
+48.2007110 50.0466980 E:aug
+50.0466980 51.7765840 A
+51.7765840 53.5645210 B
+53.5645210 55.3524570 E
+55.3524570 57.1520040 E:aug
+57.1520040 58.9167200 A
+58.9167200 60.6930470 B
+60.6930470 62.8591610 E
+62.8591610 63.3285120 B
+63.3285120 63.7696910 E:maj7
+63.7696910 64.2224800 F#:min7
+64.2224800 65.9175370 G#:min7
+65.9175370 67.7054730 A
+67.7054730 69.4818000 G#:min7
+69.4818000 71.3045660 A:maj7
+71.3045660 74.0205320 E
+74.0205320 74.4624800 E:maj7
+74.4624800 74.9733190 F#:min7
+74.9733190 76.7496460 G#:min7
+76.7496460 78.0964030 F#:min7
+78.0964030 78.5724120 B:7
+78.5724120 81.2659270 E
+81.2659270 81.7187160 E:maj7
+81.7187160 82.2179450 F#:min7
+82.2179450 83.9710510 G#:min7
+83.9710510 85.3410290 F#:min7
+85.3410290 85.7822080 B:7
+85.7822080 87.5817540 E
+87.5817540 89.3348610 G#
+89.3348610 91.1576270 C#:min
+91.1576270 92.9107340 C#:min
+92.9107340 94.7218900 A:min
+94.7218900 96.4982170 F#:9
+96.4982170 97.4453960 B
+97.4453960 97.9494640 E:maj7
+97.9494640 98.4254730 F#:min7
+98.4254730 100.2018000 G#:min7
+100.2018000 101.9665160 A
+101.9665160 103.8008930 G#:min7
+103.8008930 105.5656090 A
+105.5656090 107.3535460 E
+107.3535460 109.1414820 E:aug
+109.1414820 110.9178090 A
+110.9178090 112.6941350 B
+112.6941350 114.4820720 E
+114.4820720 116.2467880 E:aug
+116.2467880 118.0231150 A
+118.0231150 119.5961310 B
+119.5961310 121.9405290 E
+121.9405290 122.4232960 B
+122.4232960 122.8644760 E:maj7
+122.8644760 123.2940450 F#:min7
+123.2940450 125.0471510 G#:min7
+125.0471510 126.8234780 A
+126.8234780 128.6114140 G#:min7
+128.6114140 130.3943760 A:maj7
+130.3943760 132.2105070 E
+132.2105070 133.9984440 A:maj7/5
+133.9984440 135.7747700 E
+135.7747700 137.5859270 A:maj7/5
+137.5859270 139.2432030 B:maj6
+139.2432030 143.9829630 G#:min
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/07_-_Please_Please_Me.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,78 @@
+0.0000000 0.4443630 N
+0.4443630 0.8665460 B
+0.8665460 7.6467720 E
+7.6467720 11.0136660 E
+11.0136660 11.8728040 A
+11.8728040 12.9177020 E
+12.9177020 13.3937110 G
+13.3937110 13.8465000 A
+13.8465000 14.4502190 B
+14.4502190 17.8867720 E
+17.8867720 18.7459110 A
+18.7459110 21.3813760 E
+21.3813760 23.0880420 A
+23.0880420 24.8063190 F#:min
+24.8063190 26.5129860 C#:min/5
+26.5129860 28.2080420 A
+28.2080420 29.9030990 E
+29.9030990 30.7738470 A
+30.7738470 31.6445960 B
+31.6445960 33.3860920 E
+33.3860920 34.2568400 A
+34.2568400 35.1508090 B
+35.1508090 38.5293120 E
+38.5293120 39.3768400 A
+39.3768400 40.4797880 E
+40.4797880 40.9321490 G
+40.9321490 41.4341470 A
+41.4341470 42.0123050 B
+42.0123050 45.4488590 E
+45.4488590 46.3196070 A
+46.3196070 48.8970220 E
+48.8970220 50.6152980 A
+50.6152980 52.2871350 F#:min
+52.2871350 54.0170220 C#:min/5
+54.0170220 55.7352980 A
+55.7352980 57.4651850 E
+57.4651850 58.3591530 A
+58.3591530 59.2299020 B
+59.2299020 60.9713980 E
+60.9713980 62.6316250 E
+62.6316250 64.4079520 A
+64.4079520 66.1378380 B
+66.1378380 69.6092210 E
+69.6092210 71.3274980 A
+71.3274980 73.0806050 B
+73.0806050 74.8221010 E
+74.8221010 75.7276790 A
+75.7276790 76.6332580 B
+76.6332580 78.3863640 E
+78.3863640 79.2571130 A
+79.2571130 80.1394710 B
+80.1394710 83.6340740 E
+83.6340740 84.4583820 A
+84.4583820 85.3407410 E
+85.3407410 85.9060250 G
+85.9060250 86.4981260 A
+86.4981260 87.1054570 B
+87.1054570 90.5536200 E
+90.5536200 91.4243690 A
+91.4243690 94.0598340 E
+94.0598340 95.8013300 A
+95.8013300 97.5312170 F#:min
+97.5312170 99.2262740 C#:min/5
+99.2262740 100.9445500 A
+100.9445500 102.6976570 E
+102.6976570 103.6148450 A
+103.6148450 104.4739830 B
+104.4739830 106.2154800 E
+106.2154800 107.0978380 A
+107.0978380 107.9801960 B
+107.9801960 109.7216930 E
+109.7216930 110.5692210 A
+110.5692210 111.4748000 B
+111.4748000 112.3919880 E
+112.3919880 113.2627360 G
+113.2627360 114.1218740 C
+114.1218740 114.9926230 B
+114.9926230 119.3983060 E
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/08_-_Love_Me_Do.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,72 @@
+0.0000000 0.4659520 N
+0.4659520 2.1032320 G
+2.1032320 3.7054090 C
+3.7054090 5.2727560 G
+5.2727560 6.8865430 C
+6.8865430 8.5003300 G
+8.5003300 10.0908970 C
+10.0908970 13.3533000 G
+13.3533000 14.9903070 G
+14.9903070 16.6157040 C
+16.6157040 18.2411010 G
+18.2411010 19.8664970 C
+19.8664970 21.4802840 G
+21.4802840 23.1172910 C
+23.1172910 26.3913050 C
+26.3913050 28.2101550 C
+28.2101550 29.7117580 G
+29.7117580 31.3603750 C
+31.3603750 32.9393320 G
+32.9393320 34.5995590 C
+34.5995590 36.3062250 G
+36.3062250 37.9432320 C
+37.9432320 39.5570190 G
+39.5570190 41.2056360 C
+41.2056360 42.8310330 G
+42.8310330 44.4448190 C
+44.4448190 49.4022800 C
+49.4022800 51.0276770 G
+51.0276770 52.7111230 C
+52.7111230 54.3249100 G
+54.3249100 55.9851370 G
+55.9851370 59.2243210 D
+59.2243210 60.8613270 C
+60.8613270 62.4867240 G
+62.4867240 65.7375180 D
+65.7375180 67.3513050 C
+67.3513050 69.1522410 G
+69.1522410 70.7530280 G
+70.7530280 72.3319850 C
+72.3319850 73.9689920 G
+73.9689920 75.5827790 C
+75.5827790 77.1849560 G
+77.1849560 78.7987420 C
+78.7987420 83.8790750 C
+83.8790750 85.4164290 G
+85.4164290 87.0534360 C
+87.0534360 88.6672230 G
+88.6672230 90.2694000 G
+90.2694000 93.4737540 D
+93.4737540 95.1223700 C
+95.1223700 96.7477670 G
+96.7477670 99.9521210 D
+99.9521210 101.5426880 C
+101.5426880 103.1680850 G
+103.1680850 108.9051370 G
+108.9051370 109.6348420 D
+109.6348420 111.2834590 G
+111.2834590 112.8740260 C
+112.8740260 114.4762030 G
+114.4762030 116.0783800 C
+116.0783800 117.7037760 G
+117.7037760 119.2943430 C
+119.2943430 124.3115080 G
+124.3115080 125.8307610 G
+125.8307610 127.4329370 C
+127.4329370 129.0235040 G
+129.0235040 130.6140710 C
+130.6140710 132.2162480 G
+132.2162480 133.8532550 C
+133.8532550 135.4089920 G
+135.4089920 137.0459990 C
+137.0459990 138.6597850 G
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/09_-_P._S._I_Love_You.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,77 @@
+0.000000 0.465069 N
+0.465069 1.397949 G
+1.397949 2.338358 C#:7
+2.338358 4.114683 D
+4.114683 4.973822 G
+4.973822 5.844570 C#:7
+5.844570 7.644118 D
+7.644118 8.549696 G
+8.549696 9.408834 C#:7
+9.408834 11.219991 D
+11.219991 12.113959 D
+12.113959 12.996317 A
+12.996317 14.772644 D
+14.772644 16.560579 D
+16.560579 18.302076 E:min
+18.302076 20.066792 D
+20.066792 21.866339 A
+21.866339 23.689106 B:min
+23.689106 25.453822 A
+25.453822 28.147337 Bb
+28.147337 28.611736 Bb
+28.611736 29.052915 C
+29.052915 32.582349 D
+32.582349 34.405114 D
+34.405114 36.146611 E:min
+36.146611 37.934548 D
+37.934548 39.757314 A
+39.757314 41.545251 B:min
+41.545251 43.309967 A
+43.309967 46.003482 Bb
+46.003482 46.491101 Bb
+46.491101 46.932280 C
+46.932280 50.461714 D
+50.461714 52.238039 G
+52.238039 54.037586 D
+54.037586 55.860352 G
+55.860352 57.636679 D
+57.636679 59.436225 G
+59.436225 61.200942 D
+61.200942 62.118130 D
+62.118130 63.046928 A
+63.046928 64.788426 D
+64.788426 66.646022 D
+66.646022 68.375908 E:min
+68.375908 70.163844 D
+70.163844 71.998221 A
+71.998221 73.751328 B:min
+73.751328 75.527654 A
+75.527654 78.221170 Bb
+78.221170 78.662348 Bb
+78.662348 79.126747 C
+79.126747 82.656181 D
+82.656181 84.455727 G
+84.455727 86.255274 D
+86.255274 88.031600 G
+88.031600 89.796317 D
+89.796317 91.572643 G
+91.572643 93.348969 D
+93.348969 94.225395 D
+94.225395 95.148516 A
+95.148516 96.971283 D
+96.971283 98.782439 D
+98.782439 100.570375 E:min
+100.570375 102.311872 D
+102.311872 104.157859 A
+104.157859 105.945796 B:min
+105.945796 107.687292 A
+107.687292 110.427246 Bb
+110.427246 110.868426 Bb
+110.868426 111.332825 C
+111.332825 113.985730 D
+113.985730 114.479129 Bb
+114.479129 114.908698 C
+114.908698 117.590603 D
+117.590603 118.066611 Bb
+118.066611 118.542620 C
+118.542620 121.759660 D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/10_-_Baby_It's_You.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,55 @@
+0.0000000 0.4569370 N
+0.4569370 2.6513070 G
+2.6513070 4.7527130 E:min
+4.7527130 6.9005590 G
+6.9005590 9.0019650 E:min
+9.0019650 11.1101060 G
+11.1101060 13.3360430 E:min
+13.3360430 17.5817380 C
+17.5817380 21.8542100 G
+21.8542100 26.1150710 C
+26.1150710 30.2714430 G
+30.2714430 34.5787450 E:min
+34.5787450 38.7931670 A:min
+38.7931670 40.9410120 G
+40.9410120 43.1004680 E:min
+43.1004680 45.2018740 C
+45.2018740 49.4859560 D
+49.4859560 51.6570210 G
+51.6570210 53.7468170 E:min
+53.7468170 55.9294930 G
+55.9294930 58.0773390 E:min
+58.0773390 62.3498110 C
+62.3498110 66.6455020 G
+66.6455020 70.8831440 C
+70.8831440 75.1323960 G
+75.1323960 79.4164770 E:min
+79.4164770 83.5960690 A:min
+83.5960690 85.7439150 G
+85.7439150 87.8685410 E:min
+87.8685410 89.9467270 C
+89.9467270 94.3120780 D
+94.3120780 96.5411940 G
+96.5411940 98.6309900 E:min
+98.6309900 100.7788360 G
+100.7788360 102.9266810 E:min
+102.9266810 105.0977470 C
+105.0977470 107.1178830 D
+107.1178830 109.2657290 G
+109.2657290 111.3090850 G
+111.3090850 113.4569310 C
+113.4569310 115.5467270 D
+115.5467270 119.8191980 G
+119.8191980 124.1265000 E:min
+124.1265000 128.4105820 A:min
+128.4105820 130.6048670 G
+130.6048670 132.7527130 E:min
+132.7527130 134.8541190 C
+134.8541190 137.0484050 D
+137.0484050 139.2659100 D
+139.2659100 141.3789260 G
+141.3789260 143.5499920 E:min
+143.5499920 145.7326680 G
+145.7326680 147.9037340 E:min
+147.9037340 150.0515790 G
+150.0515790 152.2110350 E:min
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/11_-_Do_You_Want_To_Know_A_Secret.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,113 @@
+0.0000000 0.4978379 N
+0.4978379 3.5040128 E:min
+3.5040128 4.5864640 A:min
+4.5864640 6.9897300 E:min
+6.9897300 9.9851040 G
+9.9851040 11.2779430 F
+11.2779430 14.9541740 B
+14.9541740 15.9526330 E
+15.9526330 16.4634720 G#:min
+16.4634720 16.9394800 G:min
+16.9394800 17.8566690 F#:min
+17.8566690 18.8319080 B
+18.8319080 19.7955360 E
+19.7955360 20.3063750 G#:min
+20.3063750 20.8056040 G:min
+20.8056040 21.7692320 F#:min
+21.7692320 22.7328600 B
+22.7328600 23.6848770 E
+23.6848770 24.1608870 G#:min
+24.1608870 24.6368950 G:min
+24.6368950 25.6237440 F#:min
+25.6237440 26.5409330 C:min6
+26.5409330 27.4929500 E
+27.4929500 27.9921790 G#:min
+27.9921790 28.4797980 G:min
+28.4797980 29.4550360 F#:min
+29.4550360 30.4534940 B:7
+30.4534940 31.3939020 E
+31.3939020 31.8699120 G#:min
+31.8699120 32.3575300 G:min
+32.3575300 33.3443780 F#:min
+33.3443780 34.3080060 B
+34.3080060 36.2468730 A
+36.2468730 38.1392990 B
+38.1392990 40.0085060 C#:min
+40.0085060 41.0417940 F#:min
+41.0417940 41.9822020 B
+41.9822020 42.9342200 E
+42.9342200 43.4450600 G#:min
+43.4450600 43.9326780 G
+43.9326780 44.8730870 F#:min
+44.8730870 45.8367150 B
+45.8367150 46.7539020 E
+46.7539020 47.2415210 G#:min
+47.2415210 47.7291410 G:min
+47.7291410 48.7043780 F#:min
+48.7043780 49.6563970 B
+49.6563970 50.6664640 E
+50.6664640 51.1192550 G#:min
+51.1192550 51.6068730 G:min
+51.6068730 52.5937220 F#:min
+52.5937220 53.5225200 C:min6
+53.5225200 54.4977570 E
+54.4977570 54.9853770 G#:min
+54.9853770 55.4613850 G:min
+55.4613850 56.4482340 F#:min
+56.4482340 57.4118620 B
+57.4118620 58.3522690 E
+58.3522690 58.8282790 G#:min
+58.8282790 59.3275080 G:min
+59.3275080 60.3027470 F#:min
+60.3027470 61.2895940 B
+61.2895940 63.2400710 A
+63.2400710 65.1441060 B
+65.1441060 67.0713620 C#:min
+67.0713620 68.0466010 F#:min
+68.0466010 69.0218400 B
+69.0218400 69.9845189 A
+69.9845189 70.9723150 F#:min
+70.9723150 71.9127240 C#:min
+71.9127240 72.8415220 B:min
+72.8415220 73.8167590 A
+73.8167590 74.7803870 F#:min
+74.7803870 75.7207960 C#:min
+75.7207960 76.6728140 B:min
+76.6728140 78.6232900 F#:min
+78.6232900 80.4692760 B
+80.4692760 81.4329040 E
+81.4329040 81.9205230 G#:min
+81.9205230 82.4081430 G:min
+82.4081430 83.3601610 F#:min
+83.3601610 84.3121800 B:7
+84.3121800 85.2641970 E
+85.2641970 85.7169860 G#:min
+85.7169860 86.2394360 G:min
+86.2394360 87.2146730 F#:min
+87.2146730 88.1666920 B
+88.1666920 89.1070990 E
+89.1070990 89.5831080 G#:min
+89.5831080 90.0591190 G:min
+90.0591190 91.0343560 F#:min
+91.0343560 92.0095940 C:min6
+92.0095940 92.9383920 E
+92.9383920 93.4144020 G#:min
+93.4144020 93.8904100 G:min
+93.8904100 94.8888680 F#:min
+94.8888680 95.8408870 B
+95.8408870 96.8277340 E
+96.8277340 97.2805230 G#:min
+97.2805230 97.7681430 G:min
+97.7681430 98.7549910 F#:min
+98.7549910 99.7534490 B
+99.7534490 101.7155350 A
+101.7155350 103.6195710 B
+103.6195710 105.5468270 C#:min
+105.5468270 106.5104550 F#:min
+106.5104550 107.4973030 B
+107.4973030 109.4245610 C#:min
+109.4245610 110.3881890 F#:min
+110.3881890 111.3402060 B
+111.3402060 113.3022920 C#:min
+113.3022920 114.2543100 F#:min
+114.2543100 115.2643780 B
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/12_-_A_Taste_Of_Honey.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+0.0000000 0.4403950 N
+0.4403950 4.3679580 F#:min
+4.3679580 6.1442840 A
+6.1442840 8.1760300 E
+8.1760300 15.0026970 F#:min
+15.0026970 16.8138540 F#:min
+16.8138540 18.5785700 F#:minmaj7
+18.5785700 20.3781170 F#:min7
+20.3781170 22.2124930 B
+22.2124930 24.0120400 F#:min
+24.0120400 25.8231960 F#:minmaj7
+25.8231960 27.6459620 F#:min7
+27.6459620 29.4803390 B
+29.4803390 33.0678220 F#:min
+33.0678220 34.8905880 A
+34.8905880 36.6320850 E
+36.6320850 37.8279130 F#:min
+37.8279130 38.4780710 B:min
+38.4780710 40.1963480 F#:min
+40.1963480 41.1483660 F#:min
+41.1483660 41.9726740 B:min
+41.9726740 43.7025610 F#:min
+43.7025610 45.9665070 A
+45.9665070 48.1491820 B
+48.1491820 50.3318580 F#:min
+50.3318580 52.5261440 B
+52.5261440 54.7088200 A
+54.7088200 56.8914950 E
+56.8914950 63.7878220 F#:min
+63.7878220 65.5873680 F#:min
+65.5873680 67.3869150 F#:minmaj7
+67.3869150 69.1864610 F#:min7
+69.1864610 70.9976180 B
+70.9976180 72.8319940 F#:min
+72.8319940 74.6315410 F#:minmaj7
+74.6315410 76.4426970 F#:min7
+76.4426970 78.2306340 B
+78.2306340 81.8297270 F#:min
+81.8297270 83.6524930 A
+83.6524930 85.4056000 E
+85.4056000 86.3808380 F#:min
+86.3808380 87.2051460 B:min
+87.2051460 88.9350330 F#:min
+88.9350330 89.9567110 F#:min
+89.9567110 90.7229690 B:min
+90.7229690 92.4296360 F#:min
+92.4296360 94.6819710 A
+94.6819710 96.9343070 B
+96.9343070 99.1634230 F#:min
+99.1634230 101.3460980 B
+101.3460980 106.1061890 A
+106.1061890 111.3771190 E
+111.3771190 112.4336270 F#:min
+112.4336270 112.9444660 B:min
+112.9444660 113.8899910 F#:min
+113.8899910 114.5218630 B:min
+114.5218630 115.4983910 F#:min
+115.4983910 116.1952590 B:min
+116.1952590 120.2469980 F#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/13_-_There's_A_Place.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,61 @@
+0.000000 0.492180 N
+0.492180 0.942239 B
+0.942239 2.521195 E:maj7
+2.521195 4.193032 A
+4.193032 5.795209 E:maj7
+5.795209 8.291354 A
+8.291354 9.162102 B
+9.162102 10.752669 E
+10.752669 12.447726 A
+12.447726 14.073123 E
+14.073123 15.791400 A
+15.791400 17.463236 E
+17.463236 19.123463 C#:min
+19.123463 22.478746 B
+22.478746 24.162193 G#:min
+24.162193 25.892080 A
+25.892080 27.529087 E:maj7
+27.529087 28.353395 A
+28.353395 29.200923 F#:min
+29.200923 33.438565 C#:min
+33.438565 34.355753 B
+34.355753 35.992760 E
+35.992760 37.722647 A
+37.722647 39.417703 E
+39.417703 41.112760 A
+41.112760 42.749767 E
+42.749767 44.479654 C#:min
+44.479654 47.881377 B
+47.881377 51.294710 A
+51.294710 54.626774 B
+54.626774 56.321830 C#:min
+56.321830 58.063327 F#
+58.063327 59.735164 E
+59.735164 61.511490 G#
+61.511490 63.194937 C#:min
+63.194937 64.936434 F#
+64.936434 66.631490 E
+66.631490 68.396207 G#
+68.396207 70.996842 C#:min
+70.996842 71.902420 B
+71.902420 73.609087 E
+73.609087 75.373803 A
+75.373803 77.080470 E
+77.080470 78.798746 A
+78.798746 80.493803 E
+80.493803 82.188860 C#:min
+82.188860 85.671853 B
+85.671853 87.343690 G#:min
+87.343690 89.085186 A
+89.085186 90.791853 E:maj7
+90.791853 91.767091 A
+91.767091 92.533350 F#:min
+92.533350 95.134376 C#:min
+95.134376 96.004733 B
+96.004733 97.676570 E
+97.676570 99.360016 A
+99.360016 101.008633 E
+101.008633 102.657250 A
+102.657250 104.282647 E
+104.282647 105.931263 A
+105.931263 107.626320 E
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/14_-_Twist_And_Shout.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,115 @@
+0.000000 0.431661 N
+0.431661 1.159256 N
+1.159256 2.088054 D
+2.088054 3.028463 G
+3.028463 4.874449 A
+4.874449 5.756807 D
+5.756807 6.708825 G
+6.708825 8.578032 A
+8.578032 9.506830 D
+9.506830 10.412408 G
+10.412408 12.339664 A
+12.339664 13.268463 D
+13.268463 14.208871 G
+14.208871 16.124518 A
+16.124518 17.041705 D
+17.041705 17.982113 G
+17.982113 19.874541 A
+19.874541 20.814948 D
+20.814948 21.778576 G
+21.778576 23.566513 A
+23.566513 24.472091 D
+24.472091 25.412500 G
+25.412500 27.281706 A
+27.281706 28.233723 D
+28.233723 29.185741 G
+29.185741 31.020119 A
+31.020119 31.948916 D
+31.948916 32.900934 G
+32.900934 34.828190 A
+34.828190 35.780209 D
+35.780209 36.709007 G
+36.709007 38.520163 A
+38.520163 39.460572 D
+39.460572 40.412591 G
+40.412591 42.293406 A
+42.293406 43.268645 D
+43.268645 44.243882 G
+44.243882 46.124699 A
+46.124699 47.041888 D
+47.041888 48.028735 G
+48.028735 49.955991 A
+49.955991 50.908009 D
+50.908009 51.860028 G
+51.860028 53.659574 A
+53.659574 54.588372 D
+54.588372 55.586830 G
+55.586830 57.467647 A
+57.467647 58.419664 D
+58.419664 59.383292 G
+59.383292 61.322159 A
+61.322159 62.239348 D
+62.239348 63.237806 G
+63.237806 65.176671 A
+65.176671 66.151910 D
+66.151910 67.115538 G
+67.115538 69.054405 A
+69.054405 70.041252 D
+70.041252 70.981661 G
+70.981661 71.980119 A
+71.980119 72.490957 G
+72.490957 72.955356 A
+72.955356 73.953814 D
+73.953814 74.894222 G
+74.894222 75.915900 A
+75.915900 76.403520 G
+76.403520 76.891138 A
+76.891138 77.866377 D
+77.866377 78.864835 G
+78.864835 79.851682 A
+79.851682 80.362521 G
+80.362521 80.861751 A
+80.861751 81.836990 D
+81.836990 82.800618 G
+82.800618 83.775855 A
+83.775855 84.275084 G
+84.275084 84.785923 A
+84.785923 90.776269 A
+90.776269 92.738363 A:7
+92.738363 96.558441 A
+96.558441 97.568508 D
+97.568508 98.520527 G
+98.520527 100.436172 A
+100.436172 101.399800 D
+101.399800 102.351820 G
+102.351820 104.221025 A
+104.221025 105.161434 D
+105.161434 106.090232 G
+106.090232 108.052318 A
+108.052318 109.027557 D
+109.027557 109.956355 G
+109.956355 111.813951 A
+111.813951 112.765968 D
+112.765968 113.717986 G
+113.717986 115.622023 A
+115.622023 116.597262 D
+116.597262 117.526060 G
+117.526060 119.499755 A
+119.499755 120.416944 D
+120.416944 121.380572 G
+121.380572 123.354269 A
+123.354269 124.329506 D
+124.329506 125.316355 G
+125.316355 127.243611 A
+127.243611 128.218849 D
+128.218849 129.170867 G
+129.170867 131.132953 A
+131.132953 132.108191 D
+132.108191 133.060210 G
+133.060210 134.964246 A
+134.964246 135.939484 D
+135.939484 136.891502 G
+136.891502 138.830368 A
+138.830368 146.701932 A
+146.701932 147.657368 D
+147.657368 152.003406 D:9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+/.DS_Store/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/01_-_I_Saw_Her_Standing_There.lab/1.2/Mon Jul 24 22:46:01 2006//
+/02_-_Misery.lab/1.2/Tue Oct 17 21:52:04 2006//
+/03_-_Anna_(Go_To_Him).lab/1.2/Tue Oct 17 21:52:04 2006//
+/04_-_Chains.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/05_-_Boys.lab/1.2/Thu Jul 27 22:01:34 2006//
+/06_-_Ask_Me_Why.lab/1.2/Thu Jul 27 21:43:13 2006//
+/07_-_Please_Please_Me.lab/1.2/Thu Jul 27 21:43:44 2006//
+/08_-_Love_Me_Do.lab/1.4/Tue Oct 17 21:52:04 2006//
+/09_-_P._S._I_Love_You.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/10_-_Baby_It's_You.lab/1.2/Thu Jul 27 21:44:53 2006//
+/11_-_Do_You_Want_To_Know_A_Secret.lab/1.3/Tue Oct 17 21:52:04 2006//
+/12_-_A_Taste_Of_Honey.lab/1.2/Thu Jul 27 21:45:39 2006//
+/13_-_There's_A_Place.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/14_-_Twist_And_Shout.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/01final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/01final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/01_-_It_Won't_Be_Long.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,70 @@
+0.0000000 1.0722662 N
+1.0722662 1.7232850 F#
+1.7232850 5.1667190 C#:min
+5.1667190 8.7077620 E
+8.7077620 10.4608690 C#:min
+10.4608690 11.3548370 A
+11.3548370 12.2139750 G:dim7
+12.2139750 13.9670820 E
+13.9670820 15.7201890 E
+15.7201890 17.4384650 E
+17.4384650 19.2031820 C
+19.2031820 20.9911180 E
+20.9911180 22.7790550 E
+22.7790550 24.5669910 C
+24.5669910 26.3200980 E
+26.3200980 28.1080340 E
+28.1080340 31.6374680 C#:min
+31.6374680 35.2481700 E
+35.2481700 37.0244970 C#:min
+37.0244970 37.9300750 A
+37.9300750 38.7892140 G:dim7
+38.7892140 42.3650870 E
+42.3650870 44.1530230 E
+44.1530230 45.9177400 B:aug/3
+45.9177400 47.7521160 B:min/b3
+47.7521160 49.5516630 C#:7
+49.5516630 51.3512090 A
+51.3512090 53.1623660 B
+53.1623660 54.9386920 F#:min7
+54.9386920 56.6337490 B
+56.6337490 58.4216850 E
+58.4216850 60.2212320 C
+60.2212320 62.0323880 E
+62.0323880 63.8203250 E
+63.8203250 65.6663110 C
+65.6663110 67.4426380 E
+67.4426380 69.2537940 E
+69.2537940 72.8644970 C#:min
+72.8644970 76.4635900 E
+76.4635900 78.2515270 C#:min
+78.2515270 79.1571050 A
+79.1571050 80.0626830 G:dim7
+80.0626830 81.8506190 E
+81.8506190 83.6849960 E
+83.6849960 85.4613220 E
+85.4613220 87.2724790 B:aug/3
+87.2724790 89.1300750 B:min/b3
+89.1300750 90.9876720 C#:7
+90.9876720 92.7523880 A
+92.7523880 94.5751550 B
+94.5751550 96.3747010 F#:min7
+96.3747010 98.0813680 B
+98.0813680 99.8809140 E
+99.8809140 101.6688510 C
+101.6688510 103.4800070 E
+103.4800070 105.2911640 E
+105.2911640 107.1255400 C
+107.1255400 108.9250870 E
+108.9250870 110.7478530 E
+110.7478530 114.3701660 C#:min
+114.3701660 117.9692590 E
+117.9692590 119.8500750 C#:min
+119.8500750 120.8980171 A
+120.8980171 122.9468115 G:dim7
+122.9468115 124.0296670 E
+124.0296670 124.7494860 G:7
+124.7494860 125.7015040 F#:7
+125.7015040 126.6651320 F:7
+126.6651320 130.0122800 E:maj7
+130.0122800 133.7077690 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/02_-_All_I've_Got_To_Do.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+0.0000000 0.4978379 N
+0.4978379 3.6571650 E:aug(9,11)
+3.6571650 7.7554870 C#:min
+7.7554870 11.9234690 E
+11.9234690 15.9521310 C#:min
+15.9521310 19.9459630 F#:min
+19.9459630 21.9660990 A:min
+21.9660990 25.9715410 E
+25.9715410 30.0466430 C#:min
+30.0466430 34.1333560 E
+34.1333560 38.1504080 C#:min
+38.1504080 42.1326300 F#:min
+42.1326300 44.1411560 A:min
+44.1411560 48.0885480 E
+48.0885480 52.0011110 A
+52.0011110 55.9252830 C#:min
+55.9252830 57.8989790 A
+57.8989790 58.5916903 E
+58.5916903 59.9075050 C#:min
+59.9075050 61.8812010 A
+61.8812010 62.6701314 E
+62.6701314 63.8432870 E/5
+63.8432870 65.8866430 E
+65.8866430 70.0081850 C#:min
+70.0081850 74.1181170 E
+74.1181170 78.1467800 C#:min
+78.1467800 82.1754420 F#:min
+82.1754420 84.1491380 A:min
+84.1491380 88.1545800 E
+88.1545800 92.0787520 A
+92.0787520 96.0261450 C#:min
+96.0261450 97.9998410 A
+97.9998410 98.7250833 E
+98.7250833 99.9619270 C#:min
+99.9619270 101.9124030 A
+101.9124030 102.7018820 E
+102.7018820 103.8977090 E/5
+103.8977090 105.8481850 A
+105.8481850 106.6260540 E
+106.6260540 107.8451020 E/5
+107.8451020 109.8768480 E
+109.8768480 113.9403400 C#:min
+113.9403400 118.1083210 E
+118.1083210 120.3044411 C#:min
+120.3044411 124.4594728 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/03_-_All_My_Loving.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,74 @@
+0.0000000 0.4786903 N
+0.4786903 1.3652490 C#:min
+1.3652490 2.7932770 F#:min
+2.7932770 4.2793530 B
+4.2793530 5.8002610 E
+5.8002610 7.3443870 C#:min
+7.3443870 8.8536840 A
+8.8536840 10.3862020 F#:min
+10.3862020 11.9535480 D
+11.9535480 13.4860660 B
+13.4860660 14.9721420 F#:min
+14.9721420 16.5278790 B
+16.5278790 18.0836160 E
+18.0836160 19.6161330 C#:min
+19.6161330 21.1486500 A
+21.1486500 22.6927770 B
+22.6927770 25.8158610 E
+25.8158610 27.3483780 F#:min
+27.3483780 28.8808950 B
+28.8808950 30.3669720 E
+30.3669720 31.9227090 C#:min
+31.9227090 33.4436170 A
+33.4436170 35.0109640 F#:min
+35.0109640 36.5667010 D
+36.5667010 38.1224380 B
+38.1224380 39.6549550 F#:min
+39.6549550 41.1990820 B
+41.1990820 42.7315990 E
+42.7315990 44.2989460 C#:min
+44.2989460 45.8546830 A
+45.8546830 47.3639800 B
+47.3639800 48.9429370 E
+48.9429370 50.5218940 E
+50.5218940 52.0544110 C#:min
+52.0544110 53.5753180 C:aug
+53.5753180 56.6751820 E
+56.6751820 58.1844790 C#:min
+58.1844790 59.7169960 C:aug
+59.7169960 61.2959530 E
+61.2959530 62.8284700 E
+62.8284700 65.8702830 A:7
+65.8702830 68.9004870 E
+68.9004870 70.4330050 F#:min
+70.4330050 71.9306920 B
+71.9306920 73.4980390 E
+73.4980390 75.1466560 E
+75.1466560 76.5746830 F#:min
+76.5746830 78.1420300 B
+78.1420300 79.6629360 E
+79.6629360 81.2535040 C#:min
+81.2535040 82.7744100 A
+82.7744100 84.3301480 F#:min
+84.3301480 85.8974950 D
+85.8974950 87.4416220 B
+87.4416220 88.9973580 F#:min
+88.9973580 90.5647040 B
+90.5647040 92.1320510 E
+92.1320510 93.6645680 C#:min
+93.6645680 95.2203060 A
+95.2203060 96.7412120 B
+96.7412120 98.3085590 E
+98.3085590 99.8526860 E
+99.8526860 101.3968140 C#:min
+101.3968140 102.9641600 C:aug
+102.9641600 106.0408050 E
+106.0408050 107.5965410 C#:min
+107.5965410 109.1754980 C:aug
+109.1754980 112.2869720 E
+112.2869720 115.3636160 C#:min
+115.3636160 118.4518700 E
+118.4518700 121.5052940 C#:min
+121.5052940 123.0958610 E
+123.0958610 125.8781010 E
+125.8781010 129.3246710 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/04_-_Don't_Bother_Me.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,86 @@
+0.0000000 0.5361331 N
+0.5361331 3.3957300 D
+3.3957300 6.1937340 E:min
+6.1937340 7.5985420 B:min
+7.5985420 9.0381790 A
+9.0381790 10.4545960 G
+10.4545960 11.8710130 E
+11.8710130 13.3222600 B:min
+13.3222600 14.6922380 A
+14.6922380 17.5482920 G
+17.5482920 18.9647090 E:min
+18.9647090 20.3811270 A
+20.3811270 21.8207640 E:min
+21.8207640 23.2023510 E:min
+23.2023510 24.6187680 B:min
+24.6187680 26.0467960 A
+26.0467960 27.4283830 G
+27.4283830 28.8564100 E
+28.8564100 30.2379970 B:min
+30.2379970 31.6428050 A
+31.6428050 33.0360020 G
+33.0360020 34.4872490 G
+34.4872490 35.8804460 E:min
+35.8804460 37.2620340 A
+37.2620340 38.6552310 E:min
+38.6552310 40.0832580 E:min
+40.0832580 42.8580430 D
+42.8580430 45.6212170 E:min
+45.6212170 48.4076120 D
+48.4076120 51.2172260 E:min
+51.2172260 54.0268410 B:min
+54.0268410 56.8480650 A:min
+56.8480650 59.6112400 C
+59.6112400 61.0624870 E:min
+61.0624870 62.4440740 E:min
+62.4440740 63.8604920 B:min
+63.8604920 65.2652990 A
+65.2652990 66.6352760 G
+66.6352760 68.0516940 E
+68.0516940 69.4332810 B:min
+69.4332810 70.8845280 A
+70.8845280 72.2428950 G
+72.2428950 73.7173620 G
+73.7173620 75.1337800 E:min
+75.1337800 76.5385870 A
+76.5385870 77.9201740 E:min
+77.9201740 79.2785420 E:min
+79.2785420 80.6485190 B:min
+80.6485190 82.0417160 A
+82.0417160 83.4349130 G
+83.4349130 84.8281110 E
+84.8281110 86.2096980 B:min
+86.2096980 87.6261150 A
+87.6261150 89.0077030 G
+89.0077030 90.4357300 G
+90.4357300 91.8405370 E:min
+91.8405370 93.2685640 A
+93.2685640 94.6849810 E:min
+94.6849810 96.0665690 E:min
+96.0665690 98.8529630 D
+98.8529630 101.6625780 E:min
+101.6625780 104.3909230 D
+104.3909230 107.2121470 E:min
+107.2121470 110.0217620 B:min
+110.0217620 112.8545960 A:min
+112.8545960 115.6177710 C
+115.6177710 118.4157750 E:min
+118.4157750 119.8321920 B:min
+119.8321920 121.2253900 A
+121.2253900 122.6418070 G
+122.6418070 124.0698340 E
+124.0698340 125.4282010 B:min
+125.4282010 126.8562290 A
+126.8562290 128.2726460 G
+128.2726460 129.6890630 G
+129.6890630 131.1054800 E:min
+131.1054800 132.5102880 A
+132.5102880 133.7269166 E:min
+133.7269166 135.3663420 A
+135.3663420 136.4841726 E:min
+136.4841726 138.1875670 A
+138.1875670 139.3601740 E:min
+139.3601740 140.9043010 A
+140.9043010 142.1349590 E:min
+142.1349590 144.1815123 A
+144.1815123 149.0833008 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/05_-_Little_Child.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,67 @@
+0.0000000 0.4978379 N
+0.4978379 2.2221070 E
+2.2221070 3.6385240 A
+3.6385240 6.7267780 E:9
+6.7267780 9.9195220 E
+9.9195220 10.7554400 E
+10.7554400 11.5216990 A
+11.5216990 13.1470960 E
+13.1470960 14.7376630 B
+14.7376630 16.3050100 A
+16.3050100 17.9420160 F#:9
+17.9420160 19.5325830 B
+19.5325830 23.5264150 E
+23.5264150 24.3042840 A
+24.3042840 25.8600210 E
+25.8600210 27.4854180 B
+27.4854180 29.0643750 A
+29.0643750 29.8886830 F#:9
+29.8886830 30.6549410 B
+30.6549410 32.2338980 E
+32.2338980 33.8360750 E
+33.8360750 35.3918120 B
+35.3918120 36.9591590 E
+36.9591590 38.5148960 E
+38.5148960 40.1054630 F#
+40.1054630 41.7308600 B
+41.7308600 45.7130820 E
+45.7130820 46.4909510 A
+46.4909510 48.0815170 E
+48.0815170 49.6720840 B
+49.6720840 51.2626510 A
+51.2626510 52.0866170 F#:9
+52.0866170 52.8416080 B
+52.8416080 54.3160750 E
+54.3160750 60.6319030 E
+60.6319030 63.6969370 A
+63.6969370 66.8548510 E
+66.8548510 68.3873680 B
+68.3873680 69.9895450 A
+69.9895450 71.5220620 F#
+71.5220620 73.0894090 B
+73.0894090 74.6616500 E
+74.6616500 76.2821520 B
+76.2821520 79.4516760 E
+79.4516760 81.0886830 F#
+81.0886830 82.6792500 B
+82.6792500 86.6614720 E
+86.6614720 87.4741700 A
+87.4741700 89.0531270 E
+89.0531270 90.6669140 B
+90.6669140 92.2110410 A
+92.2110410 92.9667670 F#
+92.9667670 93.7667780 B
+93.7667780 94.5368710 E
+94.5368710 95.3109050 C#
+95.3109050 96.1261230 F#
+96.1261230 96.9014720 B
+96.9014720 97.7345220 E
+97.7345220 98.5036490 C#
+98.5036490 99.2663310 F#
+99.2663310 100.0942160 B
+100.0942160 100.8364350 E
+100.8364350 101.6847830 C#
+101.6847830 102.5207010 F#
+102.5207010 103.2637400 B
+103.2637400 104.4170380 E
+104.4170380 107.6529850 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/06_-_Till_There_Was_You.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,93 @@
+0.0000000 0.4778134 N
+0.4778134 1.4716650 F
+1.4716650 2.4933430 F#:dim
+2.4933430 3.4453610 G:min
+3.4453610 4.4322090 C:9
+4.4322090 5.4306670 F
+5.4306670 6.4175150 F#:dim
+6.4175150 7.3811430 G:min
+7.3811430 8.3679910 C:9
+8.3679910 10.3184670 F
+10.3184670 12.2805540 F#:dim
+12.2805540 14.2426400 G:min
+14.2426400 16.2047260 Bb:min
+16.2047260 17.1567440 F
+17.1567440 17.6443630 A:min
+17.6443630 18.1203720 G#:min
+18.1203720 19.1188300 G:min
+19.1188300 20.1172880 C:9
+20.1172880 22.0445440 F
+22.0445440 23.0197830 G:min7
+23.0197830 23.9950210 C:9
+23.9950210 25.9454970 F
+25.9454970 27.8727530 F#:dim
+27.8727530 29.8464490 G:min
+29.8464490 31.7737050 Bb:min
+31.7737050 32.7605540 F
+32.7605540 33.2481730 A:min
+33.2481730 33.7241820 G#:min
+33.7241820 34.7342500 G:min
+34.7342500 35.6978780 C:9
+35.6978780 37.6483540 F
+37.6483540 39.6104400 F:9
+39.6104400 41.5376960 Bb
+41.5376960 43.4765630 Bb:min
+43.4765630 45.4270390 F
+45.4270390 47.3659050 D:9
+47.3659050 48.3643630 G:min
+48.3643630 49.3163810 G:minmaj7
+49.3163810 51.2552470 G:7
+51.2552470 53.2869930 C:9
+53.2869930 55.1562000 C:7
+55.1562000 57.1531160 F
+57.1531160 59.1500320 F#:dim
+59.1500320 61.0656780 G:min
+61.0656780 63.0858140 Bb:min
+63.0858140 64.0262220 F
+64.0262220 64.5370610 A:min
+64.5370610 65.0595100 G#:min
+65.0595100 66.0115290 G:min
+66.0115290 66.9983770 C:9
+66.9983770 68.9372430 F
+68.9372430 69.8892610 G:min7
+69.8892610 70.8644990 C:9
+70.8644990 72.7801450 F
+72.7801450 74.7538410 F#:dim
+74.7538410 76.7275380 G:min
+76.7275380 78.7012340 Bb:min
+78.7012340 79.6880820 F
+79.6880820 80.1757010 A:min
+80.1757010 80.6749300 G#:min
+80.6749300 81.6385580 G:min
+81.6385580 82.6602360 F#:7(#9)
+82.6602360 84.6223220 F
+84.6223220 86.6076280 F:9
+86.6076280 88.5116650 Bb
+88.5116650 90.4853610 Bb:min
+90.4853610 92.4242270 F
+92.4242270 94.3863130 D:9
+94.3863130 95.4196010 G:min
+95.4196010 96.3600090 G:minmaj7
+96.3600090 98.3453150 G:7
+98.3453150 100.3190120 C:9
+100.3190120 102.2346580 C:7
+102.2346580 104.2547940 F
+104.2547940 106.2284900 F#:dim
+106.2284900 108.2021860 G:min
+108.2021860 110.1758820 Bb:min
+110.1758820 111.1627300 F
+111.1627300 111.6851790 A:min
+111.6851790 112.1727980 G#:min
+112.1727980 113.1015970 G:min
+113.1015970 114.1000550 C:9
+114.1000550 116.0157010 F
+116.0157010 117.9429570 F
+117.9429570 118.9065850 C:7
+118.9065850 119.8934330 B:7
+119.8934330 121.8555190 C:7/5
+121.8555190 123.7943860 F
+123.7943860 125.7216420 C#
+125.7216420 127.7069480 F
+127.7069480 128.7170160 F:maj7
+128.7170160 131.9729231 F:maj7
+131.9729231 136.5575617 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/07_-_Please_Mister_Postman.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,41 @@
+0.0000000 0.6510188 N
+0.6510188 4.4781640 C#:min
+4.4781640 8.3675060 F#:min
+8.3675060 12.1987990 A
+12.1987990 16.0881410 F#:min
+16.0881410 19.9774830 D
+19.9774830 23.8552160 E
+23.8552160 27.7097280 A
+27.7097280 31.5990710 F#:min
+31.5990710 35.5116330 D
+35.5116330 39.3893650 E
+39.3893650 43.3135380 A
+43.3135380 47.2144900 F#:min
+47.2144900 51.1386630 D
+51.1386630 55.0744450 E
+55.0744450 58.9289570 A
+58.9289570 62.8415200 F#:min
+62.8415200 66.7889120 D
+66.7889120 70.6434240 E
+70.6434240 74.5327670 A
+74.5327670 78.4337190 F#:min
+78.4337190 82.3811110 D
+82.3811110 86.3168940 E
+86.3168940 90.2410660 A
+90.2410660 94.1768480 F#:min
+94.1768480 98.1590710 D
+98.1590710 102.0832430 E
+102.0832430 106.0422450 A
+106.0422450 109.9548080 F#:min
+109.9548080 113.8441500 D
+113.8441500 117.8147620 E
+117.8147620 121.7737650 A
+121.7737650 125.6631070 F#:min
+125.6631070 129.5640590 D
+129.5640590 133.5114520 E
+133.5114520 137.4124040 A
+137.4124040 141.3365760 F#:min
+141.3365760 145.2491390 D
+145.2491390 149.2313610 E
+149.2313610 151.5916378 A
+151.5916378 156.2828026 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/08_-_Roll_Over_Beethoven.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,77 @@
+0.0000000 0.4403951 N
+0.4403951 1.0148234 A
+1.0148234 6.6442211 D
+6.6442211 9.4318790 G
+9.4318790 12.2414930 D
+12.2414930 13.6579110 G
+13.6579110 15.0743280 A
+15.0743280 16.5255750 D
+16.5255750 17.9652120 D/5
+17.9652120 19.3700200 D
+19.3700200 20.8444870 G
+20.8444870 23.7353710 D
+23.7353710 25.2330580 G
+25.2330580 26.7075250 G
+26.7075250 28.1819920 D
+28.1819920 29.6796790 D
+29.6796790 31.1425370 G
+31.1425370 32.6402240 A
+32.6402240 35.6239880 D
+35.6239880 37.1100650 D
+37.1100650 38.6193620 G
+38.6193620 41.6379560 D
+41.6379560 44.6565500 G
+44.6565500 47.6403140 D
+47.6403140 49.1380010 G
+49.1380010 50.6589080 A
+50.6589080 53.6542830 D
+53.6542830 55.1403600 D
+55.1403600 56.6380470 G
+56.6380470 59.6218110 D
+59.6218110 62.6520150 G
+62.6520150 65.6706090 D
+65.6706090 67.2495660 G
+67.2495660 68.6892030 A
+68.6892030 71.7077970 D
+71.7077970 77.5360060 D
+77.5360060 80.4733300 G
+80.4733300 83.3642150 D
+83.3642150 84.8386820 G
+84.8386820 86.2434890 A
+86.2434890 89.1924230 D
+89.1924230 90.6204500 D
+90.6204500 92.0716980 G
+92.0716980 95.0206320 D
+95.0206320 97.9463460 G
+97.9463460 100.8720600 D
+100.8720600 102.3581370 G
+102.3581370 103.8093850 A
+103.8093850 106.7931490 D
+106.7931490 108.2560060 D
+108.2560060 109.7536930 G
+109.7536930 112.7142370 D
+112.7142370 115.7328310 G
+115.7328310 118.7514250 D
+118.7514250 120.2723320 G
+120.2723320 121.7700200 A
+121.7700200 124.8002240 D
+124.8002240 126.3095210 D
+126.3095210 127.8420380 G
+127.8420380 129.3397250 D
+129.3397250 130.8954620 D
+130.8954620 133.8792260 G
+133.8792260 136.8862100 D
+136.8862100 138.3955070 G
+138.3955070 139.9280240 A
+139.9280240 142.8885680 D
+142.8885680 148.8212670 D
+148.8212670 151.7702010 G
+151.7702010 154.7887950 D
+154.7887950 156.2748720 A
+156.2748720 157.1243178 A
+157.1243178 157.7609490 D
+157.7609490 158.5504280 G
+158.5504280 159.1309270 A
+159.1309270 159.6998150 D
+159.6998150 163.4248616 D
+163.4248616 167.1203505 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/09_-_Hold_Me_Tight.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,85 @@
+0.0000000 0.4403951 N
+0.4403951 2.1569280 F
+2.1569280 3.8403750 C
+3.8403750 5.5586520 F
+5.5586520 7.2653180 Bb
+7.2653180 9.0300350 G
+9.0300350 10.8063610 C
+10.8063610 12.5478580 F
+12.5478580 14.2661350 Bb
+14.2661350 16.0076310 G
+16.0076310 17.7375180 C
+17.7375180 19.5138440 F
+19.5138440 21.2785610 F:7
+21.2785610 22.9968370 Bb
+22.9968370 24.7615540 Bb:min
+24.7615540 26.5146610 F
+26.5146610 28.3025970 Bb:min
+28.3025970 30.0673140 F
+30.0673140 31.7972000 C
+31.7972000 33.5619170 F
+33.5619170 35.2918030 Bb
+35.2918030 37.0449100 G
+37.0449100 38.8212370 C
+38.8212370 40.5859530 F
+40.5859530 42.3390600 Bb
+42.3390600 44.0921660 G
+44.0921660 45.8568830 C
+45.8568830 47.6332090 F
+47.6332090 49.3979260 F:7
+49.3979260 51.1742520 Bb
+51.1742520 52.9157490 Bb:min
+52.9157490 54.7036860 F
+54.7036860 56.5032320 Bb:min
+56.5032320 58.2563390 F
+58.2563390 60.0210550 Ab
+60.0210550 61.7625520 F
+61.7625520 63.5620980 Ab
+63.5620980 65.3268150 F
+65.3268150 67.0683110 Bb
+67.0683110 68.8098080 G:min
+68.8098080 70.5629150 G
+70.5629150 72.2811910 C
+72.2811910 73.9994680 F
+73.9994680 75.8106240 Bb
+75.8106240 77.5405110 G
+77.5405110 79.3168370 C
+79.3168370 81.1047740 F
+81.1047740 82.8811010 Bb
+82.8811010 84.6458170 G
+84.6458170 86.4105340 C
+86.4105340 88.2100800 F
+88.2100800 89.9864070 F:7
+89.9864070 91.7511230 Bb
+91.7511230 93.5274500 Bb:min
+93.5274500 95.3037760 F
+95.3037760 97.1033230 Bb:min
+97.1033230 98.8912590 F
+98.8912590 100.6791960 Ab
+100.6791960 102.4206920 F
+102.4206920 104.2202390 Ab
+104.2202390 106.0081750 F
+106.0081750 107.7380620 Bb
+107.7380620 109.5027790 G:min
+109.5027790 111.2674950 G
+111.2674950 112.9393320 C
+112.9393320 114.7156580 F
+114.7156580 116.4919850 Bb
+116.4919850 118.2683110 G
+118.2683110 120.0446380 C
+120.0446380 121.8325740 F
+121.8325740 123.6089010 Bb
+123.6089010 125.3271780 G
+125.3271780 127.1151140 C
+127.1151140 128.9262710 F
+128.9262710 130.6909870 F:7
+130.6909870 132.4789240 Bb
+132.4789240 134.2436400 Bb:min
+134.2436400 136.0431870 F
+136.0431870 137.8659530 Bb:min
+137.8659530 139.7119400 F
+139.7119400 141.5230960 Ab
+141.5230960 143.3806920 F
+143.3806920 145.5865880 Ab
+145.5865880 149.0367100 F
+149.0367100 152.4641330 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/10_-_You_Really_Got_A_Hold_On_Me.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,61 @@
+0.0000000 0.4403951 N
+0.4403951 2.0543090 E
+2.0543090 5.0380740 A
+5.0380740 8.0102280 F#:min
+8.0102280 10.9823820 A
+10.9823820 13.9777560 F#:min
+13.9777560 20.0962140 A
+20.0962140 26.2262820 F#:min
+26.2262820 29.2913160 A
+29.2913160 32.3679600 D
+32.3679600 33.8656470 B:7
+33.8656470 35.4213840 E
+35.4213840 41.6211120 A
+41.6211120 47.8672800 F#:min
+47.8672800 54.1482780 A
+54.1482780 60.3944450 F#:min
+60.3944450 63.5407490 A
+63.5407490 66.6406130 D
+66.6406130 68.2195700 B:7
+68.2195700 69.7869170 E
+69.7869170 76.0795250 A
+76.0795250 82.2908630 F#:min
+82.2908630 85.4371670 A
+85.4371670 88.5834700 D
+88.5834700 90.1856470 A
+90.1856470 91.8342640 A
+91.8342640 93.5757610 A
+93.5757610 97.3954430 E
+97.3954430 98.9740023 A
+98.9740023 99.8219280 F#:min
+99.8219280 100.5997970 A/3
+100.5997970 101.3892750 F#:min
+101.3892750 102.0858740 E
+102.0858740 103.6067810 A
+103.6067810 105.1276880 A
+105.1276880 105.8939470 B:min/5
+105.8939470 106.6485950 A/5
+106.6485950 107.4264640 F#:min
+107.4264640 108.2159420 E
+108.2159420 109.7484590 A
+109.7484590 115.9830170 A
+115.9830170 122.3220650 F#:min
+122.3220650 125.4799780 A
+125.4799780 128.6378920 D
+128.6378920 130.2632890 B:7
+130.2632890 131.8306360 E
+131.8306360 138.2161230 A
+138.2161230 144.6132210 F#:min
+144.6132210 147.8175750 A
+147.8175750 150.9870990 D
+150.9870990 152.6008850 A
+152.6008850 154.3075520 A
+154.3075520 155.9445590 A
+155.9445590 159.7178010 E
+159.7178010 166.1845590 A
+166.1845590 172.5236060 F#:min
+172.5236060 172.7497482 A
+172.7497482 173.9943429 N
+173.9943429 175.6234700 A
+175.6234700 178.7812457 A:9
+178.7812457 182.7639489 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/11_-_I_Wanna_Be_Your_Man.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,49 @@
+0.0000000 0.4212474 N
+0.4212474 1.2562470 N
+1.2562470 6.0976070 E
+6.0976070 10.9041380 E
+10.9041380 15.7687190 E
+15.7687190 19.4026410 E
+19.4026410 20.6216890 E
+20.6216890 21.8407370 E
+21.8407370 23.0481740 F#
+23.0481740 24.2904420 B
+24.2904420 25.4746600 E
+25.4746600 26.6820970 C#
+26.6820970 27.8779250 F#
+27.8779250 29.0737530 B
+29.0737530 29.3724356 E
+29.3724356 31.5466780 D:maj/2
+31.5466780 36.4228680 E
+36.4228680 41.2642290 E
+41.2642290 46.1984690 E
+46.1984690 51.0746600 E
+51.0746600 52.2937070 E
+52.2937070 53.4663150 F#
+53.4663150 54.7201920 B
+54.7201920 55.9392400 E
+55.9392400 57.1582880 C#
+57.1582880 58.3657250 F#
+58.3657250 59.5847730 B
+59.5847730 59.8937278 E
+59.8937278 62.0228680 D:maj/2
+62.0228680 66.8293990 E
+66.8293990 71.5198300 E
+71.5198300 76.2334800 E
+76.2334800 81.0167910 E
+81.0167910 85.8813720 E
+85.8813720 88.2846370 E
+88.2846370 90.6530720 E
+90.6530720 93.0911680 E
+93.0911680 95.5060430 E
+95.5060430 96.7134800 E
+96.7134800 97.9441380 F#
+97.9441380 99.1631860 B
+99.1631860 100.3938430 E
+100.3938430 101.5780610 C#
+101.5780610 102.8087190 F#
+102.8087190 103.9697160 B
+103.9697160 104.2778906 E
+104.2778906 106.4542510 D:maj/2
+106.4542510 114.1580580 E
+114.1580580 118.7534846 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/12_-_Devil_In_Her_Heart.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,92 @@
+0.0000000 0.4595427 N
+0.4595427 1.1871519 N
+1.1871519 3.1426620 A:min
+3.1426620 5.0699180 D
+5.0699180 7.0436150 G
+7.0436150 9.1334110 G
+9.1334110 11.0954970 A:min
+11.0954970 13.0808030 D
+13.0808030 15.0196680 G
+15.0196680 16.9933650 G
+16.9933650 18.9670600 A:min
+18.9670600 20.9407580 D
+20.9407580 22.8796240 G
+22.8796240 23.4601230 G
+23.4601230 23.9361320 G
+23.9361320 24.4005310 A:min
+24.4005310 24.9113690 G/3
+24.9113690 26.8850650 C
+26.8850650 28.8471510 C:min
+28.8471510 30.7976280 G
+30.7976280 31.2968570 G
+31.2968570 31.7612560 G
+31.7612560 32.2488740 A:min
+32.2488740 32.7481030 G/3
+32.7481030 34.7334110 C
+34.7334110 36.7187160 C:min
+36.7187160 38.7272430 A
+38.7272430 40.7009390 D
+40.7009390 42.7442940 D
+42.7442940 44.7063800 A:min
+44.7063800 46.7032960 D
+46.7032960 50.6739080 G
+50.6739080 52.6476050 A:min
+52.6476050 54.6096910 D
+54.6096910 56.5717770 G
+56.5717770 57.0826170 G
+57.0826170 57.5818460 G
+57.5818460 58.0462450 A:min
+58.0462450 58.5570840 G/3
+58.5570840 60.5540000 C
+60.5540000 62.5625260 C:min
+62.5625260 64.5478320 G
+64.5478320 65.0586710 G
+65.0586710 65.5346800 G
+65.5346800 66.0106890 A:min
+66.0106890 66.5215280 G/3
+66.5215280 68.5300550 C
+68.5300550 70.5385810 C:min
+70.5385810 72.5238870 A
+72.5238870 74.5091920 D
+74.5091920 76.5409390 D
+76.5409390 78.5262450 A:min
+78.5262450 80.5347710 D
+80.5347710 84.4473330 G
+84.4473330 86.4790790 A:min
+86.4790790 88.4527760 D
+88.4527760 90.4032520 G
+90.4032520 90.9837500 G
+90.9837500 91.4249300 G
+91.4249300 91.9009390 A:min
+91.9009390 92.4001680 G/3
+92.4001680 94.4319140 C
+94.4319140 96.4172200 C:min
+96.4172200 98.4257460 G
+98.4257460 98.9133650 G
+98.9133650 99.4009840 G
+99.4009840 99.8886030 A:min
+99.8886030 100.3762210 G/3
+100.3762210 102.3847480 C
+102.3847480 104.3700550 C:min
+104.3700550 106.3669710 A
+106.3669710 108.3406660 D
+108.3406660 110.3724130 D
+110.3724130 112.3809380 A:min
+112.3809380 114.3430240 D
+114.3430240 116.3051100 G
+116.3051100 118.2671960 G
+118.2671960 120.2757230 A:min
+120.2757230 122.2378090 D
+122.2378090 124.1998960 G
+124.1998960 126.1968120 G
+126.1968120 128.1588970 A:min
+128.1588970 130.1558130 D
+130.1558130 132.1178990 G
+132.1178990 134.0683760 G
+134.0683760 136.0769020 A:min
+136.0769020 138.0273780 D
+138.0273780 140.0010740 G
+140.0010740 140.5243186 G
+140.5243186 141.0343620 D
+141.0343620 143.9325934 G:maj6(9)
+143.9325934 147.4940490 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/13_-_Not_A_Second_Time.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,69 @@
+0.0000000 0.4595427 N
+0.4595427 2.3079480 G
+2.3079480 4.1358840 E:min
+4.1358840 6.0347510 G
+6.0347510 7.8342970 E:min
+7.8342970 9.7383330 D
+9.7383330 11.6075400 G
+11.6075400 13.5347960 D
+13.5347960 15.3807820 G
+15.3807820 17.2615990 E:min
+17.2615990 19.1888550 G
+19.1888550 21.0464510 E:min
+21.0464510 22.9737080 D
+22.9737080 24.8313040 A:min
+24.8313040 26.7585600 D
+26.7585600 28.6393760 A:min
+28.6393760 30.5318030 B:min
+30.5318030 32.4126190 G
+32.4126190 34.3398750 E:min
+34.3398750 36.2671320 A:min
+36.2671320 38.1247280 F#:dim/b3
+38.1247280 40.0403740 B:min
+40.0403740 41.9328010 D:7/5
+41.9328010 43.8484470 E:min
+43.8484470 44.0969486 E:min
+44.0969486 45.7408730 N
+45.7408730 47.6565190 A:min
+47.6565190 49.5605560 B:min
+49.5605560 51.4529820 G
+51.4529820 53.3686280 E:min
+53.3686280 55.2958840 A:min
+55.2958840 57.2115310 A:min
+57.2115310 59.1271770 B:min
+59.1271770 61.0544330 D:7/5
+61.0544330 62.9468590 E:min
+62.9468590 64.8276760 N
+64.8276760 66.8013720 G
+66.8013720 68.6937980 E:min
+68.6937980 70.6326640 G
+70.6326640 72.5367010 E:min
+72.5367010 74.5103970 D
+74.5103970 76.4144330 G
+76.4144330 78.3532990 D
+78.3532990 80.3269960 G
+80.3269960 82.2542520 E:min
+82.2542520 84.1931180 G
+84.1931180 86.1203740 E:min
+86.1203740 88.0708500 D
+88.0708500 90.0097170 A:min
+90.0097170 91.9601930 D
+91.9601930 93.8642290 A:min
+93.8642290 95.8843650 B:min
+95.8843650 97.8000110 G
+97.8000110 99.7272680 E:min
+99.7272680 101.6777440 A:min
+101.6777440 103.5933900 A:min
+103.5933900 105.5090360 B:min
+105.5090360 107.4479030 D:7/5
+107.4479030 109.4099890 E:min
+109.4099890 109.7541074 E:min
+109.7541074 111.3024150 N
+111.3024150 113.2528910 G
+113.2528910 115.2033670 E:min
+115.2033670 117.1074040 G
+117.1074040 119.0578800 E:min
+119.0578800 120.9735260 G
+120.9735260 122.8543420 E:min
+122.8543420 124.8396490 G
+124.8396490 128.1932570 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/14_-_Money.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,92 @@
+0.0000000 0.4595427 N
+0.4595427 1.4743661 E:min
+1.4743661 2.2785657 A
+2.2785657 2.9487321 E:min
+2.9487321 3.5231605 A
+3.5231605 4.1020400 G
+4.1020400 5.0076190 E:min
+5.0076190 5.8783670 A
+5.8783670 6.5865760 E:min
+6.5865760 7.0625850 A
+7.0625850 7.7359630 G
+7.7359630 9.5355100 B:7(#9)
+9.5355100 11.3698860 A:7
+11.3698860 12.2870740 E:min
+12.2870740 12.9715707 A
+12.9715707 13.4945120 E:min
+13.4945120 15.0270290 B:7
+15.0270290 18.0107930 E
+18.0107930 18.7190020 A
+18.7190020 21.7375960 E
+21.7375960 22.4574150 E
+22.4574150 26.1261670 A:7
+26.1261670 29.7717000 E
+29.7717000 31.6176870 B:7
+31.6176870 33.4404530 A:7
+33.4404530 35.2864400 E:7
+35.2864400 35.5534690 E:7
+35.5534690 37.1324260 B:7
+37.1324260 40.1278000 E
+40.1278000 40.8592290 A
+40.8592290 44.5628110 E
+44.5628110 48.2663940 A:7
+48.2663940 52.0164170 E
+52.0164170 53.8856230 B:7
+53.8856230 55.6851700 A:7
+55.6851700 57.7749660 E:7
+57.7749660 59.4235820 B:7
+59.4235820 62.5054133 E
+62.5054133 63.1736050 A
+63.1736050 66.9700680 E
+66.9700680 70.6852600 A:7
+70.6852600 74.4004530 E:7
+74.4004530 76.2696600 B:7
+76.2696600 78.1272560 A:7
+78.1272560 80.2170520 E:7
+80.2170520 81.8656690 B:7
+81.8656690 82.8705856 E
+82.8705856 83.7348750 A
+83.7348750 84.4314740 E:min
+84.4314740 84.8958730 A
+84.8958730 85.6156910 G
+85.6156910 86.5444890 E:min
+86.5444890 87.4500680 A
+87.4500680 88.1698860 E:min
+88.1698860 88.6226750 A
+88.6226750 89.2960540 G
+89.2960540 91.1420400 B:7(#9)
+91.1420400 93.0228570 A:7(#9)
+93.0228570 93.9864850 E:min
+93.9864850 94.6414132 A
+94.6414132 95.1358730 E:min
+95.1358730 96.7496600 B:7
+96.7496600 99.8495230 E
+99.8495230 100.5693420 A
+100.5693420 104.3541950 E
+104.3541950 108.0926070 A
+108.0926070 111.7961900 E
+111.7961900 113.6653960 B:7
+113.6653960 115.5113830 A:7
+115.5113830 117.6127890 E:7
+117.6127890 119.2033560 B:7
+119.2033560 120.2134240 E
+120.2134240 121.0957820 A
+121.0957820 122.9765980 E
+122.9765980 124.8458050 E
+124.8458050 126.6801810 E
+126.6801810 130.3837640 A
+130.3837640 134.0989570 E
+134.0989570 135.9797730 B:7
+135.9797730 137.8489790 A:7
+137.8489790 139.9736050 E:7
+139.9736050 141.5990020 B:7
+141.5990020 145.3838550 E
+145.3838550 149.1106570 E
+149.1106570 152.8142400 A
+152.8142400 156.5642630 E
+156.5642630 158.4799090 B:7
+158.4799090 160.2910650 A:7
+160.2910650 162.1951020 E
+162.1951020 163.0194100 E/5
+163.0194100 166.0536185 E:7
+166.0536185 167.3382712 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+/.DS_Store/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/01_-_It_Won't_Be_Long.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/02_-_All_I've_Got_To_Do.lab/1.3/Thu Jul 27 21:47:04 2006//
+/03_-_All_My_Loving.lab/1.2/Thu Jul 27 22:24:34 2006//
+/04_-_Don't_Bother_Me.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/05_-_Little_Child.lab/1.2/Thu Jul 27 22:24:34 2006//
+/06_-_Till_There_Was_You.lab/1.2/Thu Jul 27 21:47:04 2006//
+/07_-_Please_Mister_Postman.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/08_-_Roll_Over_Beethoven.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/09_-_Hold_Me_Tight.lab/1.2/Thu Jul 27 22:24:34 2006//
+/10_-_You_Really_Got_A_Hold_On_Me.lab/1.2/Thu Jul 27 21:47:04 2006//
+/11_-_I_Wanna_Be_Your_Man.lab/1.2/Thu Jul 27 21:47:04 2006//
+/12_-_Devil_In_Her_Heart.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/13_-_Not_A_Second_Time.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/14_-_Money.lab/1.2/Thu Jul 27 21:47:04 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/02final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/02final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/01_-_A_Hard_Day's_Night.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,101 @@
+0.0000000 1.0148234 N
+1.0148234 4.3206570 G:sus4(b7)
+4.3206570 5.0172560 G
+5.0172560 5.8531740 C
+5.8531740 7.5250110 G
+7.5250110 9.2316770 F
+9.2316770 10.9151240 G
+10.9151240 11.7742620 G
+11.7742620 12.6682310 C
+12.6682310 14.3748970 G
+14.3748970 16.0699540 F
+16.0699540 17.7882310 G
+17.7882310 19.5181170 C
+19.5181170 21.2131740 D
+21.2131740 22.1071420 G
+22.1071420 22.9546710 C
+22.9546710 24.6613370 G
+24.6613370 25.5320860 G
+25.5320860 26.4028340 C
+26.4028340 28.0746710 G
+28.0746710 29.7697270 F
+29.7697270 31.5344440 G
+31.5344440 32.3819720 G
+32.3819720 33.2411110 C
+33.2411110 34.9477770 G
+34.9477770 36.6544440 F
+36.6544440 38.4075500 G
+38.4075500 40.1258270 C
+40.1258270 41.8789340 D
+41.8789340 42.7264620 G
+42.7264620 43.5972100 C
+43.5972100 45.3387070 G
+45.3387070 47.0685940 B:min
+47.0685940 48.7868700 E:min
+48.7868700 52.3046930 B:min
+52.3046930 53.9765300 G
+53.9765300 55.6948070 E:min
+55.6948070 57.4014730 C
+57.4014730 59.1661900 D:7
+59.1661900 60.0717680 G
+60.0717680 60.9076860 C
+60.9076860 62.6259630 G
+62.6259630 64.3674600 F
+64.3674600 66.1205660 G
+66.1205660 66.9564850 G
+66.9564850 67.8388430 C
+67.8388430 69.6267790 G
+69.6267790 71.3334460 F
+71.3334460 73.0749430 G
+73.0749430 74.8464640 C
+74.8464640 76.5347160 D
+76.5347160 77.4170740 G
+77.4170740 78.2878230 C
+78.2878230 79.0350420 G
+79.0350420 80.0409290 G/5
+80.0409290 80.9116770 G
+80.9116770 81.8172560 C
+81.8172560 83.6170240 G
+83.6170240 85.3118590 F
+85.3118590 86.9953060 G
+86.9953060 87.8892740 G
+87.8892740 88.7484120 C
+88.7484120 90.4782990 G
+90.4782990 92.2662350 F
+92.2662350 93.9729020 G
+93.9729020 95.7027890 C
+95.7027890 97.4558950 D
+97.4558950 98.3034230 G
+98.3034230 99.1625620 C
+99.1625620 100.9388880 G
+100.9388880 102.6455550 B:min
+102.6455550 104.3986620 E:min
+104.3986620 107.8584350 B:min
+107.8584350 109.6115410 G
+109.6115410 111.3530380 E:min
+111.3530380 113.0364850 C
+113.0364850 114.7895910 D:7
+114.7895910 115.6255100 G
+115.6255100 116.5194780 C
+116.5194780 118.2725840 G
+118.2725840 119.9444210 F
+119.9444210 121.7323580 G
+121.7323580 122.5914960 G
+122.5914960 123.4622440 C
+123.4622440 125.2037410 G
+125.2037410 126.9220180 F
+126.9220180 128.6519040 G
+128.6519040 130.3934010 C
+130.3934010 132.1929470 D
+132.1929470 133.0753060 G
+133.0753060 133.9344440 C
+133.9344440 134.7842970 G
+134.7842970 135.6875500 G:sus4/5
+135.6875500 136.6047390 G
+136.6047390 137.4638770 C
+137.4638770 138.3457530 G
+138.3457530 139.2285940 C
+139.2285940 140.0993420 G
+140.0993420 141.0264180 C
+141.0264180 148.7046110 F:maj9(*7)
+148.7046110 152.3043610 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/02_-_I_Should_Have_Known_Better.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,136 @@
+0.000000 0.433233 N
+0.433233 1.279698 G
+1.279698 2.227599 D
+2.227599 3.133177 G
+3.133177 4.050366 D
+4.050366 4.967554 G
+4.967554 5.896352 D
+5.896352 6.825150 G
+6.825150 7.765558 D
+7.765558 8.636307 G
+8.636307 9.553495 D
+9.553495 10.470683 G
+10.470683 11.364651 D
+11.364651 12.281840 G
+12.281840 13.222248 D
+13.222248 14.127826 G
+14.127826 15.056624 D
+15.056624 15.973812 G
+15.973812 16.844561 D
+16.844561 17.808189 E:min/b3
+17.808189 18.725377 E:min
+18.725377 20.524923 C
+20.524923 22.394130 D
+22.394130 23.311318 G
+23.311318 24.228506 D
+24.228506 25.157304 G
+25.157304 26.097713 D
+26.097713 26.968461 G
+26.968461 27.862429 D
+27.862429 28.791227 G
+28.791227 29.708415 D
+29.708415 30.613994 G
+30.613994 31.507962 D
+31.507962 32.436760 G
+32.436760 33.342338 D
+33.342338 34.236307 G
+34.236307 35.141885 D
+35.141885 36.046293 E:min/b3
+36.046293 36.976261 E:min
+36.976261 38.775808 C
+38.775808 40.668234 B
+40.668234 42.525830 E:min
+42.525830 44.336987 C
+44.336987 46.148143 G
+46.148143 48.017350 B
+48.017350 51.651273 E:min
+51.651273 53.508869 G
+53.508869 55.320025 G:7
+55.320025 57.189232 C
+57.189232 58.988778 D
+58.988778 60.857985 G
+60.857985 62.715581 E:min
+62.715581 64.515127 C
+64.515127 66.361114 D
+66.361114 67.324742 G
+67.324742 68.265150 D
+68.265150 69.182338 G
+69.182338 70.134357 D
+70.134357 71.039935 G
+71.039935 71.945513 D
+71.945513 72.862701 G
+72.862701 73.779889 D
+73.779889 74.662248 G
+74.662248 75.591046 D
+75.591046 76.531454 G
+76.531454 77.460252 D
+77.460252 78.365830 G
+78.365830 79.259799 D
+79.259799 80.188597 E:min/b3
+80.188597 81.117395 E:min
+81.117395 82.928552 C
+82.928552 84.751318 D
+84.751318 85.668506 G
+85.668506 86.608914 D
+86.608914 87.537713 G
+87.537713 88.454901 D
+88.454901 89.383699 G
+89.383699 90.266057 D
+90.266057 91.183245 G
+91.183245 92.088824 D
+92.088824 92.994402 G
+92.994402 93.923200 D
+93.923200 94.863608 G
+94.863608 95.757576 D
+95.757576 96.709595 G
+96.709595 97.615173 D
+97.615173 98.556103 E:min/b3
+98.556103 99.403109 E:min
+99.403109 101.225876 C
+101.225876 103.025422 D
+103.025422 104.012270 G
+104.012270 104.941069 D
+104.941069 105.811817 G
+105.811817 106.752225 D
+106.752225 107.611363 G
+107.611363 108.551771 D
+108.551771 109.492180 G
+109.492180 110.386148 D
+110.386148 111.314946 G
+111.314946 112.197304 D
+112.197304 113.114493 G
+113.114493 114.043291 D
+114.043291 114.948869 G
+114.948869 115.854447 D
+115.854447 116.771635 E:min/b3
+116.771635 117.688824 E:min
+117.688824 119.558030 C
+119.558030 121.404016 B:7
+121.404016 123.226783 E:min
+123.226783 125.037939 C
+125.037939 126.883926 G
+126.883926 128.729912 B
+128.729912 130.622338 E:min
+130.622338 132.410275 E:min
+132.410275 134.279481 G
+134.279481 136.102248 G:7
+136.102248 137.959844 C
+137.959844 139.829050 D
+139.829050 141.651817 G
+141.651817 143.474583 E:min
+143.474583 145.355400 C
+145.355400 147.224606 D
+147.224606 148.141794 G
+148.141794 149.105422 D
+149.105422 150.022610 G
+150.022610 150.974629 D
+150.974629 151.880207 G
+151.880207 152.843835 D
+152.843835 153.761023 G
+153.761023 154.643381 D
+154.643381 155.583790 G
+155.583790 156.524198 D
+156.524198 157.429776 G
+157.429776 158.393404 D
+158.393404 159.333812 G
+159.333812 160.262610 D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/03_-_If_I_Fell.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,81 @@
+0.0000000 0.4403951 N
+0.4403951 1.0216030 N
+1.0216030 3.2042790 Eb:min
+3.2042790 5.4566150 D
+5.4566150 7.6973400 Db
+7.6973400 9.9148460 Bb:min
+9.9148460 12.1787920 Eb:min
+12.1787920 14.4775670 D
+14.4775670 16.6718530 E:min7
+16.6718530 18.9590180 A
+18.9590180 20.0735760 D
+20.0735760 21.1068640 E:min
+21.1068640 22.8483610 F#:min
+22.8483610 23.3592000 F:dim
+23.3592000 25.5418750 E:min7
+25.5418750 27.7245510 A
+27.7245510 28.8739390 D
+28.8739390 29.9072270 E:min
+29.9072270 31.5674540 F#:min
+31.5674540 32.1247330 F:dim
+32.1247330 34.3074080 E:min7
+34.3074080 36.4668640 A
+36.4668640 38.7192000 D
+38.7192000 39.8105380 G:min
+39.8105380 40.8902650 A
+40.8902650 41.9583830 D
+41.9583830 43.0729410 E:min
+43.0729410 44.7215580 F#:min
+44.7215580 45.2904470 F:dim
+45.2904470 47.4499030 E:min7
+47.4499030 49.6093580 A
+49.6093580 50.7703560 D
+50.7703560 51.8268640 E:min
+51.8268640 53.4406510 F#:min
+53.4406510 53.9747100 F:dim
+53.9747100 56.2154360 E:min7
+56.2154360 58.4097210 A
+58.4097210 60.6388370 D:9
+60.6388370 62.8795630 D:9
+62.8795630 65.0970680 G
+65.0970680 67.2565240 G:min
+67.2565240 69.5204700 G:min
+69.5204700 71.6799250 D
+71.6799250 73.9090410 A:7
+73.9090410 74.9423290 D
+74.9423290 76.0220570 E:min
+76.0220570 77.6474540 F#:min
+77.6474540 78.2163430 F:dim
+78.2163430 80.4570680 E:min7
+80.4570680 82.6513540 A
+82.6513540 83.7659120 D
+83.7659120 84.8920800 E:min
+84.8920800 86.5290860 F#:min
+86.5290860 87.1095850 F:dim
+87.1095850 89.2690410 E:min7
+89.2690410 91.4865470 A
+91.4865470 93.7040520 D:9
+93.7040520 95.8983380 D:9
+95.8983380 98.0926240 G
+98.0926240 100.3449590 G:min
+100.3449590 102.5740750 G:min
+102.5740750 104.7799710 D
+104.7799710 107.0090860 A:7
+107.0090860 108.1236440 D
+108.1236440 109.1801520 E:min
+109.1801520 110.8171590 F#:min
+110.8171590 111.3976580 F:dim
+111.3976580 113.5919430 E:min7
+113.5919430 115.8442790 A
+115.8442790 116.9936670 D
+116.9936670 118.0617850 E:min
+118.0617850 119.7684510 F#:min
+119.7684510 120.3141200 F:dim
+120.3141200 122.5548460 E:min7
+122.5548460 124.7375220 A
+124.7375220 127.0014670 D
+127.0014670 129.1957530 G:min
+129.1957530 131.4713090 D
+131.4713090 133.7700840 G:min
+133.7700840 137.3458151 D
+137.3458151 141.8455037 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/04_-_I'm_Happy_Just_To_Dance_With_You.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,108 @@
+0.0000000 0.3822458 N
+0.3822458 2.1542170 C#:min
+2.1542170 2.8043760 F#:min
+2.8043760 3.8260540 G#
+3.8260540 5.6604300 C#:min
+5.6604300 6.2989790 F#:min
+6.2989790 7.3670970 G#
+7.3670970 9.1898630 C#:min
+9.1898630 9.8864620 F#:min
+9.8864620 10.9778000 G#
+10.9778000 11.6691157 A
+11.6691157 12.7309096 B
+12.7309096 13.4623350 E:maj6
+13.4623350 14.5885030 B
+14.5885030 15.2734920 E
+15.2734920 16.3764390 G#:min
+16.3764390 17.0614280 F#:min
+17.0614280 18.1759860 B
+18.1759860 18.8609750 E
+18.8609750 19.9639220 G#:min
+19.9639220 20.6140810 F#:min
+20.6140810 21.7634690 B
+21.7634690 23.5746250 A
+23.5746250 24.2712240 E
+24.2712240 25.3857820 C#:min
+25.3857820 26.0823800 A
+26.0823800 27.1969380 B:aug
+27.1969380 27.8980695 E
+27.8980695 29.0313150 B
+29.0313150 29.7046930 E
+29.7046930 30.8076410 G#:min
+30.8076410 31.5042400 F#:min
+31.5042400 32.6420180 B
+32.6420180 33.3386160 E
+33.3386160 34.4183440 G#:min
+34.4183440 35.1149430 F#:min
+35.1149430 36.3107700 B
+36.3107700 38.0987070 A
+38.0987070 38.7953060 E
+38.7953060 39.9098630 C#:min
+39.9098630 40.6529020 A
+40.6529020 41.7442400 B:aug
+41.7442400 43.5902260 E
+43.5902260 45.4129930 C#:min
+45.4129930 46.1095910 F#:min
+46.1095910 47.2125390 G#
+47.2125390 49.0120860 C#:min
+49.0120860 49.6854640 F#:min
+49.6854640 50.8232420 G#
+50.8232420 52.6343990 C#:min
+52.6343990 53.3193870 F#:min
+53.3193870 54.4339450 G#
+54.4339450 55.3279130 A
+55.3279130 56.2451020 B
+56.2451020 56.9184800 E:maj6
+56.9184800 58.0678680 B
+58.0678680 58.7180270 E
+58.7180270 59.8674140 G#:min
+59.8674140 60.5291830 F#:min
+60.5291830 61.6785710 B
+61.6785710 62.3519500 E
+62.3519500 63.4781170 G#:min
+63.4781170 64.1747160 F#:min
+64.1747160 65.2892740 B
+65.2892740 67.1004300 A
+67.1004300 67.7738090 E
+67.7738090 68.9464170 C#:min
+68.9464170 69.8519950 A
+69.8519950 70.7691830 B:aug
+70.7691830 72.5222900 E
+72.5222900 74.3450560 C#:min
+74.3450560 75.0068250 F#:min
+75.0068250 76.2026530 G#
+76.2026530 78.0021990 C#:min
+78.0021990 78.6987980 F#:min
+78.6987980 79.8481850 G#
+79.8481850 81.6477320 C#:min
+81.6477320 82.3095010 F#:min
+82.3095010 83.4704980 G#
+83.4704980 84.4109070 A
+84.4109070 85.3280950 B
+85.3280950 86.2220630 E:maj6
+86.2220630 87.1508610 B
+87.1508610 87.7778000 E
+87.7778000 88.9620180 G#:min
+88.9620180 89.6237860 F#:min
+89.6237860 90.7731740 B
+90.7731740 91.4465530 E
+91.4465530 92.6075510 G#:min
+92.6075510 93.2460990 F#:min
+93.2460990 94.4187070 B
+94.4187070 96.2414730 A
+96.2414730 96.9148520 E
+96.9148520 98.0758500 C#:min
+98.0758500 98.7608390 A
+98.7608390 99.8870060 B:aug
+99.8870060 101.7329930 C#:min
+101.7329930 102.4412010 F#:min
+102.4412010 103.5557590 G#
+103.5557590 104.3104080 A
+104.3104080 105.4017460 B
+105.4017460 107.2709520 C#:min
+107.2709520 107.9443310 F#:min
+107.9443310 109.0821080 G#
+109.0821080 109.7670970 A
+109.7670970 110.9397050 B
+110.9397050 114.7799274 E:maj6
+114.7799274 118.6342395 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/05_-_And_I_Love_Her.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,61 @@
+0.0000000 0.4212474 N
+0.4212474 1.2138090 N
+1.2138090 5.1379810 F#:min
+5.1379810 9.2246930 E
+9.2246930 11.2448290 F#:min
+11.2448290 13.2765750 C#:min
+13.2765750 15.3431510 F#:min
+15.3431510 17.3981170 C#:min
+17.3981170 19.4763030 F#:min
+19.4763030 21.5777090 C#:min
+21.5777090 23.6210650 A
+23.6210650 25.6760310 B
+25.6760310 29.8788430 E
+29.8788430 31.9686390 F#:min
+31.9686390 34.0003850 C#:min
+34.0003850 36.1017910 F#:min
+36.1017910 38.2031970 C#:min
+38.2031970 40.2929930 F#:min
+40.2929930 42.3595690 C#:min
+42.3595690 44.4841950 A
+44.4841950 46.5739900 B
+46.5739900 50.8000220 E
+50.8000220 52.9478680 C#:min
+52.9478680 55.0724940 B
+55.0724940 57.1506800 C#:min
+57.1506800 59.2869160 G#:min
+59.2869160 61.3302720 C#:min
+61.3302720 63.4200680 G#:min
+63.4200680 67.6460990 B
+67.6460990 69.8055550 F#:min
+69.8055550 71.9301810 C#:min
+71.9301810 73.9967570 F#:min
+73.9967570 76.1097730 C#:min
+76.1097730 78.2343990 F#:min
+78.2343990 80.3474140 C#:min
+80.3474140 82.4720400 A
+82.4720400 84.5850560 B
+84.5850560 88.7878680 E
+88.7878680 90.9589340 G:min
+90.9589340 92.9790700 D:min
+92.9790700 95.1849650 G:min
+95.1849650 97.2863710 D:min
+97.2863710 99.4226070 G:min
+99.4226070 101.5356230 D:min
+101.5356230 103.6834690 Bb
+103.6834690 105.8080950 C
+105.8080950 110.0805660 F
+110.0805660 112.2284120 G:min
+112.2284120 114.3065980 D:min
+114.3065980 116.4544440 G:min
+116.4544440 118.5326300 D:min
+118.5326300 120.6572560 G:min
+120.6572560 122.7354420 D:min
+122.7354420 124.9065070 Bb
+124.9065070 127.0311330 C
+127.0311330 131.2803850 F
+131.2803850 135.6225170 G:min
+135.6225170 139.8137180 F
+139.8137180 144.1210200 G:min
+144.1210200 147.1493920 D
+147.1493920 150.8448810 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/06_-_Tell_Me_Why.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,99 @@
+0.0000000 0.8655100 N
+0.8655100 1.5272780 E:min
+1.5272780 2.3980270 A
+2.3980270 3.0249650 E:min
+3.0249650 3.8841040 A
+3.8841040 4.5574820 E:min
+4.5574820 5.4166210 A
+5.4166210 6.0667800 E:min
+6.0667800 6.9491380 A
+6.9491380 8.4352150 D
+8.4352150 9.9677320 B:min
+9.9677320 11.5466890 E:min
+11.5466890 13.0675960 A
+13.0675960 13.8222440 D
+13.8222440 14.6001130 B:min
+14.6001130 15.1806120 E:min
+15.1806120 16.1210200 A
+16.1210200 17.6535370 D
+17.6535370 19.2092740 B:min
+19.2092740 20.7417910 E:min
+20.7417910 22.3091380 A
+22.3091380 23.0521760 D
+23.0521760 23.8184350 B:min
+23.8184350 24.4105440 E:min
+24.4105440 25.3625620 A
+25.3625620 26.8834690 D
+26.8834690 28.4043760 B:min
+28.4043760 29.8788430 E:min
+29.8788430 31.4694100 A
+31.4694100 33.0135370 D
+33.0135370 34.5344440 B:min
+34.5344440 36.0785710 E:min
+36.0785710 37.6226980 A
+37.6226980 39.1087750 D
+39.1087750 40.6761220 B:min
+40.6761220 42.2202490 E:min
+42.2202490 43.7875960 A
+43.7875960 44.5654640 D
+44.5654640 45.3433330 B:min
+45.3433330 45.9122220 E:min
+45.9122220 46.8526300 A
+46.8526300 48.3851470 D
+48.3851470 49.9873240 B:min
+49.9873240 51.4966210 E:min
+51.4966210 53.0639680 A
+53.0639680 53.8070060 D
+53.8070060 54.6661450 B:min
+54.6661450 55.2698630 E:min
+55.2698630 56.1870520 A
+56.1870520 57.8008390 D
+57.8008390 59.3449650 B:min
+59.3449650 60.8658730 E:min
+60.8658730 62.4448290 A
+62.4448290 63.9773460 D
+63.9773460 65.5214730 B:min
+65.5214730 67.0772100 E:min
+67.0772100 68.6677770 A
+68.6677770 70.2002940 D
+70.2002940 71.7560310 B:min
+71.7560310 73.2885480 E:min
+73.2885480 74.8675050 A
+74.8675050 75.6685940 D
+75.6685940 76.4464620 B:min
+76.4464620 77.0385710 E:min
+77.0385710 77.9673690 A
+77.9673690 79.5347160 D
+79.5347160 81.1252830 B:min
+81.1252830 82.6926300 E:min
+82.6926300 84.2251470 A
+84.2251470 85.8157140 D
+85.8157140 87.3366210 D:7
+87.3366210 90.4597050 G
+90.4597050 93.6060090 A
+93.6060090 96.7058730 B:min
+96.7058730 98.2964390 E:min
+98.2964390 99.8289560 A
+99.8289560 100.6300450 D
+100.6300450 101.4195230 B:min
+101.4195230 101.6792229 E:min
+101.6792229 102.9404300 N
+102.9404300 104.4729470 D
+104.4729470 106.0751240 B:min
+106.0751240 107.6424710 E:min
+107.6424710 109.2562580 A
+109.2562580 110.0430716 D
+110.0430716 110.7887750 B:min
+110.7887750 111.4041040 E:min
+111.4041040 112.3445120 A
+112.3445120 113.8886390 D
+113.8886390 115.4792060 B:min
+115.4792060 117.0465530 E:min
+117.0465530 118.6719500 A
+118.6719500 120.2392970 B:min
+120.2392970 120.8861124 Bb
+120.8861124 121.7718140 Bb:7
+121.7718140 122.3523120 A:sus4
+122.3523120 123.2114510 A:9(11)
+123.2114510 125.7877610 D
+125.7877610 130.0316126 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/07_-_Can't_Buy_Me_Love.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,65 @@
+0.0000000 0.4595427 N
+0.4595427 1.5504980 C
+1.5504980 2.8508160 E:min
+2.8508160 4.1975730 A:min
+4.1975730 5.4978910 E:min
+5.4978910 6.8214280 A:min
+6.8214280 8.1333560 D:min
+8.1333560 9.5163628 G
+9.5163628 14.9484120 C:7
+14.9484120 17.6535370 F:7
+17.6535370 20.3934920 C:7
+20.3934920 21.8215190 G
+21.8215190 24.6079130 F:7
+24.6079130 26.0127210 C:7
+26.0127210 31.5390700 C:7
+31.5390700 34.3835140 F:7
+34.3835140 37.1002490 C:7
+37.1002490 38.4934460 G
+38.4934460 39.9795230 F:7
+39.9795230 41.2914510 F:7
+41.2914510 42.6962580 C:7
+42.6962580 44.1010650 E:min
+44.1010650 45.4942630 A:min
+45.4942630 48.3038770 C
+48.3038770 49.6970740 E:min
+49.6970740 51.0786620 A:min
+51.0786620 52.4602490 D:min
+52.4602490 53.9347160 G
+53.9347160 59.5307250 C:7
+59.5307250 62.3287300 F:7
+62.3287300 65.1383440 C:7
+65.1383440 66.5199310 G
+66.5199310 67.9943990 F:7
+67.9943990 69.3527660 F:7
+69.3527660 70.8272330 C:7
+70.8272330 72.1856000 C:7
+72.1856000 77.7583900 C:7
+77.7583900 80.5680040 F:7
+80.5680040 83.3776190 C:7
+83.3776190 84.8056460 G
+84.8056460 86.2220630 F:7
+86.2220630 87.6152600 C:7
+87.6152600 89.0548970 C:7
+89.0548970 90.3784350 E:min
+90.3784350 91.7948520 A:min
+91.7948520 94.6044670 C
+94.6044670 96.0092740 E:min
+96.0092740 97.4140810 A:min
+97.4140810 98.8072780 D:min
+98.8072780 100.2353060 G
+100.2353060 105.8777550 C:7
+105.8777550 108.7221990 F:7
+108.7221990 111.5202040 C:7
+111.5202040 112.9366210 G
+112.9366210 114.4110880 F:7
+114.4110880 115.8042850 F:7
+115.8042850 117.2207020 C:7
+117.2207020 118.6022900 E:min
+118.6022900 119.9258270 A:min
+119.9258270 121.2145350 E:min
+121.2145350 122.6425620 A:min
+122.6425620 124.0009290 D:min
+124.0009290 125.4753960 G
+125.4753960 130.1654609 C:7
+130.1654609 132.9035693 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/08_-_Any_Time_At_All.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,79 @@
+0.0000000 0.4403951 N
+0.4403951 1.6549880 N
+1.6549880 3.1178450 B:min
+3.1178450 4.9638320 D
+4.9638320 8.3191150 A
+8.3191150 9.9793420 B:min
+9.9793420 10.8617000 G
+10.8617000 11.6976190 A
+11.6976190 15.0296820 D
+15.0296820 16.7015190 D
+16.7015190 18.3733560 F#:min/5
+18.3733560 20.0800220 B:min
+20.0800220 21.7402490 G:min/b3
+21.7402490 23.4469160 D/5
+23.4469160 25.0839220 A/3
+25.0839220 26.7673690 D
+26.7673690 28.4740360 F#:min/5
+28.4740360 30.1342630 B:min
+30.1342630 31.8060990 G:min/b3
+31.8060990 33.4779360 D/5
+33.4779360 35.1381630 A/3
+35.1381630 38.5282760 D
+38.5282760 40.0840130 B:min
+40.0840130 41.9300000 D
+41.9300000 45.3201130 A
+45.3201130 47.0035600 B:min
+47.0035600 47.8859180 G
+47.8859180 48.7218360 A
+48.7218360 52.1119500 D
+52.1119500 53.8302260 D
+53.8302260 55.5368930 F#:min/5
+55.5368930 57.2435600 B:min
+57.2435600 58.9153960 G:min/b3
+58.9153960 60.6104530 D/5
+60.6104530 62.2822900 A/3
+62.2822900 63.9773460 D
+63.9773460 65.6840130 F#:min/5
+65.6840130 67.3906800 B:min
+67.3906800 69.1321760 G:min/b3
+69.1321760 70.7924030 D/5
+70.7924030 72.4758500 A/3
+72.4758500 74.2057360 D
+74.2057360 75.9588430 D
+75.9588430 77.4217000 B:min
+77.4217000 79.3373460 D
+79.3373460 82.6810200 A
+82.6810200 84.3876870 B:min
+84.3876870 85.3048750 G
+85.3048750 86.1407930 A
+86.1407930 89.5541260 D
+89.5541260 90.4248750 A:7/5
+90.4248750 91.2840130 B:min/5
+91.2840130 93.0139000 A:7/b7
+93.0139000 93.8498180 A:7/5
+93.8498180 94.6857360 B:min/5
+94.6857360 95.8467340 A:7/b7
+95.8467340 96.0673240 A
+96.0673240 96.3575730 G#
+96.3575730 97.4953510 G
+97.4953510 97.7623800 G
+97.7623800 98.0526300 G#
+98.0526300 99.1787980 A
+99.1787980 99.4806570 A
+99.4806570 99.7825170 G#
+99.7825170 101.5124030 G
+101.5124030 103.2190700 A
+103.2190700 106.6440130 D
+106.6440130 108.1533100 B:min
+108.1533100 110.0573460 D
+110.0573460 113.5171200 A
+113.5171200 115.2470060 B:min
+115.2470060 116.1177550 G
+116.1177550 116.9768930 A
+116.9768930 118.7300000 D
+118.7300000 120.4134460 D
+120.4134460 122.1317230 G
+122.1317230 123.8267800 A
+123.8267800 129.0166042 D
+129.0166042 133.2099311 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/09_-_I'll_Cry_Instead.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,42 @@
+0.0000000 0.4403951 N
+0.4403951 3.0249650 G
+3.0249650 10.4205210 G
+10.4205210 12.9050560 D:7
+12.9050560 17.8392970 C:7
+17.8392970 19.1396140 G
+19.1396140 20.2773920 D
+20.2773920 22.7851470 G
+22.7851470 27.7774370 G
+27.7774370 30.2155320 G
+30.2155320 32.7000680 D:7
+32.7000680 37.6807480 C:7
+37.6807480 38.9578450 G
+38.9578450 40.2001130 D
+40.2001130 42.6962580 G
+42.6962580 45.2388430 B:min
+45.2388430 46.4521048 A
+46.4521048 47.7117680 A:7
+47.7117680 50.2195230 D
+50.2195230 51.4734010 E:min
+51.4734010 52.0887300 A
+52.0887300 52.7272780 D
+52.7272780 60.1460540 G
+60.1460540 62.6770290 D:7
+62.6770290 67.6577090 C:7
+67.6577090 68.8999770 G
+68.8999770 70.1190240 D
+70.1190240 72.6616090 G
+72.6616090 75.1577550 B:min
+75.1577550 77.6190700 A
+77.6190700 80.0803850 D
+80.0803850 81.3574820 E:min
+81.3574820 81.9379810 A
+81.9379810 82.6113600 D
+82.6113600 87.4991600 G
+87.4991600 90.0301360 G
+90.0301360 92.4798410 D:7
+92.4798410 97.4489110 C:7
+97.4489110 98.6293453 G
+98.6293453 99.8521760 D
+99.8521760 103.5119861 G
+103.5119861 107.6670178 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/10_-_Things_We_Said_Today.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,46 @@
+0.0000000 0.4020998 N
+0.4020998 4.0466430 A:min
+4.0466430 17.7580270 A:min
+17.7580270 19.4995230 C
+19.4995230 21.2178000 C:9
+21.2178000 22.9360770 F
+22.9360770 24.6775730 Bb
+24.6775730 31.6087300 A:min
+31.6087300 33.3850560 A:min
+33.3850560 47.2938090 A:min
+47.2938090 49.0120860 C
+49.0120860 50.7187520 C:9
+50.7187520 52.4950790 F
+52.4950790 54.1901360 Bb
+54.1901360 59.4030150 A:min
+59.4030150 61.2373920 A
+61.2373920 62.9208390 A
+62.9208390 64.6855550 D
+64.6855550 66.4270520 B
+66.4270520 68.1337180 E:7
+68.1337180 69.8519950 A
+69.8519950 71.5934920 D
+71.5934920 73.3117680 B
+73.3117680 75.0416550 Bb
+75.0416550 89.1361670 A:min
+89.1361670 90.8660540 C
+90.8660540 92.6423800 C:9
+92.6423800 94.3606570 F
+94.3606570 96.1369840 Bb
+96.1369840 101.2221540 A:min
+101.2221540 103.1494100 A
+103.1494100 104.8212470 A
+104.8212470 106.5975730 D
+106.5975730 108.3042400 B
+108.3042400 110.0921760 E:7
+110.0921760 111.7524030 A
+111.7524030 113.4822900 D
+113.4822900 115.2353960 B
+115.2353960 116.9304530 Bb
+116.9304530 131.0249650 A:min
+131.0249650 132.7200220 C
+132.7200220 134.5195690 C:9
+134.5195690 136.2610650 F
+136.2610650 137.9909520 Bb
+137.9909520 153.2191848 A:min
+153.2191848 158.7145492 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/11_-_When_I_Get_Home.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+0.0000000 1.2138090 N
+1.2138090 4.8129020 A
+4.8129020 8.7835140 A
+8.7835140 10.6643310 D:9
+10.6643310 12.5103170 G
+12.5103170 14.3911330 A:min
+14.3911330 16.1790700 G
+16.1790700 18.0714960 C
+18.0714960 19.9639220 F
+19.9639220 21.8447390 C
+21.8447390 23.7255550 F
+23.7255550 25.6063710 C
+25.6063710 27.5104080 F
+27.5104080 31.0398410 G
+31.0398410 34.8014730 A
+34.8014730 38.7720860 A
+38.7720860 40.6645120 D:9
+40.6645120 42.5685480 G
+42.5685480 44.4377550 A:min
+44.4377550 46.2373010 G
+46.2373010 48.1181170 C
+48.1181170 50.0221540 F
+50.0221540 51.8913600 C
+51.8913600 53.8070060 F
+53.8070060 55.7110430 C
+55.7110430 57.6150790 F
+57.6150790 61.1574702 G
+61.1574702 64.8945350 A
+64.8945350 68.9696370 A
+68.9696370 70.8504530 D:9
+70.8504530 72.7544890 G
+72.7544890 76.6090020 A:min
+76.6090020 78.5478680 C
+78.5478680 80.4635140 A:min
+80.4635140 82.3791600 C
+82.3791600 84.2831970 A:min
+84.2831970 86.1872330 F
+86.1872330 88.0796590 G
+88.0796590 90.0185260 F
+90.0185260 91.9690020 G
+91.9690020 93.9426980 A:min
+93.9426980 95.7770740 G
+95.7770740 97.7507700 C
+97.7507700 99.6896370 F
+99.6896370 101.5936730 C
+101.5936730 103.4628790 F
+103.4628790 105.4597950 C
+105.4597950 107.3754420 F
+107.3754420 111.0209750 G
+111.0209750 114.8174370 A
+114.8174370 118.9041490 A
+118.9041490 120.7849650 D:9
+120.7849650 122.7354420 G
+122.7354420 126.6247840 A
+126.6247840 128.5636500 D:9
+128.5636500 130.3399770 G
+130.3399770 134.0524260 C
+134.0524260 138.1691624 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/12_-_You_Can't_Do_That.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+0.0000000 0.4212474 N
+0.4212474 4.0582530 G
+4.0582530 7.7966660 G:7
+7.7966660 15.1573920 G:7
+15.1573920 18.8958040 C:7
+18.8958040 22.6458270 G:7
+22.6458270 24.2131740 D:7
+24.2131740 26.2333100 C:7
+26.2333100 28.0909070 G:7
+28.0909070 29.9252830 D:7
+29.9252830 37.3904980 G:7
+37.3904980 41.1405210 C:7
+41.1405210 44.8905440 G:7
+44.8905440 46.6668700 D:7
+46.6668700 48.5128570 C:7
+48.5128570 52.1816090 G:7
+52.1816090 54.0508160 B
+54.0508160 55.9200220 E:min
+55.9200220 56.8488200 A:min
+56.8488200 57.7892290 B:min
+57.7892290 59.6352150 G
+59.6352150 61.4463710 B
+61.4463710 63.3736280 E:min
+63.3736280 65.2660540 A:min
+65.2660540 66.0439220 B:min
+66.0439220 67.2049200 D
+67.2049200 74.6469160 G:7
+74.6469160 78.3969380 C:7
+78.3969380 82.1237410 G:7
+82.1237410 83.9232870 D:7
+83.9232870 85.7808840 C:7
+85.7808840 87.6194688 G:7
+87.6194688 89.4612470 D:7
+89.4612470 96.9845120 G:7
+96.9845120 100.6416550 C:7
+100.6416550 104.3452380 G:7
+104.3452380 106.2144440 D:7
+106.2144440 108.0952600 C:7
+108.0952600 111.7756230 G:7
+111.7756230 113.7144890 B
+113.7144890 115.4983907 E:min
+115.4983907 116.5124940 A:min
+116.5124940 117.4412920 B:min
+117.4412920 119.3104980 G
+119.3104980 121.1913150 B
+121.1913150 123.1417910 E:min
+123.1417910 125.0226070 A:min
+125.0226070 125.7424260 B:min
+125.7424260 126.9846930 D
+126.9846930 134.5427890 G:7
+134.5427890 138.3044210 C:7
+138.3044210 142.0776640 G:7
+142.0776640 143.8656000 D:7
+143.8656000 145.8044670 C:7
+145.8044670 148.5280201 G
+148.5280201 149.0900900 F
+149.0900900 150.4236336 F#
+150.4236336 152.8170850 G
+152.8170850 157.4316593 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/13_-_I'll_Be_Back.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,68 @@
+0.0000000 0.4212474 N
+0.4212474 1.1488567 F#:(1,4,b7)
+1.1488567 4.9975265 A
+4.9975265 7.0536280 A:min
+7.0536280 8.8996140 G
+8.8996140 10.8733100 F
+10.8733100 12.7425170 E
+12.7425170 16.5389790 A
+16.5389790 18.4778450 A:min
+18.4778450 20.3470520 G
+20.3470520 22.2510880 F
+22.2510880 24.1435140 E
+24.1435140 27.9748070 A
+27.9748070 31.7712690 F#:min
+31.7712690 35.5445120 B:min
+35.5445120 36.5197500 E
+36.5197500 37.2803990 D
+37.2803990 38.4702260 E
+38.4702260 39.2016550 D
+39.2016550 40.4090920 E
+40.4090920 42.3827890 A:min
+42.3827890 44.2171650 G
+44.2171650 46.1676410 F
+46.1676410 48.0368480 E
+48.0368480 51.9378000 A
+51.9378000 53.8766660 A:min
+53.8766660 55.7807020 G
+55.7807020 57.6731290 F
+57.6731290 59.6003850 E
+59.6003850 61.5508610 A
+61.5508610 63.4897270 A
+63.4897270 67.3674600 B:min
+67.3674600 71.1987520 C#:min
+71.1987520 73.1376190 F#:min
+73.1376190 75.0880950 B
+75.0880950 76.9689110 D
+76.9689110 77.9557590 E
+77.9557590 78.6871880 D
+78.6871880 79.8946250 E
+79.8946250 80.6608840 D
+80.6608840 81.8218820 E
+81.8218820 83.7491380 A:min
+83.7491380 85.7228340 G
+85.7228340 87.6268700 F
+87.6268700 89.5657360 E
+89.5657360 91.5510430 A
+91.5510430 93.4666890 A
+93.4666890 95.3823350 A:min
+95.3823350 97.3328110 G
+97.3328110 99.3297270 F
+99.3297270 101.2221540 E
+101.2221540 103.1842400 A
+103.1842400 105.1463260 A
+105.1463260 109.0588880 F#:min
+109.0588880 112.9482310 B:min
+112.9482310 113.9118590 E
+113.9118590 114.6432870 D
+114.6432870 115.8275050 E
+115.8275050 116.6402040 D
+116.6402040 117.8128110 E
+117.8128110 119.7748970 A:min
+119.7748970 121.7137640 G
+121.7137640 123.6874600 F
+123.6874600 125.5798860 E
+125.5798860 131.2687750 A
+131.2687750 135.2161670 A:min
+135.2161670 139.0939000 A
+139.0939000 140.3136948 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+/.DS_Store/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/01_-_A_Hard_Day's_Night.lab/1.2/Thu Jul 27 22:30:52 2006//
+/02_-_I_Should_Have_Known_Better.lab/1.3/Tue Oct 17 21:53:05 2006//
+/03_-_If_I_Fell.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/04_-_I'm_Happy_Just_To_Dance_With_You.lab/1.2/Fri Apr 21 15:20:15 2006//
+/05_-_And_I_Love_Her.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/06_-_Tell_Me_Why.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/07_-_Can't_Buy_Me_Love.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/08_-_Any_Time_At_All.lab/1.2/Thu Jul 27 21:47:55 2006//
+/09_-_I'll_Cry_Instead.lab/1.2/Thu Jul 27 21:47:55 2006//
+/10_-_Things_We_Said_Today.lab/1.2/Thu Jul 27 21:47:55 2006//
+/11_-_When_I_Get_Home.lab/1.2/Thu Jul 27 21:47:55 2006//
+/12_-_You_Can't_Do_That.lab/1.2/Thu Jul 27 21:47:55 2006//
+/13_-_I'll_Be_Back.lab/1.4/Tue Oct 17 21:53:05 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/03final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/03final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/01_-_No_Reply.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+0.0000000 1.1105610 N
+1.1105610 2.3591530 C
+2.3591530 4.2316221 F
+4.2316221 6.2136650 G
+6.2136650 10.0333480 C:maj6
+10.0333480 11.9954340 F
+11.9954340 13.9110800 G
+13.9110800 17.5200640 C:maj6
+17.5200640 19.4026000 A:min
+19.4026000 21.2950260 E:min
+21.2950260 23.1294020 F:maj7
+23.1294020 25.3004680 E:min
+25.3004680 27.2509440 D:min
+27.2509440 29.1665900 G
+29.1665900 33.0327130 C:maj6
+33.0327130 34.9367490 F
+34.9367490 36.8523950 G
+36.8523950 40.7069080 C:maj6
+40.7069080 42.6806040 F
+42.6806040 44.5564910 G
+44.5564910 48.1721230 C:maj6
+48.1721230 50.0297200 A:min
+50.0297200 51.9569760 E:min
+51.9569760 53.8145720 F:maj7
+53.8145720 55.9159780 E:min
+55.9159780 57.8432340 F
+57.8432340 59.7821010 G
+59.7821010 63.7062730 C:maj6
+63.7062730 65.6219190 C
+65.6219190 67.5143460 E
+67.5143460 71.3688580 A
+71.3688580 73.2612840 D:min
+73.2612840 75.1885410 F
+75.1885410 78.9850030 C
+78.9850030 80.9006490 C
+80.9006490 82.7930760 E
+82.7930760 86.6243680 A
+86.6243680 88.5516240 D:min
+88.5516240 90.4440510 F
+90.4440510 94.2985630 C
+94.2985630 96.2606490 F
+96.2606490 98.1879060 G
+98.1879060 102.0656380 C:maj6
+102.0656380 103.9928940 F
+103.9928940 105.9433710 G
+105.9433710 109.5772930 C:maj6
+109.5772930 111.4465000 A:min
+111.4465000 113.3273160 E:min
+113.3273160 115.2313520 F:maj7
+115.2313520 117.3443680 E:min
+117.3443680 119.3412840 F
+119.3412840 121.2104910 G
+121.2104910 124.8444140 C:maj6
+124.8444140 126.7368400 A:min
+126.7368400 128.6292660 E:min
+128.6292660 130.4288130 F:maj7
+130.4288130 133.3631120 C:maj9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/02_-_I'm_a_Loser.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,116 @@
+0.0000000 0.4403950 N
+0.4403950 1.1488567 D
+1.1488567 2.8338465 A:min7
+2.8338465 5.0089350 D
+5.0089350 6.9314353 A:min7
+6.9314353 8.7696059 D
+8.7696059 10.0907910 A:min
+10.0907910 10.7790930 F
+10.7790930 11.4989120 D
+11.4989120 12.7992290 G
+12.7992290 14.0763270 D
+14.0763270 15.3882540 F
+15.3882540 16.7350120 G
+16.7350120 18.0585490 G
+18.0585490 19.3820870 D
+19.3820870 20.6940140 F
+20.6940140 22.0407710 G
+22.0407710 23.3643090 G
+23.3643090 24.6530160 D
+24.6530160 25.9997740 F
+25.9997740 27.3233110 G
+27.3233110 28.6584580 G
+28.6584580 29.9936060 D
+29.9936060 31.2358730 F
+31.2358730 32.5826310 G
+32.5826310 33.9409980 A:min7
+33.9409980 35.2761450 D
+35.2761450 36.6112930 A:min7
+36.6112930 37.9928800 D
+37.9928800 39.3396380 G
+39.3396380 40.6515650 E:min
+40.6515650 42.0099320 A:min
+42.0099320 42.6833110 F
+42.6833110 43.3450800 D
+43.3450800 44.6453970 G
+44.6453970 46.0269840 D
+46.0269840 47.3273020 F
+47.3273020 48.6740590 G
+48.6740590 49.9975970 G
+49.9975970 51.3211340 D
+51.3211340 52.6446720 F
+52.6446720 54.0030390 G
+54.0030390 55.3381860 G
+55.3381860 56.6385040 D
+56.6385040 57.9504310 F
+57.9504310 59.3087990 G
+59.3087990 60.6555560 G
+60.6555560 61.9674830 D
+61.9674830 63.2910210 F
+63.2910210 64.6493880 G
+64.6493880 65.9613160 A:min7
+65.9613160 67.2848530 D
+67.2848530 68.6200000 A:min7
+68.6200000 69.9435380 D
+69.9435380 71.2786850 G
+71.2786850 72.6022230 E:min
+72.6022230 73.9257600 A:min
+73.9257600 74.6223590 F
+74.6223590 75.3073470 D
+75.3073470 76.6308850 G
+76.6308850 77.9776420 D
+77.9776420 79.3360090 F
+79.3360090 80.6595470 G
+80.6595470 82.0063040 G
+82.0063040 83.3530620 D
+83.3530620 84.7346490 F
+84.7346490 86.0930160 G
+86.0930160 87.4049440 A:min
+87.4049440 88.7517010 D
+88.7517010 90.0868480 A:min
+90.0868480 91.4452160 D
+91.4452160 92.8500230 G
+92.8500230 94.1735600 E:min
+94.1735600 95.5087080 A:min
+95.5087080 96.0635654 F
+96.0635654 96.8786850 D:7
+96.8786850 98.2370530 G
+98.2370530 99.5722000 D
+99.5722000 100.9653970 F
+100.9653970 102.3121550 G
+102.3121550 103.6473020 G
+103.6473020 105.0056690 D
+105.0056690 106.3408170 F
+106.3408170 107.6875740 G
+107.6875740 109.0575510 G
+109.0575510 110.3578690 D
+110.3578690 111.7046260 F
+111.7046260 113.0513840 G
+113.0513840 114.3865310 G
+114.3865310 115.7216780 D
+115.7216780 117.0219960 F
+117.0219960 118.3571430 G
+118.3571430 119.6806810 A:min7
+119.6806810 121.0042180 D
+121.0042180 122.3161450 A:min7
+122.3161450 123.6396830 D
+123.6396830 125.0096600 G
+125.0096600 126.3448080 E:min
+126.3448080 127.7147850 A:min
+127.7147850 128.3881640 F
+128.3881640 129.0615420 D
+129.0615420 130.4083000 G
+130.4083000 131.7086170 D
+131.7086170 133.1250340 F
+133.1250340 134.3789120 G
+134.3789120 135.6560090 G
+135.6560090 136.9911570 D
+136.9911570 138.3379140 F
+138.3379140 139.6846720 G
+139.6846720 140.9849890 A:min
+140.9849890 142.3317460 D:maj6
+142.3317460 143.6436740 A:min
+143.6436740 144.9788210 D:maj6
+144.9788210 146.3720190 G
+146.3720190 147.7187760 E:min
+147.7187760 149.7853520 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/03_-_Baby's_In_Black.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,83 @@
+0.0000000 0.4212470 N
+0.4212470 1.2742550 A
+1.2742550 2.1662340 E
+2.1662340 3.9532110 A
+3.9532110 5.7468920 A
+5.7468920 7.5058640 E
+7.5058640 9.3054100 D:7
+9.3054100 11.0701270 E
+11.0701270 11.9640950 A
+11.9640950 12.8000130 D
+12.8000130 13.7237310 A
+13.7237310 14.5415100 E
+14.5415100 16.3294460 A
+16.3294460 18.1173830 A
+18.1173830 18.9545500 A
+18.9545500 19.8821000 A:7/3
+19.8821000 21.6584260 D
+21.6584260 23.4115330 D
+23.4115330 24.3403310 A
+24.3403310 25.2110790 E
+25.2110790 26.9990160 A
+26.9990160 28.7521220 A
+28.7521220 30.4820090 E
+30.4820090 32.3047750 D:7
+32.3047750 34.0811020 E
+34.0811020 34.9750700 A
+34.9750700 35.8109880 D
+35.8109880 37.5989250 A
+37.5989250 39.3752510 A
+39.3752510 41.1747980 A
+41.1747980 42.0107160 A
+42.0107160 42.8930750 A:7/3
+42.8930750 44.7158410 D
+44.7158410 46.4573380 D
+46.4573380 47.3861360 A
+47.3861360 48.2336640 E
+48.2336640 49.9983810 A
+49.9983810 51.7979270 F#:min7
+51.7979270 53.5510340 B
+53.5510340 55.3748916 D
+55.3748916 57.0572470 E
+57.0572470 58.9032330 A
+58.9032330 60.6795600 E
+60.6795600 62.4326660 D:7
+62.4326660 64.2322130 E
+64.2322130 65.1610110 A
+65.1610110 66.0433690 D
+66.0433690 67.8313060 A
+67.8313060 69.6656820 A
+69.6656820 71.4187890 E
+71.4187890 73.1486760 D:7
+73.1486760 74.9366120 E
+74.9366120 75.8654100 A
+75.8654100 76.7709880 D
+76.7709880 78.5357050 A
+78.5357050 80.3468610 F#:min7
+80.3468610 82.1347980 B
+82.1347980 83.9343440 D
+83.9343440 85.6990610 E
+85.6990610 87.5334370 A
+87.5334370 89.3213740 E
+89.3213740 91.0744800 D:7
+91.0744800 92.9669070 E
+92.9669070 93.8957050 A
+93.8957050 94.7316230 D
+94.7316230 96.5195600 A
+96.5195600 98.3539360 A
+98.3539360 100.2579730 A
+100.2579730 101.1287210 A
+101.1287210 102.0342990 A:7
+102.0342990 103.8802850 D
+103.8802850 105.6798320 D
+105.6798320 106.5970200 A
+106.5970200 107.4561580 E
+107.4561580 109.2789250 A
+109.2789250 111.0320320 A
+111.0320320 112.8547980 E
+112.8547980 114.7123940 D:7
+114.7123940 116.5583810 E
+116.5583810 117.4755690 A
+117.4755690 118.4043670 D
+118.4043670 120.1923040 A
+120.1923040 122.9016570 A
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/04_-_Rock_and_Roll_Music.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,55 @@
+0.000000 0.446618 N
+0.446618 2.408196 E:7
+2.408196 8.085475 A
+8.085475 10.953139 D
+10.953139 13.878853 A
+13.878853 18.139715 E
+18.139715 19.672232 A
+19.672232 21.111869 E
+21.111869 22.597946 A
+22.597946 25.477221 E
+25.477221 28.356495 A
+28.356495 31.200939 D
+31.200939 32.640577 E
+32.640577 34.103434 E
+34.103434 39.861982 A
+39.861982 42.776087 D
+42.776087 45.655361 A
+45.655361 49.974273 E
+49.974273 51.448740 A
+51.448740 52.911597 E
+52.911597 54.386064 A
+54.386064 57.230509 E
+57.230509 60.040123 A
+60.040123 62.884568 D
+62.884568 65.729012 E
+65.729012 71.429511 A
+71.429511 74.308785 D
+74.308785 77.141620 A
+77.141620 81.344431 E
+81.344431 82.784069 A
+82.784069 84.200486 E
+84.200486 85.767833 A
+85.767833 88.612277 E
+88.612277 91.433502 A
+91.433502 94.196676 D
+94.196676 97.017901 E
+97.017901 102.764840 A
+102.764840 105.632504 D
+105.632504 108.511778 A
+108.511778 112.726200 E
+112.726200 114.258717 A
+114.258717 115.605475 E
+115.605475 117.114772 A
+117.114772 119.994046 E
+119.994046 122.815270 A
+122.815270 125.601665 D
+125.601665 127.064522 E
+127.064522 128.446109 E:7
+128.446109 134.158218 A
+134.158218 137.037493 D
+137.037493 139.916767 A
+139.916767 144.200849 E
+144.200849 145.640486 A
+145.640486 147.080123 E
+147.080123 149.136676 A
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/05_-_I'll_Follow_the_Sun.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,77 @@
+0.000000 0.446041 N
+0.446041 1.323560 C
+1.323560 2.252358 G
+2.252358 3.146326 F
+3.146326 4.075124 C
+4.075124 5.805011 G
+5.805011 7.534897 F:7
+7.534897 9.334444 C
+9.334444 11.064331 D
+11.064331 11.946689 C
+11.946689 12.852267 E:min/5
+12.852267 13.723015 D
+13.723015 14.593764 G
+14.593764 15.522562 C
+15.522562 16.393310 G
+16.393310 17.298888 F
+17.298888 18.204467 C
+18.204467 20.027233 G
+20.027233 21.780340 F:7
+21.780340 23.591496 C
+23.591496 25.356213 D
+25.356213 26.203741 C
+26.203741 27.144149 E:min/5
+27.144149 28.049727 D
+28.049727 28.908866 G
+28.908866 30.731632 C
+30.731632 32.566009 C:7
+32.566009 34.365555 D:min
+34.365555 36.199931 F:min
+36.199931 37.987868 C
+37.987868 39.740975 C:7
+39.740975 41.552131 D:min
+41.552131 43.351678 F:min
+43.351678 45.139614 C
+45.139614 46.962380 D:min
+46.962380 48.773537 G
+48.773537 50.538253 F:7
+50.538253 52.361020 C
+52.361020 54.102517 D
+54.102517 55.019705 C
+55.019705 55.913673 E:min/5
+55.913673 56.830861 D
+56.830861 57.748049 G
+57.748049 58.676848 C
+58.676848 59.570816 G
+59.570816 60.464784 F
+60.464784 61.381972 C
+61.381972 63.181519 G
+63.181519 64.957845 F:7
+64.957845 66.745782 C
+66.745782 68.498888 D
+68.498888 69.427687 C
+69.427687 70.321655 E:min/5
+70.321655 71.215623 D
+71.215623 72.097981 G
+72.097981 73.932358 C
+73.932358 75.743514 C:7
+75.743514 77.566281 D:min
+77.566281 79.389047 F:min
+79.389047 81.188594 C
+81.188594 82.953310 C:7
+82.953310 84.776077 D:min
+84.776077 86.598843 F:min
+86.598843 88.410000 C
+88.410000 90.244376 D:min
+90.244376 92.032312 G
+92.032312 93.843469 F:7
+93.843469 95.666235 C
+95.666235 97.419342 D
+97.419342 98.301700 C
+98.301700 99.218888 E:min/5
+99.218888 100.089637 D
+100.089637 100.995215 G
+100.995215 101.924013 C
+101.924013 102.829591 G
+102.829591 103.723560 F
+103.723560 106.537309 C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/06_-_Mr._Moonlight.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,99 @@
+0.0000000 0.4403951 N
+0.4403951 5.6653020 F#
+5.6653020 6.5692830 F#
+6.5692830 7.4980810 F#:sus4
+7.4980810 8.4552950 F#
+8.4552950 9.3324570 F#:sus4
+9.3324570 10.2960850 F#
+10.2960850 11.2016640 F#:sus4
+11.2016640 12.1304620 F#
+12.1304620 13.0824800 F#:sus4
+13.0824800 14.0112780 F#
+14.0112780 14.9284660 F#:sus4
+14.9284660 15.8804840 F#
+15.8804840 16.8208930 F#
+16.8208930 20.5476950 B
+20.5476950 21.5229330 F#
+21.5229330 22.4517320 F#:sus4
+22.4517320 23.3457000 F#
+23.3457000 24.3093280 F#:sus4
+24.3093280 31.8325930 D#:min
+31.8325930 35.5942260 B
+35.5942260 36.5578540 F#
+36.5578540 37.4866520 F#:sus4
+37.4866520 39.4255180 F#
+39.4255180 43.1639310 B
+43.1639310 45.0215280 F#
+45.0215280 46.9255640 D#:7
+46.9255640 48.8063800 G#
+48.8063800 50.8149060 C#:7
+50.8149060 51.7901440 F#
+51.7901440 52.7305520 F#:sus4
+52.7305520 53.6825710 F#
+53.6825710 54.5997590 F#:sus4
+54.5997590 55.5866070 F#
+55.5866070 56.5037950 F#:sus4
+56.5037950 57.5022530 F#
+57.5022530 58.4194410 F#:sus4
+58.4194410 59.3830690 F#
+59.3830690 60.3583080 F#:sus4
+60.3583080 61.2987160 F#
+61.2987160 62.2507340 F#:sus4
+62.2507340 63.1795320 F#
+63.1795320 64.1779900 F#:sus4
+64.1779900 65.1067880 F#
+65.1067880 66.0704160 F#:sus4
+66.0704160 67.0224350 F#
+67.0224350 67.9744530 F#:sus4
+67.9744530 69.9481490 F#
+69.9481490 73.7446110 B
+73.7446110 75.6486480 F#
+75.6486480 77.5875140 D#:7
+77.5875140 79.4683300 G#
+79.4683300 81.4768560 C#:7
+81.4768560 82.4404840 F#
+82.4404840 83.3808930 F#:sus4
+83.3808930 84.3329110 F#
+84.3329110 85.2849290 F#:sus4
+85.2849290 100.5520490 F#
+100.5520490 102.4676950 B
+102.4676950 104.3369020 B
+104.3369020 106.2409380 F#
+106.2409380 108.0985340 D#:7
+108.0985340 110.0374010 G#
+110.0374010 112.0343170 C#:7
+112.0343170 112.9747250 F#
+112.9747250 113.9383530 F#:sus4
+113.9383530 114.9019810 F#
+114.9019810 115.8307790 F#:sus4
+115.8307790 116.7827970 F#
+116.7827970 117.7232060 F#:sus4
+117.7232060 118.6752240 F#
+118.6752240 119.6388520 F#:sus4
+119.6388520 120.5676500 F#
+120.5676500 121.5196680 F#:sus4
+121.5196680 122.4600760 F#
+122.4600760 123.4353140 F#:sus4
+123.4353140 124.3989430 F#
+124.3989430 125.3857910 F#:sus4
+125.3857910 126.3029790 F#
+126.3029790 127.2549970 F#:sus4
+127.2549970 128.2186250 F#
+128.2186250 129.1474230 F#:sus4
+129.1474230 131.0862890 F#
+131.0862890 134.8014820 B
+134.8014820 136.7055180 F#
+136.7055180 138.6095550 D#:7
+138.6095550 140.5019810 G#
+140.5019810 142.5221170 C#:7
+142.5221170 143.5321850 F#
+143.5321850 144.4493730 F#:sus4
+144.4493730 145.3549520 F#
+145.3549520 146.3534100 F#:sus4
+146.3534100 147.3170380 F#
+147.3170380 148.2690560 F#:sus4
+148.2690560 149.2210740 F#
+149.2210740 150.1847020 F#:sus4
+150.1847020 151.1483300 F#
+151.1483300 152.1583980 F#:sus4
+152.1583980 153.0755860 F#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/07_-_Kansas_City-_Hey,_Hey,_Hey,_Hey.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,61 @@
+0.000000 0.439592 N
+0.439592 1.108536 D
+1.108536 2.841419 G:7
+2.841419 4.606135 C:7
+4.606135 6.599499 G:7
+6.599499 6.812031 C
+6.812031 7.102281 C#
+7.102281 8.158789 D:7
+8.158789 15.298925 G
+15.298925 18.956067 C
+18.956067 22.589990 G
+22.589990 24.401147 D
+24.401147 26.189083 C
+26.189083 28.202000 G
+28.202000 28.461467 C
+28.461467 28.800769 C#
+28.800769 29.788176 D
+29.788176 37.079242 G
+37.079242 40.713165 C
+40.713165 44.370308 G
+44.370308 46.169854 D
+46.169854 47.981011 C
+47.981011 50.094027 G
+50.094027 50.268176 C
+50.268176 50.593256 C#
+50.593256 51.614934 D:7
+51.614934 58.882779 G
+58.882779 62.493482 C
+62.493482 66.150625 G
+66.150625 68.019832 D
+68.019832 69.830988 C
+69.830988 71.632681 G
+71.632681 73.499741 D
+73.499741 80.802417 G
+80.802417 84.447950 C
+84.447950 88.105092 G
+88.105092 89.904639 D
+89.904639 91.750625 C
+91.750625 93.567570 G
+93.567570 95.419378 D:7
+95.419378 102.768494 G
+102.768494 106.460467 C
+106.460467 110.129219 G
+110.129219 111.986816 D
+111.986816 113.786362 C
+113.786362 115.642172 G
+115.642172 115.921597 D
+115.921597 116.154798 C
+116.154798 116.421827 C#
+116.421827 117.358642 D
+117.358642 124.723496 G
+124.723496 128.426544 C
+128.426544 132.106906 G
+132.106906 133.918063 D
+133.918063 135.729219 C
+135.729219 137.577061 G
+137.577061 137.868975 D
+137.868975 138.088131 C
+138.088131 138.364684 C#
+138.364684 139.397972 D
+139.397972 144.682448 G
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/08_-_Eight_Days_a_Week.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,101 @@
+0.000000 0.414094 N
+0.414094 1.329503 D
+1.329503 1.770682 D:maj6
+1.770682 2.258301 D
+2.258301 3.117439 E/b7
+3.117439 3.593448 E:maj6/b7
+3.593448 3.999798 E/b7
+3.999798 4.893766 G/5
+4.893766 5.323335 G:maj6/5
+5.323335 5.764514 G/5
+5.764514 6.623653 D
+6.623653 7.064832 D:maj6
+7.064832 7.494401 D
+7.494401 9.212677 D
+9.212677 10.919344 E
+10.919344 12.660841 G
+12.660841 14.425557 D
+14.425557 16.143834 D
+16.143834 17.908550 E
+17.908550 19.638437 G
+19.638437 21.310274 D
+21.310274 23.133040 B:min
+23.133040 24.828097 G
+24.828097 26.534764 B:min
+26.534764 28.241430 E
+28.241430 29.948097 D
+29.948097 31.654764 E
+31.654764 33.349820 G
+33.349820 35.114537 D
+35.114537 36.867643 D
+36.867643 38.574310 E
+38.574310 40.315807 G
+40.315807 42.045693 D
+42.045693 43.763970 D
+43.763970 45.505467 E
+45.505467 47.223743 G
+47.223743 48.930410 D
+48.930410 50.671906 B:min
+50.671906 52.378573 G
+52.378573 54.027190 B:min
+54.027190 55.780296 E
+55.780296 57.521793 D
+57.521793 59.205240 E
+59.205240 60.888687 G
+60.888687 62.630183 D
+62.630183 66.101566 A
+66.101566 69.665829 B:min
+69.665829 73.125603 E
+73.125603 74.843879 G
+74.843879 76.608596 A:7
+76.608596 78.292043 D
+78.292043 80.010319 E
+80.010319 81.728596 G
+81.728596 83.481702 D
+83.481702 85.223199 D
+85.223199 86.906646 E
+86.906646 88.648142 G
+88.648142 90.389639 D
+90.389639 92.096306 B:min
+92.096306 93.814582 G
+93.814582 95.544469 B:min
+95.544469 97.274355 E
+97.274355 98.981022 D
+98.981022 100.699299 E
+100.699299 102.417575 G
+102.417575 104.170682 D
+104.170682 107.618845 A
+107.618845 111.183108 B:min
+111.183108 114.642882 E
+114.642882 116.384378 G
+116.384378 118.114265 A:7
+118.114265 119.832541 D
+119.832541 121.550818 E
+121.550818 123.303925 G
+123.303925 125.068641 D
+125.068641 126.786918 D
+126.786918 128.563244 E
+128.563244 130.339571 G
+130.339571 132.081067 D
+132.081067 133.776124 B:min
+133.776124 135.506011 G
+135.506011 137.189457 B:min
+137.189457 138.919344 E
+138.919344 140.660841 D
+140.660841 142.379117 E
+142.379117 144.085784 G
+144.085784 145.815671 D
+145.815671 147.510727 G
+147.510727 149.240614 D
+149.240614 150.970501 G
+150.970501 152.711997 D
+152.711997 153.582745 D
+153.582745 154.058755 D:maj6
+154.058755 154.511544 D
+154.511544 155.370682 E/b7
+155.370682 155.858301 E:maj6/b7
+155.858301 156.311090 E/b7
+156.311090 157.158618 G/5
+157.158618 157.599798 G:maj6/5
+157.599798 158.075807 G/5
+158.075807 161.214817 D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/09_-_Words_of_Love.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,101 @@
+0.000000 0.426857 N
+0.426857 0.656213 E
+0.656213 2.557446 A
+2.557446 3.509465 D
+3.509465 4.461483 E
+4.461483 6.319079 A
+6.319079 7.282707 D
+7.282707 8.269555 E
+8.269555 10.161982 A
+10.161982 11.137220 D
+11.137220 12.089238 E
+12.089238 14.062934 A
+14.062934 15.014952 D
+15.014952 15.966970 E
+15.966970 17.894226 A
+17.894226 18.881075 D
+18.881075 19.856313 E
+19.856313 21.771959 A
+21.771959 22.747197 D
+22.747197 23.734045 E
+23.734045 25.672911 A
+25.672911 26.636539 D
+26.636539 27.623387 E
+27.623387 29.550644 A
+29.550644 30.537492 D
+30.537492 31.512730 E
+31.512730 33.463206 A
+33.463206 34.450054 D
+34.450054 35.436902 E
+35.436902 37.364158 A
+37.364158 38.362617 D
+38.362617 39.361075 E
+39.361075 41.299941 A
+41.299941 42.321619 D
+42.321619 43.296857 E
+43.296857 45.247333 A
+45.247333 46.269011 D
+46.269011 47.197809 E
+47.197809 49.194725 A
+49.194725 50.158353 D
+50.158353 51.145202 E
+51.145202 53.142118 A
+53.142118 54.140576 D
+54.140576 55.115814 E
+55.115814 57.077900 A
+57.077900 58.064748 D
+58.064748 59.063206 E
+59.063206 61.066477 A
+61.066477 62.025456 D
+62.025456 62.964158 E
+62.964158 64.914635 A
+64.914635 65.901483 D
+65.901483 66.888331 E
+66.888331 68.838807 A
+68.838807 69.790825 D
+69.790825 70.800893 E
+70.800893 72.751369 A
+72.751369 73.726607 D
+73.726607 74.725065 E
+74.725065 76.752649 A
+76.752649 77.745879 D
+77.745879 78.660848 E
+78.660848 80.611324 A
+80.611324 81.621392 D
+81.621392 82.585020 E
+82.585020 84.547106 A
+84.547106 85.522344 D
+85.522344 86.520802 E
+86.520802 88.482889 A
+88.482889 89.492957 D
+89.492957 90.479805 E
+90.479805 92.453501 A
+92.453501 93.417129 D
+93.417129 94.427197 E
+94.427197 96.412503 A
+96.412503 97.387741 D
+97.387741 98.409419 E
+98.409419 100.406335 A
+100.406335 101.393183 D
+101.393183 102.356812 E
+102.356812 104.353728 A
+104.353728 105.352186 D
+105.352186 106.350644 E
+106.350644 108.347560 A
+108.347560 109.311188 D
+109.311188 110.309646 E
+110.309646 112.318172 A
+112.318172 113.305020 D
+113.305020 114.303478 E
+114.303478 116.323614 A
+116.323614 117.322072 D
+117.322072 118.285700 E
+118.285700 120.282617 A
+120.282617 121.292685 D
+121.292685 122.256313 E
+122.256313 124.241619 A
+124.241619 125.251687 D
+125.251687 126.226925 E
+126.226925 128.258671 A
+128.258671 129.245519 D
+129.245519 133.024226 E
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/10_-_Honey_Don't.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+0.000000 0.440395 N
+0.440395 1.900495 E/5
+1.900495 3.398182 E/#4
+3.398182 4.837819 E/4
+4.837819 7.659045 E
+7.659045 10.526708 E
+10.526708 13.405983 C
+13.405983 16.320087 E
+16.320087 19.199361 C
+19.199361 22.125076 B:9
+22.125076 25.015960 E
+25.015960 30.820949 E
+30.820949 33.711833 A
+33.711833 36.625937 E
+36.625937 39.516821 B:9
+39.516821 42.407706 E
+42.407706 45.368251 E
+45.368251 48.259135 C
+48.259135 51.138410 E
+51.138410 54.075733 C
+54.075733 57.001447 B:9
+57.001447 59.927161 E
+59.927161 65.836641 E
+65.836641 68.715914 A
+68.715914 71.630020 E
+71.630020 74.590564 B:9
+74.590564 77.504667 E
+77.504667 80.465211 E
+80.465211 83.390927 C
+83.390927 86.339861 E
+86.339861 88.021569 C
+88.021569 89.277185 B
+89.277185 92.226118 E
+92.226118 95.186663 E
+95.186663 98.135598 A
+98.135598 101.084531 E
+101.084531 104.068296 B:9
+104.068296 106.959181 E
+106.959181 109.931335 E
+109.931335 112.880268 C
+112.880268 115.829202 E
+115.829202 118.801356 C
+118.801356 121.738681 B:9
+121.738681 124.722446 E
+124.722446 127.694600 E
+127.694600 130.620314 E
+130.620314 133.546029 A
+133.546029 136.564623 E
+136.564623 139.525167 B:9
+139.525167 142.508930 E
+142.508930 145.504304 E
+145.504304 148.406800 C
+148.406800 151.367344 E
+151.367344 152.663904 C
+152.663904 154.293058 B:9
+154.293058 157.265211 E
+157.265211 160.190926 E
+160.190926 163.151470 A
+163.151470 166.112014 E
+166.112014 169.060948 B:9
+169.060948 170.624363 E
+170.624363 171.232014 B:7
+171.232014 171.677482 E
+171.677482 176.119728 E
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/11_-_Every_Little_Thing.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,96 @@
+0.000000 0.420489 N
+0.420489 1.921537 A
+1.921537 2.385936 D
+2.385936 3.744303 E
+3.744303 5.694779 A
+5.694779 6.194008 D
+6.194008 7.645256 E
+7.645256 9.618952 A
+9.618952 10.129791 G
+10.129791 11.062412 D
+11.062412 11.312776 D/7
+11.312776 11.569428 A/3
+11.569428 12.567886 B:min
+12.567886 13.508294 D/5
+13.508294 14.448702 E/3
+14.448702 15.423940 A
+15.423940 17.444076 A
+17.444076 17.908476 D
+17.908476 19.382943 E
+19.382943 21.321809 A
+21.321809 21.797818 G
+21.797818 22.756186 D
+22.756186 23.019645 D/7
+23.019645 23.272285 A/3
+23.272285 24.270743 B:min
+24.270743 25.234371 D/5
+25.234371 26.232829 E/3
+26.232829 27.184847 A
+27.184847 29.112104 A
+29.112104 31.050970 G
+31.050970 32.989836 G
+32.989836 34.882262 A
+34.882262 36.809519 A
+36.809519 38.736775 G
+38.736775 40.664031 G
+40.664031 42.556457 A
+42.556457 44.530154 A
+44.530154 45.017773 D
+45.017773 46.445800 E
+46.445800 48.442716 A
+48.442716 48.941945 G
+48.941945 49.899886 D
+49.899886 50.165672 D/7
+50.165672 50.418143 A/3
+50.418143 51.414870 B:min
+51.414870 52.378498 D/5
+52.378498 53.342126 E/3
+53.342126 54.346294 A
+54.346294 56.314280 A
+56.314280 56.848339 D
+56.848339 58.346027 E
+58.346027 60.331333 A
+60.331333 60.830562 G
+60.830562 61.796236 D
+61.796236 62.048724 D/7
+62.048724 62.305029 A/3
+62.305029 63.326707 B:min
+63.326707 64.290335 D/5
+64.290335 65.288793 E/3
+65.288793 66.275641 A
+66.275641 68.168067 A
+68.168067 70.153373 G
+70.153373 72.103850 G
+72.103850 74.007886 A
+74.007886 75.969972 A
+75.969972 77.920448 G
+77.920448 79.824485 G
+79.824485 81.737345 A
+81.737345 83.655777 A
+83.655777 84.166616 D
+84.166616 85.617863 E
+85.617863 87.498680 A
+87.498680 87.986299 G
+87.986299 89.140901 D
+89.140901 89.414326 A/3
+89.414326 90.366344 B:min
+90.366344 91.329972 D/5
+91.329972 92.270380 E/3
+92.270380 93.234008 A
+93.234008 95.196095 A
+95.196095 97.134961 G
+97.134961 99.027387 G
+99.027387 101.001083 A
+101.001083 102.916729 A
+102.916729 104.820766 G
+104.820766 106.736412 G
+106.736412 108.617228 A
+108.617228 110.544485 A
+110.544485 111.043714 D
+111.043714 112.553011 E
+112.553011 114.468657 A
+114.468657 115.002716 D
+115.002716 116.535233 E
+116.535233 118.497319 A
+118.497319 118.984938 D
+118.984938 119.817442 E
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/12_-_I_Don't_Want_to_Spoil_the_Party.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,93 @@
+0.0000000 0.4371360 N
+0.4371360 1.6989590 G
+1.6989590 2.3723380 G/b7
+2.3723380 3.0108870 E:min7
+3.0108870 4.2415440 D:sus4
+4.2415440 4.8452630 F:maj9
+4.8452630 5.4838120 C/3
+5.4838120 6.7260790 D:7
+6.7260790 7.3297980 D/2
+7.3297980 7.6330930 A:min/6
+7.6330930 7.9683470 A:min
+7.9683470 10.4528820 G
+10.4528820 12.9258070 G
+12.9258070 15.3755120 G
+15.3755120 17.8600480 G
+17.8600480 20.3329730 D
+20.3329730 21.5868500 E:min
+21.5868500 22.8291180 B
+22.8291180 24.0713850 A:min
+24.0713850 25.3252630 D
+25.3252630 26.5675310 G
+26.5675310 27.8214080 F:7
+27.8214080 29.0404560 G
+29.0404560 30.2943330 G
+30.2943330 37.7131090 G
+37.7131090 40.1628140 D
+40.1628140 41.4166920 E:min
+41.4166920 42.6241290 B
+42.6241290 43.9012270 A:min
+43.9012270 45.1318840 D
+45.1318840 46.3509320 G
+46.3509320 47.6396390 F:7
+47.6396390 50.1357840 G
+50.1357840 52.6203200 G
+52.6203200 53.8858070 E:min
+53.8858070 55.1512950 A
+55.1512950 56.3819520 C
+56.3819520 57.6010000 D
+57.6010000 60.1551950 G
+60.1551950 61.3742430 E:min
+61.3742430 62.6513400 A
+62.6513400 63.9052180 C
+63.9052180 65.1126550 D
+65.1126550 72.6939700 G
+72.6939700 75.2017260 D:7(#9)
+75.2017260 76.4672130 E:min
+76.4672130 77.7443110 B
+77.7443110 79.0097980 A:min
+79.0097980 80.2752860 D
+80.2752860 81.4943330 G
+81.4943330 82.7830410 F:7
+82.7830410 85.2327460 G
+85.2327460 90.2830860 G
+90.2830860 92.8488910 G
+92.8488910 94.0973480 D:9
+94.0973480 95.3450360 D:7(#9)
+95.3450360 96.6337440 E:min
+96.6337440 97.9224510 B
+97.9224510 99.1414990 A:min
+99.1414990 100.3953760 D
+100.3953760 101.6956940 G
+101.6956940 102.9844010 F:7
+102.9844010 105.5385960 G
+105.5385960 108.0695710 G
+108.0695710 109.3466690 E:min
+109.3466690 110.6353760 A
+110.6353760 111.8544240 C
+111.8544240 113.1083010 D
+113.1083010 115.6508870 G
+115.6508870 116.9047640 E:min
+116.9047640 118.1818620 A
+118.1818620 119.4241290 C
+119.4241290 120.6431770 D
+120.6431770 128.2128820 G
+128.2128820 129.4391590 D:7(#9)
+129.4391590 130.7670770 D:9
+130.7670770 132.0441750 E:min
+132.0441750 133.3096620 B
+133.3096620 134.5635400 A:min
+134.5635400 135.8290270 D
+135.8290270 137.0945150 G
+137.0945150 138.3832220 F:7
+138.3832220 140.8793670 G
+140.8793670 142.2145150 G
+142.2145150 142.8184320 G:7
+142.8184320 143.4683920 E:min/b3
+143.4683920 144.7106600 D:7
+144.7106600 145.3375990 D:7
+145.3375990 146.0341970 D:7
+146.0341970 147.2996850 D
+147.2996850 147.9382330 D
+147.9382330 148.5535620 D:7
+148.5535620 151.6317630 G
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/13_-_What_You're_Doing.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,72 @@
+0.0000000 0.4212470 N
+0.4212470 7.5250110 N
+7.5250110 9.3709970 D
+9.3709970 11.1241040 G
+11.1241040 12.9352600 D
+12.9352600 14.7464170 G
+14.7464170 16.5575730 D
+16.5575730 18.4035600 G
+18.4035600 20.3192060 D
+20.3192060 22.1419720 G
+22.1419720 24.0111790 B:min
+24.0111790 27.6799310 G
+27.6799310 29.5607480 D
+29.5607480 31.4299540 G
+31.4299540 33.3456000 D
+33.3456000 35.1683670 G
+35.1683670 37.0724030 D
+37.0724030 38.9067790 G
+38.9067790 40.7875960 B:min
+40.7875960 44.4911790 G
+44.4911790 46.3709760 D
+46.3709760 48.2179810 G
+48.2179810 50.0639680 B:min
+50.0639680 51.8983440 G
+51.8983440 53.7211110 B:min
+53.7211110 57.4014730 E
+57.4014730 61.1282760 A
+61.1282760 62.9974820 D
+62.9974820 64.8086390 G
+64.8086390 66.6778450 D
+66.6778450 68.5586620 G
+68.5586620 70.4394780 B:min
+70.4394780 74.1314510 G
+74.1314510 76.0238770 D
+76.0238770 77.8582530 G
+77.8582530 79.7506800 D
+79.7506800 81.5618360 G
+81.5618360 83.4542620 D
+83.4542620 85.2770290 G
+85.2770290 87.1024833 B:min
+87.1024833 88.9690020 G
+88.9690020 90.8498180 G
+90.8498180 92.7074140 D
+92.7074140 94.5882310 G
+94.5882310 96.4226070 B:min
+96.4226070 98.2453740 G
+98.2453740 100.0797500 B:min
+100.0797500 103.8181630 E:min
+103.8181630 107.5914050 A
+107.5914050 109.4722220 D
+109.4722220 111.2833780 G
+111.2833780 113.1758040 D
+113.1758040 115.0566210 G
+115.0566210 116.9258270 B:min
+116.9258270 118.7718130 G
+118.7718130 120.6410200 G
+120.6410200 122.5218360 D
+122.5218360 124.3329930 G
+124.3329930 126.2718590 D
+126.2718590 128.1642850 G
+128.1642850 130.0218820 D
+130.0218820 131.9143080 G
+131.9143080 132.4823219 D
+132.4823219 133.7652118 D:(1)
+133.7652118 135.5677080 N
+135.5677080 139.2402040 A:(1)
+139.2402040 141.0978000 D
+141.0978000 142.9321760 G:7
+142.9321760 144.7665530 D
+144.7665530 146.5893190 G:7
+146.5893190 148.4701350 D
+148.4701350 150.3045120 G
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/14_-_Everybody's_Trying_to_Be_My_Baby.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+0.000000 0.442301 N
+0.442301 7.705280 E:7
+7.705280 10.549725 A
+10.549725 13.370949 E
+13.370949 14.752537 B:9
+14.752537 16.192174 A
+16.192174 18.932128 E
+18.932128 24.632627 E:7
+24.632627 27.488682 A
+27.488682 30.298296 E
+30.298296 31.714713 B:9
+31.714713 33.107911 A
+33.107911 35.882695 E
+35.882695 38.634260 E
+38.634260 41.478704 E
+41.478704 44.311539 A
+44.311539 47.109543 E
+47.109543 48.491131 B:9
+48.491131 49.919158 A
+49.919158 52.728772 E
+52.728772 58.382831 E:7
+58.382831 61.157616 A
+61.157616 64.036890 E
+64.036890 65.418478 B:9
+65.418478 66.858115 A
+66.858115 69.621289 E
+69.621289 72.396074 E:7(#9)
+72.396074 75.182469 E:7(#9)
+75.182469 78.026913 A:7
+78.026913 80.836527 E:7(#9)
+80.836527 82.264555 B:9
+82.264555 83.669362 A:9
+83.669362 85.039339 E
+85.039339 86.432537 E
+86.432537 89.242151 E:7
+89.242151 92.121425 E:7
+92.121425 94.942650 A:9
+94.942650 97.775484 E
+97.775484 99.215122 B:9
+99.215122 100.585099 A
+100.585099 103.394713 E:7
+103.394713 109.013942 E:7
+109.013942 111.858387 A
+111.858387 114.691221 E
+114.691221 116.107639 B:9
+116.107639 117.489226 A
+117.489226 120.322060 E
+120.322060 125.918069 E:7
+125.918069 128.785734 A
+128.785734 131.595348 E
+131.595348 133.034986 B:9
+133.034986 134.486233 A
+134.486233 135.949090 E
+135.949090 136.489038 B:7
+136.489038 136.970768 E
+136.970768 139.699113 E:7
+139.699113 142.630556 E:9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+/.DS_Store/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/01_-_No_Reply.lab/1.2/Thu Jul 27 21:48:40 2006//
+/02_-_I'm_a_Loser.lab/1.3/Tue Oct 17 21:53:33 2006//
+/03_-_Baby's_In_Black.lab/1.3/Tue Oct 17 21:53:34 2006//
+/04_-_Rock_and_Roll_Music.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/05_-_I'll_Follow_the_Sun.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/06_-_Mr._Moonlight.lab/1.3/Thu Jul 27 22:35:20 2006//
+/07_-_Kansas_City-_Hey,_Hey,_Hey,_Hey.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/08_-_Eight_Days_a_Week.lab/1.2/Fri Jul 21 11:46:26 2006//
+/09_-_Words_of_Love.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/10_-_Honey_Don't.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/11_-_Every_Little_Thing.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+/12_-_I_Don't_Want_to_Spoil_the_Party.lab/1.2/Thu Jul 27 21:48:40 2006//
+/13_-_What_You're_Doing.lab/1.2/Thu Jul 27 21:48:40 2006//
+/14_-_Everybody's_Trying_to_Be_My_Baby.lab/1.1.1.1/Fri Sep 23 09:24:37 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/04final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/04final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/01_-_Help!.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+0.0000000 1.0531186 N
+1.0531186 3.5938540 B:min
+3.5938540 6.0900000 G
+6.0900000 8.6558040 E
+8.6558040 11.1403400 A
+11.1403400 13.6597050 A
+13.6597050 16.1094100 C#:min
+16.1094100 18.6868250 F#:min
+18.6868250 19.3718140 D
+19.3718140 19.9871420 G
+19.9871420 21.2526300 A
+21.2526300 23.7603850 A
+23.7603850 26.2565300 C#:min
+26.2565300 28.7642850 F#:min
+28.7642850 29.3912240 D
+29.3912240 29.9949430 G
+29.9949430 31.2139900 A
+31.2139900 36.2178910 B:min
+36.2178910 41.2566210 G
+41.2566210 46.3650110 E
+46.3650110 48.8959860 A
+48.8959860 51.3921310 A
+51.3921310 53.9463260 A
+53.9463260 56.4889110 C#:min
+56.4889110 59.0082760 F#:min
+59.0082760 59.6584350 D
+59.6584350 60.2737640 G
+60.2737640 61.5276410 A
+61.5276410 64.1398860 A
+64.1398860 66.6476410 C#:min
+66.6476410 69.1437860 F#:min
+69.1437860 69.7475050 D
+69.7475050 70.3396140 G
+70.3396140 71.5354420 A
+71.5354420 76.5973920 B:min
+76.5973920 81.7057820 G
+81.7057820 86.7677320 E
+86.7677320 89.1704253 A
+89.1704253 91.8645120 A
+91.8645120 94.3374370 A
+94.3374370 96.8800220 C#:min
+96.8800220 99.3993870 F#:min
+99.3993870 100.0495460 D
+100.0495460 100.6532650 G
+100.6532650 101.9768020 A
+101.9768020 104.5309970 A
+104.5309970 107.1316320 C#:min
+107.1316320 109.7206570 F#:min
+109.7206570 110.3359860 D
+110.3359860 110.9745350 G
+110.9745350 112.1703620 A
+112.1703620 117.2207020 B:min
+117.2207020 122.2594330 G
+122.2594330 127.3910430 E
+127.3910430 129.9336280 A
+129.9336280 132.4646030 F#:min
+132.4646030 133.7184800 A
+133.7184800 136.9437153 A:maj6
+136.9437153 140.9072708 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/02_-_The_Night_Before.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,106 @@
+0.0000000 0.7001660 N
+0.7001660 3.4961450 D
+3.4961450 6.3405890 F
+6.3405890 9.1385940 G
+9.1385940 11.8523713 A:7
+11.8523713 13.2949650 D
+13.2949650 14.7113830 C
+14.7113830 16.1510200 G
+16.1510200 17.5906570 A
+17.5906570 18.9838540 D
+18.9838540 20.4234920 C
+20.4234920 21.8282990 G
+21.8282990 23.2563260 A
+23.2563260 24.6379130 B:min
+24.6379130 26.0659410 G:min
+26.0659410 27.4707480 B:min
+27.4707480 28.9219950 G:min
+28.9219950 30.2919720 D
+30.2919720 31.7432190 G
+31.7432190 33.1015870 D
+33.1015870 33.6704760 F
+33.6704760 34.1697050 F
+34.1697050 34.5528340 G
+34.5528340 36.0040810 D
+36.0040810 37.3856680 C
+37.3856680 38.7672560 G
+38.7672560 40.1604530 A
+40.1604530 41.5884800 D
+41.5884800 43.0281170 C
+43.0281170 44.4097050 G
+44.4097050 45.8493420 A
+45.8493420 47.2889790 B:min
+47.2889790 48.7286160 G:min
+48.7286160 50.0985940 B:min
+50.0985940 51.5846710 G:min
+51.5846710 53.0010880 D
+53.0010880 54.3478450 G
+54.3478450 55.7990920 D
+55.7990920 57.2039000 D
+57.2039000 58.6203170 A:min
+58.6203170 60.0135140 D
+60.0135140 62.7999090 G
+62.7999090 64.1931060 B:min
+64.1931060 65.5863030 E
+65.5863030 68.3186767 A
+68.3186767 69.7891150 D
+69.7891150 71.1590920 C
+71.1590920 72.5755100 G
+72.5755100 73.9687070 A
+73.9687070 75.3851240 D
+75.3851240 76.7783210 C
+76.7783210 78.1715190 G
+78.1715190 79.6343760 A
+79.6343760 81.0740130 B:min
+81.0740130 82.5020400 G:min
+82.5020400 83.9416780 B:min
+83.9416780 85.4161450 G:min
+85.4161450 86.7745120 D
+86.7745120 88.2141490 G
+88.2141490 89.6653960 D
+89.6653960 90.2226750 F
+90.2226750 90.6522440 F
+90.6522440 91.0237640 G
+91.0237640 92.3937410 D
+92.3937410 93.8333780 C
+93.8333780 95.2265750 G
+95.2265750 96.6081630 A
+96.6081630 98.0826300 D
+98.0826300 99.4874370 C
+99.4874370 100.9154640 G
+100.9154640 102.3551020 A
+102.3551020 103.8643990 B:min
+103.8643990 105.2111560 G:min
+105.2111560 106.6159630 B:min
+106.6159630 108.0439900 G:min
+108.0439900 109.4487980 D
+109.4487980 110.8187750 G
+110.8187750 112.2468020 D
+112.2468020 113.6400000 D
+113.6400000 115.0564170 A:min
+115.0564170 116.4612240 D
+116.4612240 117.8544210 G
+117.8544210 119.2127890 G
+119.2127890 120.6059860 B:min
+120.6059860 122.0224030 E
+122.0224030 123.4272100 A
+123.4272100 124.7855780 A
+124.7855780 126.1439450 D
+126.1439450 127.5603620 C
+127.5603620 128.9883900 G
+128.9883900 130.4280270 A
+130.4280270 131.8560540 D
+131.8560540 133.2840810 C
+133.2840810 134.6656680 G
+134.6656680 136.0588660 A
+136.0588660 137.4636730 B:min
+137.4636730 138.9149200 G:min
+138.9149200 140.3197270 B:min
+140.3197270 141.8058040 G:min
+141.8058040 143.2222220 D
+143.2222220 144.6270290 G
+144.6270290 146.0898860 D
+146.0898860 147.5527430 F
+147.5527430 148.9343310 D
+148.9343310 152.5215760 D
+152.5215760 156.4276880 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/03_-_You've_Got_To_Hide_Your_Love_Away.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,108 @@
+0.0000000 0.4786903 N
+0.4786903 2.4560770 G
+2.4560770 3.4429250 G
+3.4429250 4.3949430 D
+4.3949430 5.3701810 F
+5.3701810 6.3454190 G
+6.3454190 8.3423350 C
+8.3423350 9.2363030 F
+9.2363030 10.1999310 C
+10.1999310 11.1751700 G
+11.1751700 12.1620180 D
+12.1620180 13.1256460 F
+13.1256460 14.1008840 G
+14.1008840 16.0629700 C
+16.0629700 17.0149880 F
+17.0149880 18.0134460 C
+18.0134460 19.9407020 D
+19.9407020 20.8927210 G
+20.8927210 21.8563490 D
+21.8563490 22.8431970 F
+22.8431970 23.8416550 G
+23.8416550 25.7805210 C
+25.7805210 26.7093190 F
+26.7093190 27.6845570 C
+27.6845570 28.6481850 G
+28.6481850 29.6350340 D
+29.6350340 30.5986620 F
+30.5986620 31.5855100 G
+31.5855100 33.5359860 C
+33.5359860 34.4996140 F
+34.4996140 35.4864620 C
+35.4864620 36.4733100 D
+36.4733100 37.4369380 D/b7
+37.4369380 38.4353960 D/6
+38.4353960 39.3990240 D/5
+39.3990240 41.3611110 G
+41.3611110 43.3115870 C
+43.3115870 44.2636050 D:sus4
+44.2636050 45.2272330 D
+45.2272330 46.2024710 D:maj(2)
+46.2024710 47.1544890 D
+47.1544890 49.1514050 G
+49.1514050 51.0786620 C
+51.0786620 52.0422900 D:sus4
+52.0422900 53.0175280 D
+53.0175280 53.9695460 D:maj(2)
+53.9695460 54.9912240 D
+54.9912240 56.0245120 G
+56.0245120 56.9881400 D
+56.9881400 57.9169380 F
+57.9169380 58.9037860 G
+58.9037860 60.8426530 C
+60.8426530 61.8527210 F
+61.8527210 62.8163490 C
+62.8163490 63.7799770 G
+63.7799770 64.7668250 D
+64.7668250 65.7420630 F
+65.7420630 66.7056910 G
+66.7056910 68.6909970 C
+68.6909970 69.6546250 F
+69.6546250 70.6182530 C
+70.6182530 72.5687300 D
+72.5687300 73.5555780 G
+73.5555780 74.5656460 D
+74.5656460 75.5060540 F
+75.5060540 76.5277320 G
+76.5277320 78.5130380 C
+78.5130380 79.4418360 F
+79.4418360 80.3938540 C
+80.3938540 81.3807020 G
+81.3807020 82.3907700 D
+82.3907700 83.2963490 F
+83.2963490 84.3180270 G
+84.3180270 86.3497730 C
+86.3497730 87.3017910 F
+87.3017910 88.2538090 C
+88.2538090 89.2058270 D
+89.2058270 90.1810650 D/b7
+90.1810650 91.1795230 D/6
+91.1795230 92.1199310 D/5
+92.1199310 94.1168480 G
+94.1168480 96.0441040 C
+96.0441040 96.9845120 D:sus4
+96.9845120 97.9249200 D
+97.9249200 98.9233780 D:maj(2)
+98.9233780 99.8753960 D
+99.8753960 101.8607020 G
+101.8607020 103.8111790 C
+103.8111790 104.7980270 D:sus4
+104.7980270 105.7500450 D
+105.7500450 106.7020630 D:maj(2)
+106.7020630 107.7353510 D
+107.7353510 108.6757590 G
+108.6757590 109.6161670 D
+109.6161670 110.6030150 F
+110.6030150 111.6130830 G
+111.6130830 113.6100000 C
+113.6100000 114.5504080 F
+114.5504080 115.5140360 C
+115.5140360 116.5124940 G
+116.5124940 117.5225620 D
+117.5225620 118.4629700 F
+118.4629700 119.4614280 G
+119.4614280 121.4931740 C
+121.4931740 122.4568020 F
+122.4568020 123.4088200 C
+123.4088200 126.9103670 G
+126.9103670 131.2760224 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/04_-_I_Need_You.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,106 @@
+0.0000000 0.4786903 N
+0.4786903 0.8616425 A
+0.8616425 2.5657799 A:sus2
+2.5657799 3.1019130 A:sus4
+3.1019130 3.9885940 A
+3.9885940 5.6720400 A
+5.6720400 7.2760923 D
+7.2760923 7.7547825 A
+7.7547825 8.9802297 A:sus2
+8.9802297 9.5738056 A:sus4
+9.5738056 10.9661900 A
+10.9661900 12.6960770 A
+12.6960770 14.2266751 D
+14.2266751 14.7053654 A
+14.7053654 15.9116649 A:sus2
+15.9116649 16.3712076 A:sus4
+16.3712076 17.8392970 A
+17.8392970 19.6388430 F#:min
+19.6388430 21.3339000 C#:min
+21.3339000 23.0870060 F#:min
+23.0870060 24.6238280 B:min
+24.6238280 25.0067802 A
+25.0067802 26.4237035 A:sus2
+26.4237035 27.0172794 A:sus4
+27.0172794 28.3695460 A
+28.3695460 30.0994330 A
+30.0994330 31.6318537 D
+31.6318537 32.0531011 A
+32.0531011 33.4125815 A:sus2
+33.4125815 33.8338290 A:sus4
+33.8338290 35.3239220 A
+35.3239220 37.0654190 A
+37.0654190 38.6207318 D
+38.6207318 39.0802745 A
+39.0802745 40.4206072 A:sus2
+40.4206072 40.8227071 A:sus4
+40.8227071 42.3247390 A
+42.3247390 44.0197950 F#:min
+44.0197950 45.7612920 C#:min
+45.7612920 47.5027890 F#:min
+47.5027890 49.1327703 B:min
+49.1327703 49.5731654 A
+49.5731654 50.8943506 A:sus2
+50.8943506 51.3155980 A:sus4
+51.3155980 52.7504980 A
+52.7504980 54.5268250 D
+54.5268250 56.2915410 E
+56.2915410 59.8093650 A
+59.8093650 61.5160310 D
+61.5160310 63.2923580 E
+63.2923580 65.1035140 B
+65.1035140 68.5865070 E
+68.5865070 70.3976640 A
+70.3976640 71.9375753 D
+71.9375753 72.3588227 A
+72.3588227 73.7720565 A:sus2
+73.7720565 74.1815979 A:sus4
+74.1815979 75.6918140 A
+75.6918140 77.4797500 A
+77.4797500 79.0278377 D
+79.0278377 79.4373791 A
+79.4373791 80.7615629 A:sus2
+80.7615629 81.1858715 A:sus4
+81.1858715 82.7274600 A
+82.7274600 84.4457360 F#:min
+84.4457360 86.1988430 C#:min
+86.1988430 87.9751700 F#:min
+87.9751700 89.5667029 B:min
+89.5667029 89.9625929 A
+89.9625929 91.3532530 A:sus2
+91.3532530 91.8510909 A:sus4
+91.8510909 93.3389790 A
+93.3389790 95.1269160 D
+95.1269160 96.8684120 E
+96.8684120 100.4094550 A
+100.4094550 102.2090020 D
+102.2090020 103.9969380 E
+103.9969380 105.7964850 B
+105.7964850 109.3607480 E
+109.3607480 111.1719040 A
+111.1719040 112.7603972 D
+112.7603972 113.1972414 A
+113.1972414 114.5218626 A:sus2
+114.5218626 114.9431100 A:sus4
+114.9431100 116.5124940 A
+116.5124940 118.3120400 A
+118.3120400 119.8864175 D
+119.8864175 120.3232616 A
+120.3232616 121.5681835 A:sus2
+121.5681835 122.0468738 A:sus4
+122.0468738 123.6410200 A
+123.6410200 125.3244670 F#:min
+125.3244670 127.2168930 C#:min
+127.2168930 128.9351700 F#:min
+128.9351700 130.5481451 B:min
+130.5481451 130.9576865 A
+130.9576865 132.4183841 A:sus2
+132.4183841 132.8825311 A:sus4
+132.8825311 134.3338090 A
+134.3338090 137.7819720 F#:min
+137.7819720 141.3694550 D
+141.3694550 141.9603894 A
+141.9603894 143.3121852 A:sus2
+143.3121852 143.9933100 A:sus4
+143.9933100 147.5323443 A
+147.5323443 151.2661285 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/05_-_Another_Girl.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,82 @@
+0.0000000 0.4403951 N
+0.4403951 1.3020376 N
+1.3020376 2.7347160 A
+2.7347160 4.1163030 D
+4.1163030 5.4398410 A
+5.4398410 6.7401580 D
+6.7401580 8.1101360 A
+8.1101360 9.4104530 G
+9.4104530 10.7804300 A
+10.7804300 12.0923580 D
+12.0923580 13.4275050 A
+13.4275050 14.7510430 G
+14.7510430 16.0397500 A
+16.0397500 17.3748970 D
+17.3748970 21.3687300 D
+21.3687300 22.7387070 E
+22.7387070 24.1086840 A
+24.1086840 25.4438320 D
+25.4438320 26.8021990 A
+26.8021990 28.1025170 D
+28.1025170 29.5073240 A
+29.5073240 30.8192510 G
+30.8192510 32.1311790 A
+32.1311790 33.4663260 D
+33.4663260 34.8130830 A
+34.8130830 36.1482310 G
+36.1482310 37.5298180 A
+37.5298180 38.8997950 D
+38.8997950 42.9052380 D
+42.9052380 44.2287750 E
+44.2287750 45.6103620 A
+45.6103620 46.9571200 D
+46.9571200 48.2806570 A
+48.2806570 49.6041950 D
+49.6041950 51.0206120 C
+51.0206120 52.3905890 G
+52.3905890 53.7025170 C
+53.7025170 55.1073240 G
+55.1073240 56.4540810 C
+56.4540810 57.7776190 E
+57.7776190 59.1592060 A
+59.1592060 60.4827430 E
+60.4827430 61.8643310 A
+61.8643310 63.2110880 G
+63.2110880 64.5926750 A
+64.5926750 65.9510430 D
+65.9510430 67.3094100 A
+67.3094100 68.6561670 G
+68.6561670 70.0493650 A
+70.0493650 71.3845120 D
+71.3845120 75.4363940 D
+75.4363940 76.8412010 E
+76.8412010 78.2460090 A
+78.2460090 79.5463260 D
+79.5463260 80.9163030 A
+80.9163030 82.2514510 D
+82.2514510 83.6794780 C
+83.6794780 85.0146250 G
+85.0146250 86.4078230 C
+86.4078230 87.7778000 G
+87.7778000 89.1361670 C
+89.1361670 90.4829250 E
+90.4829250 91.8529020 A
+91.8529020 93.2228790 E
+93.2228790 94.5812470 A
+94.5812470 95.9628340 G
+95.9628340 97.3444210 A
+97.3444210 98.7143990 D
+98.7143990 100.0843760 A
+100.0843760 101.4543530 G
+101.4543530 102.8359410 A
+102.8359410 104.2175280 D
+104.2175280 108.3274600 D
+108.3274600 109.7670970 E
+109.7670970 111.1486840 A
+111.1486840 112.5186620 D
+112.5186620 113.8654190 A
+113.8654190 115.2237860 D
+115.2237860 116.6169840 A
+116.6169840 117.9869610 D
+117.9869610 123.5403874 A
+123.5403874 127.5613858 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/06_-_You're_Going_to_Lose_That_Girl.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,75 @@
+0.0000000 0.4978379 N
+0.4978379 1.2950790 B
+1.2950790 3.0365750 E
+3.0365750 4.9522220 C#:min
+4.9522220 6.8330380 F#:min9
+6.8330380 8.7719040 B
+8.7719040 10.5830610 E
+10.5830610 12.4058270 G#
+12.4058270 14.2285940 F#:min
+14.2285940 16.0978000 B
+16.0978000 17.8509070 E
+17.8509070 19.6852830 G#
+19.6852830 21.4964390 F#:min
+21.4964390 23.3308160 B
+23.3308160 25.1651920 E
+25.1651920 26.9647390 C#:min
+26.9647390 28.7642850 F#:min9
+28.7642850 30.5522220 B
+30.5522220 32.3865980 E
+32.3865980 34.2093650 G#
+34.2093650 36.0089110 F#:min
+36.0089110 37.8200680 B
+37.8200680 39.6080040 E
+39.6080040 41.4075510 G#
+41.4075510 43.1838770 F#:min
+43.1838770 45.0879130 B
+45.0879130 46.8874600 E
+46.8874600 48.7334460 C#:min
+48.7334460 50.5213830 F#:min9
+50.5213830 52.3441490 B
+52.3441490 54.1901360 F#:min
+54.1901360 55.9432420 D
+55.9432420 57.8240580 G
+57.8240580 59.6119950 C
+59.6119950 63.2459180 G
+63.2459180 65.0454640 G
+65.0454640 66.8334010 C
+66.8334010 68.6793870 F
+68.6793870 70.4789340 E
+70.4789340 72.2784800 G#
+72.2784800 74.0431970 F#:min
+74.0431970 75.9472330 B
+75.9472330 77.7467800 E
+77.7467800 79.5695460 G#
+79.5695460 81.3574820 F#:min
+81.3574820 83.2150790 B
+83.2150790 85.0726750 E
+85.0726750 86.9302720 C#:min
+86.9302720 88.7182080 F#:min9
+88.7182080 90.5525850 B
+90.5525850 92.3405210 F#:min
+92.3405210 94.1400680 D
+94.1400680 95.9976640 G
+95.9976640 97.8088200 C
+97.8088200 101.4079130 G
+101.4079130 103.2539000 G
+103.2539000 105.0070060 C
+105.0070060 106.8529930 F
+106.8529930 108.6757590 E
+108.6757590 110.4985260 G#
+110.4985260 112.3212920 F#:min
+112.3212920 114.1440580 B
+114.1440580 115.9436050 E
+115.9436050 117.8128110 G#
+117.8128110 119.6123580 F#:min
+119.6123580 121.4699540 B
+121.4699540 123.2695010 E
+123.2695010 125.1387070 C#:min
+125.1387070 126.9498630 F#:min9
+126.9498630 128.8190700 B
+128.8190700 130.6882760 F#:min
+130.6882760 131.5706340 D
+131.5706340 132.4762130 A
+132.4762130 135.8905967 E
+135.8905967 140.0647759 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/07_-_Ticket_To_Ride.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,53 @@
+0.0000000 0.4212474 N
+0.4212474 4.0466430 A
+4.0466430 7.9475960 A
+7.9475960 19.5691830 A
+19.5691830 21.4848290 B:min
+21.4848290 23.4004760 E
+23.4004760 25.3393420 F#:min
+25.3393420 27.1853280 D
+27.1853280 28.9152150 F#:min
+28.9152150 30.9817910 G:maj7
+30.9817910 32.8742170 F#:min
+32.8742170 34.8130830 E
+34.8130830 38.7256460 A
+38.7256460 50.2775730 A
+50.2775730 52.2512690 B:min
+52.2512690 54.1785260 E
+54.1785260 56.1057820 F#:min
+56.1057820 57.9633780 D
+57.9633780 59.7280950 F#:min
+59.7280950 61.8527210 G:maj7
+61.8527210 63.7799770 F#:min
+63.7799770 65.7304530 E
+65.7304530 69.6197950 A
+69.6197950 75.4828340 D:7
+75.4828340 77.4100900 E
+77.4100900 83.2150790 D:7
+83.2150790 87.0579810 E
+87.0579810 98.9001580 A
+98.9001580 100.8854640 B:min
+100.8854640 102.8939900 E
+102.8939900 104.9025170 F#:min
+104.9025170 106.8181630 D
+106.8181630 108.5828790 F#:min
+108.5828790 110.7307250 G:maj7
+110.7307250 112.7276410 F#:min
+112.7276410 114.6665070 E
+114.6665070 118.6255100 A
+118.6255100 124.4537180 D:7
+124.4537180 126.4506340 E
+126.4506340 132.1859630 D:7
+132.1859630 136.0869160 E
+136.0869160 147.9523120 A
+147.9523120 149.9143990 B:min
+149.9143990 151.9113150 E
+151.9113150 153.8617910 F#:min
+153.8617910 155.8238770 D
+155.8238770 157.5421540 F#:min
+157.5421540 159.7480490 G:maj7
+159.7480490 161.6753060 F#:min
+161.6753060 163.6606120 E
+163.6606120 167.5731740 A
+167.5731740 187.7040326 A
+187.7040326 192.3186069 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/08_-_Act_Naturally.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+0.0000000 0.4403951 N
+0.4403951 1.4460090 G
+1.4460090 2.5837860 D
+2.5837860 3.8260540 D:7
+3.8260540 6.4150790 G
+6.4150790 8.9344440 G
+8.9344440 11.4654190 C
+11.4654190 14.0544440 G
+14.0544440 16.6086390 D
+16.6086390 19.1512240 G
+19.1512240 21.7402490 C
+21.7402490 24.3176640 D
+24.3176640 25.6063710 G
+25.6063710 26.9215413 G
+26.9215413 29.5305440 D
+29.5305440 32.0963490 G
+32.0963490 34.6737640 D
+34.6737640 37.2163490 G
+37.2163490 39.8169840 D
+39.8169840 42.3943990 G
+42.3943990 43.7179360 A
+43.7179360 44.9834240 A
+44.9834240 47.5608390 D
+47.5608390 50.1730830 G
+50.1730830 52.7156680 C
+52.7156680 55.3046930 G
+55.3046930 57.8937180 D
+57.8937180 60.4363030 G
+60.4363030 63.0717680 C
+63.0717680 65.6724030 D
+65.6724030 66.9843310 G
+66.9843310 68.2498180 G
+68.2498180 70.8388430 D
+70.8388430 73.3930380 G
+73.3930380 75.9588430 D
+75.9588430 78.5130380 G
+78.5130380 81.0904530 G
+81.0904530 83.6562580 C
+83.6562580 86.3033330 G
+86.3033330 88.8923580 D
+88.8923580 91.5278230 G
+91.5278230 94.0936280 C
+94.0936280 96.6942630 D
+96.6942630 99.2948970 G
+99.2948970 101.8839220 D
+101.8839220 104.5077770 G
+104.5077770 107.0851920 D
+107.0851920 109.6974370 G
+109.6974370 112.2400220 D
+112.2400220 114.8522670 G
+114.8522670 117.4412920 A
+117.4412920 120.0651470 D
+120.0651470 122.6541720 G
+122.6541720 125.2199770 C
+125.2199770 127.7857820 G
+127.7857820 130.3864170 D
+130.3864170 132.9986620 G
+132.9986620 135.6109070 C
+135.6109070 138.2115410 D
+138.2115410 140.8237860 G
+140.8237860 143.4476410 D
+143.4476410 144.8060090 G
+144.8060090 148.5088724 G
+148.5088724 153.0468563 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/09_-_It's_Only_Love.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,63 @@
+0.0000000 0.4595427 N
+0.4595427 2.4909070 C
+2.4909070 4.5342630 A:min
+4.5342630 6.6124480 C
+6.6124480 8.7254640 A:min
+8.7254640 9.7703620 C
+9.7703620 10.8849200 E:min/5
+10.8849200 11.9182080 Bb
+11.9182080 12.9631060 F
+12.9631060 15.0645120 G
+15.0645120 17.1659180 G:aug
+17.1659180 18.2804760 C
+18.2804760 19.3253740 E:min/5
+19.3253740 20.4167120 Bb
+20.4167120 21.4964390 F
+21.4964390 23.5630150 G
+23.5630150 25.6876410 G:aug
+25.6876410 27.8006570 F
+27.8006570 29.9485030 G
+29.9485030 32.0847390 C
+32.0847390 34.1977550 A:min
+34.1977550 36.3223800 Bb
+36.3223800 38.4818360 G
+38.4818360 40.6064620 C
+40.6064620 42.7543080 A:min
+42.7543080 44.8208840 Bb
+44.8208840 46.9571200 G
+46.9571200 49.0817460 F
+49.0817460 51.2412010 G
+51.2412010 52.3209290 C
+52.3209290 53.4006570 E:min/5
+53.4006570 54.4339450 Bb
+54.4339450 55.4788430 F
+55.4788430 57.5570290 G
+57.5570290 59.6584350 G:aug
+59.6584350 60.7381630 C
+60.7381630 61.8062810 E:min/5
+61.8062810 62.8743990 Bb
+62.8743990 63.9192970 F
+63.9192970 66.0323120 G
+66.0323120 68.1569380 G:aug
+68.1569380 70.2467340 F
+70.2467340 72.4178000 G
+72.4178000 74.5424260 C
+74.5424260 76.6786620 A:min
+76.6786620 78.7800680 Bb
+78.7800680 80.9163030 G
+80.9163030 82.9712690 C
+82.9712690 85.1423350 A:min
+85.1423350 87.2437410 Bb
+87.2437410 89.3799770 G
+89.3799770 91.5394330 F
+91.5394330 93.6176190 G
+93.6176190 95.7886840 F
+95.7886840 97.8784800 G
+97.8784800 100.0379360 C
+100.0379360 102.0929020 A:min
+102.0929020 104.2291380 C
+104.2291380 106.3305440 A:min
+106.3305440 108.4319500 C
+108.4319500 110.5449650 A:min
+110.5449650 115.0197005 C
+115.0197005 118.6385990 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/10_-_You_Like_Me_Too_Much.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,88 @@
+0.000000 0.529543 N
+0.529543 1.550839 G
+1.550839 4.488163 G
+4.488163 6.043900 Bb
+6.043900 7.773786 D:7(#9)
+7.773786 10.049342 G
+10.049342 12.742857 A:min
+12.742857 14.147664 C
+14.147664 15.459591 G
+15.459591 16.876009 A:min
+16.876009 18.199546 A:min
+18.199546 19.557913 C
+19.557913 20.951111 G
+20.951111 22.286258 B:min
+22.286258 23.679455 B:min7
+23.679455 26.442630 D:7
+26.442630 27.800997 G
+27.800997 29.170975 C
+29.170975 31.876099 D
+31.876099 33.234467 A:min
+33.234467 34.616054 A:min7
+34.616054 35.951201 C:maj7
+35.951201 37.309569 G
+37.309569 38.691156 A:min7
+38.691156 40.049523 A:min7
+40.049523 41.384671 C:maj7
+41.384671 42.789478 G:7
+42.789478 44.147845 B:min7
+44.147845 45.506213 B:min7
+45.506213 48.222947 D:7
+48.222947 49.616145 G
+49.616145 50.916462 C
+50.916462 53.656417 D:7
+53.656417 56.361541 E:min
+56.361541 59.031836 A
+59.031836 60.413424 B:min
+60.413424 61.736961 A
+61.736961 62.271020 E
+62.271020 63.106938 A
+63.106938 63.594557 A
+63.594557 64.453696 D:7
+64.453696 67.158820 A:min7
+67.158820 68.517188 C:maj7
+68.517188 69.898775 G:7
+69.898775 71.280362 A:min7
+71.280362 72.627120 A:min7
+72.627120 73.962267 C:maj7
+73.962267 75.320634 G:7
+75.320634 78.025759 B:min7
+78.025759 80.765714 D:7
+80.765714 82.054421 G
+82.054421 83.436009 C
+83.436009 86.199183 D:7
+86.199183 91.632653 G
+91.632653 94.279727 C
+94.279727 97.031292 G
+97.031292 99.748027 D
+99.748027 102.418321 D:7
+102.418321 103.788299 G
+103.788299 105.146666 C
+105.146666 107.863401 D:7
+107.863401 110.545306 E:min
+110.545306 113.215600 A
+113.215600 114.573968 B:min
+114.573968 115.967165 A
+115.967165 116.512834 E
+116.512834 117.325532 A
+117.325532 117.836371 A
+117.836371 118.660680 D
+118.660680 121.389024 A:min7
+121.389024 122.759002 C:maj7
+122.759002 124.082539 G:7
+124.082539 126.834104 A:min7
+126.834104 128.169251 C:maj7
+128.169251 129.539229 G:7
+129.539229 132.255963 B:min7
+132.255963 134.972698 D:7
+134.972698 136.307845 G
+136.307845 137.701043 C
+137.701043 140.382947 D:7
+140.382947 141.764535 G:7
+141.764535 143.180952 C
+143.180952 145.920907 D
+145.920907 148.672471 G
+148.672471 150.042448 Bb
+150.042448 151.458866 D:7(#9)
+151.458866 154.380599 G
+154.380599 158.707959 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/11_-_Tell_Me_What_You_See.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,108 @@
+0.0000000 0.4978379 N
+0.4978379 4.1511330 G
+4.1511330 4.9870520 G
+4.9870520 5.8926300 C
+5.8926300 6.7749880 D
+6.7749880 7.6689560 G
+7.6689560 8.5048750 G
+8.5048750 9.3640130 C
+9.3640130 11.1403400 G
+11.1403400 12.0226980 G
+12.0226980 12.8702260 C
+12.8702260 13.7177550 D
+13.7177550 14.6233330 G
+14.6233330 15.4940810 C
+15.4940810 16.3416090 D
+16.3416090 18.1295460 G
+18.1295460 19.8594330 C
+19.8594330 21.6009290 G
+21.6009290 23.3540360 C
+23.3540360 25.1419720 G
+25.1419720 26.8486390 C
+26.8486390 28.5901360 G
+28.5901360 29.4841040 C
+29.4841040 30.3548520 D
+30.3548520 32.1195690 G
+32.1195690 33.0135370 G
+33.0135370 33.8610650 C
+33.8610650 34.7318140 D
+34.7318140 35.6373920 G
+35.6373920 36.4849200 G
+36.4849200 37.3324480 C
+37.3324480 39.0739450 G
+39.0739450 39.9446930 G
+39.9446930 40.8038320 C
+40.8038320 41.7094100 D
+41.7094100 42.6033780 G
+42.6033780 43.4160770 C
+43.4160770 44.2868250 D
+44.2868250 46.0631510 G
+46.0631510 47.8046480 C
+47.8046480 49.5461450 G
+49.5461450 51.2644210 C
+51.2644210 53.0175280 G
+53.0175280 54.7706340 C
+54.7706340 56.5005210 G
+56.5005210 57.3480490 C
+57.3480490 58.2652380 D
+58.2652380 60.0067340 G
+60.0067340 63.5245570 G:7
+63.5245570 67.1004300 C
+67.1004300 68.8303170 G
+68.8303170 70.5369840 D
+70.5369840 74.1012470 G
+74.1012470 75.0184350 G
+75.0184350 75.8543530 C
+75.8543530 76.7599310 D
+76.7599310 77.7003400 G
+77.7003400 78.5594780 G
+78.5594780 79.4302260 C
+79.4302260 81.2297730 G
+81.2297730 82.1469610 G
+82.1469610 82.9944890 C
+82.9944890 83.8536280 D
+83.8536280 84.7475960 G
+84.7475960 85.6531740 C
+85.6531740 86.5007020 D
+86.5007020 88.2770290 G
+88.2770290 90.0649650 C
+90.0649650 91.8645120 G
+91.8645120 93.5827890 C
+93.5827890 95.3707250 G
+95.3707250 97.1238320 C
+97.1238320 98.8885480 G
+98.8885480 99.7941260 C
+99.7941260 100.6880950 D
+100.6880950 102.4644210 G
+102.4644210 106.0402940 G:7
+106.0402940 109.5697270 C
+109.5697270 111.3228340 G
+111.3228340 113.0875510 D
+113.0875510 116.5937640 G
+116.5937640 117.4645120 G
+117.4645120 118.3468700 C
+118.3468700 119.2176190 D
+119.2176190 120.1464170 G
+120.1464170 121.0287750 G
+121.0287750 121.9227430 C
+121.9227430 123.6874600 G
+123.6874600 124.5698180 G
+124.5698180 125.4637860 C
+125.4637860 126.3693650 D
+126.3693650 127.2285030 G
+127.2285030 128.1224710 C
+128.1224710 129.0164390 D
+129.0164390 130.7811560 G
+130.7811560 132.5574820 C
+132.5574820 134.3105890 G
+134.3105890 136.0404760 C
+136.0404760 137.8400220 G
+137.8400220 139.5699090 C
+139.5699090 141.3578450 G
+141.3578450 142.2169840 C
+142.2169840 143.1109520 D
+143.1109520 144.8872780 G
+144.8872780 148.4515410 G:7
+148.4515410 152.2828340 C
+152.2828340 155.3062744 G
+155.3062744 159.5570441 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/12_-_I've_Just_Seen_a_Face.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,65 @@
+0.0000000 0.4403951 N
+0.4403951 1.4552185 A
+1.4552185 5.5791600 F#:min
+5.5791600 6.5892290 D
+6.5892290 7.5992970 G:maj6/5
+7.5992970 9.6542630 D
+9.6542630 10.6411110 E/5
+10.6411110 11.6279590 D/5
+11.6279590 15.6682310 A
+15.6682310 19.7317230 F#:min
+19.7317230 21.7982990 D
+21.7982990 22.7619270 E
+22.7619270 23.7836050 A
+23.7836050 27.7658270 A
+27.7658270 31.7596590 F#:min
+31.7596590 33.8146250 D
+33.8146250 34.7898630 E
+34.7898630 35.7302720 A
+35.7302720 37.7387980 E
+37.7387980 39.7241040 D
+39.7241040 40.7225620 A
+40.7225620 41.7094100 D
+41.7094100 43.7063260 A
+43.7063260 47.7698180 A
+47.7698180 51.7404300 F#:min
+51.7404300 53.7837860 D
+53.7837860 54.6855776 E
+54.6855776 55.7110430 A
+55.7110430 57.7079590 E
+57.7079590 59.7048750 D
+59.7048750 60.6568930 A
+60.6568930 61.6553510 D
+61.6553510 63.6174370 A
+63.6174370 67.6228790 A
+67.6228790 71.5934920 F#:min
+71.5934920 73.5787980 D
+73.5787980 74.5308160 E
+74.5308160 75.5408840 A
+75.5408840 77.5378000 E
+77.5378000 79.5463260 D
+79.5463260 80.5563940 A
+80.5563940 81.5316320 D
+81.5316320 83.5169380 A
+83.5169380 87.4643310 A
+87.4643310 91.4465530 F#:min
+91.4465530 93.4666890 D
+93.4666890 94.4883670 E
+94.4883670 95.4519950 A
+95.4519950 97.4256910 E
+97.4256910 99.4458270 D
+99.4458270 100.4210650 A
+100.4210650 101.4427430 D
+101.4427430 103.3816090 A
+103.3816090 105.3436960 E
+105.3436960 107.3638320 D
+107.3638320 108.3622900 A
+108.3622900 109.3491380 D
+109.3491380 111.2996140 A
+111.2996140 113.2733100 E
+113.2733100 115.2470060 D
+115.2470060 116.2802940 A
+116.2802940 118.3513848 D
+118.3513848 119.2756680 E
+119.2756680 123.1765828 A
+123.1765828 127.0061051 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/13_-_Yesterday.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,97 @@
+0.0000000 0.4595427 N
+0.4595427 5.3469610 F:maj(*3)
+5.3469610 7.8431060 F:maj(*3)
+7.8431060 9.0621540 E:min
+9.0621540 10.2347610 A:7
+10.2347610 12.2084580 D:min
+12.2084580 12.7773460 D:min/b7
+12.7773460 13.9963940 Bb:maj7
+13.9963940 15.2502720 C:7
+15.2502720 17.6303170 F
+17.6303170 18.8377550 D:min
+18.8377550 20.0800220 G
+20.0800220 20.7185710 Bb
+20.7185710 22.5761670 F
+22.5761670 25.0450754 F
+25.0450754 26.2681400 A:sus4/5
+26.2681400 27.4871880 A
+27.4871880 29.3563940 D:min
+29.3563940 29.9368930 A:min/b3
+29.9368930 31.1675510 Bb:maj
+31.1675510 32.3865980 C
+32.3865980 32.8955960 Bb/5
+32.8955960 33.6869160 F
+33.6869160 34.8246930 F
+34.8246930 36.0901810 D:min7
+36.0901810 37.2627890 G:7
+37.2627890 37.9013370 Bb
+37.9013370 39.8402040 F
+39.8402040 41.0940810 E:min7(4)
+41.0940810 42.3015190 A
+42.3015190 42.9516780 D:min
+42.9516780 43.5553960 D:min/b7
+43.5553960 44.1823350 Bb
+44.1823350 44.8092740 Bb/7
+44.8092740 45.9934920 G
+45.9934920 47.2241490 C
+47.2241490 49.7086840 F
+49.7086840 50.9393420 E:min7(4)
+50.9393420 52.1351700 A
+52.1351700 52.7504980 D:min
+52.7504980 53.4238770 D:min/b7
+53.4238770 54.0508160 Bb
+54.0508160 54.6313150 Bb/7
+54.6313150 55.8851920 G:min
+55.8851920 57.1274600 C
+57.1274600 59.7164850 F
+59.7164850 62.1081400 F
+62.1081400 63.3271880 A:sus4/5
+63.3271880 64.6739450 A
+64.6739450 66.6012010 D:min
+66.6012010 67.2397500 A:min/b3
+67.2397500 68.4820180 Bb
+68.4820180 69.7358950 C
+69.7358950 70.2908807 Bb/5
+70.2908807 71.0710430 F
+71.0710430 72.2552600 F
+72.2552600 73.5091380 D:min7
+73.5091380 74.7514050 G:7
+74.7514050 75.4596140 Bb
+75.4596140 77.3172100 F
+77.3172100 78.6175280 E:min7(4)
+78.6175280 79.8017460 A
+79.8017460 80.4402940 D:min
+80.4402940 81.1368930 D:min/b7
+81.1368930 81.7754420 Bb
+81.7754420 82.3907700 Bb/7
+82.3907700 83.7026980 G:min
+83.7026980 84.8172560 C
+84.8172560 85.9727743 F
+85.9727743 87.2785710 F:7
+87.2785710 88.4976190 E:min7(4)
+88.4976190 89.7747160 A
+89.7747160 90.3319950 D:min
+90.3319950 90.9821540 D:min/b7
+90.9821540 91.5858730 Bb
+91.5858730 92.2128110 Bb/7
+92.2128110 93.4434690 G:min
+93.4434690 94.6741260 C
+94.6741260 97.2747610 F
+97.2747610 99.8405660 F
+99.8405660 101.0596140 E:min7(4)
+101.0596140 102.3599310 A
+102.3599310 103.6718590 D:min
+103.6718590 104.9025170 D:min
+104.9025170 106.0867340 Bb:maj7
+106.0867340 107.3406120 C:maj6
+107.3406120 107.9159367 Bb:maj7/5
+107.9159367 109.8251470 F
+109.8251470 111.1022440 D:min
+111.1022440 112.3096820 G
+112.3096820 113.0178910 Bb
+113.0178910 114.8870970 F
+114.8870970 116.2802940 F/5
+116.2802940 117.7663710 G/3
+117.7663710 118.6487300 Bb
+118.6487300 123.1191400 F
+123.1191400 127.1592860 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/14_-_Dizzy_Miss_Lizzie.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+0.0000000 0.4020998 N
+0.4020998 1.8291380 N
+1.8291380 8.6674140 A
+8.6674140 12.1039680 D
+12.1039680 15.5869610 A
+15.5869610 17.2820180 E
+17.2820180 19.0002940 D
+19.0002940 20.7766210 A
+20.7766210 22.4020180 E
+22.4020180 29.3099540 A
+29.3099540 32.7697270 D
+32.7697270 36.2875510 A
+36.2875510 38.0522670 E
+38.0522670 39.8053740 D
+39.8053740 41.8255100 A
+41.8255100 43.2999770 E
+43.2999770 50.2195230 A
+50.2195230 53.6676870 D
+53.6676870 57.2435600 A
+57.2435600 58.9966660 E
+58.9966660 60.7729930 D
+60.7729930 62.5493190 A
+62.5493190 64.2908160 E
+64.2908160 71.3729020 A
+71.3729020 74.9371650 D
+74.9371650 78.4201580 A
+78.4201580 80.2313150 E
+80.2313150 81.9728110 D
+81.9728110 83.7723580 A
+83.7723580 85.4674140 E
+85.4674140 92.5146710 A
+92.5146710 95.9744440 D
+95.9744440 99.5503170 A
+99.5503170 101.2918140 E
+101.2918140 103.0913600 D
+103.0913600 104.8909070 A
+104.8909070 106.6091830 E
+106.6091830 113.7144890 A
+113.7144890 117.2787520 D
+117.2787520 120.8081850 A
+120.8081850 122.6077320 E
+122.6077320 124.3608390 D
+124.3608390 126.2210530 A
+126.2210530 128.2966210 E
+128.2966210 134.8678680 A
+134.8678680 138.4321310 D
+138.4321310 141.9615640 A
+141.9615640 143.7727210 E
+143.7727210 145.4909970 D
+145.4909970 147.3021540 A
+147.3021540 148.9391600 E
+148.9391600 156.1373460 A
+156.1373460 159.7248290 D
+159.7248290 163.3007020 A
+163.3007020 165.0770290 E
+165.0770290 166.8185260 D
+166.8185260 168.6993420 A
+168.6993420 171.9455485 A:maj6
+171.9455485 174.0517858 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+/.DS_Store/1.1.1.1/Fri Sep 23 09:24:38 2005//
+/01_-_Help!.lab/1.2/Tue Oct 17 21:54:13 2006//
+/02_-_The_Night_Before.lab/1.3/Tue Oct 17 21:54:13 2006//
+/03_-_You've_Got_To_Hide_Your_Love_Away.lab/1.2/Tue Oct 17 21:54:13 2006//
+/04_-_I_Need_You.lab/1.3/Tue Oct 17 21:54:13 2006//
+/05_-_Another_Girl.lab/1.1.1.1/Fri Sep 23 09:24:38 2005//
+/06_-_You're_Going_to_Lose_That_Girl.lab/1.3/Tue Aug  1 22:51:53 2006//
+/07_-_Ticket_To_Ride.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/08_-_Act_Naturally.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/09_-_It's_Only_Love.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/10_-_You_Like_Me_Too_Much.lab/1.2/Wed Aug  2 00:41:06 2006//
+/11_-_Tell_Me_What_You_See.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/12_-_I've_Just_Seen_a_Face.lab/1.2/Wed Aug  2 00:41:06 2006//
+/13_-_Yesterday.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/14_-_Dizzy_Miss_Lizzie.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/05final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/05final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/01_-_Drive_My_Car.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,84 @@
+0.0000000 1.1297091 N
+1.1297091 3.0444702 N
+3.0444702 5.2081502 D
+5.2081502 7.1581170 D
+7.1581170 9.0505440 G
+9.0505440 11.0358500 D
+11.0358500 12.9979360 G
+12.9979360 14.9832420 D
+14.9832420 16.9337180 G
+16.9337180 20.7417910 A:min7(*5,b6)
+20.7417910 22.6806570 B:min
+22.6806570 24.6543530 G:7
+24.6543530 26.5816090 B:min
+26.5816090 28.5088660 G:7
+28.5088660 30.4941720 B:min
+30.4941720 31.4345800 E:7
+31.4345800 32.4214280 A
+32.4214280 33.4314960 D
+33.4314960 34.4067340 G
+34.4067340 36.3456000 A
+36.3456000 38.3076870 D
+38.3076870 40.3046030 G
+40.3046030 42.2782990 D
+42.2782990 44.2519950 G
+44.2519950 46.2256910 D
+46.2256910 48.1761670 G
+48.1761670 52.0771200 A:min7(*5,b6)
+52.0771200 54.0275960 B:min
+54.0275960 55.9316320 G:7
+55.9316320 57.9517680 B:min
+57.9517680 59.8790240 G:7
+59.8790240 61.8411110 B:min
+61.8411110 62.8395690 E:7
+62.8395690 63.8264170 A
+63.8264170 64.8364850 D
+64.8364850 65.8117230 G
+65.8117230 67.7854190 A:7(#9)
+67.7854190 69.7475050 D
+69.7475050 71.6863710 G
+71.6863710 73.6368480 D
+73.6368480 75.6221540 G
+75.6221540 77.5842400 D
+77.5842400 79.5231060 G
+79.5231060 83.4240580 A:min(*5)
+83.4240580 85.4093650 B:min
+85.4093650 87.3017910 G:7
+87.3017910 89.3103170 B:min
+89.3103170 91.2724030 G:7
+91.2724030 93.2460990 B:min
+93.2460990 94.1981170 E:7
+94.1981170 95.1965750 A
+95.1965750 96.1950340 D
+96.1950340 97.1586620 G
+97.1586620 99.0859180 A
+99.0859180 101.0712240 D
+101.0712240 103.0333100 G
+103.0333100 104.9605660 D
+104.9605660 106.9807020 G
+106.9807020 108.9195690 D
+108.9195690 110.8816550 G
+110.8816550 114.7826070 A:min7(*5,b6)
+114.7826070 116.7214730 B:min
+116.7214730 118.6603400 G:7
+118.6603400 120.6572560 B:min
+120.6572560 122.5961220 G:7
+122.5961220 124.5814280 B:min
+124.5814280 125.5450560 E:7
+125.5450560 126.5551240 A
+126.5551240 127.5187520 D
+127.5187520 128.4939900 G
+128.4939900 130.4792970 A:7(#9)
+130.4792970 131.5009750 D
+131.5009750 132.4646030 G
+132.4646030 134.4150790 A:7(#9)
+134.4150790 135.4251470 D
+135.4251470 136.4003850 G
+136.4003850 138.3740810 A:7(#9)
+138.3740810 139.3609290 D
+139.3609290 140.2781170 G
+140.2781170 142.2518140 A:7(#9)
+142.2518140 143.2386620 D
+143.2386620 144.1906800 G
+144.1906800 146.1759860 A:7(#9)
+146.1759860 149.7917624 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/02_-_Norwegian_Wood_(This_Bird_Has_Flown).lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+0.0000000 0.4212474 N
+0.4212474 5.3469610 E
+5.3469610 6.2989790 D
+6.2989790 8.3191150 E
+8.3191150 13.2185260 E
+13.2185260 14.1937640 D
+14.1937640 16.1674600 E
+16.1674600 21.0900900 E
+21.0900900 22.0304980 D
+22.0304980 24.0041950 E
+24.0041950 28.9500450 E
+28.9500450 29.9601130 D
+29.9601130 31.9686390 E
+31.9686390 35.9856910 E:min
+35.9856910 39.9795230 A
+39.9795230 43.9269160 E:min
+43.9269160 45.9122220 F#:min
+45.9122220 47.8859180 B
+47.8859180 52.9594780 E
+52.9594780 53.9927660 D
+53.9927660 55.9664620 E
+55.9664620 61.0400220 E
+61.0400220 62.0036500 D
+62.0036500 64.0934460 E
+64.0934460 69.1670060 E
+69.1670060 70.1306340 D
+70.1306340 72.1623800 E
+72.1623800 77.2707700 E
+77.2707700 78.2692290 D
+78.2692290 80.3241950 E
+80.3241950 84.4457360 E:min
+84.4457360 88.4743990 A
+88.4743990 92.5262810 E:min
+92.5262810 94.5348070 F#:min
+94.5348070 96.5897730 B
+96.5897730 101.6517230 E
+101.6517230 102.7082310 D
+102.7082310 104.7515870 E
+104.7515870 109.9064170 E
+109.9064170 110.9280950 D
+110.9280950 112.9946710 E
+112.9946710 118.0682310 E
+118.0682310 119.1131290 D
+119.1131290 122.6404497 E
+122.6404497 125.2828201 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/03_-_You_Won't_See_Me.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,94 @@
+0.0000000 0.4595427 N
+0.4595427 1.2254190 D
+1.2254190 4.4413830 A
+4.4413830 6.4382990 A
+6.4382990 8.4584350 B
+8.4584350 10.5482310 D
+10.5482310 12.5225377 A
+12.5225377 14.5652830 A
+14.5652830 16.5621990 B
+16.5621990 18.6519950 D
+18.6519950 20.6489110 A
+20.6489110 22.7038770 A:7
+22.7038770 24.7356230 D
+24.7356230 26.7905890 D:min
+26.7905890 28.8107250 A
+28.8107250 30.8308610 A
+30.8308610 32.8742170 B
+32.8742170 33.6985260 D
+33.6985260 36.8216090 A
+36.8216090 37.6575280 D
+37.6575280 40.8851020 A
+40.8851020 42.9168480 A
+42.9168480 45.0066430 B
+45.0066430 47.0732190 D
+47.0732190 49.1281850 A
+49.1281850 51.1715410 A
+51.1715410 53.2265070 B
+53.2265070 55.3163030 D
+55.3163030 57.3480490 A
+57.3480490 59.4378450 A:7
+59.4378450 61.4928110 D
+61.4928110 63.5593870 D:min
+63.5593870 65.6491830 A
+65.6491830 67.6693190 A
+67.6693190 69.7707250 B
+69.7707250 70.5834240 D
+70.5834240 73.8342170 A
+73.8342170 74.6353060 D
+74.6353060 77.9209290 A
+77.9209290 80.0107250 B:min
+80.0107250 82.0656910 B:hdim7/b3
+82.0656910 84.1322670 D:dim7
+84.1322670 86.2685030 A
+86.2685030 90.3087750 B
+90.3087750 92.4101810 E:sus4(b7)
+92.4101810 94.5115870 E
+94.5115870 96.6246030 A
+96.6246030 98.7143990 B
+98.7143990 100.8390240 D
+100.8390240 102.8475510 A
+102.8475510 104.9489560 A
+104.9489560 107.0155320 B
+107.0155320 109.1517680 D
+109.1517680 111.2183440 A
+111.2183440 113.3313600 A:7
+113.3313600 115.4443760 D
+115.4443760 117.5457820 D:min
+117.5457820 119.6587980 A
+119.6587980 121.8182530 A
+121.8182530 123.8848290 B
+123.8848290 124.6743080 D
+124.6743080 128.0295910 A
+128.0295910 128.7958500 D
+128.7958500 132.1163030 A
+132.1163030 134.2177090 B:min
+134.2177090 136.2610650 B:hdim7/b3
+136.2610650 138.3624710 D:dim7
+138.3624710 140.4754870 A
+140.4754870 144.6899090 B
+144.6899090 146.8261450 E:sus4(b7)
+146.8261450 148.8578910 E
+148.8578910 150.9709070 A
+150.9709070 153.0955320 B:7
+153.0955320 155.2085480 D
+155.2085480 157.3099540 A
+157.3099540 159.4113600 A
+159.4113600 161.5359860 B:7
+161.5359860 163.6606120 D
+163.6606120 165.7155780 A
+165.7155780 167.7821540 A:7
+167.7821540 169.9532190 D
+169.9532190 172.0430150 D:min
+172.0430150 174.2256910 A
+174.2256910 176.3735370 A
+176.3735370 178.4749430 B:7
+178.4749430 179.2876410 D
+179.2876410 182.6661450 A
+182.6661450 183.3859630 D
+183.3859630 186.8225170 A
+186.8225170 188.9007020 A
+188.9007020 190.9904980 B:7
+190.9904980 193.0919040 D
+193.0919040 197.2482760 A
+197.2482760 202.1796266 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/04_-_Nowhere_Man.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,74 @@
+0.0000000 0.4403951 N
+0.4403951 2.5373460 E
+2.5373460 4.5110430 B
+4.5110430 6.5079590 A
+6.5079590 8.5048750 E
+8.5048750 10.6643310 A:maj6
+10.6643310 12.6728570 A:min
+12.6728570 16.6550790 E
+16.6550790 18.6287750 E
+18.6287750 20.6605210 B
+20.6605210 22.6109970 A
+22.6109970 24.5730830 E
+24.5730830 26.5700000 A:maj6
+26.5700000 28.5204760 A:min
+28.5204760 32.4446480 E
+32.4446480 34.3835140 G#:min
+34.3835140 36.4036500 A
+36.4036500 38.3541260 G#:min
+38.3541260 40.3510430 A
+40.3510430 42.3711790 G#:min
+42.3711790 44.3100450 A
+44.3100450 46.2721310 A
+46.2721310 48.1993870 B
+48.1993870 50.1963030 E
+50.1963030 52.1700000 B
+52.1700000 54.1320860 A
+54.1320860 56.1290020 E
+56.1290020 58.1026980 A:maj6
+58.1026980 60.0880040 A:min
+60.0880040 64.0121760 E
+64.0121760 66.0439220 E
+66.0439220 68.0060090 B
+68.0060090 69.9680950 A
+69.9680950 71.9650110 E
+71.9650110 73.9735370 A:maj6
+73.9735370 75.8775730 A:min
+75.8775730 79.8597950 E
+79.8597950 81.8102720 G#:min
+81.8102720 83.7839680 A
+83.7839680 85.7576640 G#:min
+85.7576640 87.8126300 A
+87.8126300 89.7747160 G#:min
+89.7747160 91.7716320 A
+91.7716320 93.7801580 A
+93.7801580 95.6841950 B
+95.6841950 97.6578910 E
+97.6578910 99.6548070 B
+99.6548070 101.5936730 A
+101.5936730 103.5905890 E
+103.5905890 105.5526750 A:maj6
+105.5526750 107.5612010 A:min
+107.5612010 111.5202040 E
+111.5202040 113.4474600 G#:min
+113.4474600 115.4327660 A
+115.4327660 117.3948520 G#:min
+117.3948520 119.4265980 A
+119.4265980 121.4002940 G#:min
+121.4002940 123.3739900 A
+123.3739900 125.3825170 A
+125.3825170 127.3097730 B
+127.3097730 129.2718590 E
+129.2718590 131.2919950 B
+131.2919950 133.2424710 A
+133.2424710 135.2742170 E
+135.2742170 137.2479130 A:maj6
+137.2479130 139.2680490 A:min
+139.2680490 143.1573920 E
+143.1573920 145.1194780 A:maj6
+145.1194780 147.1163940 A:min
+147.1163940 151.0870060 E
+151.0870060 153.0839220 A:maj6
+153.0839220 155.0460090 A:min
+155.0460090 161.3377719 E
+161.3377719 163.9801423 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/05_-_Think_For_Yourself.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,63 @@
+0.0000000 0.4212474 N
+0.4212474 3.5125850 G
+3.5125850 3.7912240 G
+3.7912240 4.0930830 G#
+4.0930830 5.9158500 A:min
+5.9158500 7.7734460 D:min
+7.7734460 9.6194330 Bb
+9.6194330 11.4538090 C
+11.4538090 15.1225620 G
+15.1225620 16.9569380 A:min
+16.9569380 18.8261450 D:min
+18.8261450 20.6837410 Bb
+20.6837410 22.5297270 C
+22.5297270 24.3641040 G
+24.3641040 26.2449200 A:min
+26.2449200 29.9020630 C
+29.9020630 33.5243760 G
+33.5243760 35.3007020 Eb/5
+35.3007020 37.1234690 D
+37.1234690 40.8270520 G
+40.8270520 42.6846480 A:min
+42.6846480 44.5074140 D:min
+44.5074140 46.3766210 Bb
+46.3766210 48.1993870 C
+48.1993870 51.9378000 G
+51.9378000 53.8186160 A:min
+53.8186160 55.7110430 D:min
+55.7110430 57.5802490 Bb
+57.5802490 59.4494550 C
+59.4494550 61.3302720 G
+61.3302720 63.2226980 A:min
+63.2226980 66.8914510 C
+66.8914510 70.5485940 G
+70.5485940 72.3365300 Eb/5
+72.3365300 74.1709070 D
+74.1709070 77.8860990 G
+77.8860990 79.7088660 A:min
+79.7088660 81.5896820 D:min
+81.5896820 83.4008390 Bb
+83.4008390 85.2932650 C
+85.2932650 89.0316780 G
+89.0316780 90.8776640 A:min
+90.8776640 92.7700900 D:min
+92.7700900 94.6160770 Bb
+94.6160770 96.5201130 C
+96.5201130 98.4125390 G
+98.4125390 100.3165750 A:min
+100.3165750 104.0549880 C
+104.0549880 107.6540810 G
+107.6540810 109.4536280 Eb/5
+109.4536280 111.2763940 D
+111.2763940 114.9451470 G
+114.9451470 118.6022900 C
+118.6022900 122.2246030 G
+122.2246030 124.0589790 Eb/5
+124.0589790 125.9165750 D
+125.9165750 127.7528619 C:7
+127.7528619 129.5504980 G
+129.5504980 131.3732650 Eb/5
+131.3732650 133.1960310 D
+133.1960310 135.0187980 C:7
+135.0187980 136.4003850 G
+136.4003850 139.1456906 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/06_-_The_Word.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,65 @@
+0.0000000 0.4020998 N
+0.4020998 1.3020376 G
+1.3020376 5.3469610 D:7(#9)
+5.3469610 13.3230150 D:7(#9)
+13.3230150 17.2936280 G:7
+17.2936280 21.2642400 D:7(#9)
+21.2642400 21.9724480 A:sus4
+21.9724480 23.1914960 A
+23.1914960 23.8184350 G:sus4
+23.8184350 24.9910430 G
+24.9910430 28.7642850 D:7(#9)
+28.7642850 30.7031510 D
+30.7031510 32.6768480 C
+32.6768480 34.6505440 F
+34.6505440 36.6474600 G
+36.6474600 44.6235140 D:7(#9)
+44.6235140 48.5825170 G:7
+48.5825170 52.5531290 D:7(#9)
+52.5531290 53.3077770 A:sus4
+53.3077770 54.4107250 A
+54.4107250 55.1537640 G:sus4
+55.1537640 56.2683210 G
+56.2683210 60.0880040 D:7(#9)
+60.0880040 62.0384800 D
+62.0384800 63.9773460 C
+63.9773460 65.9162130 F
+65.9162130 67.9363490 G
+67.9363490 75.9007930 D:7(#9)
+75.9007930 79.8365750 G:7
+79.8365750 83.8304080 D:7(#9)
+83.8304080 84.5850560 A:sus4
+84.5850560 85.6664125 A
+85.6664125 86.4310430 G:sus4
+86.4310430 87.6500900 G
+87.6500900 91.3768930 D:7(#9)
+91.3768930 93.2693190 D
+93.2693190 95.2546250 C
+95.2546250 97.2399310 F
+97.2399310 99.2136280 G
+99.2136280 107.2129020 D:7(#9)
+107.2129020 111.1835140 G:7
+111.1835140 115.1309070 D:7(#9)
+115.1309070 115.8739450 A:sus4
+115.8739450 117.0697730 A
+117.0697730 117.8592510 G:sus4
+117.8592510 119.0318590 G
+119.0318590 122.9560310 D:7(#9)
+122.9560310 124.8368480 D
+124.8368480 126.8105440 C:maj(9)
+126.8105440 128.7842400 F:maj6
+128.7842400 130.7347160 G
+130.7347160 134.7285480 D
+134.7285480 138.7804300 D:7(#9)
+138.7804300 142.7278230 G:7
+142.7278230 146.6868250 D:7(#9)
+146.6868250 147.4995230 A:sus4
+147.4995230 148.5676410 A
+148.5676410 149.3687300 G:sus4
+149.3687300 150.5065070 G
+150.5065070 154.3378000 D:7(#9)
+154.3378000 156.2418360 D
+156.2418360 158.1923120 C:maj(9)
+158.1923120 160.1892290 F:maj6
+160.1892290 162.0236050 G
+162.0236050 163.6163377 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/07_-_Michelle.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,94 @@
+0.0000000 0.4212474 N
+0.4212474 1.4153749 F:min/5
+1.4153749 2.3748070 E:aug
+2.3748070 3.3848750 F:min7
+3.3848750 4.3717230 F:min6/5
+4.3717230 5.4570692 C#:maj7/3
+5.4570692 5.9166119 Bb:min/5
+5.9166119 6.4385684 C#/3
+6.4385684 8.4700450 C
+8.4700450 10.5714510 F
+10.5714510 12.6148070 Bb:min7
+12.6148070 14.6813830 Eb:maj6
+14.6813830 16.7363490 B:dim7
+16.7363490 17.7696370 C
+17.7696370 18.8029250 B:dim7
+18.8029250 20.8695010 C
+20.8695010 22.9962810 F
+22.9962810 24.9910430 Bb:min7
+24.9910430 27.0343990 Eb:maj6
+27.0343990 29.0313150 B:dim7
+29.0313150 30.0762130 C
+30.0762130 31.0862810 B:dim7
+31.0862810 33.1644670 C
+33.1644670 37.2743990 F:min
+37.2743990 39.2829250 Ab:7
+39.2829250 41.3843310 Db
+41.3843310 43.3580270 C
+43.3580270 45.3781630 F:min
+45.3781630 46.3882310 F:min/5
+46.3882310 47.3750790 E:aug
+47.3750790 48.4083670 F:min7
+48.4083670 49.4068250 F:min6/5
+49.4068250 51.4501810 C#:maj7/3
+51.4501810 53.5631970 C
+53.5631970 55.5136730 F
+55.5136730 57.5918590 Bb:min7
+57.5918590 59.5771650 Eb:maj6
+59.5771650 61.6669610 B:dim7
+61.6669610 62.6189790 C
+62.6189790 63.6174370 B:dim7
+63.6174370 65.6724030 C
+65.6724030 69.7242850 F:min
+69.7242850 71.6863710 Ab:7
+71.6863710 73.7529470 Db
+73.7529470 75.7498630 C
+75.7498630 77.7932190 F:min
+77.7932190 78.8032870 F:min/5
+78.8032870 79.8017460 E:aug
+79.8017460 80.8466430 F:min7
+80.8466430 81.8334920 F:min6/5
+81.8334920 83.8884580 C#:maj7/3
+83.8884580 85.9085940 C
+85.9085940 87.9055100 F
+87.9055100 89.9488660 Bb:min7
+89.9488660 91.9690020 Eb:maj6
+91.9690020 93.9891380 B:dim7
+93.9891380 94.9992060 C
+94.9992060 95.9976640 B:dim7
+95.9976640 98.0410200 C
+98.0410200 102.0580720 F:min
+102.0580720 104.0898180 Ab:7
+104.0898180 106.1099540 Db
+106.1099540 108.1881400 C
+108.1881400 110.2082760 F:min
+110.2082760 111.2284734 F:min/5
+111.2284734 112.2168020 E:aug
+112.2168020 113.2268700 F:min7
+113.2268700 114.1904980 F:min6/5
+114.1904980 116.2570740 C#:maj7/3
+116.2570740 118.3700900 C
+118.3700900 120.4134460 F
+120.4134460 122.5961220 Bb:min7
+122.5961220 124.7323580 Eb:maj6
+124.7323580 126.8685940 B:dim7
+126.8685940 127.9715410 C
+127.9715410 128.9816090 B:dim7
+128.9816090 131.1991150 C
+131.1991150 132.3020630 F:min/5
+132.3020630 133.3817910 E:aug
+133.3817910 134.5079590 F:min7
+134.5079590 135.5528570 F:min6/5
+135.5528570 137.7007020 C#:maj7/3
+137.7007020 139.8369380 C
+139.8369380 141.9731740 F
+141.9731740 144.2139000 Bb:min7
+144.2139000 146.4314050 Eb:maj6
+146.4314050 148.6140810 B:dim7
+148.6140810 149.7286390 C
+149.7286390 150.8083670 B:dim7
+150.8083670 153.0258730 C
+153.0258730 155.1737180 F
+155.1737180 157.3680040 Bb:min7
+157.3680040 159.5042400 Eb:maj6
+159.5042400 162.2377097 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/08_-_What_Goes_On.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,61 @@
+0.0000000 0.4595427 N
+0.4595427 1.4808390 B
+1.4808390 2.6766660 E
+2.6766660 3.8841040 B
+3.8841040 6.3570290 E
+6.3570290 13.7177550 E
+13.7177550 16.1790700 A
+16.1790700 23.6326750 E
+23.6326750 26.1404300 A
+26.1404300 27.3594780 B:sus4
+27.3594780 28.6133560 B
+28.6133560 31.0514510 E
+31.0514510 33.5708160 E
+33.5708160 36.0321310 A:min
+36.0321310 38.5282760 E
+38.5282760 41.0360310 A:min
+41.0360310 42.3131290 A:min
+42.3131290 43.5553960 B
+43.5553960 46.0167120 E
+46.0167120 48.5476870 B
+48.5476870 55.9084120 E
+55.9084120 58.3929470 A
+58.3929470 65.6956230 E
+65.6956230 68.2614280 A
+68.2614280 69.5385260 B:sus4
+69.5385260 70.7691830 B
+70.7691830 73.2304980 E
+73.2304980 75.7862451 E
+75.7862451 78.1988441 A:min
+78.1988441 80.7263288 E
+80.7263288 83.1918590 A:min
+83.1918590 84.4341260 A:min
+84.4341260 85.6531740 B
+85.6531740 88.1144890 E
+88.1144890 90.5874140 B
+90.5874140 97.9829700 E
+97.9829700 100.4326750 A
+100.4326750 107.7934010 E
+107.7934010 110.2779360 A
+110.2779360 111.4505440 B
+111.4505440 112.7160310 B:7
+112.7160310 115.2005660 E
+115.2005660 117.6851020 E
+117.6851020 120.1696370 A:min
+120.1696370 122.6213021 E
+122.6213021 125.1387070 A:min
+125.1387070 126.3345350 A:min
+126.3345350 127.6348520 B
+127.6348520 130.0613370 E
+130.0613370 132.5226530 B
+132.5226530 139.9298180 E
+139.9298180 142.4143530 A
+142.4143530 149.8099090 E
+149.8099090 152.3408840 A
+152.3408840 153.5367120 B:sus4
+153.5367120 154.7789790 B
+154.7789790 157.2286840 E
+157.2286840 159.7364390 E:7
+159.7364390 161.4547160 E
+161.4547160 165.8757558 E
+165.8757558 170.3945920 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/09_-_Girl.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,94 @@
+0.0000000 0.4403951 N
+0.4403951 1.1297091 N
+1.1297091 2.3520180 C:min
+2.3520180 3.5942850 G:7
+3.5942850 6.1252600 C:min
+6.1252600 8.6794550 F:min
+8.6794550 9.8985030 Eb
+9.8985030 11.1291600 G
+11.1291600 12.3946480 C:min
+12.3946480 13.6485260 G:7
+13.6485260 16.1098410 C:min
+16.1098410 18.6524260 F:min
+18.6524260 21.1253510 C:min
+21.1253510 22.3211790 Eb
+22.3211790 23.5634460 G:min/5
+23.5634460 24.8405440 Ab/3
+24.8405440 26.0595910 Bb
+26.0595910 27.2902490 Eb
+27.2902490 28.5441260 G:min/5
+28.5441260 29.8096140 Ab/3
+29.8096140 31.0054420 Bb
+31.0054420 32.2593190 C:min
+32.2593190 33.5015870 G:7
+33.5015870 36.0325620 C:min
+36.0325620 38.5287070 F:min
+38.5287070 39.8290240 Eb
+39.8290240 41.0248520 G
+41.0248520 42.2903400 C:min
+42.2903400 43.4977770 G:7
+43.4977770 46.0287520 C:min
+46.0287520 48.4784580 F:min
+48.4784580 51.0442630 C:min
+51.0442630 52.2749200 Eb
+52.2749200 53.5171880 G:min/5
+53.5171880 54.7942850 Ab/3
+54.7942850 56.0249430 Bb
+56.0249430 57.3020400 Eb
+57.3020400 58.5326980 G:min/5
+58.5326980 59.8097950 Ab/3
+59.8097950 61.0520630 Bb
+61.0520630 63.5133780 F:min
+63.5133780 65.9979130 C
+65.9979130 68.4243990 F:min
+68.4243990 70.9205440 C
+70.9205440 73.4166890 F:min
+73.4166890 75.8315640 C
+75.8315640 78.2812690 F:min
+78.2812690 80.6961450 Ab
+80.6961450 81.9134807 Eb
+81.9134807 83.1922900 G:min/5
+83.1922900 84.4345570 Ab/3
+84.4345570 85.6652150 Bb
+85.6652150 86.9074820 Eb
+86.9074820 88.1497500 G:min/5
+88.1497500 89.3920180 Ab/3
+89.3920180 90.5762350 Bb
+90.5762350 91.8881630 C:min
+91.8881630 93.1072100 G:7
+93.1072100 95.6033560 C:min
+95.6033560 98.0762810 F:min
+98.0762810 99.3417680 Eb
+99.3417680 100.5492060 G
+100.5492060 101.7914730 C:min
+101.7914730 103.0337410 G:7
+103.0337410 105.4950560 C:min
+105.4950560 108.0144210 F:min
+108.0144210 110.5337860 C:min
+110.5337860 111.8108840 Eb
+111.8108840 112.9951020 G:min/5
+112.9951020 114.2605890 Ab/3
+114.2605890 115.4912470 Bb
+115.4912470 116.7335140 Eb
+116.7335140 117.9525620 G:min/5
+117.9525620 119.1948290 Ab/3
+119.1948290 120.4254870 Bb
+120.4254870 121.6677550 C:min
+121.6677550 122.8635820 G:7
+122.8635820 125.3481170 C:min
+125.3481170 127.8674820 F:min
+127.8674820 129.0981400 Eb
+129.0981400 130.3868480 G
+130.3868480 131.6639450 C:min
+131.6639450 132.8829930 G:7
+132.8829930 135.3907480 C:min
+135.3907480 137.8636730 F:min
+137.8636730 140.3830380 C:min
+140.3830380 141.6717460 Eb
+141.6717460 142.9140130 G:min/5
+142.9140130 144.1330610 Ab/3
+144.1330610 145.3637180 Bb
+145.3637180 146.5827660 Eb
+146.5827660 147.8134240 G:min/5
+147.8134240 148.9976410 Ab/3
+148.9976410 153.3149229 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/10_-_I'm_Looking_Through_You.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,135 @@
+0.0000000 0.4020998 N
+0.4020998 1.7246480 Ab/5
+1.7246480 3.1294550 Eb
+3.1294550 3.8028340 Ab
+3.8028340 4.4646030 Db
+4.4646030 5.1728110 Ab
+5.1728110 5.8229700 Db
+5.8229700 6.5311790 Ab
+6.5311790 7.1929470 Db
+7.1929470 7.9243760 Ab
+7.9243760 8.5977550 Db
+8.5977550 10.0141720 Bb:min
+10.0141720 11.3957590 F:min
+11.3957590 12.7657360 Eb
+12.7657360 13.4799183 Ab
+13.4799183 14.1937640 Db
+14.1937640 15.5869610 Bb:min
+15.5869610 16.9685480 F:min
+16.9685480 18.3617460 Eb
+18.3617460 19.7781630 F:min
+19.7781630 21.1829700 Bb:min
+21.1829700 21.8795690 Ab
+21.8795690 22.5529470 Db
+22.5529470 23.9461450 Eb
+23.9461450 24.6311330 Ab
+24.6311330 25.3509520 Db
+25.3509520 26.7325390 Bb:min
+26.7325390 28.1025170 Db
+28.1025170 28.7875050 Ab
+28.7875050 29.4957140 Db
+29.4957140 30.2039220 Ab
+30.2039220 30.8773010 Db
+30.8773010 31.5739000 Ab
+31.5739000 32.2704980 Db
+32.2704980 32.9147436 Ab
+32.9147436 33.5849100 Db
+33.5849100 35.0568930 Bb:min
+35.0568930 36.4617000 F:min
+36.4617000 37.8084580 Eb
+37.8084580 38.5282760 Ab
+38.5282760 39.2132650 Db
+39.2132650 40.6180720 Bb:min
+40.6180720 41.9764390 F:min
+41.9764390 43.3928570 Eb
+43.3928570 44.7512240 F:min
+44.7512240 46.1676410 Bb:min
+46.1676410 46.8410200 Ab
+46.8410200 47.5608390 Db
+47.5608390 48.9888660 Eb
+48.9888660 49.6854640 Ab
+49.6854640 50.3704530 Db
+50.3704530 51.7520400 Bb:min
+51.7520400 53.1568480 Db
+53.1568480 53.8534460 Ab
+53.8534460 54.5732650 Db
+54.5732650 55.2698630 Ab
+55.2698630 55.9664620 Db
+55.9664620 56.6746710 Ab
+56.6746710 57.3596590 Db
+57.3596590 58.7644670 Ab
+58.7644670 61.5856910 Db
+61.5856910 64.3953060 Ab
+64.3953060 67.1700900 Db
+67.1700900 68.5516780 Eb:sus4
+68.5516780 69.9564850 Eb
+69.9564850 70.6995230 Ab
+70.6995230 71.4077320 Db
+71.4077320 72.8009290 Bb:min
+72.8009290 74.1825170 F:min
+74.1825170 75.5989340 Eb
+75.5989340 76.3768020 Ab
+76.3768020 77.0385710 Db
+77.0385710 78.4317680 Bb:min
+78.4317680 79.8249650 F:min
+79.8249650 81.2297730 Eb
+81.2297730 82.6345800 F:min
+82.6345800 84.0626070 Bb:min
+84.0626070 84.7708160 Ab
+84.7708160 85.4558040 Db
+85.4558040 86.8490020 Eb
+86.8490020 87.5688200 Ab
+87.5688200 88.2538090 Db
+88.2538090 89.6586160 Bb:min
+89.6586160 91.0866430 Db
+91.0866430 91.7716320 Ab
+91.7716320 92.5262810 Db
+92.5262810 93.2112690 Ab
+93.2112690 93.9310880 Db
+93.9310880 94.6044670 Ab
+94.6044670 95.3010650 Db
+95.3010650 96.7407020 Ab
+96.7407020 99.5038770 Db
+99.5038770 102.2786620 Ab
+102.2786620 105.0766660 Db
+105.0766660 106.4466430 Eb:sus4
+106.4466430 107.8282310 Eb
+107.8282310 108.5480490 Ab
+108.5480490 109.2562580 Db
+109.2562580 110.6726750 Bb:min
+110.6726750 112.0542630 F:min
+112.0542630 113.4242400 Eb
+113.4242400 114.1440580 Ab
+114.1440580 114.8522670 Db
+114.8522670 116.2106340 Bb:min
+116.2106340 117.6270520 F:min
+117.6270520 119.0550790 Eb
+119.0550790 120.4482760 F:min
+120.4482760 121.8414730 Bb:min
+121.8414730 122.5729020 Ab
+122.5729020 123.2578910 Db
+123.2578910 124.6162580 Eb
+124.6162580 125.3592970 Ab
+125.3592970 126.0675050 Db
+126.0675050 127.4490920 Bb:min
+127.4490920 128.8539000 Db
+128.8539000 129.5853280 Ab
+129.5853280 130.3167570 Db
+130.3167570 131.0017460 Ab
+131.0017460 131.6983440 Db
+131.6983440 132.3717230 Ab
+132.3717230 133.1147610 Db
+133.1147610 133.8113600 Ab
+133.8113600 134.5311790 Db
+134.5311790 135.2045570 Ab
+135.2045570 135.8663260 Db
+135.8663260 136.5861450 Ab
+136.5861450 137.2711330 Db
+137.2711330 138.0025620 Ab
+138.0025620 138.6991600 Db
+138.6991600 139.4189790 Ab
+139.4189790 140.0923580 Db
+140.0923580 140.8237860 Ab
+140.8237860 141.4855550 Db
+141.4855550 142.2053740 Ab
+142.2053740 147.5706395 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/11_-_In_My_Life.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,80 @@
+0.0000000 0.4403951 N
+0.4403951 2.4700418 A
+2.4700418 5.0451020 E
+5.0451020 7.1420590 A
+7.1420590 9.6078230 E
+9.6078230 10.7572100 A
+10.7572100 11.9298180 E
+11.9298180 12.8237860 F#:min
+12.8237860 14.2750340 A:7
+14.2750340 15.4360310 D
+15.4360310 16.5854190 D:min
+16.5854190 18.8958040 A
+18.8958040 20.0684120 A
+20.0684120 21.2410200 E
+21.2410200 22.0769380 F#:min
+22.0769380 23.5397950 A:7
+23.5397950 24.7305934 D
+24.7305934 25.9082310 D:min
+25.9082310 28.2302260 A
+28.2302260 30.5522220 F#:min
+30.5522220 32.8858270 D
+32.8858270 35.1729930 G
+35.1729930 37.4833780 A
+37.4833780 39.8169840 F#:min
+39.8169840 42.1273690 B
+42.1273690 44.4029250 D:min
+44.4029250 46.7017000 A
+46.7017000 49.0585260 A
+49.0585260 51.4153510 E
+51.4153510 52.5763490 A
+52.5763490 53.7489560 E
+53.7489560 54.5964850 F#:min
+54.5964850 56.0593420 A:7
+56.0593420 57.2319500 D
+57.2319500 58.4393870 D:min
+58.4393870 60.8426530 A
+60.8426530 61.9804300 A
+61.9804300 63.1646480 E
+63.1646480 63.9889560 F#:min
+63.9889560 65.4866430 A:7
+65.4866430 66.6244210 D
+66.6244210 67.8318590 D:min
+67.8318590 70.1770740 A
+70.1770740 72.5222900 F#:min
+72.5222900 74.7862350 D
+74.7862350 77.0966210 G
+77.0966210 79.3837860 A
+79.3837860 81.7638320 F#:min
+81.7638320 84.1090470 B
+84.1090470 86.3846030 D:min
+86.3846030 88.6601580 A
+88.6601580 89.8327660 A
+89.8327660 91.0402040 E
+91.0402040 91.9225620 F#:min
+91.9225620 93.3621990 A:7
+93.3621990 94.5348070 D
+94.5348070 95.7074140 D:min
+95.7074140 98.0294100 A
+98.0294100 99.1671880 A
+99.1671880 100.3397950 E
+100.3397950 101.1989340 F#:min
+101.1989340 102.6037410 A:7
+102.6037410 103.7763490 D
+103.7763490 104.9257360 D:min
+104.9257360 107.2477320 A
+107.2477320 109.5581170 F#:min
+109.5581170 111.8336730 D
+111.8336730 114.1440580 G
+114.1440580 116.4312240 A
+116.4312240 118.7764390 F#:min
+118.7764390 121.0752150 B
+121.0752150 123.3391600 D:min
+123.3391600 125.6379360 A
+125.6379360 127.6812920 A
+127.6812920 130.3399770 E
+130.3399770 134.9026980 D:min
+134.9026980 137.1898630 A
+137.1898630 139.8485480 E
+139.8485480 143.7985601 A
+143.7985601 147.8578537 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/12_-_Wait.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,117 @@
+0.0000000 0.4020998 N
+0.4020998 1.1325390 F#:min
+1.1325390 1.8291380 F#:min
+1.8291380 3.0481850 B/5
+3.0481850 3.7447840 B:min/5
+3.7447840 4.8825620 F#:min
+4.8825620 5.5443310 C#
+5.5443310 6.7749880 F#:min
+6.7749880 7.5064170 F#:min7
+7.5064170 8.7022440 B/5
+8.7022440 9.4220630 B:min/5
+9.4220630 10.6062810 F#:min
+10.6062810 11.3377090 C#
+11.3377090 12.4870970 F#:min
+12.4870970 13.2069160 A
+13.2069160 14.2982530 D:maj7
+14.2982530 15.0180720 A
+15.0180720 16.1558500 D:maj7
+16.1558500 16.8640580 A
+16.8640580 17.9902260 D:maj7
+17.9902260 18.9306340 A
+18.9306340 19.8826530 C#:7
+19.8826530 21.7286390 F#:min
+21.7286390 22.4716780 F#:min7
+22.4716780 23.6326750 B/5
+23.6326750 24.3873240 B:min/5
+24.3873240 25.5599310 F#:min
+25.5599310 26.2565300 C#:min
+26.2565300 27.4523580 F#:min
+27.4523580 28.1953960 F#:min7
+28.1953960 29.3563940 B/5
+29.3563940 30.0994330 B:min/5
+30.0994330 31.2256000 F#:min
+31.2256000 31.9686390 C#:7
+31.9686390 33.0948070 F#:min
+33.0948070 33.7681850 A
+33.7681850 34.8827430 D:maj7
+34.8827430 35.6141720 A
+35.6141720 36.7171200 D:maj7
+36.7171200 37.4021080 A
+37.4021080 38.5863260 D:maj7
+38.5863260 39.5035140 A
+39.5035140 40.3974820 C#:7
+40.3974820 42.2434690 F#:min
+42.2434690 44.0894550 B:maj(*3)
+44.0894550 45.9122220 E
+45.9122220 47.7582080 A
+47.7582080 49.6506340 F#:min
+49.6506340 51.4501810 B:maj(*3)
+51.4501810 53.2961670 E
+53.2961670 55.1653740 A
+55.1653740 55.6878230 C#:sus4
+55.6878230 57.1739000 C#
+57.1739000 57.8240580 F#:min7
+57.8240580 59.0082760 B/5
+59.0082760 59.7048750 B:min/5
+59.7048750 60.8658730 F#:min
+60.8658730 61.5973010 C#
+61.5973010 62.7931290 F#:min
+62.7931290 63.5129470 F#:min
+63.5129470 64.7319950 B/5
+64.7319950 65.4402040 B:min/5
+65.4402040 66.6592510 F#:min
+66.6592510 67.3326300 C#
+67.3326300 68.4820180 F#:min
+68.4820180 69.1902260 A
+69.1902260 70.3047840 D:maj7
+70.3047840 70.9897730 A
+70.9897730 72.1507700 D:maj7
+72.1507700 72.8473690 A
+72.8473690 74.0199770 D:maj7
+74.0199770 74.9836050 A
+74.9836050 75.8891830 C#:7
+75.8891830 77.7932190 F#:min
+77.7932190 79.6740360 B:maj(*3)
+79.6740360 81.5664620 E
+81.5664620 83.4588880 A
+83.4588880 85.3513150 F#:min
+85.3513150 87.2437410 B:maj(*3)
+87.2437410 89.1245570 E
+89.1245570 91.0169840 A
+91.0169840 91.4929930 C#:sus4
+91.4929930 92.9326300 C#
+92.9326300 93.6872780 F#:min
+93.6872780 94.8250560 B/5
+94.8250560 95.5797050 B:min/5
+95.5797050 96.7523120 F#:min
+96.7523120 97.4373010 C#:min
+97.4373010 98.6795690 F#:min
+98.6795690 99.3877770 F#:min
+99.3877770 100.5719950 B/5
+100.5719950 101.2918140 B:min/5
+101.2918140 102.4760310 F#:min
+102.4760310 103.2074600 C#
+103.2074600 104.3568480 F#:min
+104.3568480 105.0186160 A
+105.0186160 106.1796140 D:maj7
+106.1796140 106.8762130 A
+106.8762130 107.9791600 D:maj7
+107.9791600 108.7454190 A
+108.7454190 109.9180270 D:maj7
+109.9180270 110.8584350 A
+110.8584350 111.7756230 C#:7
+111.7756230 113.6448290 F#:min
+113.6448290 114.3530380 F#:min
+114.3530380 115.5720860 B/5
+115.5720860 116.2570740 B:min/5
+116.2570740 117.4412920 F#:min
+117.4412920 118.1030610 C#
+118.1030610 119.3685480 F#:min
+119.3685480 120.0767570 F#:min
+120.0767570 121.2609750 B/5
+121.2609750 121.9575730 B:min/5
+121.9575730 123.1998410 F#:min
+123.1998410 125.3941260 C#:7
+125.3941260 131.4483509 F#:min
+131.4483509 136.5990583 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/13_-_If_I_Needed_Someone.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+0.0000000 0.3829522 N
+0.3829522 7.7966660 A
+7.7966660 15.2386620 A
+15.2386620 18.9074140 G:maj/9
+18.9074140 30.0181630 A
+30.0181630 33.6869160 G:maj/9
+33.6869160 37.4369380 A
+37.4369380 39.2597050 E:min
+39.2597050 42.9516780 F#
+42.9516780 44.8557140 B:min
+44.8557140 46.7249200 E:min
+46.7249200 48.6173460 F#
+48.6173460 50.4981630 B:min
+50.4981630 52.3557590 E
+52.3557590 59.9370740 A
+59.9370740 63.6870970 G:maj/9
+63.6870970 67.4371200 A
+67.4371200 74.9603850 A
+74.9603850 78.6987980 G:maj/9
+78.6987980 82.4488200 A
+82.4488200 90.0301360 A
+90.0301360 93.8149880 G:maj/9
+93.8149880 97.6114510 A
+97.6114510 99.5154870 E:min
+99.5154870 103.3119500 F#
+103.3119500 105.2624260 B:min
+105.2624260 107.1780720 E:min
+107.1780720 109.0472780 F#
+109.0472780 110.9629250 B:min
+110.9629250 112.9017910 E
+112.9017910 120.5759860 A
+120.5759860 124.3840580 G:maj/9
+124.3840580 128.2153510 A
+128.2153510 135.8431060 A
+135.8431060 139.6243808 A
+139.6243808 143.4921983 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/14_-_Run_For_Your_Life.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+0.0000000 0.4112470 N
+0.4112470 8.5877550 D
+8.5877550 11.2696590 D
+11.2696590 13.9747840 B:min
+13.9747840 16.6915190 D
+16.6915190 19.3966430 B:min
+19.3966430 20.7898410 B:min
+20.7898410 22.1365980 E
+22.1365980 23.4949650 B:min
+23.4949650 24.8417230 E
+24.8417230 26.2233100 B:min
+26.2233100 26.8966890 E:min/b3
+26.8966890 27.6165070 F#
+27.6165070 30.2751920 B:min
+30.2751920 35.6854420 D
+35.6854420 38.3905660 D
+38.3905660 41.1189110 B:min
+41.1189110 43.8240360 D
+43.8240360 46.5291600 B:min
+46.5291600 47.8991380 B:min
+47.8991380 49.2575050 E
+49.2575050 50.6042630 B:min
+50.6042630 51.9626300 E
+51.9626300 53.3674370 B:min
+53.3674370 54.0175960 E:min/b3
+54.0175960 54.6909750 F#
+54.6909750 57.3960990 B:min
+57.3960990 62.8992290 D:maj6
+62.8992290 65.5346930 G
+65.5346930 68.2049880 D
+68.2049880 70.9565530 A
+70.9565530 73.6848970 D
+73.6848970 76.3784120 D
+76.3784120 79.0951470 B:min
+79.0951470 81.8118820 D
+81.8118820 84.5634460 B:min
+84.5634460 85.9450340 B:min
+85.9450340 87.2917910 E
+87.2917910 88.6733780 B:min
+88.6733780 90.0549650 E
+90.0549650 91.4017230 B:min
+91.4017230 92.0751020 E:min/b3
+92.0751020 92.7717000 F#
+92.7717000 95.4768250 B:min
+95.4768250 100.9270586 D
+100.9270586 103.5805890 D
+103.5805890 106.2624940 B:min
+106.2624940 109.0024480 D
+109.0024480 111.7307930 B:min
+111.7307930 113.1123800 B:min
+113.1123800 114.4823580 E
+114.4823580 115.8291150 B:min
+115.8291150 117.2107020 E
+117.2107020 118.6039000 B:min
+118.6039000 119.2772780 E:min/b3
+119.2772780 119.9622670 F#
+119.9622670 122.6906120 B:min
+122.6906120 137.2500771 D
+137.2500771 138.5521146 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+/.DS_Store/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/01_-_Drive_My_Car.lab/1.3/Tue Oct 17 21:54:46 2006//
+/02_-_Norwegian_Wood_(This_Bird_Has_Flown).lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/03_-_You_Won't_See_Me.lab/1.3/Tue Oct 17 21:54:46 2006//
+/04_-_Nowhere_Man.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/05_-_Think_For_Yourself.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/06_-_The_Word.lab/1.2/Sun Jul 30 21:51:52 2006//
+/07_-_Michelle.lab/1.3/Tue Oct 17 21:54:46 2006//
+/08_-_What_Goes_On.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/09_-_Girl.lab/1.2/Sun Jul 30 21:51:52 2006//
+/10_-_I'm_Looking_Through_You.lab/1.2/Sun Jul 30 21:51:52 2006//
+/11_-_In_My_Life.lab/1.3/Tue Oct 17 21:54:46 2006//
+/12_-_Wait.lab/1.2/Sun Jul 30 21:51:52 2006//
+/13_-_If_I_Needed_Someone.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/14_-_Run_For_Your_Life.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/06final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/06final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/01_-_Taxman.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,43 @@
+0.0000000 6.1463832 N
+6.1463832 12.5608830 D:7
+12.5608830 13.9586086 D:7(#9)
+13.9586086 19.6081390 D:7
+19.6081390 20.9474866 D:7(#9)
+20.9474866 23.0446920 D:7
+23.0446920 26.5973450 C
+26.5973450 28.4085020 G:7
+28.4085020 35.5138080 D:7
+35.5138080 36.8605650 D:7(#9)
+36.8605650 42.5958940 D:7
+42.5958940 43.9078210 D:7(#9)
+43.9078210 46.1021070 D:7
+46.1021070 49.6315400 C
+49.6315400 51.4775270 G:7
+51.4775270 60.3823790 D:7
+60.3823790 62.1703160 C:9
+62.1703160 67.3421486 D:7
+67.3421486 71.0171180 C:9
+71.0171180 85.2973910 D:7
+85.2973910 88.9313130 C
+88.9313130 90.8005200 G:7
+90.8005200 98.0335360 D:7
+98.0335360 99.3761021 D:7(#9)
+99.3761021 105.2897710 D:7
+105.2897710 106.6365290 D:7(#9)
+106.6365290 108.9004740 D:7
+108.9004740 112.5227870 C
+112.5227870 114.3919940 G:7
+114.3919940 118.0955760 D:7
+118.0955760 121.7178890 D:7
+121.7178890 123.1110870 D:7(#9)
+123.1110870 128.9973450 D:7
+128.9973450 130.4021520 D:7(#9)
+130.4021520 132.5499980 D:7
+132.5499980 136.1839210 C
+136.1839210 138.0531270 G:7
+138.0531270 139.8758940 D:7
+139.8758940 143.6259170 F:7
+143.6259170 147.2017900 D:7
+147.2017900 148.5663153 D:7(#9)
+148.5663153 154.9807650 D:7
+154.9807650 158.7528444 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/02_-_Eleanor_Rigby.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,55 @@
+0.0000000 0.3829522 N
+0.3829522 3.8492740 C
+3.8492740 7.3438770 E:min
+7.3438770 10.7920400 C
+10.7920400 14.2402040 E:min
+14.2402040 19.5575730 E:min
+19.5575730 22.2162580 C
+22.2162580 23.1218360 E:min
+23.1218360 27.4193792 E:min
+27.4193792 28.3114960 E:min/b7
+28.3114960 30.9237410 C
+30.9237410 31.7828790 E:min
+31.7828790 33.5475960 E:min7
+33.5475960 35.3123120 E:min6
+35.3123120 37.0189790 C/3
+37.0189790 38.7953060 E:min
+38.7953060 40.5948520 E:min7
+40.5948520 42.2666890 E:min6
+42.2666890 43.9733560 C/3
+43.9733560 45.7729020 E:min
+45.7729020 51.0438320 E:min
+51.0438320 53.6096370 C
+53.6096370 54.5268250 E:min
+54.5268250 59.7280950 E:min
+59.7280950 62.3403400 C
+62.3403400 63.2226980 E:min
+63.2226980 64.9409750 E:min7
+64.9409750 66.6824710 E:min6
+66.6824710 68.3891380 C/3
+68.3891380 70.1422440 E:min
+70.1422440 71.9069610 E:min7
+71.9069610 73.6252380 E:min6
+73.6252380 75.3435140 C/3
+75.3435140 77.0966210 E:min
+77.0966210 80.5447840 C
+80.5447840 83.9697270 E:min
+83.9697270 87.3830610 C
+87.3830610 90.8312240 E:min
+90.8312240 96.0208840 E:min
+96.0208840 98.6215190 C
+98.6215190 99.4574370 E:min
+99.4574370 104.6122670 E:min
+104.6122670 107.2709520 C
+107.2709520 108.1533100 E:min
+108.1533100 109.9180270 E:min7
+109.9180270 111.6711330 E:min6
+111.6711330 113.4358500 C/3
+113.4358500 115.2121760 E:min
+115.2121760 116.9652830 E:min7
+116.9652830 118.6719500 E:min6
+118.6719500 120.4366660 C/3
+120.4366660 121.8745453 E:min
+121.8745453 122.3340879 F#:min7
+122.3340879 123.5978303 E:min
+123.5978303 127.5805334 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/03_-_I'm_Only_Sleeping.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,84 @@
+0.0000000 0.4127210 N
+0.4127210 2.9088660 Eb:min
+2.9088660 5.1495910 Ab:min
+5.1495910 6.3105890 F#
+6.3105890 7.4599770 B
+7.4599770 8.6209750 F#
+8.6209750 9.6890920 Bb:7
+9.6890920 12.0459180 Eb:min
+12.0459180 14.3679130 Ab:min
+14.3679130 15.5521310 F#
+15.5521310 16.7131290 B
+16.7131290 17.8509070 F#
+17.8509070 21.3687300 B
+21.3687300 23.6675050 Gb
+23.6675050 25.9430610 Ab:min
+25.9430610 28.2534460 Bb:min
+28.2534460 30.5522220 Ab:min
+30.5522220 35.2310430 B:maj7
+35.2310430 37.5994780 Eb:min
+37.5994780 39.8402040 Ab:min
+39.8402040 41.0128110 F#
+41.0128110 42.1970290 B
+42.1970290 43.3231970 F#
+43.3231970 44.4725850 Bb:7
+44.4725850 46.8061900 Eb:min
+46.8061900 49.1514050 Ab:min
+49.1514050 50.2891830 F#
+50.2891830 51.4501810 B
+51.4501810 52.6227890 F#
+52.6227890 56.1057820 B
+56.1057820 58.3581170 Gb
+58.3581170 60.6917230 Ab:min
+60.6917230 62.9788880 Bb:min7
+62.9788880 65.3124940 Ab:min
+65.3124940 70.0377550 B:maj7
+70.0377550 74.6585260 Eb:min
+74.6585260 77.0153510 Db:min
+77.0153510 79.2676870 Eb:7
+79.2676870 81.5896820 Ab:min
+81.5896820 83.9116780 E
+83.9116780 86.2685030 Eb:7
+86.2685030 88.5556680 Ab:min
+88.5556680 89.7282760 Gb
+89.7282760 90.8892740 B
+90.8892740 92.0386620 Gb
+92.0386620 93.1996590 Bb:7
+93.1996590 95.5332650 Eb:min
+95.5332650 97.8552600 Ab:min
+97.8552600 99.0162580 F#
+99.0162580 100.1772560 B
+100.1772560 101.3266430 F#
+101.3266430 104.8444670 B
+104.8444670 107.2477320 Gb
+107.2477320 109.5116780 Ab:min
+109.5116780 111.8917230 Bb:min
+111.8917230 114.1556680 Ab:min
+114.1556680 116.5124940 B:maj7
+116.5124940 118.8460990 Ab:min7
+118.8460990 123.5249200 Eb:min
+123.5249200 125.9049650 Db:min
+125.9049650 128.1573010 Eb:7
+128.1573010 130.5605660 Ab:min
+130.5605660 132.7503884 E
+132.7503884 135.2393870 Eb:7
+135.2393870 137.5381630 Ab:min
+137.5381630 138.6759410 Gb
+138.6759410 139.8601580 B
+139.8601580 141.0095460 Gb
+141.0095460 142.1937640 Bb:7
+142.1937640 144.5389790 Eb:min
+144.5389790 146.8377550 Ab:min
+146.8377550 147.9755320 F#
+147.9755320 149.1713600 B
+149.1713600 150.3439680 F#
+150.3439680 153.8617910 B
+153.8617910 156.2534460 Gb
+156.2534460 158.5754420 Ab:min
+158.5754420 160.9206570 Bb:min
+160.9206570 163.2310430 Ab:min
+163.2310430 165.5646480 B:maj7
+165.5646480 165.9714939 Ab:min7
+165.9714939 167.9330830 Eb:min
+167.9330830 176.3494991 Eb:min
+176.3494991 181.2895828 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/04_-_Love_You_To.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,37 @@
+0.0000000 0.4403951 N
+0.4403951 4.9592313 N
+4.9592313 35.8347610 C:min(*b3)
+35.8347610 58.2652380 C:min(*b3)
+58.2652380 59.7213993 Bb
+59.7213993 60.2383848 C:min(*b3)
+60.2383848 61.6089110 Bb
+61.6089110 62.1429700 C:min(*b3)
+62.1429700 63.4781170 Bb
+63.4781170 63.9773460 C:min(*b3)
+63.9773460 65.3705440 Bb
+65.3705440 88.2770290 C:min(*b3)
+88.2770290 89.7166660 Bb
+89.7166660 90.3001344 C:min(*b3)
+90.3001344 91.6090920 Bb
+91.6090920 92.1431510 C:min(*b3)
+92.1431510 93.4782990 Bb
+93.4782990 94.0239680 C:min(*b3)
+94.0239680 95.3707250 Bb
+95.3707250 114.9048148 C:min(*b3)
+114.9048148 116.3383440 Bb
+116.3383440 116.8840130 C:min(*b3)
+116.8840130 118.2539900 Bb
+118.2539900 118.7996590 C:min(*b3)
+118.7996590 120.1696370 Bb
+120.1696370 120.6920860 C:min(*b3)
+120.6920860 122.0040130 Bb
+122.0040130 144.7176454 C:min(*b3)
+144.7176454 146.2340360 Bb
+146.2340360 146.7797050 C:min(*b3)
+146.7797050 148.1032420 Bb
+148.1032420 148.6140810 C:min(*b3)
+148.6140810 149.9840580 Bb
+149.9840580 150.4716780 C:min(*b3)
+150.4716780 151.8997050 Bb
+151.8997050 176.5984181 C:min(*b3)
+176.5984181 180.9449258 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/05_-_Here,_There_And_Everywhere.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,98 @@
+0.0000000 0.4243310 N
+0.4243310 2.0729470 G
+2.0729470 3.9635555 B:min
+3.9635555 6.8098180 Bb
+6.8098180 7.6689560 A:sus4
+7.6689560 8.3887750 A:min
+8.3887750 10.1070520 D
+10.1070520 11.5699090 G
+11.5699090 13.0792060 A:min7
+13.0792060 14.5652830 G/3
+14.5652830 15.9817000 C
+15.9817000 17.3865070 G
+17.3865070 18.8841950 A:min7
+18.8841950 20.3238320 G/3
+20.3238320 21.8099090 C
+21.8099090 23.2843760 F#:min
+23.2843760 24.6891830 B:7
+24.6891830 26.1288200 F#:min
+26.1288200 27.5220180 B:7
+27.5220180 29.0313150 E:min
+29.0313150 30.4129020 A:min
+30.4129020 31.8873690 A:min7
+31.8873690 33.3502260 D:7
+33.3502260 34.8130830 G
+34.8130830 36.2643310 A:min7
+36.2643310 37.6923580 G/3
+37.6923580 39.1087750 C
+39.1087750 40.5832420 G
+40.5832420 42.0344890 A:min7
+42.0344890 43.5205660 G/3
+43.5205660 44.9485940 C
+44.9485940 46.3882310 F#:min
+46.3882310 47.8046480 B:7
+47.8046480 49.2675050 F#:min
+49.2675050 50.7187520 B:7
+50.7187520 52.1351700 E:min
+52.1351700 53.5980270 A:min
+53.5980270 55.0608840 A:min7
+55.0608840 55.8152866 D
+55.8152866 56.4889110 F
+56.4889110 57.9401580 Bb
+57.9401580 59.4378450 G:min
+59.4378450 60.8542630 C:min
+60.8542630 62.2590700 D:7
+62.2590700 65.1151240 G:min
+65.1151240 66.5663710 C:min
+66.5663710 67.9943990 D
+67.9943990 69.4456460 G
+69.4456460 70.9085030 A:min7
+70.9085030 72.3713600 G/3
+72.3713600 73.7877770 C
+73.7877770 75.2041950 G
+75.2041950 76.6438320 A:min7
+76.6438320 78.1066890 G/3
+78.1066890 79.5231060 C
+79.5231060 80.9511330 F#:min
+80.9511330 82.3907700 B:7
+82.3907700 83.8304080 F#:min
+83.8304080 85.2932650 B
+85.2932650 86.7329020 E:min
+86.7329020 88.2189790 A:min
+88.2189790 89.6702260 A:min7
+89.6702260 90.3552150 D
+90.3552150 91.0866430 F
+91.0866430 92.5262810 Bb
+92.5262810 93.9775280 G:min
+93.9775280 95.4752150 C:min
+95.4752150 96.9032420 D:7
+96.9032420 99.8057360 G:min
+99.8057360 101.2221540 C:min
+101.2221540 102.6385710 D:7
+102.6385710 104.1014280 G
+104.1014280 105.5526750 A:min7
+105.5526750 107.0271420 G/3
+107.0271420 108.5016090 C
+108.5016090 109.9644670 G
+109.9644670 111.4041040 A:min7
+111.4041040 112.8901810 G/3
+112.8901810 114.3298180 C
+114.3298180 115.7926750 F#:min
+115.7926750 117.2323120 B:7
+117.2323120 118.6719500 F#:min
+118.6719500 120.1812470 B:7
+120.1812470 121.5860540 E:min
+121.5860540 123.0489110 A:min
+123.0489110 124.5349880 A:min7
+124.5349880 125.2199770 D:7
+125.2199770 125.9397950 D
+125.9397950 127.4258730 G
+127.4258730 128.8074600 A:min7
+128.8074600 130.3283670 G/3
+130.3283670 131.7912240 C
+131.7912240 133.3005210 G
+133.3005210 134.7285480 A:min7
+134.7285480 136.2146250 G/3
+136.2146250 137.7123120 C
+137.7123120 141.4242563 G
+141.4242563 145.7133212 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/06_-_Yellow_Submarine.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,107 @@
+0.0000000 0.4595427 N
+0.4595427 0.9932190 F#
+0.9932190 2.5953960 C#
+2.5953960 3.1875050 B
+3.1875050 4.9057820 F#
+4.9057820 5.4514510 D#:min
+5.4514510 7.1348970 G#:min
+7.1348970 7.7037860 G#:min
+7.7037860 9.3756230 C#
+9.3756230 9.9212920 B
+9.9212920 11.5466890 C#
+11.5466890 12.0575280 B
+12.0575280 13.7758040 F#
+13.7758040 14.3098630 D#:min
+14.3098630 15.8772100 G#:min
+15.8772100 16.4344890 G#:min
+16.4344890 18.0714960 C#
+18.0714960 18.6403850 B
+18.6403850 20.2425620 C#
+20.2425620 20.8114510 B
+20.8114510 22.4020180 F#
+22.4020180 22.9709070 D#:min
+22.9709070 24.5614730 G#:min
+24.5614730 25.0955320 G#:min
+25.0955320 26.7325390 C#
+26.7325390 27.2549880 B
+27.2549880 28.8803850 C#
+28.8803850 29.4492740 B
+29.4492740 31.0746710 F#
+31.0746710 31.6435600 D#:min
+31.6435600 33.2225170 G#:min
+33.2225170 33.7797950 G#:min
+33.7797950 35.9740810 C#
+35.9740810 38.1037463 F#
+38.1037463 42.4872780 C#
+42.4872780 44.6002940 F#
+44.6002940 46.7249200 F#
+46.7249200 51.0438320 C#
+51.0438320 53.1684580 F#
+53.1684580 54.7938540 C#
+54.7938540 55.3279130 B
+55.3279130 56.9881400 F#
+56.9881400 57.4989790 D#:min
+57.4989790 59.1127660 G#:min
+59.1127660 59.6352150 G#:min
+59.6352150 61.3302720 C#
+61.3302720 61.8991600 B
+61.8991600 63.4548970 C#
+63.4548970 64.0470060 B
+64.0470060 65.6259630 F#
+65.6259630 68.7016290 F#
+68.7016290 69.9564850 C#
+69.9564850 70.5137640 B
+70.5137640 72.6964390 F#
+72.6964390 74.8675050 C#
+74.8675050 76.9805210 C#
+76.9805210 79.1167570 F#
+79.1167570 81.2413830 F#
+81.2413830 83.3543990 C#
+83.3543990 85.5022440 C#
+85.5022440 87.6500900 F#
+87.6500900 89.2290470 C#
+89.2290470 89.8211560 B
+89.8211560 91.4581630 F#
+91.4581630 92.0038320 D#:min
+92.0038320 93.5827890 G#:min
+93.5827890 94.1865070 G#:min
+94.1865070 95.8699540 C#
+95.8699540 96.4388430 B
+96.4388430 98.1222900 C#
+98.1222900 98.6447390 B
+98.6447390 100.2701360 F#
+100.2701360 100.8887634 D#:min
+100.8887634 102.4295910 G#:min
+102.4295910 102.9868700 G#:min
+102.9868700 104.6819270 C#
+104.6819270 105.2275960 B
+105.2275960 106.8762130 C#
+106.8762130 107.4102720 B
+107.4102720 109.0821080 F#
+109.0821080 109.6161670 D#:min
+109.6161670 111.2183440 G#:min
+111.2183440 111.7640130 G#:min
+111.7640130 113.3661900 C#
+113.3661900 113.9350790 B
+113.9350790 115.5140360 C#
+115.5140360 116.0597050 B
+116.0597050 117.7083210 F#
+117.7083210 118.1843310 D#:min
+118.1843310 119.8445570 G#:min
+119.8445570 120.3786160 G#:min
+120.3786160 122.5496820 C#
+122.5496820 124.7787980 F#
+124.7787980 129.0396590 C#
+129.0396590 131.1642850 F#
+131.1642850 133.3237410 F#
+133.3237410 137.6194330 C#
+137.6194330 139.7556680 F#
+139.7556680 141.9151240 F#
+141.9151240 144.0629700 C#
+144.0629700 146.1992060 C#
+146.1992060 148.3586620 F#
+148.3586620 150.4600680 F#
+150.4600680 152.6659630 C#
+152.6659630 154.7673690 C#
+154.7673690 156.7997881 F#
+156.7997881 159.8634059 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/07_-_She_Said_She_Said.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,94 @@
+0.0000000 0.4403951 N
+0.4403951 2.5489560 Bb
+2.5489560 4.7896820 Bb
+4.7896820 6.8794780 Bb
+6.8794780 8.0056460 Bb
+8.0056460 9.0969840 Ab
+9.0969840 11.3377090 Eb
+11.3377090 12.3826070 Bb
+12.3826070 13.5203850 Ab
+13.5203850 15.6682310 Eb
+15.6682310 16.7827890 Bb
+16.7827890 17.9089560 Ab
+17.9089560 20.1264620 Eb
+20.1264620 20.9623800 Bb
+20.9623800 22.2975280 Ab
+22.2975280 23.1450560 Eb
+23.1450560 24.5150340 Bb
+24.5150340 25.3741720 Bb
+25.3741720 26.7325390 Ab
+26.7325390 27.5916780 Eb
+27.5916780 28.9848750 Bb
+28.9848750 30.1458730 Bb
+30.1458730 31.2023800 Ab:maj(9)
+31.2023800 33.3966660 Eb
+33.3966660 34.4880040 Bb
+34.4880040 35.6025620 Ab:maj(9)
+35.6025620 37.7968480 Eb
+37.7968480 38.8881850 Bb
+38.8881850 40.0027430 Ab:maj(9)
+40.0027430 42.2086390 Eb
+42.2086390 43.0445570 Bb
+43.0445570 44.3564850 Ab
+44.3564850 45.2040130 Eb
+45.2040130 46.5856000 Bb
+46.5856000 47.4447390 Bb
+47.4447390 48.7914960 Ab
+48.7914960 49.7319040 Eb
+49.7319040 51.1018820 Bb
+51.1018820 52.2048290 Bb
+52.2048290 53.3193870 Ab
+53.3193870 55.5949430 Bb
+55.5949430 57.3248290 Ab
+57.3248290 59.0431060 Bb
+59.0431060 60.7613830 F:min
+60.7613830 64.1398860 Bb
+64.1398860 65.8813830 Eb
+65.8813830 69.2947160 Bb
+69.2947160 71.0013830 Eb
+71.0013830 72.1623800 Bb
+72.1623800 73.2885480 Ab
+73.2885480 75.5524940 Eb
+75.5524940 76.7018820 Bb
+76.7018820 77.8628790 Ab
+77.8628790 80.1036050 Eb
+80.1036050 81.2529930 Bb
+81.2529930 82.4139900 Ab
+82.4139900 84.6198860 Eb
+84.6198860 85.4790240 Bb
+85.4790240 86.8606120 Ab
+86.8606120 87.7081400 Eb
+87.7081400 89.0897270 Bb
+89.0897270 89.8908160 Bb
+89.8908160 91.3072330 Ab
+91.3072330 92.1895910 Eb
+92.1895910 93.6176190 Bb
+93.6176190 94.7670060 Bb
+94.7670060 95.8931740 Ab
+95.8931740 98.1455100 Bb
+98.1455100 99.9102260 Ab
+99.9102260 101.6749430 Bb
+101.6749430 103.3816090 F:min
+103.3816090 106.8065530 Bb
+106.8065530 108.5016090 Eb
+108.5016090 111.9265530 Bb
+111.9265530 113.5983900 Eb
+113.5983900 114.7324863 Bb
+114.7324863 115.9784350 Ab
+115.9784350 118.2307700 Eb
+118.2307700 119.3685480 Bb
+119.3685480 120.4947160 Ab
+120.4947160 122.7818820 Eb
+122.7818820 123.9196590 Bb
+123.9196590 125.1038770 Ab
+125.1038770 127.3794330 Eb
+127.3794330 128.2153510 Bb
+128.2153510 129.6201580 Ab
+129.6201580 130.4444670 Eb
+130.4444670 131.9073240 Bb
+131.9073240 132.7664620 Bb
+132.7664620 134.1828790 Ab
+134.1828790 135.0768480 Eb
+135.0768480 136.4932650 Bb
+136.4932650 152.1086233 Bb
+152.1086233 156.8955261 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/08_-_Good_Day_Sunshine.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+0.0000000 0.4020998 N
+0.4020998 8.4352150 E
+8.4352150 9.8864620 B
+9.8864620 12.4522670 F#
+12.4522670 13.9615640 B
+13.9615640 16.5041490 F#
+16.5041490 20.5444210 E:7
+20.5444210 21.6125390 A
+21.6125390 22.6226070 F#:7
+22.6226070 24.6311330 B:7
+24.6311330 26.6512690 E:7
+26.6512690 28.7410650 A
+28.7410650 29.7511330 A
+29.7511330 30.7612010 F#:7
+30.7612010 32.8045570 B:7
+32.8045570 34.8479130 E:7
+34.8479130 36.9028790 A
+36.9028790 38.4470060 B
+38.4470060 41.0012010 F#
+41.0012010 42.5337180 B
+42.5337180 45.0763030 F#
+45.0763030 49.1630150 E:7
+49.1630150 50.1846930 A
+50.1846930 51.2295910 F#:7
+51.2295910 53.2381170 B:7
+53.2381170 55.2582530 E:7
+55.2582530 57.3596590 A
+57.3596590 58.3929470 D
+58.3929470 59.3914050 B:7
+59.3914050 61.5160310 E:7
+61.5160310 63.6290470 A:7
+63.6290470 65.6956230 D
+65.6956230 67.2745800 B
+67.2745800 69.8055550 F#
+69.8055550 71.3845120 B
+71.3845120 73.8690470 F#
+73.8690470 78.0021990 E:7
+78.0021990 79.0354870 A
+79.0354870 80.0687750 F#:7
+80.0687750 82.0656910 B:7
+82.0656910 84.1206570 E:7
+84.1206570 86.2104530 A
+86.2104530 87.2553510 A
+87.2553510 88.2886390 F#:7
+88.2886390 90.3087750 B:7
+90.3087750 92.3405210 E:7
+92.3405210 94.4651470 A
+94.4651470 96.0092740 B
+96.0092740 98.5518590 F#
+98.5518590 100.0959860 B
+100.0959860 102.6269610 F#
+102.6269610 106.2028340 E:7
+106.2028340 107.7353510 B
+107.7353510 110.2082760 F#
+110.2082760 111.7407930 B
+111.7407930 114.2601580 F#
+114.2601580 117.7315410 E:7
+117.7315410 125.4551486 F:7
+125.4551486 129.3038184 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/09_-_And_Your_Bird_Can_Sing.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,43 @@
+0.0000000 0.4978379 N
+0.4978379 7.6921760 E
+7.6921760 14.9368020 E
+14.9368020 16.7595690 F#:min
+16.7595690 18.5591150 A
+18.5591150 22.2162580 E
+22.2162580 29.4144440 E
+29.4144440 31.1907700 F#:min
+31.1907700 32.9903170 A
+32.9903170 36.6474600 E
+36.6474600 38.4353960 G#:min
+38.4353960 40.2001130 G:aug
+40.2001130 42.0460990 B/5
+42.0460990 43.8340360 F:dim
+43.8340360 45.6451920 E
+45.6451920 49.2558950 F#:min
+49.2558950 51.0902720 B
+51.0902720 58.3000680 E
+58.3000680 60.0996140 F#:min
+60.0996140 61.8875510 A
+61.8875510 65.5330830 E
+65.5330830 67.3326300 G#:min
+67.3326300 69.1321760 G:aug
+69.1321760 70.9665530 B/5
+70.9665530 72.7544890 F:dim
+72.7544890 74.6120860 E
+74.6120860 78.2227890 F#:min
+78.2227890 80.0223350 B
+80.0223350 80.9627430 E
+80.9627430 81.8915410 E/7
+81.8915410 82.8087300 E/6
+82.8087300 83.7026980 E/5
+83.7026980 87.2901810 E
+87.2901810 89.0897270 F#:min
+89.0897270 90.8892740 A
+90.8892740 94.5115870 E
+94.5115870 101.6517230 E
+101.6517230 103.4628790 F#:min
+103.4628790 105.2275960 A
+105.2275960 108.8963490 E
+108.8963490 114.2949880 E
+114.2949880 117.7199310 A/5
+117.7199310 121.5681835 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/10_-_For_No_One.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,68 @@
+0.0000000 0.4212474 N
+0.4212474 1.9336280 B
+1.9336280 3.4661450 B/7
+3.4661450 4.9290020 G#:min
+4.9290020 6.4499090 B/5
+6.4499090 7.9940360 E
+7.9940360 9.4801130 A:7
+9.4801130 12.4870970 B
+12.4870970 13.9383440 B
+13.9383440 15.4128110 B/7
+15.4128110 16.9104980 G#:min
+16.9104980 18.3849650 B/5
+18.3849650 19.8826530 E
+19.8826530 21.3687300 A:7
+21.3687300 24.2828340 B
+24.2828340 25.7340810 C#:min
+25.7340810 27.1853280 G#:7
+27.1853280 30.0413830 C#:min
+30.0413830 31.4461900 C#:min
+31.4461900 32.8974370 G#:7
+32.8974370 37.1582990 C#:min
+37.1582990 37.9361670 F#:sus4
+37.9361670 38.7256460 F#
+38.7256460 40.2813830 B
+40.2813830 41.7790700 B/7
+41.7790700 43.2535370 G#:min
+43.2535370 44.7512240 B/5
+44.7512240 46.2489110 E
+46.2489110 47.7233780 A:7
+47.7233780 50.7535820 B
+50.7535820 52.1816090 B
+52.1816090 53.6328570 B/7
+53.6328570 55.1073240 G#:min
+55.1073240 56.5817910 B/5
+56.5817910 58.0678680 E
+58.0678680 59.5655550 A:7
+59.5655550 62.5260990 B
+62.5260990 63.9425170 C#:min
+63.9425170 65.3473240 G#:7
+65.3473240 68.2265980 C#:min
+68.2265980 69.6197950 C#:min
+69.6197950 71.0129930 G#:7
+71.0129930 75.3202940 C#:min
+75.3202940 76.1213830 F#:sus4
+76.1213830 76.8644210 F#
+76.8644210 78.3737180 B
+78.3737180 79.8714050 B/7
+79.8714050 81.3458730 G#:min
+81.3458730 82.8203400 B/5
+82.8203400 84.2831970 E
+84.2831970 85.7808840 A:7
+85.7808840 88.7646480 B
+88.7646480 90.2391150 B
+90.2391150 91.7484120 B/7
+91.7484120 93.1532190 G#:min
+93.1532190 94.6392970 B/5
+94.6392970 96.0905440 E
+96.0905440 97.6336695 A:7
+97.6336695 100.4791150 B
+100.4791150 101.9651920 C#:min
+101.9651920 103.3583900 G#:7
+103.3583900 106.0203232 C#:min
+106.0203232 107.6192510 C#:min
+107.6192510 109.0008390 G#:7
+109.0008390 113.3429700 C#:min
+113.3429700 114.3495341 F#:sus4
+114.3495341 116.8578711 F#
+116.8578711 121.1852313 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/11_-_Doctor_Robert.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,33 @@
+0.0000000 0.4212474 N
+0.4212474 6.1480490 A
+6.1480490 17.6999770 A
+17.6999770 26.4887300 F#
+26.4887300 27.9864170 E
+27.9864170 29.4260540 F#
+29.4260540 32.3285480 B
+32.3285480 43.9849650 A
+43.9849650 52.7272780 F#
+52.7272780 54.1785260 E
+54.1785260 55.6297730 F#
+55.6297730 58.6251470 B
+58.6251470 61.6205210 B
+61.6205210 63.0717680 E/5
+63.0717680 64.6042850 B
+64.6042850 67.5416090 B
+67.5416090 70.4441040 E/5
+70.4441040 85.1655550 A
+85.1655550 93.9659180 F#
+93.9659180 95.3475050 E
+95.3475050 96.8219720 F#
+96.8219720 99.7941260 B
+99.7941260 102.7843769 B
+102.7843769 104.2987980 E/5
+104.2987980 105.8197050 B
+105.8197050 108.7570290 B
+108.7570290 111.7640130 E/5
+111.7640130 126.5899540 A
+126.5899540 129.3804089 F#
+129.3804089 130.1080181 B
+130.1080181 130.5867084 E/5
+130.5867084 131.8121555 B
+131.8121555 134.7417400 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/12_-_I_Want_To_Tell_You.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,66 @@
+0.0000000 2.0679420 A
+2.0679420 2.9553060 D:sus4/5
+2.9553060 3.7337842 D/5
+3.7337842 5.8345800 A
+5.8345800 6.8098180 D:sus4/5
+6.8098180 7.4948070 D/5
+7.4948070 9.6890920 A
+9.6890920 10.6411110 D:sus4/5
+10.6411110 11.4305890 D/5
+11.4305890 13.5319950 A
+13.5319950 14.5072330 D:sus4/5
+14.5072330 15.3199310 D/5
+15.3199310 22.1582080 A
+22.1582080 25.0258730 B
+25.0258730 32.5143080 E:maj(b9)
+32.5143080 34.4531740 A
+34.4531740 35.3935820 D:sus4/5
+35.3935820 36.0785710 D/5
+36.0785710 42.9052380 A
+42.9052380 45.7380720 B
+45.7380720 53.2381170 E:maj(b9)
+53.2381170 55.1305440 A
+55.1305440 56.0361220 D:sus4/5
+56.0361220 56.9417000 D/5
+56.9417000 58.8225170 B:min
+58.8225170 60.6568930 B:dim
+60.6568930 62.5725390 A
+62.5725390 64.4533560 B
+64.4533560 66.3922220 B:min
+66.3922220 68.2149880 B:dim
+68.2149880 69.0857360 A
+69.0857360 71.9766210 A:sus4
+71.9766210 78.5130380 A
+78.5130380 81.3458730 B
+81.3458730 88.7878680 E:maj(b9)
+88.7878680 90.6919040 A
+90.6919040 91.5742630 D:sus4/5
+91.5742630 92.5262810 D/5
+92.5262810 94.3838770 B:min
+94.3838770 96.2995230 B:dim
+96.2995230 98.1687300 A
+98.1687300 100.0611560 B
+100.0611560 102.0000220 B:min
+102.0000220 103.8808390 B:dim
+103.8808390 104.6587070 A
+104.6587070 107.6192510 A:sus4
+107.6192510 114.1788880 A
+114.1788880 117.0001130 B
+117.0001130 124.5001580 E:maj(b9)
+124.5001580 126.4622440 A
+126.4622440 127.3910430 D:sus4/5
+127.3910430 128.3662810 D/5
+128.3662810 130.2703170 A
+130.2703170 131.2803850 D:sus4/5
+131.2803850 132.1743530 D/5
+132.1743530 134.1480490 A
+134.1480490 135.0768480 D:sus4/5
+135.0768480 136.0288660 D/5
+136.0288660 137.9561220 A
+137.9561220 138.8617000 D:sus4/5
+138.8617000 139.7324480 D/5
+139.7324480 141.7525850 A
+141.7525850 142.7046030 D:sus4/5
+142.7046030 143.4940810 D/5
+143.4940810 145.5954870 A
+145.5954870 149.6960243 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/13_-_Got_To_Get_You_Into_My_Life.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,81 @@
+0.0000000 0.4403951 N
+0.4403951 1.7246480 G
+1.7246480 3.5040128 F:maj(9)/9
+3.5040128 7.4831970 G
+7.4831970 11.1055100 G
+11.1055100 14.4375730 F:maj(9)/9
+14.4375730 17.9553960 G
+17.9553960 21.4616090 F:maj(9)/9
+21.4616090 22.5297270 B:min
+22.5297270 23.4004760 B:min/7
+23.4004760 24.2944440 B:min/b7
+24.2944440 25.1535820 B:min/6
+25.1535820 26.0011110 B:min
+26.0011110 26.8718590 B:min/7
+26.8718590 27.7658270 B:min/b7
+27.7658270 28.6017460 B:min/6
+28.6017460 29.4957140 C
+29.4957140 30.3780720 C/7
+30.3780720 31.2488200 A:min
+31.2488200 32.0847390 D
+32.0847390 35.5329020 G
+35.5329020 38.9114050 G
+38.9114050 42.4176190 F:maj(9)/9
+42.4176190 45.9934920 G
+45.9934920 49.5113150 F:maj(9)/9
+49.5113150 50.5446030 B:min
+50.5446030 51.4037410 B:min/7
+51.4037410 52.3093190 B:min/b7
+52.3093190 52.9826980 B:min/6
+52.9826980 54.0624260 B:min
+54.0624260 54.9563940 B:min/7
+54.9563940 55.8503620 B:min/b7
+55.8503620 56.6978910 B:min/6
+56.6978910 57.5918590 C
+57.5918590 58.4626070 C/7
+58.4626070 59.3333560 A:min
+59.3333560 60.1808840 D
+60.1808840 63.6290470 G
+63.6290470 65.3821540 G
+65.3821540 68.8419270 C
+68.8419270 70.6182530 D
+70.6182530 74.1012470 G
+74.1012470 77.6887300 G
+77.6887300 81.0091830 F:maj(9)/9
+81.0091830 84.5502260 G
+84.5502260 88.2189790 F:maj(9)/9
+88.2189790 89.0897270 B:min
+89.0897270 90.0069160 B:min/7
+90.0069160 90.8660540 B:min/b7
+90.8660540 91.7484120 B:min/6
+91.7484120 92.6191600 B:min
+92.6191600 93.4899090 B:min/7
+93.4899090 94.3722670 B:min/b7
+94.3722670 95.2546250 B:min/6
+95.2546250 96.1021540 C
+96.1021540 97.0077320 C/7
+97.0077320 97.8784800 A:min
+97.8784800 98.7492290 D
+98.7492290 102.1857820 G
+102.1857820 103.9272780 G
+103.9272780 107.3986620 C
+107.3986620 109.1633780 D
+109.1633780 112.8089110 G
+112.8089110 114.2485480 G
+114.2485480 114.9622576 F:maj/9
+114.9622576 115.5366860 C:sus4/4
+115.5366860 116.0345239 C/3
+116.0345239 118.1982039 G
+118.1982039 121.6441040 C
+121.6441040 123.4088200 D
+123.4088200 126.8105440 G
+126.8105440 131.6054640 G
+131.6054640 133.7997500 G:sus4(2)
+133.7997500 135.1000680 G
+135.1000680 137.3059630 G:sus4(2)
+137.3059630 139.0706800 G
+139.0706800 140.7773460 G:sus4(2)
+140.7773460 142.0428340 G
+142.0428340 144.2255100 G:sus4(2)
+144.2255100 146.1537163 G
+146.1537163 150.5385192 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/14_-_Tomorrow_Never_Knows.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,37 @@
+0.0000000 0.7276092 N
+0.7276092 19.0931740 C
+19.0931740 22.8896370 Bb:maj(9)/9
+22.8896370 26.6628790 C
+26.6628790 34.1861450 C
+34.1861450 37.9593870 Bb:maj(9)/9
+37.9593870 41.7094100 C
+41.7094100 49.2791150 C
+49.2791150 53.0291380 Bb:maj(9)/9
+53.0291380 56.7907700 C
+56.7907700 65.2167637 C
+65.2167637 66.2315871 Bb:maj/9
+66.2315871 66.7485726 C
+66.7485726 67.6293627 Bb:maj/9
+67.6293627 80.9943954 C
+80.9943954 83.1197802 Bb:maj/9
+83.1197802 87.6500900 C
+87.6500900 94.6857360 C
+94.6857360 98.4938090 Bb:maj(9)/9
+98.4938090 109.9876870 C
+109.9876870 113.8421990 Bb:maj(9)/9
+113.8421990 117.6618820 C
+117.6618820 125.3128570 C
+125.3128570 129.0977090 Bb:maj(9)/9
+129.0977090 132.9986620 C
+132.9986620 140.6728570 C
+140.6728570 144.5389790 Bb:maj(9)/9
+144.5389790 148.3238320 C
+148.3238320 152.1667340 Bb:maj(9)/9
+152.1667340 155.9748070 C
+155.9748070 159.7712690 Bb:maj(9)/9
+159.7712690 163.6141720 C
+163.6141720 167.4338540 Bb:maj(9)/9
+167.4338540 171.3812470 C
+171.3812470 175.0666092 Bb:maj(9)/9
+175.0666092 176.2920563 C
+176.2920563 177.1154036 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+/.DS_Store/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/01_-_Taxman.lab/1.2/Sun Jul 30 21:52:25 2006//
+/02_-_Eleanor_Rigby.lab/1.2/Tue Oct 17 21:55:13 2006//
+/03_-_I'm_Only_Sleeping.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/04_-_Love_You_To.lab/1.4/Tue Oct 17 21:55:13 2006//
+/05_-_Here,_There_And_Everywhere.lab/1.2/Tue Nov  8 15:05:23 2005//
+/06_-_Yellow_Submarine.lab/1.2/Sun Jul 30 21:52:25 2006//
+/07_-_She_Said_She_Said.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/08_-_Good_Day_Sunshine.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/09_-_And_Your_Bird_Can_Sing.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/10_-_For_No_One.lab/1.2/Sun Jul 30 21:52:25 2006//
+/11_-_Doctor_Robert.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/12_-_I_Want_To_Tell_You.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/13_-_Got_To_Get_You_Into_My_Life.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/14_-_Tomorrow_Never_Knows.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/07final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/07final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/01_-_Sgt._Pepper's_Lonely_Hearts_Club_Band.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+0.0000000 12.3502092 N
+12.3502092 17.5026070 A:7
+17.5026070 20.0684120 C:7
+20.0684120 21.6821990 G
+21.6821990 22.5993870 D
+22.5993870 23.9113150 G:7
+23.9113150 25.2000220 A:7
+25.2000220 26.5467800 C:7
+26.5467800 27.7658270 G:7
+27.7658270 29.0313150 G:7
+29.0313150 30.3316320 A:7
+30.3316320 31.6319500 C:7
+31.6319500 32.8393870 G:7
+32.8393870 35.4284120 A:7
+35.4284120 37.9361670 C:7
+37.9361670 39.2248750 G
+39.2248750 40.5019720 C
+40.5019720 42.9516780 G
+42.9516780 45.5290920 C:7
+45.5290920 48.0600680 F
+48.0600680 50.5910430 C
+50.5910430 55.6646030 D
+55.6646030 56.9997500 G
+56.9997500 58.3000680 Bb:maj6
+58.3000680 59.5655550 C
+59.5655550 60.8658730 G
+60.8658730 63.4432870 C
+63.4432870 65.9162130 G
+65.9162130 67.1933100 G
+67.1933100 68.4355780 Bb:maj6
+68.4355780 69.6430150 C
+69.6430150 70.8852830 G
+70.8852830 73.3930380 A
+73.3930380 75.9007930 D
+75.9007930 78.4085480 C
+78.4085480 80.8234240 G
+80.8234240 83.0409290 A:7
+83.0409290 83.6446480 C:sus4
+83.6446480 84.2019270 C/9
+84.2019270 85.7460540 G
+85.7460540 88.1957590 C
+88.1957590 90.5990240 F:7
+90.5990240 93.0719500 C
+93.0719500 97.9365300 D
+97.9365300 99.3065070 G:7
+99.3065070 100.5371650 A:7
+100.5371650 101.7910430 C:7
+101.7910430 103.0100900 G:7
+103.0100900 104.2291380 G:7
+104.2291380 105.4017460 A:7
+105.4017460 106.6788430 C:7
+106.6788430 107.8862810 G:7
+107.8862810 110.3592060 A:7
+110.3592060 112.7276410 C:7
+112.7276410 113.9931290 G
+113.9931290 115.2121760 C:7
+115.2121760 117.6502720 G
+117.6502720 122.3915308 C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/02_-_With_A_Little_Help_From_My_Friends.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,99 @@
+0.0000000 2.2402705 C
+2.2402705 4.3833330 D
+4.3833330 8.8183440 E
+8.8183440 9.9677320 E
+9.9677320 11.0706800 B/3
+11.0706800 12.1968480 F#:min/5
+12.1968480 13.3346250 F#:min
+13.3346250 14.4027430 F#:min
+14.4027430 15.4940810 B
+15.4940810 17.7115870 E
+17.7115870 18.7797050 E
+18.7797050 19.8710430 B
+19.8710430 22.0653280 F#:min
+22.0653280 23.1450560 F#:min
+23.1450560 24.2247840 B
+24.2247840 26.4306800 E
+26.4306800 27.4523580 D
+27.4523580 28.5785260 A
+28.5785260 30.7495910 E
+30.7495910 31.8409290 D
+31.8409290 32.9206570 A
+32.9206570 35.0801130 E
+35.0801130 37.2163490 A
+37.2163490 39.4106340 E
+39.4106340 43.5786160 B
+43.5786160 44.6467340 E
+44.6467340 45.7032420 B
+45.7032420 47.8859180 F#:min
+47.8859180 48.9424260 F#:min
+48.9424260 50.0337640 B
+50.0337640 52.2048290 E
+52.2048290 53.2845570 E
+53.2845570 54.3294550 B
+54.3294550 56.4889110 F#:min
+56.4889110 57.5454190 F#:min
+57.5454190 58.5787070 B
+58.5787070 60.7381630 E
+60.7381630 61.8178910 D
+61.8178910 62.8511790 A
+62.8511790 65.0106340 E
+65.0106340 66.0787520 D
+66.0787520 67.1700900 A
+67.1700900 69.2482760 E
+69.2482760 71.3845120 A
+71.3845120 73.5671880 E
+73.5671880 75.6713594 C#:min
+75.6713594 77.8396590 F#
+77.8396590 78.9193870 E
+78.9193870 79.9642850 D
+79.9642850 82.1237410 A
+82.1237410 84.2483670 C#:min
+84.2483670 86.3613830 F#
+86.3613830 87.3830610 E
+87.3830610 88.4627890 D
+88.4627890 90.6454640 A
+90.6454640 91.7135820 E
+91.7135820 92.7933100 B
+92.7933100 94.9411560 F#:min
+94.9411560 95.9976640 F#:min
+95.9976640 97.0541720 B
+97.0541720 99.2136280 E
+99.2136280 100.2933560 E
+100.2933560 101.3730830 B
+101.3730830 103.4860990 F#:min
+103.4860990 104.5309970 F#:min
+104.5309970 105.6107250 B
+105.6107250 107.7353510 E
+107.7353510 108.7918590 D
+108.7918590 109.8367570 A
+109.8367570 111.9962130 E
+111.9962130 113.0527210 D
+113.0527210 114.1324480 A
+114.1324480 116.2686840 E
+116.2686840 118.4397500 A
+118.4397500 120.5992060 E
+120.5992060 122.7170402 C#:min
+122.7170402 124.8716780 F#
+124.8716780 125.9165750 E
+125.9165750 126.9730830 D
+126.9730830 129.1441490 A
+129.1441490 131.2687750 C#:min
+131.2687750 133.3817910 F#
+133.3817910 134.4382990 E
+134.4382990 135.4948070 D
+135.4948070 137.6542630 A
+137.6542630 138.6875510 D
+138.6875510 139.7672780 A
+139.7672780 141.8802940 E
+141.8802940 142.9716320 D
+142.9716320 144.0049200 A
+144.0049200 146.2108160 E
+146.2108160 148.3006120 A
+148.3006120 150.4484580 E
+150.4484580 152.5266430 D
+152.5266430 154.6396590 A
+154.6396590 156.7642850 C/5
+156.7642850 158.8889110 D:9/5
+158.8889110 162.9461713 E
+162.9461713 163.9035518 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/03_-_Lucy_In_The_Sky_With_Diamonds.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,120 @@
+0.0000000 0.2872142 N
+0.2872142 1.7446480 A/5
+1.7446480 3.1958950 A:7/b7
+3.1958950 4.7284120 F#:min7
+4.7284120 6.1448290 D:min/b3
+6.1448290 7.5728570 A
+7.5728570 9.0376725 A:7/b7
+9.0376725 10.4637410 F#:min7
+10.4637410 11.8569380 F:aug
+11.8569380 13.2153060 A/5
+13.2153060 14.6897730 A:7/b7
+14.6897730 16.1061900 F#:min7
+16.1061900 18.7880950 F
+18.7880950 20.2045120 A
+20.2045120 21.5628790 A:7/b7
+21.5628790 22.9560770 F#:min7
+22.9560770 24.3608840 F:aug
+24.3608840 25.6844210 A
+25.6844210 27.0776190 A:7/b7
+27.0776190 29.7943530 F#:min7
+29.7943530 31.1062810 D:min
+31.1062810 32.4530380 D:min/b7
+32.4530380 35.1117230 Bb
+35.1117230 37.7123580 C:maj(9)
+37.7123580 40.2897730 F:maj6
+40.2897730 42.8207480 Bb
+42.8207480 45.2820630 C:maj(9)
+45.2820630 47.7201580 G
+47.7201580 50.5065530 D
+50.5065530 51.8533100 G
+51.8533100 53.1768480 C
+53.1768480 55.7194330 D
+55.7194330 57.0545800 G
+57.0545800 58.3316780 C
+58.3316780 60.8046030 D
+60.8046030 62.0933100 G
+62.0933100 63.3820180 C
+63.3820180 65.9013830 D
+65.9013830 68.4671880 D
+68.4671880 69.8603850 A
+69.8603850 71.1490920 A:7/b7
+71.1490920 72.4958500 F#:min7
+72.4958500 73.9354870 F:aug
+73.9354870 75.2706340 A/5
+75.2706340 76.5709520 A:7/b7
+76.5709520 77.8480490 F#:min7
+77.8480490 80.5067340 F
+80.5067340 81.7954420 A
+81.7954420 83.1189790 A:7/b7
+83.1189790 84.5005660 F#:min7
+84.5005660 85.7544440 F:aug
+85.7544440 87.0895910 A
+87.0895910 88.4247390 A:7/b7
+88.4247390 91.0253740 F#:min
+91.0253740 92.3605210 D:min
+92.3605210 93.6376190 D:min/b7
+93.6376190 96.1918140 Bb
+96.1918140 98.6763490 C:maj(9)
+98.6763490 101.1028340 F:maj6
+101.1028340 103.5060990 Bb
+103.5060990 105.9325850 C:maj(9)
+105.9325850 108.3474600 G
+108.3474600 111.0641950 D
+111.0641950 112.3412920 G
+112.3412920 113.6880490 C
+113.6880490 116.2306340 D
+116.2306340 117.5309520 G
+117.5309520 118.8080490 C
+118.8080490 121.3622440 D
+121.3622440 122.6161220 G
+122.6161220 123.8816090 C
+123.8816090 126.4009750 D
+126.4009750 128.9319500 D
+128.9319500 130.3715870 A
+130.3715870 131.6602940 A:7/b7
+131.6602940 133.0070520 F#:min7
+133.0070520 134.3421990 F:aug
+134.3421990 135.7237860 A
+135.7237860 137.0705440 A:7/b7
+137.0705440 138.4056910 F#:min
+138.4056910 140.9366660 F
+140.9366660 142.2834240 A/5
+142.2834240 143.5489110 A:7/b7
+143.5489110 144.8608390 F#:min7
+144.8608390 146.1959860 F:aug
+146.1959860 147.5079130 A/5
+147.5079130 148.8198410 A:7/b7
+148.8198410 151.3972560 F#:min
+151.3972560 153.9514510 D:maj(*3)
+153.9514510 155.1704980 G
+155.1704980 156.4475960 C
+156.4475960 158.9205210 D
+158.9205210 160.1627890 G
+160.1627890 161.4282760 C
+161.4282760 163.8083210 D
+163.8083210 165.0970290 G
+165.0970290 166.3392970 C
+166.3392970 168.7425620 D
+168.7425620 171.2154870 D
+171.2154870 173.7116320 A
+173.7116320 174.9539000 G
+174.9539000 176.1729470 C
+176.1729470 178.5762130 D
+178.5762130 179.8533100 G
+179.8533100 181.0491380 C
+181.0491380 183.5104530 D
+183.5104530 184.7295010 G
+184.7295010 185.9717680 C
+185.9717680 188.4098630 D
+188.4098630 190.8711790 D
+190.8711790 193.3557140 A
+193.3557140 194.5979810 G
+194.5979810 195.8286390 C
+195.8286390 198.2435140 D
+198.2435140 199.4625620 G
+199.4625620 200.7048290 C
+200.7048290 203.1429250 D
+203.1429250 204.3735820 G
+204.3735820 205.5810200 C
+205.5810200 208.3451574 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/04_-_Getting_Better.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,74 @@
+0.0000000 0.4403951 N
+0.4403951 4.6387520 F:maj(9)/5
+4.6387520 6.6937180 C
+6.6937180 8.7719040 F:maj(9)/5
+8.7719040 24.8401130 G
+24.8401130 26.8370290 C
+26.8370290 28.8107250 D:min7(4)/5
+28.8107250 30.8192510 E:min7
+30.8192510 32.8161670 F:maj(9)/6
+32.8161670 34.8479130 C
+34.8479130 36.7867800 D:min7(4)/5
+36.7867800 38.8069160 E:min7
+38.8069160 40.7922220 F:maj(9)
+40.7922220 60.4246930 G
+60.4246930 62.3983900 C
+62.3983900 64.3836960 D:min7(4)/b7
+64.3836960 66.2877320 E:min7
+66.2877320 68.2265980 F:maj(9)/6
+68.2265980 70.3163940 C
+70.3163940 72.1739900 D:min7(4)/b7
+72.1739900 74.1244670 E:min7
+74.1244670 76.1329930 F:maj(9)
+76.1329930 76.5857820 F
+76.5857820 77.1082310 C/3
+77.1082310 77.5610200 F
+77.5610200 78.0648108 C/3
+78.0648108 78.5362580 F
+78.5362580 79.0238770 C/3
+79.0238770 79.5231060 F
+79.5231060 80.0223350 C/4
+80.0223350 82.0192510 C
+82.0192510 83.9581170 D:min7(4)/b7
+83.9581170 85.9085940 E:min7/b3
+85.9085940 87.8590700 F:maj(9)
+87.8590700 89.8095460 C
+89.8095460 91.8064620 D:min7(4)/b7
+91.8064620 93.7685480 E:min7/b3
+93.7685480 95.7422440 F:maj(9)
+95.7422440 117.3135820 G
+117.3135820 119.2130273 C
+119.2130273 121.1680950 D:min7(4)/b7
+121.1680950 123.1534010 E:min7/b3
+123.1534010 125.0690470 F:maj(9)
+125.0690470 127.0543530 C
+127.0543530 128.9932190 D:min7(4)/b7
+128.9932190 130.9785260 E:min7/b3
+130.9785260 132.9406120 F:maj(9)
+132.9406120 133.4494506 F
+133.4494506 133.9375403 C/3
+133.9375403 134.3970830 F
+134.3970830 134.9140685 C/3
+134.9140685 135.3712337 F
+135.3712337 135.8714491 C/5
+135.8714491 136.3539450 F/3
+136.3539450 136.9054201 G/3
+136.9054201 138.8036500 C
+138.8036500 140.7541260 D:min7(4)/b7
+140.7541260 142.7046030 E:min7/b3
+142.7046030 144.6782990 F:maj(9)
+144.6782990 146.6519950 C
+146.6519950 148.6605210 D:min7(4)/b7
+148.6605210 150.5877770 E:min7/b3
+150.5877770 152.5614730 F:maj(9)
+152.5614730 152.9678230 F
+152.9678230 153.5251020 C/3
+153.5251020 154.0011110 F
+154.0011110 154.5119500 C/3
+154.5119500 154.9531290 F
+154.9531290 155.4523580 C/3
+155.4523580 155.9764408 F
+155.9764408 156.4392060 G/3
+156.4392060 157.9869400 C
+157.9869400 167.0054649 G:(1)
+167.0054649 167.7713693 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/05_-_Fixing_A_Hole.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,99 @@
+0.0000000 0.3314510 N
+0.3314510 1.7594780 F
+1.7594780 2.9785260 C:aug
+2.9785260 4.3273601 F:min7
+4.3273601 6.7053280 Bb:7
+6.7053280 7.8547160 F
+7.8547160 9.0041040 C:aug
+9.0041040 10.1534920 F:min7
+10.1534920 11.2796590 F:min6/5
+11.2796590 13.5552150 F:min7
+13.5552150 15.7776316 F:min6
+15.7776316 18.0714960 F:min7
+18.0714960 20.3238320 F:min6
+20.3238320 22.5761670 F:min7
+22.5761670 24.8401130 F:min6
+24.8401130 25.9430610 F
+25.9430610 27.0343990 C:aug
+27.0343990 28.1025170 F:min7
+28.1025170 29.2402940 F:min6/5
+29.2402940 31.4694100 F:min7
+31.4694100 33.6172560 F:min6
+33.6172560 35.8115410 F:min7
+35.8115410 37.9477770 F:min6
+37.9477770 40.0956230 F:min7
+40.0956230 42.3247390 F:min6
+42.3247390 43.4392970 F
+43.4392970 44.5306340 C:9(*3)
+44.5306340 45.5871420 F
+45.5871420 46.6436500 C:9(*3)
+46.6436500 47.7233780 F
+47.7233780 48.7566660 C:9(*3)
+48.7566660 50.9277320 F
+50.9277320 52.0190700 C
+52.0190700 53.0871880 G
+53.0871880 54.1553060 C
+54.1553060 55.1769840 G
+55.1769840 56.2799310 C
+56.2799310 57.3596590 G
+57.3596590 59.4958950 C
+59.4958950 60.6336730 F
+60.6336730 61.6901810 C:aug
+61.6901810 62.7931290 F:min7
+62.7931290 63.8612470 F:min6/5
+63.8612470 66.0090920 F:min7
+66.0090920 68.0988880 F:min6
+68.0988880 70.2931740 F:min7
+70.2931740 72.3713600 F:min6
+72.3713600 74.5308160 F:min7
+74.5308160 76.6090020 F:min6
+76.6090020 77.7003400 F
+77.7003400 78.7800680 C:aug
+78.7800680 79.8365750 F:min7
+79.8365750 80.8698630 F:min6
+80.8698630 82.9596590 F:min7
+82.9596590 85.0378450 F:min6
+85.0378450 87.0928110 F:min7
+87.0928110 89.1477770 F:min6
+89.1477770 91.1679130 F:min7
+91.1679130 93.2577090 F:min6
+93.2577090 94.3026070 F
+94.3026070 95.3707250 C:9(*3)
+95.3707250 96.4156230 F
+96.4156230 97.4489110 C:9(*3)
+97.4489110 98.4821990 F
+98.4821990 99.5038770 C:9(*3)
+99.5038770 101.5936730 F
+101.5936730 102.6269610 C
+102.6269610 103.6718590 G
+103.6718590 104.7051470 C
+104.7051470 105.6919950 G
+105.6919950 106.7368930 C
+106.7368930 107.7469610 G
+107.7469610 109.8019270 C
+109.8019270 110.8816550 F
+110.8816550 111.9497730 C:aug
+111.9497730 112.9946710 F:min7
+112.9946710 114.0627890 F:min6
+114.0627890 116.1409750 F:min7
+116.1409750 118.2191600 F:min6
+118.2191600 120.3553960 F:min7
+120.3553960 122.4684120 F:min6/b3
+122.4684120 124.5582080 F:min7/b3
+124.5582080 126.5783440 F:min6/b3
+126.5783440 127.6812920 F
+127.6812920 128.7378000 C:aug
+128.7378000 129.7710880 F:min7
+129.7710880 130.8624260 F:min6/5
+130.8624260 132.9638320 F:min7
+132.9638320 135.0304080 F:min6
+135.0304080 137.0969840 F:min7
+137.0969840 139.1867800 F:min6
+139.1867800 141.1836960 F:min7
+141.1836960 143.2502720 F:min6
+143.2502720 145.3748970 F:min7
+145.3748970 147.3950340 F:min6
+147.3950340 149.4383900 F:min7
+149.4383900 151.5049650 F:min6
+151.5049650 153.5251020 F:min7
+153.5251020 156.4742787 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/06_-_She's_Leaving_Home.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,75 @@
+0.0000000 0.4475510 N
+0.4475510 5.9158500 E
+5.9158500 7.2858270 E
+7.2858270 8.6906340 B:min
+8.6906340 10.0373920 A/3
+10.0373920 11.4073690 A
+11.4073690 12.8005660 C#:min/5
+12.8005660 14.2169840 C#:min
+14.2169840 16.9917680 F#
+16.9917680 19.8246030 A:maj/9
+19.8246030 22.5993870 B
+22.5993870 25.3509520 A:maj/9
+25.3509520 28.1953960 B
+28.1953960 29.5769840 E
+29.5769840 31.0050110 B:min
+31.0050110 32.3865980 F#:min
+32.3865980 33.8262350 F#:min/5
+33.8262350 36.6293802 C#:min/5
+36.6293802 39.5615640 F#
+39.5615640 42.3711790 A:maj/9
+42.3711790 45.1111330 B
+45.1111330 47.9207480 A:maj/9
+47.9207480 50.7535820 B
+50.7535820 64.7784350 E
+64.7784350 67.5300000 B:min/b3
+67.5300000 70.3976640 C#:min
+70.3976640 73.2072780 F#:9
+73.2072780 76.1678230 C#:min
+76.1678230 77.6422900 F#:9
+77.6422900 79.2096370 E
+79.2096370 80.6492740 B:min/b3
+80.6492740 82.1585710 F#:min
+82.1585710 83.5982080 F#:min/b3
+83.5982080 86.5239220 C#:min
+86.5239220 89.4264170 F#
+89.4264170 92.2940810 A:maj/9
+92.2940810 95.1617460 B
+95.1617460 97.9945800 A:maj/9
+97.9945800 100.9319040 B
+100.9319040 102.3599310 E
+102.3599310 103.7763490 B:min/b3
+103.7763490 106.7949430 F#:min
+106.7949430 109.6742170 C#:min
+109.6742170 112.4954420 F#:9
+112.4954420 115.2934460 A:maj/9
+115.2934460 118.2191600 B
+118.2191600 121.1797050 A:maj/9
+121.1797050 124.1750790 B
+124.1750790 138.0954420 E
+138.0954420 140.9166660 B:min/b3
+140.9166660 143.8539900 C#:min
+143.8539900 146.6636050 F#:9
+146.6636050 149.5196590 C#:min
+149.5196590 150.9825170 F#:maj(9)
+150.9825170 152.5150340 E
+152.5150340 153.9546710 B:min
+153.9546710 155.4175280 F#:min
+155.4175280 156.8107250 F#:min/5
+156.8107250 159.6667800 C#:min/5
+159.6667800 162.5344440 F#
+162.5344440 165.3672780 A:maj/9
+165.3672780 168.1885030 B
+168.1885030 171.1142170 A:maj/9
+171.1142170 174.0167120 B
+174.0167120 187.7745350 E
+187.7745350 190.5493190 B:min/b3
+190.5493190 193.4291683 C#:min
+193.4291683 196.2614280 F#:9
+196.2614280 199.1058730 C#:min
+199.1058730 201.9619270 F#:9
+201.9619270 204.9108610 C#:min
+204.9108610 207.8017460 F#
+207.8017460 210.9828790 A
+210.9828790 213.8405218 E
+213.8405218 214.9510833 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/07_-_Being_For_The_Benefit_Of_Mr._Kite!.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,113 @@
+0.0000000 0.5172100 N
+0.5172100 2.6418360 Bb
+2.6418360 4.7664620 A
+4.7664620 5.8694100 D:min
+5.8694100 6.9375280 G
+6.9375280 8.0288660 C:min
+8.0288660 9.1782530 G:aug
+9.1782530 10.2579810 Bb
+10.2579810 11.3377090 D:min
+11.3377090 13.5436050 G
+13.5436050 15.7030610 G:aug
+15.7030610 16.7943990 C:min
+16.7943990 17.9205660 G:aug
+17.9205660 18.9654640 Bb
+18.9654640 20.0684120 D:min
+20.0684120 22.2394780 A
+22.2394780 23.3424260 D:min
+23.3424260 24.4105440 D:min7/b7
+24.4105440 25.4438320 G:min/b3
+25.4438320 26.5003400 A
+26.5003400 28.6249650 D:min
+28.6249650 29.6814730 G:min
+29.6814730 30.8076410 A
+30.8076410 32.8626070 D:min
+32.8626070 33.9075050 G:min
+33.9075050 34.9988430 A
+34.9988430 36.0437410 D:min
+36.0437410 37.1350790 G
+37.1350790 38.2612470 C:min
+38.2612470 39.3409750 G:aug
+39.3409750 40.4207020 Bb
+40.4207020 41.4772100 D:min
+41.4772100 43.6018360 G
+43.6018360 45.7496820 G:aug
+45.7496820 46.8178000 C:min
+46.8178000 47.8046480 G:aug
+47.8046480 48.9308160 Bb
+48.9308160 49.9292740 D:min
+49.9292740 52.0887300 A
+52.0887300 53.1568480 D:min
+53.1568480 54.2017460 D:min7/b7
+54.2017460 55.2582530 G:min/b3
+55.2582530 56.3612010 A
+56.3612010 58.4742170 D:min
+58.4742170 59.5191150 G:min
+59.5191150 60.5756230 A
+60.5756230 61.7598410 D:min
+61.7598410 62.9092290 A:aug/#5
+62.9092290 64.0353960 C
+64.0353960 65.1267340 E:min
+65.1267340 67.3558500 A
+67.3558500 69.5733560 A:aug
+69.5733560 70.6646930 D:min
+70.6646930 71.7676410 A:aug/#5
+71.7676410 72.8705890 C
+72.8705890 73.9038770 E:min
+73.9038770 76.0865530 B
+76.0865530 78.2924480 E:min
+78.2924480 79.3477008 A:min/b3
+79.3477008 80.4402940 B
+80.4402940 82.5533100 E:min
+82.5533100 83.6562580 A:min/b3
+83.6562580 84.7127660 B
+84.7127660 86.8838320 E:min
+86.8838320 89.1361670 G
+89.1361670 90.2623350 C:min
+90.2623350 91.3652830 G:aug
+91.3652830 92.4334010 Bb
+92.4334010 93.5131290 D:min
+93.5131290 95.6493650 G
+95.6493650 97.7972100 G:aug
+97.7972100 98.8537180 C:min
+98.8537180 99.9218360 G:aug
+99.9218360 101.0596140 Bb
+101.0596140 102.0929020 D:min
+102.0929020 104.2523580 A
+104.2523580 105.3436960 D:min
+105.3436960 106.4234240 D:min7/b7
+106.4234240 107.5031510 G:min/b3
+107.5031510 108.5132190 A
+108.5132190 110.6610650 D:min
+110.6610650 111.7407930 G:min/b3
+111.7407930 112.8437410 A
+112.8437410 114.9103170 D:min
+114.9103170 115.9668250 G:min/b3
+115.9668250 117.0001130 A
+117.0001130 118.0798410 D:min
+118.0798410 119.1943990 A:aug
+119.1943990 120.2857360 C
+120.2857360 121.3654640 E:min
+121.3654640 123.5713600 A
+123.5713600 125.6959860 A:aug
+125.6959860 126.7873240 D:min
+126.7873240 127.8902720 A:aug
+127.8902720 128.9700000 C
+128.9700000 130.0729470 E:min
+130.0729470 132.1975730 B
+132.1975730 133.2656910 E:min
+133.2656910 134.3221990 E:min/b3
+134.3221990 135.4019270 A:min/b3
+135.4019270 136.4816550 B
+136.4816550 138.5598410 E:min
+138.5598410 139.6511790 A:min/b3
+139.6511790 140.7192970 B
+140.7192970 142.9019720 E:min
+142.9019720 143.9584800 A:min/b3
+143.9584800 145.0265980 B
+145.0265980 146.0831060 E:min
+146.0831060 147.1860540 E:min7/b7
+147.1860540 148.2890020 A:min/b3
+148.2890020 149.4151700 B
+149.4151700 154.7509937 E:min
+154.7509937 156.9721166 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/08_-_Within_You_Without_You.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,16 @@
+0.0000000 1.2062995 N
+1.2062995 31.4694100 C#
+31.4694100 60.3915657 C#
+60.3915657 64.1398860 F#/5
+64.1398860 118.9258131 C#
+118.9258131 127.0061051 F#/5
+127.0061051 130.8159860 C#
+130.8159860 135.5644670 F#/5
+135.5644670 136.0629252 C#:sus4
+136.0629252 273.4853307 C#
+273.4853307 281.2401133 F#/5
+281.2401133 284.9616550 C#
+284.9616550 289.5940360 F#/5
+289.5940360 290.0288668 C#:sus4
+290.0288668 304.4661656 C#
+304.4661656 304.9831511 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/09_-_When_I'm_Sixty-Four.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,77 @@
+0.0000000 0.3446570 N
+0.3446570 3.7796140 Db
+3.7796140 4.6503620 Gb
+4.6503620 5.5211110 Ab
+5.5211110 7.5180270 Db
+7.5180270 10.7339900 Db
+10.7339900 16.0049200 Db
+16.0049200 17.7696370 Ab
+17.7696370 22.9476870 Ab
+22.9476870 24.6427430 Db
+24.6427430 28.0792970 Db
+28.0792970 29.8091830 Db:7
+29.8091830 31.4926300 Gb
+31.4926300 32.3749880 Gb
+32.3749880 33.2457360 E:dim7/b3
+33.2457360 34.1048750 Db/5
+34.1048750 34.9059630 Bb:7
+34.9059630 35.7651020 Eb:9
+35.7651020 36.6126300 Ab
+36.6126300 38.4005660 Db
+38.4005660 41.7558500 Bb:min
+41.7558500 43.4276870 Ab
+43.4276870 45.1343530 Bb:min
+45.1343530 48.5128570 Bb:min
+48.5128570 51.9610200 F
+51.9610200 55.3627430 Bb:min
+55.3627430 58.7180270 Eb:min
+58.7180270 60.4363030 Gb
+60.4363030 62.0965300 Ab
+62.0965300 63.8148070 Db
+63.8148070 67.2978000 Ab
+67.2978000 72.3713600 Db
+72.3713600 74.0664170 Ab
+74.0664170 79.2096370 Ab:7
+79.2096370 80.8814730 Db
+80.8814730 84.2135370 Db
+84.2135370 85.9550340 Db:7
+85.9550340 87.5920400 Gb
+87.5920400 88.4976190 Gb
+88.4976190 89.3335370 E:dim7/b3
+89.3335370 90.1810650 Db/5
+90.1810650 91.0053740 Bb:7
+91.0053740 91.8877320 Eb:9
+91.8877320 92.7120400 Ab
+92.7120400 94.4883670 Db
+94.4883670 97.8320400 Bb:min
+97.8320400 99.5270970 Ab
+99.5270970 101.2337640 Bb:min
+101.2337640 104.5774370 Bb:min
+104.5774370 107.9327210 F
+107.9327210 111.3112240 Bb:min
+111.3112240 114.6665070 Eb:min
+114.6665070 116.3383440 Gb
+116.3383440 118.0682310 Ab
+118.0682310 119.7865070 Db
+119.7865070 123.2114510 Ab
+123.2114510 128.3430610 Db
+128.3430610 130.0148970 Ab
+130.0148970 135.1348970 Ab
+135.1348970 136.8067340 Db
+136.8067340 140.1736280 Db
+140.1736280 141.8222440 Db:7
+141.8222440 143.5056910 Gb
+143.5056910 144.3648290 Gb
+144.3648290 145.2123580 E:dim7/b3
+145.2123580 146.0482760 Db/5
+146.0482760 146.8725850 Bb:7
+146.8725850 147.7433330 Eb:9
+147.7433330 148.5676410 Ab
+148.5676410 150.3439680 Db
+150.3439680 153.7573010 Db
+153.7573010 154.6048290 Gb
+154.6048290 155.4291380 Ab
+155.4291380 155.8232599 Db
+155.8232599 156.3210978 Ab
+156.3210978 156.7997881 Db
+156.7997881 157.6231354 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/10_-_Lovely_Rita.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,90 @@
+0.0000000 0.2680666 N
+0.2680666 3.0714050 B
+3.0714050 5.7649200 A
+5.7649200 8.5048750 E
+8.5048750 11.2332190 B
+11.2332190 13.9731740 B
+13.9731740 16.7015190 A
+16.7015190 19.4414730 E
+19.4414730 22.1698180 B
+22.1698180 23.5281850 E
+23.5281850 24.2480040 D
+24.2480040 24.9213830 A
+24.9213830 26.2913600 E
+26.2913600 27.6613370 B
+27.6613370 29.0080950 C#:min
+29.0080950 30.4245120 F#
+30.4245120 33.1992970 B
+33.1992970 34.6157140 E
+34.6157140 35.9624710 A
+35.9624710 37.3324480 D
+37.3324480 38.7140360 G
+38.7140360 40.0956230 E
+40.0956230 41.4772100 B
+41.4772100 42.8471880 E
+42.8471880 44.2403850 A
+44.2403850 45.5987520 D
+45.5987520 46.9222900 G
+46.9222900 48.3387070 E
+48.3387070 49.7086840 B
+49.7086840 50.3820630 E
+50.3820630 51.0902720 C#:min
+51.0902720 51.7636500 F#:min
+51.7636500 52.4602490 B
+52.4602490 53.8766660 E
+53.8766660 54.5964850 D
+54.5964850 55.2698630 A
+55.2698630 56.6398410 E
+56.6398410 57.9749880 B
+57.9749880 59.3565750 C#:min
+59.3565750 60.7149430 F#
+60.7149430 62.1339983 B
+62.1339983 63.5361670 A/9
+63.5361670 64.8945350 E/5
+64.8945350 66.3109520 B
+66.3109520 69.0625170 A/9
+69.0625170 71.7560310 B
+71.7560310 73.1027890 E
+73.1027890 73.8109970 D
+73.8109970 74.4611560 A
+74.4611560 75.8659630 E
+75.8659630 77.1778910 B
+77.1778910 78.5594780 C#:min
+78.5594780 79.9410650 F#
+79.9410650 82.7390700 B
+82.7390700 84.0742170 E
+84.0742170 85.3977550 A
+85.3977550 86.7561220 D
+86.7561220 88.1377090 G
+88.1377090 89.4960770 E
+89.4960770 90.8776640 B
+90.8776640 92.2244210 E
+92.2244210 93.6060090 A
+93.6060090 94.9411560 D
+94.9411560 96.3227430 G
+96.3227430 97.7275510 E
+97.7275510 99.0626980 B
+99.0626980 99.7360770 E
+99.7360770 100.4675050 C#:min
+100.4675050 101.1408840 F#:min
+101.1408840 101.8258730 B
+101.8258730 103.2306800 E
+103.2306800 103.8924480 D
+103.8924480 104.6122670 A
+104.6122670 105.9822440 E
+105.9822440 107.3406120 B
+107.3406120 108.7454190 C#:min
+108.7454190 110.0689560 F#
+110.0689560 112.7973010 B
+112.7973010 115.5256460 A
+115.5256460 118.2191600 E
+118.2191600 120.9591150 B
+120.9591150 123.6874600 B
+123.6874600 126.3925850 A
+126.3925850 129.0977090 E
+129.0977090 131.7447840 B
+131.7447840 153.2383324 A:(1,2,4)
+153.2383324 158.5986620 A:min7(*b3)
+158.5986620 159.9105890 D:min7(*b3)
+159.9105890 161.3952148 A:(1)
+161.3952148 162.0462336 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/11_-_Good_Morning_Good_Morning.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,137 @@
+0.0000000 3.5997509 N
+3.5997509 4.6155320 A
+4.6155320 5.6604300 D
+5.6604300 6.7053280 A
+6.7053280 7.7618360 D
+7.7618360 8.7602940 A
+8.7602940 9.7703620 D
+9.7703620 10.0524959 A
+10.0524959 11.7324480 A/5
+11.7324480 12.4638770 A:min
+12.4638770 13.2069160 E:min
+13.2069160 15.6450110 G
+15.6450110 16.1797315 A
+16.1797315 16.6550790 E:(1)
+16.6550790 17.4213370 A
+17.4213370 18.1411560 E:min
+18.1411560 20.5676410 G
+20.5676410 22.5181170 A
+22.5181170 25.0142630 D
+25.0142630 26.9763490 E
+26.9763490 27.7542170 A
+27.7542170 28.4856460 E:min
+28.4856460 29.9833330 G
+29.9833330 30.9701810 A
+30.9701810 31.9221990 D
+31.9221990 33.8726750 A
+33.8726750 34.6041040 A
+34.6041040 35.3007020 E:min
+35.3007020 37.7852380 G
+37.7852380 38.3309070 A
+38.3309070 38.8417460 E:(1)
+38.8417460 39.5731740 A
+39.5731740 40.2813830 E:min
+40.2813830 42.7659180 G
+42.7659180 43.7522916 A
+43.7522916 44.7280040 D
+44.7280040 45.7148520 A
+45.7148520 46.7249200 D
+46.7249200 47.7117680 A
+47.7117680 48.6986160 D
+48.6986160 49.7319040 A
+49.7319040 50.7303620 D
+50.7303620 51.7172100 A
+51.7172100 52.6808390 D
+52.6808390 53.7025170 A
+53.7025170 54.6661450 E
+54.6661450 55.4207930 A
+55.4207930 56.1290020 E:min
+56.1290020 58.5903170 G
+58.5903170 59.1127660 A
+59.1127660 59.6468250 E:(1)
+59.6468250 60.4130830 A
+60.4130830 61.0632420 E:min
+61.0632420 63.5709970 G
+63.5709970 65.4982530 A
+65.4982530 68.0408390 D
+68.0408390 69.9564850 E
+69.9564850 70.7111330 A
+70.7111330 71.5006120 E:min
+71.5006120 72.9402490 G
+72.9402490 73.9503170 A
+73.9503170 74.8907250 D
+74.8907250 76.8760310 A
+76.8760310 77.6190700 A
+77.6190700 78.3504980 E:min
+78.3504980 80.8350340 G
+80.8350340 81.3390524 A
+81.3390524 81.8177426 A/5
+81.8177426 82.6113600 A
+82.6113600 83.3079590 E:min
+83.3079590 85.7344440 G
+85.7344440 86.7445120 A
+86.7445120 87.7081400 D
+87.7081400 88.6833780 A
+88.6833780 89.6934460 D
+89.6934460 90.6222440 A
+90.6222440 91.6090920 D
+91.6090920 92.5959410 A
+92.5959410 93.5711790 D
+93.5711790 94.5696370 A
+94.5696370 95.5216550 D
+95.5216550 96.6246030 A
+96.6246030 97.5185710 E
+97.5185710 98.2964390 A
+98.2964390 99.0162580 E:min
+99.0162580 101.4427430 G
+101.4427430 101.8844392 A
+101.8844392 102.4876410 E:(1)
+102.4876410 103.2306800 A
+103.2306800 103.9504980 E:min
+103.9504980 106.3769840 G
+106.3769840 108.3042400 A
+108.3042400 110.7771650 D
+110.7771650 112.7160310 E
+112.7160310 113.4822900 A
+113.4822900 114.2253280 E:min
+114.2253280 115.7230150 G
+115.7230150 116.6750340 A
+116.6750340 117.6270520 D
+117.6270520 119.6239680 A
+119.6239680 120.5411560 A
+120.5411560 121.5396140 D
+121.5396140 122.5496820 A
+122.5496820 123.4436500 D
+123.4436500 124.4188880 A
+124.4188880 125.4405660 D
+125.4405660 126.4506340 A
+126.4506340 127.3678230 D
+127.3678230 128.2966210 A
+128.2966210 129.2950790 D
+129.2950790 130.0148970 A
+130.0148970 131.1875050 D
+131.1875050 132.2091830 A
+132.2091830 133.1960310 D
+133.1960310 133.8578000 A
+133.8578000 135.0768480 D
+135.0768480 135.8082760 A
+135.8082760 136.8531740 D
+136.8531740 137.7471420 A
+137.7471420 139.0242400 D
+139.0242400 140.0226980 A
+140.0226980 141.0327660 D
+141.0327660 141.7525850 A
+141.7525850 143.0412920 D
+143.0412920 143.7959410 A
+143.7959410 144.7595690 D
+144.7595690 145.6999770 A
+145.6999770 146.9074140 D
+146.9074140 147.7201130 A
+147.7201130 148.6721310 D
+148.6721310 149.6589790 A
+149.6589790 150.7851470 D
+150.7851470 151.6442850 A
+151.6442850 152.6256088 D
+152.6256088 153.6212846 A
+153.6212846 154.5595176 D
+154.5595176 161.2228863 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/12_-_Sgt._Pepper's_Lonely_Hearts_Club_Band_(Reprise).lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+0.0000000 0.5172100 N
+0.5172100 1.1488567 G:(1)
+1.1488567 12.5335370 N
+12.5335370 20.5328110 F
+20.5328110 21.5428790 F
+21.5428790 22.5645570 Ab
+22.5645570 23.5862350 Bb
+23.5862350 24.6079130 F
+24.6079130 26.6512690 Bb
+26.6512690 28.5785260 F
+28.5785260 29.6118140 F
+29.6118140 30.6218820 Ab
+30.6218820 31.6667800 Bb
+31.6667800 32.7000680 F
+32.7000680 34.7550340 G
+34.7550340 36.6939000 C
+36.6939000 38.7604760 Bb
+38.7604760 40.8038320 F
+40.8038320 42.8239680 G
+42.8239680 44.8208840 D
+44.8208840 45.8425620 G
+45.8425620 46.8526300 Bb
+46.8526300 47.8626980 C
+47.8626980 48.9075960 G
+48.9075960 50.9509520 C
+50.9509520 52.9594780 G
+52.9594780 54.0159860 G
+54.0159860 55.0144440 Bb
+55.0144440 56.0361220 C
+56.0361220 57.0694100 G
+57.0694100 59.0895460 A
+59.0895460 61.0864620 D
+61.0864620 63.1414280 C
+63.1414280 65.1499540 G
+65.1499540 67.1817000 A
+67.1817000 71.1987520 C:maj(2)
+71.1987520 73.2421080 G
+73.2421080 75.2738540 Bb
+75.2738540 77.2707700 C
+77.2707700 78.8690105 G
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/13_-_A_Day_In_The_Life.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,120 @@
+0.0000000 1.9147611 G
+1.9147611 3.3699796 B:min
+3.3699796 6.5195690 E:min7
+6.5195690 12.8480471 C
+12.8480471 14.4259630 G
+14.4259630 15.9236500 B:min/5
+15.9236500 17.4909970 E:min7
+17.4909970 18.9886840 E:min7/b7
+18.9886840 20.5560310 C
+20.5560310 22.1233780 E:min/5
+22.1233780 25.2232420 A:min
+25.2232420 26.7441490 G
+26.7441490 28.3695460 B:min
+28.3695460 29.9252830 E:min7
+29.9252830 31.4461900 E:min7/b7
+31.4461900 33.0599770 C
+33.0599770 34.5924940 F
+34.5924940 36.1482310 E:min
+36.1482310 37.6807480 E:min7/b7
+37.6807480 39.2945350 C
+39.2945350 40.8154420 F
+40.8154420 42.3827890 E:min
+42.3827890 43.5437860 C
+43.5437860 43.9501360 D
+43.9501360 45.5174820 G
+45.5174820 47.0035600 B:min/5
+47.0035600 50.0337640 E:min7/b7
+50.0337640 51.6591600 C
+51.6591600 53.1452380 E:min/5
+53.1452380 56.3495910 A:min
+56.3495910 57.8704980 G
+57.8704980 59.4494550 B:min
+59.4494550 61.3186620 E:min7
+61.3186620 62.4100000 E:min7/b7
+62.4100000 64.0353960 C
+64.0353960 65.5563030 F
+65.5563030 67.1584800 E:min
+67.1584800 68.6561670 E:min7/b7
+68.6561670 71.6979810 C
+71.6979810 73.2537180 G
+73.2537180 74.7862350 B:min/5
+74.7862350 76.2723120 E:min7
+76.2723120 77.8048290 E:min7/b7
+77.8048290 79.4070060 C
+79.4070060 80.9046930 E:min/5
+80.9046930 82.8783900 A:min
+82.8783900 83.9813370 A:min/5
+83.9813370 85.5370740 G
+85.5370740 87.0231510 B:min
+87.0231510 88.5672780 E:min7
+88.5672780 90.0881850 E:min7/b7
+90.0881850 91.6787520 C
+91.6787520 93.1996590 F
+93.1996590 94.7670060 E:min
+94.7670060 96.2646930 E:min7/b7
+96.2646930 100.8970740 C
+100.8970740 102.3947610 F#:(1,4,b7)
+102.3947610 103.9040580 E:min/b3
+103.9040580 105.4365750 A:min(2)
+105.4365750 106.9690920 E:min(*3)/5
+106.9690920 108.5132190 C#:dim7(*b5)
+108.5132190 110.1037860 E:min(*5)/b7
+110.1037860 111.6827430 E:min(*5)
+111.6827430 113.2617000 E:min(*5)
+113.2617000 135.6799729 N
+135.6799729 145.9437860 E
+145.9437860 148.8578910 D
+148.8578910 150.3207480 E
+150.3207480 151.7371650 B
+151.7371650 153.1768020 E
+153.1768020 156.1141260 B
+156.1141260 160.4910880 E
+160.4910880 163.4168020 D
+163.4168020 164.8216090 E
+164.8216090 166.3076870 B
+166.3076870 167.7008840 E
+167.7008840 169.1521310 B
+169.1521310 172.1126750 C
+172.1126750 174.9687300 G
+174.9687300 177.9176640 D
+177.9176640 180.8782080 A
+180.8782080 183.8039220 E
+183.8039220 186.6599770 C
+186.6599770 189.6089110 G
+189.6089110 192.4649650 D
+192.4649650 195.4487300 A
+195.4487300 196.4936280 E:(1)
+196.4936280 196.8767570 D:(1)
+196.8767570 197.9448750 C:(1)
+197.9448750 198.3396140 D:(1)
+198.3396140 199.8721310 G
+199.8721310 201.3233780 B:min/5
+201.3233780 202.8558950 E:min7
+202.8558950 204.3187520 E:min7/b7
+204.3187520 205.7816090 C
+205.7816090 207.2096370 E:min/5
+207.2096370 209.1368930 A:min
+209.1368930 210.2166210 F#:hdim7
+210.2166210 211.6562580 G
+211.6562580 213.1075050 B:min
+213.1075050 214.6168020 E:min7
+214.6168020 216.0680490 E:min7/b7
+216.0680490 217.5541260 C
+217.5541260 218.9937640 F
+218.9937640 220.4914510 E:min
+220.4914510 221.9426980 E:min7/b7
+221.9426980 224.8568020 C
+224.8568020 226.3544890 C
+226.3544890 227.7825170 F#:(1,4,b5)
+227.7825170 229.2453740 E:min/b3
+229.2453740 230.7198410 A:min(2)
+230.7198410 232.1362580 E:min(*b3)/5
+232.1362580 233.5642850 C:maj7(*5)
+233.5642850 234.9923120 E:min7(*5)/b7
+234.9923120 241.3364915 E:(1,2,5,b6)
+241.3364915 259.3160984 N
+259.3160984 261.1542691 E:(1)
+261.1542691 303.6236707 E
+303.6236707 306.8596170 N
+306.8596170 333.7045679 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+/.DS_Store/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/01_-_Sgt._Pepper's_Lonely_Hearts_Club_Band.lab/1.1.1.1/Fri Sep 23 09:24:39 2005//
+/02_-_With_A_Little_Help_From_My_Friends.lab/1.2/Tue Oct 17 21:55:42 2006//
+/03_-_Lucy_In_The_Sky_With_Diamonds.lab/1.2/Sun Jul 30 21:53:00 2006//
+/04_-_Getting_Better.lab/1.3/Tue Oct 17 21:55:42 2006//
+/05_-_Fixing_A_Hole.lab/1.2/Sun Jul 30 21:53:00 2006//
+/06_-_She's_Leaving_Home.lab/1.2/Sun Jul 30 21:53:00 2006//
+/07_-_Being_For_The_Benefit_Of_Mr._Kite!.lab/1.2/Sun Jul 30 21:53:00 2006//
+/08_-_Within_You_Without_You.lab/1.2/Tue Oct 17 21:55:42 2006//
+/09_-_When_I'm_Sixty-Four.lab/1.2/Sun Jul 30 21:53:00 2006//
+/10_-_Lovely_Rita.lab/1.2/Fri Jul 21 11:47:33 2006//
+/11_-_Good_Morning_Good_Morning.lab/1.1.1.1/Fri Sep 23 09:24:40 2005//
+/12_-_Sgt._Pepper's_Lonely_Hearts_Club_Band_(Reprise).lab/1.1.1.1/Fri Sep 23 09:24:40 2005//
+/13_-_A_Day_In_The_Life.lab/1.4/Fri Jul 21 11:49:09 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/08final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/08final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/01_-_Magical_Mystery_Tour.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,74 @@
+0.0000000 1.1105614 N
+1.1105614 2.6470970 D
+2.6470970 4.1099540 A
+4.1099540 9.7872330 E
+9.7872330 12.7245570 E
+12.7245570 14.1409750 G
+14.1409750 15.5922220 A
+15.5922220 18.4831060 E
+18.4831060 19.9111330 G
+19.9111330 21.3972100 A
+21.3972100 24.2184350 E
+24.2184350 25.6696820 G
+25.6696820 27.1093190 A
+27.1093190 29.9653740 E
+29.9653740 31.4398410 G
+31.4398410 32.8794780 A
+32.8794780 34.3075050 D
+34.3075050 35.7819720 D/b7
+35.7819720 37.2912690 G/3
+37.2912690 38.7192970 G:min(9)/b3
+38.7192970 40.1821540 D/5
+40.1821540 41.6450110 A
+41.6450110 44.4430150 E
+44.4430150 45.8246030 G
+45.8246030 47.2294100 A
+47.2294100 50.0506340 E
+50.0506340 51.4438320 G
+51.4438320 52.8834690 A
+52.8834690 55.7163030 E
+55.7163030 57.2139900 G
+57.2139900 58.6187980 A
+58.6187980 61.4168020 E
+61.4168020 62.9028790 G
+62.9028790 64.3192970 A
+64.3192970 65.8169840 D
+65.8169840 67.2798410 D/b7
+67.2798410 68.7659180 G/3
+68.7659180 70.2287750 G:min(9)/b3
+70.2287750 71.6800220 D/5
+71.6800220 73.0848290 A
+73.0848290 75.8944440 B
+75.8944440 78.7737180 F#:min7
+78.7737180 81.6413830 B
+81.6413830 83.9633780 F#:min7
+83.9633780 84.4742170 G#:(1)
+84.4742170 85.8093650 A
+85.8093650 87.2722220 B
+87.2722220 91.3241040 E
+91.3241040 93.1817000 G
+93.1817000 95.0160770 A
+95.0160770 98.6035600 E
+98.6035600 100.4495460 G
+100.4495460 102.2258730 A
+102.2258730 105.7901360 E
+105.7901360 107.6129020 G
+107.6129020 109.3892290 A
+109.3892290 113.1044210 E
+113.1044210 114.8923580 G
+114.8923580 116.7383440 A
+116.7383440 118.7004300 D
+118.7004300 120.6973460 D/b7
+120.6973460 122.6710430 G/3
+122.6710430 124.7027890 Bb
+124.7027890 126.6880950 D/5
+126.6880950 128.6501810 A
+128.6501810 130.6122670 D
+130.6122670 132.5859630 D/b7
+132.5859630 134.4900000 G/3
+134.4900000 136.3940360 Bb
+136.3940360 138.3445120 D/5
+138.3445120 140.2601580 A
+140.2601580 147.9703317 D
+147.9703317 166.4204130 D:min
+166.4204130 171.9349250 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/02_-_The_Fool_On_The_Hill.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,116 @@
+0.0000000 0.4403951 N
+0.4403951 4.0350340 D:maj6
+4.0350340 7.4831970 D:maj6
+7.4831970 10.8849200 G:maj6/3
+10.8849200 14.2285940 D
+14.2285940 17.6419270 G:maj6/3
+17.6419270 19.3718140 E:min
+19.3718140 21.0623723 A
+21.0623723 22.7473621 D:maj6
+22.7473621 24.4132043 B:min7
+24.4132043 26.0359410 E:min
+26.0359410 27.7890470 A
+27.7890470 28.6448264 D:min
+28.6448264 29.4608840 G:min/5
+29.4608840 31.1095010 D:min
+31.1095010 34.4531740 Bb/3
+34.4531740 36.1250110 C/5
+36.1250110 37.7504080 C
+37.7504080 39.3990240 D:min
+39.3990240 40.9895910 D:min7
+40.9895910 44.4224580 D:maj6
+44.4224580 47.7001580 D:maj6
+47.7001580 50.9857820 G:maj6/3
+50.9857820 54.2946250 D
+54.2946250 57.5802490 G:maj6/3
+57.5802490 59.2288660 E:min
+59.2288660 60.9007020 A
+60.9007020 62.5377090 D:maj6
+62.5377090 64.2559860 B:min7
+64.2559860 65.9278230 E:min
+65.9278230 67.6228790 A
+67.6228790 68.4144148 D:min
+68.4144148 69.2598860 G:min/5
+69.2598860 70.8852830 D:min
+70.8852830 74.2289560 Bb/3
+74.2289560 75.8891830 C/5
+75.8891830 77.5378000 C
+77.5378000 79.1980270 D:min
+79.1980270 80.5922955 D:min7
+80.5922955 83.9929470 D:maj6
+83.9929470 84.7708160 D:maj6
+84.7708160 85.6067340 D:maj6/5
+85.6067340 86.4194330 D:maj6
+86.4194330 87.2669610 D:maj6/5
+87.2669610 88.1028790 G:maj6/5
+88.1028790 88.9387980 G:maj6/2
+88.9387980 89.7398860 G:maj6/5
+89.7398860 90.5641950 G:maj6/2
+90.5641950 91.3768930 D
+91.3768930 92.2360310 D/5
+92.2360310 93.1067800 D
+93.1067800 93.9194780 D/5
+93.9194780 94.7205660 G:maj6/5
+94.7205660 95.5564850 G:maj6/2
+95.5564850 96.4040130 G:maj6/5
+96.4040130 97.1934920 G:maj6/2
+97.1934920 98.8769380 E:min
+98.8769380 100.6300450 A
+100.6300450 102.2206120 D:maj6
+102.2206120 103.8924480 B:min7
+103.8924480 105.5875050 E:min
+105.5875050 107.2361220 A
+107.2361220 108.0691176 D:min
+108.0691176 108.9195690 G:min/5
+108.9195690 110.5914050 D:min
+110.5914050 113.9582990 Bb/3
+113.9582990 115.6301360 C/5
+115.6301360 117.2207020 C
+117.2207020 118.8809290 D:min
+118.8809290 120.4250560 D:min7
+120.4250560 123.7339000 D:maj6
+123.7339000 124.5349880 D:maj6
+124.5349880 125.3825170 D:maj6/5
+125.3825170 126.1952150 D:maj6
+126.1952150 127.0427430 D:maj6/5
+127.0427430 127.8786620 G:maj6/5
+127.8786620 128.6797500 G:maj6/2
+128.6797500 129.5504980 G:maj6/5
+129.5504980 130.3631970 G:maj6/2
+130.3631970 131.2107250 D
+131.2107250 132.0118140 D/5
+132.0118140 132.8012920 D
+132.8012920 133.6604300 D/5
+133.6604300 134.4847390 G:maj6/5
+134.4847390 137.0041040 G:maj6
+137.0041040 138.6527210 E:min
+138.6527210 140.3129470 A
+140.3129470 141.9383440 D:maj6
+141.9383440 143.6334010 B:min7
+143.6334010 145.2936280 E:min
+145.2936280 146.9190240 A
+146.9190240 147.7429680 D:min
+147.7429680 148.6024710 G:min/5
+148.6024710 150.2626980 D:min
+150.2626980 153.5715410 Bb/3
+153.5715410 155.1737180 C/5
+155.1737180 156.7410650 C
+156.7410650 158.3664620 D:min
+158.3664620 159.9802490 D:min7
+159.9802490 163.3239220 D:maj6
+163.3239220 164.1366210 D:maj6
+164.1366210 164.9609290 D:maj6/5
+164.9609290 165.7736280 D:maj6
+165.7736280 166.6792060 D:maj6/5
+166.6792060 167.5035140 G:maj6/5
+167.5035140 168.3278230 G:maj6/2
+168.3278230 169.1173010 G:maj6/5
+169.1173010 169.9532190 G:maj6/2
+169.9532190 170.7775280 D
+170.7775280 171.6366660 D/5
+171.6366660 172.4377550 D
+172.4377550 173.2620630 D/5
+173.2620630 174.0283210 G:maj6/5
+174.0283210 174.9339000 G:maj6/2
+174.9339000 175.7349880 G:maj6/5
+175.7349880 180.1790214 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/03_-_Flying.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+0.0000000 0.4020998 N
+0.4020998 10.8850110 C
+10.8850110 15.9353510 F:7
+15.9353510 21.1482310 C
+21.1482310 23.7140360 G
+23.7140360 26.3146710 F
+26.3146710 28.8991960 C
+28.8991960 31.5275510 G:7
+31.5275510 39.5083410 C
+39.5083410 41.8952600 C:7
+41.8952600 47.0268700 F
+47.0268700 52.1468700 C
+52.1468700 54.7126750 G
+54.7126750 57.2784800 F
+57.2784800 59.8026390 C
+59.8026390 62.4100900 G
+62.4100900 70.0958950 C
+70.0958950 72.6384800 C:7
+72.6384800 77.7817000 F
+77.7817000 82.8784800 C
+82.8784800 85.4675050 G
+85.4675050 88.0913600 F
+88.0913600 98.2054520 C
+98.2054520 110.9392810 A:min
+110.9392810 130.0651910 F#:dim
+130.0651910 136.5076020 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/04_-_Blue_Jay_Way.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+0.0000000 1.6658422 N
+1.6658422 22.2686718 C
+22.2686718 24.2596140 D#:dim7
+24.2596140 28.1721760 C
+28.1721760 30.6451020 D#:dim7
+30.6451020 34.6621540 C
+34.6621540 43.5437860 D#:dim7
+43.5437860 48.6540801 C
+48.6540801 68.5484481 C
+68.5484481 70.5485940 D#:dim7
+70.5485940 74.1825170 C
+74.1825170 76.2723120 D#:dim7
+76.2723120 79.8263911 C
+79.8263911 87.6617000 D#:dim7
+87.6617000 110.9029641 C
+110.9029641 112.7392510 D#:dim7
+112.7392510 116.2222440 C
+116.2222440 118.3004300 D#:dim7
+118.3004300 121.7137640 C
+121.7137640 129.1209290 D#:dim7
+129.1209290 133.7652118 C
+133.7652118 231.9924573 C
+231.9924573 236.6836220 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/05_-_Your_Mother_Should_Know.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,74 @@
+0.0000000 0.6127236 N
+0.6127236 4.8060504 A:min
+4.8060504 6.8208110 A:min
+6.8208110 8.9036392 F:maj7
+8.9036392 10.9375480 A/5
+10.9375480 12.8519270 D:min
+12.8519270 14.8488430 G:7
+14.8488430 15.8240810 C
+15.8240810 16.8109290 C/7
+16.8109290 18.7497950 A:7
+18.7497950 20.7699310 D:7
+20.7699310 22.7784580 G:7
+22.7784580 24.8450340 C
+24.8450340 26.9464390 E
+26.9464390 28.9781850 A:min
+28.9781850 31.0563710 F:maj7
+31.0563710 33.1113370 A
+33.1113370 35.1779130 D:min
+35.1779130 37.2444890 G:7
+37.2444890 38.2197270 C
+38.2197270 39.2181850 C/7
+39.2181850 41.3195910 A:7
+41.3195910 43.3397270 D:7
+43.3397270 45.3714730 G:7
+45.3714730 47.4496590 C
+47.4496590 50.5727430 E
+50.5727430 52.6509290 A:min
+52.6509290 54.7407250 F:maj7
+54.7407250 56.7492510 D:min/b3
+56.7492510 58.7345570 G:9(*3)
+58.7345570 60.8127430 C
+60.8127430 62.8212690 E
+62.8212690 64.8530150 A:min
+64.8530150 66.9079810 F:maj7
+66.9079810 68.9629470 A
+68.9629470 70.9946930 D:min
+70.9946930 72.9916090 G:7
+72.9916090 74.0597270 C
+74.0597270 75.0233560 C/7
+75.0233560 77.0899310 A
+77.0899310 79.0752380 D:7
+79.0752380 81.1185940 G:7
+81.1185940 83.1619500 C
+83.1619500 85.2401360 A
+85.2401360 87.2602720 D:7
+87.2602720 89.2687980 G:7
+89.2687980 91.3469840 C
+91.3469840 94.4584580 E
+94.4584580 96.5598630 A:min
+96.5598630 98.5567800 F:maj7
+98.5567800 100.5072560 D:min/b3
+100.5072560 102.5854420 G:9(*3)
+102.5854420 104.6055780 C
+104.6055780 106.6721540 E
+106.6721540 108.6806800 A:min
+108.6806800 110.7008160 F:maj7
+110.7008160 112.7557820 A/5
+112.7557820 114.7875280 D:min
+114.7875280 116.8424940 G:7
+116.8424940 117.8061220 C
+117.8061220 118.8278000 C/7
+118.8278000 120.8711560 A
+120.8711560 122.8564620 D:7
+122.8564620 124.9346480 G:7
+124.9346480 126.9431740 C
+126.9431740 128.9865300 A
+128.9865300 131.0298860 D:7
+131.0298860 133.0616320 G:7
+133.0616320 135.0933780 C
+135.0933780 137.1715640 A
+137.1715640 139.1684800 D:7
+139.1684800 141.2234460 G:7
+141.2234460 145.2005980 C
+145.2005980 149.6236960 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/06_-_I_Am_The_Walrus.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,122 @@
+0.0000000 0.4595427 N
+0.4595427 4.7332420 B
+4.7332420 6.1496590 B
+6.1496590 7.5776870 A
+7.5776870 8.9592740 G
+8.9592740 10.3873010 F
+10.3873010 13.3014050 E
+13.3014050 16.0297500 E:7
+16.0297500 18.9206340 D
+18.9206340 21.7882990 D:7
+21.7882990 23.2163260 A
+23.2163260 24.6443530 A/b7
+24.6443530 26.0839900 C
+26.0839900 27.5700680 D
+27.5700680 28.9632650 A
+28.9632650 30.4145120 A/b7
+30.4145120 33.3170060 C
+33.3170060 36.1730610 D
+36.1730610 39.0291150 A
+39.0291150 40.4223120 A
+40.4223120 41.8619500 A/b7
+41.8619500 43.3015870 F#:min7
+43.3015870 43.9981850 F
+43.9981850 44.6715640 G
+44.6715640 46.1228110 A
+46.1228110 47.5392290 A/b7
+47.5392290 50.3488430 F
+50.3488430 55.9332420 B
+55.9332420 58.7776870 C
+58.7776870 61.5989110 D
+61.5989110 64.3736960 E
+64.3736960 65.7901130 A
+65.7901130 67.2297500 A/b7
+67.2297500 68.6809970 C
+68.6809970 70.0858040 D
+70.0858040 71.5254420 A
+71.5254420 72.9534690 A/b7
+72.9534690 75.7746930 C
+75.7746930 78.6307480 D
+78.6307480 81.4519720 A
+81.4519720 87.0944210 D:maj(11)
+87.0944210 89.9156460 A
+89.9156460 92.7484800 E
+92.7484800 95.5697050 D
+95.5697050 97.0209520 A
+97.0209520 98.4141490 A/b7
+98.4141490 99.8421760 F#:min7
+99.8421760 100.5271650 F
+100.5271650 101.1657140 G
+101.1657140 102.6053510 A
+102.6053510 103.9637180 A/b7
+103.9637180 106.7965530 F
+106.7965530 112.2764620 B
+112.2764620 115.0976870 C
+115.0976870 117.8608610 D
+117.8608610 120.6124260 E
+120.6124260 123.5729700 N
+123.5729700 124.8268480 B
+124.8268480 126.2432650 A
+126.2432650 127.6364620 G
+127.6364620 128.9832190 F
+128.9832190 131.8508840 E
+131.8508840 133.2324710 B
+133.2324710 134.6604980 A
+134.6604980 136.0072560 G
+136.0072560 137.3772330 F
+137.3772330 138.8052600 E
+138.8052600 140.1868480 F
+140.1868480 145.6783670 B
+145.6783670 148.4415410 C
+148.4415410 151.1118360 D
+151.1118360 153.8285710 E
+153.8285710 156.5336960 D
+156.5336960 157.9501130 A
+157.9501130 159.3549200 A/b7
+159.3549200 160.7365070 C
+160.7365070 162.1761450 D
+162.1761450 163.5461220 A
+163.5461220 164.9044890 A/b7
+164.9044890 167.7257140 C
+167.7257140 170.4656680 D
+170.4656680 173.2404530 A
+173.2404530 174.7033100 A
+174.7033100 176.0152380 A/b7
+176.0152380 177.3619950 F#:min7
+177.3619950 178.0702040 F
+178.0702040 178.6855320 G
+178.6855320 180.0671200 A
+180.0671200 181.4487070 A/b7
+181.4487070 184.1654420 F
+184.1654420 189.5524710 B
+189.5524710 192.3272560 C
+192.3272560 195.0556000 D
+195.0556000 197.7491150 E
+197.7491150 200.3845800 D
+200.3845800 203.1013150 C
+203.1013150 205.7367800 B
+205.7367800 208.4070740 A
+208.4070740 211.0889790 G
+211.0889790 213.7592740 F
+213.7592740 216.4411790 E:7
+216.4411790 219.0882530 D:maj(9)
+219.0882530 221.7933780 C:maj(#11)
+221.7933780 224.5217230 G/3
+224.5217230 227.2500680 A
+227.2500680 229.9087520 G
+229.9087520 232.6719270 F
+232.6719270 235.3538320 E:7
+235.3538320 238.0009070 D:maj(9)
+238.0009070 240.6595910 C:maj(#11)
+240.6595910 243.2950560 G/3
+243.2950560 245.9305210 A
+245.9305210 248.5543760 G
+248.5543760 251.1666210 F
+251.1666210 253.7904760 E:7
+253.7904760 256.5072100 D:maj(9)
+256.5072100 259.2471650 C:maj(#11)
+259.2471650 261.9755100 G/3
+261.9755100 264.6806340 A
+264.6806340 267.4089790 G
+267.4089790 270.1489340 F
+270.1489340 272.7843990 E:7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/07_-_Hello_Goodbye.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,105 @@
+0.0000000 0.5361331 N
+0.5361331 3.0597950 F:maj6
+3.0597950 5.5443310 C
+5.5443310 7.9940360 G
+7.9940360 10.4553510 A:min
+10.4553510 12.9166660 G
+12.9166660 15.3547610 A:min
+15.3547610 17.8160770 G
+17.8160770 19.0815640 G
+19.0815640 20.3238320 D:min7/4
+20.3238320 21.5428790 F:maj/9
+21.5428790 22.8083670 C
+22.8083670 24.0506340 C/7
+24.0506340 25.3161220 A:min
+25.3161220 26.5235600 C/5
+26.5235600 27.7774370 F
+27.7774370 29.0080950 Ab
+29.0080950 30.2503620 C
+30.2503620 31.4694100 C/5
+31.4694100 32.6884580 A:min
+32.6884580 33.9307250 C/5
+33.9307250 35.1613830 F
+35.1613830 36.3688200 Bb
+36.3688200 38.8185260 C
+38.8185260 41.2682310 F:maj6
+41.2682310 43.7295460 C
+43.7295460 46.1792510 G
+46.1792510 48.6057360 A:min
+48.6057360 51.0206120 G
+51.0206120 53.4935370 A:min
+53.4935370 55.8851920 G
+55.8851920 57.0810200 G
+57.0810200 58.3000680 D:min7/4
+58.3000680 59.5539450 F:maj/9
+59.5539450 60.7745179 C
+60.7745179 62.0617000 C/7
+62.0617000 63.2807480 A:min
+63.2807480 64.4881850 C/5
+64.4881850 65.7188430 F
+65.7188430 66.9495010 Ab
+66.9495010 68.1569380 C
+68.1569380 69.3875960 C/7
+69.3875960 70.5950340 A:min
+70.5950340 71.8024710 C/5
+71.8024710 72.9982990 F
+72.9982990 74.2289560 Bb
+74.2289560 76.6902720 C
+76.6902720 79.0354870 F:maj6
+79.0354870 81.4039220 C
+81.4039220 83.7955780 G
+83.7955780 86.2220630 A:min
+86.2220630 88.6369380 G
+88.6369380 91.0634240 A:min
+91.0634240 93.4202490 G
+93.4202490 94.6509070 G
+94.6509070 95.8235140 D:min7/4
+95.8235140 97.0541720 F:maj/9
+97.0541720 98.2848290 C
+98.2848290 99.4922670 C/7
+99.4922670 100.6880950 A:min
+100.6880950 101.9187520 C/5
+101.9187520 103.1261900 F
+103.1261900 104.3336280 Ab
+104.3336280 105.5642850 C
+105.5642850 106.7949430 C/7
+106.7949430 108.0023800 A:min
+108.0023800 109.1982080 C/5
+109.1982080 110.3940360 F
+110.3940360 111.6014730 Bb
+111.6014730 114.0047390 C
+114.0047390 116.4196140 F:maj6
+116.4196140 118.8228790 C
+118.8228790 121.2029250 G
+121.2029250 123.5597500 A:min
+123.5597500 125.9514050 G
+125.9514050 128.3430610 A:min
+128.3430610 130.7231060 G
+130.7231060 131.9653740 G
+131.9653740 133.0683210 D:min7/4
+133.0683210 134.2873690 F:maj/9
+134.2873690 135.4948070 C
+135.4948070 136.7022440 C/7
+136.7022440 137.9096820 A:min
+137.9096820 139.1403400 C/5
+139.1403400 140.3361670 F
+140.3361670 141.5784350 Ab
+141.5784350 142.7626530 C
+142.7626530 143.9933100 C/7
+143.9933100 145.1775280 A:min
+145.1775280 146.4197950 C/5
+146.4197950 147.6040130 F
+147.6040130 148.7998410 Bb
+148.7998410 150.0188880 C
+150.0188880 151.2147160 C/7
+151.2147160 152.4105440 A:min
+152.4105440 153.5947610 C/5
+153.5947610 154.8021990 F
+154.8021990 155.9631970 Ab
+155.9631970 157.2054640 Ab
+157.2054640 158.4129020 Ab/7
+158.4129020 159.6435600 Ab/b7
+159.6435600 160.8393870 F:7
+160.8393870 165.6343080 C
+165.6343080 205.5304586 C
+205.5304586 211.4470704 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/08_-_Strawberry_Fields_Forever.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,109 @@
+0.0000000 0.3600496 N
+0.3600496 1.7478680 F
+1.7478680 3.0365750 A:min/5
+3.0365750 4.4878230 A:dim/b5
+4.4878230 5.1728110 Eb
+5.1728110 5.8578000 A:dim7/b3
+5.8578000 7.2742170 G:min/5
+7.2742170 8.5745350 F/5
+8.5745350 9.2479130 Eb/5
+9.2479130 9.9909520 Bb
+9.9909520 15.1225620 Bb
+15.1225620 20.3006120 F:min
+20.3006120 25.5599310 D:dim
+25.5599310 26.9415190 Eb
+26.9415190 29.6698630 G
+29.6698630 31.8060990 Eb
+31.8060990 34.4183440 Bb
+34.4183440 35.6722220 F
+35.6722220 36.9957590 F:maj7
+36.9957590 38.9346250 F:7
+38.9346250 39.5963940 F#:dim
+39.5963940 40.9083210 G:min
+40.9083210 42.2550790 F
+42.2550790 44.8673240 Eb
+44.8673240 46.1792510 Eb
+46.1792510 47.5143990 F
+47.5143990 48.2226070 Bb
+48.2226070 48.8379360 F/3
+48.8379360 49.5345350 G:min
+49.5345350 50.1963030 F
+50.1963030 51.5430610 Eb
+51.5430610 52.8782080 F
+52.8782080 54.2597950 Eb
+54.2597950 55.5717230 Bb
+55.5717230 60.6220630 Bb
+60.6220630 64.2908160 F:min
+64.2908160 65.5098630 F:min/b7
+65.5098630 70.2931740 D:dim
+70.2931740 71.1523120 Eb
+71.1523120 71.5006120 F
+71.5006120 73.9270970 G
+73.9270970 75.8195230 Eb
+75.8195230 80.8118140 Bb
+80.8118140 82.3095010 F
+82.3095010 83.5401580 A:min/5
+83.5401580 84.7127660 F:7/b7
+84.7127660 85.3629250 Eb
+85.3629250 85.9666430 Eb:dim
+85.9666430 87.3714510 G:min/5
+87.3714510 88.6369380 G:min/b7
+88.6369380 90.0185260 Eb
+90.0185260 90.5525850 Eb/3
+90.5525850 91.1098630 F:(1)
+91.1098630 92.3869610 Eb
+92.3869610 93.6176190 F
+93.6176190 95.0108160 Bb
+95.0108160 95.6609750 Eb/3
+95.6609750 96.2763030 Eb/2
+96.2763030 97.4605210 Eb
+97.4605210 98.7260090 F
+98.7260090 99.9218360 Eb
+99.9218360 101.1757140 Bb
+101.1757140 106.1796140 Bb
+106.1796140 109.7903170 F:min
+109.7903170 110.9629250 F:min/b7
+110.9629250 115.7810650 D:dim
+115.7810650 116.6634240 Eb
+116.6634240 117.0117230 F
+117.0117230 119.3801580 G
+119.3801580 121.3074140 Eb
+121.3074140 126.4506340 Bb
+126.4506340 127.8554420 F
+127.8554420 129.1093190 A:min/5
+129.1093190 130.3980270 A:dim/b3
+130.3980270 131.0133560 Eb
+131.0133560 131.6286840 Eb:dim
+131.6286840 132.9986620 G:min/5
+132.9986620 134.2757590 G:min/b7
+134.2757590 135.5528570 Eb
+135.5528570 136.1333560 G:(1)
+136.1333560 136.7602940 F:(1)
+136.7602940 138.0838320 Eb
+138.0838320 139.3377090 F
+139.3377090 140.5567570 Bb
+140.5567570 141.2533560 G:(1)
+141.2533560 141.8570740 F:(1)
+141.8570740 143.0761220 Eb
+143.0761220 144.3183900 F
+144.3183900 145.5026070 Eb
+145.5026070 146.6868250 Bb
+146.6868250 151.8532650 Bb
+151.8532650 155.2433780 F:min
+155.2433780 156.7758950 F:min7
+156.7758950 161.6056460 G/5
+161.6056460 162.5460540 Eb
+162.5460540 162.8711330 F
+162.8711330 165.3556680 G
+165.3556680 167.3177550 Eb
+167.3177550 168.4903620 Bb
+168.4903620 169.7674600 G:min
+169.7674600 171.7411560 Eb
+171.7411560 173.5058730 Bb
+173.5058730 174.4811110 Eb
+174.4811110 175.5143990 F
+175.5143990 177.9989340 Eb
+177.9989340 180.4370290 Bb
+180.4370290 183.5880896 Bb/b7
+183.5880896 214.1056742 Bb
+214.1056742 250.5061666 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/09_-_Penny_Lane.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,142 @@
+0.0000000 0.4403951 N
+0.4403951 1.6898180 B
+1.6898180 2.2091879 B/7
+2.2091879 2.7463260 B/6
+2.7463260 3.2803850 B/5
+3.2803850 3.8492740 E:maj6
+3.8492740 4.4065530 C#:min7
+4.4065530 4.9406120 F#:sus4
+4.9406120 5.4862810 F#
+5.4862810 6.0203400 B
+6.0203400 6.5776190 B/7
+6.5776190 7.1232870 B/6
+7.1232870 7.6341260 B/5
+7.6341260 9.7471420 B:min
+9.7471420 11.8717680 G#:hdim7
+11.8717680 14.0080040 G:maj7
+14.0080040 15.0529020 F#:sus4
+15.0529020 16.1210200 F#
+16.1210200 17.1891380 F#:sus4
+17.1891380 18.2572560 F#
+18.2572560 18.8029250 B
+18.8029250 19.3485940 B/7
+19.3485940 19.8826530 B/6
+19.8826530 20.4515410 B/5
+20.4515410 20.9972100 E:maj6
+20.9972100 21.5312690 C#:min7
+21.5312690 22.0537180 F#:sus4
+22.0537180 22.6109970 F#
+22.6109970 23.1334460 B
+23.1334460 23.6558950 B/7
+23.6558950 24.1551240 B/6
+24.1551240 24.6891830 B/5
+24.6891830 26.8370290 B:min
+26.8370290 28.8919950 G#:hdim7
+28.8919950 31.0050110 G:maj7
+31.0050110 32.0380906 F#:sus4
+32.0380906 33.1412470 F#
+33.1412470 35.3239220 E
+35.3239220 37.4253280 A
+37.4253280 39.4919040 A/3
+39.4919040 43.6598860 D
+43.6598860 45.7729020 A
+45.7729020 47.8510880 A/3
+47.8510880 49.9408840 D
+49.9408840 52.1003400 F#
+52.1003400 52.6343990 B
+52.6343990 53.1568480 B/7
+53.1568480 53.6909070 B/6
+53.6909070 54.2249650 B/5
+54.2249650 54.7358040 E:maj6
+54.7358040 55.2698630 C#:min7
+55.2698630 55.8039220 F#:sus4
+55.8039220 56.3263710 F#
+56.3263710 56.8488200 B
+56.8488200 57.3712690 B/7
+57.3712690 57.9285480 B/6
+57.9285480 58.4277770 B/5
+58.4277770 60.5872330 B:min
+60.5872330 62.6654190 G#:hdim7
+62.6654190 64.8016550 G:maj7
+64.8016550 65.8349430 F#:sus4
+65.8349430 66.9262810 F#
+66.9262810 67.9711790 F#:sus4
+67.9711790 69.0392970 F#
+69.0392970 69.5965750 B
+69.5965750 70.1190240 B/7
+70.1190240 70.5950340 B/6
+70.5950340 71.1174820 B/5
+71.1174820 71.6515410 E:maj6
+71.6515410 72.1972100 C#:min7
+72.1972100 72.7312690 F#:sus4
+72.7312690 73.2769380 F#
+73.2769380 73.7877770 B
+73.7877770 74.3334460 B/7
+74.3334460 74.8094550 B/6
+74.8094550 75.3319040 B/5
+75.3319040 77.4913600 B:min
+77.4913600 79.5463260 G#:hdim7
+79.5463260 81.6477320 G:maj7
+81.6477320 82.7042400 F#:sus4
+82.7042400 83.8071880 F#
+83.8071880 85.9666430 E
+85.9666430 88.1144890 A
+88.1144890 90.1926750 A/3
+90.1926750 94.3954870 D
+94.3954870 96.4852830 A
+96.4852830 98.5982990 A/3
+98.5982990 100.6880950 D
+100.6880950 102.8707700 F#
+102.8707700 103.4164390 B
+103.4164390 103.9156680 B/7
+103.9156680 104.4381170 B/6
+104.4381170 104.9489560 B/5
+104.9489560 105.4830150 E:maj6
+105.4830150 106.0170740 C#:min7
+106.0170740 106.5975730 F#:sus4
+106.5975730 107.0968020 F#
+107.0968020 107.6192510 B
+107.6192510 108.1417000 B/7
+108.1417000 108.6873690 B/6
+108.6873690 109.1982080 B/5
+109.1982080 111.3344440 B:min
+111.3344440 113.4242400 G#:hdim7
+113.4242400 115.5256460 G:maj7
+115.5256460 116.5821540 F#:sus4
+116.5821540 117.6618820 F#
+117.6618820 118.7416090 F#:sus4
+118.7416090 119.7516780 F#
+119.7516780 120.2973460 B
+120.2973460 120.8430150 B/7
+120.8430150 121.3770740 B/6
+121.3770740 121.8763030 B/5
+121.8763030 122.4103620 E:maj6
+122.4103620 122.9560310 C#:min7
+122.9560310 123.4784800 F#:sus4
+123.4784800 123.9893190 F#
+123.9893190 124.5117680 B
+124.5117680 125.0226070 B/7
+125.0226070 125.5566660 B/6
+125.5566660 126.0791150 B/5
+126.0791150 128.2385710 B:min
+128.2385710 130.2935370 G#:hdim7
+130.2935370 132.4413830 G:maj7
+132.4413830 133.4630610 F#:sus4
+133.4630610 134.5195690 F#
+134.5195690 136.6674140 E
+136.6674140 138.7804300 A
+138.7804300 140.9050560 A/3
+140.9050560 145.0962580 D
+145.0962580 147.2789340 A
+147.2789340 149.3455100 A/3
+149.3455100 151.4996831 D
+151.4996831 153.6179810 F#
+153.6179810 155.6961670 B
+155.6961670 157.8440130 B/3
+157.8440130 161.9887750 E
+161.9887750 164.1830610 B
+164.1830610 166.1799770 B/3
+166.1799770 168.2813830 E
+168.2813830 170.3595690 E/5
+170.3595690 178.4284184 B
+178.4284184 183.3528637 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/10_-_Baby_You're_A_Rich_Man.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,81 @@
+0.0000000 0.4595427 N
+0.4595427 0.7276092 G
+0.7276092 3.0497950 G/5
+3.0497950 5.6272100 C/9
+5.6272100 8.2046250 G
+8.2046250 10.7239900 C/5
+10.7239900 13.2433560 G:7
+13.2433560 15.7162810 C/5
+15.7162810 18.2240360 G:7
+18.2240360 20.6853510 C/5
+20.6853510 23.2511560 G
+23.2511560 25.7356910 C/5
+25.7356910 28.2202260 G:7
+28.2202260 30.7127684 G
+30.7127684 33.1660770 F/9
+33.1660770 34.4315640 F
+34.4315640 35.6622220 G
+35.6622220 38.1351470 C
+38.1351470 40.6661220 G
+40.6661220 43.0577770 F/9
+43.0577770 44.3000450 F
+44.3000450 45.4842630 G
+45.4842630 48.0732870 C
+48.0732870 50.6042630 G
+50.6042630 53.0307480 C
+53.0307480 55.5036730 G
+55.5036730 57.9765980 G
+57.9765980 60.4611330 F/9
+60.4611330 61.7614510 F
+61.7614510 62.9921080 G
+62.9921080 65.3837640 C
+65.3837640 67.8915190 G
+67.8915190 70.2831740 F/9
+70.2831740 71.5951020 F
+71.5951020 72.7909290 G
+72.7909290 75.2754640 C
+75.2754640 77.7251700 G
+77.7251700 80.1980950 C
+80.1980950 82.7174600 G
+82.7174600 85.2136050 C
+85.2136050 86.3978230 Bb
+86.3978230 87.6865300 G/3
+87.6865300 90.1130150 C
+90.1130150 92.5743310 G
+92.5743310 95.0588660 C
+95.0588660 97.5201810 G
+97.5201810 100.0047160 C
+100.0047160 102.4892510 G
+102.4892510 104.9853960 C
+104.9853960 107.4931510 G
+107.4931510 109.9776870 C/5
+109.9776870 112.4157820 G
+112.4157820 117.3268020 G
+117.3268020 118.6039000 F
+118.6039000 119.8345570 G
+119.8345570 122.2494330 C
+122.2494330 127.1604530 G
+127.1604530 128.4839900 F
+128.4839900 129.6798180 G
+129.6798180 132.0946930 C
+132.0946930 134.5443990 G
+134.5443990 137.0289340 C
+137.0289340 139.5250790 G
+139.5250790 141.9631740 C
+141.9631740 143.1822220 Bb
+143.1822220 144.4128790 G/3
+144.4128790 146.8741950 C
+146.8741950 149.3587300 G
+149.3587300 151.8200450 C
+151.8200450 154.2233100 G
+154.2233100 156.7194550 C
+156.7194550 159.1807700 G
+159.1807700 161.5956460 C
+161.5956460 164.0221310 G
+164.0221310 166.3905660 C
+166.3905660 168.7473920 G
+168.7473920 171.1158270 C
+171.1158270 173.4958730 G
+173.4958730 175.8062580 C
+175.8062580 178.7620981 G
+178.7620981 183.6638866 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/11_-_All_You_Need_Is_Love.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,139 @@
+0.0000000 0.4403951 N
+0.4403951 1.0148234 D
+1.0148234 2.3531970 G
+2.3531970 3.5838540 D
+3.5838540 6.1264390 G
+6.1264390 6.7882080 C
+6.7882080 8.7154640 D
+8.7154640 9.9809520 G
+9.9809520 11.2232190 D/3
+11.2232190 12.6048070 E:min
+12.6048070 13.1969160 E:min/b7
+13.1969160 14.4159630 G
+14.4159630 15.6698410 D/3
+15.6698410 16.9817680 E:min
+16.9817680 17.5738770 E:min/b7
+17.5738770 18.7813150 A:min
+18.7813150 19.9771420 G
+19.9771420 21.2078000 D/3
+21.2078000 22.4848970 F#:dim/b7
+22.4848970 23.7039450 D
+23.7039450 24.9346030 D/b7
+24.9346030 26.1536500 G/3
+26.1536500 26.7573690 D
+26.7573690 27.9531970 G
+27.9531970 29.1722440 D/3
+29.1722440 30.4725620 E:min
+30.4725620 31.0646710 E:min/b7
+31.0646710 32.2372780 G
+32.2372780 33.4447160 D/3
+33.4447160 34.6985940 E:min
+34.6985940 35.2674820 E:min/b7
+35.2674820 36.4052600 A:min
+36.4052600 37.6126980 G
+37.6126980 38.8201360 D/3
+38.8201360 40.0624030 D:7/2
+40.0624030 41.2582310 D
+41.2582310 42.4540580 D/b7
+42.4540580 43.6614960 G/3
+43.6614960 44.2768250 D
+44.2768250 45.4610430 G
+45.4610430 46.6452600 D/3
+46.6452600 47.8759180 E:min
+47.8759180 48.4796370 E:min/b7
+48.4796370 49.6290240 G
+49.6290240 50.8364620 D/3
+50.8364620 52.0787300 E:min
+52.0787300 52.6824480 E:min/b7
+52.6824480 53.8666660 A:min
+53.8666660 55.0160540 G
+55.0160540 56.0259104 D/3
+56.0259104 57.3728790 D:7/2
+57.3728790 58.5919270 D
+58.5919270 59.8458040 D/b7
+59.8458040 61.0532420 G
+61.0532420 61.5978652 D
+61.5978652 62.7482990 G
+62.7482990 63.9789560 A
+63.9789560 66.3938320 D
+66.3938320 67.5432190 G
+67.5432190 68.6926070 A
+68.6926070 71.0726530 D
+71.0726530 72.1988200 G
+72.1988200 73.3714280 B
+73.3714280 74.5440360 E:min
+74.5440360 75.7050340 G:maj7/5
+75.7050340 76.8892510 C
+76.8892510 78.0618590 D
+78.0618590 79.2344670 G
+79.2344670 80.4070740 G
+80.4070740 81.6145120 D/3
+81.6145120 82.7406800 E:min
+82.7406800 83.3443990 E:min/b7
+83.3443990 84.4937860 G
+84.4937860 85.6780040 D/3
+85.6780040 86.8854420 E:min
+86.8854420 87.4427210 E:min/b7
+87.4427210 88.5804980 A:min
+88.5804980 89.6950560 G
+89.6950560 90.8908840 D/3
+90.8908840 92.0170520 D:7/2
+92.0170520 93.1664390 D
+93.1664390 94.3158270 D/b7
+94.3158270 95.5116550 G
+95.5116550 96.0573240 D
+96.0573240 97.1834920 G
+97.1834920 98.3444890 A
+98.3444890 100.6780950 D
+100.6780950 101.8274820 G
+101.8274820 103.0000900 A
+103.0000900 105.2988660 D
+105.2988660 106.4482530 G
+106.4482530 107.5860310 B
+107.5860310 108.7238090 E:min
+108.7238090 109.8267570 E:min/b7
+109.8267570 111.0225850 C
+111.0225850 112.1835820 D
+112.1835820 113.3097500 G
+113.3097500 114.4823580 G
+114.4823580 115.6317460 D/3
+115.6317460 116.8507930 E:min
+116.8507930 117.3848520 E:min/b7
+117.3848520 118.5574600 G
+118.5574600 119.7184580 D/3
+119.7184580 120.9258950 E:min
+120.9258950 121.4483440 E:min/b7
+121.4483440 122.5861220 A:min
+122.5861220 123.6542400 G
+123.6542400 124.8268480 D/3
+124.8268480 126.0226750 D:7
+126.0226750 127.1140130 D
+127.1140130 128.3330610 D/b7
+128.3330610 129.4592290 G
+129.4592290 130.0281170 D
+130.0281170 131.1775050 G
+131.1775050 132.3385030 A
+132.3385030 134.6837180 D
+134.6837180 135.8331060 G
+135.8331060 136.9244440 A
+136.9244440 139.2348290 D
+139.2348290 140.3609970 G
+140.3609970 141.4871650 B
+141.4871650 143.7627210 E:min
+143.7627210 144.9121080 C
+144.9121080 146.0614960 D
+146.0614960 147.1992740 G
+147.1992740 148.3486620 G
+148.3486620 149.5212690 A
+149.5212690 151.7852150 D
+151.7852150 152.9578230 G
+152.9578230 154.0259410 A
+154.0259410 156.3363260 D
+156.3363260 157.4741040 G
+157.4741040 158.5770520 B
+158.5770520 159.7496590 E:min
+159.7496590 160.8293870 E:min/b7
+160.8293870 161.9671650 C
+161.9671650 163.1049430 D
+163.1049430 224.7546602 G
+224.7546602 228.2203779 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+/01_-_Magical_Mystery_Tour.lab/1.3/Tue Oct 17 21:56:17 2006//
+/02_-_The_Fool_On_The_Hill.lab/1.2/Tue Oct 17 21:56:17 2006//
+/03_-_Flying.lab/1.3/Tue Oct 17 21:56:17 2006//
+/04_-_Blue_Jay_Way.lab/1.3/Tue Oct 17 21:56:17 2006//
+/05_-_Your_Mother_Should_Know.lab/1.2/Wed Aug  2 00:42:11 2006//
+/06_-_I_Am_The_Walrus.lab/1.2/Wed Aug  2 00:42:11 2006//
+/07_-_Hello_Goodbye.lab/1.2/Wed Aug  2 00:42:11 2006//
+/08_-_Strawberry_Fields_Forever.lab/1.2/Wed Aug  2 00:42:11 2006//
+/09_-_Penny_Lane.lab/1.1/Wed Jun 21 16:35:09 2006//
+/10_-_Baby_You're_A_Rich_Man.lab/1.1/Wed Jun 21 16:35:09 2006//
+/11_-_All_You_Need_Is_Love.lab/1.3/Tue Oct 17 21:56:17 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/09final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/09final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_01_-_Back_in_the_USSR.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,98 @@
+0.000000 10.006758 N
+10.006758 11.787486 E
+11.787486 16.706689 E:7
+16.706689 18.366916 A
+18.366916 20.015532 D
+20.015532 21.722199 C
+21.722199 23.417256 D
+23.417256 25.112312 A
+25.112312 26.760929 D
+26.760929 28.432766 C
+28.432766 30.127823 D
+30.127823 31.799659 A
+31.799659 33.471496 C
+33.471496 36.803560 D
+36.803560 38.730816 A
+38.730816 38.928185 D
+38.928185 39.148775 D#
+39.148775 40.135623 E
+40.135623 41.865510 A
+41.865510 43.514126 D
+43.514126 45.220793 C
+45.220793 46.904240 D
+46.904240 48.622517 A
+48.622517 50.282743 D
+50.282743 52.001020 C
+52.001020 53.696077 D
+53.696077 55.367913 A
+55.367913 57.074580 C
+57.074580 62.891179 D
+62.891179 65.015804 A
+65.015804 65.364104 A/2
+65.364104 65.770453 A/b3
+65.770453 66.200022 A/3
+66.200022 69.520476 D
+69.520476 71.679931 A
+71.679931 72.097891 A/2
+72.097891 72.504240 A/b3
+72.504240 72.922199 A/3
+72.922199 73.781337 D
+73.781337 74.582426 A/3
+74.582426 75.418344 C
+75.418344 76.300702 B
+76.300702 77.949319 E
+77.949319 79.690816 D
+79.690816 81.594852 A
+81.594852 81.850272 D
+81.850272 82.070861 D#
+82.070861 83.034489 E
+83.034489 84.717936 A
+84.717936 86.436213 D
+86.436213 88.108049 C
+88.108049 89.826326 D
+89.826326 91.498991 A
+91.498991 93.170000 D
+93.170000 94.865056 C
+94.865056 96.560113 D
+96.560113 98.231950 A
+98.231950 99.938616 C
+99.938616 101.564013 D
+101.564013 103.282290 D
+103.282290 104.954126 A
+104.954126 105.395306 A
+105.395306 105.824875 A/2
+105.824875 106.208004 A/b3
+106.208004 106.625963 A/3
+106.625963 110.027687 D
+110.027687 112.152312 A
+112.152312 112.593492 A/2
+112.593492 113.023061 A/3b
+113.023061 113.417800 A/3
+113.417800 114.276938 D
+114.276938 115.147687 A/3
+115.147687 115.995215 C
+115.995215 116.831133 B
+116.831133 118.514580 E
+118.514580 120.209637 D
+120.209637 122.125283 A
+122.125283 122.322653 D
+122.322653 122.554852 D#
+122.554852 123.588140 E
+123.588140 125.294807 A
+125.294807 126.978253 D
+126.978253 128.673310 C
+128.673310 130.403197 D
+130.403197 132.075034 A
+132.075034 133.770090 D
+133.770090 135.476757 C
+135.476757 137.218253 D
+137.218253 138.913310 A
+138.913310 140.619977 C
+140.619977 142.315034 D
+142.315034 143.975260 D
+143.975260 145.890907 A
+145.890907 146.146326 D
+146.146326 146.320476 D#
+146.320476 147.307324 E
+147.307324 160.315506 A
+160.315506 163.264238 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_02_-_Dear_Prudence.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,131 @@
+0.0000000 1.7478680 N
+1.7478680 3.3732650 D
+3.3732650 5.0218820 C/9
+5.0218820 6.6124480 G/5
+6.6124480 8.2262350 A/4
+8.2262350 11.5002490 C/9
+11.5002490 13.1488660 D/5
+13.1488660 14.7626530 D/b7
+14.7626530 16.4344890 G:maj7/3
+16.4344890 18.0947160 G:minmaj7/b3
+18.0947160 19.6852830 D/5
+19.6852830 21.3571200 D:7
+21.3571200 23.0289560 G:maj7/3
+23.0289560 24.6543530 G:minmaj7/5
+24.6543530 26.2449200 D/5
+26.2449200 27.8819270 D:7
+27.8819270 29.5256165 G:maj7/3
+29.5256165 31.1327210 G:minmaj7/5
+31.1327210 32.7929470 D/5
+32.7929470 34.4299540 D:7
+34.4299540 36.0901810 G:maj7/3
+36.0901810 37.7620180 G:minmaj7/5
+37.7620180 39.2829250 D/5
+39.2829250 40.8851020 D:7
+40.8851020 42.4060090 G:maj7/3
+42.4060090 44.0778450 G:minmaj7/5
+44.0778450 45.7032420 D/5
+45.7032420 47.3170290 D/b7
+47.3170290 48.9308160 G:maj7/3
+48.9308160 50.5097730 G:minmaj7/b3
+50.5097730 52.1932190 D/5
+52.1932190 53.7837860 D/b7
+53.7837860 55.3975730 C
+55.3975730 56.9881400 G
+56.9881400 58.6831970 D
+58.6831970 60.2853740 D/b7
+60.2853740 61.9339900 G:maj7/3
+61.9339900 63.5477770 G:minmaj7/b3
+63.5477770 65.1499540 D/5
+65.1499540 66.7289110 D/b7
+66.7289110 68.3078680 G:maj7/3
+68.3078680 69.9100450 G:minmaj7/b3
+69.9100450 71.4541720 D/5
+71.4541720 73.0447390 D/b7
+73.0447390 74.6353060 G:maj7/3
+74.6353060 76.1910430 G:minmaj7/b3
+76.1910430 77.7816090 D/5
+77.7816090 79.4186160 D/b7
+79.4186160 81.0091830 G:maj7/3
+81.0091830 82.5649200 G:minmaj7/b3
+82.5649200 84.1903170 D/5
+84.1903170 85.7344440 D/b7
+85.7344440 87.3482310 G:maj7/3
+87.3482310 88.8923580 G:minmaj7/b3
+88.8923580 90.4597050 D
+90.4597050 92.0734920 D/b7
+92.0734920 93.6872780 G:maj7/3
+93.6872780 95.3010650 G:minmaj7/b3
+95.3010650 98.4705890 D
+98.4705890 100.0959860 C
+100.0959860 101.6865530 G
+101.6865530 108.1649200 D
+108.1649200 114.5271880 D
+114.5271880 120.7733560 D
+120.7733560 122.3058730 F
+122.3058730 123.9080490 G#
+123.9080490 125.4637860 G
+125.4637860 127.1240130 D
+127.1240130 128.6565300 D/b7
+128.6565300 130.3283670 G:maj7/3
+130.3283670 131.9305440 G:minmaj7/b3
+131.9305440 133.5443310 D/5
+133.5443310 135.1813370 D/b7
+135.1813370 136.7138540 G:maj7/3
+136.7138540 138.3740810 G:minmaj7/b3
+138.3740810 139.9182080 D/5
+139.9182080 141.5087750 D/b7
+141.5087750 143.1806120 G:maj7/3
+143.1806120 144.7015190 G:minmaj7/b3
+144.7015190 146.2920860 D/5
+146.2920860 147.8942630 D/b7
+147.8942630 149.4500000 G:maj7/3
+149.4500000 151.0637860 G:minmaj7/b3
+151.0637860 152.6427430 D/5
+152.6427430 154.1636500 D/b7
+154.1636500 155.8470970 G:maj7/3
+155.8470970 157.3563940 G:minmaj7/b3
+157.3563940 158.9121310 D
+158.9121310 160.4214280 D/b7
+160.4214280 162.0119950 G:maj7/3
+162.0119950 163.6141720 G:minmaj7/b3
+163.6141720 166.7836960 D
+166.7836960 168.4207020 C
+168.4207020 169.9764390 G
+169.9764390 171.5434487 D
+171.5434487 173.0414730 D/b7
+173.0414730 174.5275510 G:maj7/3
+174.5275510 175.9787980 G:minmaj7/b3
+175.9787980 177.4648750 D
+177.4648750 178.9045120 D/b7
+178.9045120 180.3673690 G:maj7/3
+180.3673690 181.7721760 G:minmaj7/b3
+181.7721760 183.2234240 D
+183.2234240 184.6398410 D/b7
+184.6398410 186.0330380 G:maj7/3
+186.0330380 187.5075050 G:minmaj7/b3
+187.5075050 188.9355320 D
+188.9355320 190.4448290 D/b7
+190.4448290 191.8031970 G:maj7/3
+191.8031970 193.2312240 G:minmaj7/b3
+193.2312240 194.6940810 D
+194.6940810 196.0872780 D/b7
+196.0872780 197.5617460 G:maj7/3
+197.5617460 198.9665530 G:minmaj7/b3
+198.9665530 201.8458270 D
+201.8458270 204.7367120 D/b7
+204.7367120 207.5231060 G:maj7/3
+207.5231060 210.3095010 G:minmaj7/b3
+210.3095010 213.2468250 D
+213.2468250 214.7445120 C
+214.7445120 216.3118590 G
+216.3118590 219.5394330 D
+219.5394330 221.0835600 D
+221.0835600 222.6857360 D:sus4(9)
+222.6857360 224.3343530 D
+224.3343530 226.0526300 C/9
+226.0526300 227.7012470 G/5
+227.7012470 229.4659630 A/4
+229.4659630 233.0647235 C/9
+233.0647235 234.7114180 D
+234.7114180 236.3581126 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_03_-_Glass_Onion.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,69 @@
+0.0000000 1.3812690 N
+1.3812690 3.3433560 A:min
+3.3433560 5.3170520 F:7
+5.3170520 7.3487980 A:min
+7.3487980 9.3573240 F:7
+9.3573240 11.3194100 A:min
+11.3194100 13.3859860 G:min7
+13.3859860 15.4061220 C
+15.4061220 17.4378680 G:min7
+17.4378680 19.1793650 C
+19.1793650 21.1414510 F:7
+21.1414510 23.1151470 D:7
+23.1151470 25.0656230 F:7
+25.0656230 27.0741490 D:7
+27.0741490 29.0478450 F:7
+29.0478450 31.2421310 G
+31.2421310 33.2158270 A:min
+33.2158270 35.2591830 F:7
+35.2591830 37.2444890 A:min
+37.2444890 39.2530150 F:7
+39.2530150 41.2267120 A:min
+41.2267120 43.2352380 G:min7
+43.2352380 45.2553740 C
+45.2553740 47.3103400 G:min7
+47.3103400 49.0518360 C
+49.0518360 51.0835820 F:7
+51.0835820 52.9992290 D:7
+52.9992290 55.0193650 F:7
+55.0193650 56.9930610 D:7
+56.9930610 59.1525170 F:7
+59.1525170 61.1262130 G
+61.1262130 65.0852150 A:min
+65.0852150 68.9977770 F/3
+68.9977770 72.8987300 F#:dim/b3
+72.8987300 76.7880720 A:min7
+76.7880720 78.7617680 F:7
+78.7617680 79.5966197 G
+79.5966197 80.7470740 N
+80.7470740 82.8067418 A:min
+82.8067418 84.7409070 F:7
+84.7409070 86.7971936 A:min
+86.7971936 88.7231290 F:7
+88.7231290 90.7316550 A:min
+90.7316550 92.7517910 G:min7
+92.7517910 94.7719270 C
+94.7719270 96.7804530 G:min7
+96.7804530 98.4522900 C
+98.4522900 100.4956460 F:7
+100.4956460 102.3880720 D:7
+102.3880720 104.3733780 F:7
+104.3733780 106.3819040 D:7
+106.3819040 108.3091600 F:7
+108.3091600 109.0264982 G
+109.0264982 112.4887520 F:7(b9)
+112.4887520 113.2201810 B:dim7/b9
+113.2201810 113.9400000 Bb:dim7/5
+113.9400000 114.7643080 C:dim7
+114.7643080 118.6768700 C:dim7/2
+118.6768700 119.4895690 Bb:dim7/7
+119.4895690 120.3370970 D:dim7
+120.3370970 121.3703850 A:dim7
+121.3703850 125.6196370 F:7(b9)
+125.6196370 126.6297050 B:dim7/b9
+126.6297050 127.6629930 Bb:dim7/5
+127.6629930 128.7195010 C:dim7
+128.7195010 133.6305210 C:dim7/2
+133.6305210 134.6521990 B:dim7/b9
+134.6521990 135.7783670 Bb:dim7/5
+135.7783670 137.9202434 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_04_-_Ob-La-Di,_Ob-La-Da.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,103 @@
+0.0000000 1.3786280 F
+1.3786280 1.6049880 A:min/5
+1.6049880 1.8139680 A:dim/b5
+1.8139680 2.0926070 D:(1)
+2.0926070 10.6375510 Bb
+10.6375510 12.7737860 Bb
+12.7737860 17.0114280 F
+17.0114280 21.3071200 Bb
+21.3071200 23.4085260 Eb
+23.4085260 24.4998630 Bb
+24.4998630 25.5331510 F
+25.5331510 27.6809970 Bb
+27.6809970 29.8056230 Bb
+29.8056230 30.8621310 F
+30.8621310 31.9418590 G:min
+31.9418590 33.0099770 Bb
+33.0099770 34.0432650 F
+34.0432650 36.1562810 Bb
+36.1562810 38.2925170 Bb
+38.2925170 39.3374140 F
+39.3374140 40.4055320 G:min
+40.4055320 41.4388200 Bb
+41.4388200 42.5069380 F
+42.5069380 44.6083440 Bb
+44.6083440 46.7097500 Bb
+46.7097500 50.8545120 F
+50.8545120 55.0689340 Bb
+55.0689340 57.1935600 Eb
+57.1935600 58.2732870 Bb
+58.2732870 59.2833560 F
+59.2833560 61.4195910 Bb
+61.4195910 63.5209970 Bb
+63.5209970 64.5891150 F
+64.5891150 65.6456230 G:min
+65.6456230 66.6905210 Bb
+66.6905210 67.7818590 F
+67.7818590 69.8716550 Bb
+69.8716550 71.9614510 Bb
+71.9614510 73.0411790 F
+73.0411790 74.0976870 G:min
+74.0976870 75.1541950 Bb
+75.1541950 76.1990920 F
+76.1990920 78.3237180 Bb
+78.3237180 82.4800900 Eb
+82.4800900 83.5482080 Bb
+83.5482080 84.5814960 Bb:sus4(9)
+84.5814960 85.6496140 Bb
+85.6496140 86.6945120 Bb:sus2(b7)
+86.6945120 90.9321540 Eb
+90.9321540 93.0335600 Bb/5
+93.0335600 95.1349650 F
+95.1349650 97.2479810 Bb
+97.2479810 101.4972330 F
+101.4972330 105.7232650 Bb
+105.7232650 107.8362810 Eb
+107.8362810 108.9043990 Bb
+108.9043990 109.9609070 F
+109.9609070 112.0971420 Bb
+112.0971420 114.2217680 Bb
+114.2217680 115.2621956 F
+115.2621956 116.3347840 G:min
+116.3347840 117.3912920 Bb
+117.3912920 118.4594100 F
+118.4594100 120.5840360 Bb
+120.5840360 122.7086620 Bb
+122.7086620 123.7767800 F
+123.7767800 124.8100680 G:min
+124.8100680 125.9246250 Bb
+125.9246250 126.9463030 F
+126.9463030 129.0593190 Bb
+129.0593190 133.3317910 Eb
+133.3317910 134.3999090 Bb
+134.3999090 135.4680270 Bb:sus4(9)
+135.4680270 136.5825850 Bb
+136.5825850 137.5810430 Bb:sus2(b7)
+137.5810430 141.7606340 Eb
+141.7606340 143.8620400 Bb/5
+143.8620400 145.9982760 F
+145.9982760 148.1345120 Bb
+148.1345120 152.4534240 F
+152.4534240 156.6678450 Bb
+156.6678450 158.7924710 Eb
+158.7924710 159.8489790 Bb
+159.8489790 160.9054870 F
+160.9054870 163.0301130 Bb
+163.0301130 165.1779590 Bb
+165.1779590 166.2770344 F
+166.2770344 167.3217069 G:min
+167.3217069 168.3823120 Bb
+168.3823120 169.4272100 F
+169.4272100 171.5518360 Bb
+171.5518360 173.6880720 Bb
+173.6880720 174.7561900 F
+174.7561900 175.8243080 G:min
+175.8243080 176.8808160 Bb
+176.8808160 177.9373240 F
+177.9373240 182.1865750 G:min
+182.1865750 182.4303850 F
+182.4303850 182.7206340 F/b7
+182.7206340 182.9760540 F/6
+182.9760540 183.2779130 F/5
+183.2779130 187.2140118 Bb
+187.2140118 188.8027845 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_05_-_Wild_Honey_Pie.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+0.0000000 0.0873864 N
+0.0873864 2.7579360 G:7
+2.7579360 5.4398410 F:7
+5.4398410 6.7517680 E:7
+6.7517680 8.0636960 Eb:7
+8.0636960 9.3756230 D:7
+9.3756230 14.8323120 G:7
+14.8323120 17.4793870 G:7
+17.4793870 20.1845120 F:7
+20.1845120 21.4964390 E:7
+21.4964390 22.7851470 Eb:7
+22.7851470 24.1086840 D:7
+24.1086840 29.4957140 G:7
+29.4957140 32.2472780 G:7
+32.2472780 34.8711330 F:7
+34.8711330 36.1714510 E:7
+36.1714510 37.5182080 Eb:7
+37.5182080 38.8069160 D:7
+38.8069160 41.5933100 G:7
+41.5933100 44.2636050 F:7
+44.2636050 46.9687300 G:7
+46.9687300 49.6390240 F:7
+49.6390240 52.4710986 G:7
+52.4710986 52.8755002 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_06_-The_Continuing_Story_of_Bungalow_Bill.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,156 @@
+0.0000000 0.1148857 N
+0.1148857 8.5015394 E:min(2)
+8.5015394 9.4418140 C
+9.4418140 10.4983210 G
+10.4983210 11.5664390 C
+11.5664390 12.6113370 F:min
+12.6113370 13.6678450 C
+13.6678450 14.6430830 F:min
+14.6430830 15.6995910 G
+15.6995910 16.7444890 A
+16.7444890 17.7777770 E
+17.7777770 18.8110650 A
+18.8110650 19.8907930 D:min
+19.8907930 20.9008610 A
+20.9008610 21.9225390 D:min
+21.9225390 24.0703850 E
+24.0703850 25.7073920 A:min
+25.7073920 27.3560090 C
+27.3560090 29.9468639 F
+29.9468639 30.6532420 G
+30.6532420 32.2205890 A:min
+32.2205890 33.8692060 C
+33.8692060 36.2840810 F
+36.2840810 37.0967800 G
+37.0967800 38.7105660 E
+38.7105660 40.2779130 G
+40.2779130 41.9729700 A:min
+41.9729700 44.9777387 F:min
+44.9777387 46.0117097 N
+46.0117097 46.9884800 C
+46.9884800 48.0449880 G
+48.0449880 49.1014960 C
+49.1014960 50.1463940 F:min
+50.1463940 51.2145120 C
+51.2145120 52.2361900 F:min
+52.2361900 53.2810880 G
+53.2810880 54.2911560 A
+54.2911560 55.3708840 E
+55.3708840 56.3693420 A
+56.3693420 57.4606800 D:min
+57.4606800 58.5636280 A
+58.5636280 59.5272560 D:min
+59.5272560 61.6402720 E
+61.6402720 63.3353280 A:min
+63.3353280 65.0071650 C
+65.0071650 67.4568700 F
+67.4568700 68.2115190 G
+68.2115190 69.8833560 A:min
+69.8833560 71.4623120 C
+71.4623120 73.9468480 F
+73.9468480 74.7479360 G
+74.7479360 76.4546030 E
+76.4546030 77.9987300 G
+77.9987300 79.6589560 A:min
+79.6589560 82.9283041 F:min
+82.9283041 83.8965980 N
+83.8965980 84.9182760 C
+84.9182760 85.9747840 G
+85.9747840 87.0196820 C
+87.0196820 88.0761900 F:min
+88.0761900 89.1326980 C
+89.1326980 90.1659860 F:min
+90.1659860 91.2224940 G
+91.2224940 92.2673920 A
+92.2673920 93.3239000 E
+93.3239000 94.3571880 A
+94.3571880 95.3904760 D:min
+95.3904760 96.4469840 A
+96.4469840 97.5034920 D:min
+97.5034920 98.0375510 E
+98.0375510 98.5716090 E/b7
+98.5716090 99.0940580 E/b6
+99.0940580 99.5932870 E/5
+99.5932870 101.2535140 A:min
+101.2535140 102.9137410 C
+102.9137410 105.5027660 F
+105.5027660 106.2109750 G
+106.2109750 107.9060310 A:min
+107.9060310 109.5430380 C
+109.5430380 111.9927430 F
+111.9927430 112.7473920 G
+112.7473920 114.4540580 E
+114.4540580 116.1026750 G
+116.1026750 117.7164620 A:min
+117.7164620 121.1086408 F:min
+121.1086408 121.6058040 N
+121.6058040 122.5346030 C
+122.5346030 123.5911110 G
+123.5911110 124.6476190 C
+124.6476190 125.6576870 F:min
+125.6576870 126.7606340 C
+126.7606340 127.8055320 F:min
+127.8055320 128.8388200 G
+128.8388200 129.8837180 A
+129.8837180 130.9286160 E
+130.9286160 131.9967340 A
+131.9967340 133.0184120 D:min
+133.0184120 134.0865300 A
+134.0865300 135.0733780 D:min
+135.0733780 136.1414960 E
+136.1414960 137.1631740 C
+137.1631740 138.2080720 G
+138.2080720 139.2761900 C
+139.2761900 140.2862580 F:min
+140.2862580 141.3659860 C
+141.3659860 142.3876640 F:min
+142.3876640 143.4557820 G
+143.4557820 144.4890700 A
+144.4890700 145.5339680 E
+145.5339680 146.5672560 A
+146.5672560 147.6237640 D:min
+147.6237640 148.6222220 A
+148.6222220 149.6903400 D:min
+149.6903400 150.7352380 E
+150.7352380 151.7685260 C
+151.7685260 152.8250340 G
+152.8250340 153.9047610 C
+153.9047610 154.9264390 F:min
+154.9264390 155.9713370 C
+155.9713370 157.0046250 F:min
+157.0046250 158.0959630 G
+158.0959630 159.1176410 A
+159.1176410 160.1973690 E
+160.1973690 161.2538770 A
+161.2538770 162.3103850 D:min
+162.3103850 163.3668930 A
+163.3668930 164.3769610 D:min
+164.3769610 165.5495690 E
+165.5495690 166.4667570 C
+166.4667570 167.4884350 G
+167.4884350 168.5449430 C
+168.5449430 169.5782310 F:min
+169.5782310 170.6231290 C
+170.6231290 171.5051535 F:min
+171.5051535 172.6316550 G
+172.6316550 173.6649430 A
+173.6649430 174.7098410 E
+174.7098410 175.7895690 A
+175.7895690 176.7996370 D:min
+176.7996370 177.8329250 A
+177.8329250 178.8778230 D:min
+178.8778230 180.0272100 E
+180.0272100 181.1069380 C
+181.1069380 182.2679360 G
+182.2679360 183.3360540 C
+183.3360540 184.0558730 F:min
+184.0558730 185.0078910 C
+185.0078910 185.9482990 F:min
+185.9482990 187.8572134 G
+187.8572134 188.8337416 A
+188.8337416 189.6867120 E
+189.6867120 190.6619500 A
+190.6619500 191.4978680 D:min
+191.4978680 192.5195460 A
+192.5195460 193.7037640 D:min
+193.7037640 194.0418919 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_07_-_While_My_Guitar_Gently_Weeps.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,141 @@
+0.000000 2.232828 A:min
+2.232828 4.253764 A:min/b7
+4.253764 6.401609 A:min/6
+6.401609 8.491405 F
+8.491405 10.639251 A:min
+10.639251 12.717437 G
+12.717437 14.818843 D
+14.818843 16.943469 E
+16.943469 19.079705 A:min
+19.079705 21.192721 A:min/b7
+21.192721 23.270907 A:min/6
+23.270907 25.383922 F
+25.383922 27.520158 A:min
+27.520158 29.679614 G
+29.679614 31.862290 D
+31.862290 33.975306 E
+33.975306 36.076712 A:min
+36.076712 38.143287 A:min/b7
+38.143287 40.175034 A:min/6
+40.175034 42.218390 F
+42.218390 44.354625 A:min
+44.354625 46.479251 G
+46.479251 48.534217 C
+48.534217 50.682063 E
+50.682063 52.748639 A
+52.748639 54.873265 C#:min
+54.873265 56.963061 F#:min
+56.963061 59.064467 C#:min
+59.064467 63.336938 B:min
+63.336938 64.428276 E
+64.428276 65.473174 E/2
+65.473174 66.494852 E/3
+66.494852 67.528140 E/4
+67.528140 69.664376 A
+69.664376 71.719342 C#:min
+71.719342 73.878798 F#:min
+73.878798 75.968594 C#:min
+75.968594 80.252675 B:min
+80.252675 81.262743 E
+81.262743 82.330861 E/2
+82.330861 83.364149 E/3
+83.364149 84.409047 E/4
+84.409047 86.522063 A:min
+86.522063 88.565419 A:min/b7
+88.565419 90.666825 A:min/6
+90.666825 92.721791 F
+92.721791 94.823197 A:min
+94.823197 96.959433 G
+96.959433 99.130498 D
+99.130498 101.231904 E
+101.231904 103.263650 A:min
+103.263650 105.353446 A:min/b7
+105.353446 107.466462 A:min/6
+107.466462 109.544648 F
+109.544648 111.611224 A:min
+111.611224 113.666190 G
+113.666190 115.755986 C
+115.755986 117.776122 E
+117.776122 119.831088 A:min
+119.831088 121.886054 A:min/b7
+121.886054 123.952630 A:min/6
+123.952630 126.007596 F
+126.007596 128.050952 A:min
+128.050952 130.071088 G
+130.071088 132.126054 D
+132.126054 134.146190 E
+134.146190 136.212766 A:min
+136.212766 138.290952 A:min/b7
+138.290952 140.369138 A:min/6
+140.369138 142.377664 F
+142.377664 144.479070 A:min
+144.479070 146.557256 G
+146.557256 148.554172 C
+148.554172 150.632358 E
+150.632358 152.722154 A
+152.722154 154.765510 C#:min
+154.765510 156.843696 F#:min
+156.843696 158.968321 C#:min
+158.968321 163.147913 B:min
+163.147913 164.169591 E
+164.169591 165.237709 E/2
+165.237709 166.270997 E/3
+166.270997 167.223015 E/4
+167.223015 169.289591 A
+169.289591 171.379387 C#:min
+171.379387 173.515623 F#:min
+173.515623 175.628639 C#:min
+175.628639 179.808231 B:min
+179.808231 180.864739 E
+180.864739 181.886417 E/2
+181.886417 182.954535 E/3
+182.954535 183.941383 E/4
+183.941383 185.961519 A:min
+185.961519 188.062925 A:min/b7
+188.062925 190.059841 A:min/6
+190.059841 192.149637 F
+192.149637 194.216213 A:min
+194.216213 196.294399 G
+196.294399 198.430634 D
+198.430634 200.497210 E
+200.497210 202.528956 A:min
+202.528956 204.607142 A:min/b7
+204.607142 206.743378 A:min/6
+206.743378 208.798344 F
+208.798344 210.899750 A:min
+210.899750 213.001156 G
+213.001156 215.114172 C
+215.114172 217.180748 E
+217.180748 219.235714 A:min
+219.235714 221.267460 A:min/b7
+221.267460 223.380476 A:min/6
+223.380476 225.400612 F
+225.400612 227.455578 A:min
+227.455578 229.533764 G
+229.533764 231.611950 D
+231.611950 233.608866 E
+233.608866 235.756712 A:min
+235.756712 237.765238 A:min/b7
+237.765238 239.831814 A:min/6
+239.831814 241.898390 F
+241.898390 243.906916 A:min
+243.906916 245.985102 G
+245.985102 248.051678 C
+248.051678 250.083424 E
+250.083424 252.138390 A:min
+252.138390 254.158526 A:min/b7
+254.158526 256.236712 A:min/6
+256.236712 258.326507 F
+258.326507 260.381473 A:min
+260.381473 262.506099 G
+262.506099 264.549455 D
+264.549455 266.557981 E
+266.557981 268.647777 A:min
+268.647777 270.691133 A:min/b7
+270.691133 272.757709 A:min/6
+272.757709 274.754625 F
+274.754625 276.844421 A:min
+276.844421 278.876167 G
+278.876167 280.989183 C
+280.989183 283.166579 E
+283.166579 285.340240 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_08_-_Happiness_is_a_Warm_Gun.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,77 @@
+0.0000000 0.2106237 N
+0.2106237 0.7084616 E:(1)
+0.7084616 2.4909070 A:min7
+2.4909070 4.1859630 A:min6
+4.1859630 5.8926300 E:min(9)
+5.8926300 7.6109070 E:min
+7.6109070 9.2827430 A:min7
+9.2827430 10.9778000 A:min6
+10.9778000 12.6380270 E:min(9)
+12.6380270 14.3563030 E:min
+14.3563030 19.5807930 D:min
+19.5807930 23.0173460 A:min
+23.0173460 26.4539000 D:min
+26.4539000 29.9252830 A:min
+29.9252830 33.4547160 D:min
+33.4547160 36.8680490 A:min
+36.8680490 41.1753510 D:min
+41.1753510 44.6931740 A:min
+44.6931740 53.7837860 A:7
+53.7837860 56.3728110 C:7
+56.3728110 58.9618360 A:min
+58.9618360 67.9943990 A:7
+67.9943990 70.6414730 C:7
+70.6414730 73.1821700 A:min
+73.1821700 74.4031060 A
+74.4031060 76.6670520 C
+76.6670520 77.8048290 A
+77.8048290 80.4286840 G
+80.4286840 81.5664620 A
+81.5664620 83.8282418 C
+83.8282418 84.8869160 A
+84.8869160 87.4875510 G
+87.4875510 88.6137180 A
+88.6137180 90.8776640 C
+90.8776640 91.9573920 A
+91.9573920 94.5115870 G
+94.5115870 96.1950340 C
+96.1950340 97.7739900 A:min
+97.7739900 99.3529470 F
+99.3529470 100.9086840 G
+100.9086840 102.5573010 C
+102.5573010 104.1826980 A:min
+104.1826980 105.8313150 F
+105.8313150 107.4799310 G
+107.4799310 108.7201364 C
+108.7201364 110.0225170 A:min
+110.0225170 111.1951240 F
+111.1951240 112.4954420 G
+112.4954420 113.6796590 C
+113.6796590 114.8870970 A:min
+114.8870970 116.1061450 F
+116.1061450 117.3019720 G
+117.3019720 118.5674600 C
+118.5674600 119.7516780 A:min
+119.7516780 121.0055550 F
+121.0055550 122.2362130 G
+122.2362130 123.9080490 C
+123.9080490 125.6379360 A:min
+125.6379360 127.3097730 F
+127.3097730 128.9583900 G
+128.9583900 130.6534460 C
+130.6534460 132.3020630 A:min
+132.3020630 134.0087300 F
+134.0087300 135.6921760 G
+135.6921760 140.4285805 F:min
+140.4285805 141.5965848 N
+141.5965848 142.1901607 C:(1)
+142.1901607 143.8539900 C
+143.8539900 145.5142170 A:min
+145.5142170 147.2324940 F
+147.2324940 148.9043310 G
+148.9043310 150.6458270 C
+150.6458270 152.3060540 A:min
+152.3060540 154.0243310 F
+154.0243310 155.6729470 G
+155.6729470 160.8399341 C
+160.8399341 163.4248616 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_09_-_Martha_My_Dear.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,89 @@
+0.0000000 0.3446570 N
+0.3446570 2.9770060 Eb
+2.9770060 3.6155550 G:min/5
+3.6155550 4.2657140 G:min
+4.2657140 4.9158730 G:min/b7
+4.9158730 5.5544210 C/3
+5.5544210 6.2394100 C:7/3
+6.2394100 8.9445350 F
+8.9445350 10.2564620 Bb
+10.2564620 11.5451700 Ab:maj9
+11.5451700 12.9499770 Bb:7
+12.9499770 14.1458040 Ab:maj7
+14.1458040 15.4809520 Bb:7
+15.4809520 16.7348290 Ab:maj7
+16.7348290 19.4167340 Bb:7
+19.4167340 22.0638090 Eb
+22.0638090 22.6907480 G:min/5
+22.6907480 23.3176870 G:min
+23.3176870 23.9446250 G:min/b7
+23.9446250 24.6063940 C/3
+24.6063940 25.2681630 C:7/3
+25.2681630 27.9384580 F
+27.9384580 29.2968250 Bb
+29.2968250 30.6087520 Ab:maj9
+30.6087520 31.9322900 Bb:7
+31.9322900 33.1977770 Ab:maj7
+33.1977770 34.5097050 Bb:7
+34.5097050 35.7287520 Ab:maj7
+35.7287520 38.3874370 Bb:7
+38.3874370 41.0809520 D:min7
+41.0809520 43.7976870 G:min7
+43.7976870 49.2311560 F:maj6
+49.2311560 50.5779130 G:min/4
+50.5779130 51.9246710 C
+51.9246710 53.2830380 G:min/4
+53.2830380 53.9680270 C
+53.9680270 54.6414050 A
+54.6414050 57.3813600 D:min
+57.3813600 60.0516550 G:min7
+60.0516550 61.4216320 D:min
+61.4216320 64.1151470 G:9
+64.1151470 65.4619040 D:min
+65.4619040 68.1786390 G:9
+68.1786390 70.8489340 C:7
+70.8489340 73.5540580 Bb:maj7
+73.5540580 76.2475730 D:min
+76.2475730 78.9294780 G:min7
+78.9294780 80.3342850 Eb
+80.3342850 83.0974600 Eb
+83.0974600 83.7824480 G:min/5
+83.7824480 84.4558270 G:min
+84.4558270 85.1408160 G:min/b7
+85.1408160 85.7909750 C/3
+85.7909750 86.4643530 C:7/3
+86.4643530 89.1462580 F
+89.1462580 90.5394550 Bb
+90.5394550 91.8281630 Ab:maj9
+91.8281630 93.2213600 Bb:7
+93.2213600 94.4636280 Ab:maj7
+94.4636280 95.8336050 Bb:7
+95.8336050 97.1107020 Ab:maj7
+97.1107020 99.8506570 Bb:7
+99.8506570 102.5557820 D:min
+102.5557820 105.3305660 G:min7
+105.3305660 110.8336960 F:maj6
+110.8336960 112.2152830 G:min/4
+112.2152830 113.5736500 C
+113.5736500 114.9552380 G:min/4
+114.9552380 115.6170060 C
+115.6170060 116.2903850 A
+116.2903850 119.0651700 D:min
+119.0651700 121.7935140 G:min7
+121.7935140 123.1634920 Eb
+123.1634920 125.8570060 Eb
+125.8570060 126.5536050 G:min/5
+126.5536050 127.2269840 G:min
+127.2269840 127.8887520 G:min/b7
+127.8887520 128.5273010 C/3
+128.5273010 129.2006800 C:7/3
+129.2006800 131.9522440 F
+131.9522440 133.2990020 Bb
+133.2990020 134.6341490 Ab:maj9
+134.6341490 135.9344670 Bb:7
+135.9344670 137.2463940 Ab:maj7
+137.2463940 138.5699310 Bb:7
+138.5699310 139.8238090 Ab:maj7
+139.8238090 142.5405440 Bb:7
+142.5405440 147.8578537 Eb
+147.8578537 148.7220786 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_10_-_I'm_So_Tired.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,52 @@
+0.0000000 0.1723285 N
+0.1723285 1.5157590 E
+1.5157590 3.3153060 A
+3.3153060 5.0684120 G#
+5.0684120 6.8911790 D
+6.8911790 8.7139450 E
+8.7139450 10.4786620 A
+10.4786620 12.2782080 F#:min
+12.2782080 14.0661450 D
+14.0661450 15.8192510 E
+15.8192510 17.5143080 A
+17.5143080 19.2790240 E:aug
+19.2790240 21.0089110 F#:min
+21.0089110 24.5383440 D:min
+24.5383440 26.2566210 A
+26.2566210 28.0909970 G#
+28.0909970 29.7976640 D
+29.7976640 31.6320400 E
+31.6320400 33.3735370 A
+33.3735370 35.1846930 F#:min
+35.1846930 36.8681400 D
+36.8681400 38.6444670 E
+38.6444670 40.3859630 A
+40.3859630 42.0229700 E:aug
+42.0229700 43.6715870 F#:min
+43.6715870 47.0152600 D:min
+47.0152600 53.7142170 A
+53.7142170 60.2390240 E
+60.2390240 63.4433780 D
+63.4433780 67.0773010 A
+67.0773010 68.8187980 A
+68.8187980 70.5254640 G#
+70.5254640 72.2205210 D
+72.2205210 73.9271880 E
+73.9271880 75.6222440 A
+75.6222440 77.3173010 F#:min
+77.3173010 79.0239680 D
+79.0239680 80.7770740 E
+80.7770740 82.4605210 A
+82.4605210 84.1555780 E:aug
+84.1555780 85.7809750 F#:min
+85.7809750 87.4471403 D:min7
+87.4471403 89.1710880 D:min
+89.1710880 95.6958950 A
+95.6958950 102.1742630 E
+102.1742630 105.4250560 D
+105.4250560 108.6294100 A
+108.6294100 111.8221540 D
+111.8221540 115.0032870 A
+115.0032870 118.1379810 D
+118.1379810 122.8127782 A
+122.8127782 123.2723209 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_11_-_Black_Bird.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,130 @@
+0.0000000 0.0778704 N
+0.0778704 0.7627210 G
+0.7627210 1.3664390 A:min7
+1.3664390 1.9817680 G/3
+1.9817680 4.6056230 G
+4.6056230 5.2557820 G
+5.2557820 5.8943310 A:min7
+5.8943310 6.5096590 G/3
+6.5096590 9.1102940 G
+9.1102940 9.7488430 C
+9.7488430 10.4106120 C#:dim
+10.4106120 11.0375510 D
+11.0375510 11.6877090 D#:dim
+11.6877090 12.9764170 E:min
+12.9764170 14.3115640 Eb:aug
+14.3115640 14.9385030 D
+14.9385030 15.5654420 C#:dim
+15.5654420 16.8889790 C
+16.8889790 18.1892970 C:min
+18.1892970 19.4663940 G/3
+19.4663940 20.7667120 A:7
+20.7667120 22.0205890 D:sus4(b7)
+22.0205890 23.2744670 G
+23.2744670 23.9014050 C
+23.9014050 24.5980040 G/3
+24.5980040 25.8518820 A:7
+25.8518820 27.1405890 D:sus4(b7)
+27.1405890 28.4292970 G
+28.4292970 29.0678450 G
+29.0678450 29.7180040 A:min7
+29.7180040 30.3449430 G/3
+30.3449430 32.9339680 G
+32.9339680 33.5841260 C
+33.5841260 34.2110650 C#:dim
+34.2110650 34.8728340 D
+34.8728340 35.4997730 D#:dim
+35.4997730 36.7536500 E:min
+36.7536500 38.0771880 Eb:aug
+38.0771880 38.7273460 D
+38.7273460 39.3658950 C#:dim
+39.3658950 40.6313830 C
+40.6313830 41.9317000 C:min
+41.9317000 43.1971880 G/3
+43.1971880 44.4394550 A:7
+44.4394550 45.6701130 D:sus4(b7)
+45.6701130 46.9588200 G
+46.9588200 47.6205890 F
+47.6205890 48.2591380 C/3
+48.2591380 48.8860770 D:min
+48.8860770 49.5014050 C
+49.5014050 50.7668930 Bb
+50.7668930 52.0556000 C
+52.0556000 52.6941490 F
+52.6941490 53.3443080 C/3
+53.3443080 53.9828570 D:min
+53.9828570 54.5749650 C
+54.5749650 55.8985030 Bb
+55.8985030 57.1407700 A:7
+57.1407700 58.3830380 D:sus4(b7)
+58.3830380 58.9867570 G
+58.9867570 59.5904760 A:min7
+59.5904760 60.1941950 G/3
+60.1941950 62.8064390 G
+62.8064390 63.4798180 C
+63.4798180 64.0835370 C#:dim
+64.0835370 64.7336960 D
+64.7336960 65.3606340 D#:dim
+65.3606340 66.6377320 E:min
+66.6377320 67.9496590 Eb:aug
+67.9496590 68.5765980 D
+68.5765980 69.2383670 C#:dim
+69.2383670 70.5154640 C
+70.5154640 71.7925620 C:min
+71.7925620 73.0696590 G/3
+73.0696590 74.3119270 A:7
+74.3119270 75.5774140 D:sus4(b7)
+75.5774140 76.9009520 G
+76.9009520 77.5278910 F
+77.5278910 78.1548290 C/3
+78.1548290 78.7933780 D:min
+78.7933780 79.3970970 C
+79.3970970 80.6858040 Bb
+80.6858040 81.9629020 C
+81.9629020 82.6478910 F
+82.6478910 83.2632190 C/3
+83.2632190 83.9133780 D:min
+83.9133780 84.5170970 C
+84.5170970 85.7825850 Bb
+85.7825850 87.0480720 A:7
+87.0480720 88.2787300 D:sus4(b7)
+88.2787300 88.9056680 G
+88.9056680 89.5326070 A:min7
+89.5326070 90.1131060 G/3
+90.1131060 101.7463030 G
+101.7463030 102.3500220 G
+102.3500220 102.9653510 A:min7
+102.9653510 103.6503400 G/3
+103.6503400 104.3121080 C
+104.3121080 104.9970970 G/3
+104.9970970 105.6704760 G:dim/b3
+105.6704760 106.9359630 D:sus4(b7)
+106.9359630 107.5629020 G
+107.5629020 108.2014510 A:min7
+108.2014510 108.8283900 G/3
+108.8283900 111.4174140 G
+111.4174140 112.0443530 C
+112.0443530 112.6596820 C#:dim
+112.6596820 113.3214510 D
+113.3214510 113.9483900 D#:dim
+113.9483900 115.1790470 E:min
+115.1790470 116.4793650 Eb:aug
+116.4793650 117.1295230 D
+117.1295230 117.7100220 C#:dim
+117.7100220 118.9871200 C
+118.9871200 120.3106570 C:min
+120.3106570 121.5297050 G/3
+121.5297050 122.8416320 A:7
+122.8416320 124.0722900 D:sus4(b7)
+124.0722900 125.3377770 G
+125.3377770 125.9298860 C
+125.9298860 126.5568250 G/3
+126.5568250 127.8223120 A:7
+127.8223120 129.1226300 D:sus4(b7)
+129.1226300 130.3184580 G
+130.3184580 130.9570060 C
+130.9570060 131.5839450 G/3
+131.5839450 132.9190920 A:7
+132.9190920 134.3239000 D:sus4(b7)
+134.3239000 137.8208733 G
+137.8208733 138.2825178 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_12_-_Piggies.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,93 @@
+0.0000000 0.0168490 N
+0.0168490 1.4227890 Ab
+1.4227890 2.8508160 Eb
+2.8508160 4.1163030 Ab
+4.1163030 5.4746710 Eb
+5.4746710 6.8098180 Ab
+6.8098180 8.1565750 Eb
+8.1565750 9.4917230 Ab
+9.4917230 10.8152600 Eb
+10.8152600 12.1387980 Ab
+12.1387980 13.4507250 Eb
+13.4507250 14.8090920 F:min
+14.8090920 16.1790700 Bb
+16.1790700 17.5374370 F:min
+17.5374370 18.8493650 Bb
+18.8493650 19.5459630 Eb
+19.5459630 20.2193420 F:dim
+20.2193420 20.9043310 F#:dim
+20.9043310 21.6009290 G:dim
+21.6009290 22.9476870 Ab
+22.9476870 24.3292740 Eb
+24.3292740 25.5947610 Ab
+25.5947610 26.9299090 Eb
+26.9299090 28.2766660 Ab
+28.2766660 29.5653740 Eb
+29.5653740 30.9237410 Ab
+30.9237410 32.2472780 Eb
+32.2472780 33.5708160 Ab
+33.5708160 34.8595230 Eb
+34.8595230 36.2295010 F:min
+36.2295010 37.5530380 Bb
+37.5530380 38.8649650 F:min
+38.8649650 40.1768930 Bb
+40.1768930 40.8270520 Eb
+40.8270520 41.4656000 F:dim
+41.4656000 42.1041490 F#:dim
+42.1041490 42.8007480 G:dim
+42.8007480 44.1126750 Ab
+44.1126750 45.4594330 Eb
+45.4594330 46.6900900 Ab
+46.6900900 48.0020180 C
+48.0020180 49.3255550 Bb:min
+49.3255550 50.6142630 C
+50.6142630 51.9261900 Db
+51.9261900 53.1568480 Ab
+53.1568480 58.3000680 Eb
+58.3000680 59.5655550 Bb:min
+59.5655550 60.8658730 C
+60.8658730 62.1429700 Db
+62.1429700 65.9742630 Eb
+65.9742630 67.2281400 Ab
+67.2281400 68.4820180 Eb
+68.4820180 69.7475050 Ab
+69.7475050 71.0710430 Eb
+71.0710430 72.3597500 Ab
+72.3597500 73.6484580 Eb
+73.6484580 74.9255550 F:min
+74.9255550 76.2607020 Bb
+76.2607020 77.5145800 F:min
+77.5145800 78.8032870 Bb
+78.8032870 79.4302260 Eb
+79.4302260 80.0687750 F:dim
+80.0687750 80.6957140 F#:dim
+80.6957140 81.3807020 G:dim
+81.3807020 82.6345800 Ab
+82.6345800 83.9232870 Eb
+83.9232870 85.1887750 Ab
+85.1887750 86.5007020 Eb
+86.5007020 87.7778000 Ab
+87.7778000 89.0316780 Eb
+89.0316780 90.3203850 Ab
+90.3203850 91.6207020 Eb
+91.6207020 92.8745800 Ab
+92.8745800 94.1632870 Eb
+94.1632870 95.4287750 F:min
+95.4287750 96.7407020 Bb
+96.7407020 98.0061900 F:min
+98.0061900 99.3065070 Bb
+99.3065070 99.9682760 Eb
+99.9682760 100.5719950 F:dim
+100.5719950 101.2685940 F#:dim
+101.2685940 101.9071420 G:dim
+101.9071420 103.1958500 Ab
+103.1958500 104.4845570 Eb
+104.4845570 105.7848750 Ab:min
+105.7848750 107.1316320 Eb
+107.1316320 108.3855100 Ab:min
+108.3855100 109.6393870 Eb
+109.6393870 110.9397050 Bb
+110.9397050 114.3180365 Eb
+114.3180365 117.8279727 A
+117.8279727 121.0829974 E
+121.0829974 124.2399792 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_13_-_Rocky_Raccoon.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,95 @@
+0.0000000 6.3971200 A:min7
+6.3971200 9.4157140 A:min7
+9.4157140 10.8553510 D:sus4
+10.8553510 12.3182080 D
+12.3182080 15.3832420 G:7
+15.3832420 16.8460990 C
+16.8460990 18.3553960 C/7
+18.3553960 21.4204300 A:min7
+21.4204300 22.9529470 D:sus4
+22.9529470 24.4390240 D
+24.4390240 27.4576190 G:7
+27.4576190 28.9901360 C
+28.9901360 30.4878230 C/7
+30.4878230 33.5876870 A:min7
+33.5876870 35.0853740 D:sus4
+35.0853740 36.5482310 D
+36.5482310 39.6248750 G:7
+39.6248750 41.1690020 C
+41.1690020 42.6782990 C/7
+42.6782990 45.7201130 A:min7
+45.7201130 47.2990700 D:sus4
+47.2990700 48.7619270 D
+48.7619270 51.8037410 G:7
+51.8037410 53.3826980 C
+53.3826980 54.8687750 C/7
+54.8687750 57.8873690 A:min7
+57.8873690 59.4314960 D:sus4
+59.4314960 60.9524030 D
+60.9524030 63.9709970 G:7
+63.9709970 65.4802940 C
+65.4802940 67.0244210 C/7
+67.0244210 70.0546250 A:min7
+70.0546250 71.5523120 D:sus4
+71.5523120 73.0964390 D
+73.0964390 76.1730830 G:7
+76.1730830 77.7172100 C
+77.7172100 79.2497270 C/7
+79.2497270 82.3844210 A:min7
+82.3844210 83.8821080 D:sus4
+83.8821080 85.4146250 D
+85.4146250 88.4912690 G:7
+88.4912690 90.0237860 C
+90.0237860 91.5563030 C/7
+91.5563030 94.5748970 A:min7
+94.5748970 96.0958040 D:sus4
+96.0958040 97.6631510 D
+97.6631510 100.5888660 G:7
+100.5888660 102.1329930 C
+102.1329930 103.6771200 C/7
+103.6771200 106.6841040 A:min7
+106.6841040 108.1701810 D:sus4
+108.1701810 109.7259180 D
+109.7259180 112.7445120 G:7
+112.7445120 114.2421990 C
+114.2421990 115.7282760 C/7
+115.7282760 118.5843310 A:min7
+118.5843310 121.5448750 D:7
+121.5448750 124.3660990 G:7
+124.3660990 127.2802040 C
+127.2802040 130.1362580 A:min7
+130.1362580 132.9923120 D:7
+132.9923120 135.8019270 G:7
+135.8019270 138.6812010 C
+138.6812010 141.6997950 A:min7
+141.6997950 144.6951700 D
+144.6951700 147.7253740 G:7
+147.7253740 149.2230610 C
+149.2230610 150.6975280 C/7
+150.6975280 153.6812920 A:min7
+153.6812920 155.1789790 D:sus4
+155.1789790 156.6070060 D
+156.6070060 159.4746710 G:7
+159.4746710 160.9607480 C
+160.9607480 162.4352150 C/7
+162.4352150 165.4073690 A:min7
+165.4073690 166.9166660 D:sus4
+166.9166660 168.3911330 D
+168.3911330 171.3865070 G:7
+171.3865070 172.8958040 C
+172.8958040 174.3702720 C/7
+174.3702720 177.2843760 A:min7
+177.2843760 178.7704530 D:sus4
+178.7704530 180.2100900 D
+180.2100900 183.2286840 G:7
+183.2286840 184.7379810 C
+184.7379810 186.1195690 C/7
+186.1195690 188.9872330 A:min7
+188.9872330 191.8084580 D:7
+191.8084580 194.6412920 G
+194.6412920 196.0577090 C
+196.0577090 197.4973460 C/7
+197.4973460 200.2953510 A:min7
+200.2953510 203.1281850 D:7
+203.1281850 205.9378000 G:7
+205.9378000 212.7782599 C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_14_-_Don't_Pass_Me_By.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,42 @@
+0.0000000 9.8610198 N
+9.8610198 11.2480490 C
+11.2480490 22.5213370 C
+22.5213370 28.1405660 F
+28.1405660 33.7249650 G
+33.7249650 37.8929470 F
+37.8929470 43.6282760 C
+43.6282760 49.1314050 C
+49.1314050 54.7158040 F
+54.7158040 60.2769840 G
+60.2769840 64.5146250 F
+64.5146250 70.2035140 C
+70.2035140 75.8807930 C
+75.8807930 81.5580720 F
+81.5580720 87.2469610 C
+87.2469610 92.9706800 G
+92.9706800 98.6015190 F
+98.6015190 104.3020180 C
+104.3020180 109.9328570 C
+109.9328570 115.5056460 F
+115.5056460 121.1016550 G
+121.1016550 125.3509070 F
+125.3509070 130.9701360 C
+130.9701360 136.6125850 C
+136.6125850 142.2434240 F
+142.2434240 147.9090920 C
+147.9090920 153.5283210 G
+153.5283210 159.1359410 F
+159.1359410 164.8016090 C
+164.8016090 170.3511790 C/5
+170.3511790 175.9123580 C
+175.9123580 181.6360770 C
+181.6360770 187.4062350 F
+187.4062350 194.5695910 C
+194.5695910 200.2584800 G
+200.2584800 205.9473690 F
+205.9473690 211.7059180 C
+211.7059180 214.5851920 F
+214.5851920 217.4876870 G
+217.4876870 218.2307250 C:sus4
+218.2307250 218.9853740 C
+218.9853740 230.3649103 C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_15_-_Why_Don't_We_Do_It_In_The_Road.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,21 @@
+0.0000000 10.2056768 N
+10.2056768 18.0035370 D
+18.0035370 20.6157820 D:7
+20.6157820 25.7009520 G
+25.7009520 30.7977320 D:7
+30.7977320 33.3403170 A
+33.3403170 35.9409520 G
+35.9409520 40.9796820 D:7
+40.9796820 51.3473920 D:7
+51.3473920 56.3745120 G
+56.3745120 61.4248520 D:7
+61.4248520 64.0138770 A
+64.0138770 66.5216320 G
+66.5216320 71.6068020 D:7
+71.6068020 81.7539220 D:7
+81.7539220 86.9319720 G
+86.9319720 91.9823120 D:7
+91.9823120 94.5248970 A
+94.5248970 97.0790920 G
+97.0790920 99.2803641 D:7
+99.2803641 101.3866013 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_16_-_I_Will.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,83 @@
+0.0000000 0.4978379 N
+0.4978379 0.7850521 E:(1)
+0.7850521 2.2506570 F
+2.2506570 3.4464850 D:min
+3.4464850 4.6190920 G:min7
+4.6190920 5.8033100 C
+5.8033100 6.9526980 F
+6.9526980 8.1485260 D:min
+8.1485260 9.2979130 A:min
+9.2979130 10.4705210 F:7
+10.4705210 11.6315190 Bb
+11.6315190 12.7809070 C
+12.7809070 13.9767340 D:min
+13.9767340 15.1725620 F
+15.1725620 16.3451700 Bb
+16.3451700 17.4597270 C
+17.4597270 18.6787750 F
+18.6787750 19.8629930 D:min
+19.8629930 21.0239900 G:min7
+21.0239900 22.1733780 C
+22.1733780 23.3575960 F
+23.3575960 24.4953740 D:min
+24.4953740 25.6795910 G:min7
+25.6795910 26.8638090 C
+26.8638090 27.9667570 F
+27.9667570 29.1625850 D:min
+29.1625850 30.3468020 A:min
+30.3468020 31.4497500 F:7
+31.4497500 32.6455780 Bb
+32.6455780 33.7485260 C
+33.7485260 34.9211330 D:min
+34.9211330 36.1285710 F
+36.1285710 37.2663490 Bb
+37.2663490 38.4389560 C
+38.4389560 39.6115640 F
+39.6115640 40.7841720 F:7
+40.7841720 41.9451700 Bb
+41.9451700 43.1409970 A:min
+43.1409970 45.4746030 D:min
+45.4746030 46.6239900 G:min
+46.6239900 47.7617680 C
+47.7617680 48.9459860 F
+48.9459860 50.1069840 F:7
+50.1069840 51.2563710 Bb
+51.2563710 52.4173690 A:min
+52.4173690 54.7393650 D:min
+54.7393650 57.0497500 G
+57.0497500 59.3717460 C
+59.3717460 60.4979130 F
+60.4979130 61.6705210 D:min
+61.6705210 62.8199090 G:min7
+62.8199090 63.9692970 C
+63.9692970 65.1419040 F
+65.1419040 66.2912920 D:min
+66.2912920 67.4522900 A:min
+67.4522900 68.6132870 F:7
+68.6132870 69.7394550 Bb
+69.7394550 70.9236730 C
+70.9236730 71.4925620 D:min
+71.4925620 72.1078910 Bb:min/b3
+72.1078910 73.2688880 F/5
+73.2688880 74.4298860 Bb
+74.4298860 75.5560540 C
+75.5560540 76.1713830 D:min
+76.1713830 76.7634920 Bb:min/b3
+76.7634920 77.9244890 F/5
+77.9244890 79.0622670 Bb
+79.0622670 80.2116550 C
+80.2116550 80.8153740 D:min
+80.8153740 81.4423120 Bb:min/b3
+81.4423120 81.9995910 F/5
+81.9995910 82.5568700 B:min7
+82.5568700 83.7178680 G:min
+83.7178680 84.8672560 C
+84.8672560 89.5344670 Db
+89.5344670 94.0623580 F
+94.0623580 95.1885260 Bb
+95.1885260 96.3611330 A:min
+96.3611330 98.6715190 D:min
+98.6715190 99.7976870 G:min
+99.7976870 100.9819040 C
+100.9819040 103.7151670 F
+103.7151670 106.0320280 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CD1_-_17_-_Julia.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,86 @@
+0.0000000 0.4212474 N
+0.4212474 2.2470970 D
+2.2470970 4.0466430 B:min7
+4.0466430 7.5992970 F#:min
+7.5992970 9.3291830 D
+9.3291830 11.0474600 B:min7
+11.0474600 12.8702260 F#:min
+12.8702260 14.6001130 A
+14.6001130 16.4693190 D
+16.4693190 18.1875960 B:min7
+18.1875960 20.0335820 A:min7
+20.0335820 21.7402490 A:min9
+21.7402490 25.3625620 B
+25.3625620 27.1513127 G:9
+27.1513127 28.9384350 G:min7
+28.9384350 30.7147610 D
+30.7147610 32.4214280 B:min7
+32.4214280 34.2093650 F#:min
+34.2093650 35.9973010 A
+35.9973010 37.8084580 D
+37.8084580 39.6080040 B:min7
+39.6080040 41.4191600 A:min7
+41.4191600 43.2070970 A:min9
+43.2070970 46.7945800 B
+46.7945800 48.5709070 G:9
+48.5709070 50.3936730 G:min7
+50.3936730 52.1583900 D
+52.1583900 53.8882760 B:min7
+53.8882760 55.6413830 F#:min
+55.6413830 57.4641490 A
+57.4641490 59.2753060 D
+59.2753060 61.0051920 D
+61.0051920 64.5346250 C#:min
+64.5346250 68.1453280 D
+68.1453280 71.7328110 B:min7
+71.7328110 73.4885318 F#:min7
+73.4885318 75.2738540 F#:min6
+75.2738540 77.0269610 D/3
+77.0269610 78.7568480 F#:min
+78.7568480 80.5796140 D
+80.5796140 82.4023800 B:min7
+82.4023800 84.1154560 A:min7
+84.1154560 85.9898630 A:min9
+85.9898630 89.5773460 B
+89.5773460 91.3768930 G:7
+91.3768930 93.0951700 G:min7
+93.0951700 94.9063260 D
+94.9063260 96.6246030 B:min7
+96.6246030 98.4009290 F#:min
+98.4009290 100.2585260 A
+100.2585260 102.0348520 D
+102.0348520 103.8111790 D
+103.8111790 105.5178450 D
+105.5178450 107.3057820 B:min7
+107.3057820 110.8932650 F#:min
+110.8932650 112.6115410 D
+112.6115410 114.4459180 B:min7
+114.4459180 116.3151240 F#:min
+116.3151240 118.0566210 A
+118.0566210 119.8213370 D
+119.8213370 121.6092740 B:min7
+121.6092740 123.4088200 A:min7
+123.4088200 125.2199770 A:min9
+125.2199770 128.7145800 B
+128.7145800 130.5721760 G:7
+130.5721760 132.3485030 G:min7
+132.3485030 134.1248290 D
+134.1248290 135.9288919 B:min7
+135.9288919 137.7471420 F#:min
+137.7471420 139.5234690 A
+139.5234690 141.3230150 D
+141.3230150 143.1457820 B:min7
+143.1457820 144.9453280 A:min7
+144.9453280 146.6984350 A:min9
+146.6984350 150.2975280 B
+150.2975280 152.0854640 G:9
+152.0854640 153.8850110 G:min7
+153.8850110 155.6497270 D
+155.6497270 157.4260540 B:min7
+157.4260540 159.2023800 F#:min
+159.2023800 160.9554870 D
+160.9554870 162.7318140 F#:min
+162.7318140 164.4849200 D
+164.4849200 166.1821176 F#:min
+166.1821176 167.9446930 A
+167.9446930 173.4773574 D:maj7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+/CD1_-_01_-_Back_in_the_USSR.lab/1.2/Tue Oct 17 21:57:01 2006//
+/CD1_-_02_-_Dear_Prudence.lab/1.2/Tue Oct 17 21:57:01 2006//
+/CD1_-_03_-_Glass_Onion.lab/1.2/Tue Oct 17 21:57:01 2006//
+/CD1_-_04_-_Ob-La-Di,_Ob-La-Da.lab/1.2/Wed Aug  2 00:42:50 2006//
+/CD1_-_05_-_Wild_Honey_Pie.lab/1.1/Mon Jun 26 18:07:15 2006//
+/CD1_-_06_-The_Continuing_Story_of_Bungalow_Bill.lab/1.2/Wed Aug  2 00:42:50 2006//
+/CD1_-_07_-_While_My_Guitar_Gently_Weeps.lab/1.2/Wed Aug  2 00:42:50 2006//
+/CD1_-_08_-_Happiness_is_a_Warm_Gun.lab/1.1/Mon Jun 26 18:07:15 2006//
+/CD1_-_09_-_Martha_My_Dear.lab/1.2/Wed Aug  2 00:42:50 2006//
+/CD1_-_10_-_I'm_So_Tired.lab/1.1/Mon Jun 26 18:07:15 2006//
+/CD1_-_11_-_Black_Bird.lab/1.1/Mon Jun 26 18:07:15 2006//
+/CD1_-_12_-_Piggies.lab/1.1/Mon Jun 26 18:07:15 2006//
+/CD1_-_13_-_Rocky_Raccoon.lab/1.1/Mon Jun 26 18:07:15 2006//
+/CD1_-_14_-_Don't_Pass_Me_By.lab/1.1/Mon Jun 26 18:07:15 2006//
+/CD1_-_15_-_Why_Don't_We_Do_It_In_The_Road.lab/1.1/Mon Jun 26 18:07:15 2006//
+/CD1_-_16_-_I_Will.lab/1.2/Wed Aug  2 00:42:50 2006//
+/CD1_-_17_-_Julia.lab/1.1/Mon Jun 26 18:07:15 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/10CD1final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD1final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_01_-_Birthday.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,55 @@
+0.0000000 1.8343990 N
+1.8343990 8.5681850 A:7
+8.5681850 11.9931290 D:7
+11.9931290 15.4412920 A:7
+15.4412920 18.8894550 E:7
+18.8894550 22.3260090 A:7
+22.3260090 29.1758950 A:7
+29.1758950 32.6240580 D:7
+32.6240580 36.0490020 A:7
+36.0490020 39.5319950 E:7
+39.5319950 43.3693394 A:7
+43.3693394 56.6683210 N
+56.6683210 70.5190240 E
+70.5190240 72.2721310 C
+72.2721310 74.0252380 G:7
+74.0252380 75.7202940 C
+75.7202940 77.5198410 G:7
+77.5198410 79.2497270 C
+79.2497270 81.0144440 G:7
+81.0144440 82.7327210 C
+82.7327210 83.1772230 G:7
+83.1772230 83.6266890 G:7/b2
+83.6266890 84.0580132 G:7/2
+84.0580132 84.4858270 G:7/b3
+84.4858270 86.2969840 E/5
+86.2969840 87.9572100 E
+87.9572100 94.9115870 A:7
+94.9115870 98.3945800 D:7
+98.3945800 101.8659630 A:7
+101.8659630 105.3025170 E:7
+105.3025170 108.7274600 A:7
+108.7274600 111.3280950 A
+111.3280950 112.2568930 G:(1)
+112.2568930 114.8110880 A
+114.8110880 115.6586160 G:(1)
+115.6586160 117.3536730 C
+117.3536730 119.0487300 G:7
+119.0487300 120.8018360 C
+120.8018360 122.5549430 G:7
+122.5549430 124.2732190 C
+124.2732190 126.0147160 G:7
+126.0147160 127.7678230 C
+127.7678230 128.1932570 C/5
+128.1932570 128.6145044 G:7/b2
+128.6145044 129.0166042 G:7/2
+129.0166042 129.4628790 G:7/b3
+129.4628790 131.1695460 E/5
+131.1695460 132.8529930 E
+132.8529930 139.8189790 A:7
+139.8189790 143.3368020 D:7
+143.3368020 146.7617460 A:7
+146.7617460 150.1750790 E:7
+150.1750790 155.0956507 A:7
+155.0956507 162.6781047 A
+162.6781047 162.8887284 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_02_-_Yer_Blues.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,84 @@
+0.0000000 3.4365750 N
+3.4365750 12.6897270 E
+12.6897270 17.2756680 A
+17.2756680 22.0357590 E
+22.0357590 24.3577550 G
+24.3577550 27.6782080 B
+27.6782080 28.3193170 E
+28.3193170 28.8972560 E/3
+28.8972560 30.0350340 A
+30.0350340 31.1728110 E/5
+31.1728110 32.3221990 B
+32.3221990 41.7611110 E
+41.7611110 46.4283210 A
+46.4283210 51.2000220 E
+51.2000220 53.5800680 G
+53.5800680 56.9237410 B
+56.9237410 57.6900000 E
+57.6900000 58.1311790 E/3
+58.1311790 59.3270060 A
+59.3270060 60.5112240 E/5
+60.5112240 61.6838320 B
+61.6838320 63.4743311 E
+63.4743311 64.1103170 B:7
+64.1103170 65.9563030 E
+65.9563030 66.5251920 B:7
+66.5251920 70.9227519 E
+70.9227519 75.7551240 A
+75.7551240 80.5384350 E
+80.5384350 82.9068700 G
+82.9068700 86.1924940 B
+86.1924940 87.0051920 E
+87.0051920 87.4579810 E/3
+87.4579810 88.6189790 A
+88.6189790 89.7915870 E/5
+89.7915870 90.9177550 B
+90.9177550 92.8084715 E
+92.8084715 93.3326300 B:7
+93.3326300 95.1902260 E
+95.1902260 95.7591150 B:7
+95.7591150 100.5308160 E
+100.5308160 105.1051470 A
+105.1051470 109.8071880 E
+109.8071880 112.1640130 G
+112.1640130 115.3915870 B
+115.3915870 116.1578450 E
+116.1578450 116.5758040 E/3
+116.5758040 117.7600220 A
+117.7600220 118.8978000 E/5
+118.8978000 120.1052380 B
+120.1052380 121.9976640 E
+121.9976640 122.5665530 B:7
+122.5665530 124.3893190 E
+124.3893190 125.0046480 B:7
+125.0046480 129.7763490 E
+129.7763490 134.2694100 A
+134.2694100 138.8553510 E
+138.8553510 141.1309070 G
+141.1309070 143.4296820 B
+143.4296820 145.6936280 E
+145.6936280 147.9459630 B
+147.9459630 156.7347160 E
+156.7347160 161.1581170 A
+161.1581170 165.5582990 E
+165.5582990 167.7641950 G
+167.7641950 170.0165300 B
+170.0165300 172.2572560 E
+172.2572560 174.4399310 B
+174.4399310 183.3563940 E
+183.3563940 187.7449650 A
+187.7449650 192.2264170 E
+192.2264170 194.4671420 G
+194.4671420 196.7775280 B
+196.7775280 207.3774370 E
+207.3774370 212.0794780 A
+212.0794780 216.8047390 E
+216.8047390 219.1267340 G
+219.1267340 222.3995040 B
+222.3995040 223.1079657 E
+223.1079657 223.5385260 E/3
+223.5385260 224.7227430 A
+224.7227430 225.8953510 E/5
+225.8953510 226.9866890 B
+226.9866890 238.8090068 E
+238.8090068 241.0910514 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_03_-_Mother_Nature's_Son.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,121 @@
+0.0000000 0.3638046 N
+0.3638046 2.1636801 B:min
+2.1636801 4.0018507 D/5
+4.0018507 5.9357595 G#:hdim7
+5.9357595 8.4249489 E:9
+8.4249489 9.8284120 D
+9.8284120 11.2796590 D:sus4
+11.2796590 12.7076870 D:maj(9)
+12.7076870 14.1124940 D
+14.1124940 19.7085030 D
+19.7085030 21.1597500 D
+21.1597500 24.0622440 G/5
+24.0622440 25.5018820 D
+25.5018820 26.8950790 B:min
+26.8950790 28.3811560 D/5
+28.3811560 29.7859630 G#:hdim7
+29.7859630 31.2372100 E:9
+31.2372100 31.8989790 A
+31.8989790 32.6304080 D/5
+32.6304080 33.3386160 A
+33.3386160 34.0352150 D/5
+34.0352150 34.7434240 A
+34.7434240 35.4632420 D/5
+35.4632420 36.2062810 A
+36.2062810 36.9144890 D/5
+36.9144890 38.3309070 D
+38.3309070 39.7589340 F/6
+39.7589340 41.1173010 G/5
+41.1173010 42.5801580 D
+42.5801580 43.9385260 D
+43.9385260 45.3781630 F/6
+45.3781630 46.7481400 G/5
+46.7481400 48.1413370 D
+48.1413370 49.6158040 D
+49.6158040 52.4370290 G/5
+52.4370290 53.8186160 D
+53.8186160 55.2466430 B:min
+55.2466430 56.6398410 D/5
+56.6398410 58.0562580 G#:hdim7
+58.0562580 59.4726750 E:9
+59.4726750 60.1808840 A
+60.1808840 60.9007020 D/5
+60.9007020 61.6089110 A
+61.6089110 62.3171200 D/5
+62.3171200 63.0717680 A
+63.0717680 63.7335370 D/5
+63.7335370 64.3953060 A
+64.3953060 65.1731740 D/5
+65.1731740 66.6128110 D
+66.6128110 68.0060090 F/6
+68.0060090 69.3411560 G/5
+69.3411560 70.8040130 D
+70.8040130 72.3249200 D
+72.3249200 73.6484580 D:sus4(2)
+73.6484580 75.0300450 G/5
+75.0300450 76.4696820 D
+76.4696820 77.8860990 D
+77.8860990 79.2792970 D:sus4(2)
+79.2792970 80.6957140 G/5
+80.6957140 82.1005210 D
+82.1005210 83.5053280 D:maj7
+83.5053280 86.2917230 D:7
+86.2917230 87.6849200 G/5
+87.6849200 89.0432870 G:min/5
+89.0432870 91.9341720 D
+91.9341720 93.3970290 D
+93.3970290 96.2182530 G/5
+96.2182530 97.7043310 D
+97.7043310 99.1439680 B:min
+99.1439680 100.5836050 D/5
+100.5836050 101.9419720 G#:hdim7
+101.9419720 103.3816090 E:9
+103.3816090 104.1246480 A
+104.1246480 104.7980270 D/5
+104.7980270 105.5178450 A
+105.5178450 106.1796140 D/5
+106.1796140 106.8994330 A
+106.8994330 107.5728110 D/5
+107.5728110 108.3158500 A
+108.3158500 108.9776190 D/5
+108.9776190 110.4056460 D
+110.4056460 111.7872330 F/6
+111.7872330 113.1804300 G/5
+113.1804300 114.6316780 D
+114.6316780 116.0364850 D
+116.0364850 117.4645120 D:sus4(2)
+117.4645120 118.8809290 G/5
+118.8809290 120.2857360 D
+120.2857360 121.7021540 D
+121.7021540 123.0605210 D:sus4(2)
+123.0605210 124.5233780 G/5
+124.5233780 125.9281850 D
+125.9281850 127.3213830 D:maj7
+127.3213830 130.1426070 D:7
+130.1426070 131.5706340 G/5
+131.5706340 132.9638320 G:min/5
+132.9638320 135.7966660 D
+135.7966660 137.2014730 D
+137.2014730 140.0459180 G/5
+140.0459180 141.5087750 D
+141.5087750 142.9251920 B:min
+142.9251920 144.2835600 D/5
+144.2835600 145.6999770 G#:hdim7
+145.6999770 147.1047840 E:9
+147.1047840 147.8246030 A
+147.8246030 148.5560310 D/5
+148.5560310 149.2642400 A
+149.2642400 149.9492290 D/5
+149.9492290 150.6690470 A
+150.6690470 151.3656460 D/5
+151.3656460 152.1086840 A
+152.1086840 152.7820630 D/5
+152.7820630 154.2217000 D
+154.2217000 155.5800680 F/6
+155.5800680 156.9732650 G/5
+156.9732650 158.3896820 D
+158.3896820 159.8060990 D
+159.8060990 161.2457360 F/6
+161.2457360 162.6273240 G/5
+162.6273240 166.7182507 D:7
+166.7182507 167.9819930 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_04_-_Everybody's_Got_Something_To_Hide_Except_Me_and_M.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,117 @@
+0.0000000 0.6627240 N
+0.6627240 1.0645800 E
+1.0645800 1.5754190 A/3
+1.5754190 2.1210880 A:maj(*5)
+2.1210880 2.5970970 N
+2.5970970 3.1079360 E
+3.1079360 3.6419950 A/3
+3.6419950 4.1063940 A:maj(*5)
+4.1063940 4.5940130 N
+4.5940130 5.1396820 E
+5.1396820 5.6389110 A/3
+5.6389110 6.1033100 A:maj(*5)
+6.1033100 6.6025390 N
+6.6025390 7.1249880 E
+7.1249880 7.6358270 A/3
+7.6358270 8.0886160 A:maj(*5)
+8.0886160 8.4136960 N
+8.4136960 9.1567340 E
+9.1567340 10.3293420 A
+10.3293420 11.0491600 E
+11.0491600 12.3030380 A
+12.3030380 13.0576870 E
+13.0576870 14.3347840 A
+14.3347840 15.1010430 E
+15.1010430 16.3317000 A
+16.3317000 17.0747390 E
+17.0747390 18.2937860 A
+18.2937860 19.0600450 E
+19.0600450 20.3023120 A
+20.3023120 24.3890240 A
+24.3890240 28.5105660 D
+28.5105660 32.7249880 B
+32.7249880 33.4796370 E
+33.4796370 34.2923350 D
+34.2923350 35.7102949 G
+35.7102949 36.3705210 N
+36.3705210 37.1716090 E
+37.1716090 37.8914280 G
+37.8914280 40.0741040 D
+40.0741040 41.3362190 E
+41.3362190 42.0826300 A
+42.0826300 43.3132870 E
+43.3132870 44.1027660 A
+44.1027660 45.3798630 E
+45.3798630 46.1345120 A
+46.1345120 47.4000000 E
+47.4000000 48.1546480 A
+48.1546480 48.9092970 E
+48.9092970 50.1515640 A
+50.1515640 50.9642630 E
+50.9642630 52.1717000 A
+52.1717000 53.0772780 E
+53.0772780 54.1686160 A
+54.1686160 54.9116550 E
+54.9116550 56.1655320 A
+56.1655320 56.9666210 E
+56.9666210 58.2204980 A
+58.2204980 58.9983670 E
+58.9983670 60.2174140 A
+60.2174140 64.3273460 A
+64.3273460 68.4372780 D
+68.4372780 72.6168700 B
+72.6168700 73.3947390 E
+73.3947390 74.1726070 D
+74.1726070 75.8096660 G:maj6
+75.8096660 76.2507930 N
+76.2507930 76.9938320 E
+76.9938320 77.7368700 G
+77.7368700 79.4686300 D:maj6
+79.4686300 79.8847160 N
+79.8847160 81.1153740 E
+81.1153740 81.9396820 A
+81.9396820 83.1819500 E
+83.1819500 83.9482080 A
+83.9482080 85.1672560 E
+85.1672560 85.9567340 A
+85.9567340 87.1525620 E
+87.1525620 87.9420400 A
+87.9420400 88.6850790 E
+88.6850790 89.9853960 A
+89.9853960 90.7400450 E
+90.7400450 91.9823120 A
+91.9823120 92.7601810 E
+92.7601810 93.9560090 A
+93.9560090 94.7570970 E
+94.7570970 95.9993650 A
+95.9993650 96.7888430 E
+96.7888430 98.0195010 A
+98.0195010 98.8205890 E
+98.8205890 100.0512470 A
+100.0512470 104.1727890 A
+104.1727890 108.3175510 D
+108.3175510 112.4623120 B
+112.4623120 113.2517910 E
+113.2517910 114.0296590 D
+114.0296590 115.4218003 G:maj6
+115.4218003 116.1078450 N
+116.1078450 116.9089340 E
+116.9089340 117.6055320 G
+117.6055320 119.7301580 D:maj6
+119.7301580 120.3998750 E:(1)
+120.3998750 123.7175170 N
+123.7175170 125.8718360 E
+125.8718360 132.1992740 D
+132.1992740 132.6737870 E
+132.6737870 134.1845800 A
+134.1845800 134.6721990 E
+134.6721990 135.9028570 A
+135.9028570 136.6342850 E
+136.6342850 137.9113830 A
+137.9113830 138.6544210 E
+138.6544210 139.8850790 A
+139.8850790 140.6629470 E
+140.6629470 141.9168250 A
+141.9168250 142.6714730 E
+142.6714730 143.9100830 A
+143.9100830 144.8384770 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_05_-_Sexy_Sadie.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,117 @@
+0.000000 0.980790 D
+0.980790 2.414897 C
+2.414897 3.900975 D
+3.900975 5.421882 G
+5.421882 6.942789 F#
+6.942789 8.533356 F
+8.533356 9.996213 D
+9.996213 11.540340 G
+11.540340 13.107687 F#
+13.107687 16.265600 B:min
+16.265600 17.786507 C
+17.786507 19.365464 D
+19.365464 20.944421 G
+20.944421 22.500158 F#
+22.500158 24.090725 C
+24.090725 25.646462 D
+25.646462 27.248639 G
+27.248639 28.839206 F#
+28.839206 30.406553 F
+30.406553 32.020340 D
+32.020340 33.587687 G
+33.587687 35.155034 F#
+35.155034 36.757210 B:min
+36.757210 38.370997 B:min7
+38.370997 39.961564 C
+39.961564 41.552131 D
+41.552131 43.142698 G
+43.142698 44.779705 F#
+44.779705 46.300612 C
+46.300612 47.891179 D
+47.891179 49.516575 G
+49.516575 51.072312 F#
+51.072312 52.674489 F
+52.674489 54.230226 D
+54.230226 55.820793 G
+55.820793 57.422970 A:min
+57.422970 58.990317 B:min
+58.990317 60.557664 C
+60.557664 62.136621 G
+62.136621 63.680748 A:min
+63.680748 65.248095 B:min
+65.248095 66.838662 C
+66.838662 68.406009 A
+68.406009 69.926916 Ab
+69.926916 71.471043 G
+71.471043 73.050000 F#
+73.050000 76.231133 B:min
+76.231133 77.833310 C
+77.833310 79.389047 D
+79.389047 81.049274 G
+81.049274 82.581791 F#
+82.581791 84.183968 C
+84.183968 85.751315 D
+85.751315 87.365102 G
+87.365102 88.944058 F#
+88.944058 90.557845 F
+90.557845 92.160022 D
+92.160022 93.762199 G
+93.762199 95.375986 F#
+95.375986 98.568730 B:min
+98.568730 100.159297 C
+100.159297 101.703424 D
+101.703424 103.375260 G
+103.375260 104.942607 F#
+104.942607 106.568004 C
+106.568004 108.158571 D
+108.158571 109.656258 G
+109.656258 111.339705 F#
+111.339705 112.930272 F
+112.930272 114.567278 D
+114.567278 116.192675 G
+116.192675 117.771632 A:min
+117.771632 119.385419 B:min
+119.385419 121.010816 C
+121.010816 122.601383 G
+122.601383 124.191950 A:min
+124.191950 125.736077 B:min
+125.736077 127.361473 C
+127.361473 128.870770 A
+128.870770 130.484557 Ab
+130.484557 132.040294 G
+132.040294 133.700521 F#
+133.700521 136.881655 B:min
+136.881655 138.460612 C
+138.460612 140.062789 D
+140.062789 141.641746 G
+141.641746 143.278752 F#
+143.278752 144.846099 C
+144.846099 146.494716 D
+146.494716 148.096893 G
+148.096893 149.710680 F#
+149.710680 151.394126 F
+151.394126 153.007913 D
+153.007913 154.644920 G
+154.644920 156.281927 F#
+156.281927 159.567551 B:min
+159.567551 161.146507 C
+161.146507 162.783514 D
+162.783514 164.397301 G
+164.397301 166.022698 F#
+166.022698 167.601655 C
+167.601655 169.250272 D
+169.250272 170.875668 G
+170.875668 172.477845 F#
+172.477845 174.103242 F
+174.103242 175.705419 D
+175.705419 177.295986 G
+177.295986 178.909773 F#
+178.909773 181.986417 B:min
+181.986417 183.681473 C
+183.681473 185.202380 D
+185.202380 186.781337 G
+186.781337 188.337074 F#
+188.337074 189.892811 C
+189.892811 191.460158 D
+191.460158 193.097165 G
+193.097165 195.386487 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_06_-_Helter_Skelter.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,47 @@
+0.0000000 0.1654307 N
+0.1654307 0.5885710 E:(1,5)
+0.5885710 6.5212690 E:(1,b7)/b7
+6.5212690 9.4353740 C#:(1,b3)
+9.4353740 12.2449880 C
+12.2449880 15.0894330 G
+15.0894330 18.0035370 E
+18.0035370 32.2954190 E
+32.2954190 35.1979130 G
+35.1979130 37.9959180 A
+37.9959180 40.9100220 E
+40.9100220 43.7544670 A
+43.7544670 46.6105210 E
+46.6105210 49.4665750 A
+49.4665750 52.2994100 E
+52.2994100 69.5170060 E
+69.5170060 72.3614510 G
+72.3614510 75.2175050 A
+75.2175050 78.0503400 E
+78.0503400 80.9063940 A
+80.9063940 83.8321080 E
+83.8321080 86.6649430 A
+86.6649430 89.4745570 E
+89.4745570 95.2214960 E
+95.2214960 97.9382310 A
+97.9382310 100.8291150 E
+100.8291150 103.7432190 A
+103.7432190 106.7037640 E
+106.7037640 109.5482080 E
+109.5482080 112.4623120 C#:(1,b3)/b3
+112.4623120 115.2835370 C/3
+115.2835370 118.1163710 G
+118.1163710 132.7101130 E
+132.7101130 135.5661670 G
+135.5661670 138.3641720 A
+138.3641720 141.3014960 E
+141.3014960 144.2852600 A
+144.2852600 147.0368250 E
+147.0368250 149.9160990 A
+149.9160990 152.7257140 E
+152.7257140 179.6512570 E
+179.6512570 181.7533470 N
+181.7533470 191.6655780 E:9
+191.6655780 220.1796820 E
+220.1796820 224.4503470 N
+224.4503470 262.2470190 E
+262.2470190 269.7408340 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_07_-_Long_Long_Long.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,72 @@
+0.000000 0.413805 N
+0.413805 1.946938 G:min
+1.946938 3.560725 G:(1,b3,4)/b3
+3.560725 5.139682 G:min
+5.139682 6.869569 F
+6.869569 10.073922 C
+10.073922 11.699319 Bb
+11.699319 13.394376 A:min
+13.394376 14.566984 G:min
+14.566984 15.124263 C:9(*3)
+15.124263 16.749659 F
+16.749659 18.409886 Bb
+18.409886 20.058503 F
+20.058503 21.811609 C
+21.811609 23.506666 C/5
+23.506666 26.989659 G:min
+26.989659 28.603446 F
+28.603446 30.194013 C
+30.194013 33.723446 G:min
+33.723446 35.395283 F
+35.395283 38.843060 C
+38.843060 42.024580 C:7
+42.024580 43.731247 Bb
+43.731247 45.345034 A:min
+45.345034 47.074920 G:min(4)
+47.074920 48.851247 F
+48.851247 50.592743 Bb
+50.592743 52.345850 F
+52.345850 54.084559 C
+54.084559 55.852063 C/5
+55.852063 59.369886 G:min
+59.369886 61.053333 F
+61.053333 62.771609 C
+62.771609 66.103673 G:min
+66.103673 67.868390 F
+67.868390 74.660226 C
+74.660226 76.332063 Bb
+76.332063 78.050340 F
+78.050340 79.838276 C
+79.838276 84.865396 G:min
+84.865396 86.572063 Bb
+86.572063 88.290340 F
+88.290340 90.066666 C
+90.066666 91.843648 G:min
+91.843648 93.526439 Bb
+93.526439 100.271836 C
+100.271836 101.932063 Bb
+101.932063 103.673560 A:min
+103.673560 105.473106 G:min
+105.473106 107.319092 F
+107.319092 109.048979 Bb
+109.048979 110.860136 F
+110.860136 114.436009 C
+114.436009 118.058321 G:min
+118.058321 119.764988 F
+119.764988 121.367165 C
+121.367165 124.838548 G:min
+124.838548 126.533605 F
+126.533605 128.379591 C
+128.379591 131.827755 G:min
+131.827755 133.592471 F
+133.592471 135.403628 C
+135.403628 139.002721 G:min
+139.002721 140.628117 F
+140.628117 142.381224 C
+142.381224 145.945487 G:min
+145.945487 147.675374 F
+147.675374 158.190121 C
+158.190121 158.936878 C:(1)
+158.936878 159.702782 C:(1,5)
+159.702782 181.779978 C:sus4
+181.779978 184.345758 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_08_-_Revolution_1.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,88 @@
+0.0000000 0.4020998 N
+0.4020998 2.4125990 A
+2.4125990 3.2550939 N
+3.2550939 14.0734942 A
+14.0734942 16.2174600 E:7
+16.2174600 22.5216780 A
+22.5216780 27.5371880 D
+27.5371880 32.6223580 A
+32.6223580 38.8917460 A
+38.8917460 43.9420860 D
+43.9420860 48.8298860 E
+48.8298860 51.3260310 B:min
+51.3260310 53.8453960 E
+53.8453960 56.3647610 B:min
+56.3647610 56.7827210 G
+56.7827210 57.3088003 A
+57.3088003 60.0219040 F#
+60.0219040 62.5064390 E
+62.5064390 64.9909750 A
+64.9909750 67.3594100 D
+67.3594100 69.8323350 A
+69.8323350 72.3400900 D
+72.3400900 74.7433560 A
+74.7433560 77.1814510 D
+77.1814510 82.1505210 E
+82.1505210 88.2109290 A
+88.2109290 93.0987300 D/5
+93.0987300 97.9052600 A
+97.9052600 104.0121080 A
+104.0121080 108.8882990 D/5
+108.8882990 113.7180490 E
+113.7180490 116.1097050 B:min
+116.1097050 118.5245800 E
+118.5245800 121.0439450 B:min
+121.0439450 121.4735140 G
+121.4735140 122.0772330 A
+122.0772330 124.7243080 F#
+124.7243080 126.9998630 E
+126.9998630 129.3682990 A
+129.3682990 131.7599540 D
+131.7599540 134.0587300 A
+134.0587300 136.4619950 D
+136.4619950 138.8420400 A
+138.8420400 141.2336960 D
+141.2336960 145.9821760 E
+145.9821760 151.9845350 A
+151.9845350 156.7678450 D/5
+156.7678450 161.5975960 A
+161.5975960 167.5535140 A
+167.5535140 172.2787750 D/5
+172.2787750 173.5156527 E
+173.5156527 174.7052600 E:sus2(b7)
+174.7052600 175.8546480 E:maj6
+175.8546480 177.0156460 E:7
+177.0156460 179.3956910 B:min
+179.3956910 181.8221760 E
+181.8221760 184.2254420 B:min
+184.2254420 184.6434010 G
+184.6434010 185.2239000 A
+185.2239000 187.8477550 F#
+187.8477550 190.1581400 E
+190.1581400 192.5614050 A
+192.5614050 194.9066210 D
+194.9066210 197.2518360 A
+197.2518360 199.6202720 D
+199.6202720 201.9887070 A
+201.9887070 204.3339220 D
+204.3339220 209.8370520 E
+209.8370520 212.1938770 A
+212.1938770 214.5274820 D/5
+214.5274820 216.8959180 A
+216.8959180 219.2759630 D/5
+219.2759630 221.6095690 A
+221.6095690 223.8967340 D/5
+223.8967340 226.2187300 A
+226.2187300 228.6916550 D/5
+228.6916550 230.9672100 A
+230.9672100 233.3356460 D/5
+233.3356460 235.6924710 A
+235.6924710 238.0260770 D/5
+238.0260770 240.2900220 A
+240.2900220 242.6120180 D/5
+242.6120180 244.9456230 A
+244.9456230 247.2908390 D/5
+247.2908390 249.6244440 A
+249.6244440 252.0160990 D/5
+252.0160990 254.3380950 A
+254.3380950 255.6397571 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_09_-_Honey_Pie.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,95 @@
+0.0000000 0.3829522 N
+0.3829522 1.4610990 E:min
+1.4610990 2.4363370 A
+2.4363370 5.0741170 A:min/4
+5.0741170 7.1732080 C:min
+7.1732080 11.2599200 G
+11.2599200 12.1778807 E:min
+12.1778807 13.0130270 A
+13.0130270 17.3668834 A:min/4
+17.3668834 19.4449540 C:min
+19.4449540 23.6855951 G
+23.6855951 28.9651360 A:9
+28.9651360 39.1819160 D
+39.1819160 42.5720290 G
+42.5720290 44.3019160 Eb
+44.3019160 45.9621420 E
+45.9621420 47.6804190 A
+47.6804190 49.3638660 D
+49.3638660 51.0240920 G
+51.0240920 51.8484010 Eb
+51.8484010 52.7075390 D
+52.7075390 56.0976530 G
+56.0976530 57.7578790 Eb
+57.7578790 59.4529360 E
+59.4529360 61.1596030 A
+61.1596030 62.8314390 D
+62.8314390 64.5264960 G
+64.5264960 65.3391950 F#/5
+65.3391950 66.2099430 F/5
+66.2099430 67.9050000 E:min/5
+67.9050000 69.6116660 A:7/3
+69.6116660 71.6782420 G/3
+71.6782420 72.1078110 G
+72.1078110 72.5373800 F#:dim/b3
+72.5373800 72.9553400 B:dim
+72.9553400 74.6387860 C
+74.6387860 76.2990130 E/5
+76.2990130 78.0637300 A:min
+78.0637300 78.3075390 D
+78.3075390 78.7487180 D/2
+78.7487180 79.6775170 D/3
+79.6775170 83.0328000 G
+83.0328000 84.6698070 Eb
+84.6698070 86.3416430 E
+86.3416430 87.9902600 A
+87.9902600 89.7201470 D
+89.7201470 91.3571540 G
+91.3571540 92.1930720 Eb
+92.1930720 93.0289900 D
+93.0289900 96.3146140 G
+96.3146140 97.9748410 Eb
+97.9748410 99.6002380 E
+99.6002380 101.2024140 A
+101.2024140 102.8626410 D
+102.8626410 104.5344780 G
+104.5344780 105.3820060 Eb
+105.3820060 106.2411450 D
+106.2411450 109.5615980 G
+109.5615980 111.1637750 Eb
+111.1637750 112.7427320 E
+112.7427320 114.4145690 A
+114.4145690 116.0167460 D
+116.0167460 117.6885820 G
+117.6885820 118.5128910 F#/5
+118.5128910 119.3488090 F/5
+119.3488090 121.0670860 E:min/5
+121.0670860 122.6808730 A:7/3
+122.6808730 124.8287180 G/3
+124.8287180 125.2466780 G
+125.2466780 125.6181970 F#:dim/b3
+125.6181970 126.0825960 B:dim
+126.0825960 127.7776530 C
+127.7776530 129.4030490 E/5
+129.4030490 131.1097160 A:min
+131.1097160 131.3767460 D
+131.3767460 131.7830950 D/2
+131.7830950 132.7351130 D/3
+132.7351130 135.9859070 G
+135.9859070 137.6577430 Eb
+137.6577430 139.3063600 E
+139.3063600 140.9898070 A
+140.9898070 142.6848630 D
+142.6848630 144.3450900 G
+144.3450900 145.1577890 Eb
+145.1577890 146.0401470 D
+146.0401470 149.3257700 G
+149.3257700 150.9279470 Eb
+150.9279470 152.5185140 E
+152.5185140 154.1671310 A
+154.1671310 155.8389680 D
+155.8389680 157.4875850 G
+157.4875850 158.1609630 Eb
+158.1609630 159.0897610 D
+159.0897610 160.1314724 G
+160.1314724 161.2994767 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_10_-_Savoy_Truffle.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,82 @@
+0.0000000 1.4169232 N
+1.4169232 6.7686390 E:7
+6.7686390 12.7013370 E
+12.7013370 16.4978000 F#
+16.4978000 20.6657820 A
+20.6657820 24.4970740 G
+24.4970740 28.6302260 B
+28.6302260 29.6402940 E:min
+29.6402940 30.6271420 C/3
+30.6271420 31.6023800 C#:dim/b3
+31.6023800 32.5776190 C/3
+32.5776190 34.5745350 C:maj7
+34.5745350 35.6911473 G
+35.6911473 36.5714510 N
+36.5714510 42.0397500 E:7
+42.0397500 47.9956680 E
+47.9956680 51.7921310 F#
+51.7921310 55.9833330 A
+55.9833330 59.7565750 G
+59.7565750 63.9709970 B
+63.9709970 64.9578450 E:min
+64.9578450 65.9446930 C/3
+65.9446930 66.9547610 C#:dim/b3
+66.9547610 67.9067800 C/3
+67.9067800 69.9269160 C:maj7
+69.9269160 71.0184899 G
+71.0184899 71.9006120 N
+71.9006120 73.8975280 E:min
+73.8975280 75.8480040 A
+75.8480040 76.5562130 A:sus4(2)
+76.5562130 77.6591600 A
+77.6591600 78.4021990 G
+78.4021990 79.5515870 B
+79.5515870 81.5485030 E:min
+81.5485030 83.5686390 A
+83.5686390 84.3000680 A:sus4(2)
+84.3000680 85.4610650 A
+85.4610650 86.1808840 G
+86.1808840 87.2838320 B
+87.2838320 95.1670060 E
+95.1670060 99.1260090 F#
+99.1260090 103.0734010 A
+103.0734010 107.1252830 G
+107.1252830 111.0262350 B
+111.0262350 112.0130830 E:min
+112.0130830 112.9883210 C/3
+112.9883210 113.9983900 C#:dim/b3
+113.9983900 114.9504080 C/3
+114.9504080 116.9357140 C:maj7
+116.9357140 117.9875802 G
+117.9875802 118.9674600 N
+118.9674600 120.9411560 E:min
+120.9411560 122.9148520 A
+122.9148520 123.7159410 A:sus4(2)
+123.7159410 124.7956680 A
+124.7956680 125.5619270 G
+125.5619270 126.7229250 B
+126.7229250 128.6966210 E:min
+128.6966210 130.6935370 A
+130.6935370 131.4365750 E:sus4(2)
+131.4365750 132.5859630 E
+132.5859630 133.3290020 G
+133.3290020 134.5828790 B
+134.5828790 142.5473240 E
+142.5473240 146.3205660 F#
+146.3205660 150.5233780 A
+150.5233780 154.3082310 G
+154.3082310 158.4994330 B
+158.4994330 159.5095010 E:min
+159.5095010 160.4731290 C/3
+160.4731290 161.4715870 C#:dim/b3
+161.4715870 162.4119950 C/3
+162.4119950 164.4089110 C:maj7
+164.4089110 165.4545083 G
+165.4545083 166.3709970 N
+166.3709970 167.4042850 E:min
+167.4042850 168.3795230 C/3
+168.3795230 169.3199310 C#:dim/b3
+169.3199310 170.3067800 C/3
+170.3067800 172.3153060 C:maj7
+172.3153060 173.4390622 G
+173.4390622 174.8942807 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_11_-_Cry_Baby_Cry.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,99 @@
+0.0000000 0.3829522 N
+0.3829522 1.9004980 G
+1.9004980 3.4214050 A:min
+3.4214050 4.9887520 F
+4.9887520 6.5328790 G
+6.5328790 8.0305660 E:min
+8.0305660 9.5979130 A
+9.5979130 11.2000900 F
+11.2000900 12.8254870 E:min
+12.8254870 14.3696140 Eb:aug
+14.3696140 15.9485710 G/5
+15.9485710 17.4694780 C#:hdim7
+17.4694780 18.9555550 C:7
+18.9555550 20.5925620 G
+20.5925620 22.1947390 E:min
+22.1947390 23.7272560 Eb:aug
+23.7272560 25.2365530 G/5
+25.2365530 26.8387300 C#:hdim7
+26.8387300 28.3480270 C:7
+28.3480270 29.8921540 G
+29.8921540 31.4362810 A:min
+31.4362810 33.0036280 F
+33.0036280 34.5361450 G
+34.5361450 36.0686620 E:min
+36.0686620 37.6127890 A
+37.6127890 39.1801360 F
+39.1801360 40.7126530 G
+40.7126530 42.2567800 E:min
+42.2567800 43.7892970 Eb:aug
+43.7892970 45.3102040 G/5
+45.3102040 46.8775510 C#:hdim7
+46.8775510 48.4100680 C:7
+48.4100680 49.9541950 G
+49.9541950 51.5563710 E:min
+51.5563710 53.0772780 Eb:aug
+53.0772780 54.6794550 G/5
+54.6794550 56.1887520 C#:hdim7
+56.1887520 57.7328790 C:7
+57.7328790 59.3002260 G
+59.3002260 60.8211330 A:min
+60.8211330 62.4000900 F
+62.4000900 63.9790470 G
+63.9790470 65.4999540 E:min
+65.4999540 67.0440810 A
+67.0440810 68.5998180 F
+68.5998180 70.2136050 G
+70.2136050 71.8273920 E:min
+71.8273920 73.4063490 Eb:aug
+73.4063490 75.0085260 G/5
+75.0085260 76.5990920 C#:hdim7
+76.5990920 78.1664390 C:7
+78.1664390 79.7221760 G
+79.7221760 81.3011330 E:min
+81.3011330 82.8917000 Eb:aug
+82.8917000 84.5519270 G/5
+84.5519270 86.1889340 C#:hdim7
+86.1889340 87.6634010 C:7
+87.6634010 89.1959180 G
+89.1959180 90.7980950 A:min
+90.7980950 92.4002720 F
+92.4002720 93.9443990 G
+93.9443990 95.5581850 E:min
+95.5581850 97.1255320 A
+97.1255320 98.7160990 F
+98.7160990 100.3182760 G
+100.3182760 101.9552830 E:min
+101.9552830 103.5458500 Eb:aug
+103.5458500 105.1364170 G/5
+105.1364170 106.7618140 C#:hdim7
+106.7618140 108.2943310 C:7
+108.2943310 109.9081170 G
+109.9081170 111.5335140 E:min
+111.5335140 113.1589110 Eb:aug
+113.1589110 114.8075280 G/5
+114.8075280 116.4213150 C#:hdim7
+116.4213150 117.9654420 C:7
+117.9654420 119.5908390 G
+119.5908390 121.1697950 A:min
+121.1697950 122.7487520 F
+122.7487520 124.3277090 G
+124.3277090 125.9066660 E:min
+125.9066660 127.4624030 A
+127.4624030 129.0529700 F
+129.0529700 130.6203170 G
+130.6203170 132.1180040 A:min
+132.1180040 133.7434010 F
+133.7434010 135.2875280 G
+135.2875280 136.8897050 E:min
+136.8897050 138.4454420 A
+138.4454420 140.0476190 F
+140.0476190 141.6149650 G
+141.6149650 143.1358730 A:min
+143.1358730 144.7380490 F
+144.7380490 146.2937860 G
+146.2937860 147.8727430 E:min
+147.8727430 149.4400900 A
+149.4400900 151.0074370 F
+151.0074370 154.7126985 E:min
+154.7126985 181.8065683 F:min
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_12_-_Revolution_9.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,91 @@
+0.0000000 9.2865914 N
+9.2865914 10.5694814 E:min/3
+10.5694814 14.2649703 B:min
+14.2649703 16.1414362 E:min
+16.1414362 18.3617460 B:min
+18.3617460 20.5560310 C#
+20.5560310 23.5898570 C#
+23.5898570 25.1408135 B:min
+25.1408135 31.7658870 N
+31.7658870 39.9993598 C#:min
+39.9993598 59.1278234 Bb
+59.1278234 69.6398619 N
+69.6398619 75.1735216 C#:min
+75.1735216 77.7967443 B:min
+77.7967443 79.0221914 N
+79.0221914 80.5157051 E:min6
+80.5157051 82.4496138 B:min
+82.4496138 83.8473894 N
+83.8473894 85.9919219 Eb
+85.9919219 87.6003212 N
+87.6003212 89.2087206 Ab:min
+89.2087206 120.2852935 N
+120.2852935 121.3384122 D:min
+121.3384122 122.3340879 C
+122.3340879 123.5597500 G
+123.5597500 124.6318013 C
+124.6318013 125.7615103 G
+125.7615103 129.0931947 N
+129.0931947 134.0141308 E
+134.0141308 136.7522392 N
+136.7522392 138.8010336 B:min
+138.8010336 140.7732375 E:min
+140.7732375 143.9708886 C
+143.9708886 146.0482760 E:min
+146.0482760 149.7402490 C
+149.7402490 158.8308610 A:(1)
+158.8308610 168.6904546 N
+168.6904546 169.8967541 F
+169.8967541 172.4816817 Eb
+172.4816817 182.8596869 N
+182.8596869 183.5681485 F
+183.5681485 184.6787100 Eb
+184.6787100 185.9615999 N
+185.9615999 191.2807480 N
+191.2807480 192.0505403 C
+192.0505403 192.6058210 F
+192.6058210 192.9504780 C
+192.9504780 193.5057588 N
+193.5057588 195.2290438 G
+195.2290438 195.6502912 N
+195.6502912 196.6459670 C
+196.6459670 196.9523288 F
+196.9523288 197.4693143 C
+197.4693143 197.8522665 N
+197.8522665 199.8244704 G
+199.8244704 200.4563416 N
+200.4563416 201.3179841 C
+201.3179841 201.9115601 F
+201.9115601 202.2370695 C
+202.2370695 202.7157597 N
+202.7157597 204.2475686 G
+204.2475686 228.4501492 N
+228.4501492 230.2117294 B:min
+230.2117294 232.7392141 F#:min/5
+232.7392141 235.5922082 B:min
+235.5922082 239.7663874 N
+239.7663874 246.9658892 C#:min
+246.9658892 283.6729470 N
+283.6729470 307.4340454 N
+307.4340454 312.7379337 D:(1)
+312.7379337 338.1468137 D:(1,5)
+338.1468137 349.9417422 N
+349.9417422 351.4735511 C:maj7
+351.4735511 352.6989982 C
+352.6989982 353.5031979 N
+353.5031979 354.9775640 C
+354.9775640 355.8200589 N
+355.8200589 357.4859010 C:maj7
+357.4859010 403.1912490 N
+403.1912490 404.9719768 B:min
+404.9719768 409.1078608 F#:min
+409.1078608 412.5352832 B:min
+412.5352832 413.3586305 B
+413.3586305 416.2307722 N
+416.2307722 421.9367603 A
+421.9367603 435.0720216 N
+435.0720216 439.0738723 B
+439.0738723 443.5735610 B:maj7
+443.5735610 445.4883221 E:min
+445.4883221 447.8626259 B:maj7
+447.8626259 502.1652512 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CD2_-_13_-_Good_Night.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,103 @@
+0.0000000 0.4707700 N
+0.4707700 2.0613370 G:maj7
+2.0613370 3.9421540 C/5
+3.9421540 5.7417000 G:maj7
+5.7417000 7.5760770 C/5
+7.5760770 9.2595230 G:maj7
+9.2595230 10.9661900 C/5
+10.9661900 12.7889560 G:maj7
+12.7889560 14.7278230 C/5
+14.7278230 16.6782990 G
+16.6782990 18.5010650 B:min7
+18.5010650 20.3818820 A:min7
+20.3818820 21.3571200 D:sus4
+21.3571200 22.2859180 D
+22.2859180 24.2596140 G
+24.2596140 26.2217000 B:min7
+26.2217000 27.9748070 A:min7
+27.9748070 29.7163030 C/5
+29.7163030 31.5739000 B:min
+31.5739000 33.4663260 A:min
+33.4663260 35.1729930 C/5
+35.1729930 37.0654190 D/3
+37.0654190 38.9230150 G
+38.9230150 40.8154420 B:min7
+40.8154420 44.5422440 A:min7
+44.5422440 46.5159410 B:min
+46.5159410 48.4548070 A:min
+48.4548070 50.3588430 C
+50.3588430 52.0422900 D
+52.0422900 53.8186160 G:maj7
+53.8186160 55.6529930 C:maj(#4)/5
+55.6529930 57.4060990 G:maj7
+57.4060990 59.1824260 C:maj(#4)/5
+59.1824260 60.9819720 G
+60.9819720 62.8047390 C/5
+62.8047390 64.4649650 G
+64.4649650 66.3109520 C/5
+66.3109520 68.0640580 G
+68.0640580 69.9680950 B:min7
+69.9680950 71.6399310 A:min7
+71.6399310 73.4859180 C/5
+73.4859180 75.3319040 B:min
+75.3319040 76.9921310 A:min
+76.9921310 78.8381170 C/5
+78.8381170 80.6841040 D/3
+80.6841040 82.5765300 G
+82.5765300 84.4225170 B:min7
+84.4225170 88.0100000 A:min7
+88.0100000 89.8327660 B:min
+89.8327660 91.7251920 A:min
+91.7251920 93.5247390 C/5
+93.5247390 95.4055550 D/3
+95.4055550 97.1586620 G:maj7
+97.1586620 99.0859180 C:maj(#4)/5
+99.0859180 100.8041950 G:maj7
+100.8041950 102.5921310 C:maj(#4)/5
+102.5921310 104.4497270 G
+104.4497270 106.2376640 C/5
+106.2376640 107.9791600 G
+107.9791600 109.8483670 C/5
+109.8483670 111.6014730 G
+111.6014730 113.3429700 A:min
+113.3429700 115.0496370 A
+115.0496370 116.7911330 D:min
+116.7911330 118.5674600 G
+118.5674600 120.2973460 C/5
+120.2973460 122.1085030 D/3
+122.1085030 123.0721310 C
+123.0721310 124.0009290 D
+124.0009290 125.9514050 G
+125.9514050 127.7973920 B:min7
+127.7973920 129.5040580 A:min7
+129.5040580 131.3384350 C/5
+131.3384350 132.9290020 B:min
+132.9290020 134.7517680 A:min
+134.7517680 136.5280950 C/5
+136.5280950 138.2812010 D/3
+138.2812010 140.1620180 G
+140.1620180 141.9731740 B:min7
+141.9731740 145.5374370 A:min7
+145.5374370 147.3021540 B:min
+147.3021540 149.1133100 A:min
+149.1133100 150.9360770 C/5
+150.9360770 152.8052830 D/3
+152.8052830 154.6396590 G:maj7
+154.6396590 156.4740360 C:maj(#4)/5
+156.4740360 158.2039220 G:maj7
+158.2039220 160.1776190 C:maj(#4)/5
+160.1776190 161.9539450 G:maj7
+161.9539450 163.7883210 C/5
+163.7883210 165.5530380 G:maj7
+165.5530380 167.5035140 C/5
+167.5035140 169.3378910 G
+169.3378910 171.2419270 B:min7
+171.2419270 173.2504530 A:min7
+173.2504530 175.1544890 C/5
+175.1544890 176.9888660 G
+176.9888660 179.0554420 B:min7
+179.0554420 181.1336280 A:min7
+181.1336280 182.3294550 D:sus4
+182.3294550 184.1638320 D
+184.1638320 189.4273176 G
+189.4273176 191.6484405 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+/CD2_-_01_-_Birthday.lab/1.2/Tue Oct 17 21:58:19 2006//
+/CD2_-_02_-_Yer_Blues.lab/1.2/Wed Aug  2 00:43:45 2006//
+/CD2_-_03_-_Mother_Nature's_Son.lab/1.1/Sun Jul  2 19:20:54 2006//
+/CD2_-_04_-_Everybody's_Got_Something_To_Hide_Except_Me_and_M.lab/1.2/Wed Aug  2 00:43:45 2006//
+/CD2_-_05_-_Sexy_Sadie.lab/1.2/Wed Aug  2 00:43:45 2006//
+/CD2_-_06_-_Helter_Skelter.lab/1.2/Wed Aug  2 00:43:45 2006//
+/CD2_-_07_-_Long_Long_Long.lab/1.2/Wed Aug  2 00:43:45 2006//
+/CD2_-_08_-_Revolution_1.lab/1.1/Sun Jul  2 19:20:54 2006//
+/CD2_-_09_-_Honey_Pie.lab/1.2/Wed Aug  2 00:43:45 2006//
+/CD2_-_10_-_Savoy_Truffle.lab/1.2/Wed Aug  2 00:43:45 2006//
+/CD2_-_11_-_Cry_Baby_Cry.lab/1.1/Sun Jul  2 19:20:54 2006//
+/CD2_-_12_-_Revolution_9.lab/1.1/Sun Jul  2 19:20:54 2006//
+/CD2_-_13_-_Good_Night.lab/1.1/Sun Jul  2 19:20:54 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/10CD2final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/10CD2final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/01_-_Come_Together.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+0.0000000 1.1722660 N
+1.1722660 12.5852380 D:min
+12.5852380 24.3693650 D:min
+24.3693650 30.2091830 A
+30.2091830 34.6039950 G:7
+34.6039950 36.0373920 N
+36.0373920 47.4151700 D:min
+47.4151700 59.1412470 D:min
+59.1412470 64.9694550 A
+64.9694550 70.7121281 G:7
+70.7121281 72.9339000 B:min
+72.9339000 73.6188880 A
+73.6188880 75.0585260 G
+75.0585260 76.5213830 A
+76.5213830 87.9223800 D:min
+87.9223800 99.5671880 D:min
+99.5671880 105.4186160 A
+105.4186160 111.2584350 G:7
+111.2584350 113.4062810 B:min
+113.4062810 114.1144890 A
+114.1144890 115.5773460 G
+115.5773460 117.0750340 A
+117.0750340 122.6362130 D:min
+122.6362130 134.2229700 D:min
+134.2229700 145.7516780 A
+145.7516780 151.5218360 D:min
+151.5218360 163.3175730 D:min
+163.3175730 169.1806120 A
+169.1806120 175.0204300 G:7
+175.0204300 177.1798860 B:min
+177.1798860 177.9229250 A
+177.9229250 179.3625620 G
+179.3625620 180.8602490 A
+180.8602490 192.2728570 D:min
+192.2728570 256.2758900 D:min
+256.2758900 260.6798410 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/02_-_Something.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,99 @@
+0.0000000 1.2637423 N
+1.2637423 3.1228450 F
+3.1228450 4.0748630 Eb
+4.0748630 5.0733210 G/5
+5.0733210 8.8465640 C
+8.8465640 12.5037070 E:min/5
+12.5037070 16.1840700 C:7
+16.1840700 18.8775850 F
+18.8775850 19.7599430 C/3
+19.7599430 23.4403060 D
+23.4403060 24.4706471 G
+24.4706471 25.3211220 G:sus4(2)/2
+25.3211220 27.1903280 G/3
+27.1903280 29.0247050 A:min
+29.0247050 30.8242510 Ab:aug
+30.8242510 32.6005780 C/5
+32.6005780 34.4117340 D:7
+34.4117340 36.2345010 F
+36.2345010 37.1865190 Eb
+37.1865190 38.1269270 G/5
+38.1269270 41.8885600 C
+41.8885600 45.5457020 E:min/5
+45.5457020 49.1680150 C:7
+49.1680150 51.8731400 F
+51.8731400 52.7903280 C/3
+52.7903280 56.4126410 D
+56.4126410 57.3066090 G
+57.3066090 58.2586280 G:sus4(2)/2
+58.2586280 60.0233440 G/3
+60.0233440 61.8228910 A:min
+61.8228910 63.6340470 Ab:aug
+63.6340470 65.3987640 C/5
+65.3987640 67.2331400 D:7
+67.2331400 69.1023460 F
+69.1023460 70.0802570 Eb
+70.0802570 71.0184899 G/5
+71.0184899 74.6286960 A
+74.6286960 76.3701920 A
+76.3701920 78.0456632 C#:min/5
+78.0456632 79.7138660 F#:min
+79.7138660 81.4437520 A/5
+81.4437520 83.1039790 D
+83.1039790 84.7874260 G
+84.7874260 85.4749364 A
+85.4749364 86.1833980 A/7
+86.1833980 86.8152692 A/b7
+86.8152692 87.4279927 A/6
+87.4279927 87.8875354 A/b6
+87.8875354 88.2820290 A/5
+88.2820290 89.9306460 A
+89.9306460 91.6140920 C#:min/5
+91.6140920 93.2859290 F#:min
+93.2859290 94.9809860 A/5
+94.9809860 96.6412130 D
+96.6412130 98.3478790 G
+98.3478790 99.0328680 C
+99.0328680 99.6714170 C/7
+99.6714170 100.2867460 C/6
+100.2867460 100.9601240 C/5
+100.9601240 101.3780830 C/3
+101.3780830 101.8308730 C/2
+101.8308730 105.4880150 C
+105.4880150 108.9942290 E:min/5
+108.9942290 112.6281510 C:7
+112.6281510 115.2403960 F
+115.2403960 116.0879250 C/3
+116.0879250 119.7102380 D
+119.7102380 120.6274260 G
+120.6274260 121.4517340 G:sus4(2)/2
+121.4517340 123.2977210 G/3
+123.2977210 125.0392170 A:min
+125.0392170 126.8271540 Ab:aug
+126.8271540 128.6034800 C/5
+128.6034800 130.2985370 D:7
+130.2985370 132.1561330 F
+132.1561330 133.0384920 Eb
+133.0384920 133.8976300 G/5
+133.8976300 137.5779930 C
+137.5779930 141.2351360 E:min/5
+141.2351360 144.8110090 C:7
+144.8110090 147.5161330 F
+147.5161330 148.3984920 C/3
+148.3984920 152.0091950 D
+152.0091950 152.9147730 G
+152.9147730 153.8319084 G:sus4(2)
+153.8319084 155.6082870 G/3
+155.6082870 157.3730040 A:min
+157.3730040 159.1145010 Ab:aug
+159.1145010 160.9488770 C/5
+160.9488770 162.7484240 D:7
+162.7484240 164.5828000 F
+164.5828000 165.4767680 Eb
+165.4767680 166.3475170 G/5
+166.3475170 169.8885600 A
+169.8885600 171.7113260 F
+171.7113260 172.6517340 Eb
+172.6517340 173.7546820 G/5
+173.7546820 178.8386886 C
+178.8386886 182.8979821 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/03_-_Maxwell's_Silver_Hammer.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,96 @@
+0.0000000 0.3829522 N
+0.3829522 1.3299090 D
+1.3299090 2.2703170 F#:min/5
+2.2703170 4.1395230 B
+4.1395230 7.8313730 E:min
+7.8313730 11.5002490 A
+11.5002490 13.3114050 D
+13.3114050 15.1341720 A
+15.1341720 16.0745800 D
+16.0745800 16.9569380 F#:min/5
+16.9569380 18.8261450 B
+18.8261450 22.4484580 E:min
+22.4484580 26.1520400 A
+26.1520400 27.9748070 D
+27.9748070 29.8207930 A
+29.8207930 33.4779360 E:7
+33.4779360 37.0770290 A
+37.0770290 40.7341720 D
+40.7341720 44.3448750 E:7
+44.3448750 47.9555780 A:7
+47.9555780 48.8727660 E:min
+48.8727660 49.7783440 A
+49.7783440 51.5778910 D
+51.5778910 52.5879590 D
+52.5879590 53.4935370 F#/5
+53.4935370 54.4339450 B:min
+54.4339450 55.3975730 D:7/5
+55.3975730 57.2783900 G
+57.2783900 59.0314960 D
+59.0314960 59.9602940 D
+59.9602940 60.8774820 F#:min/5
+60.8774820 62.7118590 B
+62.7118590 66.3457820 E:min
+66.3457820 70.0029250 A
+70.0029250 71.7908610 D
+71.7908610 73.6368480 A
+73.6368480 74.5424260 D
+74.5424260 75.4712240 F#:min/5
+75.4712240 77.2707700 B
+77.2707700 80.9975730 E:min
+80.9975730 84.6779360 A
+84.6779360 86.5123120 D
+86.5123120 88.3350790 A
+88.3350790 91.9922220 E:7
+91.9922220 95.5332650 A
+95.5332650 99.1904080 D
+99.1904080 102.7430610 E:7
+102.7430610 106.3653740 A:7
+106.3653740 108.1765300 E:min
+108.1765300 109.9528570 A
+109.9528570 113.5751700 D
+113.5751700 117.1742630 E:7
+117.1742630 120.8430150 A:7
+120.8430150 121.7602040 E:min
+121.7602040 122.6541720 A
+122.6541720 124.5117680 D
+124.5117680 125.4405660 D
+125.4405660 126.3693650 F#/5
+126.3693650 127.2981630 B:min
+127.2981630 128.2385710 D:7/5
+128.2385710 129.8973944 G
+129.8973944 131.8608840 G/5
+131.8608840 132.8477320 D
+132.8477320 133.7300900 F#:min/5
+133.7300900 135.5528570 B
+135.5528570 139.1983900 E:min
+139.1983900 142.8555320 A
+142.8555320 144.7363490 D
+144.7363490 146.5126750 A
+146.5126750 147.4530830 D
+147.4530830 148.3702720 F#:min/5
+148.3702720 150.1930380 B
+150.1930380 153.8385710 E:min
+153.8385710 157.4957140 A
+157.4957140 159.3417000 D
+159.3417000 161.1760770 A
+161.1760770 164.7983900 E:7
+164.7983900 168.3858730 A
+168.3858730 172.0430150 D
+172.0430150 175.5608390 E:7
+175.5608390 179.1367120 A:7
+179.1367120 180.9943080 E:min
+180.9943080 182.7822440 A
+182.7822440 186.3232870 D
+186.3232870 189.8178910 E:7
+189.8178910 193.3937640 A:7
+193.3937640 194.2877320 E:min
+194.2877320 195.1933100 A
+195.1933100 197.0509070 D
+197.0509070 197.9448750 D
+197.9448750 198.8620630 F#/5
+198.8620630 199.8140810 B:min
+199.8140810 200.7544890 D:7/5
+200.7544890 202.5656460 G
+202.5656460 204.7262589 D
+204.7262589 207.1580055 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/04_-_Oh!_Darling.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,68 @@
+0.0000000 0.4403951 N
+0.4403951 2.7955512 E:aug
+2.7955512 7.1803542 A
+7.1803542 11.3028790 E
+11.3028790 15.4476410 F#:min
+15.4476410 19.6272330 D
+19.6272330 21.6705890 B:min
+21.6705890 23.7952150 E
+23.7952150 25.8501810 B:min
+25.8501810 28.0096370 E
+28.0096370 29.9252830 A
+29.9252830 31.8989790 D
+31.8989790 33.8262350 A
+33.8262350 35.9624710 E
+35.9624710 40.1420630 A
+40.1420630 44.2868250 E
+44.2868250 48.4664170 F#:min
+48.4664170 52.5879590 D
+52.5879590 54.6661450 B:min
+54.6661450 56.7559410 E
+56.7559410 58.8689560 B:min
+58.8689560 60.9355320 E
+60.9355320 62.9324480 A
+62.9324480 64.8713150 D
+64.8713150 66.7869610 A
+66.7869610 68.7142170 A:7
+68.7142170 72.7777090 D
+72.7777090 76.9340810 F:7
+76.9340810 85.1423350 A
+85.1423350 93.3621990 B
+93.3621990 95.4171650 E
+95.4171650 97.4373010 F:7
+97.4373010 99.1654784 E
+99.1654784 101.5820630 E:aug
+101.5820630 105.9125850 A
+105.9125850 110.1270060 E
+110.1270060 114.3414280 F#:min
+114.3414280 118.4861900 D
+118.4861900 120.5875960 B:min
+120.5875960 122.7470520 E
+122.7470520 124.8484580 B:min
+124.8484580 126.9614730 E
+126.9614730 128.9467800 A
+128.9467800 130.9320860 D
+130.9320860 132.8825620 A
+132.8825620 134.8214280 A:7
+134.8214280 138.9894100 D
+138.9894100 143.0645120 F:7
+143.0645120 151.3308160 A
+151.3308160 159.5739000 B
+159.5739000 161.6172560 E
+161.6172560 163.6141720 F:7
+163.6141720 165.7504080 E
+165.7504080 168.0491830 E:aug
+168.0491830 172.2636050 A
+172.2636050 176.4896370 E
+176.4896370 180.6227890 F#:min
+180.6227890 184.8836500 D
+184.8836500 186.9850560 B:min
+186.9850560 189.1096820 E
+189.1096820 191.1762580 B:min
+191.1762580 193.2776640 E
+193.2776640 195.2745800 A
+195.2745800 197.2831060 D
+197.2831060 198.3976640 A
+198.3976640 199.0478230 Bb:7
+199.0478230 204.2858639 A:7
+204.2858639 206.5452820 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/05_-_Octopus's_Garden.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,100 @@
+0.0000000 0.4212474 N
+0.4212474 1.9452380 E
+1.9452380 2.2354870 B:9
+2.2354870 4.4413830 E
+4.4413830 4.7548520 E/5
+4.7548520 5.0451020 D
+5.0451020 5.3934010 D#
+5.3934010 6.6588880 E
+6.6588880 7.9359860 C#:min
+7.9359860 9.2014730 A
+9.2014730 10.5017910 B
+10.5017910 12.4987070 E
+12.4987070 13.1488660 E/7
+13.1488660 15.1225620 C#:min
+15.1225620 15.7959410 C#:min/b7
+15.7959410 18.4197950 A
+18.4197950 21.0668700 B
+21.0668700 23.0289560 E
+23.0289560 23.6675050 E/7
+23.6675050 25.6644210 C#:min
+25.6644210 26.3145800 C#:min/b7
+26.3145800 28.9384350 A
+28.9384350 31.5739000 B
+31.5739000 36.1250110 C#:min
+36.1250110 36.7867800 C#:min/b7
+36.7867800 39.4338540 A
+39.4338540 42.0344890 B
+42.0344890 43.9965750 E
+43.9965750 44.6119040 E/7
+44.6119040 46.5391600 C#:min
+46.5391600 47.1777090 C#:min/b7
+47.1777090 48.5244670 A
+48.5244670 49.7783440 B
+49.7783440 52.4602490 E
+52.4602490 54.3875050 E
+54.3875050 55.0260540 E/7
+55.0260540 57.0345800 C#:min
+57.0345800 57.6615190 C#:min/b7
+57.6615190 60.3318140 A
+60.3318140 62.9324480 B
+62.9324480 64.9177550 E
+64.9177550 65.5446930 E/7
+65.5446930 67.5719199 C#:min
+67.5719199 68.1801580 C#:min/b7
+68.1801580 70.8040130 A
+70.8040130 73.3698180 B
+73.3698180 77.9557590 C#:min
+77.9557590 78.5943080 C#:min/b7
+78.5943080 81.2065530 A
+81.2065530 83.8187980 B
+83.8187980 85.7228340 E
+85.7228340 86.3962130 E/7
+86.3962130 88.3466890 C#:min
+88.3466890 88.9620180 C#:min/b7
+88.9620180 90.3087750 A
+90.3087750 91.5510430 B
+91.5510430 94.1748970 E
+94.1748970 96.7871420 A
+96.7871420 99.3413370 F#:min
+99.3413370 101.9303620 D
+101.9303620 104.4845570 E
+104.4845570 107.0271420 A
+107.0271420 109.6045570 F#:min
+109.6045570 110.8932650 D
+110.8932650 112.1935820 E
+112.1935820 113.4822900 A
+113.4822900 114.7477770 B
+114.7477770 117.3600220 E
+117.3600220 119.6342748 C#:min
+119.6342748 119.9722670 C#:min/b7
+119.9722670 122.5845120 A
+122.5845120 125.1735370 B
+125.1735370 127.1401383 E
+127.1401383 127.7973920 E/7
+127.7973920 129.7250659 C#:min
+129.7250659 130.3864170 C#:min/b7
+130.3864170 132.9754420 A
+132.9754420 135.5992970 B
+135.5992970 140.1155780 C#:min
+140.1155780 140.7657360 C#:min/b7
+140.7657360 143.4476410 A
+143.4476410 146.0250560 B
+146.0250560 147.9535917 E
+147.9535917 148.6140810 E/7
+148.6140810 150.4619288 C#:min
+150.4619288 151.2031060 C#:min/b7
+151.2031060 152.4685940 A
+152.4685940 153.7340810 B
+153.7340810 155.6317838 C#:min
+155.6317838 156.2882760 C#:min/b7
+156.2882760 157.5885940 A
+157.5885940 158.8424710 B
+158.8424710 160.7348970 C#:min
+160.7348970 161.3734460 C#:min/b7
+161.3734460 162.6621540 A
+162.6621540 163.9392510 B
+163.9392510 165.5762580 E
+165.5762580 165.9593870 B
+165.9593870 168.3075024 E
+168.3075024 171.1030537 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/06_-_I_Want_You.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,232 @@
+0.0000000 0.4020998 N
+0.4020998 1.5272780 D:min
+1.5272780 2.6766660 D:min/2
+2.6766660 3.7447840 D:min/b3
+3.7447840 4.4496296 D:min/4
+4.4496296 4.7896820 D:min/5
+4.7896820 7.0071880 E:9
+7.0071880 9.3175730 Bb:7
+9.3175730 13.5319950 A:aug
+13.5319950 26.8718590 A:min
+26.8718590 27.9051470 A:min
+27.9051470 28.9964850 C
+28.9964850 30.0065530 D:min7(2,*b3,4)
+30.0065530 31.1211110 F
+31.1211110 31.6203400 G
+31.6203400 32.1892290 G#:aug
+32.1892290 35.0018333 A:min
+35.0018333 36.3804300 A
+36.3804300 48.6986160 D:min
+48.6986160 49.6622440 D:min
+49.6622440 50.6955320 F
+50.6955320 51.7172100 C
+51.7172100 52.7504980 Bb
+52.7504980 53.1104080 D:(1,4)
+53.1104080 53.4587070 D#:(1,4)
+53.4587070 53.8186160 E:(1,4)
+53.8186160 65.7072330 E:9
+65.7072330 78.0370290 A:min
+78.0370290 79.0470970 A:min
+79.0470970 80.0687750 C
+80.0687750 81.0904530 D:min7(2,*b3,4)
+81.0904530 82.1353510 F
+82.1353510 82.5881400 G
+82.5881400 83.0873690 G#:aug
+83.0873690 85.9919219 A:min
+85.9919219 87.1856910 A
+87.1856910 99.4458270 D:min
+99.4458270 100.4791150 D:min
+100.4791150 101.4775730 F
+101.4775730 102.5224710 C
+102.5224710 103.5673690 Bb
+103.5673690 103.8808390 D:(1,4)
+103.8808390 104.1826980 D#:(1,4)
+104.1826980 104.5890470 E:(1,4)
+104.5890470 116.6866430 E:9
+116.6866430 117.9985710 D:min
+117.9985710 119.2524480 D:min/2
+119.2524480 120.5179360 D:min/b3
+120.5179360 121.3684239 D:min/4
+121.3684239 121.8066430 D:min/5
+121.8066430 124.3027890 E:9
+124.3027890 126.7408840 Bb:7
+126.7408840 129.2370290 A:aug
+129.2370290 130.5101179 D:min
+130.5101179 131.7099540 D:min/2
+131.7099540 132.9406120 D:min/b3
+132.9406120 133.7755199 D:min/4
+133.7755199 134.1712690 D:min/5
+134.1712690 136.6209750 E:9
+136.6209750 139.0939000 Bb:7
+139.0939000 144.2198075 A:aug
+144.2198075 158.1807020 A:min
+158.1807020 159.2720400 A:min
+159.2720400 160.3517680 C
+160.3517680 161.4547160 D:min7(2,*b3,4)
+161.4547160 162.4647840 F
+162.4647840 162.9640130 G
+162.9640130 163.5329020 G#:aug
+163.5329020 165.6459180 A:min
+165.6459180 167.7589340 A
+167.7589340 180.5647390 D:min
+180.5647390 181.6560770 D:min
+181.6560770 182.7358040 F
+182.7358040 183.7807020 C
+183.7807020 184.8488200 Bb
+184.8488200 185.1855100 D:(1,4)
+185.1855100 185.4873690 D#:(1,4)
+185.4873690 185.8704980 E:(1,4)
+185.8704980 198.2160711 E:9
+198.2160711 199.4890020 D:min
+199.4890020 200.8009290 D:min/2
+200.8009290 202.0315870 D:min/b3
+202.0315870 202.8326750 D:min/4
+202.8326750 203.3202940 D:min/5
+203.3202940 205.7700000 E:9
+205.7700000 208.1732650 Bb:7
+208.1732650 210.6810200 A:aug
+210.6810200 211.9697270 D:min
+211.9697270 213.1539450 D:min/2
+213.1539450 214.4310430 D:min/b3
+214.4310430 215.2321310 D:min/4
+215.2321310 215.7197500 D:min/5
+215.7197500 218.1578450 E:9
+218.1578450 220.6656000 Bb:7
+220.6656000 225.6695010 A:aug
+225.6695010 238.0341260 A:min
+238.0341260 239.0674140 A:min
+239.0674140 240.0890920 C
+240.0890920 241.1107700 D:min7(2,*b3,4)
+241.1107700 242.1556680 F
+242.1556680 242.6548970 G
+242.6548970 243.1657360 G#:aug
+243.1657360 247.2060090 A:min
+247.2060090 259.5358040 D:min
+259.5358040 260.5458730 D:min
+260.5458730 261.6023800 F
+261.6023800 262.6821080 C
+262.6821080 263.6805660 Bb
+263.6805660 264.0288660 D:(1,4)
+264.0288660 264.3307250 D#:(1,4)
+264.3307250 264.6582820 E:(1,4)
+264.6582820 276.8811110 E:9
+276.8811110 278.1930380 D:min
+278.1930380 279.5630150 D:min/2
+279.5630150 280.8168930 D:min/b3
+280.8168930 282.0591600 D:min/4
+282.0591600 284.5204760 E:9
+284.5204760 286.9701810 Bb:7
+286.9701810 289.4547160 A:aug
+289.4547160 290.6853740 D:min
+290.6853740 291.9392510 D:min/2
+291.9392510 293.1466890 D:min/b3
+293.1466890 294.0290470 D:min/4
+294.0290470 294.4818360 D:min/5
+294.4818360 296.9083210 E:9
+296.9083210 299.4160770 Bb:7
+299.4160770 301.9238320 A:aug
+301.9238320 303.1544890 D:min
+303.1544890 304.4431970 D:min/2
+304.4431970 305.7435140 D:min/b3
+305.7435140 306.5794330 D:min/4
+306.5794330 307.0090020 D:min/5
+307.0090020 309.5051470 E:9
+309.5051470 311.9664620 Bb:7
+311.9664620 314.4742170 A:aug
+314.4742170 315.6700450 D:min
+315.6700450 316.9239220 D:min/2
+316.9239220 318.2358500 D:min/b3
+318.2358500 319.0253280 D:min/4
+319.0253280 319.4316780 D:min/5
+319.4316780 321.8813830 E:9
+321.8813830 324.3891380 Bb:7
+324.3891380 326.8968930 A:aug
+326.8968930 328.1275510 D:min
+328.1275510 329.3930380 D:min/2
+329.3930380 330.6353060 D:min/b3
+330.6353060 331.4363940 D:min/4
+331.4363940 331.9240130 D:min/5
+331.9240130 334.3737180 E:9
+334.3737180 336.9046930 Bb:7
+336.9046930 339.4588880 A:aug
+339.4588880 340.6431060 D:min
+340.6431060 341.9666430 D:min/2
+341.9666430 343.2205210 D:min/b3
+343.2205210 344.0332190 D:min/4
+344.0332190 344.4860090 D:min/5
+344.4860090 346.9705440 E:9
+346.9705440 349.5015190 Bb:7
+349.5015190 352.0905440 A:aug
+352.0905440 353.2979810 D:min
+353.2979810 354.6911790 D:min/2
+354.6911790 355.8637860 D:min/b3
+355.8637860 356.6880950 D:min/4
+356.6880950 357.0828340 D:min/5
+357.0828340 359.4977090 E:9
+359.4977090 362.0054640 Bb:7
+362.0054640 364.5480490 A:aug
+364.5480490 365.8019270 D:min
+365.8019270 367.0906340 D:min/2
+367.0906340 368.3096820 D:min/b3
+368.3096820 369.1339900 D:min/4
+369.1339900 369.5635600 D:min/5
+369.5635600 372.0597050 E:9
+372.0597050 374.5326300 Bb:7
+374.5326300 377.1680950 A:aug
+377.1680950 378.3871420 D:min
+378.3871420 379.6758500 D:min/2
+379.6758500 380.9529470 D:min/b3
+380.9529470 381.7540360 D:min/4
+381.7540360 382.2416550 D:min/5
+382.2416550 384.7958500 E:9
+384.7958500 387.2919950 Bb:7
+387.2919950 389.7881400 A:aug
+389.7881400 391.1465070 D:min
+391.1465070 392.3887750 D:min/2
+392.3887750 393.6658730 D:min/b3
+393.6658730 394.5366210 D:min/4
+394.5366210 395.0126300 D:min/5
+395.0126300 397.4391150 E:9
+397.4391150 399.9236500 Bb:7
+399.9236500 402.5010650 A:aug
+402.5010650 403.7317230 D:min
+403.7317230 405.0436500 D:min/2
+405.0436500 406.2743080 D:min/b3
+406.2743080 407.0182637 D:min/4
+407.0182637 407.5165750 D:min/5
+407.5165750 410.0591600 E:9
+410.0591600 412.6365750 Bb:7
+412.6365750 415.2023800 A:aug
+415.2023800 416.4214280 D:min
+416.4214280 417.7565750 D:min/2
+417.7565750 419.0104530 D:min/b3
+419.0104530 419.8928110 D:min/4
+419.8928110 420.3456000 D:min/5
+420.3456000 422.9114050 E:9
+422.9114050 425.4423800 Bb:7
+425.4423800 428.0197950 A:aug
+428.0197950 429.2852830 D:min
+429.2852830 430.5623800 D:min/2
+430.5623800 431.8162580 D:min/b3
+431.8162580 432.5941260 D:min/4
+432.5941260 433.0353060 D:min/5
+433.0353060 435.6243310 E:9
+435.6243310 438.2017460 Bb:7
+438.2017460 440.6978910 A:aug
+440.6978910 441.9633780 D:min
+441.9633780 443.2288660 D:min/2
+443.2288660 444.5640130 D:min/b3
+444.5640130 445.3651020 D:min/4
+445.3651020 445.8178910 D:min/5
+445.8178910 448.3604760 E:9
+448.3604760 450.8566210 Bb:7
+450.8566210 453.4456460 A:aug
+453.4456460 454.7343530 D:min
+454.7343530 456.0462810 D:min/2
+456.0462810 457.2769380 D:min/b3
+457.2769380 458.1476870 D:min/4
+458.1476870 458.6236960 D:min/5
+458.6236960 461.1314510 E:9
+461.1314510 463.6508160 Bb:7
+463.6508160 464.0892246 A
+464.0892246 467.1547630 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/07_-_Here_Comes_The_Sun.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,131 @@
+0.0000000 0.3662810 N
+0.3662810 3.6054640 A
+3.6054640 5.4630610 D
+5.4630610 7.2626070 E
+7.2626070 10.9661900 A
+10.9661900 12.5915870 D
+12.5915870 14.7046030 E
+14.7046030 18.3269160 A
+18.3269160 20.1729020 D
+20.1729020 21.9956680 B
+21.9956680 23.8532650 A
+23.8532650 24.4802040 D:maj6
+24.4802040 25.1651920 A:maj(9)/3
+25.1651920 25.8385710 B:min
+25.8385710 26.5003400 A
+26.5003400 26.9879590 E:sus4(b7)
+26.9879590 27.4523580 E:7
+27.4523580 31.2023800 A
+31.2023800 33.0599770 D
+33.0599770 34.9291830 E
+34.9291830 38.6559860 A
+38.6559860 40.5251920 D
+40.5251920 42.3827890 E
+42.3827890 46.1328110 A
+46.1328110 48.0368480 D
+48.0368480 49.9060540 B
+49.9060540 51.7636500 A
+51.7636500 52.4370290 D:maj6
+52.4370290 53.1104080 A:maj(9)/3
+53.1104080 53.8302260 B:min
+53.8302260 54.4919950 A
+54.4919950 55.0028340 E:sus4(7)
+55.0028340 55.4672330 E:7
+55.4672330 57.3248290 A
+57.3248290 59.1243760 E
+59.1243760 62.8743990 A
+62.8743990 64.7436050 D
+64.7436050 66.6360310 E
+66.6360310 70.3744440 A
+70.3744440 72.2552600 D
+72.2552600 74.1360770 E
+74.1360770 77.9325390 A
+77.9325390 79.7901360 D
+79.7901360 81.6709520 B
+81.6709520 83.4937180 A
+83.4937180 84.2135370 D:maj6
+84.2135370 84.8985260 A:maj(9)/3
+84.8985260 85.5951240 B:min
+85.5951240 86.2801130 A
+86.2801130 86.7561220 E:sus4(b7)
+86.7561220 87.2437410 E:7
+87.2437410 89.0897270 A
+89.0897270 90.7267340 E
+90.7267340 91.3652830 C
+91.3652830 92.0734920 G
+92.0734920 92.7468700 D/3
+92.7468700 93.2112690 D
+93.2112690 95.0224260 A
+95.0224260 96.5897730 E
+96.5897730 97.2747610 C
+97.2747610 97.9249200 G
+97.9249200 98.6215190 D/3
+98.6215190 99.1091380 D
+99.1091380 100.9086840 A
+100.9086840 102.4644210 E
+102.4644210 103.1261900 C
+103.1261900 103.8227890 G
+103.8227890 104.5077770 D/3
+104.5077770 104.9837860 D
+104.9837860 106.8065530 A
+106.8065530 108.3390700 E
+108.3390700 109.0240580 C
+109.0240580 109.6974370 G
+109.6974370 110.3940360 D/3
+110.3940360 110.8468250 D
+110.8468250 112.6812010 A
+112.6812010 114.2369380 E
+114.2369380 114.9103170 C
+114.9103170 115.5488660 G
+115.5488660 116.2454640 D/3
+116.2454640 116.7098630 D
+116.7098630 118.5558500 A
+118.5558500 120.0767570 E
+120.0767570 120.7269160 C
+120.7269160 121.4351240 G
+121.4351240 122.1085030 D/3
+122.1085030 122.5612920 D
+122.5612920 124.4188880 A
+124.4188880 126.2068250 E
+126.2068250 127.8090020 E:sus4
+127.8090020 129.6201580 E
+129.6201580 131.6286840 E:7
+131.6286840 135.4135370 A
+135.4135370 137.2595230 D
+137.2595230 139.1055100 E
+139.1055100 142.8439220 A
+142.8439220 144.7247390 D
+144.7247390 146.5939450 E
+146.5939450 150.3323580 A
+150.3323580 152.2363940 D
+152.2363940 154.1056000 B
+154.1056000 155.9748070 A
+155.9748070 156.6597950 D:maj6
+156.6597950 157.3912240 A:maj(9)/3
+157.3912240 158.0413830 B:min
+158.0413830 158.6915410 A
+158.6915410 159.1791600 E:sus4(b7)
+159.1791600 159.6551700 E:7
+159.6551700 163.3703620 A
+163.3703620 165.1815190 D
+165.1815190 167.1203850 B
+167.1203850 169.0128110 A
+169.0128110 169.6397500 D:maj6
+169.6397500 170.3595690 A:maj(9)/3
+170.3595690 171.0445570 B:min
+171.0445570 171.7527660 A
+171.7527660 172.2055550 E:sus4(b7)
+172.2055550 172.6815640 E:7
+172.6815640 174.5507700 A
+174.5507700 175.2473690 D:maj6
+175.2473690 175.9555780 A:maj(9)/3
+175.9555780 176.6637860 B:min
+176.6637860 177.3023350 A
+177.3023350 177.7667340 E:sus4(b7)
+177.7667340 178.2543530 E:7
+178.2543530 178.9857820 A:min7
+178.9857820 179.7056000 G/2
+179.7056000 180.4254190 D/5
+180.4254190 181.0291380 D
+181.0291380 183.5910890 A
+183.5910890 185.5266208 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/08_-_Because.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,49 @@
+0.0000000 0.3829522 N
+0.3829522 6.5311790 C#:min
+6.5311790 9.6194330 D#:hdim7
+9.6194330 12.6844670 G#
+12.6844670 15.7146710 A
+15.7146710 18.7448750 C#:min
+18.7448750 22.8896370 A:9
+22.8896370 24.8517230 A:7(*5,13)
+24.8517230 27.7542170 D
+27.7542170 30.8773010 D:dim
+30.8773010 36.9260990 C#:min
+36.9260990 39.9098630 D#:hdim7
+39.9098630 42.9400680 G#
+42.9400680 45.9586620 A
+45.9586620 48.9656460 C#:min
+48.9656460 51.9842400 A:9
+51.9842400 54.8751240 A:7(13)
+54.8751240 57.9053280 D
+57.9053280 60.8774820 D:dim
+60.8774820 66.9262810 C#:min
+66.9262810 69.9100450 D#:hdim7
+69.9100450 72.8125390 G#
+72.8125390 75.8079130 A
+75.8079130 78.7916780 C#:min
+78.7916780 81.7870520 A:9
+81.7870520 84.7708160 A:7(13)
+84.7708160 87.8126300 D
+87.8126300 90.7267340 D:dim
+90.7267340 96.7639220 F#
+96.7639220 102.7662810 G#:7
+102.7662810 108.6525390 C#:min
+108.6525390 111.6246930 D#:hdim7
+111.6246930 114.6200680 G#
+114.6200680 117.5341720 A
+117.5341720 120.4947160 C#:min
+120.4947160 123.4320400 A:9
+123.4320400 126.2997050 A:7(13)
+126.2997050 129.3182990 D
+129.3182990 132.2788430 D:dim7
+132.2788430 138.1186620 C#:min
+138.1186620 140.9863260 D#:hdim7
+140.9863260 143.9120400 G#
+143.9120400 146.8145350 A
+146.8145350 149.7054190 C#:min
+149.7054190 152.6891830 A:9
+152.6891830 155.5916780 A:7(13)
+155.5916780 158.4941720 D
+158.4941720 164.4396850 D:dim7
+164.4396850 165.5188163 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/09_-_You_Never_Give_Me_Your_Money.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,126 @@
+0.0000000 3.0976547 A:min7
+3.0976547 4.1279130 D:min9
+4.1279130 5.9855100 D:min
+5.9855100 8.8880040 G:7
+8.8880040 9.9096820 C:sus4
+9.9096820 11.7904980 C
+11.7904980 14.6813830 F:maj7
+14.6813830 15.7030610 B:dim
+15.7030610 17.5142170 E
+17.5142170 23.2959860 A:min
+23.2959860 26.2449200 A:min7
+26.2449200 27.3503231 D:min9
+27.3503231 29.1474140 D:min
+29.1474140 32.0847390 G:7
+32.0847390 33.1528570 C:sus4
+33.1528570 35.0104530 C
+35.0104530 37.9129470 F:maj7
+37.9129470 38.9578450 B:dim
+38.9578450 40.8270520 E
+40.8270520 46.5972100 A:min
+46.5972100 49.5577550 A:min7
+49.5577550 50.5678230 D:min9
+50.5678230 52.4486390 D:min
+52.4486390 55.3511330 G:7
+55.3511330 56.4540810 C:sus4
+56.4540810 58.2536280 C
+58.2536280 61.1677320 F:maj7
+61.1677320 62.2358500 B:dim
+62.2358500 64.1166660 E
+64.1166660 68.4956484 A:min
+68.4956484 69.8171650 G
+69.8171650 71.2568020 C
+71.2568020 72.6383900 E
+72.6383900 74.0083670 A:min
+74.0083670 75.3551240 C:7
+75.3551240 76.7251020 F
+76.7251020 78.0718590 G
+78.0718590 80.7421540 C
+80.7421540 82.1005210 C
+82.1005210 83.4472780 E
+83.4472780 84.8172560 A:min
+84.8172560 86.2104530 C:7
+86.2104530 87.5920400 F
+87.5920400 88.9504080 G
+88.9504080 91.6787520 C
+91.6787520 94.3722670 Bb
+94.3722670 97.1354420 F
+97.1354420 99.9102260 C
+99.9102260 102.6501810 Bb
+102.6501810 105.3669160 F
+105.3669160 108.0952600 C
+108.0952600 110.7655550 Bb
+110.7655550 113.4590700 F
+113.4590700 116.2222440 C
+116.2222440 118.8809290 Bb
+118.8809290 121.5860540 F
+121.5860540 124.3027890 C
+124.3027890 126.9846930 Bb
+126.9846930 129.6665980 F
+129.6665980 132.3368930 C
+132.3368930 134.9839680 D
+134.9839680 136.3191150 Eb
+136.3191150 137.6194330 G
+137.6194330 138.5830610 C
+138.5830610 140.1968480 A
+140.1968480 141.2533560 Eb
+141.2533560 142.8439220 C
+142.8439220 143.8656000 Gb
+143.8656000 145.4329470 Eb
+145.4329470 146.4546250 A
+146.4546250 147.0931740 Gb
+147.0931740 147.6968930 G
+147.6968930 148.0451920 Ab
+148.0451920 150.7619270 A
+150.7619270 153.3625620 B
+153.3625620 154.6512690 C
+154.6512690 155.9980270 E
+155.9980270 158.6567120 A
+158.6567120 159.7132190 D:min
+159.7132190 161.3153960 G/5
+161.3153960 162.3138540 D:min
+162.3138540 163.9276410 G/5
+163.9276410 166.5863260 A
+166.5863260 167.9446930 B
+167.9446930 168.9199310 C
+168.9199310 170.5801580 G/3
+170.5801580 173.1691830 A
+173.1691830 174.1792510 C
+174.1792510 175.8278680 G/3
+175.8278680 178.4285030 A
+178.4285030 179.3921310 C
+179.3921310 181.0639680 G/3
+181.0639680 183.7226530 A
+183.7226530 184.6978910 C
+184.6978910 186.3697270 G/3
+186.3697270 188.9471420 A
+188.9471420 189.9223800 C
+189.9223800 191.5709970 G/3
+191.5709970 194.1600220 A
+194.1600220 195.1236500 C
+195.1236500 196.7142170 G/3
+196.7142170 199.3148520 A
+199.3148520 200.3133100 C
+200.3133100 201.8806570 G/3
+201.8806570 204.4232420 A
+204.4232420 205.3404300 C
+205.3404300 206.9774370 G/3
+206.9774370 209.4735820 A
+209.4735820 210.3791600 C
+210.3791600 211.9465070 G/3
+211.9465070 214.5123120 A
+214.5123120 215.3946710 C
+215.3946710 216.9620180 G/3
+216.9620180 219.5394330 A
+219.5394330 220.3753510 C
+220.3753510 221.9543080 G/3
+221.9543080 224.4736730 A
+224.4736730 225.3212010 C
+225.3212010 226.9233780 G/3
+226.9233780 229.3730830 A
+229.3730830 230.2786620 C
+230.2786620 231.8460090 G/3
+231.8460090 234.3073240 A
+234.3073240 235.2129020 C
+235.2129020 236.7802490 G/3
+236.7802490 242.3180036 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/10_-_Sun_King.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,39 @@
+0.0000000 0.1914761 N
+0.1914761 1.3647390 E
+1.3647390 7.7850560 E:maj6
+7.7850560 14.2750340 E:maj6
+14.2750340 20.2890020 F#:min7
+20.2890020 20.7301810 B:maj6
+20.7301810 27.1621080 E:maj6
+27.1621080 32.7348970 F#:min7
+32.7348970 33.5243760 B:maj6
+33.5243760 39.8750340 E:maj6
+39.8750340 45.7612920 F#:min7
+45.7612920 46.2837410 B:maj6
+46.2837410 52.6692290 E:maj6
+52.6692290 58.8921760 G:9(*3,11)
+58.8921760 62.0965300 C
+62.0965300 65.2428340 C:maj7
+65.2428340 68.4123580 G
+68.4123580 71.6051020 A
+71.6051020 74.7630150 C
+74.7630150 77.9673690 C:maj7
+77.9673690 81.1717230 G
+81.1717230 84.3064170 A
+84.3064170 87.4991600 F
+87.4991600 90.6802940 D:7
+90.6802940 93.9078680 F
+93.9078680 97.1238320 D:7
+97.1238320 100.3630150 C
+100.3630150 103.5441490 E:min7
+103.5441490 106.7252830 C:7
+106.7252830 109.9064170 F
+109.9064170 115.4908160 F#:min7
+115.4908160 116.2570740 B:maj6
+116.2570740 122.7354420 E:maj6
+122.7354420 128.2501810 F#:min7
+128.2501810 129.0048290 B:maj6
+129.0048290 135.5296370 E:maj6
+135.5296370 141.0559860 F#:min7
+141.0559860 141.8106340 B:maj6
+141.8106340 146.2954868 E:maj6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/11_-_Mean_Mr_Mustard.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,33 @@
+0.0000000 1.7710880 E:maj6
+1.7710880 11.6743990 E
+11.6743990 15.3199310 B
+15.3199310 15.5869610 B
+15.5869610 15.8656000 C
+15.8656000 16.1674600 C#
+16.1674600 20.0335820 D
+20.0335820 20.3354420 D
+20.3354420 20.6256910 C#
+20.6256910 20.9275510 C
+20.9275510 26.0127210 B
+26.0127210 26.9066890 E
+26.9066890 28.3695460 C
+28.3695460 30.8076410 B
+30.8076410 31.9918590 E
+31.9918590 33.1760770 C
+33.1760770 35.5677320 B
+35.5677320 45.1227430 E
+45.1227430 48.7218360 B
+48.7218360 48.9772560 B
+48.9772560 49.2558950 C
+49.2558950 49.5461450 C#
+49.5461450 53.3542170 D
+53.3542170 53.6560770 D
+53.6560770 53.9463260 C#
+53.9463260 54.2249650 C
+54.2249650 59.2172560 B
+59.2172560 60.0996140 E
+60.0996140 61.0051920 C
+61.0051920 62.8511790 B
+62.8511790 63.6870970 E
+63.6870970 64.5926750 C
+64.5926750 66.2124395 B
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/12_-_Polythene_Pam.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,70 @@
+0.0000000 1.0148234 D/2
+1.0148234 1.7014280 A/5
+1.7014280 3.3268250 E
+3.3268250 4.0814730 D/2
+4.0814730 4.7780720 A/5
+4.7780720 6.2873690 E
+6.2873690 7.0071880 D
+7.0071880 7.5644670 A
+7.5644670 9.1550340 E
+9.1550340 9.8748520 D
+9.8748520 10.3973010 A
+10.3973010 11.9762580 E
+11.9762580 13.4158950 G
+13.4158950 14.8439220 B
+14.8439220 15.5753510 C
+15.5753510 16.1210200 D
+16.1210200 17.7231970 E
+17.7231970 18.4546250 C
+18.4546250 19.0002940 D
+19.0002940 20.5908610 E
+20.5908610 21.3455100 D/2
+21.3455100 22.0653280 A/5
+22.0653280 23.5397950 E
+23.5397950 24.2596140 D/2
+24.2596140 25.0258730 A/5
+25.0258730 26.5351700 E
+26.5351700 27.2317680 D
+27.2317680 27.7890470 A
+27.7890470 29.4260540 E
+29.4260540 30.1342630 D
+30.1342630 30.6799310 A
+30.6799310 32.2588880 E
+32.2588880 33.6753060 G
+33.6753060 35.0917230 B
+35.0917230 35.8231510 C
+35.8231510 36.3688200 D
+36.3688200 37.9942170 E
+37.9942170 38.7140360 C
+38.7140360 39.2597050 D
+39.2597050 40.8734920 E
+40.8734920 41.6165300 D/2
+41.6165300 42.3479590 A/5
+42.3479590 43.8688660 E
+43.8688660 44.6931740 D/2
+44.6931740 45.4478230 A/5
+45.4478230 46.9919500 E
+46.9919500 47.6769380 D
+47.6769380 48.2226070 A
+48.2226070 49.8480040 E
+49.8480040 50.5562130 D
+50.5562130 51.0902720 A
+51.0902720 52.6808390 E
+52.6808390 53.4006570 D
+53.4006570 53.9463260 A
+53.9463260 55.5601130 E
+55.5601130 56.2915410 D
+56.2915410 56.8488200 A
+56.8488200 58.4742170 E
+58.4742170 59.2056460 D
+59.2056460 59.7513150 A
+59.7513150 61.3534920 E
+61.3534920 62.0733100 D
+62.0733100 62.6073690 A
+62.6073690 64.2327660 E
+64.2327660 64.9758040 D
+64.9758040 65.5098630 A
+65.5098630 67.1236500 E
+67.1236500 67.8666890 D
+67.8666890 68.4239680 A
+68.4239680 72.7226273 E
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/13_-_She_Came_In_Through_The_Bathroom_Window.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,59 @@
+0.0000000 1.6466946 E
+1.6466946 3.0365750 E/b7
+3.0365750 4.4413830 E/6
+4.4413830 5.9158500 E/5
+5.9158500 8.8996140 A
+8.8996140 11.8601580 D
+11.8601580 14.8671420 A
+14.8671420 17.7348070 D
+17.7348070 20.6721310 A
+20.6721310 23.6210650 D
+23.6210650 26.5700000 D
+26.5700000 29.5305440 A
+29.5305440 30.2723733 D:min
+30.2723733 31.0382777 D:min/2
+31.0382777 31.7850346 D:min/b3
+31.7850346 32.5126438 D:min/4
+32.5126438 35.4516320 A
+35.4516320 36.1506899 D:min
+36.1506899 36.9292047 D:min/b7
+36.9292047 37.6824988 D:min/6
+37.6824988 38.3541260 D:min/5
+38.3541260 41.3611110 G
+41.3611110 42.4756680 C
+42.4756680 43.5670060 C/7
+43.5670060 44.2636050 C/6
+44.2636050 47.2705890 G
+47.2705890 48.4199770 C
+48.4199770 51.6591600 A
+51.6591600 54.6661450 D
+54.6661450 57.6847390 A
+57.6847390 60.6917230 D
+60.6917230 63.6290470 A
+63.6290470 66.6128110 D
+66.6128110 69.5849650 D
+69.5849650 72.4990700 A
+72.4990700 75.5176640 D
+75.5176640 78.4782080 A
+78.4782080 81.4503620 D
+81.4503620 84.3876870 A
+84.3876870 87.3714510 D
+87.3714510 90.3319950 D
+90.3319950 93.2925390 A
+93.2925390 94.0909718 D:min
+94.0909718 94.8008863 D:min/2
+94.8008863 95.5244530 D:min/b3
+95.5244530 96.2879130 D:min/4
+96.2879130 99.3297270 A
+99.3297270 100.0843760 D:min
+100.0843760 100.8506340 D:min/b7
+100.8506340 101.5240130 D:min/6
+101.5240130 102.2554420 D:min/5
+102.2554420 105.2624260 G
+105.2624260 106.3769840 C
+106.3769840 107.4799310 C/7
+107.4799310 108.2461900 C/6
+108.2461900 111.2415640 G
+111.2415640 112.3793420 C
+112.3793420 116.7812807 A
+116.7812807 117.7147315 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/14_-_Golden_Slumbers.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,32 @@
+0.0000000 0.3829522 N
+0.3829522 6.3378593 A:min7
+6.3378593 9.3307930 A:min7
+9.3307930 15.1590020 D:min
+15.1590020 21.1613600 G:7
+21.1613600 22.6358270 C
+22.6358270 24.0290240 E
+24.0290240 25.5731510 A:min
+25.5731510 28.5685260 D:min9
+28.5685260 31.6219500 G:7
+31.6219500 34.5244440 C
+34.5244440 37.4617680 C
+37.4617680 40.3526530 F:maj7
+40.3526530 43.2087070 C
+43.2087070 46.0647610 C
+46.0647610 48.8859860 F:maj7
+48.8859860 50.3256230 C
+50.3256230 51.8000900 E/5
+51.8000900 53.2977770 A:min
+53.2977770 56.2118820 D:min9
+56.2118820 59.2304760 G:7
+59.2304760 62.2258500 C
+62.2258500 65.2676640 A:min7
+65.2676640 68.2282080 A:min7
+68.2282080 74.1492970 D:min
+74.1492970 80.0471650 G:7
+80.0471650 81.5564620 C
+81.5564620 82.9496590 E
+82.9496590 84.3660770 A:min
+84.3660770 87.2685710 D:min9
+87.2685710 90.1826750 G:7
+90.1826750 91.5661566 C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/15_-_Carry_That_Weight.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,44 @@
+0.0000000 1.6201580 C
+1.6201580 4.4762130 C
+4.4762130 10.2347610 G
+10.2347610 13.0559860 C
+13.0559860 15.8656000 C
+15.8656000 18.7680950 G
+18.7680950 21.6357590 G
+21.6357590 23.1102260 C
+23.1102260 24.4918140 C:maj7/7
+24.4918140 27.3710880 A:min
+27.3710880 28.4275960 D:min9
+28.4275960 30.2619720 D:min
+30.2619720 33.0599770 G:7
+33.0599770 34.0584350 C:sus4
+34.0584350 35.8928110 C
+35.8928110 38.7140360 F
+38.7140360 39.7705440 B:dim
+39.7705440 41.5236500 E:7
+41.5236500 44.4145350 A:min
+44.4145350 47.3750790 A:min7
+47.3750790 48.3387070 D:min9
+48.3387070 50.2195230 D:min
+50.2195230 53.0059180 G:7
+53.0059180 54.1320860 C:sus4
+54.1320860 55.8271420 C
+55.8271420 58.7064170 F
+58.7064170 59.7048750 B:dim
+59.7048750 61.5160310 E:7
+61.5160310 64.4765750 A:min
+64.4765750 65.2167637 G
+65.2167637 66.9017535 C/5
+66.9017535 67.2978000 G
+67.2978000 70.0994046 C
+70.0994046 75.7614730 G
+75.7614730 78.5246480 C
+78.5246480 81.3574820 C
+81.3574820 84.1670970 G
+84.1670970 86.9999310 G
+86.9999310 88.1260990 C
+88.1260990 89.8559860 G/3
+89.8559860 92.6075510 A
+92.6075510 93.6872780 C
+93.6872780 95.4171650 G/3
+95.4171650 96.8677650 A
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/16_-_The_End.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+0.0000000 0.2617910 A
+0.2617910 1.5969380 D
+1.5969380 2.1077770 B
+2.1077770 3.8841040 E
+3.8841040 5.8113600 A
+5.8113600 7.7153960 D#:dim/b5
+7.7153960 11.2448290 A
+11.2448290 11.7440580 A
+11.7440580 13.1836960 D
+13.1836960 13.7061450 B
+13.7061450 15.3779810 E
+15.3779810 17.3052380 A
+17.3052380 19.1860540 D#:dim/b5
+19.1860540 19.5688586 A
+19.5688586 34.7529143 N
+34.7529143 36.7287300 A:7
+36.7287300 38.6908160 D:7
+38.6908160 40.6529020 A:7
+40.6529020 42.6265980 D:7
+42.6265980 44.5886840 A:7
+44.5886840 46.5623800 D:7
+46.5623800 48.4780270 A:7
+48.4780270 50.3820630 D:7
+50.3820630 52.2977090 A:7
+52.2977090 54.2597950 D:7
+54.2597950 56.2218820 A:7
+56.2218820 58.1955780 D:7
+58.1955780 60.1112240 A:7
+60.1112240 62.0733100 D:7
+62.0733100 63.9889560 A:7
+63.9889560 65.9162130 D:7
+65.9162130 67.8434690 A:7
+67.8434690 69.7242850 D:7
+69.7242850 71.6863710 A:7
+71.6863710 73.5323580 D:7
+73.5323580 75.5060540 A:7
+75.5060540 77.3752600 D:7
+77.3752600 79.2909070 A:7
+79.2909070 81.2646030 D:7
+81.2646030 83.3079590 A:7
+83.3079590 85.1423350 D:7
+85.1423350 87.0812010 A:7
+87.0812010 88.9968480 D:7
+88.9968480 92.8629700 A
+92.8629700 96.8568020 A
+96.8568020 100.7925850 G/2
+100.7925850 101.5472330 F/3
+101.5472330 102.2554420 C:maj6/5
+102.2554420 103.0217000 D:min7/b3
+103.0217000 103.8227890 A:min/5
+103.8227890 105.4481850 D:min
+105.4481850 107.2129020 G
+107.2129020 110.7423350 C
+110.7423350 114.1092290 D/b7
+114.1092290 115.8623350 Eb/6
+115.8623350 117.6154420 F/5
+117.6154420 123.4063542 C
+123.4063542 139.7775617 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/17_-_Her_Majesty.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+0.0000000 0.3255094 N
+0.3255094 2.0729470 D
+2.0729470 2.6070060 D
+2.6070060 3.1758950 D/7
+3.1758950 3.7563940 D/6
+3.7563940 4.3485030 D/5
+4.3485030 4.9754420 E:9
+4.9754420 5.5327210 A
+5.5327210 6.7749880 D
+6.7749880 7.3903170 D
+7.3903170 7.9824260 D/7
+7.9824260 8.5861450 D/6
+8.5861450 9.1550340 D/5
+9.1550340 10.3740810 E:9
+10.3740810 11.5815190 A
+11.5815190 12.7657360 B:min
+12.7657360 13.9499540 B:sus2
+13.9499540 15.1341720 D:7
+15.1341720 16.3416090 G
+16.3416090 17.5258270 E:dim/b3
+17.5258270 18.0947160 D
+18.0947160 18.7100450 B
+18.7100450 19.3137640 E:7
+19.3137640 19.9174820 A
+19.9174820 20.4631510 D
+20.4631510 21.0088200 B
+21.0088200 21.6357590 E:7
+21.6357590 22.2046480 A
+22.2046480 22.5750336 D
+22.5750336 23.1253417 A:(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+/01_-_Come_Together.lab/1.3/Tue Oct 17 21:58:53 2006//
+/02_-_Something.lab/1.2/Tue Oct 17 21:58:53 2006//
+/03_-_Maxwell's_Silver_Hammer.lab/1.1/Tue Jul 18 12:05:57 2006//
+/04_-_Oh!_Darling.lab/1.2/Wed Aug  2 00:44:14 2006//
+/05_-_Octopus's_Garden.lab/1.3/Tue Oct 17 21:58:53 2006//
+/06_-_I_Want_You.lab/1.2/Wed Aug  2 00:44:14 2006//
+/07_-_Here_Comes_The_Sun.lab/1.2/Wed Aug  2 00:44:14 2006//
+/08_-_Because.lab/1.1/Tue Jul 18 12:05:57 2006//
+/09_-_You_Never_Give_Me_Your_Money.lab/1.1/Tue Jul 18 12:05:57 2006//
+/10_-_Sun_King.lab/1.1/Tue Jul 18 12:05:57 2006//
+/11_-_Mean_Mr_Mustard.lab/1.1/Tue Jul 18 12:05:57 2006//
+/12_-_Polythene_Pam.lab/1.1/Tue Jul 18 12:05:57 2006//
+/13_-_She_Came_In_Trough_The_Bathroom_Window.lab/1.2/Tue Oct 17 21:58:53 2006//
+/14_-_Golden_Slumbers.lab/1.2/Wed Aug  2 12:21:42 2006//
+/15_-_Carry_That_Weight.lab/1.1/Tue Jul 18 12:05:57 2006//
+/16_-_The_End.lab/1.3/Tue Oct 17 21:58:53 2006//
+/17_-_Her_Majesty.lab/1.1/Tue Jul 18 12:05:57 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/11final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/11final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/01_-_Two_of_Us.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,97 @@
+0.0000000 10.4545957 N
+10.4545957 14.6287750 G:maj(*1)/5
+14.6287750 18.8261450 G
+18.8261450 24.2596140 G
+24.2596140 25.3509520 C
+25.3509520 26.4306800 G/3
+26.4306800 27.4768221 A:min7
+27.4768221 28.5901360 C/5
+28.5901360 33.9655550 G
+33.9655550 35.0568930 C
+35.0568930 36.1598410 G/3
+36.1598410 37.2395690 A:min7
+37.2395690 38.2612470 C/5
+38.2612470 39.8866430 G
+39.8866430 40.9547610 D
+40.9547610 41.5352600 C
+41.5352600 43.0909970 G
+43.0909970 44.1591150 D
+44.1591150 44.7280040 C
+44.7280040 46.3185710 G
+46.3185710 47.4099090 C
+47.4099090 49.6880511 G
+49.6880511 53.9811560 G:maj(*1)/5
+53.9811560 58.3348970 G
+58.3348970 63.7335370 G
+63.7335370 64.8480950 C
+64.8480950 65.9278230 G/3
+65.9278230 67.0307700 A:min7
+67.0307700 68.0756680 C/5
+68.0756680 73.5671880 G
+73.5671880 74.6701360 C
+74.6701360 75.7382530 G/3
+75.7382530 76.8644210 A:min7
+76.8644210 77.9209290 C/5
+77.9209290 79.5231060 G
+79.5231060 80.6492740 D
+80.6492740 81.2065530 C
+81.2065530 82.8551700 G
+82.8551700 83.9116780 D
+83.9116780 84.5037860 C
+84.5037860 86.0711330 G
+86.0711330 87.1740810 C
+87.1740810 89.8980346 G
+89.8980346 91.4929930 N
+91.4929930 93.6872780 Bb
+93.6872780 95.9047840 D:min
+95.9047840 98.0758500 G:min
+98.0758500 102.4528110 A:min
+102.4528110 104.5774370 D
+104.5774370 110.1850560 G
+110.1850560 111.2647840 C
+111.2647840 112.3445120 G/3
+112.3445120 113.4126300 A:min7
+113.4126300 114.5039680 C/5
+114.5039680 119.9490470 G
+119.9490470 121.0868250 C
+121.0868250 122.1433330 G/3
+122.1433330 123.2811110 A:min7
+123.2811110 124.3724480 C/5
+124.3724480 126.0094550 G
+126.0094550 127.1356230 D
+127.1356230 127.6696820 C
+127.6696820 129.3299090 G
+129.3299090 130.4560770 D
+130.4560770 131.0133560 C
+131.0133560 132.6503620 G
+132.6503620 133.7765300 C
+133.7765300 136.5224678 G
+136.5224678 138.1767120 N
+138.1767120 140.4058270 Bb
+140.4058270 142.6581630 D:min
+142.6581630 144.8640580 G:min
+144.8640580 149.2874600 A:min
+149.2874600 151.4236960 D
+151.4236960 156.9384350 G
+156.9384350 158.0646030 C
+158.0646030 159.1211110 G/3
+159.1211110 160.2463581 A:min7
+160.2463581 161.3618360 C/5
+161.3618360 166.9462350 G
+166.9462350 168.0724030 C
+168.0724030 169.1289110 G/3
+169.1289110 170.3015190 A:min7
+170.3015190 171.4276870 C/5
+171.4276870 173.0763030 G
+173.0763030 174.1792510 D
+174.1792510 174.7597500 C
+174.7597500 176.4083670 G
+176.4083670 177.5461450 D
+177.5461450 178.1150340 C
+178.1150340 179.7752600 G
+179.7752600 180.9594780 C
+180.9594780 184.1425769 G
+184.1425769 185.3944890 N
+185.3944890 189.7946710 G:maj(*1)/5
+189.7946710 211.2364467 G
+211.2364467 216.5977779 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/02_-_Dig_a_Pony.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,87 @@
+0.0000000 1.2305890 N
+1.2305890 3.6802940 N
+3.6802940 5.0502720 G
+5.0502720 9.2308530 N
+9.2308530 10.6114510 G
+10.6114510 12.0046480 D
+12.0046480 14.8490920 A
+14.8490920 16.2422900 G
+16.2422900 17.6703170 D
+17.6703170 20.5031510 A
+20.5031510 26.5635600 A
+26.5635600 29.6053740 F#:min
+29.6053740 31.0450110 B:min
+31.0450110 34.2377550 G
+34.2377550 35.7586620 B:min
+35.7586620 37.3376190 G
+37.3376190 40.5071420 E
+40.5071420 46.8113600 A
+46.8113600 50.0041040 F#:min
+50.0041040 51.3973010 B:min
+51.3973010 54.6132650 G
+54.6132650 56.1341720 B:min
+56.1341720 57.7131290 G
+57.7131290 60.7317230 E
+60.7317230 62.2642400 G
+62.2642400 63.8199770 D
+63.8199770 66.7108610 A
+66.7108610 68.1156680 G
+68.1156680 69.6249650 D
+69.6249650 74.6965360 A
+74.6965360 76.2857880 N
+76.2857880 82.5236500 A
+82.5236500 85.6002940 F#:min
+85.6002940 87.1212010 B:min
+87.1212010 90.2907250 G
+90.2907250 91.8232420 B:min
+91.8232420 93.4138090 G
+93.4138090 96.5136730 E
+96.5136730 102.8295010 A
+102.8295010 105.9409750 F#:min
+105.9409750 107.4372464 B:min
+107.4372464 110.6081850 G
+110.6081850 112.1755320 B:min
+112.1755320 113.7196590 G
+113.7196590 116.7498630 E
+116.7498630 118.2939900 G
+118.2939900 119.8729470 D
+119.8729470 122.7638320 A
+122.7638320 124.1918590 G
+124.1918590 125.6779360 D
+125.6779360 132.2143530 A
+132.2143530 138.2863710 A
+138.2863710 141.3746250 F#:min
+141.3746250 142.8955320 B:min
+142.8955320 145.9721760 G
+145.9721760 147.4698630 B:min
+147.4698630 148.9684151 G
+148.9684151 151.9745350 E
+151.9745350 158.1278230 A
+158.1278230 161.2625170 F#:min
+161.2625170 162.7834240 B:min
+162.7834240 165.8832870 G
+165.8832870 167.4041950 B:min
+167.4041950 168.9947610 G
+168.9947610 172.0714050 E
+172.0714050 178.3756230 A
+178.3756230 181.6612470 F#:min
+181.6612470 183.1660487 B:min
+183.1660487 186.3865070 G
+186.3865070 187.9306340 B:min
+187.9306340 189.5996461 G
+189.5996461 192.6210650 E
+192.6210650 194.1768020 G
+194.1768020 195.7441490 D
+195.7441490 198.7163030 A
+198.7163030 200.1559410 G
+200.1559410 201.6420180 D
+201.6420180 206.7001680 A
+206.7001680 208.1900450 N
+208.1900450 209.6412920 G
+209.6412920 211.0577090 D
+211.0577090 213.9718140 A
+213.9718140 215.4230610 G
+215.4230610 216.8278680 D
+216.8278680 219.7419720 A
+219.7419720 225.8669270 A
+225.8669270 234.8088610 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/03_-_Across_the_Universe.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,65 @@
+0.0000000 0.4038050 N
+0.4038050 1.9817680 Db
+1.9817680 3.5607250 Db:maj7
+3.5607250 6.7882990 F:min
+6.7882990 10.0507020 Ab:maj6
+10.0507020 11.6528790 Db
+11.6528790 13.1970060 Bb:min
+13.1970060 16.3549200 F:min
+16.3549200 19.5012240 Eb:min7
+19.5012240 21.9257200 Ab
+21.9257200 23.4718360 Ab:7
+23.4718360 25.0624030 Db
+25.0624030 26.6761900 Bb:min
+26.6761900 29.8341040 F:min
+29.8341040 31.4478910 Eb:min7
+31.4478910 34.6174140 Gb:min
+34.6174140 41.0377320 Db
+41.0377320 44.3117460 Ab
+44.3117460 50.5513980 Ab
+50.5513980 53.7158270 Gb
+53.7158270 56.8621310 Db
+56.8621310 63.2445598 Ab
+63.2445598 66.4039156 Gb
+66.4039156 69.4821760 Db
+69.4821760 71.0263030 Db
+71.0263030 72.5588200 Bb:min
+72.5588200 75.7051240 F:min
+75.7051240 78.8978680 Eb:min7
+78.8978680 80.4216720 Ab
+80.4216720 81.9861220 Ab:7
+81.9861220 83.5650790 Db
+83.5650790 85.1208160 Bb:min
+85.1208160 88.2787300 F:min
+88.2787300 91.4366430 Eb:min7
+91.4366430 94.5909040 Ab
+94.5909040 95.4072560 Ab:7
+95.4072560 101.7579130 Db
+101.7579130 104.9738770 Ab
+104.9738770 111.3013150 Ab
+111.3013150 114.4243990 Gb
+114.4243990 117.5242630 Db
+117.5242630 123.7704300 Ab
+123.7704300 126.9167340 Gb
+126.9167340 129.9817680 Db
+129.9817680 131.5491150 Db
+131.5491150 133.0932420 Bb:min
+133.0932420 136.1350560 F:min
+136.1350560 137.7256230 Eb:min7
+137.7256230 140.7906570 Gb:min
+140.7906570 142.3115640 Db
+142.3115640 143.9253510 Bb:min
+143.9253510 146.9903850 F:min
+146.9903850 150.0786390 Eb:min7
+150.0786390 151.6124900 Ab
+151.6124900 153.2017230 Ab:7
+153.2017230 159.5291600 Db
+159.5291600 162.6870740 Ab
+162.6870740 168.8751920 Ab
+168.8751920 171.9634460 Gb
+171.9634460 175.0981400 Db
+175.0981400 181.2862580 Ab
+181.2862580 184.4906120 Gb
+184.4906120 187.4511560 Db
+187.4511560 222.7841610 Db
+222.7841610 228.5922790 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/04_-_I_Me_Mine.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,81 @@
+0.0000000 0.4020998 N
+0.4020998 1.4227890 A:min
+1.4227890 2.5721760 A:min/b3
+2.5721760 4.6387520 D
+4.6387520 5.6720400 G
+5.6720400 6.7169380 E:7
+6.7169380 7.7734460 A:min
+7.7734460 8.8415640 A:min/b3
+8.8415640 10.9081400 D
+10.9081400 11.8833780 G
+11.8833780 12.9514960 E:7
+12.9514960 14.9484120 A:min
+14.9484120 15.9817000 A:min
+15.9817000 17.0382080 A:min/b3
+17.0382080 19.0467340 D
+19.0467340 20.0451920 G
+20.0451920 21.0320400 E:7
+21.0320400 23.1218360 A:min
+23.1218360 25.1419720 D:min
+25.1419720 27.1156680 D:min/b3
+27.1156680 28.1257360 E
+28.1257360 29.1474140 F#:hdim7/b7
+29.1474140 31.1095010 E:7
+31.1095010 32.1079590 A:min
+32.1079590 33.1528570 G#:aug
+33.1528570 34.1513150 C/5
+34.1513150 35.1613830 F#:hdim7
+35.1613830 39.0042850 F:maj7
+39.0042850 46.3998410 A:min7
+46.3998410 50.1266430 D:min7
+50.1266430 53.7953960 A:min7
+53.7953960 57.5105890 E
+57.5105890 58.6019270 A:min
+58.6019270 59.6236050 A:min/b3
+59.6236050 61.6785710 D
+61.6785710 62.6073690 G
+62.6073690 63.5942170 E:7
+63.5942170 65.5446930 A:min
+65.5446930 66.5199310 A:min
+66.5199310 67.4719500 A:min/b3
+67.4719500 69.5036960 D
+69.5036960 70.4208840 G
+70.4208840 71.4077320 E:7
+71.4077320 73.3465980 A:min
+73.3465980 75.2854640 D:min
+75.2854640 77.2359410 D:min/b3
+77.2359410 78.1879590 E
+78.1879590 79.1748070 F#:hdim7/b7
+79.1748070 81.0904530 E:7
+81.0904530 82.0773010 A:min
+82.0773010 83.1221990 G#:aug
+83.1221990 84.1554870 C/5
+84.1554870 85.1191150 F#:hdim7
+85.1191150 89.0200680 F:maj7
+89.0200680 96.4156230 A:min7
+96.4156230 100.1192060 D:min7
+100.1192060 103.7415190 A:min7
+103.7415190 107.5031510 E
+107.5031510 108.5712690 A:min
+108.5712690 109.6277770 A:min/b3
+109.6277770 111.6595230 D
+111.6595230 112.5883210 G
+112.5883210 113.6216090 E:7
+113.6216090 115.5140360 A:min
+115.5140360 116.5124940 A:min
+116.5124940 117.4877320 A:min/b3
+117.4877320 119.4382080 D
+119.4382080 120.4018360 G
+120.4018360 121.4119040 E:7
+121.4119040 123.3507700 A:min
+123.3507700 125.2315870 D:min
+125.2315870 127.2401130 D:min/b3
+127.2401130 128.1573010 E
+128.1573010 129.1557590 F#:hdim7/b7
+129.1557590 131.0481850 E:7
+131.0481850 132.0118140 A:min
+132.0118140 133.0915410 G#:aug
+133.0915410 134.0667800 C/5
+134.0667800 134.9723580 F#:hdim7
+134.9723580 144.2581028 F:maj7
+144.2581028 145.6558784 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/05_-_Dig_It.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,42 @@
+0.0000000 2.5721760 N
+2.5721760 3.7796140 F:7
+3.7796140 4.9173920 Bb
+4.9173920 6.0900000 C
+6.0900000 7.2393870 Bb
+7.2393870 8.4003850 F:7
+8.4003850 9.5381630 Bb
+9.5381630 10.6411110 C
+10.6411110 11.8485480 Bb
+11.8485480 13.0095460 F:7
+13.0095460 14.2053740 Bb
+14.2053740 15.3547610 C
+15.3547610 16.5041490 Bb
+16.5041490 17.6419270 F:7
+17.6419270 18.7797050 Bb
+18.7797050 19.9058730 C
+19.9058730 21.0784800 Bb
+21.0784800 22.2278680 F:7
+22.2278680 23.4120860 Bb
+23.4120860 24.5498630 C
+24.5498630 25.7573010 Bb
+25.7573010 26.9299090 F:7
+26.9299090 28.0909070 Bb
+28.0909070 29.2054640 C
+29.2054640 30.3780720 Bb
+30.3780720 31.5042400 F:7
+31.5042400 32.6187980 Bb
+32.6187980 33.7449650 C
+33.7449650 34.9291830 Bb
+34.9291830 36.0437410 F:7
+36.0437410 37.1699090 Bb
+37.1699090 38.2960770 C
+38.2960770 39.4338540 Bb
+39.4338540 40.5716320 F:7
+40.5716320 41.7210200 Bb
+41.7210200 42.8704080 C
+42.8704080 43.9617460 Bb
+43.9617460 45.1227430 F:7
+45.1227430 46.3301810 Bb
+46.3301810 47.4215190 C
+47.4215190 48.7689657 Bb
+48.7689657 49.9944128 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/06_-_Let_It_Be.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,155 @@
+0.0000000 0.1751573 N
+0.1751573 1.8523580 C
+1.8523580 3.4545350 G
+3.4545350 4.7200220 A:min
+4.7200220 5.1263710 A:min/b7
+5.1263710 5.9506800 F:maj7
+5.9506800 6.7749880 F:maj6
+6.7749880 8.4236050 C
+8.4236050 10.0141720 G
+10.0141720 11.6511790 F
+11.6511790 13.3926750 C
+13.3926750 15.0180720 C
+15.0180720 16.5273690 G
+16.5273690 17.7348070 A:min
+17.7348070 18.1295460 A:min/b7
+18.1295460 18.9190240 F:maj7
+18.9190240 19.6620630 F:maj6
+19.6620630 21.2642400 C
+21.2642400 22.7967570 G
+22.7967570 24.3989340 F
+24.3989340 26.0359410 C
+26.0359410 27.5916780 C
+27.5916780 29.2170740 G
+29.2170740 30.7612010 A:min
+30.7612010 31.5622900 F:maj7
+31.5622900 32.2937180 F:maj6
+32.2937180 33.9307250 C
+33.9307250 35.5909520 G
+35.5909520 37.1699090 F
+37.1699090 37.9826070 C
+37.9826070 38.7836960 C/7
+38.7836960 40.4903620 A:min
+40.4903620 42.1157590 E:min/b3
+42.1157590 43.7527660 F
+43.7527660 45.4246030 C
+45.4246030 47.0848290 C
+47.0848290 48.7218360 G
+48.7218360 50.3124030 F
+50.3124030 52.0074600 C
+52.0074600 53.6328570 C
+53.6328570 55.2234240 G
+55.2234240 56.8256000 A:min
+56.8256000 57.6034690 F:maj7
+57.6034690 58.4393870 F:maj6
+58.4393870 60.0647840 C
+60.0647840 61.7714510 G
+61.7714510 63.3736280 F
+63.3736280 65.0106340 C
+65.0106340 66.6592510 C
+66.6592510 68.2962580 G
+68.2962580 69.9797050 A:min
+69.9797050 70.8504530 F:maj7
+70.8504530 71.6283210 F:maj6
+71.6283210 73.3349880 C
+73.3349880 75.0300450 G
+75.0300450 76.7483210 F
+76.7483210 78.3853280 C
+78.3853280 80.2080950 A:min
+80.2080950 81.8915410 E:min/b3
+81.8915410 83.5285480 F
+83.5285480 85.2003850 C
+85.2003850 86.9186620 C
+86.9186620 88.5440580 G
+88.5440580 90.2158950 F
+90.2158950 91.8180720 C
+91.8180720 93.5131290 A:min
+93.5131290 95.1849650 E:min/b3
+95.1849650 96.8335820 F
+96.8335820 98.5402490 C
+98.5402490 100.2004760 C
+100.2004760 101.8490920 G
+101.8490920 103.5209290 F
+103.5209290 105.1927660 C
+105.1927660 106.9342630 F
+106.9342630 108.6641490 C
+108.6641490 109.4768480 G
+109.4768480 110.3824260 F
+110.3824260 112.1587520 C
+112.1587520 113.9699090 F
+113.9699090 115.6881850 C
+115.6881850 116.4892740 G
+116.4892740 117.3600220 F
+117.3600220 119.1479590 C
+119.1479590 120.8314050 C
+120.8314050 122.5845120 G
+122.5845120 124.2911790 A:min
+124.2911790 126.0791150 F
+126.0791150 127.7393420 C
+127.7393420 129.4460090 G
+129.4460090 131.1410650 F
+131.1410650 132.9173920 C
+132.9173920 134.6588880 C
+134.6588880 136.3655550 G
+136.3655550 138.1186620 A:min
+138.1186620 139.8485480 F
+139.8485480 141.5319950 C
+141.5319950 143.2154420 G
+143.2154420 144.9453280 F
+144.9453280 146.6519950 C
+146.6519950 148.4399310 A:min
+148.4399310 150.2162580 E:min/b3
+150.2162580 151.9809750 F
+151.9809750 153.7921310 C
+153.7921310 155.5452380 C
+155.5452380 157.3331740 G
+157.3331740 159.0862810 F
+159.0862810 160.8742170 C
+160.8742170 162.6505440 C
+162.6505440 164.3804300 G
+164.3804300 166.1335370 A:min
+166.1335370 166.9850938 F:maj7
+166.9850938 167.8982530 F:maj6
+167.8982530 169.5933100 C
+169.5933100 171.3115870 G
+171.3115870 173.0414730 F
+173.0414730 174.7945800 C
+174.7945800 176.5825170 C
+176.5825170 178.2659630 G
+178.2659630 180.0422900 A:min
+180.0422900 180.9130380 F:maj7
+180.9130380 181.7257360 F:maj6
+181.7257360 183.4672330 C
+183.4672330 185.2203400 G
+185.2203400 186.9618360 F
+186.9618360 188.6452830 C
+188.6452830 190.3635600 A:min
+190.3635600 192.1514960 E:min/b3
+192.1514960 193.8697730 F
+193.8697730 195.6809290 C
+195.6809290 197.4108160 C
+197.4108160 199.0826530 G
+199.0826530 200.8473690 F
+200.8473690 202.5540360 C
+202.5540360 204.2723120 A:min
+204.2723120 206.0486390 E:min/b3
+206.0486390 207.7901360 F
+207.7901360 209.5316320 C
+209.5316320 211.2731290 C
+211.2731290 213.0146250 G
+213.0146250 214.7445120 F
+214.7445120 216.4976190 C
+216.4976190 218.1810650 A:min
+218.1810650 219.9690020 E:min/b3
+219.9690020 221.7337180 F
+221.7337180 223.4752150 C
+223.4752150 225.1934920 C
+225.1934920 226.9698180 G
+226.9698180 228.7113150 F
+228.7113150 230.5340810 C
+230.5340810 232.3800680 F
+232.3800680 234.2260540 C
+234.2260540 235.1548520 G
+235.1548520 236.3390700 F
+236.3390700 241.0072816 C
+241.0072816 243.2822359 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/07_-_Maggie_Mae.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+0.0000000 0.3446570 N
+0.3446570 3.1178450 G
+3.1178450 5.7997500 C
+5.7997500 11.3377090 G
+11.3377090 14.1589340 D
+14.1589340 17.0033780 G
+17.0033780 19.8478230 C
+19.8478230 21.2642400 D/5
+21.2642400 22.6806570 D
+22.6806570 25.5831510 G
+25.5831510 28.4972560 C
+28.4972560 34.1977550 G
+34.1977550 38.0845987 D
+38.0845987 40.6012595 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/08_-_I've_Got_A_Feeling.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,150 @@
+0.0000000 0.4212474 N
+0.4212474 1.9220180 A
+1.9220180 3.3384350 D/5
+3.3384350 4.8245120 A
+4.8245120 6.2060990 D/5
+6.2060990 7.7037860 A
+7.7037860 9.2246930 D/5
+9.2246930 10.6875510 A
+10.6875510 12.1620180 D/5
+12.1620180 13.5900450 A
+13.5900450 15.0645120 D/5
+15.0645120 16.5273690 A
+16.5273690 17.9437860 D/5
+17.9437860 19.4414730 A
+19.4414730 20.9043310 D/5
+20.9043310 22.3671880 A
+22.3671880 23.8764850 D/5
+23.8764850 25.3509520 A
+25.3509520 26.8138090 D/5
+26.8138090 28.2650560 A
+28.2650560 29.6582530 D/5
+29.6582530 32.6071880 A:7
+32.6071880 33.3270060 E
+33.3270060 34.0584350 G
+34.0584350 35.5329020 D
+35.5329020 37.0305890 A
+37.0305890 38.4470060 D
+38.4470060 39.9214730 A
+39.9214730 41.3146710 D
+41.3146710 42.8471880 A
+42.8471880 44.2984350 D/5
+44.2984350 45.7032420 A
+45.7032420 47.2357590 D/5
+47.2357590 48.6289560 A
+48.6289560 50.0802040 D/5
+50.0802040 51.5430610 A
+51.5430610 52.9594780 D/5
+52.9594780 54.4455550 A
+54.4455550 55.8503620 D/5
+55.8503620 57.2551700 A
+57.2551700 58.7528570 D/5
+58.7528570 60.1808840 A
+60.1808840 61.5856910 D/5
+61.5856910 63.0021080 A
+63.0021080 64.3836960 D/5
+64.3836960 67.2978000 A:7
+67.2978000 67.9943990 E
+67.9943990 68.7258270 G
+68.7258270 70.2119040 D
+70.2119040 71.6283210 A
+71.6283210 73.0679590 D
+73.0679590 74.4959860 A
+74.4959860 75.9356230 D
+75.9356230 78.8497270 E
+78.8497270 81.7406120 G
+81.7406120 82.4604300 D
+82.4604300 83.1802490 D/3
+83.1802490 83.9116780 G
+83.9116780 84.6198860 G#:dim7
+84.6198860 90.5177550 A
+90.5177550 92.0270520 A
+92.0270520 93.4318590 D/5
+93.4318590 94.8831060 A
+94.8831060 96.3459630 D/5
+96.3459630 97.7856000 A
+97.7856000 99.2252380 D/5
+99.2252380 100.6764850 A
+100.6764850 102.0812920 D/5
+102.0812920 103.5209290 A
+103.5209290 104.9953960 D/5
+104.9953960 106.4466430 A
+106.4466430 107.8978910 D/5
+107.8978910 109.3375280 A
+109.3375280 110.7771650 D/5
+110.7771650 112.2051920 A
+112.2051920 113.5635600 D/5
+113.5635600 116.5241040 A:7
+116.5241040 117.2555320 E
+117.2555320 117.9521310 G
+117.9521310 119.4382080 D
+119.4382080 120.8894550 A
+120.8894550 122.2826530 D
+122.2826530 123.7455100 A
+123.7455100 125.1619270 D
+125.1619270 126.6247840 A
+126.6247840 128.0644210 D
+128.0644210 129.5504980 A
+129.5504980 130.9785260 D
+130.9785260 132.4413830 A
+132.4413830 133.8461900 D
+133.8461900 135.2858270 A
+135.2858270 136.6790240 D
+136.6790240 138.1534920 A
+138.1534920 139.5699090 D
+139.5699090 141.0327660 A
+141.0327660 142.4027430 D
+142.4027430 143.8656000 A
+143.8656000 145.2936280 D
+145.2936280 146.7216550 A
+146.7216550 148.2193420 D
+148.2193420 149.6473690 A
+149.6473690 151.0986160 D
+151.0986160 152.5846930 A
+152.5846930 154.0243310 D
+154.0243310 155.4407480 A:7
+155.4407480 156.1605660 A:dim7
+156.1605660 156.8339450 B:hdim7/b7
+156.8339450 158.2851920 A
+158.2851920 158.9934010 B:hdim7/b7
+158.9934010 159.7132190 A:dim7
+159.7132190 161.1876870 A:7
+161.1876870 162.5924940 D/5
+162.5924940 164.0089110 A
+164.0089110 165.4717680 D/5
+165.4717680 166.9230150 A
+166.9230150 168.4090920 D/5
+168.4090920 169.8719500 A
+169.8719500 171.3464170 D/5
+171.3464170 172.7628340 A
+172.7628340 174.2241143 D
+174.2241143 175.6653280 A
+175.6653280 177.1049650 D
+177.1049650 178.5562130 A
+178.5562130 180.0074600 D/5
+180.0074600 181.4238770 A
+181.4238770 182.8751240 D/5
+182.8751240 184.3263710 A
+184.3263710 185.7776190 D
+185.7776190 187.1940360 A
+187.1940360 188.6104530 D
+188.6104530 190.0500900 A
+190.0500900 190.7582990 A:dim7
+190.7582990 191.4432870 B:hdim7/b7
+191.4432870 192.9061450 A:7
+192.9061450 193.6027430 A:dim7
+193.6027430 194.3690020 B:hdim7/b7
+194.3690020 195.7505890 A:7
+195.7505890 196.4355780 B:hdim7/b7
+196.4355780 197.1321760 A:dim7
+197.1321760 198.5834240 A:7
+198.5834240 199.2335820 A:dim7
+199.2335820 199.9766210 B:hdim7/b7
+199.9766210 201.3582080 A:7
+201.3582080 202.0431970 B:hdim7/b7
+202.0431970 202.7630150 A:dim7
+202.7630150 204.1562130 A:7
+204.1562130 204.8528110 A:dim7
+204.8528110 205.5494100 B:hdim7/b7
+205.5494100 208.8091711 A:7
+208.8091711 217.9276030 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/09_-_One_After_909.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+0.000000 0.433805 N
+0.433805 1.421269 B:(b3,5)
+1.421269 9.107074 B
+9.107074 19.602494 B
+19.602494 22.168299 B
+22.168299 24.838594 E
+24.838594 26.162131 B
+26.162131 27.450839 F#
+27.450839 30.028253 B
+30.028253 40.546893 B
+40.546893 43.252018 B
+43.252018 45.875873 E
+45.875873 47.211020 B
+47.211020 48.488117 F#
+48.488117 51.111972 B
+51.111972 53.747437 E
+53.747437 56.394512 B
+56.394512 59.041587 C#
+59.041587 61.688662 F#
+61.688662 64.370566 E
+64.370566 66.994421 B
+66.994421 69.560226 C#
+69.560226 70.906984 F#
+70.906984 72.218911 F#:aug
+72.218911 82.749160 B
+82.749160 85.431065 B
+85.431065 87.985260 E
+87.985260 89.285578 B
+89.285578 90.597505 F#
+90.597505 93.128480 B
+93.128480 106.247755 B
+106.247755 108.883219 E
+108.883219 110.218367 B
+110.218367 111.530294 F#
+111.530294 114.130929 B
+114.130929 116.778004 E
+116.778004 119.436689 B
+119.436689 122.118594 C#
+122.118594 124.754058 F#
+124.754058 127.389523 E
+127.389523 130.106258 B
+130.106258 132.706893 C#
+132.706893 135.330748 F#:aug
+135.330748 146.058367 B
+146.058367 148.635782 B
+148.635782 151.259637 E
+151.259637 152.583174 B
+152.583174 153.929931 F#
+153.929931 155.218639 B
+155.218639 156.565396 F#
+156.565396 157.900544 B
+157.900544 159.154421 F#
+159.154421 161.101410 B
+161.101410 161.580907 F#:aug
+161.580907 164.969228 B
+164.969228 169.468916 E
+169.468916 175.519561 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/10_-_The_Long_and_Winding_Road.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,97 @@
+0.0000000 0.3829522 N
+0.3829522 3.7384350 C:min
+3.7384350 4.5163030 Ab
+4.5163030 7.6045570 Ab:maj(2)/2
+7.6045570 9.4273240 Eb
+9.4273240 11.1456000 Eb:7/b7
+11.1456000 14.6750340 Ab
+14.6750340 16.3700900 Ab
+16.3700900 18.1464170 G:min
+18.1464170 21.6990700 C:min
+21.6990700 23.4289560 F:min7
+23.4289560 25.2517230 Bb
+25.2517230 28.9553060 Eb:7
+28.9553060 30.7316320 Ab
+30.7316320 32.4847390 G:min
+32.4847390 36.0606120 C:min
+36.0606120 37.8485480 F:min
+37.8485480 39.7641950 Bb
+39.7641950 43.3632870 Eb
+43.3632870 46.4712524 C:min
+46.4712524 47.2990700 Ab
+47.2990700 50.4221540 Ab:maj(2)/2
+50.4221540 52.3145800 Eb
+52.3145800 54.2186160 Eb:7/b7
+54.2186160 57.7248290 Ab
+57.7248290 59.5011560 Ab
+59.5011560 61.3819720 G:min
+61.3819720 64.9926750 C:min
+64.9926750 66.8270520 F:min7
+66.8270520 68.6382080 Bb
+68.6382080 72.2140810 Eb:7
+72.2140810 74.0368480 Ab
+74.0368480 75.8828340 G:min
+75.8828340 79.5399770 C:min
+79.5399770 81.3975730 F:min
+81.3975730 83.2667800 Bb
+83.2667800 86.9239220 Eb
+86.9239220 88.7350790 Eb/5
+88.7350790 90.5810650 Ab
+90.5810650 92.3225620 Eb/3
+92.3225620 93.1817000 F:min
+93.1817000 94.1104980 Bb
+94.1104980 95.9100450 Eb/5
+95.9100450 97.7095910 Ab
+97.7095910 99.4975280 Eb/3
+99.4975280 100.3798860 F:min
+100.3798860 101.2506340 Bb
+101.2506340 104.4885143 C:min
+104.4885143 105.3489560 Ab
+105.3489560 108.4139900 Ab:maj(2)/2
+108.4139900 110.2715870 Eb
+110.2715870 112.0363030 Eb:7
+112.0363030 115.6121760 Ab
+115.6121760 117.4465530 Ab
+117.4465530 119.2228790 G:min
+119.2228790 122.8451920 C:min
+122.8451920 124.7027890 F:min7
+124.7027890 126.5719950 Bb
+126.5719950 130.3104080 Eb:7
+130.3104080 132.1563940 Ab
+132.1563940 133.9675510 G:min
+133.9675510 137.6943530 C:min
+137.6943530 139.4939000 F:min
+139.4939000 141.3747160 Bb
+141.3747160 145.0550790 Eb
+145.0550790 146.8778450 Eb/5
+146.8778450 148.6309520 Ab
+148.6309520 150.4769380 Eb/3
+150.4769380 151.3592970 F:min
+151.3592970 152.2532650 Bb
+152.2532650 154.0063710 Eb/5
+154.0063710 155.8291380 Ab
+155.8291380 157.6170740 Eb/3
+157.6170740 158.4878230 F:min
+158.4878230 159.3585710 Bb
+159.3585710 162.5513150 C:min
+162.5513150 163.3988430 Ab
+163.3988430 166.5103170 Ab:maj(2)/2
+166.5103170 168.3330830 Eb
+168.3330830 170.2371200 Eb:7/b7
+170.2371200 173.8594330 Ab
+173.8594330 175.6821990 Ab
+175.6821990 177.5397950 G:min
+177.5397950 181.2201580 C:min
+181.2201580 183.0197050 F:min7
+183.0197050 184.9121310 Bb
+184.9121310 188.4299540 Eb:7
+188.4299540 190.3688200 Ab
+190.3688200 192.0638770 G:min
+192.0638770 195.8022900 C:min
+195.8022900 197.6714960 F:min
+197.6714960 199.4942630 Bb
+199.4942630 202.7682760 Eb
+202.7682760 203.5925850 Ab/5
+203.5925850 206.9362580 Ab:maj(2)/2
+206.9362580 215.8701686 Eb
+215.8701686 217.8615202 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/11_-_For_You_Blue.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,62 @@
+0.0000000 3.3699796 N
+3.3699796 4.3850340 A
+4.3850340 6.1845800 D
+6.1845800 7.9492970 G:7/3
+7.9492970 9.7604530 E:7
+9.7604530 13.4408160 A:7
+13.4408160 15.2519720 D
+15.2519720 17.1754072 G:7
+17.1754072 20.8247610 D
+20.8247610 24.5747840 G:7
+24.5747840 28.3131970 D
+28.3131970 30.1707930 A
+30.1707930 32.0748290 G:7
+32.0748290 33.9788660 D
+33.9788660 35.8132420 A
+35.8132420 37.7056680 D
+37.7056680 39.5400450 G:7
+39.5400450 43.2668480 D
+43.2668480 47.0400900 G:7
+47.0400900 50.7668930 D
+50.7668930 52.6128790 A
+52.6128790 54.4704760 G:7
+54.4704760 56.7152244 D
+56.7152244 58.2553280 A
+58.2553280 60.1129250 D
+60.1129250 62.0053510 G:7
+62.0053510 65.6973240 D
+65.6973240 69.4241260 G:7
+69.4241260 73.1160990 D
+73.1160990 75.0777835 A
+75.0777835 76.8661220 G:7
+76.8661220 78.7121080 D
+78.7121080 80.5813150 A
+80.5813150 82.4621310 D
+82.4621310 84.4409654 G:7
+84.4409654 88.0813600 D
+88.0813600 91.8197730 G:7
+91.8197730 95.5581850 D
+95.5581850 99.2965980 A
+99.2965980 101.1376823 D
+101.1376823 102.9885710 A
+102.9885710 104.8906141 D
+104.8906141 106.6921540 G:7
+106.6921540 110.4537860 D
+110.4537860 114.1689790 G:7
+114.1689790 117.9073920 D
+117.9073920 119.7533780 A
+119.7533780 121.5993650 G:7
+121.5993650 123.4829446 D
+123.4829446 125.3029470 A
+125.3029470 127.1837640 D
+127.1837640 129.0994100 G:7
+129.0994100 132.7913830 D
+132.7913830 136.5990583 G:7
+136.5990583 140.3136948 D
+140.3136948 142.1374140 A
+142.1374140 144.0530610 G:7
+144.0530610 145.0048596 D
+145.0048596 145.9430925 G
+145.9430925 146.7664398 A:aug
+146.7664398 149.4471054 D
+149.4471054 152.6639041 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/12_-_Get_Back.lab	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,84 @@
+0.0000000 0.4020998 N
+0.4020998 1.9147611 A:(1)
+1.9147611 11.4119763 N
+11.4119763 13.3267374 A:7
+13.3267374 17.2711453 N
+17.2711453 20.6985677 G:(1,5)
+20.6985677 27.4755780 A
+27.4755780 27.9631970 G/2
+27.9631970 28.4508160 D/5
+28.4508160 32.3517680 A
+32.3517680 34.2906340 D
+34.2906340 36.2295010 A
+36.2295010 40.0956230 A
+40.0956230 42.0112690 D
+42.0112690 43.9269160 A
+43.9269160 47.8046480 A:7
+47.8046480 49.7551240 D
+49.7551240 50.7651920 A
+50.7651920 51.2063710 G/2
+51.2063710 51.6939900 D/5
+51.6939900 55.5485030 A
+55.5485030 57.4757590 D
+57.4757590 59.3681850 A
+59.3681850 63.3504080 A
+63.3504080 65.2660540 D
+65.2660540 66.2761220 A
+66.2761220 66.7637410 G
+66.7637410 67.2397500 D
+67.2397500 71.0942630 A
+71.0942630 73.0215190 D
+73.0215190 74.0083670 A
+74.0083670 74.4843760 G/2
+74.4843760 74.9952150 D/5
+74.9952150 78.8845570 A:min7
+78.8845570 80.8002040 D
+80.8002040 81.7638320 A
+81.7638320 82.2978910 G/2
+82.2978910 82.7622900 D/5
+82.7622900 88.4279590 A:7
+88.4279590 92.6191600 D
+92.6191600 96.4968930 A
+96.4968930 98.4125390 D
+98.4125390 99.4458270 A
+99.4458270 99.9450560 G/2
+99.9450560 100.4326750 D/5
+100.4326750 104.2871880 A
+104.2871880 106.2608840 D
+106.2608840 107.2593420 A
+107.2593420 107.7469610 G/2
+107.7469610 108.2461900 D/5
+108.2461900 112.1935820 A
+112.1935820 114.1788880 D
+114.1788880 116.1177550 A
+116.1177550 120.0535370 A
+120.0535370 122.0040130 D
+122.0040130 122.9676410 A
+122.9676410 123.9428790 G/2
+123.9428790 127.8438320 A:7
+127.8438320 129.8059180 D
+129.8059180 130.7927660 A
+130.7927660 131.2455550 G/2
+131.2455550 131.7563940 D/5
+131.7563940 135.6225170 A:7
+135.6225170 137.5497730 D
+137.5497730 139.4770290 A
+139.4770290 143.3083210 A
+143.3083210 145.2587980 D
+145.2587980 146.2456460 A
+146.2456460 146.7332650 G/2
+146.7332650 147.2441040 D/5
+147.2441040 151.1102260 A
+151.1102260 153.0607020 D
+153.0607020 154.0243310 A
+154.0243310 154.5235600 G/2
+154.5235600 155.0227890 D/5
+155.0227890 158.8540810 A:7
+158.8540810 160.7813370 D
+160.7813370 161.4895460 A
+161.4895460 162.1745350 G/2
+162.1745350 162.6969840 D/5
+162.6969840 166.4237860 A:7
+166.4237860 168.1926168 D
+168.1926168 174.2815571 D:7
+174.2815571 186.9189805 N
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+/01_-_Two_of_Us.lab/1.1/Sun Jul 23 18:26:12 2006//
+/02_-_Dig_a_Pony.lab/1.3/Tue Oct 17 21:59:32 2006//
+/03_-_Across_the_Universe.lab/1.3/Tue Oct 17 21:59:32 2006//
+/04_-_I_Me_Mine.lab/1.1/Sun Jul 23 18:26:12 2006//
+/05_-_Dig_It.lab/1.1/Sun Jul 23 18:26:12 2006//
+/06_-_Let_It_Be.lab/1.1/Sun Jul 23 18:26:12 2006//
+/07_-_Maggie_Mae.lab/1.1/Sun Jul 23 18:26:12 2006//
+/08_-_I've_Got_A_Feeling.lab/1.1/Sun Jul 23 18:26:12 2006//
+/09_-_One_After_909.lab/1.2/Wed Aug  2 12:22:35 2006//
+/10_-_The_Long_and_Winding_Road.lab/1.2/Wed Aug  2 12:22:35 2006//
+/11_-_For_You_Blue.lab/1.2/Tue Oct 17 21:59:32 2006//
+/12_-_Get_Back.lab/1.2/Wed Aug  2 12:22:35 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions/12final
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/12final/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+A D/01final////
+A D/02final////
+A D/03final////
+A D/04final////
+A D/05final////
+A D/06final////
+A D/07final////
+A D/08final////
+A D/09final////
+A D/10CD1final////
+A D/10CD2final////
+A D/11final////
+A D/12final////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/transcriptions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/transcriptions/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/01_-_I_Saw_Her_Standing_There.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/02_-_Misery.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+434
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/03_-_Anna_(Go_To_Him).tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+430
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/04_-_Chains.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+430
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/05_-_Boys.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+430
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/06_-_Ask_Me_Why.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/07_-_Please_Please_Me.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/08_-_Love_Me_Do.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/09_-_P._S._I_Love_You.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/10_-_Baby_It's_You.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/11_-_Do_You_Want_To_Know_A_Secret.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+431
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/12_-_A_Taste_Of_Honey.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+435
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/13_-_There's_A_Place.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/14_-_Twist_And_Shout.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+/01_-_I_Saw_Her_Standing_There.tun/1.1/Tue Aug 15 13:12:44 2006//
+/02_-_Misery.tun/1.1/Tue Aug 15 13:12:44 2006//
+/03_-_Anna_(Go_To_Him).tun/1.1/Tue Aug 15 13:12:44 2006//
+/04_-_Chains.tun/1.1/Tue Aug 15 13:12:44 2006//
+/05_-_Boys.tun/1.1/Tue Aug 15 13:12:44 2006//
+/06_-_Ask_Me_Why.tun/1.1/Tue Aug 15 13:12:44 2006//
+/07_-_Please_Please_Me.tun/1.1/Tue Aug 15 13:12:44 2006//
+/08_-_Love_Me_Do.tun/1.1/Tue Aug 15 13:12:44 2006//
+/09_-_P._S._I_Love_You.tun/1.1/Tue Aug 15 13:12:44 2006//
+/10_-_Baby_It's_You.tun/1.1/Tue Aug 15 13:12:44 2006//
+/11_-_Do_You_Want_To_Know_A_Secret.tun/1.1/Tue Aug 15 13:12:44 2006//
+/12_-_A_Taste_Of_Honey.tun/1.1/Tue Aug 15 13:12:44 2006//
+/13_-_There's_A_Place.tun/1.1/Tue Aug 15 13:12:44 2006//
+/14_-_Twist_And_Shout.tun/1.1/Tue Aug 15 13:12:44 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/01tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/01tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/01_-_It_Won't_Be_Long.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/02_-_All_I've_Got_To_Do.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/03_-_All_My_Loving.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/04_-_Don't_Bother_Me.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/05_-_Little_Child.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/06_-_Till_There_Was_You.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/07_-_Please_Mister_Postman.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/08_-_Roll_Over_Beethoven.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+437
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/09_-_Hold_Me_Tight.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/10_-_You_Really_Got_A_Hold_On_Me.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/11_-_I_Wanna_Be_Your_Man.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/12_-_Devil_In_Her_Heart.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/13_-_Not_A_Second_Time.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/14_-_Money.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+/01_-_It_Won't_Be_Long.tun/1.1/Tue Aug 15 13:13:47 2006//
+/02_-_All_I've_Got_To_Do.tun/1.1/Tue Aug 15 13:13:47 2006//
+/03_-_All_My_Loving.tun/1.1/Tue Aug 15 13:13:47 2006//
+/04_-_Don't_Bother_Me.tun/1.1/Tue Aug 15 13:13:47 2006//
+/05_-_Little_Child.tun/1.1/Tue Aug 15 13:13:47 2006//
+/06_-_Till_There_Was_You.tun/1.1/Tue Aug 15 13:13:47 2006//
+/07_-_Please_Mister_Postman.tun/1.1/Tue Aug 15 13:13:47 2006//
+/08_-_Roll_Over_Beethoven.tun/1.1/Tue Aug 15 13:13:47 2006//
+/09_-_Hold_Me_Tight.tun/1.1/Tue Aug 15 13:13:47 2006//
+/10_-_You_Really_Got_A_Hold_On_Me.tun/1.1/Tue Aug 15 13:13:47 2006//
+/11_-_I_Wanna_Be_Your_Man.tun/1.1/Tue Aug 15 13:13:47 2006//
+/12_-_Devil_In_Her_Heart.tun/1.1/Tue Aug 15 13:13:47 2006//
+/13_-_Not_A_Second_Time.tun/1.1/Tue Aug 15 13:13:47 2006//
+/14_-_Money.tun/1.1/Tue Aug 15 13:13:47 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/02tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/02tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/01_-_A_Hard_Day's_Night.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/02_-_I_Should_Have_Known_Better.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/03_-_If_I_Fell.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/04_-_I'm_Happy_Just_To_Dance_With_You.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/05_-_And_I_Love_Her.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/06_-_Tell_Me_Why.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/07_-_Can't_Buy_Me_Love.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/08_-_Any_Time_At_All.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/09_-_I'll_Cry_Instead.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/10_-_Things_We_Said_Today.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/11_-_When_I_Get_Home.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/12_-_You_Can't_Do_That.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/13_-_I'll_Be_Back.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+/01_-_A_Hard_Day's_Night.tun/1.1/Tue Aug 15 13:14:26 2006//
+/02_-_I_Should_Have_Known_Better.tun/1.1/Tue Aug 15 13:14:26 2006//
+/03_-_If_I_Fell.tun/1.1/Tue Aug 15 13:14:26 2006//
+/04_-_I'm_Happy_Just_To_Dance_With_You.tun/1.1/Tue Aug 15 13:14:26 2006//
+/05_-_And_I_Love_Her.tun/1.1/Tue Aug 15 13:14:26 2006//
+/06_-_Tell_Me_Why.tun/1.1/Tue Aug 15 13:14:26 2006//
+/07_-_Can't_Buy_Me_Love.tun/1.1/Tue Aug 15 13:14:26 2006//
+/08_-_Any_Time_At_All.tun/1.1/Tue Aug 15 13:14:26 2006//
+/09_-_I'll_Cry_Instead.tun/1.1/Tue Aug 15 13:14:26 2006//
+/10_-_Things_We_Said_Today.tun/1.1/Tue Aug 15 13:14:26 2006//
+/11_-_When_I_Get_Home.tun/1.1/Tue Aug 15 13:14:26 2006//
+/12_-_You_Can't_Do_That.tun/1.1/Tue Aug 15 13:14:26 2006//
+/13_-_I'll_Be_Back.tun/1.1/Tue Aug 15 13:14:26 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/03tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/03tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/01_-_No_Reply.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/02_-_I'm_a_Loser.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/03_-_Baby's_In_Black.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/04_-_Rock_and_Roll_Music.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/05_-_I'll_Follow_the_Sun.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/06_-_Mr._Moonlight.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/07_-_Kansas_City-_Hey,_Hey,_Hey,_Hey.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/08_-_Eight_Days_a_Week.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/09_-_Words_of_Love.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+441
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/10_-_Honey_Don't.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/11_-_Every_Little_Thing.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/12_-_I_Don't_Want_to_Spoil_the_Party.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/13_-_What_You're_Doing.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/14_-_Everybody's_Trying_to_Be_My_Baby.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+/01_-_No_Reply.tun/1.1/Tue Aug 15 13:15:08 2006//
+/02_-_I'm_a_Loser.tun/1.1/Tue Aug 15 13:15:08 2006//
+/03_-_Baby's_In_Black.tun/1.1/Tue Aug 15 13:15:08 2006//
+/04_-_Rock_and_Roll_Music.tun/1.1/Tue Aug 15 13:15:08 2006//
+/05_-_I'll_Follow_the_Sun.tun/1.1/Tue Aug 15 13:15:08 2006//
+/06_-_Mr._Moonlight.tun/1.1/Tue Aug 15 13:15:08 2006//
+/07_-_Kansas_City-_Hey,_Hey,_Hey,_Hey.tun/1.1/Tue Aug 15 13:15:08 2006//
+/08_-_Eight_Days_a_Week.tun/1.1/Tue Aug 15 13:15:08 2006//
+/09_-_Words_of_Love.tun/1.1/Tue Aug 15 13:15:08 2006//
+/10_-_Honey_Don't.tun/1.1/Tue Aug 15 13:15:08 2006//
+/11_-_Every_Little_Thing.tun/1.1/Tue Aug 15 13:15:08 2006//
+/12_-_I_Don't_Want_to_Spoil_the_Party.tun/1.1/Tue Aug 15 13:15:08 2006//
+/13_-_What_You're_Doing.tun/1.1/Tue Aug 15 13:15:08 2006//
+/14_-_Everybody's_Trying_to_Be_My_Baby.tun/1.1/Tue Aug 15 13:15:08 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/04tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/04tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/01_-_Help!.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/02_-_The_Night_Before.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/03_-_You've_Got_To_Hide_Your_Love_Away.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+434
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/04_-_I_Need_You.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+428
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/05_-_Another_Girl.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+431
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/06_-_You're_Going_to_Lose_That_Girl.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+434
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/07_-_Ticket_To_Ride.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+430
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/08_-_Act_Naturally.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+441
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/09_-_It's_Only_Love.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+435
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/10_-_You_Like_Me_Too_Much.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+435
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/11_-_Tell_Me_What_You_See.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+435
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/12_-_I've_Just_Seen_a_Face.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+435
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/13_-_Yesterday.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/14_-_Dizzy_Miss_Lizzie.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+/01_-_Help!.tun/1.1/Tue Aug 15 13:16:00 2006//
+/02_-_The_Night_Before.tun/1.1/Tue Aug 15 13:16:00 2006//
+/03_-_You've_Got_To_Hide_Your_Love_Away.tun/1.1/Tue Aug 15 13:16:00 2006//
+/04_-_I_Need_You.tun/1.1/Tue Aug 15 13:16:00 2006//
+/05_-_Another_Girl.tun/1.1/Tue Aug 15 13:16:00 2006//
+/06_-_You're_Going_to_Lose_That_Girl.tun/1.1/Tue Aug 15 13:16:00 2006//
+/07_-_Ticket_To_Ride.tun/1.1/Tue Aug 15 13:16:00 2006//
+/08_-_Act_Naturally.tun/1.1/Tue Aug 15 13:16:00 2006//
+/09_-_It's_Only_Love.tun/1.1/Tue Aug 15 13:16:00 2006//
+/10_-_You_Like_Me_Too_Much.tun/1.1/Tue Aug 15 13:16:00 2006//
+/11_-_Tell_Me_What_You_See.tun/1.1/Tue Aug 15 13:16:00 2006//
+/12_-_I've_Just_Seen_a_Face.tun/1.1/Tue Aug 15 13:16:00 2006//
+/13_-_Yesterday.tun/1.1/Tue Aug 15 13:16:00 2006//
+/14_-_Dizzy_Miss_Lizzie.tun/1.1/Tue Aug 15 13:16:00 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/05tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/05tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/01_-_Drive_My_Car.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/02_-_Norwegian_Wood_(This_Bird_Has_Flown).tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/03_-_You_Won't_See_Me.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/04_-_Nowhere_Man.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+433
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/05_-_Think_For_Yourself.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/06_-_The_Word.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/07_-_Michelle.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/08_-_What_Goes_On.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/09_-_Girl.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+437
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/10_-_I'm_Looking_Through_You.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/11_-_In_My_Life.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/12_-_Wait.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/13_-_If_I_Needed_Someone.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+441
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/14_-_Run_For_Your_Life.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+433
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+/01_-_Drive_My_Car.tun/1.1/Tue Aug 15 13:16:32 2006//
+/02_-_Norwegian_Wood_(This_Bird_Has_Flown).tun/1.1/Tue Aug 15 13:16:32 2006//
+/03_-_You_Won't_See_Me.tun/1.1/Tue Aug 15 13:16:32 2006//
+/04_-_Nowhere_Man.tun/1.1/Tue Aug 15 13:16:32 2006//
+/05_-_Think_For_Yourself.tun/1.1/Tue Aug 15 13:16:32 2006//
+/06_-_The_Word.tun/1.1/Tue Aug 15 13:16:32 2006//
+/07_-_Michelle.tun/1.1/Tue Aug 15 13:16:32 2006//
+/08_-_What_Goes_On.tun/1.1/Tue Aug 15 13:16:32 2006//
+/09_-_Girl.tun/1.1/Tue Aug 15 13:16:32 2006//
+/10_-_I'm_Looking_Through_You.tun/1.1/Tue Aug 15 13:16:32 2006//
+/11_-_In_My_Life.tun/1.1/Tue Aug 15 13:16:32 2006//
+/12_-_Wait.tun/1.1/Tue Aug 15 13:16:32 2006//
+/13_-_If_I_Needed_Someone.tun/1.1/Tue Aug 15 13:16:32 2006//
+/14_-_Run_For_Your_Life.tun/1.1/Tue Aug 15 13:16:32 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/06tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/06tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/01_-_Taxman.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+441
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/02_-_Eleanor_Rigby.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/03_-_I'm_Only_Sleeping.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+443
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/04_-_Love_You_To.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/05_-_Here,_There_And_Everywhere.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/06_-_Yellow_Submarine.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/07_-_She_Said_She_Said.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+443
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/08_-_Good_Day_Sunshine.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/09_-_And_Your_Bird_Can_Sing.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/10_-_For_No_One.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+443
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/11_-_Doctor_Robert.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/12_-_I_Want_To_Tell_You.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/13_-_Got_To_Get_You_Into_My_Life.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/14_-_Tomorrow_Never_Knows.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+/01_-_Taxman.tun/1.1/Tue Aug 15 13:17:14 2006//
+/02_-_Eleanor_Rigby.tun/1.1/Tue Aug 15 13:17:14 2006//
+/03_-_I'm_Only_Sleeping.tun/1.1/Tue Aug 15 13:17:14 2006//
+/04_-_Love_You_To.tun/1.1/Tue Aug 15 13:17:14 2006//
+/05_-_Here,_There_And_Everywhere.tun/1.1/Tue Aug 15 13:17:14 2006//
+/06_-_Yellow_Submarine.tun/1.1/Tue Aug 15 13:17:14 2006//
+/07_-_She_Said_She_Said.tun/1.1/Tue Aug 15 13:17:14 2006//
+/08_-_Good_Day_Sunshine.tun/1.1/Tue Aug 15 13:17:14 2006//
+/09_-_And_Your_Bird_Can_Sing.tun/1.1/Tue Aug 15 13:17:14 2006//
+/10_-_For_No_One.tun/1.1/Tue Aug 15 13:17:14 2006//
+/11_-_Doctor_Robert.tun/1.1/Tue Aug 15 13:17:14 2006//
+/12_-_I_Want_To_Tell_You.tun/1.1/Tue Aug 15 13:17:14 2006//
+/13_-_Got_To_Get_You_Into_My_Life.tun/1.1/Tue Aug 15 13:17:14 2006//
+/14_-_Tomorrow_Never_Knows.tun/1.1/Tue Aug 15 13:17:14 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/07tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/07tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/01_-_Sgt._Pepper's_Lonely_Hearts_Club_Band.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/02_-_With_A_Little_Help_From_My_Friends.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/03_-_Lucy_In_The_Sky_With_Diamonds.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/04_-_Getting_Better.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/05_-_Fixing_A_Hole.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/06_-_She's_Leaving_Home.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/07_-_Being_For_The_Benefit_Of_Mr._Kite!.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/08_-_Within_You_Without_You.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/09_-_When_I'm_Sixty-Four.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/10_-_Lovely_Rita.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+425
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/11_-_Good_Morning_Good_Morning.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/12_-_Sgt._Pepper's_Lonely_Hearts_Club_Band_(Reprise).tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/13_-_A_Day_In_The_Life.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+/01_-_Sgt._Pepper's_Lonely_Hearts_Club_Band.tun/1.1/Tue Aug 15 13:17:53 2006//
+/02_-_With_A_Little_Help_From_My_Friends.tun/1.1/Tue Aug 15 13:17:53 2006//
+/03_-_Lucy_In_The_Sky_With_Diamonds.tun/1.1/Tue Aug 15 13:17:53 2006//
+/04_-_Getting_Better.tun/1.1/Tue Aug 15 13:17:53 2006//
+/05_-_Fixing_A_Hole.tun/1.1/Tue Aug 15 13:17:53 2006//
+/06_-_She's_Leaving_Home.tun/1.1/Tue Aug 15 13:17:53 2006//
+/07_-_Being_For_The_Benefit_Of_Mr._Kite!.tun/1.1/Tue Aug 15 13:17:53 2006//
+/08_-_Within_You_Without_You.tun/1.1/Tue Aug 15 13:17:53 2006//
+/09_-_When_I'm_Sixty-Four.tun/1.1/Tue Aug 15 13:17:53 2006//
+/10_-_Lovely_Rita.tun/1.1/Tue Aug 15 13:17:53 2006//
+/11_-_Good_Morning_Good_Morning.tun/1.1/Tue Aug 15 13:17:53 2006//
+/12_-_Sgt._Pepper's_Lonely_Hearts_Club_Band_(Reprise).tun/1.1/Tue Aug 15 13:17:53 2006//
+/13_-_A_Day_In_The_Life.tun/1.1/Tue Aug 15 13:17:53 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/08tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/08tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/01_-_Magical_Mystery_Tour.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/02_-_The_Fool_On_The_Hill.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/03_-_Flying.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/04_-_Blue_Jay_Way.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/05_-_Your_Mother_Should_Know.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/06_-_I_Am_The_Walrus.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/07_-_Hello_Goodbye.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/08_-_Strawberry_Fields_Forever.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+431
+435
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/09_-_Penny_Lane.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/10_-_Baby_You're_A_Rich_Man.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/11_-_All_You_Need_Is_Love.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+428
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+/01_-_Magical_Mystery_Tour.tun/1.1/Tue Aug 15 13:18:16 2006//
+/02_-_The_Fool_On_The_Hill.tun/1.1/Tue Aug 15 13:18:16 2006//
+/03_-_Flying.tun/1.1/Tue Aug 15 13:18:16 2006//
+/04_-_Blue_Jay_Way.tun/1.1/Tue Aug 15 13:18:16 2006//
+/05_-_Your_Mother_Should_Know.tun/1.1/Tue Aug 15 13:18:16 2006//
+/06_-_I_Am_The_Walrus.tun/1.1/Tue Aug 15 13:18:16 2006//
+/07_-_Hello_Goodbye.tun/1.1/Tue Aug 15 13:18:16 2006//
+/08_-_Strawberry_Fields_Forever.tun/1.1/Tue Aug 15 13:18:16 2006//
+/09_-_Penny_Lane.tun/1.1/Tue Aug 15 13:18:16 2006//
+/10_-_Baby_You're_A_Rich_Man.tun/1.1/Tue Aug 15 13:18:16 2006//
+/11_-_All_You_Need_Is_Love.tun/1.1/Tue Aug 15 13:18:16 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/09tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/09tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_01_-_Back_in_the_USSR.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_02_-_Dear_Prudence.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_03_-_Glass_Onion.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+435
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_04_-_Ob-La-Di,_Ob-La-Da.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+443
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_05_-_Wild_Honey_Pie.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+426
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_06_-The_Continuing_Story_of_Bungalow_Bill.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_07_-_While_My_Guitar_Gently_Weeps.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_08_-_Happiness_is_a_Warm_Gun.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_09_-_Martha_My_Dear.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_10_-_I'm_So_Tired.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_11_-_Black_Bird.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+437
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_12_-_Piggies.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+435
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_13_-_Rocky_Raccoon.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+434
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_14_-_Don't_Pass_Me_By.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_15_-_Why_Don't_We_Do_It_In_The_Road.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+441
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_16_-_I_Will.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CD1_-_17_-_Julia.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+/CD1_-_01_-_Back_in_the_USSR.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_02_-_Dear_Prudence.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_03_-_Glass_Onion.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_04_-_Ob-La-Di,_Ob-La-Da.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_05_-_Wild_Honey_Pie.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_06_-The_Continuing_Story_of_Bungalow_Bill.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_07_-_While_My_Guitar_Gently_Weeps.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_08_-_Happiness_is_a_Warm_Gun.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_09_-_Martha_My_Dear.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_10_-_I'm_So_Tired.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_11_-_Black_Bird.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_12_-_Piggies.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_13_-_Rocky_Raccoon.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_14_-_Don't_Pass_Me_By.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_15_-_Why_Don't_We_Do_It_In_The_Road.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_16_-_I_Will.tun/1.1/Tue Aug 15 13:19:18 2006//
+/CD1_-_17_-_Julia.tun/1.1/Tue Aug 15 13:19:18 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/10CD1tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD1tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_01_-_Birthday.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+443
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_02_-_Yer_Blues.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_03_-_Mother_Nature's_Son.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+433
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_04_-_Everybody's_Got_Something_To_Hide_Except_Me_and_M.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_05_-_Sexy_Sadie.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_06_-_Helter_Skelter.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_07_-_Long_Long_Long.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+437
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_08_-_Revolution_1.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+436
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_09_-_Honey_Pie.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_10_-_Savoy_Truffle.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_11_-_Cry_Baby_Cry.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_12_-_Revolution_9.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CD2_-_13_-_Good_Night.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,14 @@
+/CD2_-_01_-_Birthday.tun/1.1/Tue Aug 15 13:20:03 2006//
+/CD2_-_02_-_Yer_Blues.tun/1.1/Tue Aug 15 13:20:03 2006//
+/CD2_-_03_-_Mother_Nature's_Son.tun/1.1/Tue Aug 15 13:20:03 2006//
+/CD2_-_04_-_Everybody's_Got_Something_To_Hide_Except_Me_and_M.tun/1.1/Tue Aug 15 13:20:03 2006//
+/CD2_-_05_-_Sexy_Sadie.tun/1.1/Tue Aug 15 13:20:03 2006//
+/CD2_-_06_-_Helter_Skelter.tun/1.1/Tue Aug 15 13:20:03 2006//
+/CD2_-_07_-_Long_Long_Long.tun/1.1/Tue Aug 15 13:20:03 2006//
+/CD2_-_08_-_Revolution_1.tun/1.1/Tue Aug 15 13:20:03 2006//
+/CD2_-_09_-_Honey_Pie.tun/1.1/Tue Aug 15 13:20:03 2006//
+/CD2_-_10_-_Savoy_Truffle.tun/1.1/Tue Aug 15 13:20:03 2006//
+/CD2_-_11_-_Cry_Baby_Cry.tun/1.1/Tue Aug 15 13:20:03 2006//
+/CD2_-_12_-_Revolution_9.tun/1.1/Tue Aug 15 13:20:03 2006//
+/CD2_-_13_-_Good_Night.tun/1.1/Tue Aug 15 13:20:03 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/10CD2tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/10CD2tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/01_-_Come_Together.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/02_-_Something.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/03_-_Maxwell's_Silver_Hammer.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+446
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/04_-_Oh!_Darling.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+435
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/05_-_Octopus's_Garden.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/06_-_I_Want_You.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/07_-_Here_Comes_The_Sun.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+446
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/08_-_Because.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/09_-_You_Never_Give_Me_Your_Money.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/10_-_Sun_King.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/11_-_Mean_Mr_Mustard.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/12_-_Polythene_Pam.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/13_-_She_Came_In_Through_The_Bathroom_Window.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/14_-_Golden_Slumbers.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/15_-_Carry_That_Weight.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/16_-_The_End.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+442
+451
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/17_-_Her_Majesty.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+443
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+/01_-_Come_Together.tun/1.1/Tue Aug 15 13:20:30 2006//
+/02_-_Something.tun/1.1/Tue Aug 15 13:20:30 2006//
+/03_-_Maxwell's_Silver_Hammer.tun/1.1/Tue Aug 15 13:20:30 2006//
+/04_-_Oh!_Darling.tun/1.1/Tue Aug 15 13:20:30 2006//
+/05_-_Octopus's_Garden.tun/1.1/Tue Aug 15 13:20:30 2006//
+/06_-_I_Want_You.tun/1.1/Tue Aug 15 13:20:30 2006//
+/07_-_Here_Comes_The_Sun.tun/1.1/Tue Aug 15 13:20:30 2006//
+/08_-_Because.tun/1.1/Tue Aug 15 13:20:30 2006//
+/09_-_You_Never_Give_Me_Your_Money.tun/1.1/Tue Aug 15 13:20:30 2006//
+/10_-_Sun_King.tun/1.1/Tue Aug 15 13:20:30 2006//
+/11_-_Mean_Mr_Mustard.tun/1.1/Tue Aug 15 13:20:30 2006//
+/12_-_Polythene_Pam.tun/1.1/Tue Aug 15 13:20:30 2006//
+/13_-_She_Came_In_Trough_The_Bathroom_Window.tun/1.1/Tue Aug 15 13:20:30 2006//
+/14_-_Golden_Slumbers.tun/1.1/Tue Aug 15 13:20:30 2006//
+/15_-_Carry_That_Weight.tun/1.1/Tue Aug 15 13:20:30 2006//
+/16_-_The_End.tun/1.1/Tue Aug 15 13:20:30 2006//
+/17_-_Her_Majesty.tun/1.1/Tue Aug 15 13:20:30 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/11tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/11tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/01_-_Two_of_Us.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/02_-_Dig_a_Pony.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/03_-_Across_the_Universe.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+446
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/04_-_I_Me_Mine.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/05_-_Dig_It.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/06_-_Let_It_Be.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+440
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/07_-_Maggie_Mae.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+438
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/08_-_I've_Got_A_Feeling.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+442
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/09_-_One_After_909.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+441
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/10_-_The_Long_and_Winding_Road.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/11_-_For_You_Blue.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+439
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/12_-_Get_Back.tun	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+441
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+/01_-_Two_of_Us.tun/1.1/Tue Aug 15 13:21:39 2006//
+/02_-_Dig_a_Pony.tun/1.1/Tue Aug 15 13:21:39 2006//
+/03_-_Across_the_Universe.tun/1.1/Tue Aug 15 13:21:39 2006//
+/04_-_I_Me_Mine.tun/1.1/Tue Aug 15 13:21:39 2006//
+/05_-_Dig_It.tun/1.1/Tue Aug 15 13:21:39 2006//
+/06_-_Let_It_Be.tun/1.1/Tue Aug 15 13:21:39 2006//
+/07_-_Maggie_Mae.tun/1.1/Tue Aug 15 13:21:39 2006//
+/08_-_I've_Got_A_Feeling.tun/1.1/Tue Aug 15 13:21:39 2006//
+/09_-_One_After_909.tun/1.1/Tue Aug 15 13:21:39 2006//
+/10_-_The_Long_and_Winding_Road.tun/1.1/Tue Aug 15 13:21:39 2006//
+/11_-_For_You_Blue.tun/1.1/Tue Aug 15 13:21:39 2006//
+/12_-_Get_Back.tun/1.1/Tue Aug 15 13:21:39 2006//
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning/12tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/12tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/CVS/Entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+D
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/CVS/Entries.Log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,13 @@
+A D/01tuning////
+A D/02tuning////
+A D/03tuning////
+A D/04tuning////
+A D/05tuning////
+A D/06tuning////
+A D/07tuning////
+A D/08tuning////
+A D/09tuning////
+A D/10CD1tuning////
+A D/10CD2tuning////
+A D/11tuning////
+A D/12tuning////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/CVS/Repository	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+chrish/tuning
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/tuning/CVS/Root	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,1 @@
+:ext:matthiasm@dspmac1.elec.qmul.ac.uk:/cvsroot
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chordtools/types.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,114 @@
+%
+%TYPES for C4DM Chord Toolkit
+% 
+% Help file on types, structures and enumerations used in chord symbol
+% toolbox
+% 
+%
+% *** STRING TYPES ***
+%
+%NATURAL
+% 
+% Character A|B|C|D|E|F|G
+% 
+% 
+%MODIFIER
+% 
+% Character b|#
+% 
+% 
+%NOTE
+% 
+% Character string containing one natural and optional modifiers. 
+% Modifiers may only occur after the natural. 
+% 
+% note = <natural> | <note> <modifier>
+% 
+%
+%INTERVAL
+% 
+% Character string containing digits 1|2|3|4|5|6|7|8|9|10|11|12|13
+% 
+% 
+%DEGREE
+% 
+% Character string containing one interval and optional modifiers.
+% Modifiers may only occur before the interval.
+% 
+% degree =  <interval> | <modifier> <degree>
+% 
+%
+% *** OTHER TYPES ***
+% 
+%ACCIDENTALS
+% 
+% signed integer number of sharps or flats.  If positive then denotes 
+% sharps, if negative then denotes flats.
+% 
+% 
+%SEMITONE
+% 
+% Integer value signifying a number of semitone intervals. 
+% 
+% 
+%PITCHCLASS
+% 
+% Integer value between 0 and 11 enumerating pitch classes with C as
+% reference pitch class 0.
+% 
+% 
+%CHORDTYPE
+% 
+% Enumerates shorthand chordtypes
+% 
+% 0   maj 
+% 1   min 
+% 2   dim 
+% 3   aug 
+% 4   maj7 
+% 5   min7 
+% 6   7 
+% 7   dim7 
+% 8   hdim7 
+% 9   minmaj7 
+% 10  maj6 
+% 11  min6 
+% 12  9 
+% 13  maj9 
+% 14  min9 
+% 15  sus4 
+% 16  sus2
+% 
+%QUALITY
+% 
+% Enumerates chord quality
+% 
+% 0   Major
+% 1   Minor
+% 2   Diminished
+% 3   Augmented
+% 4   Suspended
+% 
+% 
+%
+%
+% Author: Christopher Harte,  August 2005
+% 
+% Copyright: Centre for Digital Music, Queen Mary University of London 2005 
+%
+% This file is part of the C4DM Chord Toolkit.  
+%
+% The C4DM Chord Toolkit 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 2 of the License, or
+% (at your option) any later version.
+%
+% The C4DM Chord Toolkit 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
+% along with the C4DM Toolkit; if not, write to the Free Software
+% Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+%
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chroma/chroma_main.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,20 @@
+function [chroma, t] = chroma_main(filename, param)
+
+switch param.dsp.extractiontype
+    case 'ieee2008'
+        [chroma, t] = chroma_ieee2008(filename, param);
+    case 'MIREX2009'
+        [chroma, t] = chroma_MIREX2009(filename, param);
+    case 'MIREX2009precalculated'
+        [chroma, t] = chroma_MIREX2009precalculated(param);
+    case 'lsqnonneg'
+        [chroma, t] = chroma_lsqnonneg(filename,param);
+        case 'lsqnonnegfast'
+        [chroma, t] = chroma_lsqnonneg_fast(filename,param);
+    case 'vampprecalculated'
+        [chroma, t] = chroma_vampprecalculated(param);
+    case 'ISMIR2010'
+        [chroma, t] = chroma_lsqnonneg_ISMIR2010(filename, param);
+    otherwise
+        fprintf(1, 'chroma type %s not recognised', param.dsp.extractiontype)
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chroma/chroma_vampprecalculated.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function [chroma, t] = chroma_vampprecalculated(param)
+timeandchroma = dlmread(param.metafilename);
+
+t = timeandchroma(:,1);
+chroma.bass = timeandchroma(:,[5:13 2:4])';
+chroma.treble = timeandchroma(:,[17:25 14:16])';
+chroma.wide = chroma.treble + 0.8 * chroma.bass;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chroma/fftbin2frequency.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+function frequency = fftbin2frequency(iBin,fs,blocksize)
+frequency = (iBin-1) * fs / blocksize;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chroma/kldiv.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,2 @@
+function d = kldiv(p,q)
+d = sum(p .* log2(p./q));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chroma/midinote2frequency.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+function frequency = midinote2frequency(midinote)
+
+frequency = 440 * 2.^((midinote-69)/12);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chroma/newdict.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,165 @@
+s = chunkspectrogram(filename,4096,4096*7/8,4096,inf);
+a = abs(s);
+T = size(s,2);
+%%
+zeroind = find(sum(a)==0 | sum(a)==-inf);
+a(:,zeroind) = randn(size(a,1),length(zeroind)).^2;
+
+wind_size = 6 * 3 + 1;
+pad_size = (wind_size-1)/2;
+wind = qnormalise(hamming(wind_size),1,1);
+
+atransf = wm' * qnormalise(a,2,1);
+
+nFbin = size(wm,2);
+
+
+
+
+% CHANGED: this is an equivalent formulation in terms of phase.
+fftr=fft(sum(atransf(3:end-2,:),2));
+th = -angle(fftr((nFbin - 4)/3+1)) - 2*pi/3;
+th(th < -pi) = th(th < -pi) + 2*pi;
+disp(440*2.^(th/2/pi/12))
+
+for iFrame = 1:T
+    atransf(:,iFrame) = interp1(1:nFbin, atransf(:,iFrame), (1:nFbin) + th / (2 * pi) * 3,'spline',0);
+end
+
+
+%
+nFbin = size(atransf,1);
+T = size(atransf,2);
+
+% calculate running mean
+m = conv2(atransf,wind(:),'valid');
+m = [repmat(m(1,:),pad_size,1); m ; repmat(m(end,:),pad_size,1)];
+
+% calculate running standard deviation
+stdev = sqrt(conv2((atransf-m).^2,wind(:),'valid'));
+stdev = [repmat(stdev(1,:),pad_size,1); stdev ; repmat(stdev(end,:),pad_size,1)];
+
+% loamp = logical(atransf < 1.5 * m);
+% atransf(loamp) = atransf(loamp)/5;
+atransf = (atransf - m)./stdev;
+atransf(atransf<0) = 0;
+
+% atransf = qnormalise(atransf,inf,2);
+% atransf(isnan(atransf)) = 0;
+
+%% generate dictionary
+nSBin = 3;
+fs = 11025;
+blocksize = 4096;
+minMidi = 20;
+maxMidi = 105;
+overs = 40;
+midiFrequencies = midinote2frequency(minMidi:1/nSBin:maxMidi);
+
+
+
+dx = fs/blocksize/overs;
+x = dx:dx:fs/2;
+nX = length(x);
+
+nMidi = length(midiFrequencies);
+% nFFT = length(fftFrequencies);
+
+midiWarp = semitonedistance(midiFrequencies,nSBin);
+% fftWarp = ones(size(x)) * fs / blocksize;
+
+B = zeros(256, 7*12);
+
+for iMidi = 1:7*12
+    f0 = midiFrequencies(3*iMidi+1);
+    f = f0;
+    factor = 1;
+    help = (log(f0) - log(midiFrequencies(1)))/log(midiFrequencies(end));
+    factorred(iMidi) = 0.9 * (1 - help) + 0.9 * help;
+    fprintf(1,'%3.2f %%\r',iMidi/nMidi*100*3)
+    midiVector = cospuls_warped(midiFrequencies,f,midiWarp);
+    while f < 11025/2;
+        f = f + f0;
+        factor = factor * factorred(iMidi);
+        midiVector = midiVector + factor * cospuls_warped(midiFrequencies,f,midiWarp);    
+    end
+    B(:,iMidi) = midiVector;
+end
+% %%
+
+%%
+B = qnormalise(B,1,1);
+% C = B(:,12:6*36+11)';
+C=B;
+% atransf(atransf<0) = atransf(atransf<0)/5;
+% mys = mldivide(C,(atransf));
+
+atransf = sparse(atransf);
+
+for t = 1:T
+    fprintf('%0.1f %%\n',t/T*100)
+    mys(:,t) = lsqnonneg(C,atransf(:,t));
+end
+
+% mys =  qnormalise(mys,1,1);
+% mys(mys<0)=0;
+imagesc(mys.*(mys>0))
+axis xy
+%%
+
+n = size(mys,1);
+
+bt_spacing = 1/4.5;
+
+basswindow = cospuls(1:n,n * bt_spacing +0.5,n * 2 * bt_spacing);
+% treblewindow =  cospuls(1:n,2 * n * bt_spacing+0.5,n * 2 * bt_spacing) + cospuls(1:n,3*n * bt_spacing+0.5,n* 2 * bt_spacing);
+treblewindow = cospuls(1:n,n * 0.5 + 0.5,n * 2 * 0.5);
+% treblewindow = basswindow(12:6*36+11)/2 + treblewindow(12:6*36+11);
+% basswindow = basswindow(12:6*36+11);
+
+%%
+thirtysix2twelve = zeros(12,36);
+for iSemitone = 0:11
+    thirtysix2twelve(iSemitone+1,iSemitone*3+(1:3)) = 1;
+end
+if n == 256
+    toPC = repmat(eye(36),7,1);
+    toPC = [toPC(end-1:end,:); toPC; toPC(1:2,:)];
+    bass_chromagram = mys' * diag(basswindow) * toPC * thirtysix2twelve';
+    treble_chromagram = mys' * diag(treblewindow) * toPC * thirtysix2twelve';
+else
+    toPC = repmat(eye(12),7,1);
+    bass_chromagram = mys' * diag(basswindow) * toPC;
+    treble_chromagram = mys' * diag(treblewindow) * toPC;
+end
+% chromagram = mys' * repmat(eye(36),6,1);
+thr_l = 0.0;
+thr_h = 3;
+treble_chromagram(treble_chromagram<thr)=thr_l;
+bass_chromagram(bass_chromagram<thr)=thr_l;
+
+treble_chromagram = circshift(treble_chromagram,[0 -3]);
+bass_chromagram = circshift(bass_chromagram,[0, -3]);
+
+% treble_chromagram = treble_chromagram + bass_chromagram/4;
+
+% bass_chromagram = medfilt1(bass_chromagram,10);
+% treble_chromagram = medfilt1(treble_chromagram,10);
+
+%%
+some = 100 * 0;
+% subplot(211)
+imagesc(qnormalise([(bass_chromagram');(treble_chromagram')],2,1))
+hold on
+ax = axis;
+plot(ax(1:2),[12.5 12.5],'color',[0.7 0.7 0.7])
+axis xy
+hold off
+% xlim([0 800] + some)
+% subplot(212)
+% imagesc()
+% xlim([0 800] + some)
+% axis xy
+%%
+dlmwrite('/Users/matthiasmauch/temptreble.csv',treble_chromagram, 'delimiter','\t');
+dlmwrite('/Users/matthiasmauch/tempbass.csv',bass_chromagram, 'delimiter','\t');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chroma/pitch2octave.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function strout = pitch2octave(pitch)
+octave = floor((pitch-60)/12);
+if octave < 0
+    sig = '-';
+else
+    sig = '''';
+end
+strout = '';
+for iOct = 1:abs(octave)
+    strout = [strout,sig];
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chroma/semitonedistance.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,7 @@
+function df = semitonedistance(f,varargin)
+if nargin == 1
+    df = log(2)/12*f;
+else
+    bins_per_semitone = varargin{1};
+    df = log(2)/(12*bins_per_semitone)*f;
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_chroma/sparsePrint.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,48 @@
+sizeMat = size(cosw);
+
+fid  = fopen('/Users/matthiasmauch/Documents/_workspace/2010/2010-VampDevel-code/plugin-tutorial/coskernel-20-105-3-11025-4096-80.cpp','w');
+
+fprintf(fid, 'const int lengthOfNoteIndex = %0.0f;\n\n', sum(cosw(:)>0));
+
+fprintf(fid, 'const int nNote = %0.0f;\n\n', sizeMat(2));
+
+fprintf(fid,'const int noteIndex[] = {')
+
+for iCol = 1:sizeMat(2)
+    for iRow = 1:sizeMat(1)
+        if cosw(iRow,iCol) > 0
+            fprintf(fid, '%0.0f,',iCol-1);
+        end
+    end
+    fprintf(fid,'\n');
+end
+fprintf(fid,'};\n\n');transform
+
+% ---------------------------
+fprintf(fid,'const int fftBin[] = {')
+
+for iCol = 1:sizeMat(2)
+    for iRow = 1:sizeMat(1)
+        if cosw(iRow,iCol) > 0
+            fprintf(fid, '%0.0f,',iRow-1);
+        end
+    end
+    fprintf(fid,'\n');
+end
+fprintf(fid,'};\n\n');
+
+% ---------------------------
+fprintf(fid,'const double transfValue[] = {')
+
+for iCol = 1:sizeMat(2)
+    for iRow = 1:sizeMat(1)
+        if cosw(iRow,iCol) > 0
+            fprintf(fid, '%0.5f,',cosw(iRow,iCol));
+        end
+    end
+    fprintf(fid,'\n');
+end
+fprintf(fid,'};\n\n');
+
+
+fclose(fid);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_dbn/add_chords.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,118 @@
+function param = add_chords(param)
+
+
+patterns = [];
+lilytypenames = {};
+bassn = [];
+hasN = false;
+for iChord = 1:length(param.dbn.chordclassset)
+    switch param.dbn.chordclassset{iChord}
+        case ''
+            patterns = [patterns; ...
+                1 0 0 0 1 0 0 1 0 0 0 0]; % major
+            lilytypenames = [lilytypenames, ' '];
+            bassn = [bassn, 1];
+        case '/3'
+            patterns = [patterns; ...
+                1 0 0 0 1 0 0 1 0 0 0 0]; % major/3
+            lilytypenames = [lilytypenames, ' '];
+            bassn = [bassn, 5];
+        case '/5'
+            patterns = [patterns; ...
+                1 0 0 0 1 0 0 1 0 0 0 0]; % major/5
+            lilytypenames = [lilytypenames, ' '];
+            bassn = [bassn, 8];
+        case ':maj6'
+            patterns = [patterns; ...
+                1 0 0 0 1 0 0 1 0 1 0 0]; % major 6
+            lilytypenames = [lilytypenames, ':6'];
+            bassn = [bassn, 1];
+        case ':maj7'
+            patterns = [patterns; ...
+                1 0 0 0 1 0 0 1 0 0 0 1]; % major 7
+            lilytypenames = [lilytypenames, ':maj7'];
+            bassn = [bassn, 1];
+        case ':min'
+            patterns = [patterns; ...
+                1 0 0 1 0 0 0 1 0 0 0 0]; % minor
+            lilytypenames = [lilytypenames, ':m'];
+            bassn = [bassn, 1];
+        case ':min7'
+            patterns = [patterns; ...
+                1 0 0 1 0 0 0 1 0 0 1 0]; % minor
+            lilytypenames = [lilytypenames, ':m7'];
+            bassn = [bassn, 1];
+        case ':7'
+            patterns = [patterns; ...
+                1 0 0 0 1 0 0 1 0 0 1 0]; % dominant
+            lilytypenames = [lilytypenames, ':7'];
+            bassn = [bassn, 1];
+        case ':dim'
+            patterns = [patterns; ...
+                1 0 0 1 0 0 1 0 0 0 0 0]; % diminished
+            lilytypenames = [lilytypenames, ':dim'];
+            bassn = [bassn, 1];
+        case ':aug'
+            patterns = [patterns; ...
+                1 0 0 0 1 0 0 0 1 0 0 0]; % augmented
+            lilytypenames = [lilytypenames, ':aug'];
+            bassn = [bassn, 1];
+        case 'N'            
+            hasN = true;
+            hasN0 = false;
+        case 'N0';
+            hasN0 = true;
+            hasN = false;
+    end
+end
+nRow = size(patterns,1);
+
+sz = 12;
+
+bass_notes = zeros(1,sz*nRow+1);
+root_notes = bass_notes;
+chordnames = cell(1,sz*nRow+1);
+lilychordnames = chordnames;
+mu = zeros(sz,sz*nRow+1);
+cova = zeros(sz,sz,sz*nRow+1);
+count = 1;
+
+for iRow = 1:nRow
+    for iSemitone = 1:sz
+        mu(:,count) = circshift(patterns(iRow,:)',iSemitone-1);
+        cova(:,:,count) = eye(sz) * param.dbn.chromavar;
+        root_notes(count) = iSemitone;
+        chordnames{count} = param.dbn.chordclassset{iRow};
+        lilychordnames{count} = lilytypenames{iRow};
+        if bassn(iRow) ~= 13
+            bass_notes(count) = mod(bassn(iRow)+iSemitone-2,12)+1;
+        else
+            bass_notes(count) = 13;
+        end
+        count = count + 1;
+    end
+end
+indexN = count;
+if hasN
+    mu(:,indexN) = ones(12,1); % "no chord"
+    lilychordnames{count} = ' ';
+    cova(:,:,indexN) = mean(cova,3);
+    bass_notes(indexN) = 13;
+    root_notes(indexN) = 13;
+end
+if hasN0
+    mu(:,indexN) = zeros(12,1); % "no chord"
+    cova(:,:,indexN) = mean(cova,3);
+    bass_notes(indexN) = 13;
+    root_notes(indexN) = 13;
+end
+
+%%
+param.dbn.nChord = size(mu,2);
+param.dbn.chordpcs = mu;
+param.dbn.cova = cova;
+param.dbn.lilytypechordnames = lilychordnames;
+param.dbn.chordnames = chordnames;
+param.dbn.chordrootnotes = root_notes;
+param.dbn.chordbassnotes = bass_notes;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_dbn/add_keys.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+function param = add_keys(param)
+names = {'A','Bb','B','C','C#','D','Eb','E','F','F#','G','G#','Am','Bbm','Bm','Cm','C#m','Dm','Ebm','Em','Fm','F#m','Gm','G#m'};
+switch param.key.set
+    case 'major'
+        param.key.names = names(1:12);
+        profile = [1 0 1 0 1 1 0 1 0 1 0 1];
+    case 'majorminor'
+        param.key.names = names;
+        profile = [1 0 1 0 1 1 0 1 0 1 0 1;
+                   1 0 1 1 0 1 0 1 1 0 0 1];
+end
+
+nMode = size(profile,1);
+
+param.key.profiles = zeros(12 * nMode, 12);
+param.key.n = nMode * 12;
+
+for iMode = 1:nMode
+    for iSemitone = 1:12
+        param.key.profiles(12 * (iMode-1) + iSemitone,:) = ...
+            circshift(profile(iMode,:),[0,iSemitone-1]);
+    end
+end
+
+
+param.chord.givenkey = zeros([param.key.n,param.chord.n]);
+
+for iKey = 1:param.key.n
+    for iChord = 1:param.chord.n
+        chord_prefit = ...
+            (1-param.key.profiles(iKey,:)) * param.chord.mu(:,iChord);
+        param.chord.givenkey(iKey,iChord) = 1 / (chord_prefit + param.key.c);
+    end
+end
+param.chord.givenkey = qnormalise(param.chord.givenkey,1,2);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_dbn/dbn_ISMIR2010.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,236 @@
+function bnet = dbn_thesis_mbk24bx(param)
+
+node_sizes = [param.dbn.nMetpos param.dbn.nKey param.dbn.nChord 13 13 12];
+discrete = 1:4;
+observed = 5:6;
+%% topology: metric position
+
+nodenames = {'metpos', 'key', 'chord', 'bass' , 'basschroma','treblechroma'};
+
+%% topology: dependencies
+% I first create full dependency matrices, and then eliminate the
+% inapproapriate rows and columns
+
+intra = zeros(6);
+inter = zeros(6);
+
+intra(1,3) = 1; % metpos to chord
+intra(2,3) = 1; % key to chord
+intra(3,4) = 1; % chord to bass
+intra(3,6) = 1; % chord to treble chroma
+intra(4,5) = 1; % bass to bass chroma
+
+inter(1,1) = 1; % metpos to metpos
+inter(2,2) = 1; % key to key
+inter(3,3) = 1; % chord to chord
+inter(3,4) = 1; % chord to bass
+
+bnet = mk_dbn(intra, inter, ...
+    node_sizes, 'discrete', discrete, 'observed', observed, ...
+    'names', nodenames);
+
+%-------------------------------------------------------
+% Flat initialisation for hidden nodes in first slice
+%-------------------------------------------------------
+fprintf(1,'   - First Slice\n');
+iNode = 1;
+for nodename = nodenames(discrete)
+    fprintf(1,'    %s \n', nodename{1});
+    bnet.CPD{iNode} = tabular_CPD(bnet, iNode, 'CPT', 'unif');
+    iNode = iNode + 1;
+end
+
+%-------------------------------------------------------
+% Observed nodes
+%-------------------------------------------------------
+bnet.CPD{bnet.names('basschroma')} = ...
+    gaussian_CPD(bnet,bnet.names('basschroma'), ...
+    'mean', eye(13), 'cov', repmat(eye(13) * sqrt(param.dbn.basschromavar),[1,1,13]));
+chordpcs = param.dbn.chordpcs;
+chordpcs(:,end) = chordpcs(:,end) - 0.5;
+cova = param.dbn.cova;
+cova(:,:,end) = cova(:,:,end);
+bnet.CPD{bnet.names('treblechroma')} = ...
+    gaussian_CPD(bnet,bnet.names('treblechroma'), ...
+    'mean', chordpcs, 'cov', cova);
+
+%-------------------------------------------------------
+% second slice -- more elaborate stuff ...
+%-------------------------------------------------------
+
+fprintf(1,'   - Second Slice\n');
+nodename = 'metpos';
+nodenumber = bnet.names(nodename) + bnet.nnodes_per_slice;
+fprintf(1,'    (%d) %s (slice 2) \n', nodenumber, nodename);
+% columns are:
+% (1) old metpos,
+% (2) this metpos,
+% (3) conditional probability.
+
+helper_table = get_field(tabular_CPD(bnet,nodenumber,'CPT','unif'),'cpt');
+helper_table = helper_table * 0;
+for oldmetpos = 1:param.dbn.nMetpos
+    for thismetpos = 1:param.dbn.nMetpos
+        if oldmetpos <= 4
+            if mod(oldmetpos + 1,4)  == ...
+                    mod(thismetpos,4)
+                helper_table(oldmetpos,thismetpos) = param.dbn.beattrans;
+            else
+                helper_table(oldmetpos,thismetpos) = (1-param.dbn.beattrans)/3;
+            end
+        else
+            helper_table(oldmetpos,thismetpos) = 1/param.dbn.nMetpos;
+        end
+    end
+end
+
+bnet.CPD{nodenumber} = tabular_CPD(bnet,nodenumber,helper_table);
+
+%-------------------------------------------------------
+
+nodename = 'key';
+nodenumber = bnet.names(nodename) + bnet.nnodes_per_slice;
+fprintf(1,'    (%d) %s (slice 2) \n', nodenumber, nodename);
+% columns are
+% (1) old key
+% (2) this key
+% (3) probability.
+
+helper_table = get_field(tabular_CPD(bnet,nodenumber,'CPT','unif'),'cpt');
+
+for iOld = 1:param.dbn.nKey
+    for iThis = 1:param.dbn.nKey
+        if iOld == iThis
+            helper_table(iOld,iThis) = 1-param.dbn.keychange;
+        else
+            helper_table(iOld,iThis) = param.dbn.keychange/(param.dbn.nKey-1);
+        end
+    end
+end
+
+bnet.CPD{nodenumber} = tabular_CPD(bnet,nodenumber,helper_table);
+
+%-------------------------------------------------------
+nodename = 'chord';
+nodenumber = bnet.names(nodename) + bnet.nnodes_per_slice;
+fprintf(1,'    (%d) %s (slice 2) \n', nodenumber, nodename);
+% columns are:
+% (1) old chord,
+% (2) new metpos,
+% (3) new harmonic meter,
+% () new key,
+% (5) this chord,
+% (6) probability.
+
+helper_table = get_field(tabular_CPD(bnet,nodenumber,'CPT','unif'),'cpt');
+[cgivenk, param] = chordgivenkey(param);
+
+for iKey = 1:param.dbn.nKey
+    for iThis = 1:param.dbn.nChord
+        for iBeat = 1:param.dbn.nMetpos
+            for iOld = 1:param.dbn.nChord
+                if iOld == iThis
+                    helper_table(iOld,iBeat,iKey,iThis) = ...
+                        param.dbn.chordchange(iBeat) * cgivenk(iKey, iThis);
+                else
+                    helper_table(iOld,iBeat,iKey,iThis) = ...
+                        (1-param.dbn.chordchange(iBeat)) / (param.dbn.nChord - 1) * cgivenk(iKey, iThis);
+                end
+            end
+        end
+    end
+end
+bnet.CPD{nodenumber} = tabular_CPD(bnet,nodenumber,helper_table);
+
+%-------------------------------------------------------
+nodename = 'bass';
+% (1) old chord
+% (2) new chord
+% (3) this bass
+nodenumber = bnet.names(nodename) + bnet.nnodes_per_slice;
+fprintf(1,'    (%d) %s (slice 2) \n', nodenumber, nodename);
+helper_table = get_field(tabular_CPD(bnet,nodenumber,'CPT','unif'),'cpt');
+for iOldchord = 1:param.dbn.nChord
+    for iNewchord = 1:param.dbn.nChord
+        if iOldchord ~= iNewchord % first beat of new chord
+            for iThisbass = 1:param.dbn.nBass
+                if iThisbass == param.dbn.chordbassnotes(iNewchord) % correct bass note
+                    helper_table(iOldchord, iNewchord, iThisbass) = param.dbn.nominalbass;
+                else
+                    helper_table(iOldchord, iNewchord, iThisbass) = (1 - param.dbn.nominalbass) / (param.dbn.nBass-1);
+                end
+            end
+        else
+            for iThisbass = 1:param.dbn.nBass
+                if ~param.dbn.basshaschordnotes
+                    if iThisbass == param.dbn.chordbassnotes(iNewchord) % correct bass note
+                        helper_table(iOldchord, iNewchord, iThisbass) = param.dbn.nominalbass_inner;
+                    else
+                        helper_table(iOldchord, iNewchord, iThisbass) = (1 - param.dbn.nominalbass_inner) / (param.dbn.nBass-1);
+                    end
+                else
+                    chordnbass = [param.dbn.chordpcs(:,iNewchord); 0];
+                    chordnbass(param.dbn.chordbassnotes(iNewchord)) = chordnbass(param.dbn.chordbassnotes(iNewchord))+1;
+                    if ismember(iThisbass, find(chordnbass)) % chord bass note
+                        helper_table(iOldchord, iNewchord, iThisbass) = param.dbn.nominalbass_inner * chordnbass(iThisbass) / sum(chordnbass);
+                    else
+                        helper_table(iOldchord, iNewchord, iThisbass) = (1 - param.dbn.nominalbass_inner) / (param.dbn.nBass-sum(chordnbass)-1);
+                    end
+                end
+            end
+        end
+    end
+end
+
+bnet.CPD{nodenumber} = tabular_CPD(bnet,nodenumber,helper_table);
+
+
+
+function [cgivenk, param] = chordgivenkey(param)
+switch param.dbn.keyset
+    case 'major'
+        profile = [1 0 1 0 1 1 0 1 0 1 0 1];
+    case 'majorminor'
+        profile = [1 0 1 0 1 1 0 1 0 1 0 1;
+                   1 0 1 1 0 1 0 1 1 1 1 1];
+end
+
+nMode = size(profile,1);
+
+profiles = zeros(12 * nMode, 12);
+param.dbn.nKey = nMode * 12;
+
+for iMode = 1:nMode
+    for iSemitone = 1:12
+        profiles(12 * (iMode-1) + iSemitone,:) = ...
+            circshift(profile(iMode,:),[0,iSemitone-1]);
+    end
+end
+
+cgivenk = zeros([param.dbn.nKey,param.dbn.nChord]);
+
+% for iKey = 1:param.dbn.nKey
+%     for iChord = 1:param.dbn.nChord
+%         chord_prefit = ...
+%             (1-profiles(iKey,:)) * param.dbn.chordpcs(:,iChord);
+%         cgivenk(iKey,iChord) = 1 / (chord_prefit + param.dbn.key_c);
+%     end
+% end
+
+
+for iKey = 1:param.dbn.nKey
+    for iChord = 1:param.dbn.nChord
+        chord_prefit = ...
+            (1-profiles(iKey,:)) * param.dbn.chordpcs(:,iChord);
+        if chord_prefit == 0 && mod(iKey-iChord,12) == 0 % is in key and key and chord share root
+            chord_chord_prefit = 2;
+        else
+            chord_chord_prefit = 1;
+        end
+        cgivenk(iKey,iChord) = (chord_chord_prefit / exp(chord_prefit + 0.0997)) * 0.0363 + 0.0667;
+    end
+end
+
+cgivenk = qnormalise(cgivenk,1,2);
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_dbn/inference.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,89 @@
+function song = inference(song, bnet, param)
+
+
+if param.dsp.separatenormalising % means that also bass and treble chroma are separate
+    evidence = cell(bnet.nnodes_per_slice,song.nBeat);
+    if param.dbn.nBass > 0
+        basschromanode = bnet.names('basschroma');
+        evidence(basschromanode,:) = ...
+            num2cell(song.segchroma.bass(:,1:param.dbn.nBass)',1);
+    end
+
+    treblechromanode = bnet.names('treblechroma');
+    evidence(treblechromanode,:) = ...
+        num2cell(song.segchroma.treble',1);
+
+    if param.dbn.inferencebypart
+        fprintf(2,'    ');
+        song = integratesmallparts(song);
+        song.mpe = cell(size(evidence));
+        nIntegratedParts = numel(song.integratedparts);
+        if param.dbn.infermpe
+            for iIP = 1:nIntegratedParts
+                startind = song.integratedparts(iIP).indices; % only one index for integrated parts
+                endind = song.integratedparts(iIP).indices + song.integratedparts(iIP).n - 1;
+                leftoverlap = min(startind - 1, param.seg.inferenceoverlap);
+                rightoverlap = min(song.nBeat - endind, param.seg.inferenceoverlap);
+                currevidence = evidence(:,startind - leftoverlap:endind + rightoverlap);
+                engine = smoother_engine(jtree_2TBN_inf_engine(bnet));
+                fprintf(1,'\nFinding maximum probability path (part %1.0f of %1.0f, beats %1.0f to %1.0f)... \n', iIP, nIntegratedParts, startind, endind)
+                fprintf(2,'\b\b\b\b%3.0f%%',iIP/nIntegratedParts*100);
+                currmpe = find_mpeMM(engine, currevidence);
+                song.mpe(:,startind:endind) = currmpe(:,leftoverlap + 1:size(currmpe,2)-rightoverlap);
+            end
+        else
+            error('inference by part + mpe not yet supported');
+        end
+    else
+
+        if param.dbn.infermpe
+            engine = smoother_engine(jtree_2TBN_inf_engine(bnet));
+            fprintf(1,'\n__ Finding maximum probability path... _________\n')
+            song.mpe = find_mpeMM(engine, evidence);
+        else
+            engine = filter_engine(jtree_2TBN_inf_engine(bnet));
+            fprintf(1,'\n__ Inference... _________\n')
+            tic
+            for t = 1:song.nBeat
+                t
+                param.engine = enter_evidence(engine,[evidence{:,t}],t);
+            end
+            toc
+            song.inferred = cell(bnet.nnodes_per_slice, song.nBeat);
+            for iBeat = 1:song.nBeat
+                for iNode = 1:bnet.nnodes_per_slice-2
+                    temp = marginal_nodes(engine,iNode,iBeat);
+                    song.inferred{iNode, iBeat} = temp.T;
+                end
+            end
+        end
+    end
+else
+    chromanode = bnet.names('chroma');
+
+    evidence = cell(bnet.nnodes_per_slice,song.nBeat);
+
+    evidence(chromanode,:) = ...
+        num2cell([song.segchroma.bass, song.segchroma.treble]',1);
+
+    if param.dbn.inferencebypart
+    else
+        engine = smoother_engine(jtree_2TBN_inf_engine(bnet));
+        if param.dbn.infermpe
+            fprintf(1,'\n__ Finding maximum probability path... _________\n')
+            song.mpe = find_mpe(engine, evidence);
+        else
+            fprintf(1,'\n__ Inference... _________\n')
+            tic
+            param.engine = enter_evidence(engine,evidence);
+            toc
+            song.inferred = cell(bnet.nnodes_per_slice, song.nBeat);
+            for iBeat = 1:beat.n
+                for iNode = 1:bnet.nnodes_per_slice-1
+                    temp = marginal_nodes(engine,iNode,iBeat);
+                    song.inferred{iNode, iBeat} = temp.T;
+                end
+            end
+        end
+    end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_dbn/make_dbn.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function bnet = make_dbn(param)
+% generates the right dbn
+switch param.dbn.name
+    case 'ieee2008mbk'
+        bnet = ieee2008mbk(param);
+    otherwise
+        bnet = [];
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_logfiles/03_-_Across_the_Universe.wav.log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,342 @@
+CSVFeatureWriter::setParameters
+stdout -> 
+NOTE: Using default sample rate of 44100 for default transform
+NOTE: Loaded and initialised plugin for transform "vamp:matthiasm:nnls_chroma:bothchroma" with plugin step size 2048 and block size 16384 (adapter step and block size 16384)
+NOTE: PluginInputDomainAdapter timestamp adjustment is  0.000000000R
+Extracting features for: "/Users/matthias/Music/Other/The Beatles/12_-_Let_It_Be/03_-_Across_the_Universe.wav"
+
Retrieving audio data... Done
+Opened 2-channel file or URL "/Users/matthias/Music/Other/The Beatles/12_-_Let_It_Be/03_-_Across_the_Universe.wav"
+timestamp  0.000000000R: very low magnitude, setting magnitude to all zeros
+timestamp  0.046439909R: very low magnitude, setting magnitude to all zeros
+timestamp  0.092879818R: very low magnitude, setting magnitude to all zeros
+timestamp  0.139319727R: very low magnitude, setting magnitude to all zeros
+timestamp  0.185759637R: very low magnitude, setting magnitude to all zeros
+timestamp  0.232199546R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 1%
Extracting and writing features... 2%
Extracting and writing features... 3%
Extracting and writing features... 4%
Extracting and writing features... 5%
Extracting and writing features... 6%
Extracting and writing features... 7%
Extracting and writing features... 8%
Extracting and writing features... 9%
Extracting and writing features... 10%
Extracting and writing features... 11%
Extracting and writing features... 12%
Extracting and writing features... 13%
Extracting and writing features... 14%
Extracting and writing features... 15%
Extracting and writing features... 16%
Extracting and writing features... 17%
Extracting and writing features... 18%
Extracting and writing features... 19%
Extracting and writing features... 20%
Extracting and writing features... 21%
Extracting and writing features... 22%
Extracting and writing features... 23%
Extracting and writing features... 24%
Extracting and writing features... 25%
Extracting and writing features... 26%
Extracting and writing features... 27%
Extracting and writing features... 28%
Extracting and writing features... 29%
Extracting and writing features... 30%
Extracting and writing features... 31%
Extracting and writing features... 32%
Extracting and writing features... 33%
Extracting and writing features... 34%
Extracting and writing features... 35%
Extracting and writing features... 36%
Extracting and writing features... 37%
Extracting and writing features... 38%
Extracting and writing features... 39%
Extracting and writing features... 40%
Extracting and writing features... 41%
Extracting and writing features... 42%
Extracting and writing features... 43%
Extracting and writing features... 44%
Extracting and writing features... 45%
Extracting and writing features... 46%
Extracting and writing features... 47%
Extracting and writing features... 48%
Extracting and writing features... 49%
Extracting and writing features... 50%
Extracting and writing features... 51%
Extracting and writing features... 52%
Extracting and writing features... 53%
Extracting and writing features... 54%
Extracting and writing features... 55%
Extracting and writing features... 56%
Extracting and writing features... 57%
Extracting and writing features... 58%
Extracting and writing features... 59%
Extracting and writing features... 60%
Extracting and writing features... 61%
Extracting and writing features... 62%
Extracting and writing features... 63%
Extracting and writing features... 64%
Extracting and writing features... 65%
Extracting and writing features... 66%
Extracting and writing features... 67%
Extracting and writing features... 68%
Extracting and writing features... 69%
Extracting and writing features... 70%
Extracting and writing features... 71%
Extracting and writing features... 72%
Extracting and writing features... 73%
Extracting and writing features... 74%
Extracting and writing features... 75%
Extracting and writing features... 76%
Extracting and writing features... 77%
Extracting and writing features... 78%
Extracting and writing features... 79%
Extracting and writing features... 80%
Extracting and writing features... 81%
Extracting and writing features... 82%
Extracting and writing features... 83%
Extracting and writing features... 84%
Extracting and writing features... 85%
Extracting and writing features... 86%
Extracting and writing features... 87%
Extracting and writing features... 88%
Extracting and writing features... 89%
Extracting and writing features... 90%
Extracting and writing features... 91%
Extracting and writing features... 92%
Extracting and writing features... 93%
Extracting and writing features... 94%
Extracting and writing features... 95%timestamp  218.824852607R: very low magnitude, setting magnitude to all zeros
+timestamp  218.871292517R: very low magnitude, setting magnitude to all zeros
+timestamp  218.917732426R: very low magnitude, setting magnitude to all zeros
+timestamp  218.964172335R: very low magnitude, setting magnitude to all zeros
+timestamp  219.010612244R: very low magnitude, setting magnitude to all zeros
+timestamp  219.057052154R: very low magnitude, setting magnitude to all zeros
+timestamp  219.103492063R: very low magnitude, setting magnitude to all zeros
+timestamp  219.149931972R: very low magnitude, setting magnitude to all zeros
+timestamp  219.196371882R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 96%timestamp  219.242811791R: very low magnitude, setting magnitude to all zeros
+timestamp  219.289251700R: very low magnitude, setting magnitude to all zeros
+timestamp  219.521451247R: very low magnitude, setting magnitude to all zeros
+timestamp  219.567891156R: very low magnitude, setting magnitude to all zeros
+timestamp  219.614331065R: very low magnitude, setting magnitude to all zeros
+timestamp  219.660770975R: very low magnitude, setting magnitude to all zeros
+timestamp  219.707210884R: very low magnitude, setting magnitude to all zeros
+timestamp  219.753650793R: very low magnitude, setting magnitude to all zeros
+timestamp  219.800090702R: very low magnitude, setting magnitude to all zeros
+timestamp  219.846530612R: very low magnitude, setting magnitude to all zeros
+timestamp  219.892970521R: very low magnitude, setting magnitude to all zeros
+timestamp  219.939410430R: very low magnitude, setting magnitude to all zeros
+timestamp  219.985850340R: very low magnitude, setting magnitude to all zeros
+timestamp  220.032290249R: very low magnitude, setting magnitude to all zeros
+timestamp  220.078730158R: very low magnitude, setting magnitude to all zeros
+timestamp  220.125170068R: very low magnitude, setting magnitude to all zeros
+timestamp  220.171609977R: very low magnitude, setting magnitude to all zeros
+timestamp  220.218049886R: very low magnitude, setting magnitude to all zeros
+timestamp  220.264489795R: very low magnitude, setting magnitude to all zeros
+timestamp  220.310929705R: very low magnitude, setting magnitude to all zeros
+timestamp  220.357369614R: very low magnitude, setting magnitude to all zeros
+timestamp  220.403809523R: very low magnitude, setting magnitude to all zeros
+timestamp  220.450249433R: very low magnitude, setting magnitude to all zeros
+timestamp  220.496689342R: very low magnitude, setting magnitude to all zeros
+timestamp  220.543129251R: very low magnitude, setting magnitude to all zeros
+timestamp  220.589569160R: very low magnitude, setting magnitude to all zeros
+timestamp  220.636009070R: very low magnitude, setting magnitude to all zeros
+timestamp  220.682448979R: very low magnitude, setting magnitude to all zeros
+timestamp  220.728888888R: very low magnitude, setting magnitude to all zeros
+timestamp  220.775328798R: very low magnitude, setting magnitude to all zeros
+timestamp  220.821768707R: very low magnitude, setting magnitude to all zeros
+timestamp  220.868208616R: very low magnitude, setting magnitude to all zeros
+timestamp  220.914648526R: very low magnitude, setting magnitude to all zeros
+timestamp  220.961088435R: very low magnitude, setting magnitude to all zeros
+timestamp  221.007528344R: very low magnitude, setting magnitude to all zeros
+timestamp  221.053968253R: very low magnitude, setting magnitude to all zeros
+timestamp  221.100408163R: very low magnitude, setting magnitude to all zeros
+timestamp  221.146848072R: very low magnitude, setting magnitude to all zeros
+timestamp  221.193287981R: very low magnitude, setting magnitude to all zeros
+timestamp  221.239727891R: very low magnitude, setting magnitude to all zeros
+timestamp  221.286167800R: very low magnitude, setting magnitude to all zeros
+timestamp  221.332607709R: very low magnitude, setting magnitude to all zeros
+timestamp  221.379047619R: very low magnitude, setting magnitude to all zeros
+timestamp  221.425487528R: very low magnitude, setting magnitude to all zeros
+timestamp  221.471927437R: very low magnitude, setting magnitude to all zeros
+timestamp  221.518367346R: very low magnitude, setting magnitude to all zeros
+timestamp  221.564807256R: very low magnitude, setting magnitude to all zeros
+timestamp  221.611247165R: very low magnitude, setting magnitude to all zeros
+timestamp  221.657687074R: very low magnitude, setting magnitude to all zeros
+timestamp  221.704126984R: very low magnitude, setting magnitude to all zeros
+timestamp  221.750566893R: very low magnitude, setting magnitude to all zeros
+timestamp  221.797006802R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 97%timestamp  221.843446712R: very low magnitude, setting magnitude to all zeros
+timestamp  221.889886621R: very low magnitude, setting magnitude to all zeros
+timestamp  221.936326530R: very low magnitude, setting magnitude to all zeros
+timestamp  221.982766439R: very low magnitude, setting magnitude to all zeros
+timestamp  222.029206349R: very low magnitude, setting magnitude to all zeros
+timestamp  222.075646258R: very low magnitude, setting magnitude to all zeros
+timestamp  222.122086167R: very low magnitude, setting magnitude to all zeros
+timestamp  222.168526077R: very low magnitude, setting magnitude to all zeros
+timestamp  222.214965986R: very low magnitude, setting magnitude to all zeros
+timestamp  222.261405895R: very low magnitude, setting magnitude to all zeros
+timestamp  222.307845804R: very low magnitude, setting magnitude to all zeros
+timestamp  222.354285714R: very low magnitude, setting magnitude to all zeros
+timestamp  222.400725623R: very low magnitude, setting magnitude to all zeros
+timestamp  222.447165532R: very low magnitude, setting magnitude to all zeros
+timestamp  222.493605442R: very low magnitude, setting magnitude to all zeros
+timestamp  222.540045351R: very low magnitude, setting magnitude to all zeros
+timestamp  222.586485260R: very low magnitude, setting magnitude to all zeros
+timestamp  222.632925170R: very low magnitude, setting magnitude to all zeros
+timestamp  222.679365079R: very low magnitude, setting magnitude to all zeros
+timestamp  222.725804988R: very low magnitude, setting magnitude to all zeros
+timestamp  222.772244897R: very low magnitude, setting magnitude to all zeros
+timestamp  222.818684807R: very low magnitude, setting magnitude to all zeros
+timestamp  222.865124716R: very low magnitude, setting magnitude to all zeros
+timestamp  222.911564625R: very low magnitude, setting magnitude to all zeros
+timestamp  222.958004535R: very low magnitude, setting magnitude to all zeros
+timestamp  223.004444444R: very low magnitude, setting magnitude to all zeros
+timestamp  223.050884353R: very low magnitude, setting magnitude to all zeros
+timestamp  223.097324263R: very low magnitude, setting magnitude to all zeros
+timestamp  223.143764172R: very low magnitude, setting magnitude to all zeros
+timestamp  223.190204081R: very low magnitude, setting magnitude to all zeros
+timestamp  223.236643990R: very low magnitude, setting magnitude to all zeros
+timestamp  223.283083900R: very low magnitude, setting magnitude to all zeros
+timestamp  223.329523809R: very low magnitude, setting magnitude to all zeros
+timestamp  223.375963718R: very low magnitude, setting magnitude to all zeros
+timestamp  223.422403628R: very low magnitude, setting magnitude to all zeros
+timestamp  223.468843537R: very low magnitude, setting magnitude to all zeros
+timestamp  223.515283446R: very low magnitude, setting magnitude to all zeros
+timestamp  223.561723356R: very low magnitude, setting magnitude to all zeros
+timestamp  223.608163265R: very low magnitude, setting magnitude to all zeros
+timestamp  223.654603174R: very low magnitude, setting magnitude to all zeros
+timestamp  223.701043083R: very low magnitude, setting magnitude to all zeros
+timestamp  223.747482993R: very low magnitude, setting magnitude to all zeros
+timestamp  223.793922902R: very low magnitude, setting magnitude to all zeros
+timestamp  223.840362811R: very low magnitude, setting magnitude to all zeros
+timestamp  223.886802721R: very low magnitude, setting magnitude to all zeros
+timestamp  223.933242630R: very low magnitude, setting magnitude to all zeros
+timestamp  223.979682539R: very low magnitude, setting magnitude to all zeros
+timestamp  224.026122448R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 98%timestamp  224.072562358R: very low magnitude, setting magnitude to all zeros
+timestamp  224.119002267R: very low magnitude, setting magnitude to all zeros
+timestamp  224.165442176R: very low magnitude, setting magnitude to all zeros
+timestamp  224.211882086R: very low magnitude, setting magnitude to all zeros
+timestamp  224.258321995R: very low magnitude, setting magnitude to all zeros
+timestamp  224.304761904R: very low magnitude, setting magnitude to all zeros
+timestamp  224.351201814R: very low magnitude, setting magnitude to all zeros
+timestamp  224.397641723R: very low magnitude, setting magnitude to all zeros
+timestamp  224.444081632R: very low magnitude, setting magnitude to all zeros
+timestamp  224.490521541R: very low magnitude, setting magnitude to all zeros
+timestamp  224.536961451R: very low magnitude, setting magnitude to all zeros
+timestamp  224.583401360R: very low magnitude, setting magnitude to all zeros
+timestamp  224.629841269R: very low magnitude, setting magnitude to all zeros
+timestamp  224.676281179R: very low magnitude, setting magnitude to all zeros
+timestamp  224.722721088R: very low magnitude, setting magnitude to all zeros
+timestamp  224.769160997R: very low magnitude, setting magnitude to all zeros
+timestamp  224.815600907R: very low magnitude, setting magnitude to all zeros
+timestamp  224.862040816R: very low magnitude, setting magnitude to all zeros
+timestamp  224.908480725R: very low magnitude, setting magnitude to all zeros
+timestamp  224.954920634R: very low magnitude, setting magnitude to all zeros
+timestamp  225.001360544R: very low magnitude, setting magnitude to all zeros
+timestamp  225.047800453R: very low magnitude, setting magnitude to all zeros
+timestamp  225.094240362R: very low magnitude, setting magnitude to all zeros
+timestamp  225.140680272R: very low magnitude, setting magnitude to all zeros
+timestamp  225.187120181R: very low magnitude, setting magnitude to all zeros
+timestamp  225.233560090R: very low magnitude, setting magnitude to all zeros
+timestamp  225.280000000R: very low magnitude, setting magnitude to all zeros
+timestamp  225.326439909R: very low magnitude, setting magnitude to all zeros
+timestamp  225.372879818R: very low magnitude, setting magnitude to all zeros
+timestamp  225.419319727R: very low magnitude, setting magnitude to all zeros
+timestamp  225.465759637R: very low magnitude, setting magnitude to all zeros
+timestamp  225.512199546R: very low magnitude, setting magnitude to all zeros
+timestamp  225.558639455R: very low magnitude, setting magnitude to all zeros
+timestamp  225.605079365R: very low magnitude, setting magnitude to all zeros
+timestamp  225.651519274R: very low magnitude, setting magnitude to all zeros
+timestamp  225.697959183R: very low magnitude, setting magnitude to all zeros
+timestamp  225.744399092R: very low magnitude, setting magnitude to all zeros
+timestamp  225.790839002R: very low magnitude, setting magnitude to all zeros
+timestamp  225.837278911R: very low magnitude, setting magnitude to all zeros
+timestamp  225.883718820R: very low magnitude, setting magnitude to all zeros
+timestamp  225.930158730R: very low magnitude, setting magnitude to all zeros
+timestamp  225.976598639R: very low magnitude, setting magnitude to all zeros
+timestamp  226.023038548R: very low magnitude, setting magnitude to all zeros
+timestamp  226.069478458R: very low magnitude, setting magnitude to all zeros
+timestamp  226.115918367R: very low magnitude, setting magnitude to all zeros
+timestamp  226.162358276R: very low magnitude, setting magnitude to all zeros
+timestamp  226.208798185R: very low magnitude, setting magnitude to all zeros
+timestamp  226.255238095R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 99%timestamp  226.301678004R: very low magnitude, setting magnitude to all zeros
+timestamp  226.348117913R: very low magnitude, setting magnitude to all zeros
+timestamp  226.394557823R: very low magnitude, setting magnitude to all zeros
+timestamp  226.440997732R: very low magnitude, setting magnitude to all zeros
+timestamp  226.487437641R: very low magnitude, setting magnitude to all zeros
+timestamp  226.533877551R: very low magnitude, setting magnitude to all zeros
+timestamp  226.580317460R: very low magnitude, setting magnitude to all zeros
+timestamp  226.626757369R: very low magnitude, setting magnitude to all zeros
+timestamp  226.673197278R: very low magnitude, setting magnitude to all zeros
+timestamp  226.719637188R: very low magnitude, setting magnitude to all zeros
+timestamp  226.766077097R: very low magnitude, setting magnitude to all zeros
+timestamp  226.812517006R: very low magnitude, setting magnitude to all zeros
+timestamp  226.858956916R: very low magnitude, setting magnitude to all zeros
+timestamp  226.905396825R: very low magnitude, setting magnitude to all zeros
+timestamp  226.951836734R: very low magnitude, setting magnitude to all zeros
+timestamp  226.998276643R: very low magnitude, setting magnitude to all zeros
+timestamp  227.044716553R: very low magnitude, setting magnitude to all zeros
+timestamp  227.091156462R: very low magnitude, setting magnitude to all zeros
+timestamp  227.137596371R: very low magnitude, setting magnitude to all zeros
+timestamp  227.184036281R: very low magnitude, setting magnitude to all zeros
+timestamp  227.230476190R: very low magnitude, setting magnitude to all zeros
+timestamp  227.276916099R: very low magnitude, setting magnitude to all zeros
+timestamp  227.323356009R: very low magnitude, setting magnitude to all zeros
+timestamp  227.369795918R: very low magnitude, setting magnitude to all zeros
+timestamp  227.416235827R: very low magnitude, setting magnitude to all zeros
+timestamp  227.462675736R: very low magnitude, setting magnitude to all zeros
+timestamp  227.509115646R: very low magnitude, setting magnitude to all zeros
+timestamp  227.555555555R: very low magnitude, setting magnitude to all zeros
+timestamp  227.601995464R: very low magnitude, setting magnitude to all zeros
+timestamp  227.648435374R: very low magnitude, setting magnitude to all zeros
+timestamp  227.694875283R: very low magnitude, setting magnitude to all zeros
+timestamp  227.741315192R: very low magnitude, setting magnitude to all zeros
+timestamp  227.787755102R: very low magnitude, setting magnitude to all zeros
+timestamp  227.834195011R: very low magnitude, setting magnitude to all zeros
+timestamp  227.880634920R: very low magnitude, setting magnitude to all zeros
+timestamp  227.927074829R: very low magnitude, setting magnitude to all zeros
+timestamp  227.973514739R: very low magnitude, setting magnitude to all zeros
+timestamp  228.019954648R: very low magnitude, setting magnitude to all zeros
+timestamp  228.066394557R: very low magnitude, setting magnitude to all zeros
+timestamp  228.112834467R: very low magnitude, setting magnitude to all zeros
+timestamp  228.159274376R: very low magnitude, setting magnitude to all zeros
+timestamp  228.205714285R: very low magnitude, setting magnitude to all zeros
+timestamp  228.252154195R: very low magnitude, setting magnitude to all zeros
+timestamp  228.298594104R: very low magnitude, setting magnitude to all zeros
+timestamp  228.345034013R: very low magnitude, setting magnitude to all zeros
+timestamp  228.391473922R: very low magnitude, setting magnitude to all zeros
+timestamp  228.437913832R: very low magnitude, setting magnitude to all zeros
+timestamp  228.484353741R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 100%timestamp  228.530793650R: very low magnitude, setting magnitude to all zeros
+[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... done.
+[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... done.
+[NNLS Chroma Plugin] Chord Estimation ... done.
+
Extracting and writing features... Done
+
+                              < M A T L A B >
+                  Copyright 1984-2007 The MathWorks, Inc.
+                         Version 7.5.0.338 (R2007b)
+                               August 9, 2007
+
+ 
+  To get started, type one of these: helpwin, helpdesk, or demo.
+  For product information, visit www.mathworks.com.
+ 
+   - First Slice
+    metpos 
+    key 
+    chord 
+    bass 
+   - Second Slice
+    (7) metpos (slice 2) 
+    (8) key (slice 2) 
+    (9) chord (slice 2) 
+    (10) bass (slice 2) 
+onset detection function
+beats
+
+
Length: 28
Length: 32
Length: 36
Length: 40
Length: 44
Length: 48
Length: 52
Length: 56
Length: 60
Length: 64
Length: 68
Length: 72
Length: 76
Length: 80
Length: 84
Length: 88
Length: 92
Length: 96
Length: 100
Length: 104
Length: 108
Length: 112
Length: 116
Length: 120
Length: 124
Length: 128
+Finding maximum probability path (part 1 of 10, beats 1 to 17)... 
+forward step
+backward step
+
+Finding maximum probability path (part 2 of 10, beats 18 to 51)... 
+forward step
+backward step
+
+Finding maximum probability path (part 3 of 10, beats 52 to 88)... 
+forward step
+backward step
+
+Finding maximum probability path (part 4 of 10, beats 89 to 199)... 
+forward step
+backward step
+
+Finding maximum probability path (part 5 of 10, beats 200 to 227)... 
+forward step
+backward step
+
+Finding maximum probability path (part 6 of 10, beats 228 to 242)... 
+forward step
+backward step
+
+Finding maximum probability path (part 7 of 10, beats 243 to 342)... 
+forward step
+backward step
+
+Finding maximum probability path (part 8 of 10, beats 343 to 390)... 
+forward step
+backward step
+
+Finding maximum probability path (part 9 of 10, beats 391 to 490)... 
+forward step
+backward step
+
+Finding maximum probability path (part 10 of 10, beats 491 to 584)... 
+forward step
+backward step
+0.0 0.023 N
+0.023 0.372 N
+0.372 2.821 Db
+2.821 6.850 F:min
+6.850 10.136 Ab
+10.136 13.305 Db/5
+13.305 16.068 F:min
+16.068 18.831 Eb:min7
+18.831 23.557 Ab
+23.557 26.749 Db/5
+26.749 29.501 F:min
+29.501 31.509 Eb:min7
+31.509 34.702 Gb:min
+34.702 41.146 Db/5
+41.146 47.113 Ab
+47.113 50.283 Ab:7
+50.283 53.418 Gb
+53.418 56.959 Db/5
+56.959 59.710 Ab/5
+59.710 63.251 Ab:7
+63.251 66.014 Gb
+66.014 73.085 Db/5
+73.085 75.418 F:min
+75.418 78.565 Eb:min7
+78.565 82.071 Ab
+82.071 85.217 Db/5
+85.217 87.980 F:min
+87.980 91.127 Eb:min7
+91.127 95.469 Ab
+95.469 101.854 Db/5
+101.854 107.381 Ab
+107.381 111.351 Ab:7
+111.351 114.080 Gb
+114.080 117.609 Db/5
+117.609 123.820 Ab
+123.820 126.932 Gb
+126.932 133.909 Db/5
+133.909 136.208 F:min
+136.208 137.764 Eb:min7
+137.764 140.864 Gb:min
+140.864 143.964 Db/5
+143.964 146.692 F:min
+146.692 150.210 Eb:min7
+150.210 153.298 Ab:7
+153.298 159.602 Db/5
+159.602 165.082 Ab
+165.082 168.983 Ab:7
+168.983 171.700 Gb
+171.700 175.195 Db/5
+175.195 181.383 Ab
+181.383 184.483 Gb
+184.483 218.778 Db/5
+218.778 228.560 N0.0 0.023 N
+0.023 20.410 Ab
+20.410 228.560 Db
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_logfiles/06_-_Let_It_Be.wav.log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,269 @@
+CSVFeatureWriter::setParameters
+stdout -> 
+NOTE: Using default sample rate of 44100 for default transform
+NOTE: Loaded and initialised plugin for transform "vamp:matthiasm:nnls_chroma:bothchroma" with plugin step size 2048 and block size 16384 (adapter step and block size 16384)
+NOTE: PluginInputDomainAdapter timestamp adjustment is  0.000000000R
+Extracting features for: "/Users/matthias/Music/Other/The Beatles/12_-_Let_It_Be/06_-_Let_It_Be.wav"
+
Retrieving audio data... Done
+Opened 2-channel file or URL "/Users/matthias/Music/Other/The Beatles/12_-_Let_It_Be/06_-_Let_It_Be.wav"
+timestamp  0.000000000R: very low magnitude, setting magnitude to all zeros
+timestamp  0.046439909R: very low magnitude, setting magnitude to all zeros
+timestamp  0.092879818R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 1%
Extracting and writing features... 2%
Extracting and writing features... 3%
Extracting and writing features... 4%
Extracting and writing features... 5%
Extracting and writing features... 6%
Extracting and writing features... 7%
Extracting and writing features... 8%
Extracting and writing features... 9%
Extracting and writing features... 10%
Extracting and writing features... 11%
Extracting and writing features... 12%
Extracting and writing features... 13%
Extracting and writing features... 14%
Extracting and writing features... 15%
Extracting and writing features... 16%
Extracting and writing features... 17%
Extracting and writing features... 18%
Extracting and writing features... 19%
Extracting and writing features... 20%
Extracting and writing features... 21%
Extracting and writing features... 22%
Extracting and writing features... 23%
Extracting and writing features... 24%
Extracting and writing features... 25%
Extracting and writing features... 26%
Extracting and writing features... 27%
Extracting and writing features... 28%
Extracting and writing features... 29%
Extracting and writing features... 30%
Extracting and writing features... 31%
Extracting and writing features... 32%
Extracting and writing features... 33%
Extracting and writing features... 34%
Extracting and writing features... 35%
Extracting and writing features... 36%
Extracting and writing features... 37%
Extracting and writing features... 38%
Extracting and writing features... 39%
Extracting and writing features... 40%
Extracting and writing features... 41%
Extracting and writing features... 42%
Extracting and writing features... 43%
Extracting and writing features... 44%
Extracting and writing features... 45%
Extracting and writing features... 46%
Extracting and writing features... 47%
Extracting and writing features... 48%
Extracting and writing features... 49%
Extracting and writing features... 50%
Extracting and writing features... 51%
Extracting and writing features... 52%
Extracting and writing features... 53%
Extracting and writing features... 54%
Extracting and writing features... 55%
Extracting and writing features... 56%
Extracting and writing features... 57%
Extracting and writing features... 58%
Extracting and writing features... 59%
Extracting and writing features... 60%
Extracting and writing features... 61%
Extracting and writing features... 62%
Extracting and writing features... 63%
Extracting and writing features... 64%
Extracting and writing features... 65%
Extracting and writing features... 66%
Extracting and writing features... 67%
Extracting and writing features... 68%
Extracting and writing features... 69%
Extracting and writing features... 70%
Extracting and writing features... 71%
Extracting and writing features... 72%
Extracting and writing features... 73%
Extracting and writing features... 74%
Extracting and writing features... 75%
Extracting and writing features... 76%
Extracting and writing features... 77%
Extracting and writing features... 78%
Extracting and writing features... 79%
Extracting and writing features... 80%
Extracting and writing features... 81%
Extracting and writing features... 82%
Extracting and writing features... 83%
Extracting and writing features... 84%
Extracting and writing features... 85%
Extracting and writing features... 86%
Extracting and writing features... 87%
Extracting and writing features... 88%
Extracting and writing features... 89%
Extracting and writing features... 90%
Extracting and writing features... 91%
Extracting and writing features... 92%
Extracting and writing features... 93%
Extracting and writing features... 94%
Extracting and writing features... 95%
Extracting and writing features... 96%
Extracting and writing features... 97%
Extracting and writing features... 98%
Extracting and writing features... 99%timestamp  240.837369614R: very low magnitude, setting magnitude to all zeros
+timestamp  240.883809523R: very low magnitude, setting magnitude to all zeros
+timestamp  240.930249433R: very low magnitude, setting magnitude to all zeros
+timestamp  240.976689342R: very low magnitude, setting magnitude to all zeros
+timestamp  241.023129251R: very low magnitude, setting magnitude to all zeros
+timestamp  241.069569160R: very low magnitude, setting magnitude to all zeros
+timestamp  241.116009070R: very low magnitude, setting magnitude to all zeros
+timestamp  241.162448979R: very low magnitude, setting magnitude to all zeros
+timestamp  241.208888888R: very low magnitude, setting magnitude to all zeros
+timestamp  241.255328798R: very low magnitude, setting magnitude to all zeros
+timestamp  241.301768707R: very low magnitude, setting magnitude to all zeros
+timestamp  241.348208616R: very low magnitude, setting magnitude to all zeros
+timestamp  241.394648526R: very low magnitude, setting magnitude to all zeros
+timestamp  241.441088435R: very low magnitude, setting magnitude to all zeros
+timestamp  241.487528344R: very low magnitude, setting magnitude to all zeros
+timestamp  241.533968253R: very low magnitude, setting magnitude to all zeros
+timestamp  241.580408163R: very low magnitude, setting magnitude to all zeros
+timestamp  241.626848072R: very low magnitude, setting magnitude to all zeros
+timestamp  241.673287981R: very low magnitude, setting magnitude to all zeros
+timestamp  241.719727891R: very low magnitude, setting magnitude to all zeros
+timestamp  241.766167800R: very low magnitude, setting magnitude to all zeros
+timestamp  241.812607709R: very low magnitude, setting magnitude to all zeros
+timestamp  241.859047619R: very low magnitude, setting magnitude to all zeros
+timestamp  241.905487528R: very low magnitude, setting magnitude to all zeros
+timestamp  241.951927437R: very low magnitude, setting magnitude to all zeros
+timestamp  241.998367346R: very low magnitude, setting magnitude to all zeros
+timestamp  242.044807256R: very low magnitude, setting magnitude to all zeros
+timestamp  242.091247165R: very low magnitude, setting magnitude to all zeros
+timestamp  242.137687074R: very low magnitude, setting magnitude to all zeros
+timestamp  242.184126984R: very low magnitude, setting magnitude to all zeros
+timestamp  242.230566893R: very low magnitude, setting magnitude to all zeros
+timestamp  242.277006802R: very low magnitude, setting magnitude to all zeros
+timestamp  242.323446712R: very low magnitude, setting magnitude to all zeros
+timestamp  242.369886621R: very low magnitude, setting magnitude to all zeros
+timestamp  242.416326530R: very low magnitude, setting magnitude to all zeros
+timestamp  242.462766439R: very low magnitude, setting magnitude to all zeros
+timestamp  242.509206349R: very low magnitude, setting magnitude to all zeros
+timestamp  242.555646258R: very low magnitude, setting magnitude to all zeros
+timestamp  242.602086167R: very low magnitude, setting magnitude to all zeros
+timestamp  242.648526077R: very low magnitude, setting magnitude to all zeros
+timestamp  242.694965986R: very low magnitude, setting magnitude to all zeros
+timestamp  242.741405895R: very low magnitude, setting magnitude to all zeros
+timestamp  242.787845804R: very low magnitude, setting magnitude to all zeros
+timestamp  242.834285714R: very low magnitude, setting magnitude to all zeros
+timestamp  242.880725623R: very low magnitude, setting magnitude to all zeros
+timestamp  242.927165532R: very low magnitude, setting magnitude to all zeros
+timestamp  242.973605442R: very low magnitude, setting magnitude to all zeros
+timestamp  243.020045351R: very low magnitude, setting magnitude to all zeros
+[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... done.
+[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... done.
+[NNLS Chroma Plugin] Chord Estimation ... done.
+
Extracting and writing features... Done
+
+
+                              < M A T L A B >
+                  Copyright 1984-2007 The MathWorks, Inc.
+                         Version 7.5.0.338 (R2007b)
+                               August 9, 2007
+
+ 
+  To get started, type one of these: helpwin, helpdesk, or demo.
+  For product information, visit www.mathworks.com.
+ 
+   - First Slice
+    metpos 
+    key 
+    chord 
+    bass 
+   - Second Slice
+    (7) metpos (slice 2) 
+    (8) key (slice 2) 
+    (9) chord (slice 2) 
+    (10) bass (slice 2) 
+onset detection function
+beats
+
+
Length: 28
Length: 32
Length: 36
Length: 40
Length: 44
Length: 48
Length: 52
Length: 56
Length: 60
Length: 64
Length: 68
Length: 72
Length: 76
Length: 80
Length: 84
Length: 88
Length: 92
Length: 96
Length: 100
Length: 104
Length: 108
Length: 112
Length: 116
Length: 120
Length: 124
Length: 128
+Finding maximum probability path (part 1 of 10, beats 1 to 34)... 
+forward step
+backward step
+
+Finding maximum probability path (part 2 of 10, beats 35 to 128)... 
+forward step
+backward step
+
+Finding maximum probability path (part 3 of 10, beats 129 to 220)... 
+forward step
+backward step
+
+Finding maximum probability path (part 4 of 10, beats 221 to 276)... 
+forward step
+backward step
+
+Finding maximum probability path (part 5 of 10, beats 277 to 288)... 
+forward step
+backward step
+
+Finding maximum probability path (part 6 of 10, beats 289 to 384)... 
+forward step
+backward step
+
+Finding maximum probability path (part 7 of 10, beats 385 to 476)... 
+forward step
+backward step
+
+Finding maximum probability path (part 8 of 10, beats 477 to 508)... 
+forward step
+backward step
+
+Finding maximum probability path (part 9 of 10, beats 509 to 564)... 
+forward step
+backward step
+
+Finding maximum probability path (part 10 of 10, beats 565 to 577)... 
+forward step
+backward step
+0.0 0.197 N
+0.197 1.869 C
+1.869 3.506 G
+3.506 5.166 A:min
+5.166 5.979 F:maj7
+5.979 6.815 F:maj6
+6.815 8.452 C
+8.452 10.077 G
+10.077 11.738 F
+11.738 14.559 C
+14.559 16.370 G
+16.370 18.158 A:min
+18.158 19.725 F
+19.725 21.293 C
+21.293 22.848 G
+22.848 23.650 F
+23.650 27.516 C
+27.516 29.013 G
+29.013 30.569 A:min
+30.569 32.171 F:maj6
+32.171 33.866 C
+33.866 35.585 G
+35.585 36.397 F
+36.397 36.804 C/3
+36.804 37.198 D:min7
+37.198 38.893 C
+38.893 40.565 A:min
+40.565 42.249 C/5
+42.249 44.234 F
+44.234 47.821 C
+47.821 49.551 G
+49.551 50.376 F
+50.376 53.685 C
+53.685 55.275 G
+55.275 56.877 A:min
+56.877 58.526 F
+58.526 60.116 C
+60.116 61.788 G
+61.788 62.613 F
+62.613 66.757 C
+66.757 68.394 G
+68.394 70.055 A:min
+70.055 71.761 F:maj6
+71.761 73.433 C
+73.433 75.117 G
+75.117 75.952 F
+75.952 76.382 C/3
+76.382 76.812 D:min7
+76.812 78.518 C
+78.518 80.260 A:min
+80.260 81.932 C/5
+81.932 83.592 F
+83.592 86.924 C
+86.924 88.584 G
+88.584 89.420 F
+89.420 91.893 C
+91.893 93.588 A:min
+93.588 95.248 C/5
+95.248 96.897 F
+96.897 100.229 C
+100.229 101.889 G
+101.889 103.584 F
+103.584 105.268 C
+105.268 106.127 F
+106.127 107.822 C/3
+107.822 108.263 Bb
+108.263 108.704 C:maj6
+108.704 109.598 G
+109.598 110.481 F
+110.481 115.705 C
+115.705 116.599 G
+116.599 117.481 F
+117.481 120.918 C
+120.918 122.648 G
+122.648 124.366 A:min
+124.366 126.084 F
+126.084 127.803 C
+127.803 129.486 G
+129.486 130.357 F
+130.357 134.676 C
+134.676 136.429 G
+136.429 138.159 A:min
+138.159 139.865 F:maj6
+139.865 141.572 C
+141.572 143.290 G
+143.290 144.161 F
+144.161 144.579 C/3
+144.579 145.009 D:min7
+145.009 146.762 C
+146.762 148.538 A:min
+148.538 150.314 C/5
+150.314 152.091 F
+152.091 155.620 C
+155.620 157.385 G
+157.385 158.279 F
+158.279 162.702 C
+162.702 164.455 G
+164.455 166.197 A:min
+166.197 167.938 F
+167.938 169.668 C
+169.668 171.386 G
+171.386 172.257 F
+172.257 176.646 C
+176.646 178.387 G
+178.387 180.106 A:min
+180.106 181.835 F:maj6
+181.835 183.565 C
+183.565 185.284 G
+185.284 186.154 F
+186.154 186.572 C/3
+186.572 187.002 D:min7
+187.002 188.720 C
+188.720 190.450 A:min
+190.450 192.192 C/5
+192.192 193.945 F
+193.945 197.451 C
+197.451 199.181 G
+199.181 200.052 F
+200.052 202.617 C
+202.617 204.359 A:min
+204.359 206.112 C/5
+206.112 207.853 F:maj7
+207.853 211.360 C
+211.360 213.078 G
+213.078 213.960 F
+213.960 216.514 C/3
+216.514 218.256 A:min
+218.256 220.021 C/5
+220.021 221.797 F
+221.797 225.245 C
+225.245 227.033 G
+227.033 228.798 F
+228.798 230.597 C
+230.597 231.503 F
+231.503 233.326 C/3
+233.326 233.767 Bb
+233.767 234.220 C:maj6
+234.220 234.986 G
+234.986 235.683 F
+235.683 240.965 C
+240.965 243.307 N0.0 0.197 N
+0.197 243.307 C
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_logfiles/Bangles.EternalFlame.wav.log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,362 @@
+CSVFeatureWriter::setParameters
+stdout -> 
+NOTE: Using default sample rate of 44100 for default transform
+NOTE: Loaded and initialised plugin for transform "vamp:matthiasm:nnls_chroma:bothchroma" with plugin step size 2048 and block size 16384 (adapter step and block size 16384)
+NOTE: PluginInputDomainAdapter timestamp adjustment is  0.000000000R
+Extracting features for: "/Users/matthias/Music/MUSICDB44k/Bangles.EternalFlame.wav"
+
Retrieving audio data... Done
+Opened 2-channel file or URL "/Users/matthias/Music/MUSICDB44k/Bangles.EternalFlame.wav"
+timestamp  0.000000000R: very low magnitude, setting magnitude to all zeros
+timestamp  0.046439909R: very low magnitude, setting magnitude to all zeros
+timestamp  0.092879818R: very low magnitude, setting magnitude to all zeros
+timestamp  0.139319727R: very low magnitude, setting magnitude to all zeros
+timestamp  0.185759637R: very low magnitude, setting magnitude to all zeros
+timestamp  0.232199546R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 1%
Extracting and writing features... 2%
Extracting and writing features... 3%
Extracting and writing features... 4%
Extracting and writing features... 5%
Extracting and writing features... 6%
Extracting and writing features... 7%
Extracting and writing features... 8%
Extracting and writing features... 9%
Extracting and writing features... 10%
Extracting and writing features... 11%
Extracting and writing features... 12%
Extracting and writing features... 13%
Extracting and writing features... 14%
Extracting and writing features... 15%
Extracting and writing features... 16%
Extracting and writing features... 17%
Extracting and writing features... 18%
Extracting and writing features... 19%
Extracting and writing features... 20%
Extracting and writing features... 21%
Extracting and writing features... 22%
Extracting and writing features... 23%
Extracting and writing features... 24%
Extracting and writing features... 25%
Extracting and writing features... 26%
Extracting and writing features... 27%
Extracting and writing features... 28%
Extracting and writing features... 29%
Extracting and writing features... 30%
Extracting and writing features... 31%
Extracting and writing features... 32%
Extracting and writing features... 33%
Extracting and writing features... 34%
Extracting and writing features... 35%
Extracting and writing features... 36%
Extracting and writing features... 37%
Extracting and writing features... 38%
Extracting and writing features... 39%
Extracting and writing features... 40%
Extracting and writing features... 41%
Extracting and writing features... 42%
Extracting and writing features... 43%
Extracting and writing features... 44%
Extracting and writing features... 45%
Extracting and writing features... 46%
Extracting and writing features... 47%
Extracting and writing features... 48%
Extracting and writing features... 49%
Extracting and writing features... 50%
Extracting and writing features... 51%
Extracting and writing features... 52%
Extracting and writing features... 53%
Extracting and writing features... 54%
Extracting and writing features... 55%
Extracting and writing features... 56%
Extracting and writing features... 57%
Extracting and writing features... 58%
Extracting and writing features... 59%
Extracting and writing features... 60%
Extracting and writing features... 61%
Extracting and writing features... 62%
Extracting and writing features... 63%
Extracting and writing features... 64%
Extracting and writing features... 65%
Extracting and writing features... 66%
Extracting and writing features... 67%
Extracting and writing features... 68%
Extracting and writing features... 69%
Extracting and writing features... 70%
Extracting and writing features... 71%
Extracting and writing features... 72%
Extracting and writing features... 73%
Extracting and writing features... 74%
Extracting and writing features... 75%
Extracting and writing features... 76%
Extracting and writing features... 77%
Extracting and writing features... 78%
Extracting and writing features... 79%
Extracting and writing features... 80%
Extracting and writing features... 81%
Extracting and writing features... 82%
Extracting and writing features... 83%
Extracting and writing features... 84%
Extracting and writing features... 85%
Extracting and writing features... 86%
Extracting and writing features... 87%
Extracting and writing features... 88%
Extracting and writing features... 89%
Extracting and writing features... 90%
Extracting and writing features... 91%
Extracting and writing features... 92%
Extracting and writing features... 93%
Extracting and writing features... 94%
Extracting and writing features... 95%timestamp  226.673197278R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 96%timestamp  228.902312925R: very low magnitude, setting magnitude to all zeros
+timestamp  229.552471655R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 97%timestamp  230.481269841R: very low magnitude, setting magnitude to all zeros
+timestamp  230.527709750R: very low magnitude, setting magnitude to all zeros
+timestamp  230.759909297R: very low magnitude, setting magnitude to all zeros
+timestamp  230.806349206R: very low magnitude, setting magnitude to all zeros
+timestamp  230.852789115R: very low magnitude, setting magnitude to all zeros
+timestamp  230.899229024R: very low magnitude, setting magnitude to all zeros
+timestamp  230.945668934R: very low magnitude, setting magnitude to all zeros
+timestamp  230.992108843R: very low magnitude, setting magnitude to all zeros
+timestamp  231.038548752R: very low magnitude, setting magnitude to all zeros
+timestamp  231.084988662R: very low magnitude, setting magnitude to all zeros
+timestamp  231.131428571R: very low magnitude, setting magnitude to all zeros
+timestamp  231.177868480R: very low magnitude, setting magnitude to all zeros
+timestamp  231.224308390R: very low magnitude, setting magnitude to all zeros
+timestamp  231.270748299R: very low magnitude, setting magnitude to all zeros
+timestamp  231.317188208R: very low magnitude, setting magnitude to all zeros
+timestamp  231.363628117R: very low magnitude, setting magnitude to all zeros
+timestamp  231.410068027R: very low magnitude, setting magnitude to all zeros
+timestamp  231.735147392R: very low magnitude, setting magnitude to all zeros
+timestamp  231.781587301R: very low magnitude, setting magnitude to all zeros
+timestamp  231.828027210R: very low magnitude, setting magnitude to all zeros
+timestamp  231.874467120R: very low magnitude, setting magnitude to all zeros
+timestamp  231.920907029R: very low magnitude, setting magnitude to all zeros
+timestamp  231.967346938R: very low magnitude, setting magnitude to all zeros
+timestamp  232.013786848R: very low magnitude, setting magnitude to all zeros
+timestamp  232.060226757R: very low magnitude, setting magnitude to all zeros
+timestamp  232.106666666R: very low magnitude, setting magnitude to all zeros
+timestamp  232.153106575R: very low magnitude, setting magnitude to all zeros
+timestamp  232.199546485R: very low magnitude, setting magnitude to all zeros
+timestamp  232.245986394R: very low magnitude, setting magnitude to all zeros
+timestamp  232.292426303R: very low magnitude, setting magnitude to all zeros
+timestamp  232.338866213R: very low magnitude, setting magnitude to all zeros
+timestamp  232.385306122R: very low magnitude, setting magnitude to all zeros
+timestamp  232.431746031R: very low magnitude, setting magnitude to all zeros
+timestamp  232.478185941R: very low magnitude, setting magnitude to all zeros
+timestamp  232.524625850R: very low magnitude, setting magnitude to all zeros
+timestamp  232.571065759R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 98%timestamp  232.617505668R: very low magnitude, setting magnitude to all zeros
+timestamp  232.663945578R: very low magnitude, setting magnitude to all zeros
+timestamp  232.710385487R: very low magnitude, setting magnitude to all zeros
+timestamp  232.756825396R: very low magnitude, setting magnitude to all zeros
+timestamp  232.803265306R: very low magnitude, setting magnitude to all zeros
+timestamp  232.849705215R: very low magnitude, setting magnitude to all zeros
+timestamp  232.896145124R: very low magnitude, setting magnitude to all zeros
+timestamp  232.942585034R: very low magnitude, setting magnitude to all zeros
+timestamp  232.989024943R: very low magnitude, setting magnitude to all zeros
+timestamp  233.035464852R: very low magnitude, setting magnitude to all zeros
+timestamp  233.081904761R: very low magnitude, setting magnitude to all zeros
+timestamp  233.128344671R: very low magnitude, setting magnitude to all zeros
+timestamp  233.174784580R: very low magnitude, setting magnitude to all zeros
+timestamp  233.221224489R: very low magnitude, setting magnitude to all zeros
+timestamp  233.267664399R: very low magnitude, setting magnitude to all zeros
+timestamp  233.314104308R: very low magnitude, setting magnitude to all zeros
+timestamp  233.360544217R: very low magnitude, setting magnitude to all zeros
+timestamp  233.406984126R: very low magnitude, setting magnitude to all zeros
+timestamp  233.453424036R: very low magnitude, setting magnitude to all zeros
+timestamp  233.499863945R: very low magnitude, setting magnitude to all zeros
+timestamp  233.546303854R: very low magnitude, setting magnitude to all zeros
+timestamp  233.592743764R: very low magnitude, setting magnitude to all zeros
+timestamp  233.639183673R: very low magnitude, setting magnitude to all zeros
+timestamp  233.685623582R: very low magnitude, setting magnitude to all zeros
+timestamp  233.732063492R: very low magnitude, setting magnitude to all zeros
+timestamp  233.778503401R: very low magnitude, setting magnitude to all zeros
+timestamp  233.824943310R: very low magnitude, setting magnitude to all zeros
+timestamp  233.871383219R: very low magnitude, setting magnitude to all zeros
+timestamp  233.917823129R: very low magnitude, setting magnitude to all zeros
+timestamp  233.964263038R: very low magnitude, setting magnitude to all zeros
+timestamp  234.010702947R: very low magnitude, setting magnitude to all zeros
+timestamp  234.057142857R: very low magnitude, setting magnitude to all zeros
+timestamp  234.103582766R: very low magnitude, setting magnitude to all zeros
+timestamp  234.150022675R: very low magnitude, setting magnitude to all zeros
+timestamp  234.196462585R: very low magnitude, setting magnitude to all zeros
+timestamp  234.242902494R: very low magnitude, setting magnitude to all zeros
+timestamp  234.289342403R: very low magnitude, setting magnitude to all zeros
+timestamp  234.335782312R: very low magnitude, setting magnitude to all zeros
+timestamp  234.382222222R: very low magnitude, setting magnitude to all zeros
+timestamp  234.428662131R: very low magnitude, setting magnitude to all zeros
+timestamp  234.475102040R: very low magnitude, setting magnitude to all zeros
+timestamp  234.521541950R: very low magnitude, setting magnitude to all zeros
+timestamp  234.567981859R: very low magnitude, setting magnitude to all zeros
+timestamp  234.614421768R: very low magnitude, setting magnitude to all zeros
+timestamp  234.660861678R: very low magnitude, setting magnitude to all zeros
+timestamp  234.707301587R: very low magnitude, setting magnitude to all zeros
+timestamp  234.753741496R: very low magnitude, setting magnitude to all zeros
+timestamp  234.800181405R: very low magnitude, setting magnitude to all zeros
+timestamp  234.846621315R: very low magnitude, setting magnitude to all zeros
+timestamp  234.893061224R: very low magnitude, setting magnitude to all zeros
+timestamp  234.939501133R: very low magnitude, setting magnitude to all zeros
+timestamp  234.985941043R: very low magnitude, setting magnitude to all zeros
+timestamp  235.032380952R: very low magnitude, setting magnitude to all zeros
+timestamp  235.078820861R: very low magnitude, setting magnitude to all zeros
+timestamp  235.125260770R: very low magnitude, setting magnitude to all zeros
+timestamp  235.171700680R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 99%timestamp  235.218140589R: very low magnitude, setting magnitude to all zeros
+timestamp  235.264580498R: very low magnitude, setting magnitude to all zeros
+timestamp  235.311020408R: very low magnitude, setting magnitude to all zeros
+timestamp  235.357460317R: very low magnitude, setting magnitude to all zeros
+timestamp  235.403900226R: very low magnitude, setting magnitude to all zeros
+timestamp  235.450340136R: very low magnitude, setting magnitude to all zeros
+timestamp  235.496780045R: very low magnitude, setting magnitude to all zeros
+timestamp  235.543219954R: very low magnitude, setting magnitude to all zeros
+timestamp  235.589659863R: very low magnitude, setting magnitude to all zeros
+timestamp  235.636099773R: very low magnitude, setting magnitude to all zeros
+timestamp  235.682539682R: very low magnitude, setting magnitude to all zeros
+timestamp  235.728979591R: very low magnitude, setting magnitude to all zeros
+timestamp  235.775419501R: very low magnitude, setting magnitude to all zeros
+timestamp  235.821859410R: very low magnitude, setting magnitude to all zeros
+timestamp  235.868299319R: very low magnitude, setting magnitude to all zeros
+timestamp  235.914739229R: very low magnitude, setting magnitude to all zeros
+timestamp  235.961179138R: very low magnitude, setting magnitude to all zeros
+timestamp  236.007619047R: very low magnitude, setting magnitude to all zeros
+timestamp  236.054058956R: very low magnitude, setting magnitude to all zeros
+timestamp  236.100498866R: very low magnitude, setting magnitude to all zeros
+timestamp  236.146938775R: very low magnitude, setting magnitude to all zeros
+timestamp  236.193378684R: very low magnitude, setting magnitude to all zeros
+timestamp  236.239818594R: very low magnitude, setting magnitude to all zeros
+timestamp  236.286258503R: very low magnitude, setting magnitude to all zeros
+timestamp  236.332698412R: very low magnitude, setting magnitude to all zeros
+timestamp  236.379138321R: very low magnitude, setting magnitude to all zeros
+timestamp  236.425578231R: very low magnitude, setting magnitude to all zeros
+timestamp  236.472018140R: very low magnitude, setting magnitude to all zeros
+timestamp  236.518458049R: very low magnitude, setting magnitude to all zeros
+timestamp  236.564897959R: very low magnitude, setting magnitude to all zeros
+timestamp  236.611337868R: very low magnitude, setting magnitude to all zeros
+timestamp  236.657777777R: very low magnitude, setting magnitude to all zeros
+timestamp  236.704217687R: very low magnitude, setting magnitude to all zeros
+timestamp  236.750657596R: very low magnitude, setting magnitude to all zeros
+timestamp  236.797097505R: very low magnitude, setting magnitude to all zeros
+timestamp  236.843537414R: very low magnitude, setting magnitude to all zeros
+timestamp  236.889977324R: very low magnitude, setting magnitude to all zeros
+timestamp  236.936417233R: very low magnitude, setting magnitude to all zeros
+timestamp  236.982857142R: very low magnitude, setting magnitude to all zeros
+timestamp  237.029297052R: very low magnitude, setting magnitude to all zeros
+timestamp  237.075736961R: very low magnitude, setting magnitude to all zeros
+timestamp  237.122176870R: very low magnitude, setting magnitude to all zeros
+timestamp  237.168616780R: very low magnitude, setting magnitude to all zeros
+timestamp  237.215056689R: very low magnitude, setting magnitude to all zeros
+timestamp  237.261496598R: very low magnitude, setting magnitude to all zeros
+timestamp  237.307936507R: very low magnitude, setting magnitude to all zeros
+timestamp  237.354376417R: very low magnitude, setting magnitude to all zeros
+timestamp  237.400816326R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 100%timestamp  237.447256235R: very low magnitude, setting magnitude to all zeros
+[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... done.
+[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... done.
+[NNLS Chroma Plugin] Chord Estimation ... done.
+
Extracting and writing features... Done
+
+                              < M A T L A B >
+                  Copyright 1984-2007 The MathWorks, Inc.
+                         Version 7.5.0.338 (R2007b)
+                               August 9, 2007
+
+ 
+  To get started, type one of these: helpwin, helpdesk, or demo.
+  For product information, visit www.mathworks.com.
+ 
+   - First Slice
+    metpos 
+    key 
+    chord 
+    bass 
+   - Second Slice
+    (7) metpos (slice 2) 
+    (8) key (slice 2) 
+    (9) chord (slice 2) 
+    (10) bass (slice 2) 
+onset detection function
+beats
+
+
Length: 28
Length: 32
Length: 36
Length: 40
Length: 44
Length: 48
Length: 52
Length: 56
Length: 60
Length: 64
Length: 68
Length: 72
Length: 76
Length: 80
Length: 84
Length: 88
Length: 92
Length: 96
Length: 100
Length: 104
Length: 108
Length: 112
Length: 116
Length: 120
Length: 124
Length: 128
+Finding maximum probability path (part 1 of 11, beats 1 to 17)... 
+forward step
+backward step
+
+Finding maximum probability path (part 2 of 11, beats 18 to 89)... 
+forward step
+backward step
+
+Finding maximum probability path (part 3 of 11, beats 90 to 161)... 
+forward step
+backward step
+
+Finding maximum probability path (part 4 of 11, beats 162 to 217)... 
+forward step
+backward step
+
+Finding maximum probability path (part 5 of 11, beats 218 to 257)... 
+forward step
+backward step
+
+Finding maximum probability path (part 6 of 11, beats 258 to 313)... 
+forward step
+backward step
+
+Finding maximum probability path (part 7 of 11, beats 314 to 385)... 
+forward step
+backward step
+
+Finding maximum probability path (part 8 of 11, beats 386 to 457)... 
+forward step
+backward step
+
+Finding maximum probability path (part 9 of 11, beats 458 to 529)... 
+forward step
+backward step
+
+Finding maximum probability path (part 10 of 11, beats 530 to 601)... 
+forward step
+backward step
+
+Finding maximum probability path (part 11 of 11, beats 602 to 626)... 
+forward step
+backward step
+0.0 0.023 N
+0.023 0.348 N
+0.348 1.869 G
+1.869 3.379 C/5
+3.379 7.941 G
+7.941 9.462 E:min7
+9.462 10.983 C
+10.983 12.492 D
+12.492 15.523 G
+15.523 17.043 C
+17.043 18.564 D
+18.564 20.085 E:min
+20.085 21.606 B
+21.606 23.139 E:min
+23.139 24.648 A
+24.648 26.157 D
+26.157 27.678 B:min
+27.678 33.750 A:min7
+33.750 35.260 G
+35.260 36.769 E:min7
+36.769 38.301 C
+38.301 39.822 D
+39.822 42.864 G
+42.864 44.373 C
+44.373 45.906 D
+45.906 47.427 E:min
+47.427 48.924 B
+48.924 50.434 E:min
+50.434 51.966 A
+51.966 53.487 D
+53.487 54.996 B:min
+54.996 61.068 A:min7
+61.068 62.624 D
+62.624 64.134 D:min7
+64.134 65.260 G/5
+65.260 67.152 D
+67.152 68.661 F
+68.661 70.182 G
+70.182 70.937 C
+70.937 71.703 G/3
+71.703 72.469 A:min7
+72.469 73.224 C/5
+73.224 74.745 D
+74.745 76.266 B:min
+76.266 77.392 F/5
+77.392 79.296 C
+79.296 82.303 D
+82.303 83.847 E:min
+83.847 85.368 B
+85.368 86.877 E:min
+86.877 88.398 A
+88.398 89.908 D
+89.908 91.429 B:min7
+91.429 94.470 A:min7
+94.470 95.225 D/5
+95.225 97.512 A:min
+97.512 99.021 D
+99.021 100.542 D:min7
+100.542 101.680 G/5
+101.680 103.573 D
+103.573 105.105 F
+105.105 106.638 G
+106.638 107.381 C
+107.381 108.124 G/3
+108.124 108.890 A:min7
+108.890 109.656 C/5
+109.656 111.177 D
+111.177 112.721 B:min
+112.721 113.836 F/5
+113.836 115.728 C
+115.728 118.758 D
+118.758 120.279 G
+120.279 121.789 E:min7
+121.789 123.310 C
+123.310 124.830 D
+124.830 127.872 G
+127.872 129.393 C
+129.393 130.914 D
+130.914 132.447 E:min
+132.447 133.933 B
+133.933 135.477 E:min
+135.477 136.986 A
+136.986 138.495 D
+138.495 140.028 B:min
+140.028 146.077 A:min7
+146.077 147.598 G
+147.598 149.130 E:min7
+149.130 150.651 C
+150.651 152.160 D
+152.160 155.191 G
+155.191 156.723 C
+156.723 158.244 D
+158.244 159.753 E:min
+159.753 161.263 B
+161.263 162.783 E:min
+162.783 164.293 A
+164.293 165.814 D
+165.814 167.358 B:min
+167.358 173.430 A:min7
+173.430 174.928 G
+174.928 176.448 E:min7
+176.448 177.969 C
+177.969 179.490 D
+179.490 182.509 G
+182.509 184.041 C
+184.041 185.562 D
+185.562 187.095 E:min
+187.095 188.604 B
+188.604 190.102 E:min
+190.102 191.634 A
+191.634 193.132 D
+193.132 194.676 B:min
+194.676 200.737 A:min7
+200.737 202.257 G
+202.257 203.790 E:min7
+203.790 205.299 C
+205.299 206.809 D
+206.809 209.850 G
+209.850 211.383 C
+211.383 212.892 D
+212.892 214.413 E:min
+214.413 215.922 B
+215.922 217.443 E:min
+217.443 218.964 A
+218.964 220.473 D
+220.473 222.006 B:min
+222.006 228.078 A:min7
+228.078 229.587 G
+229.587 230.725 E:min7
+230.725 237.533 N0.0 0.023 N
+0.023 82.303 G
+82.303 97.512 D
+97.512 237.533 G
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_logfiles/DuranDuran.OrdinaryWorld.wav.log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,438 @@
+CSVFeatureWriter::setParameters
+stdout -> 
+NOTE: Using default sample rate of 44100 for default transform
+NOTE: Loaded and initialised plugin for transform "vamp:matthiasm:nnls_chroma:bothchroma" with plugin step size 2048 and block size 16384 (adapter step and block size 16384)
+NOTE: PluginInputDomainAdapter timestamp adjustment is  0.000000000R
+Extracting features for: "/Users/matthias/Music/MUSICDB44k/DuranDuran.OrdinaryWorld.wav"
+
Retrieving audio data... Done
+Opened 2-channel file or URL "/Users/matthias/Music/MUSICDB44k/DuranDuran.OrdinaryWorld.wav"
+timestamp  0.000000000R: very low magnitude, setting magnitude to all zeros
+timestamp  0.046439909R: very low magnitude, setting magnitude to all zeros
+timestamp  0.092879818R: very low magnitude, setting magnitude to all zeros
+timestamp  0.139319727R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 1%
Extracting and writing features... 2%
Extracting and writing features... 3%
Extracting and writing features... 4%
Extracting and writing features... 5%
Extracting and writing features... 6%
Extracting and writing features... 7%
Extracting and writing features... 8%
Extracting and writing features... 9%
Extracting and writing features... 10%
Extracting and writing features... 11%
Extracting and writing features... 12%
Extracting and writing features... 13%
Extracting and writing features... 14%
Extracting and writing features... 15%
Extracting and writing features... 16%
Extracting and writing features... 17%
Extracting and writing features... 18%
Extracting and writing features... 19%
Extracting and writing features... 20%
Extracting and writing features... 21%
Extracting and writing features... 22%
Extracting and writing features... 23%
Extracting and writing features... 24%
Extracting and writing features... 25%
Extracting and writing features... 26%
Extracting and writing features... 27%
Extracting and writing features... 28%
Extracting and writing features... 29%
Extracting and writing features... 30%
Extracting and writing features... 31%
Extracting and writing features... 32%
Extracting and writing features... 33%
Extracting and writing features... 34%
Extracting and writing features... 35%
Extracting and writing features... 36%
Extracting and writing features... 37%
Extracting and writing features... 38%
Extracting and writing features... 39%
Extracting and writing features... 40%
Extracting and writing features... 41%
Extracting and writing features... 42%
Extracting and writing features... 43%
Extracting and writing features... 44%
Extracting and writing features... 45%
Extracting and writing features... 46%
Extracting and writing features... 47%
Extracting and writing features... 48%
Extracting and writing features... 49%
Extracting and writing features... 50%
Extracting and writing features... 51%
Extracting and writing features... 52%
Extracting and writing features... 53%
Extracting and writing features... 54%
Extracting and writing features... 55%
Extracting and writing features... 56%
Extracting and writing features... 57%
Extracting and writing features... 58%
Extracting and writing features... 59%
Extracting and writing features... 60%
Extracting and writing features... 61%
Extracting and writing features... 62%
Extracting and writing features... 63%
Extracting and writing features... 64%
Extracting and writing features... 65%
Extracting and writing features... 66%
Extracting and writing features... 67%
Extracting and writing features... 68%
Extracting and writing features... 69%
Extracting and writing features... 70%
Extracting and writing features... 71%
Extracting and writing features... 72%
Extracting and writing features... 73%
Extracting and writing features... 74%
Extracting and writing features... 75%
Extracting and writing features... 76%
Extracting and writing features... 77%
Extracting and writing features... 78%
Extracting and writing features... 79%
Extracting and writing features... 80%
Extracting and writing features... 81%
Extracting and writing features... 82%
Extracting and writing features... 83%
Extracting and writing features... 84%
Extracting and writing features... 85%
Extracting and writing features... 86%
Extracting and writing features... 87%
Extracting and writing features... 88%
Extracting and writing features... 89%
Extracting and writing features... 90%
Extracting and writing features... 91%
Extracting and writing features... 92%
Extracting and writing features... 93%
Extracting and writing features... 94%
Extracting and writing features... 95%
Extracting and writing features... 96%
Extracting and writing features... 97%timestamp  333.067029478R: very low magnitude, setting magnitude to all zeros
+timestamp  333.113469387R: very low magnitude, setting magnitude to all zeros
+timestamp  333.159909297R: very low magnitude, setting magnitude to all zeros
+timestamp  333.206349206R: very low magnitude, setting magnitude to all zeros
+timestamp  333.252789115R: very low magnitude, setting magnitude to all zeros
+timestamp  333.299229024R: very low magnitude, setting magnitude to all zeros
+timestamp  333.345668934R: very low magnitude, setting magnitude to all zeros
+timestamp  333.392108843R: very low magnitude, setting magnitude to all zeros
+timestamp  333.438548752R: very low magnitude, setting magnitude to all zeros
+timestamp  333.484988662R: very low magnitude, setting magnitude to all zeros
+timestamp  333.531428571R: very low magnitude, setting magnitude to all zeros
+timestamp  333.577868480R: very low magnitude, setting magnitude to all zeros
+timestamp  333.624308390R: very low magnitude, setting magnitude to all zeros
+timestamp  333.670748299R: very low magnitude, setting magnitude to all zeros
+timestamp  333.717188208R: very low magnitude, setting magnitude to all zeros
+timestamp  333.763628117R: very low magnitude, setting magnitude to all zeros
+timestamp  333.810068027R: very low magnitude, setting magnitude to all zeros
+timestamp  333.856507936R: very low magnitude, setting magnitude to all zeros
+timestamp  333.902947845R: very low magnitude, setting magnitude to all zeros
+timestamp  333.949387755R: very low magnitude, setting magnitude to all zeros
+timestamp  333.995827664R: very low magnitude, setting magnitude to all zeros
+timestamp  334.042267573R: very low magnitude, setting magnitude to all zeros
+timestamp  334.088707482R: very low magnitude, setting magnitude to all zeros
+timestamp  334.135147392R: very low magnitude, setting magnitude to all zeros
+timestamp  334.181587301R: very low magnitude, setting magnitude to all zeros
+timestamp  334.228027210R: very low magnitude, setting magnitude to all zeros
+timestamp  334.274467120R: very low magnitude, setting magnitude to all zeros
+timestamp  334.320907029R: very low magnitude, setting magnitude to all zeros
+timestamp  334.367346938R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 98%timestamp  334.413786848R: very low magnitude, setting magnitude to all zeros
+timestamp  334.460226757R: very low magnitude, setting magnitude to all zeros
+timestamp  334.506666666R: very low magnitude, setting magnitude to all zeros
+timestamp  334.553106575R: very low magnitude, setting magnitude to all zeros
+timestamp  334.599546485R: very low magnitude, setting magnitude to all zeros
+timestamp  334.645986394R: very low magnitude, setting magnitude to all zeros
+timestamp  334.692426303R: very low magnitude, setting magnitude to all zeros
+timestamp  334.738866213R: very low magnitude, setting magnitude to all zeros
+timestamp  334.785306122R: very low magnitude, setting magnitude to all zeros
+timestamp  334.831746031R: very low magnitude, setting magnitude to all zeros
+timestamp  334.878185941R: very low magnitude, setting magnitude to all zeros
+timestamp  334.924625850R: very low magnitude, setting magnitude to all zeros
+timestamp  334.971065759R: very low magnitude, setting magnitude to all zeros
+timestamp  335.017505668R: very low magnitude, setting magnitude to all zeros
+timestamp  335.063945578R: very low magnitude, setting magnitude to all zeros
+timestamp  335.110385487R: very low magnitude, setting magnitude to all zeros
+timestamp  335.156825396R: very low magnitude, setting magnitude to all zeros
+timestamp  335.203265306R: very low magnitude, setting magnitude to all zeros
+timestamp  335.249705215R: very low magnitude, setting magnitude to all zeros
+timestamp  335.296145124R: very low magnitude, setting magnitude to all zeros
+timestamp  335.342585034R: very low magnitude, setting magnitude to all zeros
+timestamp  335.389024943R: very low magnitude, setting magnitude to all zeros
+timestamp  335.435464852R: very low magnitude, setting magnitude to all zeros
+timestamp  335.481904761R: very low magnitude, setting magnitude to all zeros
+timestamp  335.528344671R: very low magnitude, setting magnitude to all zeros
+timestamp  335.574784580R: very low magnitude, setting magnitude to all zeros
+timestamp  335.621224489R: very low magnitude, setting magnitude to all zeros
+timestamp  335.667664399R: very low magnitude, setting magnitude to all zeros
+timestamp  335.714104308R: very low magnitude, setting magnitude to all zeros
+timestamp  335.760544217R: very low magnitude, setting magnitude to all zeros
+timestamp  335.806984126R: very low magnitude, setting magnitude to all zeros
+timestamp  335.853424036R: very low magnitude, setting magnitude to all zeros
+timestamp  335.899863945R: very low magnitude, setting magnitude to all zeros
+timestamp  335.946303854R: very low magnitude, setting magnitude to all zeros
+timestamp  335.992743764R: very low magnitude, setting magnitude to all zeros
+timestamp  336.039183673R: very low magnitude, setting magnitude to all zeros
+timestamp  336.085623582R: very low magnitude, setting magnitude to all zeros
+timestamp  336.132063492R: very low magnitude, setting magnitude to all zeros
+timestamp  336.178503401R: very low magnitude, setting magnitude to all zeros
+timestamp  336.224943310R: very low magnitude, setting magnitude to all zeros
+timestamp  336.271383219R: very low magnitude, setting magnitude to all zeros
+timestamp  336.317823129R: very low magnitude, setting magnitude to all zeros
+timestamp  336.364263038R: very low magnitude, setting magnitude to all zeros
+timestamp  336.410702947R: very low magnitude, setting magnitude to all zeros
+timestamp  336.457142857R: very low magnitude, setting magnitude to all zeros
+timestamp  336.503582766R: very low magnitude, setting magnitude to all zeros
+timestamp  336.550022675R: very low magnitude, setting magnitude to all zeros
+timestamp  336.596462585R: very low magnitude, setting magnitude to all zeros
+timestamp  336.642902494R: very low magnitude, setting magnitude to all zeros
+timestamp  336.689342403R: very low magnitude, setting magnitude to all zeros
+timestamp  336.735782312R: very low magnitude, setting magnitude to all zeros
+timestamp  336.782222222R: very low magnitude, setting magnitude to all zeros
+timestamp  336.828662131R: very low magnitude, setting magnitude to all zeros
+timestamp  336.875102040R: very low magnitude, setting magnitude to all zeros
+timestamp  336.921541950R: very low magnitude, setting magnitude to all zeros
+timestamp  336.967981859R: very low magnitude, setting magnitude to all zeros
+timestamp  337.014421768R: very low magnitude, setting magnitude to all zeros
+timestamp  337.060861678R: very low magnitude, setting magnitude to all zeros
+timestamp  337.107301587R: very low magnitude, setting magnitude to all zeros
+timestamp  337.153741496R: very low magnitude, setting magnitude to all zeros
+timestamp  337.200181405R: very low magnitude, setting magnitude to all zeros
+timestamp  337.246621315R: very low magnitude, setting magnitude to all zeros
+timestamp  337.293061224R: very low magnitude, setting magnitude to all zeros
+timestamp  337.339501133R: very low magnitude, setting magnitude to all zeros
+timestamp  337.385941043R: very low magnitude, setting magnitude to all zeros
+timestamp  337.432380952R: very low magnitude, setting magnitude to all zeros
+timestamp  337.478820861R: very low magnitude, setting magnitude to all zeros
+timestamp  337.525260770R: very low magnitude, setting magnitude to all zeros
+timestamp  337.571700680R: very low magnitude, setting magnitude to all zeros
+timestamp  337.618140589R: very low magnitude, setting magnitude to all zeros
+timestamp  337.664580498R: very low magnitude, setting magnitude to all zeros
+timestamp  337.711020408R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 99%timestamp  337.757460317R: very low magnitude, setting magnitude to all zeros
+timestamp  337.803900226R: very low magnitude, setting magnitude to all zeros
+timestamp  337.850340136R: very low magnitude, setting magnitude to all zeros
+timestamp  337.896780045R: very low magnitude, setting magnitude to all zeros
+timestamp  337.943219954R: very low magnitude, setting magnitude to all zeros
+timestamp  337.989659863R: very low magnitude, setting magnitude to all zeros
+timestamp  338.036099773R: very low magnitude, setting magnitude to all zeros
+timestamp  338.082539682R: very low magnitude, setting magnitude to all zeros
+timestamp  338.128979591R: very low magnitude, setting magnitude to all zeros
+timestamp  338.175419501R: very low magnitude, setting magnitude to all zeros
+timestamp  338.221859410R: very low magnitude, setting magnitude to all zeros
+timestamp  338.268299319R: very low magnitude, setting magnitude to all zeros
+timestamp  338.314739229R: very low magnitude, setting magnitude to all zeros
+timestamp  338.361179138R: very low magnitude, setting magnitude to all zeros
+timestamp  338.407619047R: very low magnitude, setting magnitude to all zeros
+timestamp  338.454058956R: very low magnitude, setting magnitude to all zeros
+timestamp  338.500498866R: very low magnitude, setting magnitude to all zeros
+timestamp  338.546938775R: very low magnitude, setting magnitude to all zeros
+timestamp  338.593378684R: very low magnitude, setting magnitude to all zeros
+timestamp  338.639818594R: very low magnitude, setting magnitude to all zeros
+timestamp  338.686258503R: very low magnitude, setting magnitude to all zeros
+timestamp  338.732698412R: very low magnitude, setting magnitude to all zeros
+timestamp  338.779138321R: very low magnitude, setting magnitude to all zeros
+timestamp  338.825578231R: very low magnitude, setting magnitude to all zeros
+timestamp  338.872018140R: very low magnitude, setting magnitude to all zeros
+timestamp  338.918458049R: very low magnitude, setting magnitude to all zeros
+timestamp  338.964897959R: very low magnitude, setting magnitude to all zeros
+timestamp  339.011337868R: very low magnitude, setting magnitude to all zeros
+timestamp  339.057777777R: very low magnitude, setting magnitude to all zeros
+timestamp  339.104217687R: very low magnitude, setting magnitude to all zeros
+timestamp  339.150657596R: very low magnitude, setting magnitude to all zeros
+timestamp  339.197097505R: very low magnitude, setting magnitude to all zeros
+timestamp  339.243537414R: very low magnitude, setting magnitude to all zeros
+timestamp  339.289977324R: very low magnitude, setting magnitude to all zeros
+timestamp  339.336417233R: very low magnitude, setting magnitude to all zeros
+timestamp  339.382857142R: very low magnitude, setting magnitude to all zeros
+timestamp  339.429297052R: very low magnitude, setting magnitude to all zeros
+timestamp  339.475736961R: very low magnitude, setting magnitude to all zeros
+timestamp  339.522176870R: very low magnitude, setting magnitude to all zeros
+timestamp  339.568616780R: very low magnitude, setting magnitude to all zeros
+timestamp  339.615056689R: very low magnitude, setting magnitude to all zeros
+timestamp  339.661496598R: very low magnitude, setting magnitude to all zeros
+timestamp  339.707936507R: very low magnitude, setting magnitude to all zeros
+timestamp  339.754376417R: very low magnitude, setting magnitude to all zeros
+timestamp  339.800816326R: very low magnitude, setting magnitude to all zeros
+timestamp  339.847256235R: very low magnitude, setting magnitude to all zeros
+timestamp  339.893696145R: very low magnitude, setting magnitude to all zeros
+timestamp  339.940136054R: very low magnitude, setting magnitude to all zeros
+timestamp  339.986575963R: very low magnitude, setting magnitude to all zeros
+timestamp  340.033015873R: very low magnitude, setting magnitude to all zeros
+timestamp  340.079455782R: very low magnitude, setting magnitude to all zeros
+timestamp  340.125895691R: very low magnitude, setting magnitude to all zeros
+timestamp  340.172335600R: very low magnitude, setting magnitude to all zeros
+timestamp  340.218775510R: very low magnitude, setting magnitude to all zeros
+timestamp  340.265215419R: very low magnitude, setting magnitude to all zeros
+timestamp  340.311655328R: very low magnitude, setting magnitude to all zeros
+timestamp  340.358095238R: very low magnitude, setting magnitude to all zeros
+timestamp  340.404535147R: very low magnitude, setting magnitude to all zeros
+timestamp  340.450975056R: very low magnitude, setting magnitude to all zeros
+timestamp  340.497414965R: very low magnitude, setting magnitude to all zeros
+timestamp  340.543854875R: very low magnitude, setting magnitude to all zeros
+timestamp  340.590294784R: very low magnitude, setting magnitude to all zeros
+timestamp  340.636734693R: very low magnitude, setting magnitude to all zeros
+timestamp  340.683174603R: very low magnitude, setting magnitude to all zeros
+timestamp  340.729614512R: very low magnitude, setting magnitude to all zeros
+timestamp  340.776054421R: very low magnitude, setting magnitude to all zeros
+timestamp  340.822494331R: very low magnitude, setting magnitude to all zeros
+timestamp  340.868934240R: very low magnitude, setting magnitude to all zeros
+timestamp  340.915374149R: very low magnitude, setting magnitude to all zeros
+timestamp  340.961814058R: very low magnitude, setting magnitude to all zeros
+timestamp  341.008253968R: very low magnitude, setting magnitude to all zeros
+timestamp  341.054693877R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 100%timestamp  341.101133786R: very low magnitude, setting magnitude to all zeros
+[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... done.
+[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... done.
+[NNLS Chroma Plugin] Chord Estimation ... done.
+
Extracting and writing features... Done
+
+                              < M A T L A B >
+                  Copyright 1984-2007 The MathWorks, Inc.
+                         Version 7.5.0.338 (R2007b)
+                               August 9, 2007
+
+ 
+  To get started, type one of these: helpwin, helpdesk, or demo.
+  For product information, visit www.mathworks.com.
+ 
+   - First Slice
+    metpos 
+    key 
+    chord 
+    bass 
+   - Second Slice
+    (7) metpos (slice 2) 
+    (8) key (slice 2) 
+    (9) chord (slice 2) 
+    (10) bass (slice 2) 
+onset detection function
+beats
+
+
Length: 28
Length: 32
Length: 36
Length: 40
Length: 44
Length: 48
Length: 52
Length: 56
Length: 60
Length: 64
Length: 68
Length: 72
Length: 76
Length: 80
Length: 84
Length: 88
Length: 92
Length: 96
Length: 100
Length: 104
Length: 108
Length: 112
Length: 116
Length: 120
Length: 124
Length: 128
+Finding maximum probability path (part 1 of 28, beats 1 to 29)... 
+forward step
+backward step
+
+Finding maximum probability path (part 2 of 28, beats 30 to 57)... 
+forward step
+backward step
+
+Finding maximum probability path (part 3 of 28, beats 58 to 70)... 
+forward step
+backward step
+
+Finding maximum probability path (part 4 of 28, beats 71 to 102)... 
+forward step
+backward step
+
+Finding maximum probability path (part 5 of 28, beats 103 to 134)... 
+forward step
+backward step
+
+Finding maximum probability path (part 6 of 28, beats 135 to 157)... 
+forward step
+backward step
+
+Finding maximum probability path (part 7 of 28, beats 158 to 189)... 
+forward step
+backward step
+
+Finding maximum probability path (part 8 of 28, beats 190 to 217)... 
+forward step
+backward step
+
+Finding maximum probability path (part 9 of 28, beats 218 to 246)... 
+forward step
+backward step
+
+Finding maximum probability path (part 10 of 28, beats 247 to 278)... 
+forward step
+backward step
+
+Finding maximum probability path (part 11 of 28, beats 279 to 310)... 
+forward step
+backward step
+
+Finding maximum probability path (part 12 of 28, beats 311 to 334)... 
+forward step
+backward step
+
+Finding maximum probability path (part 13 of 28, beats 335 to 365)... 
+forward step
+backward step
+
+Finding maximum probability path (part 14 of 28, beats 366 to 398)... 
+forward step
+backward step
+
+Finding maximum probability path (part 15 of 28, beats 399 to 430)... 
+forward step
+backward step
+
+Finding maximum probability path (part 16 of 28, beats 431 to 458)... 
+forward step
+backward step
+
+Finding maximum probability path (part 17 of 28, beats 459 to 470)... 
+forward step
+backward step
+
+Finding maximum probability path (part 18 of 28, beats 471 to 502)... 
+forward step
+backward step
+
+Finding maximum probability path (part 19 of 28, beats 503 to 523)... 
+forward step
+backward step
+
+Finding maximum probability path (part 20 of 28, beats 524 to 558)... 
+forward step
+backward step
+
+Finding maximum probability path (part 21 of 28, beats 559 to 590)... 
+forward step
+backward step
+
+Finding maximum probability path (part 22 of 28, beats 591 to 621)... 
+forward step
+backward step
+
+Finding maximum probability path (part 23 of 28, beats 622 to 654)... 
+forward step
+backward step
+
+Finding maximum probability path (part 24 of 28, beats 655 to 686)... 
+forward step
+backward step
+
+Finding maximum probability path (part 25 of 28, beats 687 to 718)... 
+forward step
+backward step
+
+Finding maximum probability path (part 26 of 28, beats 719 to 751)... 
+forward step
+backward step
+
+Finding maximum probability path (part 27 of 28, beats 752 to 779)... 
+forward step
+backward step
+
+Finding maximum probability path (part 28 of 28, beats 780 to 796)... 
+forward step
+backward step
+0.0 0.163 N
+0.163 1.265 N
+1.265 4.679 B
+4.679 8.115 F#:min7
+8.115 11.552 A
+11.552 14.977 E
+14.977 18.402 B
+18.402 22.709 F#:min7
+22.709 25.263 A
+25.263 28.688 Bbb:min
+28.688 32.113 Db:min
+32.113 33.820 Fb:maj6
+33.820 35.109 Gb:min
+35.109 38.963 Db:min
+38.963 40.681 Fb
+40.681 41.970 Cb/5
+41.970 45.825 Db:min
+45.825 47.531 Fb:maj6
+47.531 48.820 Gb:min
+48.820 52.674 Db:min
+52.674 54.393 Fb
+54.393 55.670 Cb/5
+55.670 59.536 Db:min
+59.536 62.949 Ab:min
+62.949 66.386 Eb:7
+66.386 69.799 Fb
+69.799 73.236 B
+73.236 77.520 F#:min7
+77.520 80.086 A/3
+80.086 83.499 E
+83.499 86.947 B
+86.947 91.231 F#:min7
+91.231 93.797 A
+93.797 97.210 Gb:dim
+97.210 107.497 Db:min
+107.497 109.215 Fb:maj6
+109.215 110.504 Gb:min
+110.504 114.347 Db:min
+114.347 116.065 Fb
+116.065 117.342 Cb/5
+117.342 121.197 Db:min
+121.197 122.926 Fb:maj6
+122.926 124.204 Gb:min
+124.204 128.046 Db:min
+128.046 129.765 Fb
+129.765 131.042 Cb/5
+131.042 134.920 Db:min
+134.920 138.344 Ab:min
+138.344 141.781 Eb:7
+141.781 145.194 Fb
+145.194 148.631 B
+148.631 156.340 F#:min7
+156.340 158.906 E
+158.906 162.331 B
+162.331 166.615 F#:min7
+166.615 169.181 A/3
+169.181 172.617 E
+172.617 176.042 B
+176.042 180.315 F#:min7
+180.315 182.892 A
+182.892 186.317 E
+186.317 189.742 B
+189.742 194.026 F#:min7
+194.026 196.603 A
+196.603 200.028 Bbb:min
+200.028 203.465 Db:min
+203.465 205.172 Fb:maj6
+205.172 206.449 Gb:min
+206.449 210.303 Db:min
+210.303 212.033 Fb
+212.033 213.299 Cb/5
+213.299 218.442 Db:min
+218.442 219.301 Fb:min
+219.301 220.148 Gb
+220.148 224.015 Db:min
+224.015 226.580 E
+226.580 230.017 B
+230.017 237.726 F#:min7
+237.726 241.139 E
+241.139 244.576 B
+244.576 251.426 F#:min7
+251.426 254.839 E
+254.839 258.276 B
+258.276 262.560 F#:min7
+262.560 265.125 A
+265.125 268.562 E
+268.562 271.987 B
+271.987 276.271 F#:min7
+276.271 278.837 A
+278.837 282.680 E
+282.680 286.116 B
+286.116 292.978 F#:min7
+292.978 296.403 E
+296.403 299.828 B
+299.828 306.678 F#:min7
+306.678 310.114 E
+310.114 313.539 B
+313.539 320.389 F#:min7
+320.389 324.243 E
+324.243 327.680 B
+327.680 331.952 F#:min7
+331.952 333.671 A
+333.671 341.293 N0.0 0.163 N
+0.163 24.404 E
+24.404 57.377 Db:minor
+57.377 67.245 Ab:minor
+67.245 92.938 E
+92.938 132.760 Db:minor
+132.760 143.047 Ab:minor
+143.047 196.162 E
+196.162 224.015 Db:minor
+224.015 333.671 E
+333.671 341.293 A
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_logfiles/EltonJohn.IslandGirl.wav.log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,228 @@
+CSVFeatureWriter::setParameters
+stdout -> 
+NOTE: Using default sample rate of 44100 for default transform
+NOTE: Loaded and initialised plugin for transform "vamp:matthiasm:nnls_chroma:bothchroma" with plugin step size 2048 and block size 16384 (adapter step and block size 16384)
+NOTE: PluginInputDomainAdapter timestamp adjustment is  0.000000000R
+Extracting features for: "/Users/matthias/Music/MUSICDB44k/EltonJohn.IslandGirl.wav"
+
Retrieving audio data... Done
+Opened 2-channel file or URL "/Users/matthias/Music/MUSICDB44k/EltonJohn.IslandGirl.wav"
+timestamp  0.000000000R: very low magnitude, setting magnitude to all zeros
+timestamp  0.046439909R: very low magnitude, setting magnitude to all zeros
+timestamp  0.092879818R: very low magnitude, setting magnitude to all zeros
+timestamp  0.139319727R: very low magnitude, setting magnitude to all zeros
+timestamp  0.185759637R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 1%
Extracting and writing features... 2%
Extracting and writing features... 3%
Extracting and writing features... 4%
Extracting and writing features... 5%
Extracting and writing features... 6%
Extracting and writing features... 7%
Extracting and writing features... 8%
Extracting and writing features... 9%
Extracting and writing features... 10%
Extracting and writing features... 11%
Extracting and writing features... 12%
Extracting and writing features... 13%
Extracting and writing features... 14%
Extracting and writing features... 15%
Extracting and writing features... 16%
Extracting and writing features... 17%
Extracting and writing features... 18%
Extracting and writing features... 19%
Extracting and writing features... 20%
Extracting and writing features... 21%
Extracting and writing features... 22%
Extracting and writing features... 23%
Extracting and writing features... 24%
Extracting and writing features... 25%
Extracting and writing features... 26%
Extracting and writing features... 27%
Extracting and writing features... 28%
Extracting and writing features... 29%
Extracting and writing features... 30%
Extracting and writing features... 31%
Extracting and writing features... 32%
Extracting and writing features... 33%
Extracting and writing features... 34%
Extracting and writing features... 35%
Extracting and writing features... 36%
Extracting and writing features... 37%
Extracting and writing features... 38%
Extracting and writing features... 39%
Extracting and writing features... 40%
Extracting and writing features... 41%
Extracting and writing features... 42%
Extracting and writing features... 43%
Extracting and writing features... 44%
Extracting and writing features... 45%
Extracting and writing features... 46%
Extracting and writing features... 47%
Extracting and writing features... 48%
Extracting and writing features... 49%
Extracting and writing features... 50%
Extracting and writing features... 51%
Extracting and writing features... 52%
Extracting and writing features... 53%
Extracting and writing features... 54%
Extracting and writing features... 55%
Extracting and writing features... 56%
Extracting and writing features... 57%
Extracting and writing features... 58%
Extracting and writing features... 59%
Extracting and writing features... 60%
Extracting and writing features... 61%
Extracting and writing features... 62%
Extracting and writing features... 63%
Extracting and writing features... 64%
Extracting and writing features... 65%
Extracting and writing features... 66%
Extracting and writing features... 67%
Extracting and writing features... 68%
Extracting and writing features... 69%
Extracting and writing features... 70%
Extracting and writing features... 71%
Extracting and writing features... 72%
Extracting and writing features... 73%
Extracting and writing features... 74%
Extracting and writing features... 75%
Extracting and writing features... 76%
Extracting and writing features... 77%
Extracting and writing features... 78%
Extracting and writing features... 79%
Extracting and writing features... 80%
Extracting and writing features... 81%
Extracting and writing features... 82%
Extracting and writing features... 83%
Extracting and writing features... 84%
Extracting and writing features... 85%
Extracting and writing features... 86%
Extracting and writing features... 87%
Extracting and writing features... 88%
Extracting and writing features... 89%
Extracting and writing features... 90%
Extracting and writing features... 91%
Extracting and writing features... 92%
Extracting and writing features... 93%
Extracting and writing features... 94%
Extracting and writing features... 95%
Extracting and writing features... 96%
Extracting and writing features... 97%
Extracting and writing features... 98%timestamp  223.190204081R: very low magnitude, setting magnitude to all zeros
+timestamp  223.236643990R: very low magnitude, setting magnitude to all zeros
+timestamp  223.283083900R: very low magnitude, setting magnitude to all zeros
+timestamp  223.329523809R: very low magnitude, setting magnitude to all zeros
+timestamp  223.375963718R: very low magnitude, setting magnitude to all zeros
+timestamp  223.422403628R: very low magnitude, setting magnitude to all zeros
+timestamp  223.468843537R: very low magnitude, setting magnitude to all zeros
+timestamp  223.515283446R: very low magnitude, setting magnitude to all zeros
+timestamp  223.561723356R: very low magnitude, setting magnitude to all zeros
+timestamp  223.608163265R: very low magnitude, setting magnitude to all zeros
+timestamp  223.654603174R: very low magnitude, setting magnitude to all zeros
+timestamp  223.701043083R: very low magnitude, setting magnitude to all zeros
+timestamp  223.747482993R: very low magnitude, setting magnitude to all zeros
+timestamp  223.793922902R: very low magnitude, setting magnitude to all zeros
+timestamp  223.840362811R: very low magnitude, setting magnitude to all zeros
+timestamp  223.886802721R: very low magnitude, setting magnitude to all zeros
+timestamp  223.933242630R: very low magnitude, setting magnitude to all zeros
+timestamp  223.979682539R: very low magnitude, setting magnitude to all zeros
+timestamp  224.026122448R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 99%timestamp  224.072562358R: very low magnitude, setting magnitude to all zeros
+timestamp  224.119002267R: very low magnitude, setting magnitude to all zeros
+timestamp  224.165442176R: very low magnitude, setting magnitude to all zeros
+timestamp  224.211882086R: very low magnitude, setting magnitude to all zeros
+timestamp  224.258321995R: very low magnitude, setting magnitude to all zeros
+timestamp  224.304761904R: very low magnitude, setting magnitude to all zeros
+timestamp  224.351201814R: very low magnitude, setting magnitude to all zeros
+timestamp  224.397641723R: very low magnitude, setting magnitude to all zeros
+timestamp  224.444081632R: very low magnitude, setting magnitude to all zeros
+timestamp  224.490521541R: very low magnitude, setting magnitude to all zeros
+timestamp  224.536961451R: very low magnitude, setting magnitude to all zeros
+timestamp  224.583401360R: very low magnitude, setting magnitude to all zeros
+timestamp  224.629841269R: very low magnitude, setting magnitude to all zeros
+timestamp  224.676281179R: very low magnitude, setting magnitude to all zeros
+timestamp  224.722721088R: very low magnitude, setting magnitude to all zeros
+timestamp  224.769160997R: very low magnitude, setting magnitude to all zeros
+timestamp  224.815600907R: very low magnitude, setting magnitude to all zeros
+timestamp  224.862040816R: very low magnitude, setting magnitude to all zeros
+timestamp  224.908480725R: very low magnitude, setting magnitude to all zeros
+timestamp  224.954920634R: very low magnitude, setting magnitude to all zeros
+timestamp  225.001360544R: very low magnitude, setting magnitude to all zeros
+timestamp  225.047800453R: very low magnitude, setting magnitude to all zeros
+timestamp  225.094240362R: very low magnitude, setting magnitude to all zeros
+timestamp  225.140680272R: very low magnitude, setting magnitude to all zeros
+timestamp  225.187120181R: very low magnitude, setting magnitude to all zeros
+timestamp  225.233560090R: very low magnitude, setting magnitude to all zeros
+timestamp  225.280000000R: very low magnitude, setting magnitude to all zeros
+timestamp  225.326439909R: very low magnitude, setting magnitude to all zeros
+timestamp  225.372879818R: very low magnitude, setting magnitude to all zeros
+timestamp  225.419319727R: very low magnitude, setting magnitude to all zeros
+timestamp  225.465759637R: very low magnitude, setting magnitude to all zeros
+timestamp  225.512199546R: very low magnitude, setting magnitude to all zeros
+timestamp  225.558639455R: very low magnitude, setting magnitude to all zeros
+timestamp  225.605079365R: very low magnitude, setting magnitude to all zeros
+timestamp  225.651519274R: very low magnitude, setting magnitude to all zeros
+timestamp  225.697959183R: very low magnitude, setting magnitude to all zeros
+timestamp  225.744399092R: very low magnitude, setting magnitude to all zeros
+timestamp  225.790839002R: very low magnitude, setting magnitude to all zeros
+timestamp  225.837278911R: very low magnitude, setting magnitude to all zeros
+timestamp  225.883718820R: very low magnitude, setting magnitude to all zeros
+timestamp  225.930158730R: very low magnitude, setting magnitude to all zeros
+[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... done.
+[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... done.
+[NNLS Chroma Plugin] Chord Estimation ... done.
+
Extracting and writing features... Done
+
+
+                              < M A T L A B >
+                  Copyright 1984-2007 The MathWorks, Inc.
+                         Version 7.5.0.338 (R2007b)
+                               August 9, 2007
+
+ 
+  To get started, type one of these: helpwin, helpdesk, or demo.
+  For product information, visit www.mathworks.com.
+ 
+   - First Slice
+    metpos 
+    key 
+    chord 
+    bass 
+   - Second Slice
+    (7) metpos (slice 2) 
+    (8) key (slice 2) 
+    (9) chord (slice 2) 
+    (10) bass (slice 2) 
+onset detection function
+beats
+
+
Length: 28
Length: 32
Length: 36
Length: 40
Length: 44
Length: 48
Length: 52
Length: 56
Length: 60
Length: 64
Length: 68
Length: 72
Length: 76
Length: 80
Length: 84
Length: 88
Length: 92
Length: 96
Length: 100
Length: 104
Length: 108
Length: 112
Length: 116
Length: 120
Length: 124
Length: 128
+Finding maximum probability path (part 1 of 7, beats 1 to 29)... 
+forward step
+backward step
+
+Finding maximum probability path (part 2 of 7, beats 30 to 157)... 
+forward step
+backward step
+
+Finding maximum probability path (part 3 of 7, beats 158 to 189)... 
+forward step
+backward step
+
+Finding maximum probability path (part 4 of 7, beats 190 to 317)... 
+forward step
+backward step
+
+Finding maximum probability path (part 5 of 7, beats 318 to 349)... 
+forward step
+backward step
+
+Finding maximum probability path (part 6 of 7, beats 350 to 477)... 
+forward step
+backward step
+
+Finding maximum probability path (part 7 of 7, beats 478 to 526)... 
+forward step
+backward step
+0.0 0.012 N
+0.012 0.964 N
+0.964 10.461 D:min
+10.461 11.331 N
+11.331 14.756 Bb/5
+14.756 16.475 C/5
+16.475 18.193 F/3
+18.193 21.629 Bb
+21.629 24.207 D:min
+24.207 25.066 F/5
+25.066 28.502 Bb/5
+28.502 30.221 F
+30.221 31.927 C/5
+31.927 34.516 Ab:maj7
+34.516 35.376 Eb
+35.376 38.847 Bb
+38.847 41.436 F
+41.436 42.307 Eb
+42.307 45.755 Bb:maj6
+45.755 49.215 F
+49.215 50.956 Bb
+50.956 52.686 F/3
+52.686 54.416 F:min
+54.416 56.134 Eb
+56.134 59.594 Bb
+59.594 61.324 Eb
+61.324 63.054 C/3
+63.054 64.807 Bb/5
+64.807 65.666 Eb/3
+65.666 66.548 F/3
+66.548 70.194 Bb
+70.194 79.702 D:min
+79.702 80.562 C:maj6
+80.562 83.998 Bb/5
+83.998 85.716 C/5
+85.716 87.435 F/3
+87.435 90.883 Bb
+90.883 93.425 D:min
+93.425 94.285 F/5
+94.285 97.710 Bb/5
+97.710 99.439 F
+99.439 101.158 C/5
+101.158 103.735 Ab:maj7
+103.735 104.606 Eb
+104.606 108.089 Bb
+108.089 110.678 F
+110.678 111.549 Eb
+111.549 115.008 Bb:maj6
+115.008 118.480 F
+118.480 120.221 Bb
+120.221 121.963 F/3
+121.963 123.693 F:min
+123.693 125.423 Eb
+125.423 128.859 Bb
+128.859 130.577 Eb
+130.577 132.296 C/3
+132.296 134.026 Bb/5
+134.026 134.885 Eb/3
+134.885 135.755 F/3
+135.755 139.343 Bb
+139.343 148.840 D:min
+148.840 149.699 C:maj6
+149.699 153.147 Bb/5
+153.147 154.865 C/5
+154.865 156.572 F/3
+156.572 159.985 Bb
+159.985 162.575 D:min
+162.575 163.422 F/5
+163.422 166.847 Bb/5
+166.847 168.577 F
+168.577 170.295 C/5
+170.295 172.896 Ab:maj7
+172.896 173.767 Eb
+173.767 177.215 Bb
+177.215 179.815 F
+179.815 180.674 Eb
+180.674 184.123 Bb:maj6
+184.123 187.548 F
+187.548 189.277 Bb
+189.277 190.996 F/3
+190.996 192.702 F:min
+192.702 194.421 Eb
+194.421 197.857 Bb
+197.857 199.552 Eb
+199.552 201.271 C/3
+201.271 202.989 Bb/5
+202.989 203.848 Eb/3
+203.848 204.696 F/3
+204.696 206.414 Bb
+206.414 207.261 Eb/3
+207.261 208.109 F/3
+208.109 209.816 Bb/5
+209.816 210.686 Eb/3
+210.686 211.603 F/3
+211.603 221.890 F:maj6
+221.890 226.240 N0.0 0.012 N
+0.012 12.190 D:minor
+12.190 205.555 Bb
+205.555 226.240 F
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_logfiles/GloriaEstefanAndMiamiSoundMachine.AnythingForYou.wav.log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,497 @@
+CSVFeatureWriter::setParameters
+stdout -> 
+NOTE: Using default sample rate of 44100 for default transform
+NOTE: Loaded and initialised plugin for transform "vamp:matthiasm:nnls_chroma:bothchroma" with plugin step size 2048 and block size 16384 (adapter step and block size 16384)
+NOTE: PluginInputDomainAdapter timestamp adjustment is  0.000000000R
+Extracting features for: "/Users/matthias/Music/MUSICDB44k/GloriaEstefanAndMiamiSoundMachine.AnythingForYou.wav"
+
Retrieving audio data... Done
+Opened 2-channel file or URL "/Users/matthias/Music/MUSICDB44k/GloriaEstefanAndMiamiSoundMachine.AnythingForYou.wav"
+timestamp  0.000000000R: very low magnitude, setting magnitude to all zeros
+timestamp  0.046439909R: very low magnitude, setting magnitude to all zeros
+timestamp  0.092879818R: very low magnitude, setting magnitude to all zeros
+timestamp  0.139319727R: very low magnitude, setting magnitude to all zeros
+timestamp  0.185759637R: very low magnitude, setting magnitude to all zeros
+timestamp  0.232199546R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 1%
Extracting and writing features... 2%
Extracting and writing features... 3%
Extracting and writing features... 4%
Extracting and writing features... 5%
Extracting and writing features... 6%
Extracting and writing features... 7%
Extracting and writing features... 8%
Extracting and writing features... 9%
Extracting and writing features... 10%
Extracting and writing features... 11%
Extracting and writing features... 12%
Extracting and writing features... 13%
Extracting and writing features... 14%
Extracting and writing features... 15%
Extracting and writing features... 16%
Extracting and writing features... 17%
Extracting and writing features... 18%
Extracting and writing features... 19%
Extracting and writing features... 20%
Extracting and writing features... 21%
Extracting and writing features... 22%
Extracting and writing features... 23%
Extracting and writing features... 24%
Extracting and writing features... 25%
Extracting and writing features... 26%
Extracting and writing features... 27%
Extracting and writing features... 28%
Extracting and writing features... 29%
Extracting and writing features... 30%
Extracting and writing features... 31%
Extracting and writing features... 32%
Extracting and writing features... 33%
Extracting and writing features... 34%
Extracting and writing features... 35%
Extracting and writing features... 36%
Extracting and writing features... 37%
Extracting and writing features... 38%
Extracting and writing features... 39%
Extracting and writing features... 40%
Extracting and writing features... 41%
Extracting and writing features... 42%
Extracting and writing features... 43%
Extracting and writing features... 44%
Extracting and writing features... 45%
Extracting and writing features... 46%
Extracting and writing features... 47%
Extracting and writing features... 48%
Extracting and writing features... 49%
Extracting and writing features... 50%
Extracting and writing features... 51%
Extracting and writing features... 52%
Extracting and writing features... 53%
Extracting and writing features... 54%
Extracting and writing features... 55%
Extracting and writing features... 56%
Extracting and writing features... 57%
Extracting and writing features... 58%
Extracting and writing features... 59%
Extracting and writing features... 60%
Extracting and writing features... 61%
Extracting and writing features... 62%
Extracting and writing features... 63%
Extracting and writing features... 64%
Extracting and writing features... 65%
Extracting and writing features... 66%
Extracting and writing features... 67%
Extracting and writing features... 68%
Extracting and writing features... 69%
Extracting and writing features... 70%
Extracting and writing features... 71%
Extracting and writing features... 72%
Extracting and writing features... 73%
Extracting and writing features... 74%
Extracting and writing features... 75%
Extracting and writing features... 76%
Extracting and writing features... 77%
Extracting and writing features... 78%
Extracting and writing features... 79%
Extracting and writing features... 80%
Extracting and writing features... 81%
Extracting and writing features... 82%
Extracting and writing features... 83%
Extracting and writing features... 84%
Extracting and writing features... 85%
Extracting and writing features... 86%
Extracting and writing features... 87%
Extracting and writing features... 88%
Extracting and writing features... 89%
Extracting and writing features... 90%
Extracting and writing features... 91%
Extracting and writing features... 92%
Extracting and writing features... 93%
Extracting and writing features... 94%timestamp  231.224308390R: very low magnitude, setting magnitude to all zeros
+timestamp  231.270748299R: very low magnitude, setting magnitude to all zeros
+timestamp  231.317188208R: very low magnitude, setting magnitude to all zeros
+timestamp  231.363628117R: very low magnitude, setting magnitude to all zeros
+timestamp  231.410068027R: very low magnitude, setting magnitude to all zeros
+timestamp  231.456507936R: very low magnitude, setting magnitude to all zeros
+timestamp  231.502947845R: very low magnitude, setting magnitude to all zeros
+timestamp  231.549387755R: very low magnitude, setting magnitude to all zeros
+timestamp  231.595827664R: very low magnitude, setting magnitude to all zeros
+timestamp  231.642267573R: very low magnitude, setting magnitude to all zeros
+timestamp  231.688707482R: very low magnitude, setting magnitude to all zeros
+timestamp  231.735147392R: very low magnitude, setting magnitude to all zeros
+timestamp  231.781587301R: very low magnitude, setting magnitude to all zeros
+timestamp  232.013786848R: very low magnitude, setting magnitude to all zeros
+timestamp  232.060226757R: very low magnitude, setting magnitude to all zeros
+timestamp  232.106666666R: very low magnitude, setting magnitude to all zeros
+timestamp  232.153106575R: very low magnitude, setting magnitude to all zeros
+timestamp  232.199546485R: very low magnitude, setting magnitude to all zeros
+timestamp  232.245986394R: very low magnitude, setting magnitude to all zeros
+timestamp  232.292426303R: very low magnitude, setting magnitude to all zeros
+timestamp  232.338866213R: very low magnitude, setting magnitude to all zeros
+timestamp  232.385306122R: very low magnitude, setting magnitude to all zeros
+timestamp  232.431746031R: very low magnitude, setting magnitude to all zeros
+timestamp  232.478185941R: very low magnitude, setting magnitude to all zeros
+timestamp  232.524625850R: very low magnitude, setting magnitude to all zeros
+timestamp  232.571065759R: very low magnitude, setting magnitude to all zeros
+timestamp  232.617505668R: very low magnitude, setting magnitude to all zeros
+timestamp  232.663945578R: very low magnitude, setting magnitude to all zeros
+timestamp  232.710385487R: very low magnitude, setting magnitude to all zeros
+timestamp  232.756825396R: very low magnitude, setting magnitude to all zeros
+timestamp  232.803265306R: very low magnitude, setting magnitude to all zeros
+timestamp  232.849705215R: very low magnitude, setting magnitude to all zeros
+timestamp  232.896145124R: very low magnitude, setting magnitude to all zeros
+timestamp  232.942585034R: very low magnitude, setting magnitude to all zeros
+timestamp  233.128344671R: very low magnitude, setting magnitude to all zeros
+timestamp  233.174784580R: very low magnitude, setting magnitude to all zeros
+timestamp  233.221224489R: very low magnitude, setting magnitude to all zeros
+timestamp  233.267664399R: very low magnitude, setting magnitude to all zeros
+timestamp  233.406984126R: very low magnitude, setting magnitude to all zeros
+timestamp  233.453424036R: very low magnitude, setting magnitude to all zeros
+timestamp  233.499863945R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 95%timestamp  233.732063492R: very low magnitude, setting magnitude to all zeros
+timestamp  233.778503401R: very low magnitude, setting magnitude to all zeros
+timestamp  233.824943310R: very low magnitude, setting magnitude to all zeros
+timestamp  233.871383219R: very low magnitude, setting magnitude to all zeros
+timestamp  233.917823129R: very low magnitude, setting magnitude to all zeros
+timestamp  233.964263038R: very low magnitude, setting magnitude to all zeros
+timestamp  234.010702947R: very low magnitude, setting magnitude to all zeros
+timestamp  234.057142857R: very low magnitude, setting magnitude to all zeros
+timestamp  234.103582766R: very low magnitude, setting magnitude to all zeros
+timestamp  234.150022675R: very low magnitude, setting magnitude to all zeros
+timestamp  234.196462585R: very low magnitude, setting magnitude to all zeros
+timestamp  234.242902494R: very low magnitude, setting magnitude to all zeros
+timestamp  234.289342403R: very low magnitude, setting magnitude to all zeros
+timestamp  234.335782312R: very low magnitude, setting magnitude to all zeros
+timestamp  234.382222222R: very low magnitude, setting magnitude to all zeros
+timestamp  234.428662131R: very low magnitude, setting magnitude to all zeros
+timestamp  234.475102040R: very low magnitude, setting magnitude to all zeros
+timestamp  234.521541950R: very low magnitude, setting magnitude to all zeros
+timestamp  234.567981859R: very low magnitude, setting magnitude to all zeros
+timestamp  234.614421768R: very low magnitude, setting magnitude to all zeros
+timestamp  234.660861678R: very low magnitude, setting magnitude to all zeros
+timestamp  234.707301587R: very low magnitude, setting magnitude to all zeros
+timestamp  234.753741496R: very low magnitude, setting magnitude to all zeros
+timestamp  234.800181405R: very low magnitude, setting magnitude to all zeros
+timestamp  234.846621315R: very low magnitude, setting magnitude to all zeros
+timestamp  234.893061224R: very low magnitude, setting magnitude to all zeros
+timestamp  234.939501133R: very low magnitude, setting magnitude to all zeros
+timestamp  234.985941043R: very low magnitude, setting magnitude to all zeros
+timestamp  235.032380952R: very low magnitude, setting magnitude to all zeros
+timestamp  235.078820861R: very low magnitude, setting magnitude to all zeros
+timestamp  235.125260770R: very low magnitude, setting magnitude to all zeros
+timestamp  235.171700680R: very low magnitude, setting magnitude to all zeros
+timestamp  235.218140589R: very low magnitude, setting magnitude to all zeros
+timestamp  235.264580498R: very low magnitude, setting magnitude to all zeros
+timestamp  235.311020408R: very low magnitude, setting magnitude to all zeros
+timestamp  235.357460317R: very low magnitude, setting magnitude to all zeros
+timestamp  235.403900226R: very low magnitude, setting magnitude to all zeros
+timestamp  235.450340136R: very low magnitude, setting magnitude to all zeros
+timestamp  235.496780045R: very low magnitude, setting magnitude to all zeros
+timestamp  235.543219954R: very low magnitude, setting magnitude to all zeros
+timestamp  235.589659863R: very low magnitude, setting magnitude to all zeros
+timestamp  235.636099773R: very low magnitude, setting magnitude to all zeros
+timestamp  235.682539682R: very low magnitude, setting magnitude to all zeros
+timestamp  235.728979591R: very low magnitude, setting magnitude to all zeros
+timestamp  235.775419501R: very low magnitude, setting magnitude to all zeros
+timestamp  235.821859410R: very low magnitude, setting magnitude to all zeros
+timestamp  235.868299319R: very low magnitude, setting magnitude to all zeros
+timestamp  235.914739229R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 96%timestamp  235.961179138R: very low magnitude, setting magnitude to all zeros
+timestamp  236.007619047R: very low magnitude, setting magnitude to all zeros
+timestamp  236.054058956R: very low magnitude, setting magnitude to all zeros
+timestamp  236.100498866R: very low magnitude, setting magnitude to all zeros
+timestamp  236.146938775R: very low magnitude, setting magnitude to all zeros
+timestamp  236.193378684R: very low magnitude, setting magnitude to all zeros
+timestamp  236.239818594R: very low magnitude, setting magnitude to all zeros
+timestamp  236.286258503R: very low magnitude, setting magnitude to all zeros
+timestamp  236.332698412R: very low magnitude, setting magnitude to all zeros
+timestamp  236.379138321R: very low magnitude, setting magnitude to all zeros
+timestamp  236.425578231R: very low magnitude, setting magnitude to all zeros
+timestamp  236.472018140R: very low magnitude, setting magnitude to all zeros
+timestamp  236.518458049R: very low magnitude, setting magnitude to all zeros
+timestamp  236.564897959R: very low magnitude, setting magnitude to all zeros
+timestamp  236.611337868R: very low magnitude, setting magnitude to all zeros
+timestamp  236.657777777R: very low magnitude, setting magnitude to all zeros
+timestamp  236.704217687R: very low magnitude, setting magnitude to all zeros
+timestamp  236.750657596R: very low magnitude, setting magnitude to all zeros
+timestamp  236.797097505R: very low magnitude, setting magnitude to all zeros
+timestamp  236.843537414R: very low magnitude, setting magnitude to all zeros
+timestamp  236.889977324R: very low magnitude, setting magnitude to all zeros
+timestamp  236.936417233R: very low magnitude, setting magnitude to all zeros
+timestamp  236.982857142R: very low magnitude, setting magnitude to all zeros
+timestamp  237.029297052R: very low magnitude, setting magnitude to all zeros
+timestamp  237.075736961R: very low magnitude, setting magnitude to all zeros
+timestamp  237.122176870R: very low magnitude, setting magnitude to all zeros
+timestamp  237.168616780R: very low magnitude, setting magnitude to all zeros
+timestamp  237.215056689R: very low magnitude, setting magnitude to all zeros
+timestamp  237.261496598R: very low magnitude, setting magnitude to all zeros
+timestamp  237.307936507R: very low magnitude, setting magnitude to all zeros
+timestamp  237.354376417R: very low magnitude, setting magnitude to all zeros
+timestamp  237.400816326R: very low magnitude, setting magnitude to all zeros
+timestamp  237.447256235R: very low magnitude, setting magnitude to all zeros
+timestamp  237.493696145R: very low magnitude, setting magnitude to all zeros
+timestamp  237.540136054R: very low magnitude, setting magnitude to all zeros
+timestamp  237.586575963R: very low magnitude, setting magnitude to all zeros
+timestamp  237.633015873R: very low magnitude, setting magnitude to all zeros
+timestamp  237.679455782R: very low magnitude, setting magnitude to all zeros
+timestamp  237.725895691R: very low magnitude, setting magnitude to all zeros
+timestamp  237.772335600R: very low magnitude, setting magnitude to all zeros
+timestamp  237.818775510R: very low magnitude, setting magnitude to all zeros
+timestamp  237.865215419R: very low magnitude, setting magnitude to all zeros
+timestamp  237.911655328R: very low magnitude, setting magnitude to all zeros
+timestamp  237.958095238R: very low magnitude, setting magnitude to all zeros
+timestamp  238.004535147R: very low magnitude, setting magnitude to all zeros
+timestamp  238.050975056R: very low magnitude, setting magnitude to all zeros
+timestamp  238.097414965R: very low magnitude, setting magnitude to all zeros
+timestamp  238.143854875R: very low magnitude, setting magnitude to all zeros
+timestamp  238.190294784R: very low magnitude, setting magnitude to all zeros
+timestamp  238.236734693R: very low magnitude, setting magnitude to all zeros
+timestamp  238.283174603R: very low magnitude, setting magnitude to all zeros
+timestamp  238.329614512R: very low magnitude, setting magnitude to all zeros
+timestamp  238.376054421R: very low magnitude, setting magnitude to all zeros
+timestamp  238.422494331R: very low magnitude, setting magnitude to all zeros
+timestamp  238.468934240R: very low magnitude, setting magnitude to all zeros
+timestamp  238.515374149R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 97%timestamp  238.561814058R: very low magnitude, setting magnitude to all zeros
+timestamp  238.608253968R: very low magnitude, setting magnitude to all zeros
+timestamp  238.654693877R: very low magnitude, setting magnitude to all zeros
+timestamp  238.701133786R: very low magnitude, setting magnitude to all zeros
+timestamp  238.747573696R: very low magnitude, setting magnitude to all zeros
+timestamp  238.794013605R: very low magnitude, setting magnitude to all zeros
+timestamp  238.840453514R: very low magnitude, setting magnitude to all zeros
+timestamp  238.886893424R: very low magnitude, setting magnitude to all zeros
+timestamp  238.933333333R: very low magnitude, setting magnitude to all zeros
+timestamp  238.979773242R: very low magnitude, setting magnitude to all zeros
+timestamp  239.026213151R: very low magnitude, setting magnitude to all zeros
+timestamp  239.072653061R: very low magnitude, setting magnitude to all zeros
+timestamp  239.119092970R: very low magnitude, setting magnitude to all zeros
+timestamp  239.165532879R: very low magnitude, setting magnitude to all zeros
+timestamp  239.211972789R: very low magnitude, setting magnitude to all zeros
+timestamp  239.258412698R: very low magnitude, setting magnitude to all zeros
+timestamp  239.304852607R: very low magnitude, setting magnitude to all zeros
+timestamp  239.351292517R: very low magnitude, setting magnitude to all zeros
+timestamp  239.397732426R: very low magnitude, setting magnitude to all zeros
+timestamp  239.444172335R: very low magnitude, setting magnitude to all zeros
+timestamp  239.490612244R: very low magnitude, setting magnitude to all zeros
+timestamp  239.537052154R: very low magnitude, setting magnitude to all zeros
+timestamp  239.583492063R: very low magnitude, setting magnitude to all zeros
+timestamp  239.629931972R: very low magnitude, setting magnitude to all zeros
+timestamp  239.676371882R: very low magnitude, setting magnitude to all zeros
+timestamp  239.722811791R: very low magnitude, setting magnitude to all zeros
+timestamp  239.769251700R: very low magnitude, setting magnitude to all zeros
+timestamp  239.815691609R: very low magnitude, setting magnitude to all zeros
+timestamp  239.862131519R: very low magnitude, setting magnitude to all zeros
+timestamp  239.908571428R: very low magnitude, setting magnitude to all zeros
+timestamp  239.955011337R: very low magnitude, setting magnitude to all zeros
+timestamp  240.001451247R: very low magnitude, setting magnitude to all zeros
+timestamp  240.047891156R: very low magnitude, setting magnitude to all zeros
+timestamp  240.094331065R: very low magnitude, setting magnitude to all zeros
+timestamp  240.140770975R: very low magnitude, setting magnitude to all zeros
+timestamp  240.187210884R: very low magnitude, setting magnitude to all zeros
+timestamp  240.233650793R: very low magnitude, setting magnitude to all zeros
+timestamp  240.280090702R: very low magnitude, setting magnitude to all zeros
+timestamp  240.326530612R: very low magnitude, setting magnitude to all zeros
+timestamp  240.372970521R: very low magnitude, setting magnitude to all zeros
+timestamp  240.419410430R: very low magnitude, setting magnitude to all zeros
+timestamp  240.465850340R: very low magnitude, setting magnitude to all zeros
+timestamp  240.512290249R: very low magnitude, setting magnitude to all zeros
+timestamp  240.558730158R: very low magnitude, setting magnitude to all zeros
+timestamp  240.605170068R: very low magnitude, setting magnitude to all zeros
+timestamp  240.651609977R: very low magnitude, setting magnitude to all zeros
+timestamp  240.698049886R: very low magnitude, setting magnitude to all zeros
+timestamp  240.744489795R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 98%timestamp  240.790929705R: very low magnitude, setting magnitude to all zeros
+timestamp  240.837369614R: very low magnitude, setting magnitude to all zeros
+timestamp  240.883809523R: very low magnitude, setting magnitude to all zeros
+timestamp  240.930249433R: very low magnitude, setting magnitude to all zeros
+timestamp  240.976689342R: very low magnitude, setting magnitude to all zeros
+timestamp  241.023129251R: very low magnitude, setting magnitude to all zeros
+timestamp  241.069569160R: very low magnitude, setting magnitude to all zeros
+timestamp  241.116009070R: very low magnitude, setting magnitude to all zeros
+timestamp  241.162448979R: very low magnitude, setting magnitude to all zeros
+timestamp  241.208888888R: very low magnitude, setting magnitude to all zeros
+timestamp  241.255328798R: very low magnitude, setting magnitude to all zeros
+timestamp  241.301768707R: very low magnitude, setting magnitude to all zeros
+timestamp  241.348208616R: very low magnitude, setting magnitude to all zeros
+timestamp  241.394648526R: very low magnitude, setting magnitude to all zeros
+timestamp  241.441088435R: very low magnitude, setting magnitude to all zeros
+timestamp  241.487528344R: very low magnitude, setting magnitude to all zeros
+timestamp  241.533968253R: very low magnitude, setting magnitude to all zeros
+timestamp  241.580408163R: very low magnitude, setting magnitude to all zeros
+timestamp  241.626848072R: very low magnitude, setting magnitude to all zeros
+timestamp  241.673287981R: very low magnitude, setting magnitude to all zeros
+timestamp  241.719727891R: very low magnitude, setting magnitude to all zeros
+timestamp  241.766167800R: very low magnitude, setting magnitude to all zeros
+timestamp  241.812607709R: very low magnitude, setting magnitude to all zeros
+timestamp  241.859047619R: very low magnitude, setting magnitude to all zeros
+timestamp  241.905487528R: very low magnitude, setting magnitude to all zeros
+timestamp  241.951927437R: very low magnitude, setting magnitude to all zeros
+timestamp  241.998367346R: very low magnitude, setting magnitude to all zeros
+timestamp  242.044807256R: very low magnitude, setting magnitude to all zeros
+timestamp  242.091247165R: very low magnitude, setting magnitude to all zeros
+timestamp  242.137687074R: very low magnitude, setting magnitude to all zeros
+timestamp  242.184126984R: very low magnitude, setting magnitude to all zeros
+timestamp  242.230566893R: very low magnitude, setting magnitude to all zeros
+timestamp  242.277006802R: very low magnitude, setting magnitude to all zeros
+timestamp  242.323446712R: very low magnitude, setting magnitude to all zeros
+timestamp  242.369886621R: very low magnitude, setting magnitude to all zeros
+timestamp  242.416326530R: very low magnitude, setting magnitude to all zeros
+timestamp  242.462766439R: very low magnitude, setting magnitude to all zeros
+timestamp  242.509206349R: very low magnitude, setting magnitude to all zeros
+timestamp  242.555646258R: very low magnitude, setting magnitude to all zeros
+timestamp  242.602086167R: very low magnitude, setting magnitude to all zeros
+timestamp  242.648526077R: very low magnitude, setting magnitude to all zeros
+timestamp  242.694965986R: very low magnitude, setting magnitude to all zeros
+timestamp  242.741405895R: very low magnitude, setting magnitude to all zeros
+timestamp  242.787845804R: very low magnitude, setting magnitude to all zeros
+timestamp  242.834285714R: very low magnitude, setting magnitude to all zeros
+timestamp  242.880725623R: very low magnitude, setting magnitude to all zeros
+timestamp  242.927165532R: very low magnitude, setting magnitude to all zeros
+timestamp  242.973605442R: very low magnitude, setting magnitude to all zeros
+timestamp  243.020045351R: very low magnitude, setting magnitude to all zeros
+timestamp  243.066485260R: very low magnitude, setting magnitude to all zeros
+timestamp  243.112925170R: very low magnitude, setting magnitude to all zeros
+timestamp  243.159365079R: very low magnitude, setting magnitude to all zeros
+timestamp  243.205804988R: very low magnitude, setting magnitude to all zeros
+timestamp  243.252244897R: very low magnitude, setting magnitude to all zeros
+timestamp  243.298684807R: very low magnitude, setting magnitude to all zeros
+timestamp  243.345124716R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 99%timestamp  243.391564625R: very low magnitude, setting magnitude to all zeros
+timestamp  243.438004535R: very low magnitude, setting magnitude to all zeros
+timestamp  243.484444444R: very low magnitude, setting magnitude to all zeros
+timestamp  243.530884353R: very low magnitude, setting magnitude to all zeros
+timestamp  243.577324263R: very low magnitude, setting magnitude to all zeros
+timestamp  243.623764172R: very low magnitude, setting magnitude to all zeros
+timestamp  243.670204081R: very low magnitude, setting magnitude to all zeros
+timestamp  243.716643990R: very low magnitude, setting magnitude to all zeros
+timestamp  243.763083900R: very low magnitude, setting magnitude to all zeros
+timestamp  243.809523809R: very low magnitude, setting magnitude to all zeros
+timestamp  243.855963718R: very low magnitude, setting magnitude to all zeros
+timestamp  243.902403628R: very low magnitude, setting magnitude to all zeros
+timestamp  243.948843537R: very low magnitude, setting magnitude to all zeros
+timestamp  243.995283446R: very low magnitude, setting magnitude to all zeros
+timestamp  244.041723356R: very low magnitude, setting magnitude to all zeros
+timestamp  244.088163265R: very low magnitude, setting magnitude to all zeros
+timestamp  244.134603174R: very low magnitude, setting magnitude to all zeros
+timestamp  244.181043083R: very low magnitude, setting magnitude to all zeros
+timestamp  244.227482993R: very low magnitude, setting magnitude to all zeros
+timestamp  244.273922902R: very low magnitude, setting magnitude to all zeros
+timestamp  244.320362811R: very low magnitude, setting magnitude to all zeros
+timestamp  244.366802721R: very low magnitude, setting magnitude to all zeros
+timestamp  244.413242630R: very low magnitude, setting magnitude to all zeros
+timestamp  244.459682539R: very low magnitude, setting magnitude to all zeros
+timestamp  244.506122448R: very low magnitude, setting magnitude to all zeros
+timestamp  244.552562358R: very low magnitude, setting magnitude to all zeros
+timestamp  244.599002267R: very low magnitude, setting magnitude to all zeros
+timestamp  244.645442176R: very low magnitude, setting magnitude to all zeros
+timestamp  244.691882086R: very low magnitude, setting magnitude to all zeros
+timestamp  244.738321995R: very low magnitude, setting magnitude to all zeros
+timestamp  244.784761904R: very low magnitude, setting magnitude to all zeros
+timestamp  244.831201814R: very low magnitude, setting magnitude to all zeros
+timestamp  244.877641723R: very low magnitude, setting magnitude to all zeros
+timestamp  244.924081632R: very low magnitude, setting magnitude to all zeros
+timestamp  244.970521541R: very low magnitude, setting magnitude to all zeros
+timestamp  245.016961451R: very low magnitude, setting magnitude to all zeros
+timestamp  245.063401360R: very low magnitude, setting magnitude to all zeros
+timestamp  245.109841269R: very low magnitude, setting magnitude to all zeros
+timestamp  245.156281179R: very low magnitude, setting magnitude to all zeros
+timestamp  245.202721088R: very low magnitude, setting magnitude to all zeros
+timestamp  245.249160997R: very low magnitude, setting magnitude to all zeros
+timestamp  245.295600907R: very low magnitude, setting magnitude to all zeros
+timestamp  245.342040816R: very low magnitude, setting magnitude to all zeros
+timestamp  245.388480725R: very low magnitude, setting magnitude to all zeros
+timestamp  245.434920634R: very low magnitude, setting magnitude to all zeros
+timestamp  245.481360544R: very low magnitude, setting magnitude to all zeros
+timestamp  245.527800453R: very low magnitude, setting magnitude to all zeros
+timestamp  245.574240362R: very low magnitude, setting magnitude to all zeros
+timestamp  245.620680272R: very low magnitude, setting magnitude to all zeros
+[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... done.
+[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... done.
+[NNLS Chroma Plugin] Chord Estimation ... done.
+
Extracting and writing features... Done
+
+
+                              < M A T L A B >
+                  Copyright 1984-2007 The MathWorks, Inc.
+                         Version 7.5.0.338 (R2007b)
+                               August 9, 2007
+
+ 
+  To get started, type one of these: helpwin, helpdesk, or demo.
+  For product information, visit www.mathworks.com.
+ 
+   - First Slice
+    metpos 
+    key 
+    chord 
+    bass 
+   - Second Slice
+    (7) metpos (slice 2) 
+    (8) key (slice 2) 
+    (9) chord (slice 2) 
+    (10) bass (slice 2) 
+onset detection function
+beats
+
+
Length: 28
Length: 32
Length: 36
Length: 40
Length: 44
Length: 48
Length: 52
Length: 56
Length: 60
Length: 64
Length: 68
Length: 72
Length: 76
Length: 80
Length: 84
Length: 88
Length: 92
Length: 96
Length: 100
Length: 104
Length: 108
Length: 112
Length: 116
Length: 120
Length: 124
Length: 128
+Finding maximum probability path (part 1 of 17, beats 1 to 57)... 
+forward step
+backward step
+
+Finding maximum probability path (part 2 of 17, beats 58 to 91)... 
+forward step
+backward step
+
+Finding maximum probability path (part 3 of 17, beats 92 to 126)... 
+forward step
+backward step
+
+Finding maximum probability path (part 4 of 17, beats 127 to 154)... 
+forward step
+backward step
+
+Finding maximum probability path (part 5 of 17, beats 155 to 199)... 
+forward step
+backward step
+
+Finding maximum probability path (part 6 of 17, beats 200 to 227)... 
+forward step
+backward step
+
+Finding maximum probability path (part 7 of 17, beats 228 to 262)... 
+forward step
+backward step
+
+Finding maximum probability path (part 8 of 17, beats 263 to 302)... 
+forward step
+backward step
+
+Finding maximum probability path (part 9 of 17, beats 303 to 330)... 
+forward step
+backward step
+
+Finding maximum probability path (part 10 of 17, beats 331 to 366)... 
+forward step
+backward step
+
+Finding maximum probability path (part 11 of 17, beats 367 to 398)... 
+forward step
+backward step
+
+Finding maximum probability path (part 12 of 17, beats 399 to 430)... 
+forward step
+backward step
+
+Finding maximum probability path (part 13 of 17, beats 431 to 462)... 
+forward step
+backward step
+
+Finding maximum probability path (part 14 of 17, beats 463 to 494)... 
+forward step
+backward step
+
+Finding maximum probability path (part 15 of 17, beats 494 to 526)... 
+forward step
+backward step
+
+Finding maximum probability path (part 16 of 17, beats 527 to 558)... 
+forward step
+backward step
+
+Finding maximum probability path (part 17 of 17, beats 559 to 592)... 
+forward step
+backward step
+0.0 0.012 N
+0.012 0.325 N
+0.325 6.142 F#/5
+6.142 6.920 G#:min
+6.920 12.016 F#/5
+12.016 13.259 G#:min
+13.259 18.692 F#/5
+18.692 20.376 G#:min
+20.376 21.618 B
+21.618 22.860 F#/3
+22.860 23.696 G#:min7
+23.696 27.040 C#
+27.040 31.335 F#
+31.335 33.866 C#
+33.866 36.223 F#
+36.223 36.989 D#:min7
+36.989 39.253 C#:min
+39.253 43.921 F#
+43.921 46.951 F#/5
+46.951 50.585 D#:min7
+50.585 53.777 C#
+53.777 57.144 Gb
+57.144 60.442 Db
+60.442 62.113 Gb
+62.113 63.843 D#:min7
+63.843 65.457 C#:min
+65.457 67.129 F#
+67.129 70.484 B
+70.484 73.828 F#/5
+73.828 75.453 D#:min7
+75.453 77.125 G#:7
+77.125 78.785 F#/5
+78.785 84.230 C#
+84.230 87.574 Gb
+87.574 90.918 Db
+90.918 93.414 Gb
+93.414 93.832 B/3
+93.832 95.504 E:maj6
+95.504 97.187 G#
+97.187 107.207 F#/5
+107.207 108.867 C#:min
+108.867 113.894 F#
+113.894 117.214 F#/5
+117.214 120.570 D#:min7
+120.570 127.245 C#
+127.245 130.577 Gb
+130.577 133.909 Db
+133.909 135.581 Gb
+135.581 137.300 D#:min7
+137.300 138.913 C#:min
+138.913 140.597 F#
+140.597 143.929 B
+143.929 147.296 F#/5
+147.296 148.956 D#:min7
+148.956 150.628 G#:7
+150.628 152.276 C#:min
+152.276 157.292 F#
+157.292 160.636 F#/5
+160.636 163.979 D#:min7
+163.979 165.640 C#:min
+165.640 170.643 F#
+170.643 173.999 F#/5
+173.999 177.331 D#:min7
+177.331 179.003 C#:min
+179.003 184.018 F#
+184.018 187.362 F#/5
+187.362 190.694 D#:min7
+190.694 192.366 C#:min
+192.366 197.370 F#
+197.370 200.713 F#/5
+200.713 203.627 D#:min7
+203.627 205.311 C#:min
+205.311 210.315 F#
+210.315 213.658 F#/5
+213.658 217.408 D#:min7
+217.408 219.080 C#:min
+219.080 224.096 F#
+224.096 227.439 F#/5
+227.439 230.772 D#:min7
+230.772 231.189 C#:min
+231.189 245.893 N0.0 0.012 N
+0.012 50.956 F#
+50.956 62.113 Db
+62.113 80.875 F#
+80.875 92.578 Db
+92.578 123.902 F#
+123.902 135.581 Db
+135.581 230.772 F#
+230.772 245.893 B
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_logfiles/Martika.ToySoldiers.wav.log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,353 @@
+CSVFeatureWriter::setParameters
+stdout -> 
+NOTE: Using default sample rate of 44100 for default transform
+NOTE: Loaded and initialised plugin for transform "vamp:matthiasm:nnls_chroma:bothchroma" with plugin step size 2048 and block size 16384 (adapter step and block size 16384)
+NOTE: PluginInputDomainAdapter timestamp adjustment is  0.000000000R
+Extracting features for: "/Users/matthias/Music/MUSICDB44k/Martika.ToySoldiers.wav"
+
Retrieving audio data... Done
+Opened 2-channel file or URL "/Users/matthias/Music/MUSICDB44k/Martika.ToySoldiers.wav"
+timestamp  0.000000000R: very low magnitude, setting magnitude to all zeros
+timestamp  0.046439909R: very low magnitude, setting magnitude to all zeros
+timestamp  0.092879818R: very low magnitude, setting magnitude to all zeros
+timestamp  0.139319727R: very low magnitude, setting magnitude to all zeros
+timestamp  0.185759637R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 1%
Extracting and writing features... 2%
Extracting and writing features... 3%
Extracting and writing features... 4%
Extracting and writing features... 5%
Extracting and writing features... 6%
Extracting and writing features... 7%
Extracting and writing features... 8%
Extracting and writing features... 9%
Extracting and writing features... 10%
Extracting and writing features... 11%
Extracting and writing features... 12%
Extracting and writing features... 13%
Extracting and writing features... 14%
Extracting and writing features... 15%
Extracting and writing features... 16%
Extracting and writing features... 17%
Extracting and writing features... 18%
Extracting and writing features... 19%
Extracting and writing features... 20%
Extracting and writing features... 21%
Extracting and writing features... 22%
Extracting and writing features... 23%
Extracting and writing features... 24%
Extracting and writing features... 25%
Extracting and writing features... 26%
Extracting and writing features... 27%
Extracting and writing features... 28%
Extracting and writing features... 29%
Extracting and writing features... 30%
Extracting and writing features... 31%
Extracting and writing features... 32%
Extracting and writing features... 33%
Extracting and writing features... 34%
Extracting and writing features... 35%
Extracting and writing features... 36%
Extracting and writing features... 37%
Extracting and writing features... 38%
Extracting and writing features... 39%
Extracting and writing features... 40%
Extracting and writing features... 41%
Extracting and writing features... 42%
Extracting and writing features... 43%
Extracting and writing features... 44%
Extracting and writing features... 45%
Extracting and writing features... 46%
Extracting and writing features... 47%
Extracting and writing features... 48%
Extracting and writing features... 49%
Extracting and writing features... 50%
Extracting and writing features... 51%
Extracting and writing features... 52%
Extracting and writing features... 53%
Extracting and writing features... 54%
Extracting and writing features... 55%
Extracting and writing features... 56%
Extracting and writing features... 57%
Extracting and writing features... 58%
Extracting and writing features... 59%
Extracting and writing features... 60%
Extracting and writing features... 61%
Extracting and writing features... 62%
Extracting and writing features... 63%
Extracting and writing features... 64%
Extracting and writing features... 65%
Extracting and writing features... 66%
Extracting and writing features... 67%
Extracting and writing features... 68%
Extracting and writing features... 69%
Extracting and writing features... 70%
Extracting and writing features... 71%
Extracting and writing features... 72%
Extracting and writing features... 73%
Extracting and writing features... 74%
Extracting and writing features... 75%
Extracting and writing features... 76%
Extracting and writing features... 77%
Extracting and writing features... 78%
Extracting and writing features... 79%
Extracting and writing features... 80%
Extracting and writing features... 81%
Extracting and writing features... 82%
Extracting and writing features... 83%
Extracting and writing features... 84%
Extracting and writing features... 85%
Extracting and writing features... 86%
Extracting and writing features... 87%
Extracting and writing features... 88%
Extracting and writing features... 89%
Extracting and writing features... 90%
Extracting and writing features... 91%
Extracting and writing features... 92%
Extracting and writing features... 93%
Extracting and writing features... 94%
Extracting and writing features... 95%
Extracting and writing features... 96%
Extracting and writing features... 97%timestamp  273.113106575R: very low magnitude, setting magnitude to all zeros
+timestamp  273.159546485R: very low magnitude, setting magnitude to all zeros
+timestamp  273.623945578R: very low magnitude, setting magnitude to all zeros
+timestamp  273.670385487R: very low magnitude, setting magnitude to all zeros
+timestamp  273.716825396R: very low magnitude, setting magnitude to all zeros
+timestamp  273.763265306R: very low magnitude, setting magnitude to all zeros
+timestamp  273.809705215R: very low magnitude, setting magnitude to all zeros
+timestamp  273.856145124R: very low magnitude, setting magnitude to all zeros
+timestamp  273.902585034R: very low magnitude, setting magnitude to all zeros
+timestamp  273.949024943R: very low magnitude, setting magnitude to all zeros
+timestamp  273.995464852R: very low magnitude, setting magnitude to all zeros
+timestamp  274.041904761R: very low magnitude, setting magnitude to all zeros
+timestamp  274.088344671R: very low magnitude, setting magnitude to all zeros
+timestamp  274.134784580R: very low magnitude, setting magnitude to all zeros
+timestamp  274.181224489R: very low magnitude, setting magnitude to all zeros
+timestamp  274.227664399R: very low magnitude, setting magnitude to all zeros
+timestamp  274.274104308R: very low magnitude, setting magnitude to all zeros
+timestamp  274.320544217R: very low magnitude, setting magnitude to all zeros
+timestamp  274.366984126R: very low magnitude, setting magnitude to all zeros
+timestamp  274.413424036R: very low magnitude, setting magnitude to all zeros
+timestamp  274.459863945R: very low magnitude, setting magnitude to all zeros
+timestamp  274.506303854R: very low magnitude, setting magnitude to all zeros
+timestamp  274.552743764R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 98%timestamp  274.599183673R: very low magnitude, setting magnitude to all zeros
+timestamp  274.645623582R: very low magnitude, setting magnitude to all zeros
+timestamp  274.692063492R: very low magnitude, setting magnitude to all zeros
+timestamp  274.738503401R: very low magnitude, setting magnitude to all zeros
+timestamp  274.784943310R: very low magnitude, setting magnitude to all zeros
+timestamp  274.831383219R: very low magnitude, setting magnitude to all zeros
+timestamp  274.877823129R: very low magnitude, setting magnitude to all zeros
+timestamp  274.924263038R: very low magnitude, setting magnitude to all zeros
+timestamp  274.970702947R: very low magnitude, setting magnitude to all zeros
+timestamp  275.017142857R: very low magnitude, setting magnitude to all zeros
+timestamp  275.063582766R: very low magnitude, setting magnitude to all zeros
+timestamp  275.110022675R: very low magnitude, setting magnitude to all zeros
+timestamp  275.156462585R: very low magnitude, setting magnitude to all zeros
+timestamp  275.202902494R: very low magnitude, setting magnitude to all zeros
+timestamp  275.249342403R: very low magnitude, setting magnitude to all zeros
+timestamp  275.295782312R: very low magnitude, setting magnitude to all zeros
+timestamp  275.342222222R: very low magnitude, setting magnitude to all zeros
+timestamp  275.388662131R: very low magnitude, setting magnitude to all zeros
+timestamp  275.435102040R: very low magnitude, setting magnitude to all zeros
+timestamp  275.481541950R: very low magnitude, setting magnitude to all zeros
+timestamp  275.527981859R: very low magnitude, setting magnitude to all zeros
+timestamp  275.574421768R: very low magnitude, setting magnitude to all zeros
+timestamp  275.620861678R: very low magnitude, setting magnitude to all zeros
+timestamp  275.667301587R: very low magnitude, setting magnitude to all zeros
+timestamp  275.713741496R: very low magnitude, setting magnitude to all zeros
+timestamp  275.760181405R: very low magnitude, setting magnitude to all zeros
+timestamp  275.806621315R: very low magnitude, setting magnitude to all zeros
+timestamp  275.853061224R: very low magnitude, setting magnitude to all zeros
+timestamp  275.899501133R: very low magnitude, setting magnitude to all zeros
+timestamp  275.945941043R: very low magnitude, setting magnitude to all zeros
+timestamp  275.992380952R: very low magnitude, setting magnitude to all zeros
+timestamp  276.038820861R: very low magnitude, setting magnitude to all zeros
+timestamp  276.085260770R: very low magnitude, setting magnitude to all zeros
+timestamp  276.131700680R: very low magnitude, setting magnitude to all zeros
+timestamp  276.178140589R: very low magnitude, setting magnitude to all zeros
+timestamp  276.224580498R: very low magnitude, setting magnitude to all zeros
+timestamp  276.271020408R: very low magnitude, setting magnitude to all zeros
+timestamp  276.317460317R: very low magnitude, setting magnitude to all zeros
+timestamp  276.363900226R: very low magnitude, setting magnitude to all zeros
+timestamp  276.410340136R: very low magnitude, setting magnitude to all zeros
+timestamp  276.456780045R: very low magnitude, setting magnitude to all zeros
+timestamp  276.503219954R: very low magnitude, setting magnitude to all zeros
+timestamp  276.549659863R: very low magnitude, setting magnitude to all zeros
+timestamp  276.596099773R: very low magnitude, setting magnitude to all zeros
+timestamp  276.642539682R: very low magnitude, setting magnitude to all zeros
+timestamp  276.688979591R: very low magnitude, setting magnitude to all zeros
+timestamp  276.735419501R: very low magnitude, setting magnitude to all zeros
+timestamp  276.781859410R: very low magnitude, setting magnitude to all zeros
+timestamp  276.828299319R: very low magnitude, setting magnitude to all zeros
+timestamp  276.874739229R: very low magnitude, setting magnitude to all zeros
+timestamp  276.921179138R: very low magnitude, setting magnitude to all zeros
+timestamp  276.967619047R: very low magnitude, setting magnitude to all zeros
+timestamp  277.014058956R: very low magnitude, setting magnitude to all zeros
+timestamp  277.060498866R: very low magnitude, setting magnitude to all zeros
+timestamp  277.106938775R: very low magnitude, setting magnitude to all zeros
+timestamp  277.153378684R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 99%timestamp  277.199818594R: very low magnitude, setting magnitude to all zeros
+timestamp  277.246258503R: very low magnitude, setting magnitude to all zeros
+timestamp  277.292698412R: very low magnitude, setting magnitude to all zeros
+timestamp  277.339138321R: very low magnitude, setting magnitude to all zeros
+timestamp  277.385578231R: very low magnitude, setting magnitude to all zeros
+timestamp  277.432018140R: very low magnitude, setting magnitude to all zeros
+timestamp  277.478458049R: very low magnitude, setting magnitude to all zeros
+timestamp  277.524897959R: very low magnitude, setting magnitude to all zeros
+timestamp  277.571337868R: very low magnitude, setting magnitude to all zeros
+timestamp  277.617777777R: very low magnitude, setting magnitude to all zeros
+timestamp  277.664217687R: very low magnitude, setting magnitude to all zeros
+timestamp  277.710657596R: very low magnitude, setting magnitude to all zeros
+timestamp  277.757097505R: very low magnitude, setting magnitude to all zeros
+timestamp  277.803537414R: very low magnitude, setting magnitude to all zeros
+timestamp  277.849977324R: very low magnitude, setting magnitude to all zeros
+timestamp  277.896417233R: very low magnitude, setting magnitude to all zeros
+timestamp  277.942857142R: very low magnitude, setting magnitude to all zeros
+timestamp  277.989297052R: very low magnitude, setting magnitude to all zeros
+timestamp  278.035736961R: very low magnitude, setting magnitude to all zeros
+timestamp  278.082176870R: very low magnitude, setting magnitude to all zeros
+timestamp  278.128616780R: very low magnitude, setting magnitude to all zeros
+timestamp  278.175056689R: very low magnitude, setting magnitude to all zeros
+timestamp  278.221496598R: very low magnitude, setting magnitude to all zeros
+timestamp  278.267936507R: very low magnitude, setting magnitude to all zeros
+timestamp  278.314376417R: very low magnitude, setting magnitude to all zeros
+timestamp  278.360816326R: very low magnitude, setting magnitude to all zeros
+timestamp  278.407256235R: very low magnitude, setting magnitude to all zeros
+timestamp  278.453696145R: very low magnitude, setting magnitude to all zeros
+timestamp  278.500136054R: very low magnitude, setting magnitude to all zeros
+timestamp  278.546575963R: very low magnitude, setting magnitude to all zeros
+timestamp  278.593015873R: very low magnitude, setting magnitude to all zeros
+timestamp  278.639455782R: very low magnitude, setting magnitude to all zeros
+timestamp  278.685895691R: very low magnitude, setting magnitude to all zeros
+timestamp  278.732335600R: very low magnitude, setting magnitude to all zeros
+timestamp  278.778775510R: very low magnitude, setting magnitude to all zeros
+timestamp  278.825215419R: very low magnitude, setting magnitude to all zeros
+timestamp  278.871655328R: very low magnitude, setting magnitude to all zeros
+timestamp  278.918095238R: very low magnitude, setting magnitude to all zeros
+timestamp  278.964535147R: very low magnitude, setting magnitude to all zeros
+timestamp  279.010975056R: very low magnitude, setting magnitude to all zeros
+timestamp  279.057414965R: very low magnitude, setting magnitude to all zeros
+timestamp  279.103854875R: very low magnitude, setting magnitude to all zeros
+timestamp  279.150294784R: very low magnitude, setting magnitude to all zeros
+timestamp  279.196734693R: very low magnitude, setting magnitude to all zeros
+timestamp  279.243174603R: very low magnitude, setting magnitude to all zeros
+timestamp  279.289614512R: very low magnitude, setting magnitude to all zeros
+timestamp  279.336054421R: very low magnitude, setting magnitude to all zeros
+timestamp  279.382494331R: very low magnitude, setting magnitude to all zeros
+timestamp  279.428934240R: very low magnitude, setting magnitude to all zeros
+timestamp  279.475374149R: very low magnitude, setting magnitude to all zeros
+timestamp  279.521814058R: very low magnitude, setting magnitude to all zeros
+timestamp  279.568253968R: very low magnitude, setting magnitude to all zeros
+timestamp  279.614693877R: very low magnitude, setting magnitude to all zeros
+timestamp  279.661133786R: very low magnitude, setting magnitude to all zeros
+timestamp  279.707573696R: very low magnitude, setting magnitude to all zeros
+timestamp  279.754013605R: very low magnitude, setting magnitude to all zeros
+timestamp  279.800453514R: very low magnitude, setting magnitude to all zeros
+timestamp  279.846893424R: very low magnitude, setting magnitude to all zeros
+timestamp  279.893333333R: very low magnitude, setting magnitude to all zeros
+timestamp  279.939773242R: very low magnitude, setting magnitude to all zeros
+timestamp  279.986213151R: very low magnitude, setting magnitude to all zeros
+timestamp  280.032653061R: very low magnitude, setting magnitude to all zeros
+timestamp  280.079092970R: very low magnitude, setting magnitude to all zeros
+timestamp  280.125532879R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 100%timestamp  280.171972789R: very low magnitude, setting magnitude to all zeros
+[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... done.
+[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... done.
+[NNLS Chroma Plugin] Chord Estimation ... done.
+
Extracting and writing features... Done
+
+                              < M A T L A B >
+                  Copyright 1984-2007 The MathWorks, Inc.
+                         Version 7.5.0.338 (R2007b)
+                               August 9, 2007
+
+ 
+  To get started, type one of these: helpwin, helpdesk, or demo.
+  For product information, visit www.mathworks.com.
+ 
+   - First Slice
+    metpos 
+    key 
+    chord 
+    bass 
+   - Second Slice
+    (7) metpos (slice 2) 
+    (8) key (slice 2) 
+    (9) chord (slice 2) 
+    (10) bass (slice 2) 
+onset detection function
+beats
+
+
Length: 28
Length: 32
Length: 36
Length: 40
Length: 44
Length: 48
Length: 52
Length: 56
Length: 60
Length: 64
Length: 68
Length: 72
Length: 76
Length: 80
Length: 84
Length: 88
Length: 92
Length: 96
Length: 100
Length: 104
Length: 108
Length: 112
Length: 116
Length: 120
Length: 124
Length: 128
+Finding maximum probability path (part 1 of 8, beats 1 to 9)... 
+forward step
+backward step
+
+Finding maximum probability path (part 2 of 8, beats 10 to 73)... 
+forward step
+backward step
+
+Finding maximum probability path (part 3 of 8, beats 74 to 185)... 
+forward step
+backward step
+
+Finding maximum probability path (part 4 of 8, beats 186 to 249)... 
+forward step
+backward step
+
+Finding maximum probability path (part 5 of 8, beats 250 to 361)... 
+forward step
+backward step
+
+Finding maximum probability path (part 6 of 8, beats 362 to 393)... 
+forward step
+backward step
+
+Finding maximum probability path (part 7 of 8, beats 394 to 505)... 
+forward step
+backward step
+
+Finding maximum probability path (part 8 of 8, beats 506 to 606)... 
+forward step
+backward step
+0.0 0.023 N
+0.023 4.063 Db:min
+4.063 6.850 A
+6.850 7.755 B
+7.755 10.542 A
+10.542 11.447 B
+11.447 14.234 C#:min
+14.234 15.139 B:maj6
+15.139 18.820 C#:min
+18.820 21.606 A
+21.606 22.523 B
+22.523 25.298 A
+25.298 26.215 C#:min
+26.215 28.990 B
+28.990 29.907 A
+29.907 33.611 B
+33.611 35.457 C#:min
+35.457 37.291 B
+37.291 40.066 A
+40.066 40.995 B
+40.995 42.841 C#:min
+42.841 44.664 B
+44.664 45.592 F#:min7
+45.592 46.521 G#:min
+46.521 52.059 A
+52.059 53.905 E
+53.905 55.751 B
+55.751 57.597 C#:min
+57.597 59.443 A#:dim
+59.443 61.289 A
+61.289 63.123 B
+63.123 65.898 C#:min
+65.898 66.839 B/3
+66.839 68.673 E
+68.673 70.519 B
+70.519 72.377 C#:min
+72.377 74.211 A#:dim
+74.211 76.057 A
+76.057 77.903 B
+77.903 80.666 C#:min
+80.666 81.583 B/3
+81.583 83.429 E
+83.429 85.287 B/5
+85.287 88.062 A
+88.062 88.979 B
+88.979 91.754 A
+91.754 92.671 B
+92.671 95.446 C#:min
+95.446 96.363 B:maj6
+96.363 100.055 C#:min
+100.055 102.830 A
+102.830 103.747 B
+103.747 106.533 A
+106.533 107.439 C#:min
+107.439 110.202 B
+110.202 111.119 A
+111.119 114.823 B
+114.823 116.657 C#:min
+116.657 118.491 B
+118.491 121.278 A
+121.278 122.207 B
+122.207 124.053 C#:min
+124.053 125.887 B
+125.887 126.816 F#:min7
+126.816 127.745 G#:min
+127.745 133.271 A
+133.271 135.129 E
+135.129 136.963 B
+136.963 138.820 C#:min
+138.820 140.655 A#:dim
+140.655 142.501 A
+142.501 144.347 B
+144.347 147.110 C#:min
+147.110 148.039 B/3
+148.039 149.873 E
+149.873 151.731 B
+151.731 153.600 C#:min
+153.600 155.434 A#:dim
+155.434 157.269 A
+157.269 159.115 B
+159.115 161.866 C#:min
+161.866 162.807 B/3
+162.807 164.641 E
+164.641 168.333 B
+168.333 169.262 C#:min7
+169.262 170.179 B:maj6
+170.179 172.037 E
+172.037 173.906 F#:min
+173.906 181.255 G#:min
+181.255 183.101 C#:min
+183.101 184.947 B
+184.947 187.722 A
+187.722 188.639 B
+188.639 190.485 C#:min
+190.485 192.331 B
+192.331 193.248 F#:min7
+193.248 194.177 G#:min
+194.177 199.715 A
+199.715 201.572 E
+201.572 203.418 B
+203.418 205.264 C#:min
+205.264 207.110 A#:dim
+207.110 208.945 A
+208.945 210.791 B
+210.791 213.554 C#:min
+213.554 214.483 B/3
+214.483 216.329 E
+216.329 218.186 B
+218.186 220.032 C#:min
+220.032 221.867 A#:dim
+221.867 223.713 A
+223.713 225.547 B
+225.547 228.310 C#:min
+228.310 229.251 B/3
+229.251 231.097 E
+231.097 232.943 B/5
+232.943 234.789 Db:min
+234.789 236.623 Bb:dim
+236.623 238.481 Bbb
+238.481 240.327 Cb
+240.327 243.090 Db:min
+243.090 244.019 Cb/3
+244.019 245.853 Fb
+245.853 247.710 Cb
+247.710 249.556 Db:min
+249.556 251.437 Bb:dim
+251.437 253.411 Bbb
+253.411 255.338 Cb
+255.338 263.628 Db:min
+263.628 273.821 Db:min7
+273.821 280.200 N0.0 0.023 N
+0.023 4.063 Db:minor
+4.063 26.215 A
+26.215 85.287 B
+85.287 106.533 A
+106.533 232.943 B
+232.943 280.200 Db:minor
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_logfiles/OtisRedding.TheDockOfTheBay.wav.log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,270 @@
+CSVFeatureWriter::setParameters
+stdout -> 
+NOTE: Using default sample rate of 44100 for default transform
+NOTE: Loaded and initialised plugin for transform "vamp:matthiasm:nnls_chroma:bothchroma" with plugin step size 2048 and block size 16384 (adapter step and block size 16384)
+NOTE: PluginInputDomainAdapter timestamp adjustment is  0.000000000R
+Extracting features for: "/Users/matthias/Music/MUSICDB44k/OtisRedding.TheDockOfTheBay.wav"
+
Retrieving audio data... Done
+Opened 2-channel file or URL "/Users/matthias/Music/MUSICDB44k/OtisRedding.TheDockOfTheBay.wav"
+timestamp  0.000000000R: very low magnitude, setting magnitude to all zeros
+timestamp  0.046439909R: very low magnitude, setting magnitude to all zeros
+timestamp  0.092879818R: very low magnitude, setting magnitude to all zeros
+timestamp  0.139319727R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 1%
Extracting and writing features... 2%
Extracting and writing features... 3%
Extracting and writing features... 4%
Extracting and writing features... 5%
Extracting and writing features... 6%
Extracting and writing features... 7%
Extracting and writing features... 8%
Extracting and writing features... 9%
Extracting and writing features... 10%
Extracting and writing features... 11%
Extracting and writing features... 12%
Extracting and writing features... 13%
Extracting and writing features... 14%
Extracting and writing features... 15%
Extracting and writing features... 16%
Extracting and writing features... 17%
Extracting and writing features... 18%
Extracting and writing features... 19%
Extracting and writing features... 20%
Extracting and writing features... 21%
Extracting and writing features... 22%
Extracting and writing features... 23%
Extracting and writing features... 24%
Extracting and writing features... 25%
Extracting and writing features... 26%
Extracting and writing features... 27%
Extracting and writing features... 28%
Extracting and writing features... 29%
Extracting and writing features... 30%
Extracting and writing features... 31%
Extracting and writing features... 32%
Extracting and writing features... 33%
Extracting and writing features... 34%
Extracting and writing features... 35%
Extracting and writing features... 36%
Extracting and writing features... 37%
Extracting and writing features... 38%
Extracting and writing features... 39%
Extracting and writing features... 40%
Extracting and writing features... 41%
Extracting and writing features... 42%
Extracting and writing features... 43%
Extracting and writing features... 44%
Extracting and writing features... 45%
Extracting and writing features... 46%
Extracting and writing features... 47%
Extracting and writing features... 48%
Extracting and writing features... 49%
Extracting and writing features... 50%
Extracting and writing features... 51%
Extracting and writing features... 52%
Extracting and writing features... 53%
Extracting and writing features... 54%
Extracting and writing features... 55%
Extracting and writing features... 56%
Extracting and writing features... 57%
Extracting and writing features... 58%
Extracting and writing features... 59%
Extracting and writing features... 60%
Extracting and writing features... 61%
Extracting and writing features... 62%
Extracting and writing features... 63%
Extracting and writing features... 64%
Extracting and writing features... 65%
Extracting and writing features... 66%
Extracting and writing features... 67%
Extracting and writing features... 68%
Extracting and writing features... 69%
Extracting and writing features... 70%
Extracting and writing features... 71%
Extracting and writing features... 72%
Extracting and writing features... 73%
Extracting and writing features... 74%
Extracting and writing features... 75%
Extracting and writing features... 76%
Extracting and writing features... 77%
Extracting and writing features... 78%
Extracting and writing features... 79%
Extracting and writing features... 80%
Extracting and writing features... 81%
Extracting and writing features... 82%
Extracting and writing features... 83%
Extracting and writing features... 84%
Extracting and writing features... 85%
Extracting and writing features... 86%
Extracting and writing features... 87%
Extracting and writing features... 88%
Extracting and writing features... 89%
Extracting and writing features... 90%
Extracting and writing features... 91%
Extracting and writing features... 92%
Extracting and writing features... 93%
Extracting and writing features... 94%
Extracting and writing features... 95%timestamp  155.062857142R: very low magnitude, setting magnitude to all zeros
+timestamp  155.109297052R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 96%timestamp  155.434376417R: very low magnitude, setting magnitude to all zeros
+timestamp  155.480816326R: very low magnitude, setting magnitude to all zeros
+timestamp  155.527256235R: very low magnitude, setting magnitude to all zeros
+timestamp  155.573696145R: very low magnitude, setting magnitude to all zeros
+timestamp  155.620136054R: very low magnitude, setting magnitude to all zeros
+timestamp  155.666575963R: very low magnitude, setting magnitude to all zeros
+timestamp  155.945215419R: very low magnitude, setting magnitude to all zeros
+timestamp  155.991655328R: very low magnitude, setting magnitude to all zeros
+timestamp  156.038095238R: very low magnitude, setting magnitude to all zeros
+timestamp  156.084535147R: very low magnitude, setting magnitude to all zeros
+timestamp  156.130975056R: very low magnitude, setting magnitude to all zeros
+timestamp  156.177414965R: very low magnitude, setting magnitude to all zeros
+timestamp  156.223854875R: very low magnitude, setting magnitude to all zeros
+timestamp  156.270294784R: very low magnitude, setting magnitude to all zeros
+timestamp  156.316734693R: very low magnitude, setting magnitude to all zeros
+timestamp  156.363174603R: very low magnitude, setting magnitude to all zeros
+timestamp  156.409614512R: very low magnitude, setting magnitude to all zeros
+timestamp  156.456054421R: very low magnitude, setting magnitude to all zeros
+timestamp  156.502494331R: very low magnitude, setting magnitude to all zeros
+timestamp  156.548934240R: very low magnitude, setting magnitude to all zeros
+timestamp  156.595374149R: very low magnitude, setting magnitude to all zeros
+timestamp  156.641814058R: very low magnitude, setting magnitude to all zeros
+timestamp  156.688253968R: very low magnitude, setting magnitude to all zeros
+timestamp  156.734693877R: very low magnitude, setting magnitude to all zeros
+timestamp  156.781133786R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 97%timestamp  156.827573696R: very low magnitude, setting magnitude to all zeros
+timestamp  156.874013605R: very low magnitude, setting magnitude to all zeros
+timestamp  156.920453514R: very low magnitude, setting magnitude to all zeros
+timestamp  156.966893424R: very low magnitude, setting magnitude to all zeros
+timestamp  157.013333333R: very low magnitude, setting magnitude to all zeros
+timestamp  157.059773242R: very low magnitude, setting magnitude to all zeros
+timestamp  157.106213151R: very low magnitude, setting magnitude to all zeros
+timestamp  157.152653061R: very low magnitude, setting magnitude to all zeros
+timestamp  157.199092970R: very low magnitude, setting magnitude to all zeros
+timestamp  157.245532879R: very low magnitude, setting magnitude to all zeros
+timestamp  157.291972789R: very low magnitude, setting magnitude to all zeros
+timestamp  157.338412698R: very low magnitude, setting magnitude to all zeros
+timestamp  157.384852607R: very low magnitude, setting magnitude to all zeros
+timestamp  157.431292517R: very low magnitude, setting magnitude to all zeros
+timestamp  157.477732426R: very low magnitude, setting magnitude to all zeros
+timestamp  157.524172335R: very low magnitude, setting magnitude to all zeros
+timestamp  157.570612244R: very low magnitude, setting magnitude to all zeros
+timestamp  157.617052154R: very low magnitude, setting magnitude to all zeros
+timestamp  157.663492063R: very low magnitude, setting magnitude to all zeros
+timestamp  157.709931972R: very low magnitude, setting magnitude to all zeros
+timestamp  157.756371882R: very low magnitude, setting magnitude to all zeros
+timestamp  157.802811791R: very low magnitude, setting magnitude to all zeros
+timestamp  157.849251700R: very low magnitude, setting magnitude to all zeros
+timestamp  157.895691609R: very low magnitude, setting magnitude to all zeros
+timestamp  157.942131519R: very low magnitude, setting magnitude to all zeros
+timestamp  157.988571428R: very low magnitude, setting magnitude to all zeros
+timestamp  158.035011337R: very low magnitude, setting magnitude to all zeros
+timestamp  158.081451247R: very low magnitude, setting magnitude to all zeros
+timestamp  158.127891156R: very low magnitude, setting magnitude to all zeros
+timestamp  158.174331065R: very low magnitude, setting magnitude to all zeros
+timestamp  158.220770975R: very low magnitude, setting magnitude to all zeros
+timestamp  158.267210884R: very low magnitude, setting magnitude to all zeros
+timestamp  158.313650793R: very low magnitude, setting magnitude to all zeros
+timestamp  158.360090702R: very low magnitude, setting magnitude to all zeros
+timestamp  158.406530612R: very low magnitude, setting magnitude to all zeros
+timestamp  158.452970521R: very low magnitude, setting magnitude to all zeros
+timestamp  158.499410430R: very low magnitude, setting magnitude to all zeros
+timestamp  158.545850340R: very low magnitude, setting magnitude to all zeros
+timestamp  158.592290249R: very low magnitude, setting magnitude to all zeros
+timestamp  158.638730158R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 98%timestamp  158.685170068R: very low magnitude, setting magnitude to all zeros
+timestamp  158.731609977R: very low magnitude, setting magnitude to all zeros
+timestamp  158.778049886R: very low magnitude, setting magnitude to all zeros
+timestamp  158.824489795R: very low magnitude, setting magnitude to all zeros
+timestamp  158.870929705R: very low magnitude, setting magnitude to all zeros
+timestamp  158.917369614R: very low magnitude, setting magnitude to all zeros
+timestamp  158.963809523R: very low magnitude, setting magnitude to all zeros
+timestamp  159.010249433R: very low magnitude, setting magnitude to all zeros
+timestamp  159.056689342R: very low magnitude, setting magnitude to all zeros
+timestamp  159.103129251R: very low magnitude, setting magnitude to all zeros
+timestamp  159.149569160R: very low magnitude, setting magnitude to all zeros
+timestamp  159.196009070R: very low magnitude, setting magnitude to all zeros
+timestamp  159.242448979R: very low magnitude, setting magnitude to all zeros
+timestamp  159.288888888R: very low magnitude, setting magnitude to all zeros
+timestamp  159.335328798R: very low magnitude, setting magnitude to all zeros
+timestamp  159.381768707R: very low magnitude, setting magnitude to all zeros
+timestamp  159.428208616R: very low magnitude, setting magnitude to all zeros
+timestamp  159.474648526R: very low magnitude, setting magnitude to all zeros
+timestamp  159.521088435R: very low magnitude, setting magnitude to all zeros
+timestamp  159.567528344R: very low magnitude, setting magnitude to all zeros
+timestamp  159.613968253R: very low magnitude, setting magnitude to all zeros
+timestamp  159.660408163R: very low magnitude, setting magnitude to all zeros
+timestamp  159.706848072R: very low magnitude, setting magnitude to all zeros
+timestamp  159.753287981R: very low magnitude, setting magnitude to all zeros
+timestamp  159.799727891R: very low magnitude, setting magnitude to all zeros
+timestamp  159.846167800R: very low magnitude, setting magnitude to all zeros
+timestamp  159.892607709R: very low magnitude, setting magnitude to all zeros
+timestamp  159.939047619R: very low magnitude, setting magnitude to all zeros
+timestamp  159.985487528R: very low magnitude, setting magnitude to all zeros
+timestamp  160.031927437R: very low magnitude, setting magnitude to all zeros
+timestamp  160.078367346R: very low magnitude, setting magnitude to all zeros
+timestamp  160.124807256R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 99%timestamp  160.171247165R: very low magnitude, setting magnitude to all zeros
+timestamp  160.217687074R: very low magnitude, setting magnitude to all zeros
+timestamp  160.264126984R: very low magnitude, setting magnitude to all zeros
+timestamp  160.310566893R: very low magnitude, setting magnitude to all zeros
+timestamp  160.357006802R: very low magnitude, setting magnitude to all zeros
+timestamp  160.403446712R: very low magnitude, setting magnitude to all zeros
+timestamp  160.449886621R: very low magnitude, setting magnitude to all zeros
+timestamp  160.496326530R: very low magnitude, setting magnitude to all zeros
+timestamp  160.542766439R: very low magnitude, setting magnitude to all zeros
+timestamp  160.589206349R: very low magnitude, setting magnitude to all zeros
+timestamp  160.635646258R: very low magnitude, setting magnitude to all zeros
+timestamp  160.682086167R: very low magnitude, setting magnitude to all zeros
+timestamp  160.728526077R: very low magnitude, setting magnitude to all zeros
+timestamp  160.774965986R: very low magnitude, setting magnitude to all zeros
+timestamp  160.821405895R: very low magnitude, setting magnitude to all zeros
+timestamp  160.867845804R: very low magnitude, setting magnitude to all zeros
+timestamp  160.914285714R: very low magnitude, setting magnitude to all zeros
+timestamp  160.960725623R: very low magnitude, setting magnitude to all zeros
+timestamp  161.007165532R: very low magnitude, setting magnitude to all zeros
+timestamp  161.053605442R: very low magnitude, setting magnitude to all zeros
+timestamp  161.100045351R: very low magnitude, setting magnitude to all zeros
+timestamp  161.146485260R: very low magnitude, setting magnitude to all zeros
+timestamp  161.192925170R: very low magnitude, setting magnitude to all zeros
+timestamp  161.239365079R: very low magnitude, setting magnitude to all zeros
+timestamp  161.285804988R: very low magnitude, setting magnitude to all zeros
+timestamp  161.332244897R: very low magnitude, setting magnitude to all zeros
+timestamp  161.378684807R: very low magnitude, setting magnitude to all zeros
+timestamp  161.425124716R: very low magnitude, setting magnitude to all zeros
+timestamp  161.471564625R: very low magnitude, setting magnitude to all zeros
+timestamp  161.518004535R: very low magnitude, setting magnitude to all zeros
+timestamp  161.564444444R: very low magnitude, setting magnitude to all zeros
+timestamp  161.610884353R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 100%timestamp  161.657324263R: very low magnitude, setting magnitude to all zeros
+[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... done.
+[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... done.
+[NNLS Chroma Plugin] Chord Estimation ... done.
+
Extracting and writing features... Done
+
+                              < M A T L A B >
+                  Copyright 1984-2007 The MathWorks, Inc.
+                         Version 7.5.0.338 (R2007b)
+                               August 9, 2007
+
+ 
+  To get started, type one of these: helpwin, helpdesk, or demo.
+  For product information, visit www.mathworks.com.
+ 
+   - First Slice
+    metpos 
+    key 
+    chord 
+    bass 
+   - Second Slice
+    (7) metpos (slice 2) 
+    (8) key (slice 2) 
+    (9) chord (slice 2) 
+    (10) bass (slice 2) 
+onset detection function
+beats
+
+
Length: 28
Length: 32
Length: 36
Length: 40
Length: 44
Length: 48
Length: 52
Length: 56
Length: 60
Length: 64
Length: 68
Length: 72
Length: 76
Length: 80
Length: 84
Length: 88
Length: 92
Length: 96
Length: 100
Length: 104
Length: 108
Length: 112
Length: 116
Length: 120
Length: 124
Length: 128
+Finding maximum probability path (part 1 of 6, beats 1 to 34)... 
+forward step
+backward step
+
+Finding maximum probability path (part 2 of 6, beats 35 to 162)... 
+forward step
+backward step
+
+Finding maximum probability path (part 3 of 6, beats 163 to 290)... 
+forward step
+backward step
+
+Finding maximum probability path (part 4 of 6, beats 291 to 354)... 
+forward step
+backward step
+
+Finding maximum probability path (part 5 of 6, beats 355 to 482)... 
+forward step
+backward step
+
+Finding maximum probability path (part 6 of 6, beats 483 to 559)... 
+forward step
+backward step
+0.0 0.023 N
+0.023 11.529 G
+11.529 14.141 B
+14.141 15.581 C
+15.581 16.149 N
+16.149 18.762 A
+18.762 20.770 G
+20.770 23.359 B
+23.359 24.811 C
+24.811 25.391 N
+25.391 27.992 A
+27.992 30.023 G
+30.023 32.311 E
+32.311 34.633 G
+34.633 37.222 E
+37.222 39.253 G
+39.253 41.575 A
+41.575 43.862 G/5
+43.862 46.475 E
+46.475 48.506 G
+48.506 51.142 B
+51.142 52.605 C
+52.605 53.197 N
+53.197 55.821 A
+55.821 57.876 G
+57.876 60.500 B
+60.500 61.962 C
+61.962 62.566 N
+62.566 65.202 A
+65.202 67.257 G
+67.257 69.613 E
+69.613 71.912 G
+71.912 74.513 E
+74.513 76.556 G
+76.556 78.890 A
+78.890 81.200 G/5
+81.200 83.824 E
+83.824 85.008 G
+85.008 85.867 D
+85.867 88.155 C
+88.155 88.433 F#:dim
+88.433 89.594 G
+89.594 90.465 D
+90.465 93.077 C
+93.077 94.250 G
+94.250 95.411 D
+95.411 96.583 C
+96.583 97.744 G
+97.744 98.348 G:7
+98.348 99.532 F:maj7
+99.532 100.113 F/5
+100.113 102.412 D
+102.412 104.455 G
+104.455 107.067 B
+107.067 108.518 C
+108.518 109.099 N
+109.099 111.700 A
+111.700 113.697 G
+113.697 116.320 B
+116.320 117.772 C
+117.772 118.340 N
+118.340 120.953 A
+120.953 122.984 G
+122.984 125.295 E
+125.295 127.594 G
+127.594 130.229 E
+130.229 132.261 G
+132.261 134.594 A
+134.594 136.916 G/5
+136.916 139.517 E
+139.517 146.460 G
+146.460 148.793 E
+148.793 155.400 G
+155.400 161.733 N0.0 0.023 N
+0.023 161.733 G
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_logfiles/RollingStonesRipThisJoint.wav.log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,166 @@
+CSVFeatureWriter::setParameters
+stdout -> 
+NOTE: Using default sample rate of 44100 for default transform
+NOTE: Loaded and initialised plugin for transform "vamp:matthiasm:nnls_chroma:bothchroma" with plugin step size 2048 and block size 16384 (adapter step and block size 16384)
+NOTE: PluginInputDomainAdapter timestamp adjustment is  0.000000000R
+Extracting features for: "/Users/matthiasm/data/RollingStonesRipThisJoint.wav"
+
Retrieving audio data... Done
+Opened 2-channel file or URL "/Users/matthiasm/data/RollingStonesRipThisJoint.wav"
+timestamp  0.000000000R: very low magnitude, setting magnitude to all zeros
+timestamp  0.046439909R: very low magnitude, setting magnitude to all zeros
+timestamp  0.092879818R: very low magnitude, setting magnitude to all zeros
+timestamp  0.139319727R: very low magnitude, setting magnitude to all zeros
+timestamp  0.185759637R: very low magnitude, setting magnitude to all zeros
+timestamp  0.232199546R: very low magnitude, setting magnitude to all zeros
+timestamp  0.278639455R: very low magnitude, setting magnitude to all zeros
+timestamp  0.325079365R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 1%
Extracting and writing features... 2%
Extracting and writing features... 3%
Extracting and writing features... 4%
Extracting and writing features... 5%
Extracting and writing features... 6%
Extracting and writing features... 7%
Extracting and writing features... 8%
Extracting and writing features... 9%
Extracting and writing features... 10%
Extracting and writing features... 11%
Extracting and writing features... 12%
Extracting and writing features... 13%
Extracting and writing features... 14%
Extracting and writing features... 15%
Extracting and writing features... 16%
Extracting and writing features... 17%
Extracting and writing features... 18%
Extracting and writing features... 19%
Extracting and writing features... 20%
Extracting and writing features... 21%
Extracting and writing features... 22%
Extracting and writing features... 23%
Extracting and writing features... 24%
Extracting and writing features... 25%
Extracting and writing features... 26%
Extracting and writing features... 27%
Extracting and writing features... 28%
Extracting and writing features... 29%
Extracting and writing features... 30%
Extracting and writing features... 31%
Extracting and writing features... 32%
Extracting and writing features... 33%
Extracting and writing features... 34%
Extracting and writing features... 35%
Extracting and writing features... 36%
Extracting and writing features... 37%
Extracting and writing features... 38%
Extracting and writing features... 39%
Extracting and writing features... 40%
Extracting and writing features... 41%
Extracting and writing features... 42%
Extracting and writing features... 43%
Extracting and writing features... 44%
Extracting and writing features... 45%
Extracting and writing features... 46%
Extracting and writing features... 47%
Extracting and writing features... 48%
Extracting and writing features... 49%
Extracting and writing features... 50%
Extracting and writing features... 51%
Extracting and writing features... 52%
Extracting and writing features... 53%
Extracting and writing features... 54%
Extracting and writing features... 55%
Extracting and writing features... 56%
Extracting and writing features... 57%
Extracting and writing features... 58%
Extracting and writing features... 59%
Extracting and writing features... 60%
Extracting and writing features... 61%
Extracting and writing features... 62%
Extracting and writing features... 63%
Extracting and writing features... 64%
Extracting and writing features... 65%
Extracting and writing features... 66%
Extracting and writing features... 67%
Extracting and writing features... 68%
Extracting and writing features... 69%
Extracting and writing features... 70%
Extracting and writing features... 71%
Extracting and writing features... 72%
Extracting and writing features... 73%
Extracting and writing features... 74%
Extracting and writing features... 75%
Extracting and writing features... 76%
Extracting and writing features... 77%
Extracting and writing features... 78%
Extracting and writing features... 79%
Extracting and writing features... 80%
Extracting and writing features... 81%
Extracting and writing features... 82%
Extracting and writing features... 83%
Extracting and writing features... 84%
Extracting and writing features... 85%
Extracting and writing features... 86%
Extracting and writing features... 87%
Extracting and writing features... 88%
Extracting and writing features... 89%
Extracting and writing features... 90%
Extracting and writing features... 91%
Extracting and writing features... 92%
Extracting and writing features... 93%
Extracting and writing features... 94%
Extracting and writing features... 95%
Extracting and writing features... 96%
Extracting and writing features... 97%
Extracting and writing features... 98%timestamp  140.852244897R: very low magnitude, setting magnitude to all zeros
+timestamp  140.898684807R: very low magnitude, setting magnitude to all zeros
+timestamp  140.945124716R: very low magnitude, setting magnitude to all zeros
+timestamp  140.991564625R: very low magnitude, setting magnitude to all zeros
+timestamp  141.038004535R: very low magnitude, setting magnitude to all zeros
+timestamp  141.084444444R: very low magnitude, setting magnitude to all zeros
+timestamp  141.130884353R: very low magnitude, setting magnitude to all zeros
+timestamp  141.177324263R: very low magnitude, setting magnitude to all zeros
+timestamp  141.223764172R: very low magnitude, setting magnitude to all zeros
+timestamp  141.270204081R: very low magnitude, setting magnitude to all zeros
+timestamp  141.316643990R: very low magnitude, setting magnitude to all zeros
+timestamp  141.363083900R: very low magnitude, setting magnitude to all zeros
+timestamp  141.409523809R: very low magnitude, setting magnitude to all zeros
+timestamp  141.455963718R: very low magnitude, setting magnitude to all zeros
+timestamp  141.502403628R: very low magnitude, setting magnitude to all zeros
+timestamp  141.548843537R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 99%timestamp  141.595283446R: very low magnitude, setting magnitude to all zeros
+timestamp  141.641723356R: very low magnitude, setting magnitude to all zeros
+timestamp  141.688163265R: very low magnitude, setting magnitude to all zeros
+timestamp  141.734603174R: very low magnitude, setting magnitude to all zeros
+timestamp  141.781043083R: very low magnitude, setting magnitude to all zeros
+timestamp  141.827482993R: very low magnitude, setting magnitude to all zeros
+timestamp  141.873922902R: very low magnitude, setting magnitude to all zeros
+timestamp  141.920362811R: very low magnitude, setting magnitude to all zeros
+timestamp  141.966802721R: very low magnitude, setting magnitude to all zeros
+timestamp  142.013242630R: very low magnitude, setting magnitude to all zeros
+timestamp  142.059682539R: very low magnitude, setting magnitude to all zeros
+timestamp  142.106122448R: very low magnitude, setting magnitude to all zeros
+timestamp  142.152562358R: very low magnitude, setting magnitude to all zeros
+timestamp  142.199002267R: very low magnitude, setting magnitude to all zeros
+timestamp  142.245442176R: very low magnitude, setting magnitude to all zeros
+timestamp  142.291882086R: very low magnitude, setting magnitude to all zeros
+timestamp  142.338321995R: very low magnitude, setting magnitude to all zeros
+timestamp  142.384761904R: very low magnitude, setting magnitude to all zeros
+timestamp  142.431201814R: very low magnitude, setting magnitude to all zeros
+timestamp  142.477641723R: very low magnitude, setting magnitude to all zeros
+timestamp  142.524081632R: very low magnitude, setting magnitude to all zeros
+timestamp  142.570521541R: very low magnitude, setting magnitude to all zeros
+timestamp  142.616961451R: very low magnitude, setting magnitude to all zeros
+timestamp  142.663401360R: very low magnitude, setting magnitude to all zeros
+timestamp  142.709841269R: very low magnitude, setting magnitude to all zeros
+[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... done.
+[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... done.
+[NNLS Chroma Plugin] Chord Estimation ... done.
+
Extracting and writing features... Done
+
+
+                            < M A T L A B (R) >
+                  Copyright 1984-2011 The MathWorks, Inc.
+                    R2011b (7.13.0.564) 64-bit (maci64)
+                              August 13, 2011
+
+ 
+To get started, type one of these: helpwin, helpdesk, or demo.
+For product information, visit www.mathworks.com.
+ 
+   - First Slice
+    metpos 
+    key 
+    chord 
+    bass 
+   - Second Slice
+    (7) metpos (slice 2) 
+    (8) key (slice 2) 
+    (9) chord (slice 2) 
+    (10) bass (slice 2) 
+onset detection function
+beats
+
+
Length: 28
Length: 32
Length: 36
Length: 40
Length: 44
Length: 48
Length: 52
Length: 56
Length: 60
Length: 64
Length: 68
Length: 72
Length: 76
Length: 80
Length: 84
Length: 88
Length: 92
Length: 96
Length: 100
Length: 104
Length: 108
Length: 112
Length: 116
Length: 120
Length: 124
Length: 128
+Finding maximum probability path (part 1 of 11, beats 1 to 45)... 
+forward step
+backward step
+
+Finding maximum probability path (part 2 of 11, beats 46 to 115)... 
+forward step
+backward step
+
+Finding maximum probability path (part 3 of 11, beats 116 to 143)... 
+forward step
+backward step
+
+Finding maximum probability path (part 4 of 11, beats 144 to 155)... 
+forward step
+backward step
+
+Finding maximum probability path (part 5 of 11, beats 156 to 185)... 
+forward step
+backward step
+
+Finding maximum probability path (part 6 of 11, beats 186 to 221)... 
+forward step
+backward step
+
+Finding maximum probability path (part 7 of 11, beats 222 to 285)... 
+forward step
+backward step
+
+Finding maximum probability path (part 8 of 11, beats 286 to 331)... 
+forward step
+backward step
+
+Finding maximum probability path (part 9 of 11, beats 332 to 361)... 
+forward step
+backward step
+
+Finding maximum probability path (part 10 of 11, beats 362 to 397)... 
+forward step
+backward step
+
+Finding maximum probability path (part 11 of 11, beats 398 to 469)... 
+forward step
+backward step
+0.0 0.151 N
+0.151 0.464 N
+0.464 12.655 D
+12.655 13.897 A
+13.897 14.826 A:min7
+14.826 15.755 D/5
+15.755 16.370 G
+16.370 17.589 D
+17.589 19.725 A:min
+19.725 42.109 D
+42.109 44.246 A:min
+44.246 54.358 D
+54.358 56.750 A:min
+56.750 66.456 D
+66.456 67.686 A:min
+67.686 68.603 A:min7
+68.603 69.532 D/5
+69.532 70.136 G
+70.136 71.332 D
+71.332 73.468 A:min
+73.468 90.895 D
+90.895 93.019 A
+93.019 95.759 D
+95.759 98.197 A:min
+98.197 107.950 D
+107.950 110.039 A:min
+110.039 110.353 D/5
+110.353 120.070 D
+120.070 120.999 A
+120.999 121.313 A:min7
+121.313 123.147 D/5
+123.147 123.751 G
+123.751 124.970 D
+124.970 127.118 A:min
+127.118 140.690 D
+140.690 142.960 N0.0 0.151 N
+0.151 142.960 D
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_logfiles/U2.WithOrWithoutYou.wav.log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,612 @@
+CSVFeatureWriter::setParameters
+stdout -> 
+NOTE: Using default sample rate of 44100 for default transform
+NOTE: Loaded and initialised plugin for transform "vamp:matthiasm:nnls_chroma:bothchroma" with plugin step size 2048 and block size 16384 (adapter step and block size 16384)
+NOTE: PluginInputDomainAdapter timestamp adjustment is  0.000000000R
+Extracting features for: "/Users/matthias/Music/MUSICDB44k/U2.WithOrWithoutYou.wav"
+
Retrieving audio data... Done
+Opened 2-channel file or URL "/Users/matthias/Music/MUSICDB44k/U2.WithOrWithoutYou.wav"
+timestamp  0.000000000R: very low magnitude, setting magnitude to all zeros
+timestamp  0.046439909R: very low magnitude, setting magnitude to all zeros
+timestamp  0.092879818R: very low magnitude, setting magnitude to all zeros
+timestamp  0.139319727R: very low magnitude, setting magnitude to all zeros
+timestamp  0.185759637R: very low magnitude, setting magnitude to all zeros
+timestamp  0.232199546R: very low magnitude, setting magnitude to all zeros
+timestamp  0.278639455R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 1%
Extracting and writing features... 2%
Extracting and writing features... 3%
Extracting and writing features... 4%
Extracting and writing features... 5%
Extracting and writing features... 6%
Extracting and writing features... 7%
Extracting and writing features... 8%
Extracting and writing features... 9%
Extracting and writing features... 10%
Extracting and writing features... 11%
Extracting and writing features... 12%
Extracting and writing features... 13%
Extracting and writing features... 14%
Extracting and writing features... 15%
Extracting and writing features... 16%
Extracting and writing features... 17%
Extracting and writing features... 18%
Extracting and writing features... 19%
Extracting and writing features... 20%
Extracting and writing features... 21%
Extracting and writing features... 22%
Extracting and writing features... 23%
Extracting and writing features... 24%
Extracting and writing features... 25%
Extracting and writing features... 26%
Extracting and writing features... 27%
Extracting and writing features... 28%
Extracting and writing features... 29%
Extracting and writing features... 30%
Extracting and writing features... 31%
Extracting and writing features... 32%
Extracting and writing features... 33%
Extracting and writing features... 34%
Extracting and writing features... 35%
Extracting and writing features... 36%
Extracting and writing features... 37%
Extracting and writing features... 38%
Extracting and writing features... 39%
Extracting and writing features... 40%
Extracting and writing features... 41%
Extracting and writing features... 42%
Extracting and writing features... 43%
Extracting and writing features... 44%
Extracting and writing features... 45%
Extracting and writing features... 46%
Extracting and writing features... 47%
Extracting and writing features... 48%
Extracting and writing features... 49%
Extracting and writing features... 50%
Extracting and writing features... 51%
Extracting and writing features... 52%
Extracting and writing features... 53%
Extracting and writing features... 54%
Extracting and writing features... 55%
Extracting and writing features... 56%
Extracting and writing features... 57%
Extracting and writing features... 58%
Extracting and writing features... 59%
Extracting and writing features... 60%
Extracting and writing features... 61%
Extracting and writing features... 62%
Extracting and writing features... 63%
Extracting and writing features... 64%
Extracting and writing features... 65%
Extracting and writing features... 66%
Extracting and writing features... 67%
Extracting and writing features... 68%
Extracting and writing features... 69%
Extracting and writing features... 70%
Extracting and writing features... 71%
Extracting and writing features... 72%
Extracting and writing features... 73%
Extracting and writing features... 74%
Extracting and writing features... 75%
Extracting and writing features... 76%
Extracting and writing features... 77%
Extracting and writing features... 78%
Extracting and writing features... 79%
Extracting and writing features... 80%
Extracting and writing features... 81%
Extracting and writing features... 82%
Extracting and writing features... 83%
Extracting and writing features... 84%
Extracting and writing features... 85%
Extracting and writing features... 86%
Extracting and writing features... 87%
Extracting and writing features... 88%
Extracting and writing features... 89%
Extracting and writing features... 90%
Extracting and writing features... 91%
Extracting and writing features... 92%
Extracting and writing features... 93%
Extracting and writing features... 94%
Extracting and writing features... 95%
Extracting and writing features... 96%
Extracting and writing features... 97%timestamp  292.060589569R: very low magnitude, setting magnitude to all zeros
+timestamp  292.107029478R: very low magnitude, setting magnitude to all zeros
+timestamp  292.292789115R: very low magnitude, setting magnitude to all zeros
+timestamp  292.339229024R: very low magnitude, setting magnitude to all zeros
+timestamp  292.385668934R: very low magnitude, setting magnitude to all zeros
+timestamp  292.432108843R: very low magnitude, setting magnitude to all zeros
+timestamp  292.478548752R: very low magnitude, setting magnitude to all zeros
+timestamp  292.524988662R: very low magnitude, setting magnitude to all zeros
+timestamp  293.407346938R: very low magnitude, setting magnitude to all zeros
+timestamp  293.453786848R: very low magnitude, setting magnitude to all zeros
+timestamp  293.500226757R: very low magnitude, setting magnitude to all zeros
+timestamp  293.546666666R: very low magnitude, setting magnitude to all zeros
+timestamp  293.593106575R: very low magnitude, setting magnitude to all zeros
+timestamp  293.639546485R: very low magnitude, setting magnitude to all zeros
+timestamp  293.685986394R: very low magnitude, setting magnitude to all zeros
+timestamp  293.732426303R: very low magnitude, setting magnitude to all zeros
+timestamp  293.778866213R: very low magnitude, setting magnitude to all zeros
+timestamp  293.825306122R: very low magnitude, setting magnitude to all zeros
+timestamp  293.871746031R: very low magnitude, setting magnitude to all zeros
+timestamp  293.918185941R: very low magnitude, setting magnitude to all zeros
+timestamp  293.964625850R: very low magnitude, setting magnitude to all zeros
+timestamp  294.011065759R: very low magnitude, setting magnitude to all zeros
+timestamp  294.057505668R: very low magnitude, setting magnitude to all zeros
+timestamp  294.103945578R: very low magnitude, setting magnitude to all zeros
+timestamp  294.150385487R: very low magnitude, setting magnitude to all zeros
+timestamp  294.196825396R: very low magnitude, setting magnitude to all zeros
+timestamp  294.243265306R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 98%timestamp  294.289705215R: very low magnitude, setting magnitude to all zeros
+timestamp  294.336145124R: very low magnitude, setting magnitude to all zeros
+timestamp  294.382585034R: very low magnitude, setting magnitude to all zeros
+timestamp  294.429024943R: very low magnitude, setting magnitude to all zeros
+timestamp  294.475464852R: very low magnitude, setting magnitude to all zeros
+timestamp  294.521904761R: very low magnitude, setting magnitude to all zeros
+timestamp  294.568344671R: very low magnitude, setting magnitude to all zeros
+timestamp  294.614784580R: very low magnitude, setting magnitude to all zeros
+timestamp  294.661224489R: very low magnitude, setting magnitude to all zeros
+timestamp  294.707664399R: very low magnitude, setting magnitude to all zeros
+timestamp  294.754104308R: very low magnitude, setting magnitude to all zeros
+timestamp  294.800544217R: very low magnitude, setting magnitude to all zeros
+timestamp  294.846984126R: very low magnitude, setting magnitude to all zeros
+timestamp  294.893424036R: very low magnitude, setting magnitude to all zeros
+timestamp  294.939863945R: very low magnitude, setting magnitude to all zeros
+timestamp  294.986303854R: very low magnitude, setting magnitude to all zeros
+timestamp  295.032743764R: very low magnitude, setting magnitude to all zeros
+timestamp  295.079183673R: very low magnitude, setting magnitude to all zeros
+timestamp  295.125623582R: very low magnitude, setting magnitude to all zeros
+timestamp  295.172063492R: very low magnitude, setting magnitude to all zeros
+timestamp  295.218503401R: very low magnitude, setting magnitude to all zeros
+timestamp  295.264943310R: very low magnitude, setting magnitude to all zeros
+timestamp  295.311383219R: very low magnitude, setting magnitude to all zeros
+timestamp  295.357823129R: very low magnitude, setting magnitude to all zeros
+timestamp  295.404263038R: very low magnitude, setting magnitude to all zeros
+timestamp  295.450702947R: very low magnitude, setting magnitude to all zeros
+timestamp  295.497142857R: very low magnitude, setting magnitude to all zeros
+timestamp  295.543582766R: very low magnitude, setting magnitude to all zeros
+timestamp  295.590022675R: very low magnitude, setting magnitude to all zeros
+timestamp  295.636462585R: very low magnitude, setting magnitude to all zeros
+timestamp  295.682902494R: very low magnitude, setting magnitude to all zeros
+timestamp  295.729342403R: very low magnitude, setting magnitude to all zeros
+timestamp  295.775782312R: very low magnitude, setting magnitude to all zeros
+timestamp  295.822222222R: very low magnitude, setting magnitude to all zeros
+timestamp  295.868662131R: very low magnitude, setting magnitude to all zeros
+timestamp  295.915102040R: very low magnitude, setting magnitude to all zeros
+timestamp  295.961541950R: very low magnitude, setting magnitude to all zeros
+timestamp  296.007981859R: very low magnitude, setting magnitude to all zeros
+timestamp  296.054421768R: very low magnitude, setting magnitude to all zeros
+timestamp  296.100861678R: very low magnitude, setting magnitude to all zeros
+timestamp  296.147301587R: very low magnitude, setting magnitude to all zeros
+timestamp  296.193741496R: very low magnitude, setting magnitude to all zeros
+timestamp  296.240181405R: very low magnitude, setting magnitude to all zeros
+timestamp  296.286621315R: very low magnitude, setting magnitude to all zeros
+timestamp  296.333061224R: very low magnitude, setting magnitude to all zeros
+timestamp  296.379501133R: very low magnitude, setting magnitude to all zeros
+timestamp  296.425941043R: very low magnitude, setting magnitude to all zeros
+timestamp  296.472380952R: very low magnitude, setting magnitude to all zeros
+timestamp  296.518820861R: very low magnitude, setting magnitude to all zeros
+timestamp  296.565260770R: very low magnitude, setting magnitude to all zeros
+timestamp  296.611700680R: very low magnitude, setting magnitude to all zeros
+timestamp  296.658140589R: very low magnitude, setting magnitude to all zeros
+timestamp  296.704580498R: very low magnitude, setting magnitude to all zeros
+timestamp  296.751020408R: very low magnitude, setting magnitude to all zeros
+timestamp  296.797460317R: very low magnitude, setting magnitude to all zeros
+timestamp  296.843900226R: very low magnitude, setting magnitude to all zeros
+timestamp  296.890340136R: very low magnitude, setting magnitude to all zeros
+timestamp  296.936780045R: very low magnitude, setting magnitude to all zeros
+timestamp  296.983219954R: very low magnitude, setting magnitude to all zeros
+timestamp  297.029659863R: very low magnitude, setting magnitude to all zeros
+timestamp  297.076099773R: very low magnitude, setting magnitude to all zeros
+timestamp  297.122539682R: very low magnitude, setting magnitude to all zeros
+timestamp  297.168979591R: very low magnitude, setting magnitude to all zeros
+timestamp  297.215419501R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 99%timestamp  297.261859410R: very low magnitude, setting magnitude to all zeros
+timestamp  297.308299319R: very low magnitude, setting magnitude to all zeros
+timestamp  297.354739229R: very low magnitude, setting magnitude to all zeros
+timestamp  297.401179138R: very low magnitude, setting magnitude to all zeros
+timestamp  297.447619047R: very low magnitude, setting magnitude to all zeros
+timestamp  297.494058956R: very low magnitude, setting magnitude to all zeros
+timestamp  297.540498866R: very low magnitude, setting magnitude to all zeros
+timestamp  297.586938775R: very low magnitude, setting magnitude to all zeros
+timestamp  297.633378684R: very low magnitude, setting magnitude to all zeros
+timestamp  297.679818594R: very low magnitude, setting magnitude to all zeros
+timestamp  297.726258503R: very low magnitude, setting magnitude to all zeros
+timestamp  297.772698412R: very low magnitude, setting magnitude to all zeros
+timestamp  297.819138321R: very low magnitude, setting magnitude to all zeros
+timestamp  297.865578231R: very low magnitude, setting magnitude to all zeros
+timestamp  297.912018140R: very low magnitude, setting magnitude to all zeros
+timestamp  297.958458049R: very low magnitude, setting magnitude to all zeros
+timestamp  298.004897959R: very low magnitude, setting magnitude to all zeros
+timestamp  298.051337868R: very low magnitude, setting magnitude to all zeros
+timestamp  298.097777777R: very low magnitude, setting magnitude to all zeros
+timestamp  298.144217687R: very low magnitude, setting magnitude to all zeros
+timestamp  298.190657596R: very low magnitude, setting magnitude to all zeros
+timestamp  298.237097505R: very low magnitude, setting magnitude to all zeros
+timestamp  298.283537414R: very low magnitude, setting magnitude to all zeros
+timestamp  298.329977324R: very low magnitude, setting magnitude to all zeros
+timestamp  298.376417233R: very low magnitude, setting magnitude to all zeros
+timestamp  298.422857142R: very low magnitude, setting magnitude to all zeros
+timestamp  298.469297052R: very low magnitude, setting magnitude to all zeros
+timestamp  298.515736961R: very low magnitude, setting magnitude to all zeros
+timestamp  298.562176870R: very low magnitude, setting magnitude to all zeros
+timestamp  298.608616780R: very low magnitude, setting magnitude to all zeros
+timestamp  298.655056689R: very low magnitude, setting magnitude to all zeros
+timestamp  298.701496598R: very low magnitude, setting magnitude to all zeros
+timestamp  298.747936507R: very low magnitude, setting magnitude to all zeros
+timestamp  298.794376417R: very low magnitude, setting magnitude to all zeros
+timestamp  298.840816326R: very low magnitude, setting magnitude to all zeros
+timestamp  298.887256235R: very low magnitude, setting magnitude to all zeros
+timestamp  298.933696145R: very low magnitude, setting magnitude to all zeros
+timestamp  298.980136054R: very low magnitude, setting magnitude to all zeros
+timestamp  299.026575963R: very low magnitude, setting magnitude to all zeros
+timestamp  299.073015873R: very low magnitude, setting magnitude to all zeros
+timestamp  299.119455782R: very low magnitude, setting magnitude to all zeros
+timestamp  299.165895691R: very low magnitude, setting magnitude to all zeros
+timestamp  299.212335600R: very low magnitude, setting magnitude to all zeros
+timestamp  299.258775510R: very low magnitude, setting magnitude to all zeros
+timestamp  299.305215419R: very low magnitude, setting magnitude to all zeros
+timestamp  299.351655328R: very low magnitude, setting magnitude to all zeros
+timestamp  299.398095238R: very low magnitude, setting magnitude to all zeros
+timestamp  299.444535147R: very low magnitude, setting magnitude to all zeros
+timestamp  299.490975056R: very low magnitude, setting magnitude to all zeros
+timestamp  299.537414965R: very low magnitude, setting magnitude to all zeros
+timestamp  299.583854875R: very low magnitude, setting magnitude to all zeros
+timestamp  299.630294784R: very low magnitude, setting magnitude to all zeros
+timestamp  299.676734693R: very low magnitude, setting magnitude to all zeros
+timestamp  299.723174603R: very low magnitude, setting magnitude to all zeros
+timestamp  299.769614512R: very low magnitude, setting magnitude to all zeros
+timestamp  299.816054421R: very low magnitude, setting magnitude to all zeros
+timestamp  299.862494331R: very low magnitude, setting magnitude to all zeros
+timestamp  299.908934240R: very low magnitude, setting magnitude to all zeros
+timestamp  299.955374149R: very low magnitude, setting magnitude to all zeros
+timestamp  300.001814058R: very low magnitude, setting magnitude to all zeros
+timestamp  300.048253968R: very low magnitude, setting magnitude to all zeros
+timestamp  300.094693877R: very low magnitude, setting magnitude to all zeros
+timestamp  300.141133786R: very low magnitude, setting magnitude to all zeros
+timestamp  300.187573696R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 100%timestamp  300.234013605R: very low magnitude, setting magnitude to all zeros
+[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... done.
+[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... done.
+[NNLS Chroma Plugin] Chord Estimation ... done.
+
Extracting and writing features... Done
+ep
+
+Finding maximum probability path (part 6 of 26, beats 174 to 205)... 
+forward step
+backward step
+
+                              < M A T L A B >
+                  Copyright 1984-2007 The MathWorks, Inc.
+                         Version 7.5.0.338 (R2007b)
+                               August 9, 2007
+
+ 
+  To get started, type one of these: helpwin, helpdesk, or demo.
+  For product information, visit www.mathworks.com.
+ 
+   - First Slice
+    metpos 
+    key 
+    chord 
+    bass 
+   - Second Slice
+    (7) metpos (slice 2) 
+    (8) key (slice 2) 
+    (9) chord (slice 2) 
+    (10) bass (slice 2) 
+
+Finding maximum probability path (part 7 of 26, beats 206 to 237)... 
+forward step
+onset detection function
+beats
+backward step
+
+Finding maximum probability path (part 8 of 26, beats 238 to 268)... 
+forward step
+
+
Length: 28backward step
+
Length: 32
+Finding maximum probability path (part 9 of 26, beats 269 to 301)... 
+forward step
+
Length: 36
Length: 40
Length: 44backward step
+
Length: 48
Length: 52
+Finding maximum probability path (part 10 of 26, beats 302 to 333)... 
+forward step
+
Length: 56
Length: 60
Length: 64backward step
+
Length: 68
Length: 72
+Finding maximum probability path (part 11 of 26, beats 334 to 365)... 
+forward step
+
Length: 76
Length: 80
Length: 84backward step
+
Length: 88
Length: 92
+Finding maximum probability path (part 12 of 26, beats 366 to 396)... 
+forward step
+
Length: 96
Length: 100
Length: 104backward step
+
Length: 108
Length: 112
+Finding maximum probability path (part 13 of 26, beats 397 to 429)... 
+forward step
+
Length: 116
Length: 120backward step
+
Length: 124
Length: 128
+Finding maximum probability path (part 14 of 26, beats 430 to 461)... 
+forward step
+
+Finding maximum probability path (part 1 of 26, beats 1 to 35)... 
+forward step
+backward step
+backward step
+
+Finding maximum probability path (part 15 of 26, beats 462 to 493)... 
+forward step
+
+Finding maximum probability path (part 2 of 26, beats 36 to 67)... 
+forward step
+backward step
+backward step
+
+Finding maximum probability path (part 16 of 26, beats 494 to 524)... 
+forward step
+
+Finding maximum probability path (part 3 of 26, beats 68 to 99)... 
+forward step
+backward step
+backward step
+
+Finding maximum probability path (part 17 of 26, beats 525 to 557)... 
+forward step
+
+Finding maximum probability path (part 4 of 26, beats 100 to 132)... 
+forward step
+backward step
+backward step
+
+Finding maximum probability path (part 18 of 26, beats 558 to 585)... 
+forward step
+
+Finding maximum probability path (part 5 of 26, beats 133 to 164)... 
+forward step
+backward step
+
+Finding maximum probability path (part 19 of 26, beats 586 to 654)... 
+forward step
+backward step
+
+Finding maximum probability path (part 6 of 26, beats 165 to 193)... 
+forward step
+backward step
+backward step
+
+Finding maximum probability path (part 7 of 26, beats 194 to 227)... 
+forward step
+
+Finding maximum probability path (part 20 of 26, beats 655 to 682)... 
+forward step
+backward step
+backward step
+
+Finding maximum probability path (part 8 of 26, beats 228 to 255)... 
+forward step
+
+Finding maximum probability path (part 21 of 26, beats 683 to 718)... 
+forward step
+backward step
+backward step
+
+Finding maximum probability path (part 9 of 26, beats 256 to 291)... 
+forward step
+
+Finding maximum probability path (part 22 of 26, beats 719 to 746)... 
+forward step
+backward step
+backward step
+
+Finding maximum probability path (part 10 of 26, beats 292 to 323)... 
+forward step
+
+Finding maximum probability path (part 23 of 26, beats 747 to 766)... 
+forward step
+backward step
+backward step
+
+Finding maximum probability path (part 11 of 26, beats 324 to 355)... 
+forward step
+
+Finding maximum probability path (part 24 of 26, beats 767 to 798)... 
+forward step
+backward step
+backward step
+
+Finding maximum probability path (part 25 of 26, beats 799 to 826)... 
+forward step
+
+Finding maximum probability path (part 12 of 26, beats 356 to 388)... 
+forward step
+backward step
+backward step
+
+Finding maximum probability path (part 26 of 26, beats 827 to 847)... 
+forward step
+
+Finding maximum probability path (part 13 of 26, beats 389 to 419)... 
+forward step
+backward step
+0.0 0.197 N
+0.197 0.383 N
+0.383 11.355 D
+11.355 13.549 D/5
+13.549 15.743 B:min7
+15.743 17.392 G
+17.392 20.143 D
+20.143 22.326 D/5
+22.326 24.520 B:min7
+24.520 26.169 G
+26.169 28.909 D
+28.909 31.103 D/5
+31.103 33.309 B:min7
+33.309 34.958 G
+34.958 37.674 D
+37.674 39.880 D/5
+39.880 42.063 B:min7
+42.063 43.700 G
+43.700 46.463 D
+46.463 48.634 D/5
+48.634 50.828 B:min7
+50.828 52.477 G
+52.477 55.240 D
+55.240 57.423 D/5
+57.423 59.617 B:min7
+59.617 61.254 G
+61.254 63.994 D
+63.994 66.177 D/5
+66.177 68.383 B:min7
+68.383 70.020 G
+70.020 72.783 D
+72.783 74.687 D/5
+74.687 76.870 B:min7
+76.870 78.785 G
+78.785 81.514 D
+81.514 83.720 D/5
+83.720 85.914 B:min7
+85.914 87.562 G
+87.562 90.314 D
+90.314 92.497 D/5
+92.497 94.691 B:min7
+94.691 96.340 G
+96.340 99.091 D
+99.091 101.262 D/5
+101.262 103.468 B:min7
+103.468 105.105 G
+105.105 107.833 D
+107.833 109.749 D/5
+109.749 111.955 B:min7
+111.955 113.569 G
+113.569 116.309 D
+116.309 116.843 G/5
+116.843 118.782 D/5
+118.782 120.953 B:min7
+120.953 122.601 G
+122.601 125.353 D
+125.353 126.456 A:7
+126.456 127.536 D/5
+127.536 129.741 B:min7
+129.741 131.390 G
+131.390 134.118 D
+134.118 136.313 D/5
+136.313 138.507 B:min7
+138.507 140.156 G
+140.156 142.884 D
+142.884 144.823 D/5
+144.823 147.006 B:min7
+147.006 148.654 G
+148.654 151.394 D
+151.394 151.940 D:maj6
+151.940 153.855 D/5
+153.855 156.050 B:min7
+156.050 157.698 G
+157.698 160.438 D
+160.438 162.644 D/5
+162.644 164.629 B:min
+164.629 167.021 G
+167.021 170.295 D
+170.295 171.386 A:7
+171.386 173.581 B:min
+173.581 175.775 G
+175.775 180.164 D
+180.164 182.370 B:min
+182.370 184.552 G:maj7
+184.552 188.929 D
+188.929 191.135 B:min7
+191.135 193.318 G
+193.318 196.627 D/5
+196.627 201.004 B:min7
+201.004 204.289 G
+204.289 215.261 D
+215.261 217.466 B:min7
+217.466 219.103 G
+219.103 231.724 D
+231.724 236.112 B:min7
+236.112 239.398 G
+239.398 250.392 D
+250.392 252.575 B:min
+252.575 254.769 G
+254.769 258.067 D/5
+258.067 262.455 B:min7
+262.455 265.752 G
+265.752 271.221 D
+271.221 272.335 G
+272.335 275.632 D/5
+275.632 279.998 B:min7
+279.998 283.295 G
+283.295 292.084 D
+292.084 300.373 N0.0 0.197 N
+0.197 300.373 Dbackward step
+
+Finding maximum probability path (part 14 of 26, beats 420 to 452)... 
+forward step
+backward step
+
+Finding maximum probability path (part 15 of 26, beats 453 to 483)... 
+forward step
+backward step
+
+Finding maximum probability path (part 16 of 26, beats 484 to 515)... 
+forward step
+backward step
+
+Finding maximum probability path (part 17 of 26, beats 516 to 548)... 
+forward step
+backward step
+
+Finding maximum probability path (part 18 of 26, beats 549 to 579)... 
+forward step
+backward step
+
+Finding maximum probability path (part 19 of 26, beats 580 to 608)... 
+forward step
+backward step
+
+Finding maximum probability path (part 20 of 26, beats 609 to 640)... 
+forward step
+backward step
+
+Finding maximum probability path (part 21 of 26, beats 641 to 672)... 
+forward step
+backward step
+
+Finding maximum probability path (part 22 of 26, beats 673 to 705)... 
+forward step
+backward step
+
+Finding maximum probability path (part 23 of 26, beats 706 to 740)... 
+forward step
+backward step
+
+Finding maximum probability path (part 24 of 26, beats 741 to 768)... 
+forward step
+backward step
+
+Finding maximum probability path (part 25 of 26, beats 769 to 800)... 
+forward step
+backward step
+
+Finding maximum probability path (part 26 of 26, beats 801 to 847)... 
+forward step
+backward step
+0.0 0.197 N
+0.197 0.383 N
+0.383 11.355 D
+11.355 13.549 D/5
+13.549 15.743 B:min7
+15.743 17.937 G
+17.937 20.143 D
+20.143 22.326 D/5
+22.326 24.520 B:min7
+24.520 26.169 G
+26.169 28.909 D
+28.909 31.103 D/5
+31.103 33.309 B:min7
+33.309 34.958 G
+34.958 37.953 D
+37.953 40.147 D/5
+40.147 42.330 B:min7
+42.330 43.979 G
+43.979 46.730 D
+46.730 48.913 D/5
+48.913 51.096 B:min7
+51.096 52.744 G
+52.744 54.683 D
+54.683 56.877 D/5
+56.877 59.060 B:min7
+59.060 61.800 G
+61.800 63.994 D
+63.994 66.177 D/5
+66.177 68.383 B:min7
+68.383 70.565 G
+70.565 72.783 D
+72.783 74.954 D/5
+74.954 77.148 B:min
+77.148 79.343 G:maj7
+79.343 81.514 D
+81.514 83.720 D/5
+83.720 85.914 B:min7
+85.914 88.120 G
+88.120 90.314 D
+90.314 92.497 D/5
+92.497 94.691 B:min7
+94.691 96.340 G
+96.340 99.091 D
+99.091 101.262 D/5
+101.262 103.468 B:min7
+103.468 105.639 G
+105.639 108.112 D
+108.112 110.306 D/5
+110.306 112.477 B:min7
+112.477 114.126 G
+114.126 116.576 D
+116.576 118.782 D/5
+118.782 120.953 B:min7
+120.953 122.601 G
+122.601 125.620 D
+125.620 127.814 D/5
+127.814 130.009 B:min7
+130.009 131.669 G
+131.669 134.118 D
+134.118 136.313 D/5
+136.313 138.507 B:min7
+138.507 140.156 G
+140.156 142.884 D
+142.884 145.101 D/5
+145.101 147.284 B:min7
+147.284 149.478 G
+149.478 151.940 D
+151.940 154.134 D/5
+154.134 156.317 B:min7
+156.317 157.977 G
+157.977 160.438 D
+160.438 162.644 D/5
+162.644 165.489 B:min7
+165.489 168.647 G
+168.647 169.192 D/5
+169.192 171.386 D
+171.386 173.581 B:min7
+173.581 175.775 G
+175.775 180.164 D
+180.164 182.370 B:min7
+182.370 184.552 G
+184.552 188.929 D
+188.929 191.135 B:min7
+191.135 193.318 G
+193.318 197.718 D
+197.718 199.912 B:min7
+199.912 202.095 G
+202.095 206.483 D
+206.483 208.689 B:min7
+208.689 210.872 G
+210.872 215.261 D
+215.261 217.466 B:min7
+217.466 219.661 G
+219.661 225.686 D
+225.686 230.075 D/5
+230.075 234.475 B:min7
+234.475 237.749 G
+237.749 244.889 D
+244.889 249.313 D/5
+249.313 253.678 B:min7
+253.678 256.975 G
+256.975 259.170 D/5
+259.170 261.364 B:min7
+261.364 263.558 G
+263.558 267.935 D
+267.935 270.129 B:min7
+270.129 272.335 G
+272.335 276.724 D
+276.724 278.906 B:min
+278.906 281.089 G
+281.089 283.295 D
+283.295 285.489 A:7
+285.489 287.672 G/3
+287.672 292.084 D
+292.084 300.373 N0.0 0.197 N
+0.197 300.373 D
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_logfiles/friends.wav.log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,56 @@
+CSVFeatureWriter::setParameters
+stdout -> 
+NOTE: Using default sample rate of 44100 for default transform
+NOTE: Loaded and initialised plugin for transform "vamp:matthiasm:nnls_chroma:bothchroma" with plugin step size 2048 and block size 16384 (adapter step and block size 16384)
+NOTE: PluginInputDomainAdapter timestamp adjustment is  0.000000000R
+Extracting features for: "/Users/matthias/Workspace/2010/Thesis-code/wav/friends.wav"
+
Retrieving audio data... Done
+Opened 2-channel file or URL "/Users/matthias/Workspace/2010/Thesis-code/wav/friends.wav"
+
Extracting and writing features... 1%
Extracting and writing features... 3%
Extracting and writing features... 5%
Extracting and writing features... 7%
Extracting and writing features... 8%
Extracting and writing features... 10%
Extracting and writing features... 12%
Extracting and writing features... 14%
Extracting and writing features... 15%
Extracting and writing features... 17%
Extracting and writing features... 19%
Extracting and writing features... 21%
Extracting and writing features... 22%
Extracting and writing features... 24%
Extracting and writing features... 26%
Extracting and writing features... 28%
Extracting and writing features... 30%
Extracting and writing features... 31%
Extracting and writing features... 33%
Extracting and writing features... 35%
Extracting and writing features... 37%
Extracting and writing features... 38%
Extracting and writing features... 40%
Extracting and writing features... 42%
Extracting and writing features... 44%
Extracting and writing features... 45%
Extracting and writing features... 47%
Extracting and writing features... 49%
Extracting and writing features... 51%
Extracting and writing features... 52%
Extracting and writing features... 54%
Extracting and writing features... 56%
Extracting and writing features... 58%
Extracting and writing features... 59%
Extracting and writing features... 61%
Extracting and writing features... 63%
Extracting and writing features... 65%
Extracting and writing features... 66%
Extracting and writing features... 68%
Extracting and writing features... 70%
Extracting and writing features... 72%
Extracting and writing features... 73%
Extracting and writing features... 75%
Extracting and writing features... 77%
Extracting and writing features... 79%
Extracting and writing features... 81%
Extracting and writing features... 82%
Extracting and writing features... 84%
Extracting and writing features... 86%
Extracting and writing features... 88%
Extracting and writing features... 89%
Extracting and writing features... 91%
Extracting and writing features... 93%
Extracting and writing features... 95%
Extracting and writing features... 96%
Extracting and writing features... 98%[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... done.
+[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... done.
+[NNLS Chroma Plugin] Chord Estimation ... done.
+
Extracting and writing features... Done
+
+
+                              < M A T L A B >
+                  Copyright 1984-2007 The MathWorks, Inc.
+                         Version 7.5.0.338 (R2007b)
+                               August 9, 2007
+
+ 
+  To get started, type one of these: helpwin, helpdesk, or demo.
+  For product information, visit www.mathworks.com.
+ 
+   - First Slice
+    metpos 
+    key 
+    chord 
+    bass 
+   - Second Slice
+    (7) metpos (slice 2) 
+    (8) key (slice 2) 
+    (9) chord (slice 2) 
+    (10) bass (slice 2) 
+onset detection function
+beats
+
+
Length: 28
Length: 32
Length: 36
Length: 40
Length: 44
Length: 48
Length: 52
Length: 56
Length: 60
Length: 64
Length: 68
Length: 72
Length: 76
Length: 80
Length: 84
Length: 88
Length: 92
Length: 96
Length: 100
Length: 104
Length: 108
Length: 112
Length: 116
Length: 120
Length: 124
Length: 128
+Finding maximum probability path (part 1 of 1, beats 1 to 53)... 
+forward step
+backward step
+0.0 0.023 N
+0.023 0.418 A:min
+0.418 3.622 D
+3.622 5.224 C
+5.224 6.815 C#:min
+6.815 8.429 G
+8.429 10.031 E:min7
+10.031 11.622 D
+11.622 13.224 D#:min
+13.224 14.814 E:min
+14.814 16.417 Eb
+16.417 18.019 G/5
+18.019 19.621 A/3
+19.621 20.863 C
+20.863 21.119 N0.0 0.023 N
+0.023 21.119 D
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_logfiles/show.wav.log	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,348 @@
+CSVFeatureWriter::setParameters
+stdout -> 
+NOTE: Using default sample rate of 44100 for default transform
+NOTE: Loaded and initialised plugin for transform "vamp:matthiasm:nnls_chroma:bothchroma" with plugin step size 2048 and block size 16384 (adapter step and block size 16384)
+NOTE: PluginInputDomainAdapter timestamp adjustment is  0.000000000R
+Extracting features for: "testdata/show.wav"
+
Retrieving audio data... Done
+Opened 1-channel file or URL "testdata/show.wav"
+timestamp  0.000000000R: very low magnitude, setting magnitude to all zeros
+timestamp  0.046439909R: very low magnitude, setting magnitude to all zeros
+timestamp  0.092879818R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 1%
Extracting and writing features... 2%
Extracting and writing features... 3%
Extracting and writing features... 4%
Extracting and writing features... 5%
Extracting and writing features... 6%
Extracting and writing features... 7%
Extracting and writing features... 8%
Extracting and writing features... 9%
Extracting and writing features... 10%
Extracting and writing features... 11%
Extracting and writing features... 12%
Extracting and writing features... 13%
Extracting and writing features... 14%
Extracting and writing features... 15%
Extracting and writing features... 16%
Extracting and writing features... 17%
Extracting and writing features... 18%
Extracting and writing features... 19%
Extracting and writing features... 20%
Extracting and writing features... 21%
Extracting and writing features... 22%
Extracting and writing features... 23%
Extracting and writing features... 24%
Extracting and writing features... 25%
Extracting and writing features... 26%
Extracting and writing features... 27%
Extracting and writing features... 28%
Extracting and writing features... 29%
Extracting and writing features... 30%
Extracting and writing features... 31%
Extracting and writing features... 32%
Extracting and writing features... 33%
Extracting and writing features... 34%
Extracting and writing features... 35%
Extracting and writing features... 36%
Extracting and writing features... 37%
Extracting and writing features... 38%
Extracting and writing features... 39%
Extracting and writing features... 40%
Extracting and writing features... 41%
Extracting and writing features... 42%
Extracting and writing features... 43%
Extracting and writing features... 44%
Extracting and writing features... 45%
Extracting and writing features... 46%
Extracting and writing features... 47%
Extracting and writing features... 48%
Extracting and writing features... 49%
Extracting and writing features... 50%
Extracting and writing features... 51%
Extracting and writing features... 52%
Extracting and writing features... 53%
Extracting and writing features... 54%
Extracting and writing features... 55%
Extracting and writing features... 56%
Extracting and writing features... 57%
Extracting and writing features... 58%
Extracting and writing features... 59%
Extracting and writing features... 60%
Extracting and writing features... 61%
Extracting and writing features... 62%
Extracting and writing features... 63%
Extracting and writing features... 64%
Extracting and writing features... 65%
Extracting and writing features... 66%
Extracting and writing features... 67%
Extracting and writing features... 68%
Extracting and writing features... 69%
Extracting and writing features... 70%
Extracting and writing features... 71%
Extracting and writing features... 72%
Extracting and writing features... 73%
Extracting and writing features... 74%
Extracting and writing features... 75%
Extracting and writing features... 76%
Extracting and writing features... 77%
Extracting and writing features... 78%
Extracting and writing features... 79%
Extracting and writing features... 80%
Extracting and writing features... 81%
Extracting and writing features... 82%
Extracting and writing features... 83%
Extracting and writing features... 84%
Extracting and writing features... 85%
Extracting and writing features... 86%
Extracting and writing features... 87%
Extracting and writing features... 88%
Extracting and writing features... 89%
Extracting and writing features... 90%
Extracting and writing features... 91%
Extracting and writing features... 92%
Extracting and writing features... 93%timestamp  246.688798185R: very low magnitude, setting magnitude to all zeros
+timestamp  247.431836734R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 94%timestamp  248.081995464R: very low magnitude, setting magnitude to all zeros
+timestamp  248.128435374R: very low magnitude, setting magnitude to all zeros
+timestamp  248.174875283R: very low magnitude, setting magnitude to all zeros
+timestamp  248.732154195R: very low magnitude, setting magnitude to all zeros
+timestamp  248.778594104R: very low magnitude, setting magnitude to all zeros
+timestamp  248.825034013R: very low magnitude, setting magnitude to all zeros
+timestamp  248.871473922R: very low magnitude, setting magnitude to all zeros
+timestamp  248.917913832R: very low magnitude, setting magnitude to all zeros
+timestamp  248.964353741R: very low magnitude, setting magnitude to all zeros
+timestamp  249.010793650R: very low magnitude, setting magnitude to all zeros
+timestamp  249.057233560R: very low magnitude, setting magnitude to all zeros
+timestamp  249.103673469R: very low magnitude, setting magnitude to all zeros
+timestamp  249.150113378R: very low magnitude, setting magnitude to all zeros
+timestamp  249.196553287R: very low magnitude, setting magnitude to all zeros
+timestamp  249.242993197R: very low magnitude, setting magnitude to all zeros
+timestamp  249.289433106R: very low magnitude, setting magnitude to all zeros
+timestamp  249.335873015R: very low magnitude, setting magnitude to all zeros
+timestamp  249.382312925R: very low magnitude, setting magnitude to all zeros
+timestamp  249.428752834R: very low magnitude, setting magnitude to all zeros
+timestamp  249.475192743R: very low magnitude, setting magnitude to all zeros
+timestamp  249.521632653R: very low magnitude, setting magnitude to all zeros
+timestamp  249.568072562R: very low magnitude, setting magnitude to all zeros
+timestamp  249.614512471R: very low magnitude, setting magnitude to all zeros
+timestamp  249.846712018R: very low magnitude, setting magnitude to all zeros
+timestamp  249.893151927R: very low magnitude, setting magnitude to all zeros
+timestamp  249.939591836R: very low magnitude, setting magnitude to all zeros
+timestamp  249.986031746R: very low magnitude, setting magnitude to all zeros
+timestamp  250.032471655R: very low magnitude, setting magnitude to all zeros
+timestamp  250.078911564R: very low magnitude, setting magnitude to all zeros
+timestamp  250.125351473R: very low magnitude, setting magnitude to all zeros
+timestamp  250.171791383R: very low magnitude, setting magnitude to all zeros
+timestamp  250.218231292R: very low magnitude, setting magnitude to all zeros
+timestamp  250.264671201R: very low magnitude, setting magnitude to all zeros
+timestamp  250.311111111R: very low magnitude, setting magnitude to all zeros
+timestamp  250.357551020R: very low magnitude, setting magnitude to all zeros
+timestamp  250.403990929R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 95%timestamp  250.450430839R: very low magnitude, setting magnitude to all zeros
+timestamp  250.496870748R: very low magnitude, setting magnitude to all zeros
+timestamp  250.543310657R: very low magnitude, setting magnitude to all zeros
+timestamp  250.589750566R: very low magnitude, setting magnitude to all zeros
+timestamp  250.636190476R: very low magnitude, setting magnitude to all zeros
+timestamp  250.682630385R: very low magnitude, setting magnitude to all zeros
+timestamp  250.729070294R: very low magnitude, setting magnitude to all zeros
+timestamp  250.775510204R: very low magnitude, setting magnitude to all zeros
+timestamp  250.821950113R: very low magnitude, setting magnitude to all zeros
+timestamp  250.868390022R: very low magnitude, setting magnitude to all zeros
+timestamp  250.914829931R: very low magnitude, setting magnitude to all zeros
+timestamp  250.961269841R: very low magnitude, setting magnitude to all zeros
+timestamp  251.007709750R: very low magnitude, setting magnitude to all zeros
+timestamp  251.054149659R: very low magnitude, setting magnitude to all zeros
+timestamp  251.100589569R: very low magnitude, setting magnitude to all zeros
+timestamp  251.147029478R: very low magnitude, setting magnitude to all zeros
+timestamp  251.193469387R: very low magnitude, setting magnitude to all zeros
+timestamp  251.239909297R: very low magnitude, setting magnitude to all zeros
+timestamp  251.286349206R: very low magnitude, setting magnitude to all zeros
+timestamp  251.332789115R: very low magnitude, setting magnitude to all zeros
+timestamp  251.379229024R: very low magnitude, setting magnitude to all zeros
+timestamp  251.425668934R: very low magnitude, setting magnitude to all zeros
+timestamp  251.472108843R: very low magnitude, setting magnitude to all zeros
+timestamp  251.518548752R: very low magnitude, setting magnitude to all zeros
+timestamp  251.564988662R: very low magnitude, setting magnitude to all zeros
+timestamp  251.611428571R: very low magnitude, setting magnitude to all zeros
+timestamp  251.657868480R: very low magnitude, setting magnitude to all zeros
+timestamp  251.704308390R: very low magnitude, setting magnitude to all zeros
+timestamp  251.750748299R: very low magnitude, setting magnitude to all zeros
+timestamp  251.797188208R: very low magnitude, setting magnitude to all zeros
+timestamp  251.843628117R: very low magnitude, setting magnitude to all zeros
+timestamp  251.890068027R: very low magnitude, setting magnitude to all zeros
+timestamp  251.936507936R: very low magnitude, setting magnitude to all zeros
+timestamp  251.982947845R: very low magnitude, setting magnitude to all zeros
+timestamp  252.029387755R: very low magnitude, setting magnitude to all zeros
+timestamp  252.075827664R: very low magnitude, setting magnitude to all zeros
+timestamp  252.122267573R: very low magnitude, setting magnitude to all zeros
+timestamp  252.168707482R: very low magnitude, setting magnitude to all zeros
+timestamp  252.215147392R: very low magnitude, setting magnitude to all zeros
+timestamp  252.261587301R: very low magnitude, setting magnitude to all zeros
+timestamp  252.308027210R: very low magnitude, setting magnitude to all zeros
+timestamp  252.354467120R: very low magnitude, setting magnitude to all zeros
+timestamp  252.400907029R: very low magnitude, setting magnitude to all zeros
+timestamp  252.447346938R: very low magnitude, setting magnitude to all zeros
+timestamp  252.493786848R: very low magnitude, setting magnitude to all zeros
+timestamp  252.540226757R: very low magnitude, setting magnitude to all zeros
+timestamp  252.586666666R: very low magnitude, setting magnitude to all zeros
+timestamp  252.633106575R: very low magnitude, setting magnitude to all zeros
+timestamp  252.679546485R: very low magnitude, setting magnitude to all zeros
+timestamp  252.725986394R: very low magnitude, setting magnitude to all zeros
+timestamp  252.772426303R: very low magnitude, setting magnitude to all zeros
+timestamp  252.818866213R: very low magnitude, setting magnitude to all zeros
+timestamp  252.865306122R: very low magnitude, setting magnitude to all zeros
+timestamp  252.911746031R: very low magnitude, setting magnitude to all zeros
+timestamp  252.958185941R: very low magnitude, setting magnitude to all zeros
+timestamp  253.004625850R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 96%timestamp  253.051065759R: very low magnitude, setting magnitude to all zeros
+timestamp  253.097505668R: very low magnitude, setting magnitude to all zeros
+timestamp  253.143945578R: very low magnitude, setting magnitude to all zeros
+timestamp  253.190385487R: very low magnitude, setting magnitude to all zeros
+timestamp  253.236825396R: very low magnitude, setting magnitude to all zeros
+timestamp  253.283265306R: very low magnitude, setting magnitude to all zeros
+timestamp  253.329705215R: very low magnitude, setting magnitude to all zeros
+timestamp  253.376145124R: very low magnitude, setting magnitude to all zeros
+timestamp  253.422585034R: very low magnitude, setting magnitude to all zeros
+timestamp  253.469024943R: very low magnitude, setting magnitude to all zeros
+timestamp  253.515464852R: very low magnitude, setting magnitude to all zeros
+timestamp  253.561904761R: very low magnitude, setting magnitude to all zeros
+timestamp  253.608344671R: very low magnitude, setting magnitude to all zeros
+timestamp  253.654784580R: very low magnitude, setting magnitude to all zeros
+timestamp  253.701224489R: very low magnitude, setting magnitude to all zeros
+timestamp  253.747664399R: very low magnitude, setting magnitude to all zeros
+timestamp  253.794104308R: very low magnitude, setting magnitude to all zeros
+timestamp  253.840544217R: very low magnitude, setting magnitude to all zeros
+timestamp  253.886984126R: very low magnitude, setting magnitude to all zeros
+timestamp  253.933424036R: very low magnitude, setting magnitude to all zeros
+timestamp  253.979863945R: very low magnitude, setting magnitude to all zeros
+timestamp  254.026303854R: very low magnitude, setting magnitude to all zeros
+timestamp  254.072743764R: very low magnitude, setting magnitude to all zeros
+timestamp  254.119183673R: very low magnitude, setting magnitude to all zeros
+timestamp  254.165623582R: very low magnitude, setting magnitude to all zeros
+timestamp  254.212063492R: very low magnitude, setting magnitude to all zeros
+timestamp  254.258503401R: very low magnitude, setting magnitude to all zeros
+timestamp  254.304943310R: very low magnitude, setting magnitude to all zeros
+timestamp  254.351383219R: very low magnitude, setting magnitude to all zeros
+timestamp  254.397823129R: very low magnitude, setting magnitude to all zeros
+timestamp  254.444263038R: very low magnitude, setting magnitude to all zeros
+timestamp  254.490702947R: very low magnitude, setting magnitude to all zeros
+timestamp  254.537142857R: very low magnitude, setting magnitude to all zeros
+timestamp  254.583582766R: very low magnitude, setting magnitude to all zeros
+timestamp  254.630022675R: very low magnitude, setting magnitude to all zeros
+timestamp  254.676462585R: very low magnitude, setting magnitude to all zeros
+timestamp  254.722902494R: very low magnitude, setting magnitude to all zeros
+timestamp  254.769342403R: very low magnitude, setting magnitude to all zeros
+timestamp  254.815782312R: very low magnitude, setting magnitude to all zeros
+timestamp  254.862222222R: very low magnitude, setting magnitude to all zeros
+timestamp  254.908662131R: very low magnitude, setting magnitude to all zeros
+timestamp  254.955102040R: very low magnitude, setting magnitude to all zeros
+timestamp  255.001541950R: very low magnitude, setting magnitude to all zeros
+timestamp  255.047981859R: very low magnitude, setting magnitude to all zeros
+timestamp  255.094421768R: very low magnitude, setting magnitude to all zeros
+timestamp  255.140861678R: very low magnitude, setting magnitude to all zeros
+timestamp  255.187301587R: very low magnitude, setting magnitude to all zeros
+timestamp  255.233741496R: very low magnitude, setting magnitude to all zeros
+timestamp  255.280181405R: very low magnitude, setting magnitude to all zeros
+timestamp  255.326621315R: very low magnitude, setting magnitude to all zeros
+timestamp  255.373061224R: very low magnitude, setting magnitude to all zeros
+timestamp  255.419501133R: very low magnitude, setting magnitude to all zeros
+timestamp  255.465941043R: very low magnitude, setting magnitude to all zeros
+timestamp  255.512380952R: very low magnitude, setting magnitude to all zeros
+timestamp  255.558820861R: very low magnitude, setting magnitude to all zeros
+timestamp  255.605260770R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 97%timestamp  255.651700680R: very low magnitude, setting magnitude to all zeros
+timestamp  255.698140589R: very low magnitude, setting magnitude to all zeros
+timestamp  255.744580498R: very low magnitude, setting magnitude to all zeros
+timestamp  255.791020408R: very low magnitude, setting magnitude to all zeros
+timestamp  255.837460317R: very low magnitude, setting magnitude to all zeros
+timestamp  255.883900226R: very low magnitude, setting magnitude to all zeros
+timestamp  255.930340136R: very low magnitude, setting magnitude to all zeros
+timestamp  255.976780045R: very low magnitude, setting magnitude to all zeros
+timestamp  256.023219954R: very low magnitude, setting magnitude to all zeros
+timestamp  256.069659863R: very low magnitude, setting magnitude to all zeros
+timestamp  256.116099773R: very low magnitude, setting magnitude to all zeros
+timestamp  256.162539682R: very low magnitude, setting magnitude to all zeros
+timestamp  256.208979591R: very low magnitude, setting magnitude to all zeros
+timestamp  256.255419501R: very low magnitude, setting magnitude to all zeros
+timestamp  256.301859410R: very low magnitude, setting magnitude to all zeros
+timestamp  256.348299319R: very low magnitude, setting magnitude to all zeros
+timestamp  256.394739229R: very low magnitude, setting magnitude to all zeros
+timestamp  256.441179138R: very low magnitude, setting magnitude to all zeros
+timestamp  256.487619047R: very low magnitude, setting magnitude to all zeros
+timestamp  256.534058956R: very low magnitude, setting magnitude to all zeros
+timestamp  256.580498866R: very low magnitude, setting magnitude to all zeros
+timestamp  256.626938775R: very low magnitude, setting magnitude to all zeros
+timestamp  256.673378684R: very low magnitude, setting magnitude to all zeros
+timestamp  256.719818594R: very low magnitude, setting magnitude to all zeros
+timestamp  256.766258503R: very low magnitude, setting magnitude to all zeros
+timestamp  256.812698412R: very low magnitude, setting magnitude to all zeros
+timestamp  256.859138321R: very low magnitude, setting magnitude to all zeros
+timestamp  256.905578231R: very low magnitude, setting magnitude to all zeros
+timestamp  256.952018140R: very low magnitude, setting magnitude to all zeros
+timestamp  256.998458049R: very low magnitude, setting magnitude to all zeros
+timestamp  257.044897959R: very low magnitude, setting magnitude to all zeros
+timestamp  257.091337868R: very low magnitude, setting magnitude to all zeros
+timestamp  257.137777777R: very low magnitude, setting magnitude to all zeros
+timestamp  257.184217687R: very low magnitude, setting magnitude to all zeros
+timestamp  257.230657596R: very low magnitude, setting magnitude to all zeros
+timestamp  257.277097505R: very low magnitude, setting magnitude to all zeros
+timestamp  257.323537414R: very low magnitude, setting magnitude to all zeros
+timestamp  257.369977324R: very low magnitude, setting magnitude to all zeros
+timestamp  257.416417233R: very low magnitude, setting magnitude to all zeros
+timestamp  257.462857142R: very low magnitude, setting magnitude to all zeros
+timestamp  257.509297052R: very low magnitude, setting magnitude to all zeros
+timestamp  257.555736961R: very low magnitude, setting magnitude to all zeros
+timestamp  257.602176870R: very low magnitude, setting magnitude to all zeros
+timestamp  257.648616780R: very low magnitude, setting magnitude to all zeros
+timestamp  257.695056689R: very low magnitude, setting magnitude to all zeros
+timestamp  257.741496598R: very low magnitude, setting magnitude to all zeros
+timestamp  257.787936507R: very low magnitude, setting magnitude to all zeros
+timestamp  257.834376417R: very low magnitude, setting magnitude to all zeros
+timestamp  257.880816326R: very low magnitude, setting magnitude to all zeros
+timestamp  257.927256235R: very low magnitude, setting magnitude to all zeros
+timestamp  257.973696145R: very low magnitude, setting magnitude to all zeros
+timestamp  258.020136054R: very low magnitude, setting magnitude to all zeros
+timestamp  258.066575963R: very low magnitude, setting magnitude to all zeros
+timestamp  258.113015873R: very low magnitude, setting magnitude to all zeros
+timestamp  258.159455782R: very low magnitude, setting magnitude to all zeros
+timestamp  258.205895691R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 98%timestamp  258.252335600R: very low magnitude, setting magnitude to all zeros
+timestamp  258.298775510R: very low magnitude, setting magnitude to all zeros
+timestamp  258.345215419R: very low magnitude, setting magnitude to all zeros
+timestamp  258.391655328R: very low magnitude, setting magnitude to all zeros
+timestamp  258.438095238R: very low magnitude, setting magnitude to all zeros
+timestamp  258.484535147R: very low magnitude, setting magnitude to all zeros
+timestamp  258.530975056R: very low magnitude, setting magnitude to all zeros
+timestamp  258.577414965R: very low magnitude, setting magnitude to all zeros
+timestamp  258.623854875R: very low magnitude, setting magnitude to all zeros
+timestamp  258.670294784R: very low magnitude, setting magnitude to all zeros
+timestamp  258.716734693R: very low magnitude, setting magnitude to all zeros
+timestamp  258.763174603R: very low magnitude, setting magnitude to all zeros
+timestamp  258.809614512R: very low magnitude, setting magnitude to all zeros
+timestamp  258.856054421R: very low magnitude, setting magnitude to all zeros
+timestamp  258.902494331R: very low magnitude, setting magnitude to all zeros
+timestamp  258.948934240R: very low magnitude, setting magnitude to all zeros
+timestamp  258.995374149R: very low magnitude, setting magnitude to all zeros
+timestamp  259.041814058R: very low magnitude, setting magnitude to all zeros
+timestamp  259.088253968R: very low magnitude, setting magnitude to all zeros
+timestamp  259.134693877R: very low magnitude, setting magnitude to all zeros
+timestamp  259.181133786R: very low magnitude, setting magnitude to all zeros
+timestamp  259.227573696R: very low magnitude, setting magnitude to all zeros
+timestamp  259.274013605R: very low magnitude, setting magnitude to all zeros
+timestamp  259.320453514R: very low magnitude, setting magnitude to all zeros
+timestamp  259.366893424R: very low magnitude, setting magnitude to all zeros
+timestamp  259.413333333R: very low magnitude, setting magnitude to all zeros
+timestamp  259.459773242R: very low magnitude, setting magnitude to all zeros
+timestamp  259.506213151R: very low magnitude, setting magnitude to all zeros
+timestamp  259.552653061R: very low magnitude, setting magnitude to all zeros
+timestamp  259.599092970R: very low magnitude, setting magnitude to all zeros
+timestamp  259.645532879R: very low magnitude, setting magnitude to all zeros
+timestamp  259.691972789R: very low magnitude, setting magnitude to all zeros
+timestamp  259.738412698R: very low magnitude, setting magnitude to all zeros
+timestamp  259.784852607R: very low magnitude, setting magnitude to all zeros
+timestamp  259.831292517R: very low magnitude, setting magnitude to all zeros
+timestamp  259.877732426R: very low magnitude, setting magnitude to all zeros
+timestamp  259.924172335R: very low magnitude, setting magnitude to all zeros
+timestamp  259.970612244R: very low magnitude, setting magnitude to all zeros
+timestamp  260.017052154R: very low magnitude, setting magnitude to all zeros
+timestamp  260.063492063R: very low magnitude, setting magnitude to all zeros
+timestamp  260.109931972R: very low magnitude, setting magnitude to all zeros
+timestamp  260.156371882R: very low magnitude, setting magnitude to all zeros
+timestamp  260.202811791R: very low magnitude, setting magnitude to all zeros
+timestamp  260.249251700R: very low magnitude, setting magnitude to all zeros
+timestamp  260.295691609R: very low magnitude, setting magnitude to all zeros
+timestamp  260.342131519R: very low magnitude, setting magnitude to all zeros
+timestamp  260.388571428R: very low magnitude, setting magnitude to all zeros
+timestamp  260.435011337R: very low magnitude, setting magnitude to all zeros
+timestamp  260.481451247R: very low magnitude, setting magnitude to all zeros
+timestamp  260.527891156R: very low magnitude, setting magnitude to all zeros
+timestamp  260.574331065R: very low magnitude, setting magnitude to all zeros
+timestamp  260.620770975R: very low magnitude, setting magnitude to all zeros
+timestamp  260.667210884R: very low magnitude, setting magnitude to all zeros
+timestamp  260.713650793R: very low magnitude, setting magnitude to all zeros
+timestamp  260.760090702R: very low magnitude, setting magnitude to all zeros
+timestamp  260.806530612R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 99%timestamp  260.852970521R: very low magnitude, setting magnitude to all zeros
+timestamp  260.899410430R: very low magnitude, setting magnitude to all zeros
+timestamp  260.945850340R: very low magnitude, setting magnitude to all zeros
+timestamp  260.992290249R: very low magnitude, setting magnitude to all zeros
+timestamp  261.038730158R: very low magnitude, setting magnitude to all zeros
+timestamp  261.085170068R: very low magnitude, setting magnitude to all zeros
+timestamp  261.131609977R: very low magnitude, setting magnitude to all zeros
+timestamp  261.178049886R: very low magnitude, setting magnitude to all zeros
+timestamp  261.224489795R: very low magnitude, setting magnitude to all zeros
+timestamp  261.270929705R: very low magnitude, setting magnitude to all zeros
+timestamp  261.317369614R: very low magnitude, setting magnitude to all zeros
+timestamp  261.363809523R: very low magnitude, setting magnitude to all zeros
+timestamp  261.410249433R: very low magnitude, setting magnitude to all zeros
+timestamp  261.456689342R: very low magnitude, setting magnitude to all zeros
+timestamp  261.503129251R: very low magnitude, setting magnitude to all zeros
+timestamp  261.549569160R: very low magnitude, setting magnitude to all zeros
+timestamp  261.596009070R: very low magnitude, setting magnitude to all zeros
+timestamp  261.642448979R: very low magnitude, setting magnitude to all zeros
+timestamp  261.688888888R: very low magnitude, setting magnitude to all zeros
+timestamp  261.735328798R: very low magnitude, setting magnitude to all zeros
+timestamp  261.781768707R: very low magnitude, setting magnitude to all zeros
+timestamp  261.828208616R: very low magnitude, setting magnitude to all zeros
+timestamp  261.874648526R: very low magnitude, setting magnitude to all zeros
+timestamp  261.921088435R: very low magnitude, setting magnitude to all zeros
+timestamp  261.967528344R: very low magnitude, setting magnitude to all zeros
+timestamp  262.013968253R: very low magnitude, setting magnitude to all zeros
+timestamp  262.060408163R: very low magnitude, setting magnitude to all zeros
+timestamp  262.106848072R: very low magnitude, setting magnitude to all zeros
+timestamp  262.153287981R: very low magnitude, setting magnitude to all zeros
+timestamp  262.199727891R: very low magnitude, setting magnitude to all zeros
+timestamp  262.246167800R: very low magnitude, setting magnitude to all zeros
+timestamp  262.292607709R: very low magnitude, setting magnitude to all zeros
+timestamp  262.339047619R: very low magnitude, setting magnitude to all zeros
+timestamp  262.385487528R: very low magnitude, setting magnitude to all zeros
+timestamp  262.431927437R: very low magnitude, setting magnitude to all zeros
+timestamp  262.478367346R: very low magnitude, setting magnitude to all zeros
+timestamp  262.524807256R: very low magnitude, setting magnitude to all zeros
+timestamp  262.571247165R: very low magnitude, setting magnitude to all zeros
+timestamp  262.617687074R: very low magnitude, setting magnitude to all zeros
+timestamp  262.664126984R: very low magnitude, setting magnitude to all zeros
+timestamp  262.710566893R: very low magnitude, setting magnitude to all zeros
+timestamp  262.757006802R: very low magnitude, setting magnitude to all zeros
+timestamp  262.803446712R: very low magnitude, setting magnitude to all zeros
+timestamp  262.849886621R: very low magnitude, setting magnitude to all zeros
+timestamp  262.896326530R: very low magnitude, setting magnitude to all zeros
+timestamp  262.942766439R: very low magnitude, setting magnitude to all zeros
+timestamp  262.989206349R: very low magnitude, setting magnitude to all zeros
+timestamp  263.035646258R: very low magnitude, setting magnitude to all zeros
+timestamp  263.082086167R: very low magnitude, setting magnitude to all zeros
+timestamp  263.128526077R: very low magnitude, setting magnitude to all zeros
+timestamp  263.174965986R: very low magnitude, setting magnitude to all zeros
+timestamp  263.221405895R: very low magnitude, setting magnitude to all zeros
+timestamp  263.267845804R: very low magnitude, setting magnitude to all zeros
+timestamp  263.314285714R: very low magnitude, setting magnitude to all zeros
+timestamp  263.360725623R: very low magnitude, setting magnitude to all zeros
+timestamp  263.407165532R: very low magnitude, setting magnitude to all zeros
+
Extracting and writing features... 100%timestamp  263.453605442R: very low magnitude, setting magnitude to all zeros
+[NNLS Chroma Plugin] Tuning Log-Frequency Spectrogram ... done.
+[NNLS Chroma Plugin] Performing NNLS and mapping to chroma ... done.
+[NNLS Chroma Plugin] Chord Estimation ... done.
+
Extracting and writing features... Done
+
+                            < M A T L A B (R) >
+                  Copyright 1984-2011 The MathWorks, Inc.
+                    R2011b (7.13.0.564) 64-bit (maci64)
+                              August 13, 2011
+
+ 
+To get started, type one of these: helpwin, helpdesk, or demo.
+For product information, visit www.mathworks.com.
+ 
+onset detection function
+beats
+
+
Length: 28
Length: 32
Length: 36
Length: 40
Length: 44
Length: 48
Length: 52
Length: 56
Length: 60
Length: 64
Length: 68
Length: 72
Length: 76
Length: 80
Length: 84
Length: 88
Length: 92
Length: 96
Length: 100
Length: 104
Length: 108
Length: 112
Length: 116
Length: 120
Length: 124
Length: 128
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/all-wcprops	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,107 @@
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svnroot/!svn/ver/7216/matlabtoolboxes/misc/featureextraction
+END
+chunkspectrogram_ISMIR2010.m
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/svnroot/!svn/ver/7216/matlabtoolboxes/misc/featureextraction/chunkspectrogram_ISMIR2010.m
+END
+basschroma13.m
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svnroot/!svn/ver/1421/matlabtoolboxes/misc/featureextraction/basschroma13.m
+END
+readaudiochunk.m
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/featureextraction/readaudiochunk.m
+END
+shadedplot.m
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/featureextraction/shadedplot.m
+END
+mmcq2hpcp.m
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/featureextraction/mmcq2hpcp.m
+END
+synchronisechroma.m~
+K 25
+svn:wc:ra_dav:version-url
+V 82
+/svnroot/!svn/ver/5903/matlabtoolboxes/misc/featureextraction/synchronisechroma.m~
+END
+myframefft.m~
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svnroot/!svn/ver/5883/matlabtoolboxes/misc/featureextraction/myframefft.m~
+END
+synchronisechroma.m
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/svnroot/!svn/ver/7216/matlabtoolboxes/misc/featureextraction/synchronisechroma.m
+END
+myframefft.m
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svnroot/!svn/ver/5883/matlabtoolboxes/misc/featureextraction/myframefft.m
+END
+chromamatthias.m
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/featureextraction/chromamatthias.m
+END
+beatchroma.m
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svnroot/!svn/ver/1421/matlabtoolboxes/misc/featureextraction/beatchroma.m
+END
+hpcp2chroma.m
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/featureextraction/hpcp2chroma.m
+END
+bigframefft.m
+K 25
+svn:wc:ra_dav:version-url
+V 75
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/featureextraction/bigframefft.m
+END
+mychroma.m~
+K 25
+svn:wc:ra_dav:version-url
+V 73
+/svnroot/!svn/ver/5883/matlabtoolboxes/misc/featureextraction/mychroma.m~
+END
+chunkspectrogram.m
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/svnroot/!svn/ver/7216/matlabtoolboxes/misc/featureextraction/chunkspectrogram.m
+END
+mychroma.m
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svnroot/!svn/ver/1456/matlabtoolboxes/misc/featureextraction/mychroma.m
+END
+chromagenerator.m
+K 25
+svn:wc:ra_dav:version-url
+V 79
+/svnroot/!svn/ver/5903/matlabtoolboxes/misc/featureextraction/chromagenerator.m
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,606 @@
+10
+
+dir
+7329
+https://parrot.dcs.qmul.ac.uk/svnroot/matlabtoolboxes/misc/featureextraction
+https://parrot.dcs.qmul.ac.uk/svnroot
+
+
+
+2010-03-18T15:36:32.961649Z
+7216
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+214cd2a9-030a-0410-b9a1-da4e402363b6
+
+chunkspectrogram_ISMIR2010.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+89293138f75a03b0346ce694a4e4705d
+2010-03-18T15:36:32.961649Z
+7216
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1055
+
+readaudiochunk.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+6fbf766050031cebb16eceb746d89d11
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+473
+
+basschroma13.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+d96b8625968bc9eeabf3c0520ed6ebc0
+2009-03-06T16:14:34.602437Z
+1421
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+157
+
+shadedplot.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+ddfcfef326e89837da17cdd32b8499ac
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2124
+
+mmcq2hpcp.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+0c1d93851b2bc5bbeb925d1a9878c8ba
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1125
+
+synchronisechroma.m~
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+c91b2ff658248b0b784ae66cc294db46
+2009-05-07T16:17:08.483462Z
+5903
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+463
+
+synchronisechroma.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+875e110c61fef598065a8b7f81107d98
+2010-03-18T15:36:32.961649Z
+7216
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+765
+
+myframefft.m~
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+86c231607c073aa1be71667c09c4c9e4
+2009-05-01T16:56:49.073671Z
+5883
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1287
+
+myframefft.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+b06c6bfc85fbe7ff537c442920821b92
+2009-05-01T16:56:49.073671Z
+5883
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1461
+
+chromamatthias.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+eaedef2354cf063123300bef2bd80c59
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5228
+
+beatchroma.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+9d77c0c014c5c2654cd614b3f666a845
+2009-03-06T16:14:34.602437Z
+1421
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+705
+
+hpcp2chroma.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+107d11dff0c8dce973b7efdc3870599a
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1558
+
+bigframefft.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+05546bac5869d08d5110e3e91b0eeae4
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1013
+
+mychroma.m~
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+0c5cebc9155999ddd1b0927803de3f3f
+2009-05-01T16:56:49.073671Z
+5883
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5666
+
+mychroma.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+5207db104c1e8caee4529631dfb964b0
+2009-04-06T10:13:34.612045Z
+1456
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5676
+
+chunkspectrogram.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+25be0d0e89228e9a6ec2a30d75a34181
+2010-03-18T15:36:32.961649Z
+7216
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1928
+
+chromagenerator.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+b8c5b05ddcf0da7f9ac7bada17c55ccf
+2009-05-07T16:17:08.483462Z
+5903
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7718
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/prop-base/chunkspectrogram_ISMIR2010.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/basschroma13.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function bc13 = basschroma13(bc)
+bc(isnan(sum(bc,2)),:) = 1;
+bc = qnormalise(bc,1,2);
+bc13 = [bc,(1./12./max(bc,[],2)).^2];
+bc13 = qnormalise(bc13, inf, 2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/beatchroma.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function bc = beatchroma(chromag, beats, frame_t)
+
+% assigning beats to frames
+nBeat = length(beats);
+nFrame = size(chromag, 2);
+beatassign = zeros(1,nFrame);
+iBeat = 1;
+
+for iFrame = 1:nFrame
+    if frame_t(iFrame) > beats(iBeat) && frame_t(iFrame) < beats(end)
+        iBeat = iBeat + 1;
+    end
+    beatassign(iFrame) = iBeat;
+end
+% averaging over frames belonging to one beat
+fprintf(1,'__ preprocessing chromagram... ___________________________________________\n');
+bc = zeros(nBeat,12);
+chromag(:,isnan(sum(chromag))) = 1;
+
+for iBeat = 1:nBeat
+    bc(iBeat,:) = median(chromag(:,beatassign == iBeat),2);
+    if ~any(isnan(bc(iBeat,:)))
+        bc(iBeat,:) = bc(iBeat,:)/max(bc(iBeat,:));
+    end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/bigframefft.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,61 @@
+
+% segment audio data into overlapping frames and take fft of each frame
+
+function [fftframes,info] = bigframefft(audiodata, info)
+
+fprintf(1,'framefft\n');
+    
+info.undertest = [info.undertest '\nfft'];
+
+% set window length
+win = info.windowlength;
+
+
+% Pad audio with zeros so that first analysis frame corresponds with first
+% audio sample
+
+pad = zeros((win/2),1);
+
+%audiodata = [pad; audiodata; pad];
+
+% find size of input
+ilength = length(audiodata);
+
+
+%pad audio data
+audiodata = [pad; audiodata; pad]; 
+
+% set hop size
+hop = fix(win.*info.overlap); 
+
+info.hopsize = hop;
+
+% set number of windows
+num_win = ceil((ilength+1)/hop);
+
+info.numberframes = num_win;
+
+start=1;
+
+fftframes = zeros(win,num_win);
+
+check = ceil(num_win/10);
+
+
+% do fft analysis for each window:
+for i = 1 : num_win;
+  
+    segment = audiodata(start:(start + win - 1));
+    
+    fftframes(:,i) = fft(segment, win)';
+  
+    start = start + hop;
+    
+    if mod(i,check)  == 0
+        fprintf(1,'.');
+    end
+    
+end;
+fprintf(1,'\n');
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/chromagenerator.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,212 @@
+function [chroma, t, salience, tuning, URIstring] = chromagenerator(filename, kammerton, nBin)
+
+%% make URI string
+URIstring = strcat('chromagenerator-', num2str(kammerton), '-',num2str(nBin));
+
+%% parameters
+% set the bins per semitone (i.e. binsperoctave/12)
+% kammerton = 440;
+% nBin = 7;
+midbin = ceil(nBin/2);
+
+% minimum and maximum MIDI bin, should be n octaves apart.
+midimin = 21; % 69 has 440 Hz
+% midimin = 45; % 69 has 440 Hz
+midimax = 92; 
+% midimax = 68; 
+noterange = midimax - midimin + 1;
+
+% midi note values including the fractions "between" actual MIDI notes
+midibins = midimin-(midbin-1)/nBin:(1/nBin):midimax+(midbin-1)/nBin;
+% the same in frequencies
+fbins = kammerton * 2.^((midibins-69)/12);
+nFbin = length(fbins);
+
+% the sampling frequency everything is (down)sampled to
+used_fs = 11025;
+
+% intuitive setting of how long the frame is (quite short here!)
+fracofsecond = 4; 
+
+hopspersecond = 20;
+
+% calculate a convenient FFT length
+nFFT = 2^nextpow2(used_fs/fracofsecond);
+% hopsize in samples
+hopsize = used_fs/hopspersecond/nFFT;
+
+% "instrument" means a particular spectral shape
+used_instruments = 1:2;
+nInstrument = length(used_instruments);
+
+%% generate dictionary
+% (complex) tones for all fundamental frequencies are generated. then their
+% amplitude spectrum is calculated and normalised according to the L2 norm.
+
+% preliminary t for dictionary generation
+t = (1:nFFT)/used_fs;
+% initialise note dictionary
+A = zeros(nFbin,nFFT/2,nInstrument);
+
+% loop over all instruments
+for iInstrument = used_instruments
+    % loop over all fundamental frequencies
+    for iFbin = 1:nFbin;
+        f0 = fbins(iFbin);
+        switch iInstrument
+            case 1
+                wave = sum([sin(t*2*pi*f0*1); ...
+                    0.9^1 * sin(t*2*pi*f0*2); ...
+                    0.9^2 * sin(t*2*pi*f0*3); ...
+                    0.9^3 * sin(t*2*pi*f0*4); ...
+                    ...0.9^4 * sin(t*2*pi*f0*5); ...
+                    ]);
+            case 2
+                wave = sin(t*2*pi*f0*1);
+        end
+        % window wave and fft
+        wave = hamming(nFFT)' .* wave;
+        fullfft = fft(wave);
+        % calculate amplitude spectrum from fft
+        A(iFbin,:,iInstrument) = abs(fullfft(1:round(nFFT/2)));
+    end
+    % normalise (L2 norm)
+    A(:,:,iInstrument) = qnormalise(A(:,:,iInstrument),2,2);
+end
+
+%% get the fft frames from a wave file
+%this is probably ending up not being used in a vamp plugin
+% fprintf(1,'%s\n',filename)
+% [audiosize,fs] = wavread(filename,'size');
+% chunk_sec = 20;
+% nChunk = ceil(audiosize(1)/fs/chunk_sec);
+% songframes = [];
+% start = 1;
+% % extract fft from chunks (for less memory consumption)
+% for iChunk = 1:nChunk
+%     samplemin = (iChunk-1) * chunk_sec * fs + 1;
+%     samplemax = min(audiosize(1), (iChunk * chunk_sec + 1) * fs);    
+%     audiodata0 = wavread(filename,[samplemin samplemax]);   
+%     audiodata = resample(mean(audiodata0,2),used_fs,fs,20);
+%     songframes0 = myframefft(audiodata,nFFT,hopsize,'hamming');
+%     if size(songframes0,2)>=start
+%         songframes = [songframes(:,1:end-start) abs(songframes0(1:round(nFFT/2),start:end))];
+%     end
+%     start = round(hopspersecond/2)+1;
+% end
+% clear songframes0
+% clear audiodata
+% clear audiodata0
+% t = (0:T-1)./hopspersecond;
+
+%%
+[songframes,f,t]=chunkspectrogram(filename,4096,4096*7/8,4096,inf);
+hopspersecond = 1/(t(2)-t(1));
+songframes = abs(songframes);
+%%
+T = size(songframes,2);
+
+fprintf(1, '%d different notes, %d frequency bins, %d time frames\n', noterange,nFFT/2, T)
+
+notespectrum0 = zeros(nFbin, T, nInstrument);
+songframes = qnormalise(songframes,2,1);
+songframes(isnan(songframes)) = 0;
+
+%% calculate cosine distance
+for iInstrument = 1:nInstrument
+    for iTone = 1:nFbin
+        notespectrum0(iTone,:,iInstrument) = A(iTone,:,iInstrument) * songframes;
+    end
+end
+%% get only the bins with "more than 1 st. deviation"
+notespectrum = zeros(size(notespectrum0));
+wind_size = 6 * nBin;
+wind = hamming(wind_size)/sum(hamming(wind_size));
+stdthresh = 1;
+for iInstrument = used_instruments
+    % calculate running mean
+    m = conv2(notespectrum0(:,:,iInstrument),wind(:),'same');
+    % calculate running standard deviation
+    stdev = sqrt(conv2((notespectrum0(:,:,iInstrument)-m).^2,wind(:),'same'));
+    % take only those tones that are above 1 standard deviation from the
+    % mean
+    notespectrum(:,:,iInstrument) = (notespectrum0(:,:,iInstrument)-m)./stdev;
+    temp = notespectrum(:,:,iInstrument);
+    temp(temp<stdthresh) = 0;
+    notespectrum(:,:,iInstrument) = temp;
+end
+% notes that are one were not "good enough" (not greater than 1 st.
+% deviation reater than the mean) and are hence set to 0.
+notespectrum(notespectrum<=stdthresh) = 0;
+% we require that the notes be on in *both* "instruments". hence the final
+% note spectrum note_s is their product, which works a bit like a minimum
+note_s =  notespectrum(:,:,1) .* notespectrum(:,:,2);
+
+note_s(1:nBin*6,:) = 0;
+note_s(isnan(note_s)) = 0;
+%% tuning
+% I wrap the note spectrum to one semitone, kind of generating the note
+% spectrum modulo one semitone. one gets a matrix of size nBin x T. from
+% that matrix, the tuning can be calculated by extracting the angle of the
+% sum of all columns, the sum of all columns being a nBin-dimensional
+% vector.
+th = tuner(note_s(36*nBin+(1:12*nBin),:), nBin)
+% th = tuner(notespectrum0(36*nBin+(1:12*nBin),:,2), nBin)
+tuning = kammerton*2^((th/2/pi)/12)
+% tune the spectrum by interpolating the bins such that now the middle bin
+% of every semitone corresponds to the right frequency in equal
+% temperament
+tuned_s = zeros(size(note_s));
+for iFrame = 1:T
+    tuned_s(:,iFrame) = interp1(1:nFbin, note_s(:,iFrame), (1:nFbin) + th / (2 * pi) * nBin,[],0);
+end
+
+%% reduce to 1 bin per semitone
+% just sum the nBin bins that correspond to one semitone.
+wrapped_tuned_s = reshape(tuned_s,[nBin,noterange*T]);
+% if you want to emphasize the middle bin, use a fancy window, otherwise
+% just use the rectangular window
+wei = rectwin(nBin)';
+salience.reduced = reshape(wei * wrapped_tuned_s,noterange,T);
+% median filter in time direction, if you like
+salience.reduced = medfilt1(salience.reduced,floor(hopspersecond/5)-1,[],2);
+
+%% make chromagram
+% actually the edge of the note spectrum is a bit noisy (due to the
+% convolution three parts above. that's why I start some bins from the
+% lower edge (i.e. midimin_used). maybe one could do this properly
+% sometime.
+midimin_used = midimin+6;
+% uebergang is where bass and treble chroma overlap equally
+uebergang = 50;
+
+% some simple linear functions to generate the treble and bass profiles
+leftfunc = zeros(2,noterange);
+rightfunc = zeros(2,noterange);
+leftfunc(1,:) = 2/12*((midimin:midimax)-midimin_used);
+leftfunc(2,:) = 1/12*((midimin:midimax)-uebergang) + 0.5;
+rightfunc(1,:) = -1/12*((midimin:midimax)-uebergang) + 0.5;
+rightfunc(2,:) = -(.5)/12*((midimin:midimax)-midimax);
+
+% initialise stuff
+salience.bass = zeros(size(salience.reduced));
+salience.treble = zeros(size(salience.reduced));
+profiles = zeros(noterange,3);
+
+% bass and treble profiles
+for i = 1:2
+   profiles(:,i) = max(0,min(1,min(leftfunc(i,:),rightfunc(i,:))))';
+end
+% wide profile (i.e. both bass and treble)
+profiles(:,3) = min(1,sum(profiles(:,1:2),2));
+
+% calculate specific saliences (windowed in f0 direction)
+salience.bass = salience.reduced .* profiles(:,ones(1,T));
+salience.treble = salience.reduced .* profiles(:,2 * ones(1,T));
+salience.wide = salience.reduced .* profiles(:,3 * ones(1,T));
+
+% calculate chromagrams
+chroma.bass = squeeze(max(reshape(salience.bass,[12,6,T]),[],2));
+chroma.treble = squeeze(max(reshape(salience.treble,[12,6,T]),[],2));
+chroma.wide = squeeze(max(reshape(salience.wide,[12,6,T]),[],2));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/chromamatthias.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,138 @@
+function [results, info] = chromamatthias(filename, prod, maxx)
+
+%---------------------------------------------------------------
+%   Part of the matthiasmISMIR08 project
+%   Written by Christopher Harte, modified by Matthias Mauch 
+%   @ Queen Mary, University of London
+%   2008
+%---------------------------------------------------------------
+
+
+% Set up info structure (initialise variables to 0 if we don't have values
+% now...
+
+info = {};
+%%
+info.filename = filename;
+% info.filename = '/Volumes/Music/Music/Beatles/12_-_Let_It_Be/wav/06_-_Let_It_Be.wav';
+% info.filename = '/Volumes/Music/Music/Beatles/unrevised/01wave/01_-_I_Saw_Her_Standing_There.wav';
+info.undertest = '';            % which algorithms are run
+
+% Signal Parameters:
+info.fs = 44100;                % Sampling freq of audio file
+info.downsample  = 4;           % downsampling factor
+info.fsdownsampled = ...
+    info.fs / info.downsample;   % fs after downsampling
+info.preprocessing = 'downsample'; % What kind of preprocessing?
+info.numberframes = 0;          % number of frames calculated
+info.windowlength = 0;          % window length in samples
+info.overlap = ...
+    1/8;                        % window overlap factor
+info.overl = ...
+    1 - info.overlap;
+info.hopsize = 0;               % window overlap in samples
+info.framespersecond = 0;       % effective frames per second
+
+% Constant Q parameters:
+info.binsperoctave = 36;        % bins per octave for const q
+info.fmax = 1760;              % top frequency for const q
+info.fmin = 110;                % bottom frequency for const q
+info.numcqbins = 0;             % number of bins in a Constant Q vector
+info.sparkernelfile = '';       % mat file containing sparse spectral kernels matrix 
+info.sparsethreshold =  0.0054; % sparsekernel threshold
+info.maxx = maxx;
+% Get constant Q parameters - need to do this first to set window length
+info = getcqparameters(info);
+
+% Prepare chunking
+info.chunkoverlap = 2 * 1/info.overlap;         % frames
+info.audiofilesize = wavread(info.filename,'size');
+info.chunksize =  500;          % frames
+info.samplechunksize = (info.chunksize - 1) * ...
+    info.hopsize * info.downsample; % chunk length in original samples
+info.samplechunkhopsize = (info.chunksize - 1 - info.chunkoverlap) * ...
+    info.hopsize * info.downsample;
+info.framespersecond = info.fsdownsampled/info.hopsize;
+%%
+nChunk = ceil(info.audiofilesize / info.samplechunkhopsize);
+results = {};
+iChunk = 0;
+for iChunk = 1:nChunk  
+%
+    info.startsample = (iChunk - 1) * info.samplechunkhopsize + 1;
+    info.endsample = min(...
+        info.startsample + info.samplechunksize -1, ...
+        info.audiofilesize(1));
+%
+    [audiodata, info] = readaudiochunk(info);
+
+    % Perform downsampling here if required
+
+    [audiodata, info] = preprocessing(audiodata,info);
+
+    % Perform FFT
+    [fftframes,info] = bigframefft(audiodata,info);
+
+    % Harmonics adjustment
+    if prod
+        [fftframes] = prodfft(fftframes, 3);
+    end
+
+
+    % Perform Constant Q
+    [constqframes, info] = constq(fftframes,info);
+    
+    % Smooth constqframes for transient removal (time direction)
+    constqframes = medfilt1(constqframes,round(info.framespersecond/2),[],2);
+
+    % 'Normalise' Constant Q
+    % constqframes = constqframes ./ repmat(sum(abs(constqframes),1),size(constqframes,1),1);
+
+    % fftframes = 10 * log10(abs(fftframes).^2);
+
+    % Calculate HPCP
+    [hpcpframes,info] = hpcp(constqframes,info);
+
+    % Peakpick HPCP
+    % [peakpickframes,info] = framepeakpick(hpcpframes,info);
+
+
+    % Calculate Tuning
+    % [tuningframes,info] = tuning(peakpickframes,info);
+
+    % Calculate slightly adjusted chromagram
+    [chromaframes, info] = tunebyshift(hpcpframes, info);
+    % figure,
+    % imagesc(info.t,[],(chromaframes')), axis xy
+
+    % put results in output structure
+    if iChunk == 1
+%         results.fftframes = fftframes;
+%         results.constqframes = constqframes;
+%         results.hpcpframes = hpcpframes;
+        results.chromaframes = chromaframes;
+    else
+%         results.fftframes = ...
+%             [results.fftframes(:,1:end-info.frameoverlap),...
+%              results.fftframes(:,end-info.frameoverlap+1:end) ...
+%              + fftframes(:,1:info.frameoverlap),...
+%              fftframes(:,info.frameoverlap+1:end)];
+%         results.constqframes = ...
+%             [results.constqframes(:,1:end-info.frameoverlap),...
+%              results.constqframes(:,end-info.frameoverlap+1:end) ...
+%              + constqframes(:,1:info.frameoverlap),...
+%              constqframes(:,info.frameoverlap+1:end)];
+%         results.hpcpframes = ...
+%             [results.hpcpframes(1:end-info.frameoverlap,:);...
+%              results.hpcpframes(end-info.frameoverlap+1:end,:) ...
+%              + hpcpframes(1:info.frameoverlap,:);...
+%              hpcpframes(info.frameoverlap+1:end,:)];
+        x = round(info.chunkoverlap/2);
+%         results.chromaframes = chromaframes;
+        results.chromaframes = ...
+            [results.chromaframes(1:end-info.chunkoverlap+x,:);...
+             chromaframes(2+x:end,:)];
+    end
+end
+info.numberframes = size(results.chromaframes,1);
+info.t = ((0:info.numberframes-1) * info.hopsize) / info.fsdownsampled;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/chunkspectrogram.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,70 @@
+function [s,f,t] = chunkspectrogram(filename,d_windo,d_nOverlap,d_nFFT, maxf)
+%%
+% d_ are the downsampled things
+% o_ are the original things
+
+
+d_fs = 11025;
+
+[temp, o_fs] = wavread(filename,'size');
+
+if mod(o_fs/d_fs,1) ~= 0
+    error('The sample frequency of the wave file has to be an integer multiple of %1.0f.',d_fs);
+end
+
+o_nSample = temp(1);
+d_nSample = floor(o_nSample*d_fs/o_fs);
+
+o_nOverlap = d_nOverlap * o_fs/d_fs;
+
+
+d_nSamplePerChunk = d_windo+200*(d_windo-d_nOverlap);
+
+if d_nSample < d_nSamplePerChunk
+    d_nSamplePerChunk = d_nSample;
+end
+
+d_endsample = d_nSamplePerChunk:d_nSamplePerChunk:d_nSample;
+
+o_startsample = [1, d_endsample * o_fs / d_fs + 1];
+o_endsample = d_endsample * o_fs / d_fs;
+o_endsample = min(o_endsample + o_fs / d_fs * d_nOverlap, o_nSample); % extend so that chunks overlap
+
+% in most cases the file length is not exactly a multiple of 
+if o_endsample(end) < o_nSample
+    o_endsample = [o_endsample o_nSample];
+end
+
+%%
+
+nChunk = length(o_startsample);
+
+for iChunk = 1:nChunk
+    fprintf(1,'_');
+end
+leftpad = zeros(d_windo/2,1);
+fprintf(1,'\n.')
+x = resample(mean(wavread(filename,[o_startsample(1) o_endsample(1)]),2),d_fs,o_fs);
+s = spectrogram([leftpad; x], d_windo,d_nOverlap,d_nFFT, d_fs);
+f = (0:d_nFFT/2-1)/d_nFFT*d_fs;
+if maxf < max(f)
+    maxbin = find(f>maxf,1)-1;
+else
+    maxbin = length(f);
+end
+s = s(1:maxbin,:);
+f = f(1:maxbin);
+for iChunk = 2:nChunk-1
+    fprintf(1,'.')
+    temps = spectrogram(resample(mean(wavread(filename,[o_startsample(iChunk) o_endsample(iChunk)]),2),d_fs,o_fs), ...
+        d_windo,d_nOverlap,d_nFFT, d_fs);
+    s = [s(1:maxbin,:),temps(1:maxbin,:)];
+end
+x = resample(mean(wavread(filename,[o_startsample(nChunk) o_nSample]),2),d_fs,o_fs);
+if length(x)>d_windo
+    temps = spectrogram(x, ...
+        d_windo,d_nOverlap,d_nFFT, d_fs);
+    s = [s(1:maxbin,:),temps(1:maxbin,:)];
+end
+fprintf(1,'.\n')
+t = (0:size(s,2)-1) * (d_windo-d_nOverlap)/d_fs;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/chunkspectrogram_ISMIR2010.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+function [s,f,t] = chunkspectrogram_ISMIR2010(filename,d_windo,d_nOverlap,d_nFFT, maxf)
+%%
+% d_ are the downsampled things
+% o_ are the original things
+
+
+d_fs = 11025;
+
+[filesize, o_fs] = wavread(filename,'size');
+
+
+
+if mod(o_fs/d_fs,1) ~= 0
+    error('The sample frequency of the wave file has to be an integer multiple of %1.0f.',d_fs);
+end
+downsample = o_fs/d_fs;
+
+o_windo = d_windo * downsample;
+o_nOverlap = d_nOverlap * downsample;
+o_hopSize = o_windo-o_nOverlap;
+nFrame = floor((filesize(1) - o_windo) / o_hopSize);
+
+s = zeros(d_nFFT/2, nFrame);
+f = (0:d_nFFT/2-1)/d_fs;
+t = zeros(nFrame,1);
+
+wind = hamming(d_windo);
+wind = wind/sum(wind);
+
+for iLine = 1:round(nFrame/200)
+    fprintf(1,'_');
+end
+fprintf(1,'\n');
+
+for iFrame = 1:nFrame
+    if mod(iFrame,200) == 0
+        fprintf(1,'.');
+    end
+    ind = [1,o_windo] + (iFrame-1) * (o_hopSize);
+    wave = sum(wavread(filename, ind),2) / 2;
+    temp = fft(resample(wave,d_fs,o_fs) .* wind);
+    s(:, iFrame) = temp(1:d_nFFT/2);
+    t(iFrame) = (ind(1) + ind(2)) / 2 / o_fs;
+end
+fprintf(1,'\n');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/hpcp2chroma.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,53 @@
+function [chromaframes, info] = hpcp2chroma(hpcpframes, info)
+
+% calculate the best shift 
+% (0 - none, 1 - one third of semitone down, 
+%  2 - two thirds of semitone down)
+
+bps = info.binsperoctave/12;
+
+indices = (0:11) * bps;
+
+
+%%%%% NANs! $%%%%%%%%%%%%
+% nanrows = isnan(sum(hpcpframes,2));
+% binweights = sum(hpcpframes(~nanrows,:));
+% condensedweights = zeros(bps,12);
+% for iBin = 1:bps
+%     condensedweights(iBin,1:12) = sum(binweights(indices+iBin)); 
+% end
+% % [maximum, maxind] = max(...
+% %     [sum(binweights(indices+1)),...
+% %      sum(binweights(indices+2)),...
+% %      sum(binweights(indices+3))]);
+% [maximum, maxind] = max(sum(condensedweights,2));
+% shiftposs = [1 0 -1];
+% shift = shiftposs(maxind);
+% if bps ==3
+%     hpcpframes = circshift(hpcpframes',shift)';
+%     info.tuning6th = shift;
+% end
+maxind = 1;
+
+% fprintf(1,['(max. energy at ' num2str(maxind) ', shift by ' num2str(shift) ')\n\n'])
+if (~info.maxx)
+    if bps == 3
+        chromaframes = ...
+            0 * hpcpframes(:,indices+1) + ...
+            1 * hpcpframes(:,indices+2) + ...
+            0 * hpcpframes(:,indices+3);
+    elseif bps == 2
+        chromaframes = ...
+            (1-shift)* hpcpframes(:,indices+1) + ...
+             shift* hpcpframes(:,indices+2);
+    elseif bps == 1
+        chromaframes = hpcpframes;
+    end
+else
+    chromaframes = zeros(size(hpcpframes,1),12);
+    for iChroma = 1:12
+        chromaframes(:,iChroma) = max(hpcpframes(:,indices(iChroma)+(1:3)),[],2);
+    end
+end
+
+chromaframes = chromaframes ./ repmat(sum(chromaframes,2),1,12);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/mmcq2hpcp.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,48 @@
+
+
+
+
+% CQ2HPCP Convert Constant Q spectrum to a HPCP
+%
+%   CQ2HPCP(cqframes, info)
+%
+%   cqframes = vector or matrix constant q spectrum / spectra
+%   info = info structure containing parameters
+%
+
+function [hpcpframes] = mmcq2hpcp(cqframes, info)
+
+%get cq parameters from info structure
+num_win = info.numberframes;
+
+cqbins = size(cqframes,1); 
+
+bpo = info.binsperoctave;
+
+% calculate the number of octaves we have in the spectrum
+num_oct = floor(cqbins/bpo)-1;
+
+hpcpframes(1:num_win, 1:bpo) = 0;   
+
+
+
+% for each window calculate chromagram
+for i = 1 : num_win
+    % add each octave of the spectrum into the chromagram
+    for oct = 0:num_oct;     
+        ind = oct*bpo;
+        
+        hpcpframes(i, 1:bpo) = hpcpframes(i, 1:bpo) + abs(cqframes(ind+1:ind+bpo,i))';   
+                
+    end;
+ 
+    % normalise
+%     hpcpframes(i,1:bpo) = hpcpframes(i,1:bpo)/max(hpcpframes(i,1:bpo));
+    meanc = mean(hpcpframes(i,1:bpo));
+    if meanc > 0.0000001
+        hpcpframes(i,1:bpo) = hpcpframes(i,1:bpo)/mean(hpcpframes(i,1:bpo)); %scale to be a distribution!
+    else
+        hpcpframes(i,1:bpo) = (bpo)^(-1);
+    end
+end;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/mychroma.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,170 @@
+function [chromagram,t,salience] = ...
+    mychroma(filename, nBins, fmin, used_fs, fracofsecond, calcu)
+
+if isempty(nBins)
+    nBins = 3;
+end
+midbin = ceil(nBins/2);
+if isempty(fmin)
+    fmin = 55 * 2^(-7/12-(midbin-1)/12/nBins);
+end
+
+if isempty(used_fs)
+    used_fs=round(44100/4);
+end
+
+hopspersecond = 20;
+nFFT = 2^nextpow2(used_fs/fracofsecond);
+hopsize = used_fs/hopspersecond/nFFT;
+noterange = 61;
+used_instruments = 1:2;
+nInstrument = length(used_instruments);
+
+%% load or generate dictionary
+dirc = what('./data');
+dicfilename = ['mydict-' num2str(nBins) '.mat'];
+if ~calcu && any(strcmp(dirc.mat, dicfilename))
+    load(['data/' dicfilename])
+else
+    % dictionary parameters
+    midbin = nBins/2 + .5;
+    %hopspersecond = 10;
+    secs = .8;
+    t = linspace(0,secs,secs*used_fs)';
+
+    % make note dictionary
+    A = zeros(noterange*nBins,nFFT/2,nInstrument);
+    for iInstrument = used_instruments
+        for iMidiNote = 1:noterange
+            for iBin = 1:nBins
+                f0 = fmin * 2^((iMidiNote-1)/12 + (iBin-1)/12/nBins);
+                %wave = zeros(size(t));
+                switch iInstrument
+                    case 1
+                        wave = sum([sin(t*2*pi*f0*1) ...
+                            0.6^1 * sin(t*2*pi*f0*2) ...
+                            0.6^2 * sin(t*2*pi*f0*3) ...
+                            0.6^3 * sin(t*2*pi*f0*4)],2);
+                    case 2
+                        wave = sin(t*2*pi*f0*1);
+                    case 3
+                        wave = sum([...
+                            0.6^1 * sin(t*2*pi*f0*1/2) ...
+                            0.6^2 * sin(t*2*pi*f0*1/3) ...
+                            0.6^3 * sin(t*2*pi*f0*1/4) ...
+                            0.6^4 * sin(t*2*pi*f0*1/5) ...
+                            0.6^5 * sin(t*2*pi*f0*1/6) ...                         
+                            0.6^6 * sin(t*2*pi*f0*1/7) ...
+                            0.6^7 * sin(t*2*pi*f0*1/8) ...                            
+                            0.6^8 * sin(t*2*pi*f0*1/9)],2);
+                end
+                fftframes0 = myframefft(wave,nFFT,hopsize,'hamming');
+                A(nBins*(iMidiNote-1)+iBin,:,iInstrument) = mean(abs(fftframes0(1:round(nFFT/2),:)),2);
+            end
+        end
+    end
+    save(['data/' dicfilename], 'A', 'nFFT', 'hopsize');
+end
+
+%% get the fft frames from a wave file
+fprintf(1,'%s\n',filename)
+[audiosize,fs] = wavread(filename,'size');
+chunk_sec = 20;
+nChunk = ceil(audiosize(1)/fs/chunk_sec);
+songframes = [];
+s = [];
+start = 1;
+
+for iChunk = 1:nChunk
+    samplemin = (iChunk-1) * chunk_sec * fs + 1;
+    samplemax = min(audiosize(1), (iChunk * chunk_sec + 1) * fs);
+    
+    audiodata0 = wavread(filename,[samplemin samplemax]);
+   
+    audiodata = resample(mean(audiodata0,2),used_fs,fs,20);
+   
+    songframes0 = myframefft(audiodata,nFFT,hopsize,'hamming');
+    
+    if size(songframes0,2)>=start
+        songframes = [songframes(:,1:end-start) abs(songframes0(1:round(nFFT/2),start:end))];
+    end
+    start = round(hopspersecond/2)+1;
+end
+clear songframes0
+clear audiodata
+clear audiodata0
+
+T = size(songframes,2);
+t = (0:T-1)./hopspersecond;
+fprintf(1, '%d different notes, %d frequency bins, %d time frames\n', noterange,nFFT/2, T)
+
+simpleS = zeros(noterange*nBins,T, nInstrument+1);
+songframes(isnan(songframes)) = 0;
+
+for iInstrument = 1:nInstrument
+    At = A(:,:,iInstrument);
+    for kFrame = 1:T
+        simpleS(:,kFrame,iInstrument) = At * songframes(:,kFrame);
+    end
+end
+simpleS(:,:,2) =  max(0,conv2(simpleS(:,:,2), ...
+        repmat([-1 -1 4 -1 -1]',1,1),'same'));
+
+%% add the instruments (i.e. the different partial decay bla)
+%---------------------------------------------------------
+note_s =  (simpleS(:,:,1) .* simpleS(:,:,2));
+clear simpleS
+
+%% tuning
+
+wrapped_s = zeros(nBins,T);
+for iBin = 1:nBins
+    wrapped_s(iBin,:) = sum(note_s(iBin:nBins:end,:));
+end
+on_circle = exp(i * ((1:nBins)-midbin)/nBins * 2 * pi);
+complex_tuning = on_circle * wrapped_s;
+smooth_complex_tuning = conv2(complex_tuning,hamming(20*hopspersecond)','same');
+tooflat = angle(mean(smooth_complex_tuning)) / (2 * pi) * nBins;
+tooflat = repmat(tooflat,T,1);
+tuned_s = note_s;
+for iFrame = 1:T
+    tuned_s(:,iFrame) = interp1(1:nBins*noterange, note_s(:,iFrame), (1:nBins*noterange) + 1 * tooflat(iFrame),[],0);
+end
+
+%% reduce to 1 bin per semitone
+wrapped_tuned_s = reshape(tuned_s,[nBins,noterange*T]);
+wei = rectwin(nBins)';
+reduced = reshape(wei * wrapped_tuned_s,noterange,T);
+
+salience.full = s;
+salience.reduced = reduced;
+
+%% make chromagram
+
+reduced = medfilt1(reduced',9)';
+chromagen = [zeros(12,1) repmat(eye(12),1,5)];
+
+
+treble_profile = ([0 zeros(1,24) linspace(0,1,6) linspace(1,1,6) ones(1,12)  linspace(1,0,6) zeros(1,6)]);
+bass_profile   = [0 ones(1,18) linspace(1,0,12) ,zeros(1,noterange-31)];
+wide_profile = max(treble_profile, bass_profile);
+
+treble_salience = reduced .* repmat(treble_profile(:),1,T);
+bass_salience = reduced  .* repmat(bass_profile(:),1,T);
+wide_salience = reduced  .* repmat(wide_profile(:),1,T);
+
+bass_chromag = circshift(chromagen * bass_salience,6);
+wide_chromag = circshift(chromagen * wide_salience,6);
+
+[peakindex,peakindex]=sort(treble_salience,'descend');
+for iFrame = 1:T
+    treble_salience(peakindex(1,iFrame),iFrame) = treble_salience(peakindex(2,iFrame),iFrame);
+end
+treble_chromag = circshift(chromagen * treble_salience,6);
+
+chromagram.treble = treble_chromag;
+chromagram.bass = bass_chromag;
+chromagram.wide = wide_chromag;
+
+% csvwrite('chr.csv',[ones(25,1) [maxn(circshift(bass_chromag,4));ones(1,size(treble_chromag,2)); maxn(circshift(treble_chromag,4))]]');
+% csvwrite('tuned_s.csv',[maxn(reduced)]');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/mychroma.m~.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,170 @@
+function [chromagram,t,salience] = ...
+    mychroma(filename, nBins, fmin, used_fs, fracofsecond, calcu)
+
+if isempty(nBins)
+    nBins = 3;
+end
+midbin = ceil(nBins/2);
+if isempty(fmin)
+    fmin = 55 * 2^(-7/12-(midbin-1)/12/nBins);
+end
+
+if isempty(used_fs)
+    used_fs=round(44100/4);
+end
+
+hopspersecond = 20;
+nFFT = 2^nextpow2(used_fs/fracofsecond);
+hopsize = used_fs/hopspersecond/nFFT;
+noterange = 61;
+used_instruments = 1:2;
+nInstrument = length(used_instruments);
+
+%% load or generate dictionary
+dirc = what('./data');
+dicfilename = ['mydict-' num2str(nBins) '.mat'];
+if ~calcu && any(strcmp(dirc.mat, dicfilename))
+    load(['data/' dicfilename])
+else
+    % dictionary parameters
+    midbin = nBins/2 + .5;
+    %hopspersecond = 10;
+    secs = .8;
+    t = linspace(0,secs,secs*used_fs)';
+
+    % make note dictionary
+    A = zeros(noterange*nBins,nFFT/2,nInstrument);
+    for iInstrument = used_instruments
+        for iMidiNote = 1:noterange
+            for iBin = 1:nBins
+                f0 = fmin * 2^((iMidiNote-1)/12 + (iBin-1)/12/nBins);
+                %wave = zeros(size(t));
+                switch iInstrument
+                    case 1
+                        wave = sum([sin(t*2*pi*f0*1) ...
+                            0.6^1 * sin(t*2*pi*f0*2) ...
+                            0.6^2 * sin(t*2*pi*f0*3) ...
+                            0.6^3 * sin(t*2*pi*f0*4)],2);
+                    case 2
+                        wave = sin(t*2*pi*f0*1);
+                    case 3
+                        wave = sum([...
+                            0.6^1 * sin(t*2*pi*f0*1/2) ...
+                            0.6^2 * sin(t*2*pi*f0*1/3) ...
+                            0.6^3 * sin(t*2*pi*f0*1/4) ...
+                            0.6^4 * sin(t*2*pi*f0*1/5) ...
+                            0.6^5 * sin(t*2*pi*f0*1/6) ...                         
+                            0.6^6 * sin(t*2*pi*f0*1/7) ...
+                            0.6^7 * sin(t*2*pi*f0*1/8) ...                            
+                            0.6^8 * sin(t*2*pi*f0*1/9)],2);
+                end
+                fftframes0 = myframefft(wave,nFFT,hopsize,'hamming');
+                A(nBins*(iMidiNote-1)+iBin,:,iInstrument) = mean(abs(fftframes0(1:round(nFFT/2),:)),2);
+            end
+        end
+    end
+    save(dicfilename, 'A', 'nFFT', 'hopsize');
+end
+
+%% get the fft frames from a wave file
+fprintf(1,'%s\n',filename)
+[audiosize,fs] = wavread(filename,'size');
+chunk_sec = 20;
+nChunk = ceil(audiosize(1)/fs/chunk_sec);
+songframes = [];
+s = [];
+start = 1;
+
+for iChunk = 1:nChunk
+    samplemin = (iChunk-1) * chunk_sec * fs + 1;
+    samplemax = min(audiosize(1), (iChunk * chunk_sec + 1) * fs);
+    
+    audiodata0 = wavread(filename,[samplemin samplemax]);
+   
+    audiodata = resample(mean(audiodata0,2),used_fs,fs,20);
+   
+    songframes0 = myframefft(audiodata,nFFT,hopsize,'hamming');
+    
+    if size(songframes0,2)>=start
+        songframes = [songframes(:,1:end-start) abs(songframes0(1:round(nFFT/2),start:end))];
+    end
+    start = round(hopspersecond/2)+1;
+end
+clear songframes0
+clear audiodata
+clear audiodata0
+
+T = size(songframes,2);
+t = (0:T-1)./hopspersecond;
+fprintf(1, '%d different notes, %d frequency bins, %d time frames\n', noterange,nFFT/2, T)
+
+simpleS = zeros(noterange*nBins,T, nInstrument+1);
+songframes(isnan(songframes)) = 0;
+
+for iInstrument = 1:nInstrument
+    At = A(:,:,iInstrument);
+    for kFrame = 1:T
+        simpleS(:,kFrame,iInstrument) = At * songframes(:,kFrame);
+    end
+end
+simpleS(:,:,2) =  max(0,conv2(simpleS(:,:,2), ...
+        repmat([-1 -1 4 -1 -1]',1,1),'same'));
+
+%% add the instruments (i.e. the different partial decay bla)
+%---------------------------------------------------------
+note_s =  (simpleS(:,:,1) .* simpleS(:,:,2));
+clear simpleS
+
+%% tuning
+
+wrapped_s = zeros(nBins,T);
+for iBin = 1:nBins
+    wrapped_s(iBin,:) = sum(note_s(iBin:nBins:end,:));
+end
+on_circle = exp(i * ((1:nBins)-midbin)/nBins * 2 * pi);
+complex_tuning = on_circle * wrapped_s;
+smooth_complex_tuning = conv2(complex_tuning,hamming(20*hopspersecond)','same');
+tooflat = angle(mean(smooth_complex_tuning)) / (2 * pi) * nBins;
+tooflat = repmat(tooflat,T,1);
+tuned_s = note_s;
+for iFrame = 1:T
+    tuned_s(:,iFrame) = interp1(1:nBins*noterange, note_s(:,iFrame), (1:nBins*noterange) + 1 * tooflat(iFrame),[],0);
+end
+
+%% reduce to 1 bin per semitone
+wrapped_tuned_s = reshape(tuned_s,[nBins,noterange*T]);
+wei = rectwin(nBins)';
+reduced = reshape(wei * wrapped_tuned_s,noterange,T);
+
+salience.full = s;
+salience.reduced = reduced;
+
+%% make chromagram
+
+reduced = medfilt1(reduced',9)';
+chromagen = [zeros(12,1) repmat(eye(12),1,5)];
+
+
+treble_profile = ([0 zeros(1,24) linspace(0,1,6) linspace(1,1,6) ones(1,12)  linspace(1,0,6) zeros(1,6)]);
+bass_profile   = [0 ones(1,18) linspace(1,0,12) ,zeros(1,noterange-31)];
+wide_profile = max(treble_profile, bass_profile);
+
+treble_salience = reduced .* repmat(treble_profile(:),1,T);
+bass_salience = reduced  .* repmat(bass_profile(:),1,T);
+wide_salience = reduced  .* repmat(wide_profile(:),1,T);
+
+bass_chromag = circshift(chromagen * bass_salience,6);
+wide_chromag = circshift(chromagen * wide_salience,6);
+
+[peakindex,peakindex]=sort(treble_salience,'descend');
+for iFrame = 1:T
+    treble_salience(peakindex(1,iFrame),iFrame) = treble_salience(peakindex(2,iFrame),iFrame);
+end
+treble_chromag = circshift(chromagen * treble_salience,6);
+
+chromagram.treble = treble_chromag;
+chromagram.bass = bass_chromag;
+chromagram.wide = wide_chromag;
+
+% csvwrite('chr.csv',[ones(25,1) [maxn(circshift(bass_chromag,4));ones(1,size(treble_chromag,2)); maxn(circshift(treble_chromag,4))]]');
+% csvwrite('tuned_s.csv',[maxn(reduced)]');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/myframefft.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,76 @@
+
+% segment audio data into overlapping frames and take fft of each frame
+
+function fftframes = myframefft(audiodata, winlength, overlap, windowkind, varargin)
+
+if nargin > 4
+    nPad = varargin{1};
+    zeropadding = true;
+else
+    zeropadding = false;
+end
+
+fprintf(1,'');   
+
+win = winlength;
+
+% Pad audio with zeros so that first analysis frame corresponds with first
+% audio sample
+
+pad = zeros((win/2),1);
+
+%audiodata = [pad; audiodata; pad];
+
+% find size of input
+ilength = length(audiodata);
+
+
+%pad audio data
+audiodata = [pad; audiodata; pad]; 
+
+% set hop size
+hop = fix(win.*overlap); 
+
+% set number of windows
+num_win = ceil((ilength+1)/win/overlap);
+
+start=1;
+if ~zeropadding
+    fftframes = zeros(win,num_win);
+else
+    fftframes = zeros(win*(nPad+1),num_win);
+end
+
+check = ceil(num_win/10);
+
+switch windowkind 
+    case 'hamming'
+        window = hamming(win);
+    case 'rect'
+        window = rectwin(win);
+    case 'kaiser'
+        window = kaiser(win);
+end
+
+
+% do fft analysis for each window:
+for i = 1 : num_win;
+    start = floor(win * overlap * (i-1) + 1);
+    if ~zeropadding
+        segment = window .* audiodata(start:(start + win - 1));
+        fftframes(:,i) = fft(segment, win)';
+    else
+        segment = window .* audiodata(start:(start + win - 1));
+        fftframes(:,i) = fft(segment, win * (nPad+1))';
+    end
+  
+%    start = start + hop
+    
+    if mod(i,check)  == 0
+        fprintf(1,'.');
+    end
+    
+end;
+fprintf(1,'\n');
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/myframefft.m~.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,68 @@
+
+% segment audio data into overlapping frames and take fft of each frame
+
+function fftframes = myframefft(audiodata, winlength, overlap, windowkind, varargin)
+
+if nargin > 4
+    nPad = varargin{1};
+    zeropadding = true;
+end
+
+fprintf(1,'');   
+
+win = winlength;
+
+% Pad audio with zeros so that first analysis frame corresponds with first
+% audio sample
+
+pad = zeros((win/2),1);
+
+%audiodata = [pad; audiodata; pad];
+
+% find size of input
+ilength = length(audiodata);
+
+
+%pad audio data
+audiodata = [pad; audiodata; pad]; 
+
+% set hop size
+hop = fix(win.*overlap); 
+
+% set number of windows
+num_win = ceil((ilength+1)/win/overlap);
+
+start=1;
+
+fftframes = zeros(win,num_win);
+
+check = ceil(num_win/10);
+
+if windowkind == 'hamming'
+    window = hamming(win);
+else
+    window = rectwin(win);
+end
+
+
+% do fft analysis for each window:
+for i = 1 : num_win;
+    start = floor(win * overlap * (i-1) + 1);
+    if ~zeropadding
+        segment = window .* audiodata(start:(start + win - 1));
+        fftframes(:,i) = fft(segment, win)';
+    else
+        segment = [window .* audiodata(start:(start + win - 1)) zeros(nPad*win)];
+        fftframes(:,i) = fft(segment, win)';
+    end
+  
+%    start = start + hop
+    
+    if mod(i,check)  == 0
+        fprintf(1,'.');
+    end
+    
+end;
+fprintf(1,'\n');
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/readaudiochunk.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+
+% Read in an audio file
+
+
+function [audiodata, info] = readaudiochunk(info)
+
+fprintf(1,'reading audio chunk\n');
+
+% read in wav file
+
+[rawdata, info.fs] = wavread(info.filename,[info.startsample info.endsample]);
+
+info.fsdownsampled = info.fs;
+
+% take average of stereo signals to give one mono audio vector
+
+meandata = mean(rawdata,2);
+
+% normalise audio
+if max(meandata) > 0.00001
+    audiodata = meandata/max(meandata);
+else
+    audiodata = meandata;
+end
+
+    
+    
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/shadedplot.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,65 @@
+function [ha hb hc] = shadedplot(x, y1, y2, varargin)
+
+% SHADEDPLOT draws two lines on a plot and shades the area between those
+% lines.
+%
+% SHADEDPLOT(x, y1, y2)
+%   All of the arguments are vectors of the same length, and each y-vector is
+%   horizontal (i.e. size(y1) = [1  N]). Vector x contains the x-axis values,
+%   and y1:y2 contain the y-axis values.
+%
+%   Plot y1 and y2 vs x, then shade the area between those two
+%   lines. Highlight the edges of that band with lines.
+%
+%   SHADEDPLOT(x, y1, y2, areacolor, linecolor)
+%   The arguments areacolor and linecolor allow the user to set the color
+%   of the shaded area and the boundary lines. These arguments must be
+%   either text values (see the help for the PLOT function) or a
+%   3-element vector with the color values in RGB (see the help for
+%   COLORMAP).
+%
+%   [HA HB HC = SHADEDPLOT(x, y1, y2) returns three handles to the calling
+%   function. HA is a vector of handles to areaseries objects (HA(2) is the
+%   shaded area), HB is the handle to the first line (x vs y1), and HC is
+%   the handle to the second line (x vs y2).
+%
+%   Example:
+%
+%     x1 = [1 2 3 4 5 6];
+%     y1 = x1;
+%     y2 = x1+1;
+%     x3 = [1.5 2 2.5 3 3.5 4];
+%     y3 = 2*x3;
+%     y4 = 4*ones(size(x3));
+%     ha = shadedplot(x1, y1, y2, [1 0.7 0.7], 'r'); %first area is red
+%     hold on
+%     hb = shadedplot(x3, y3, y4, [0.7 0.7 1]); %second area is blue
+%     hold off
+
+% plot the shaded area
+y = [y1; (y2-y1)]'; 
+ha = area(x, y);
+set(ha(1), 'FaceColor', 'none') % this makes the bottom area invisible
+set(ha, 'LineStyle', 'none')
+
+% plot the line edges
+hold on 
+hb = plot(x, y1, 'LineWidth', 1);
+hc = plot(x, y2, 'LineWidth', 1);
+hold off
+
+% set the line and area colors if they are specified
+switch length(varargin)
+    case 0
+    case 1
+        set(ha(2), 'FaceColor', varargin{1})
+    case 2
+        set(ha(2), 'FaceColor', varargin{1})
+        set(hb, 'Color', varargin{2})
+        set(hc, 'Color', varargin{2})
+    otherwise
+end
+
+% put the grid on top of the colored area
+set(gca, 'Layer', 'top')
+grid on
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/synchronisechroma.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function bc = synchronisechroma(chromag, beats, frame_t)
+
+% assigning beats to frames
+nBeat = size(beats,1);
+nFrame = size(chromag, 2);
+
+bc = ones(nBeat,size(chromag,1));
+chromag(:,isnan(sum(chromag))) = 1;
+
+if size(beats,2) < 2
+    for iBeat = 1:nBeat-1
+        currind = find(frame_t >= beats(iBeat) & frame_t < beats(iBeat+1));
+        bc(iBeat,:) = median(chromag(:,currind),2);
+        if ~any(isnan(bc(iBeat,:)))
+            bc(iBeat,:) = bc(iBeat,:)/max(bc(iBeat,:));
+        end
+    end
+else
+    for iBeat = 1:nBeat
+        currind = (frame_t >= beats(iBeat,1) & frame_t < beats(iBeat,2));
+        bc(iBeat,:) = median(chromag(:,currind),2);
+        if ~any(isnan(bc(iBeat,:)))
+            bc(iBeat,:) = bc(iBeat,:)/max(bc(iBeat,:));
+        end
+    end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/.svn/text-base/synchronisechroma.m~.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function bc = synchronisechroma(chromag, beats, frame_t)
+
+% assigning beats to frames
+nBeat = length(beats);
+nFrame = size(chromag, 2);
+beatassign = zeros(nFrame,1);
+iBeat = 2;
+minFrame = find(frame_t > beats(1),1);
+
+bc = ones(nBeat,12);
+chromag(:,isnan(sum(chromag))) = 1;
+
+for iBeat = 1:nBeat-1
+    find()
+    bc(iBeat,:) = median(chromag(:,beatassign == iBeat),2);
+    if ~any(isnan(bc(iBeat,:)))
+        bc(iBeat,:) = bc(iBeat,:)/max(bc(iBeat,:));
+    end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/basschroma13.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function bc13 = basschroma13(bc)
+bc(isnan(sum(bc,2)),:) = 1;
+bc = qnormalise(bc,1,2);
+bc13 = [bc,(1./12./max(bc,[],2)).^2];
+bc13 = qnormalise(bc13, inf, 2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/beatchroma.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,25 @@
+function bc = beatchroma(chromag, beats, frame_t)
+
+% assigning beats to frames
+nBeat = length(beats);
+nFrame = size(chromag, 2);
+beatassign = zeros(1,nFrame);
+iBeat = 1;
+
+for iFrame = 1:nFrame
+    if frame_t(iFrame) > beats(iBeat) && frame_t(iFrame) < beats(end)
+        iBeat = iBeat + 1;
+    end
+    beatassign(iFrame) = iBeat;
+end
+% averaging over frames belonging to one beat
+fprintf(1,'__ preprocessing chromagram... ___________________________________________\n');
+bc = zeros(nBeat,12);
+chromag(:,isnan(sum(chromag))) = 1;
+
+for iBeat = 1:nBeat
+    bc(iBeat,:) = median(chromag(:,beatassign == iBeat),2);
+    if ~any(isnan(bc(iBeat,:)))
+        bc(iBeat,:) = bc(iBeat,:)/max(bc(iBeat,:));
+    end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/bigframefft.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,61 @@
+
+% segment audio data into overlapping frames and take fft of each frame
+
+function [fftframes,info] = bigframefft(audiodata, info)
+
+fprintf(1,'framefft\n');
+    
+info.undertest = [info.undertest '\nfft'];
+
+% set window length
+win = info.windowlength;
+
+
+% Pad audio with zeros so that first analysis frame corresponds with first
+% audio sample
+
+pad = zeros((win/2),1);
+
+%audiodata = [pad; audiodata; pad];
+
+% find size of input
+ilength = length(audiodata);
+
+
+%pad audio data
+audiodata = [pad; audiodata; pad]; 
+
+% set hop size
+hop = fix(win.*info.overlap); 
+
+info.hopsize = hop;
+
+% set number of windows
+num_win = ceil((ilength+1)/hop);
+
+info.numberframes = num_win;
+
+start=1;
+
+fftframes = zeros(win,num_win);
+
+check = ceil(num_win/10);
+
+
+% do fft analysis for each window:
+for i = 1 : num_win;
+  
+    segment = audiodata(start:(start + win - 1));
+    
+    fftframes(:,i) = fft(segment, win)';
+  
+    start = start + hop;
+    
+    if mod(i,check)  == 0
+        fprintf(1,'.');
+    end
+    
+end;
+fprintf(1,'\n');
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/chromagenerator.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,212 @@
+function [chroma, t, salience, tuning, URIstring] = chromagenerator(filename, kammerton, nBin)
+
+%% make URI string
+URIstring = strcat('chromagenerator-', num2str(kammerton), '-',num2str(nBin));
+
+%% parameters
+% set the bins per semitone (i.e. binsperoctave/12)
+% kammerton = 440;
+% nBin = 7;
+midbin = ceil(nBin/2);
+
+% minimum and maximum MIDI bin, should be n octaves apart.
+midimin = 21; % 69 has 440 Hz
+% midimin = 45; % 69 has 440 Hz
+midimax = 92; 
+% midimax = 68; 
+noterange = midimax - midimin + 1;
+
+% midi note values including the fractions "between" actual MIDI notes
+midibins = midimin-(midbin-1)/nBin:(1/nBin):midimax+(midbin-1)/nBin;
+% the same in frequencies
+fbins = kammerton * 2.^((midibins-69)/12);
+nFbin = length(fbins);
+
+% the sampling frequency everything is (down)sampled to
+used_fs = 11025;
+
+% intuitive setting of how long the frame is (quite short here!)
+fracofsecond = 4; 
+
+hopspersecond = 20;
+
+% calculate a convenient FFT length
+nFFT = 2^nextpow2(used_fs/fracofsecond);
+% hopsize in samples
+hopsize = used_fs/hopspersecond/nFFT;
+
+% "instrument" means a particular spectral shape
+used_instruments = 1:2;
+nInstrument = length(used_instruments);
+
+%% generate dictionary
+% (complex) tones for all fundamental frequencies are generated. then their
+% amplitude spectrum is calculated and normalised according to the L2 norm.
+
+% preliminary t for dictionary generation
+t = (1:nFFT)/used_fs;
+% initialise note dictionary
+A = zeros(nFbin,nFFT/2,nInstrument);
+
+% loop over all instruments
+for iInstrument = used_instruments
+    % loop over all fundamental frequencies
+    for iFbin = 1:nFbin;
+        f0 = fbins(iFbin);
+        switch iInstrument
+            case 1
+                wave = sum([sin(t*2*pi*f0*1); ...
+                    0.9^1 * sin(t*2*pi*f0*2); ...
+                    0.9^2 * sin(t*2*pi*f0*3); ...
+                    0.9^3 * sin(t*2*pi*f0*4); ...
+                    ...0.9^4 * sin(t*2*pi*f0*5); ...
+                    ]);
+            case 2
+                wave = sin(t*2*pi*f0*1);
+        end
+        % window wave and fft
+        wave = hamming(nFFT)' .* wave;
+        fullfft = fft(wave);
+        % calculate amplitude spectrum from fft
+        A(iFbin,:,iInstrument) = abs(fullfft(1:round(nFFT/2)));
+    end
+    % normalise (L2 norm)
+    A(:,:,iInstrument) = qnormalise(A(:,:,iInstrument),2,2);
+end
+
+%% get the fft frames from a wave file
+%this is probably ending up not being used in a vamp plugin
+% fprintf(1,'%s\n',filename)
+% [audiosize,fs] = wavread(filename,'size');
+% chunk_sec = 20;
+% nChunk = ceil(audiosize(1)/fs/chunk_sec);
+% songframes = [];
+% start = 1;
+% % extract fft from chunks (for less memory consumption)
+% for iChunk = 1:nChunk
+%     samplemin = (iChunk-1) * chunk_sec * fs + 1;
+%     samplemax = min(audiosize(1), (iChunk * chunk_sec + 1) * fs);    
+%     audiodata0 = wavread(filename,[samplemin samplemax]);   
+%     audiodata = resample(mean(audiodata0,2),used_fs,fs,20);
+%     songframes0 = myframefft(audiodata,nFFT,hopsize,'hamming');
+%     if size(songframes0,2)>=start
+%         songframes = [songframes(:,1:end-start) abs(songframes0(1:round(nFFT/2),start:end))];
+%     end
+%     start = round(hopspersecond/2)+1;
+% end
+% clear songframes0
+% clear audiodata
+% clear audiodata0
+% t = (0:T-1)./hopspersecond;
+
+%%
+[songframes,f,t]=chunkspectrogram(filename,4096,4096*7/8,4096,inf);
+hopspersecond = 1/(t(2)-t(1));
+songframes = abs(songframes);
+%%
+T = size(songframes,2);
+
+fprintf(1, '%d different notes, %d frequency bins, %d time frames\n', noterange,nFFT/2, T)
+
+notespectrum0 = zeros(nFbin, T, nInstrument);
+songframes = qnormalise(songframes,2,1);
+songframes(isnan(songframes)) = 0;
+
+%% calculate cosine distance
+for iInstrument = 1:nInstrument
+    for iTone = 1:nFbin
+        notespectrum0(iTone,:,iInstrument) = A(iTone,:,iInstrument) * songframes;
+    end
+end
+%% get only the bins with "more than 1 st. deviation"
+notespectrum = zeros(size(notespectrum0));
+wind_size = 6 * nBin;
+wind = hamming(wind_size)/sum(hamming(wind_size));
+stdthresh = 1;
+for iInstrument = used_instruments
+    % calculate running mean
+    m = conv2(notespectrum0(:,:,iInstrument),wind(:),'same');
+    % calculate running standard deviation
+    stdev = sqrt(conv2((notespectrum0(:,:,iInstrument)-m).^2,wind(:),'same'));
+    % take only those tones that are above 1 standard deviation from the
+    % mean
+    notespectrum(:,:,iInstrument) = (notespectrum0(:,:,iInstrument)-m)./stdev;
+    temp = notespectrum(:,:,iInstrument);
+    temp(temp<stdthresh) = 0;
+    notespectrum(:,:,iInstrument) = temp;
+end
+% notes that are one were not "good enough" (not greater than 1 st.
+% deviation reater than the mean) and are hence set to 0.
+notespectrum(notespectrum<=stdthresh) = 0;
+% we require that the notes be on in *both* "instruments". hence the final
+% note spectrum note_s is their product, which works a bit like a minimum
+note_s =  notespectrum(:,:,1) .* notespectrum(:,:,2);
+
+note_s(1:nBin*6,:) = 0;
+note_s(isnan(note_s)) = 0;
+%% tuning
+% I wrap the note spectrum to one semitone, kind of generating the note
+% spectrum modulo one semitone. one gets a matrix of size nBin x T. from
+% that matrix, the tuning can be calculated by extracting the angle of the
+% sum of all columns, the sum of all columns being a nBin-dimensional
+% vector.
+th = tuner(note_s(36*nBin+(1:12*nBin),:), nBin)
+% th = tuner(notespectrum0(36*nBin+(1:12*nBin),:,2), nBin)
+tuning = kammerton*2^((th/2/pi)/12)
+% tune the spectrum by interpolating the bins such that now the middle bin
+% of every semitone corresponds to the right frequency in equal
+% temperament
+tuned_s = zeros(size(note_s));
+for iFrame = 1:T
+    tuned_s(:,iFrame) = interp1(1:nFbin, note_s(:,iFrame), (1:nFbin) + th / (2 * pi) * nBin,[],0);
+end
+
+%% reduce to 1 bin per semitone
+% just sum the nBin bins that correspond to one semitone.
+wrapped_tuned_s = reshape(tuned_s,[nBin,noterange*T]);
+% if you want to emphasize the middle bin, use a fancy window, otherwise
+% just use the rectangular window
+wei = rectwin(nBin)';
+salience.reduced = reshape(wei * wrapped_tuned_s,noterange,T);
+% median filter in time direction, if you like
+salience.reduced = medfilt1(salience.reduced,floor(hopspersecond/5)-1,[],2);
+
+%% make chromagram
+% actually the edge of the note spectrum is a bit noisy (due to the
+% convolution three parts above. that's why I start some bins from the
+% lower edge (i.e. midimin_used). maybe one could do this properly
+% sometime.
+midimin_used = midimin+6;
+% uebergang is where bass and treble chroma overlap equally
+uebergang = 50;
+
+% some simple linear functions to generate the treble and bass profiles
+leftfunc = zeros(2,noterange);
+rightfunc = zeros(2,noterange);
+leftfunc(1,:) = 2/12*((midimin:midimax)-midimin_used);
+leftfunc(2,:) = 1/12*((midimin:midimax)-uebergang) + 0.5;
+rightfunc(1,:) = -1/12*((midimin:midimax)-uebergang) + 0.5;
+rightfunc(2,:) = -(.5)/12*((midimin:midimax)-midimax);
+
+% initialise stuff
+salience.bass = zeros(size(salience.reduced));
+salience.treble = zeros(size(salience.reduced));
+profiles = zeros(noterange,3);
+
+% bass and treble profiles
+for i = 1:2
+   profiles(:,i) = max(0,min(1,min(leftfunc(i,:),rightfunc(i,:))))';
+end
+% wide profile (i.e. both bass and treble)
+profiles(:,3) = min(1,sum(profiles(:,1:2),2));
+
+% calculate specific saliences (windowed in f0 direction)
+salience.bass = salience.reduced .* profiles(:,ones(1,T));
+salience.treble = salience.reduced .* profiles(:,2 * ones(1,T));
+salience.wide = salience.reduced .* profiles(:,3 * ones(1,T));
+
+% calculate chromagrams
+chroma.bass = squeeze(max(reshape(salience.bass,[12,6,T]),[],2));
+chroma.treble = squeeze(max(reshape(salience.treble,[12,6,T]),[],2));
+chroma.wide = squeeze(max(reshape(salience.wide,[12,6,T]),[],2));
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/chromamatthias.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,138 @@
+function [results, info] = chromamatthias(filename, prod, maxx)
+
+%---------------------------------------------------------------
+%   Part of the matthiasmISMIR08 project
+%   Written by Christopher Harte, modified by Matthias Mauch 
+%   @ Queen Mary, University of London
+%   2008
+%---------------------------------------------------------------
+
+
+% Set up info structure (initialise variables to 0 if we don't have values
+% now...
+
+info = {};
+%%
+info.filename = filename;
+% info.filename = '/Volumes/Music/Music/Beatles/12_-_Let_It_Be/wav/06_-_Let_It_Be.wav';
+% info.filename = '/Volumes/Music/Music/Beatles/unrevised/01wave/01_-_I_Saw_Her_Standing_There.wav';
+info.undertest = '';            % which algorithms are run
+
+% Signal Parameters:
+info.fs = 44100;                % Sampling freq of audio file
+info.downsample  = 4;           % downsampling factor
+info.fsdownsampled = ...
+    info.fs / info.downsample;   % fs after downsampling
+info.preprocessing = 'downsample'; % What kind of preprocessing?
+info.numberframes = 0;          % number of frames calculated
+info.windowlength = 0;          % window length in samples
+info.overlap = ...
+    1/8;                        % window overlap factor
+info.overl = ...
+    1 - info.overlap;
+info.hopsize = 0;               % window overlap in samples
+info.framespersecond = 0;       % effective frames per second
+
+% Constant Q parameters:
+info.binsperoctave = 36;        % bins per octave for const q
+info.fmax = 1760;              % top frequency for const q
+info.fmin = 110;                % bottom frequency for const q
+info.numcqbins = 0;             % number of bins in a Constant Q vector
+info.sparkernelfile = '';       % mat file containing sparse spectral kernels matrix 
+info.sparsethreshold =  0.0054; % sparsekernel threshold
+info.maxx = maxx;
+% Get constant Q parameters - need to do this first to set window length
+info = getcqparameters(info);
+
+% Prepare chunking
+info.chunkoverlap = 2 * 1/info.overlap;         % frames
+info.audiofilesize = wavread(info.filename,'size');
+info.chunksize =  500;          % frames
+info.samplechunksize = (info.chunksize - 1) * ...
+    info.hopsize * info.downsample; % chunk length in original samples
+info.samplechunkhopsize = (info.chunksize - 1 - info.chunkoverlap) * ...
+    info.hopsize * info.downsample;
+info.framespersecond = info.fsdownsampled/info.hopsize;
+%%
+nChunk = ceil(info.audiofilesize / info.samplechunkhopsize);
+results = {};
+iChunk = 0;
+for iChunk = 1:nChunk  
+%
+    info.startsample = (iChunk - 1) * info.samplechunkhopsize + 1;
+    info.endsample = min(...
+        info.startsample + info.samplechunksize -1, ...
+        info.audiofilesize(1));
+%
+    [audiodata, info] = readaudiochunk(info);
+
+    % Perform downsampling here if required
+
+    [audiodata, info] = preprocessing(audiodata,info);
+
+    % Perform FFT
+    [fftframes,info] = bigframefft(audiodata,info);
+
+    % Harmonics adjustment
+    if prod
+        [fftframes] = prodfft(fftframes, 3);
+    end
+
+
+    % Perform Constant Q
+    [constqframes, info] = constq(fftframes,info);
+    
+    % Smooth constqframes for transient removal (time direction)
+    constqframes = medfilt1(constqframes,round(info.framespersecond/2),[],2);
+
+    % 'Normalise' Constant Q
+    % constqframes = constqframes ./ repmat(sum(abs(constqframes),1),size(constqframes,1),1);
+
+    % fftframes = 10 * log10(abs(fftframes).^2);
+
+    % Calculate HPCP
+    [hpcpframes,info] = hpcp(constqframes,info);
+
+    % Peakpick HPCP
+    % [peakpickframes,info] = framepeakpick(hpcpframes,info);
+
+
+    % Calculate Tuning
+    % [tuningframes,info] = tuning(peakpickframes,info);
+
+    % Calculate slightly adjusted chromagram
+    [chromaframes, info] = tunebyshift(hpcpframes, info);
+    % figure,
+    % imagesc(info.t,[],(chromaframes')), axis xy
+
+    % put results in output structure
+    if iChunk == 1
+%         results.fftframes = fftframes;
+%         results.constqframes = constqframes;
+%         results.hpcpframes = hpcpframes;
+        results.chromaframes = chromaframes;
+    else
+%         results.fftframes = ...
+%             [results.fftframes(:,1:end-info.frameoverlap),...
+%              results.fftframes(:,end-info.frameoverlap+1:end) ...
+%              + fftframes(:,1:info.frameoverlap),...
+%              fftframes(:,info.frameoverlap+1:end)];
+%         results.constqframes = ...
+%             [results.constqframes(:,1:end-info.frameoverlap),...
+%              results.constqframes(:,end-info.frameoverlap+1:end) ...
+%              + constqframes(:,1:info.frameoverlap),...
+%              constqframes(:,info.frameoverlap+1:end)];
+%         results.hpcpframes = ...
+%             [results.hpcpframes(1:end-info.frameoverlap,:);...
+%              results.hpcpframes(end-info.frameoverlap+1:end,:) ...
+%              + hpcpframes(1:info.frameoverlap,:);...
+%              hpcpframes(info.frameoverlap+1:end,:)];
+        x = round(info.chunkoverlap/2);
+%         results.chromaframes = chromaframes;
+        results.chromaframes = ...
+            [results.chromaframes(1:end-info.chunkoverlap+x,:);...
+             chromaframes(2+x:end,:)];
+    end
+end
+info.numberframes = size(results.chromaframes,1);
+info.t = ((0:info.numberframes-1) * info.hopsize) / info.fsdownsampled;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/chunkspectrogram.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,70 @@
+function [s,f,t] = chunkspectrogram(filename,d_windo,d_nOverlap,d_nFFT, maxf)
+%%
+% d_ are the downsampled things
+% o_ are the original things
+
+
+d_fs = 11025;
+
+[temp, o_fs] = wavread(filename,'size');
+
+if mod(o_fs/d_fs,1) ~= 0
+    error('The sample frequency of the wave file has to be an integer multiple of %1.0f.',d_fs);
+end
+
+o_nSample = temp(1);
+d_nSample = floor(o_nSample*d_fs/o_fs);
+
+o_nOverlap = d_nOverlap * o_fs/d_fs;
+
+
+d_nSamplePerChunk = d_windo+200*(d_windo-d_nOverlap);
+
+if d_nSample < d_nSamplePerChunk
+    d_nSamplePerChunk = d_nSample;
+end
+
+d_endsample = d_nSamplePerChunk:d_nSamplePerChunk:d_nSample;
+
+o_startsample = [1, d_endsample * o_fs / d_fs + 1];
+o_endsample = d_endsample * o_fs / d_fs;
+o_endsample = min(o_endsample + o_fs / d_fs * d_nOverlap, o_nSample); % extend so that chunks overlap
+
+% in most cases the file length is not exactly a multiple of 
+if o_endsample(end) < o_nSample
+    o_endsample = [o_endsample o_nSample];
+end
+
+%%
+
+nChunk = length(o_startsample);
+
+for iChunk = 1:nChunk
+    fprintf(1,'_');
+end
+leftpad = zeros(d_windo/2,1);
+fprintf(1,'\n.')
+x = resample(mean(wavread(filename,[o_startsample(1) o_endsample(1)]),2),d_fs,o_fs);
+s = spectrogram([leftpad; x], d_windo,d_nOverlap,d_nFFT, d_fs);
+f = (0:d_nFFT/2-1)/d_nFFT*d_fs;
+if maxf < max(f)
+    maxbin = find(f>maxf,1)-1;
+else
+    maxbin = length(f);
+end
+s = s(1:maxbin,:);
+f = f(1:maxbin);
+for iChunk = 2:nChunk-1
+    fprintf(1,'.')
+    temps = spectrogram(resample(mean(wavread(filename,[o_startsample(iChunk) o_endsample(iChunk)]),2),d_fs,o_fs), ...
+        d_windo,d_nOverlap,d_nFFT, d_fs);
+    s = [s(1:maxbin,:),temps(1:maxbin,:)];
+end
+x = resample(mean(wavread(filename,[o_startsample(nChunk) o_nSample]),2),d_fs,o_fs);
+if length(x)>d_windo
+    temps = spectrogram(x, ...
+        d_windo,d_nOverlap,d_nFFT, d_fs);
+    s = [s(1:maxbin,:),temps(1:maxbin,:)];
+end
+fprintf(1,'.\n')
+t = (0:size(s,2)-1) * (d_windo-d_nOverlap)/d_fs;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/chunkspectrogram_ISMIR2010.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,45 @@
+function [s,f,t] = chunkspectrogram_ISMIR2010(filename,d_windo,d_nOverlap,d_nFFT, maxf)
+%%
+% d_ are the downsampled things
+% o_ are the original things
+
+
+d_fs = 11025;
+
+[filesize, o_fs] = wavread(filename,'size');
+
+
+
+if mod(o_fs/d_fs,1) ~= 0
+    error('The sample frequency of the wave file has to be an integer multiple of %1.0f.',d_fs);
+end
+downsample = o_fs/d_fs;
+
+o_windo = d_windo * downsample;
+o_nOverlap = d_nOverlap * downsample;
+o_hopSize = o_windo-o_nOverlap;
+nFrame = floor((filesize(1) - o_windo) / o_hopSize);
+
+s = zeros(d_nFFT/2, nFrame);
+f = (0:d_nFFT/2-1)/d_fs;
+t = zeros(nFrame,1);
+
+wind = hamming(d_windo);
+wind = wind/sum(wind);
+
+for iLine = 1:round(nFrame/200)
+    fprintf(1,'_');
+end
+fprintf(1,'\n');
+
+for iFrame = 1:nFrame
+    if mod(iFrame,200) == 0
+        fprintf(1,'.');
+    end
+    ind = [1,o_windo] + (iFrame-1) * (o_hopSize);
+    wave = sum(wavread(filename, ind),2) / 2;
+    temp = fft(resample(wave,d_fs,o_fs) .* wind);
+    s(:, iFrame) = temp(1:d_nFFT/2);
+    t(iFrame) = (ind(1) + ind(2)) / 2 / o_fs;
+end
+fprintf(1,'\n');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/hpcp2chroma.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,53 @@
+function [chromaframes, info] = hpcp2chroma(hpcpframes, info)
+
+% calculate the best shift 
+% (0 - none, 1 - one third of semitone down, 
+%  2 - two thirds of semitone down)
+
+bps = info.binsperoctave/12;
+
+indices = (0:11) * bps;
+
+
+%%%%% NANs! $%%%%%%%%%%%%
+% nanrows = isnan(sum(hpcpframes,2));
+% binweights = sum(hpcpframes(~nanrows,:));
+% condensedweights = zeros(bps,12);
+% for iBin = 1:bps
+%     condensedweights(iBin,1:12) = sum(binweights(indices+iBin)); 
+% end
+% % [maximum, maxind] = max(...
+% %     [sum(binweights(indices+1)),...
+% %      sum(binweights(indices+2)),...
+% %      sum(binweights(indices+3))]);
+% [maximum, maxind] = max(sum(condensedweights,2));
+% shiftposs = [1 0 -1];
+% shift = shiftposs(maxind);
+% if bps ==3
+%     hpcpframes = circshift(hpcpframes',shift)';
+%     info.tuning6th = shift;
+% end
+maxind = 1;
+
+% fprintf(1,['(max. energy at ' num2str(maxind) ', shift by ' num2str(shift) ')\n\n'])
+if (~info.maxx)
+    if bps == 3
+        chromaframes = ...
+            0 * hpcpframes(:,indices+1) + ...
+            1 * hpcpframes(:,indices+2) + ...
+            0 * hpcpframes(:,indices+3);
+    elseif bps == 2
+        chromaframes = ...
+            (1-shift)* hpcpframes(:,indices+1) + ...
+             shift* hpcpframes(:,indices+2);
+    elseif bps == 1
+        chromaframes = hpcpframes;
+    end
+else
+    chromaframes = zeros(size(hpcpframes,1),12);
+    for iChroma = 1:12
+        chromaframes(:,iChroma) = max(hpcpframes(:,indices(iChroma)+(1:3)),[],2);
+    end
+end
+
+chromaframes = chromaframes ./ repmat(sum(chromaframes,2),1,12);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/mmcq2hpcp.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,48 @@
+
+
+
+
+% CQ2HPCP Convert Constant Q spectrum to a HPCP
+%
+%   CQ2HPCP(cqframes, info)
+%
+%   cqframes = vector or matrix constant q spectrum / spectra
+%   info = info structure containing parameters
+%
+
+function [hpcpframes] = mmcq2hpcp(cqframes, info)
+
+%get cq parameters from info structure
+num_win = info.numberframes;
+
+cqbins = size(cqframes,1); 
+
+bpo = info.binsperoctave;
+
+% calculate the number of octaves we have in the spectrum
+num_oct = floor(cqbins/bpo)-1;
+
+hpcpframes(1:num_win, 1:bpo) = 0;   
+
+
+
+% for each window calculate chromagram
+for i = 1 : num_win
+    % add each octave of the spectrum into the chromagram
+    for oct = 0:num_oct;     
+        ind = oct*bpo;
+        
+        hpcpframes(i, 1:bpo) = hpcpframes(i, 1:bpo) + abs(cqframes(ind+1:ind+bpo,i))';   
+                
+    end;
+ 
+    % normalise
+%     hpcpframes(i,1:bpo) = hpcpframes(i,1:bpo)/max(hpcpframes(i,1:bpo));
+    meanc = mean(hpcpframes(i,1:bpo));
+    if meanc > 0.0000001
+        hpcpframes(i,1:bpo) = hpcpframes(i,1:bpo)/mean(hpcpframes(i,1:bpo)); %scale to be a distribution!
+    else
+        hpcpframes(i,1:bpo) = (bpo)^(-1);
+    end
+end;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/mychroma.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,170 @@
+function [chromagram,t,salience] = ...
+    mychroma(filename, nBins, fmin, used_fs, fracofsecond, calcu)
+
+if isempty(nBins)
+    nBins = 3;
+end
+midbin = ceil(nBins/2);
+if isempty(fmin)
+    fmin = 55 * 2^(-7/12-(midbin-1)/12/nBins);
+end
+
+if isempty(used_fs)
+    used_fs=round(44100/4);
+end
+
+hopspersecond = 20;
+nFFT = 2^nextpow2(used_fs/fracofsecond);
+hopsize = used_fs/hopspersecond/nFFT;
+noterange = 61;
+used_instruments = 1:2;
+nInstrument = length(used_instruments);
+
+%% load or generate dictionary
+dirc = what('./data');
+dicfilename = ['mydict-' num2str(nBins) '.mat'];
+if ~calcu && any(strcmp(dirc.mat, dicfilename))
+    load(['data/' dicfilename])
+else
+    % dictionary parameters
+    midbin = nBins/2 + .5;
+    %hopspersecond = 10;
+    secs = .8;
+    t = linspace(0,secs,secs*used_fs)';
+
+    % make note dictionary
+    A = zeros(noterange*nBins,nFFT/2,nInstrument);
+    for iInstrument = used_instruments
+        for iMidiNote = 1:noterange
+            for iBin = 1:nBins
+                f0 = fmin * 2^((iMidiNote-1)/12 + (iBin-1)/12/nBins);
+                %wave = zeros(size(t));
+                switch iInstrument
+                    case 1
+                        wave = sum([sin(t*2*pi*f0*1) ...
+                            0.6^1 * sin(t*2*pi*f0*2) ...
+                            0.6^2 * sin(t*2*pi*f0*3) ...
+                            0.6^3 * sin(t*2*pi*f0*4)],2);
+                    case 2
+                        wave = sin(t*2*pi*f0*1);
+                    case 3
+                        wave = sum([...
+                            0.6^1 * sin(t*2*pi*f0*1/2) ...
+                            0.6^2 * sin(t*2*pi*f0*1/3) ...
+                            0.6^3 * sin(t*2*pi*f0*1/4) ...
+                            0.6^4 * sin(t*2*pi*f0*1/5) ...
+                            0.6^5 * sin(t*2*pi*f0*1/6) ...                         
+                            0.6^6 * sin(t*2*pi*f0*1/7) ...
+                            0.6^7 * sin(t*2*pi*f0*1/8) ...                            
+                            0.6^8 * sin(t*2*pi*f0*1/9)],2);
+                end
+                fftframes0 = myframefft(wave,nFFT,hopsize,'hamming');
+                A(nBins*(iMidiNote-1)+iBin,:,iInstrument) = mean(abs(fftframes0(1:round(nFFT/2),:)),2);
+            end
+        end
+    end
+    save(['data/' dicfilename], 'A', 'nFFT', 'hopsize');
+end
+
+%% get the fft frames from a wave file
+fprintf(1,'%s\n',filename)
+[audiosize,fs] = wavread(filename,'size');
+chunk_sec = 20;
+nChunk = ceil(audiosize(1)/fs/chunk_sec);
+songframes = [];
+s = [];
+start = 1;
+
+for iChunk = 1:nChunk
+    samplemin = (iChunk-1) * chunk_sec * fs + 1;
+    samplemax = min(audiosize(1), (iChunk * chunk_sec + 1) * fs);
+    
+    audiodata0 = wavread(filename,[samplemin samplemax]);
+   
+    audiodata = resample(mean(audiodata0,2),used_fs,fs,20);
+   
+    songframes0 = myframefft(audiodata,nFFT,hopsize,'hamming');
+    
+    if size(songframes0,2)>=start
+        songframes = [songframes(:,1:end-start) abs(songframes0(1:round(nFFT/2),start:end))];
+    end
+    start = round(hopspersecond/2)+1;
+end
+clear songframes0
+clear audiodata
+clear audiodata0
+
+T = size(songframes,2);
+t = (0:T-1)./hopspersecond;
+fprintf(1, '%d different notes, %d frequency bins, %d time frames\n', noterange,nFFT/2, T)
+
+simpleS = zeros(noterange*nBins,T, nInstrument+1);
+songframes(isnan(songframes)) = 0;
+
+for iInstrument = 1:nInstrument
+    At = A(:,:,iInstrument);
+    for kFrame = 1:T
+        simpleS(:,kFrame,iInstrument) = At * songframes(:,kFrame);
+    end
+end
+simpleS(:,:,2) =  max(0,conv2(simpleS(:,:,2), ...
+        repmat([-1 -1 4 -1 -1]',1,1),'same'));
+
+%% add the instruments (i.e. the different partial decay bla)
+%---------------------------------------------------------
+note_s =  (simpleS(:,:,1) .* simpleS(:,:,2));
+clear simpleS
+
+%% tuning
+
+wrapped_s = zeros(nBins,T);
+for iBin = 1:nBins
+    wrapped_s(iBin,:) = sum(note_s(iBin:nBins:end,:));
+end
+on_circle = exp(i * ((1:nBins)-midbin)/nBins * 2 * pi);
+complex_tuning = on_circle * wrapped_s;
+smooth_complex_tuning = conv2(complex_tuning,hamming(20*hopspersecond)','same');
+tooflat = angle(mean(smooth_complex_tuning)) / (2 * pi) * nBins;
+tooflat = repmat(tooflat,T,1);
+tuned_s = note_s;
+for iFrame = 1:T
+    tuned_s(:,iFrame) = interp1(1:nBins*noterange, note_s(:,iFrame), (1:nBins*noterange) + 1 * tooflat(iFrame),[],0);
+end
+
+%% reduce to 1 bin per semitone
+wrapped_tuned_s = reshape(tuned_s,[nBins,noterange*T]);
+wei = rectwin(nBins)';
+reduced = reshape(wei * wrapped_tuned_s,noterange,T);
+
+salience.full = s;
+salience.reduced = reduced;
+
+%% make chromagram
+
+reduced = medfilt1(reduced',9)';
+chromagen = [zeros(12,1) repmat(eye(12),1,5)];
+
+
+treble_profile = ([0 zeros(1,24) linspace(0,1,6) linspace(1,1,6) ones(1,12)  linspace(1,0,6) zeros(1,6)]);
+bass_profile   = [0 ones(1,18) linspace(1,0,12) ,zeros(1,noterange-31)];
+wide_profile = max(treble_profile, bass_profile);
+
+treble_salience = reduced .* repmat(treble_profile(:),1,T);
+bass_salience = reduced  .* repmat(bass_profile(:),1,T);
+wide_salience = reduced  .* repmat(wide_profile(:),1,T);
+
+bass_chromag = circshift(chromagen * bass_salience,6);
+wide_chromag = circshift(chromagen * wide_salience,6);
+
+[peakindex,peakindex]=sort(treble_salience,'descend');
+for iFrame = 1:T
+    treble_salience(peakindex(1,iFrame),iFrame) = treble_salience(peakindex(2,iFrame),iFrame);
+end
+treble_chromag = circshift(chromagen * treble_salience,6);
+
+chromagram.treble = treble_chromag;
+chromagram.bass = bass_chromag;
+chromagram.wide = wide_chromag;
+
+% csvwrite('chr.csv',[ones(25,1) [maxn(circshift(bass_chromag,4));ones(1,size(treble_chromag,2)); maxn(circshift(treble_chromag,4))]]');
+% csvwrite('tuned_s.csv',[maxn(reduced)]');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/mychroma.m~	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,170 @@
+function [chromagram,t,salience] = ...
+    mychroma(filename, nBins, fmin, used_fs, fracofsecond, calcu)
+
+if isempty(nBins)
+    nBins = 3;
+end
+midbin = ceil(nBins/2);
+if isempty(fmin)
+    fmin = 55 * 2^(-7/12-(midbin-1)/12/nBins);
+end
+
+if isempty(used_fs)
+    used_fs=round(44100/4);
+end
+
+hopspersecond = 20;
+nFFT = 2^nextpow2(used_fs/fracofsecond);
+hopsize = used_fs/hopspersecond/nFFT;
+noterange = 61;
+used_instruments = 1:2;
+nInstrument = length(used_instruments);
+
+%% load or generate dictionary
+dirc = what('./data');
+dicfilename = ['mydict-' num2str(nBins) '.mat'];
+if ~calcu && any(strcmp(dirc.mat, dicfilename))
+    load(['data/' dicfilename])
+else
+    % dictionary parameters
+    midbin = nBins/2 + .5;
+    %hopspersecond = 10;
+    secs = .8;
+    t = linspace(0,secs,secs*used_fs)';
+
+    % make note dictionary
+    A = zeros(noterange*nBins,nFFT/2,nInstrument);
+    for iInstrument = used_instruments
+        for iMidiNote = 1:noterange
+            for iBin = 1:nBins
+                f0 = fmin * 2^((iMidiNote-1)/12 + (iBin-1)/12/nBins);
+                %wave = zeros(size(t));
+                switch iInstrument
+                    case 1
+                        wave = sum([sin(t*2*pi*f0*1) ...
+                            0.6^1 * sin(t*2*pi*f0*2) ...
+                            0.6^2 * sin(t*2*pi*f0*3) ...
+                            0.6^3 * sin(t*2*pi*f0*4)],2);
+                    case 2
+                        wave = sin(t*2*pi*f0*1);
+                    case 3
+                        wave = sum([...
+                            0.6^1 * sin(t*2*pi*f0*1/2) ...
+                            0.6^2 * sin(t*2*pi*f0*1/3) ...
+                            0.6^3 * sin(t*2*pi*f0*1/4) ...
+                            0.6^4 * sin(t*2*pi*f0*1/5) ...
+                            0.6^5 * sin(t*2*pi*f0*1/6) ...                         
+                            0.6^6 * sin(t*2*pi*f0*1/7) ...
+                            0.6^7 * sin(t*2*pi*f0*1/8) ...                            
+                            0.6^8 * sin(t*2*pi*f0*1/9)],2);
+                end
+                fftframes0 = myframefft(wave,nFFT,hopsize,'hamming');
+                A(nBins*(iMidiNote-1)+iBin,:,iInstrument) = mean(abs(fftframes0(1:round(nFFT/2),:)),2);
+            end
+        end
+    end
+    save(dicfilename, 'A', 'nFFT', 'hopsize');
+end
+
+%% get the fft frames from a wave file
+fprintf(1,'%s\n',filename)
+[audiosize,fs] = wavread(filename,'size');
+chunk_sec = 20;
+nChunk = ceil(audiosize(1)/fs/chunk_sec);
+songframes = [];
+s = [];
+start = 1;
+
+for iChunk = 1:nChunk
+    samplemin = (iChunk-1) * chunk_sec * fs + 1;
+    samplemax = min(audiosize(1), (iChunk * chunk_sec + 1) * fs);
+    
+    audiodata0 = wavread(filename,[samplemin samplemax]);
+   
+    audiodata = resample(mean(audiodata0,2),used_fs,fs,20);
+   
+    songframes0 = myframefft(audiodata,nFFT,hopsize,'hamming');
+    
+    if size(songframes0,2)>=start
+        songframes = [songframes(:,1:end-start) abs(songframes0(1:round(nFFT/2),start:end))];
+    end
+    start = round(hopspersecond/2)+1;
+end
+clear songframes0
+clear audiodata
+clear audiodata0
+
+T = size(songframes,2);
+t = (0:T-1)./hopspersecond;
+fprintf(1, '%d different notes, %d frequency bins, %d time frames\n', noterange,nFFT/2, T)
+
+simpleS = zeros(noterange*nBins,T, nInstrument+1);
+songframes(isnan(songframes)) = 0;
+
+for iInstrument = 1:nInstrument
+    At = A(:,:,iInstrument);
+    for kFrame = 1:T
+        simpleS(:,kFrame,iInstrument) = At * songframes(:,kFrame);
+    end
+end
+simpleS(:,:,2) =  max(0,conv2(simpleS(:,:,2), ...
+        repmat([-1 -1 4 -1 -1]',1,1),'same'));
+
+%% add the instruments (i.e. the different partial decay bla)
+%---------------------------------------------------------
+note_s =  (simpleS(:,:,1) .* simpleS(:,:,2));
+clear simpleS
+
+%% tuning
+
+wrapped_s = zeros(nBins,T);
+for iBin = 1:nBins
+    wrapped_s(iBin,:) = sum(note_s(iBin:nBins:end,:));
+end
+on_circle = exp(i * ((1:nBins)-midbin)/nBins * 2 * pi);
+complex_tuning = on_circle * wrapped_s;
+smooth_complex_tuning = conv2(complex_tuning,hamming(20*hopspersecond)','same');
+tooflat = angle(mean(smooth_complex_tuning)) / (2 * pi) * nBins;
+tooflat = repmat(tooflat,T,1);
+tuned_s = note_s;
+for iFrame = 1:T
+    tuned_s(:,iFrame) = interp1(1:nBins*noterange, note_s(:,iFrame), (1:nBins*noterange) + 1 * tooflat(iFrame),[],0);
+end
+
+%% reduce to 1 bin per semitone
+wrapped_tuned_s = reshape(tuned_s,[nBins,noterange*T]);
+wei = rectwin(nBins)';
+reduced = reshape(wei * wrapped_tuned_s,noterange,T);
+
+salience.full = s;
+salience.reduced = reduced;
+
+%% make chromagram
+
+reduced = medfilt1(reduced',9)';
+chromagen = [zeros(12,1) repmat(eye(12),1,5)];
+
+
+treble_profile = ([0 zeros(1,24) linspace(0,1,6) linspace(1,1,6) ones(1,12)  linspace(1,0,6) zeros(1,6)]);
+bass_profile   = [0 ones(1,18) linspace(1,0,12) ,zeros(1,noterange-31)];
+wide_profile = max(treble_profile, bass_profile);
+
+treble_salience = reduced .* repmat(treble_profile(:),1,T);
+bass_salience = reduced  .* repmat(bass_profile(:),1,T);
+wide_salience = reduced  .* repmat(wide_profile(:),1,T);
+
+bass_chromag = circshift(chromagen * bass_salience,6);
+wide_chromag = circshift(chromagen * wide_salience,6);
+
+[peakindex,peakindex]=sort(treble_salience,'descend');
+for iFrame = 1:T
+    treble_salience(peakindex(1,iFrame),iFrame) = treble_salience(peakindex(2,iFrame),iFrame);
+end
+treble_chromag = circshift(chromagen * treble_salience,6);
+
+chromagram.treble = treble_chromag;
+chromagram.bass = bass_chromag;
+chromagram.wide = wide_chromag;
+
+% csvwrite('chr.csv',[ones(25,1) [maxn(circshift(bass_chromag,4));ones(1,size(treble_chromag,2)); maxn(circshift(treble_chromag,4))]]');
+% csvwrite('tuned_s.csv',[maxn(reduced)]');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/myframefft.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,76 @@
+
+% segment audio data into overlapping frames and take fft of each frame
+
+function fftframes = myframefft(audiodata, winlength, overlap, windowkind, varargin)
+
+if nargin > 4
+    nPad = varargin{1};
+    zeropadding = true;
+else
+    zeropadding = false;
+end
+
+fprintf(1,'');   
+
+win = winlength;
+
+% Pad audio with zeros so that first analysis frame corresponds with first
+% audio sample
+
+pad = zeros((win/2),1);
+
+%audiodata = [pad; audiodata; pad];
+
+% find size of input
+ilength = length(audiodata);
+
+
+%pad audio data
+audiodata = [pad; audiodata; pad]; 
+
+% set hop size
+hop = fix(win.*overlap); 
+
+% set number of windows
+num_win = ceil((ilength+1)/win/overlap);
+
+start=1;
+if ~zeropadding
+    fftframes = zeros(win,num_win);
+else
+    fftframes = zeros(win*(nPad+1),num_win);
+end
+
+check = ceil(num_win/10);
+
+switch windowkind 
+    case 'hamming'
+        window = hamming(win);
+    case 'rect'
+        window = rectwin(win);
+    case 'kaiser'
+        window = kaiser(win);
+end
+
+
+% do fft analysis for each window:
+for i = 1 : num_win;
+    start = floor(win * overlap * (i-1) + 1);
+    if ~zeropadding
+        segment = window .* audiodata(start:(start + win - 1));
+        fftframes(:,i) = fft(segment, win)';
+    else
+        segment = window .* audiodata(start:(start + win - 1));
+        fftframes(:,i) = fft(segment, win * (nPad+1))';
+    end
+  
+%    start = start + hop
+    
+    if mod(i,check)  == 0
+        fprintf(1,'.');
+    end
+    
+end;
+fprintf(1,'\n');
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/myframefft.m~	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,68 @@
+
+% segment audio data into overlapping frames and take fft of each frame
+
+function fftframes = myframefft(audiodata, winlength, overlap, windowkind, varargin)
+
+if nargin > 4
+    nPad = varargin{1};
+    zeropadding = true;
+end
+
+fprintf(1,'');   
+
+win = winlength;
+
+% Pad audio with zeros so that first analysis frame corresponds with first
+% audio sample
+
+pad = zeros((win/2),1);
+
+%audiodata = [pad; audiodata; pad];
+
+% find size of input
+ilength = length(audiodata);
+
+
+%pad audio data
+audiodata = [pad; audiodata; pad]; 
+
+% set hop size
+hop = fix(win.*overlap); 
+
+% set number of windows
+num_win = ceil((ilength+1)/win/overlap);
+
+start=1;
+
+fftframes = zeros(win,num_win);
+
+check = ceil(num_win/10);
+
+if windowkind == 'hamming'
+    window = hamming(win);
+else
+    window = rectwin(win);
+end
+
+
+% do fft analysis for each window:
+for i = 1 : num_win;
+    start = floor(win * overlap * (i-1) + 1);
+    if ~zeropadding
+        segment = window .* audiodata(start:(start + win - 1));
+        fftframes(:,i) = fft(segment, win)';
+    else
+        segment = [window .* audiodata(start:(start + win - 1)) zeros(nPad*win)];
+        fftframes(:,i) = fft(segment, win)';
+    end
+  
+%    start = start + hop
+    
+    if mod(i,check)  == 0
+        fprintf(1,'.');
+    end
+    
+end;
+fprintf(1,'\n');
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/readaudiochunk.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,30 @@
+
+% Read in an audio file
+
+
+function [audiodata, info] = readaudiochunk(info)
+
+fprintf(1,'reading audio chunk\n');
+
+% read in wav file
+
+[rawdata, info.fs] = wavread(info.filename,[info.startsample info.endsample]);
+
+info.fsdownsampled = info.fs;
+
+% take average of stereo signals to give one mono audio vector
+
+meandata = mean(rawdata,2);
+
+% normalise audio
+if max(meandata) > 0.00001
+    audiodata = meandata/max(meandata);
+else
+    audiodata = meandata;
+end
+
+    
+    
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/shadedplot.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,65 @@
+function [ha hb hc] = shadedplot(x, y1, y2, varargin)
+
+% SHADEDPLOT draws two lines on a plot and shades the area between those
+% lines.
+%
+% SHADEDPLOT(x, y1, y2)
+%   All of the arguments are vectors of the same length, and each y-vector is
+%   horizontal (i.e. size(y1) = [1  N]). Vector x contains the x-axis values,
+%   and y1:y2 contain the y-axis values.
+%
+%   Plot y1 and y2 vs x, then shade the area between those two
+%   lines. Highlight the edges of that band with lines.
+%
+%   SHADEDPLOT(x, y1, y2, areacolor, linecolor)
+%   The arguments areacolor and linecolor allow the user to set the color
+%   of the shaded area and the boundary lines. These arguments must be
+%   either text values (see the help for the PLOT function) or a
+%   3-element vector with the color values in RGB (see the help for
+%   COLORMAP).
+%
+%   [HA HB HC = SHADEDPLOT(x, y1, y2) returns three handles to the calling
+%   function. HA is a vector of handles to areaseries objects (HA(2) is the
+%   shaded area), HB is the handle to the first line (x vs y1), and HC is
+%   the handle to the second line (x vs y2).
+%
+%   Example:
+%
+%     x1 = [1 2 3 4 5 6];
+%     y1 = x1;
+%     y2 = x1+1;
+%     x3 = [1.5 2 2.5 3 3.5 4];
+%     y3 = 2*x3;
+%     y4 = 4*ones(size(x3));
+%     ha = shadedplot(x1, y1, y2, [1 0.7 0.7], 'r'); %first area is red
+%     hold on
+%     hb = shadedplot(x3, y3, y4, [0.7 0.7 1]); %second area is blue
+%     hold off
+
+% plot the shaded area
+y = [y1; (y2-y1)]'; 
+ha = area(x, y);
+set(ha(1), 'FaceColor', 'none') % this makes the bottom area invisible
+set(ha, 'LineStyle', 'none')
+
+% plot the line edges
+hold on 
+hb = plot(x, y1, 'LineWidth', 1);
+hc = plot(x, y2, 'LineWidth', 1);
+hold off
+
+% set the line and area colors if they are specified
+switch length(varargin)
+    case 0
+    case 1
+        set(ha(2), 'FaceColor', varargin{1})
+    case 2
+        set(ha(2), 'FaceColor', varargin{1})
+        set(hb, 'Color', varargin{2})
+        set(hc, 'Color', varargin{2})
+    otherwise
+end
+
+% put the grid on top of the colored area
+set(gca, 'Layer', 'top')
+grid on
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/synchronisechroma.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,26 @@
+function bc = synchronisechroma(chromag, beats, frame_t)
+
+% assigning beats to frames
+nBeat = size(beats,1);
+nFrame = size(chromag, 2);
+
+bc = ones(nBeat,size(chromag,1));
+chromag(:,isnan(sum(chromag))) = 1;
+
+if size(beats,2) < 2
+    for iBeat = 1:nBeat-1
+        currind = find(frame_t >= beats(iBeat) & frame_t < beats(iBeat+1));
+        bc(iBeat,:) = median(chromag(:,currind),2);
+        if ~any(isnan(bc(iBeat,:)))
+            bc(iBeat,:) = bc(iBeat,:)/max(bc(iBeat,:));
+        end
+    end
+else
+    for iBeat = 1:nBeat
+        currind = (frame_t >= beats(iBeat,1) & frame_t < beats(iBeat,2));
+        bc(iBeat,:) = median(chromag(:,currind),2);
+        if ~any(isnan(bc(iBeat,:)))
+            bc(iBeat,:) = bc(iBeat,:)/max(bc(iBeat,:));
+        end
+    end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/featureextraction/synchronisechroma.m~	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function bc = synchronisechroma(chromag, beats, frame_t)
+
+% assigning beats to frames
+nBeat = length(beats);
+nFrame = size(chromag, 2);
+beatassign = zeros(nFrame,1);
+iBeat = 2;
+minFrame = find(frame_t > beats(1),1);
+
+bc = ones(nBeat,12);
+chromag(:,isnan(sum(chromag))) = 1;
+
+for iBeat = 1:nBeat-1
+    find()
+    bc(iBeat,:) = median(chromag(:,beatassign == iBeat),2);
+    if ~any(isnan(bc(iBeat,:)))
+        bc(iBeat,:) = bc(iBeat,:)/max(bc(iBeat,:));
+    end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/.svn/all-wcprops	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,47 @@
+K 25
+svn:wc:ra_dav:version-url
+V 51
+/svnroot/!svn/ver/1421/matlabtoolboxes/misc/figures
+END
+imxy.m
+K 25
+svn:wc:ra_dav:version-url
+V 58
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/figures/imxy.m
+END
+exportfig.m
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/figures/exportfig.m
+END
+uimage.m
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svnroot/!svn/ver/1421/matlabtoolboxes/misc/figures/uimage.m
+END
+rotateticklabel.m
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/figures/rotateticklabel.m
+END
+uimagesc.m
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svnroot/!svn/ver/1421/matlabtoolboxes/misc/figures/uimagesc.m
+END
+addmax.m
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/figures/addmax.m
+END
+printme.m
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/figures/printme.m
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/.svn/entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,266 @@
+10
+
+dir
+7329
+https://parrot.dcs.qmul.ac.uk/svnroot/matlabtoolboxes/misc/figures
+https://parrot.dcs.qmul.ac.uk/svnroot
+
+
+
+2009-03-06T16:14:34.602437Z
+1421
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+214cd2a9-030a-0410-b9a1-da4e402363b6
+
+imxy.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+593215c20d55052d29e75d09f527e7df
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+133
+
+exportfig.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+5258cb74eb732a511a7f81782faa774a
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+31654
+
+uimage.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+8cf09f5e178e103d6bfc0ffe54be1d78
+2009-03-06T16:14:34.602437Z
+1421
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3873
+
+rotateticklabel.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+a8a3bf8dee99631c41da4a3304a2a47a
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1720
+
+uimagesc.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+6ad496d4a4fdfb67e36eece540164b8b
+2009-03-06T16:14:34.602437Z
+1421
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1413
+
+addmax.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+fa25c8d98cc68c5c881042ca565434be
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+345
+
+printme.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+b1d815d085882132c06bf84c83463e42
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+222
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/.svn/prop-base/uimage.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/.svn/prop-base/uimagesc.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 0
+
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/.svn/text-base/addmax.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function addmax(varargin)
+if length(varargin)>0 && strcmp(varargin,'rows')
+    dimension = 2;
+else
+    dimension = 1;
+end
+
+chil=get(gca,'children');
+z = get(chil(1),'CData');
+x = get(chil(1),'XData');
+[maxind, maxind] = max(z,[],dimension);
+
+if length(x) == 2
+    x = x(1):x(2);
+end
+
+hold on
+m = plot(x, maxind, '.k','Erasemode','xor')
+hold off
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/.svn/text-base/exportfig.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,991 @@
+function varargout = exportfig(varargin)
+%EXPORTFIG  Export a figure.
+%   EXPORTFIG(H, FILENAME) writes the figure H to FILENAME.  H is
+%   a figure handle and FILENAME is a string that specifies the
+%   name of the output file.
+%
+%   EXPORTFIG(H, FILENAME, OPTIONS) writes the figure H to FILENAME
+%   with options initially specified by the structure OPTIONS. The
+%   field names of OPTIONS must be legal parameters listed below
+%   and the field values must be legal values for the corresponding
+%   parameter. Default options can be set in releases prior to R12
+%   by storing the OPTIONS structure in the root object's appdata
+%   with the command 
+%      setappdata(0,'exportfigdefaults', OPTIONS) 
+%   and for releases after R12 by setting the preference with the
+%   command 
+%      setpref('exportfig', 'defaults', OPTIONS) 
+%
+%   EXPORTFIG(...,PARAM1,VAL1,PARAM2,VAL2,...) specifies
+%   parameters that control various characteristics of the output
+%   file. Any parameter value can be the string 'auto' which means
+%   the parameter uses the default factory behavior, overriding
+%   any other default for the parameter.
+%
+%   Format Paramter:
+%     'Format'  a string
+%          specifies the output format. Defaults to 'eps'. For a
+%          list of export formats type 'help print'.
+%     'Preview' one of the strings 'none', 'tiff'
+%          specifies a preview for EPS files. Defaults to 'none'.
+%
+%   Size Parameters:
+%     'Width'   a positive scalar
+%          specifies the width in the figure's PaperUnits
+%     'Height'  a positive scalar
+%          specifies the height in the figure's PaperUnits
+%     'Bounds' one of the strings 'tight', 'loose'
+%          specifies a tight or loose bounding box. Defaults to 'tight'.
+%     'Reference' an axes handle or a string
+%          specifies that the width and height parameters
+%          are relative to the given axes. If a string is
+%          specified then it must evaluate to an axes handle.
+%
+%     Specifying only one dimension sets the other dimension
+%     so that the exported aspect ratio is the same as the
+%     figure's or reference axes' current aspect ratio. 
+%     If neither dimension is specified the size defaults to 
+%     the width and height from the figure's or reference
+%     axes' size. Tight bounding boxes are only computed for
+%     2-D views and in that case the computed bounds enclose all
+%     text objects.
+%           
+%   Rendering Parameters:
+%     'Color'     one of the strings 'bw', 'gray', 'cmyk'
+%         'bw'    specifies that lines and text are exported in
+%                 black and all other objects in grayscale
+%         'gray'  specifies that all objects are exported in grayscale
+%         'rgb'   specifies that all objects are exported in color
+%                 using the RGB color space
+%         'cmyk'  specifies that all objects are exported in color
+%                 using the CMYK color space
+%     'Renderer'  one of 'painters', 'zbuffer', 'opengl'
+%         specifies the renderer to use
+%     'Resolution'   a positive scalar
+%         specifies the resolution in dots-per-inch.
+%     'LockAxes'  one of 0 or 1
+%         specifies that all axes limits and ticks should be fixed
+%         while exporting.
+%     
+%     The default color setting is 'bw'.
+%
+%   Font Parameters:
+%     'FontMode'     one of the strings 'scaled', 'fixed'
+%     'FontSize'     a positive scalar
+%          in 'scaled' mode multiplies with the font size of each
+%          text object to obtain the exported font size
+%          in 'fixed' mode specifies the font size of all text
+%          objects in points
+%     'DefaultFixedFontSize' a positive scalar
+%          in 'fixed' mode specified the default font size in
+%          points
+%     'FontSizeMin' a positive scalar
+%          specifies the minimum font size allowed after scaling
+%     'FontSizeMax' a positive scalar
+%          specifies the maximum font size allowed after scaling
+%     'FontEncoding' one of the strings 'latin1', 'adobe'
+%          specifies the character encoding of the font
+%     'SeparateText' one of 0 or 1
+%          specifies that the text objects are stored in separate
+%          file as EPS with the base filename having '_t' appended.
+%
+%     If FontMode is 'scaled' but FontSize is not specified then a
+%     scaling factor is computed from the ratio of the size of the
+%     exported figure to the size of the actual figure.
+%
+%     The default 'FontMode' setting is 'scaled'.
+%
+%   Line Width Parameters:
+%     'LineMode'     one of the strings 'scaled', 'fixed'
+%     'LineWidth'    a positive scalar
+%     'DefaultFixedLineWidth' a positive scalar
+%     'LineWidthMin' a positive scalar
+%          specifies the minimum line width allowed after scaling
+%     'LineWidthMax' a positive scalar
+%          specifies the maximum line width allowed after scaling
+%     The semantics of 'Line' parameters are exactly the
+%     same as the corresponding 'Font' parameters, except that
+%     they apply to line widths instead of font sizes.
+%
+%   Style Map Parameter:
+%     'LineStyleMap'    one of [], 'bw', or a function name or handle
+%          specifies how to map line colors to styles. An empty
+%          style map means styles are not changed. The style map
+%          'bw' is a built-in mapping that maps lines with the same
+%          color to the same style and otherwise cycles through the
+%          available styles. A user-specified map is a function
+%          that takes as input a cell array of line objects and
+%          outputs a cell array of line style strings. The default
+%          map is [].
+%      
+%   Examples:
+%     exportfig(gcf,'fig1.eps','height',3);
+%       Exports the current figure to the file named 'fig1.eps' with
+%       a height of 3 inches (assuming the figure's PaperUnits is 
+%       inches) and an aspect ratio the same as the figure's aspect
+%       ratio on screen.
+%
+%     opts = struct('FontMode','fixed','FontSize',10,'height',3);
+%     exportfig(gcf, 'fig2.eps', opts, 'height', 5);
+%       Exports the current figure to 'fig2.eps' with all
+%       text in 10 point fonts and with height 5 inches.
+%
+%   See also PREVIEWFIG, APPLYTOFIG, RESTOREFIG, PRINT.
+
+%  Copyright 2000 Ben Hinkle
+%  Email bug reports and comments to bhinkle@mathworks.com
+
+if (nargin < 2)
+  error('Too few input arguments');
+end
+
+% exportfig(H, filename, [options,] ...)
+H = varargin{1};
+if ~LocalIsHG(H,'figure')
+  error('First argument must be a handle to a figure.');
+end
+filename = varargin{2};
+if ~ischar(filename)
+  error('Second argument must be a string.');
+end
+paramPairs = {varargin{3:end}};
+if nargin > 2
+  if isstruct(paramPairs{1})
+    pcell = LocalToCell(paramPairs{1});
+    paramPairs = {pcell{:}, paramPairs{2:end}};
+  end
+end
+verstr = version;
+majorver = str2num(verstr(1));
+defaults = [];
+if majorver > 5
+  if ispref('exportfig','defaults')
+    defaults = getpref('exportfig','defaults');
+  end
+elseif exist('getappdata')
+  defaults = getappdata(0,'exportfigdefaults');
+end
+if ~isempty(defaults)
+  dcell = LocalToCell(defaults);
+  paramPairs = {dcell{:}, paramPairs{:}};
+end
+
+% Do some validity checking on param-value pairs
+if (rem(length(paramPairs),2) ~= 0)
+  error(['Invalid input syntax. Optional parameters and values' ...
+	 ' must be in pairs.']);
+end
+
+auto.format = 'eps';
+auto.preview = 'none';
+auto.width = -1;
+auto.height = -1;
+auto.color = 'bw';
+auto.defaultfontsize=10;
+auto.fontsize = -1;
+auto.fontmode='scaled';
+auto.fontmin = 8;
+auto.fontmax = 60;
+auto.defaultlinewidth = 1.0;
+auto.linewidth = -1;
+auto.linemode=[];
+auto.linemin = 0.5;
+auto.linemax = 100;
+auto.fontencoding = 'latin1';
+auto.renderer = [];
+auto.resolution = [];
+auto.stylemap = [];
+auto.applystyle = 0;
+auto.refobj = -1;
+auto.bounds = 'tight';
+explicitbounds = 0;
+auto.lockaxes = 1;
+auto.separatetext = 0;
+opts = auto;
+
+% Process param-value pairs
+args = {};
+for k = 1:2:length(paramPairs)
+  param = lower(paramPairs{k});
+  if ~ischar(param)
+    error('Optional parameter names must be strings');
+  end
+  value = paramPairs{k+1};
+  
+  switch (param)
+   case 'format'
+    opts.format = LocalCheckAuto(lower(value),auto.format);
+    if strcmp(opts.format,'preview')
+      error(['Format ''preview'' no longer supported. Use PREVIEWFIG' ...
+	     ' instead.']);
+    end
+   case 'preview'
+    opts.preview = LocalCheckAuto(lower(value),auto.preview);
+    if ~strcmp(opts.preview,{'none','tiff'})
+      error('Preview must be ''none'' or ''tiff''.');
+    end
+   case 'width'
+    opts.width = LocalToNum(value, auto.width);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.width)
+	error('Width must be a numeric scalar > 0');
+      end
+    end
+   case 'height'
+    opts.height = LocalToNum(value, auto.height);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if(~LocalIsPositiveScalar(opts.height))
+	error('Height must be a numeric scalar > 0');
+      end
+    end
+   case 'color'
+    opts.color = LocalCheckAuto(lower(value),auto.color);
+    if ~strcmp(opts.color,{'bw','gray','rgb','cmyk'})
+      error('Color must be ''bw'', ''gray'',''rgb'' or ''cmyk''.');
+    end
+   case 'fontmode'
+    opts.fontmode = LocalCheckAuto(lower(value),auto.fontmode);
+    if ~strcmp(opts.fontmode,{'scaled','fixed'})
+      error('FontMode must be ''scaled'' or ''fixed''.');
+    end
+   case 'fontsize'
+    opts.fontsize = LocalToNum(value,auto.fontsize);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.fontsize)
+	error('FontSize must be a numeric scalar > 0');
+      end
+    end
+   case 'defaultfixedfontsize'
+    opts.defaultfontsize = LocalToNum(value,auto.defaultfontsize);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.defaultfontsize)
+	error('DefaultFixedFontSize must be a numeric scalar > 0');
+      end
+    end
+   case 'fontsizemin'
+    opts.fontmin = LocalToNum(value,auto.fontmin);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.fontmin)
+	error('FontSizeMin must be a numeric scalar > 0');
+      end
+    end
+   case 'fontsizemax'
+    opts.fontmax = LocalToNum(value,auto.fontmax);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.fontmax)
+	error('FontSizeMax must be a numeric scalar > 0');
+      end
+    end
+   case 'fontencoding'
+    opts.fontencoding = LocalCheckAuto(lower(value),auto.fontencoding);
+    if ~strcmp(opts.fontencoding,{'latin1','adobe'})
+      error('FontEncoding must be ''latin1'' or ''adobe''.');
+    end
+   case 'linemode'
+    opts.linemode = LocalCheckAuto(lower(value),auto.linemode);
+    if ~strcmp(opts.linemode,{'scaled','fixed'})
+      error('LineMode must be ''scaled'' or ''fixed''.');
+    end
+   case 'linewidth'
+    opts.linewidth = LocalToNum(value,auto.linewidth);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.linewidth)
+	error('LineWidth must be a numeric scalar > 0');
+      end
+    end
+   case 'defaultfixedlinewidth'
+    opts.defaultlinewidth = LocalToNum(value,auto.defaultlinewidth);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.defaultlinewidth)
+	error(['DefaultFixedLineWidth must be a numeric scalar >' ...
+	       ' 0']);
+      end
+    end
+   case 'linewidthmin'
+    opts.linemin = LocalToNum(value,auto.linemin);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.linemin)
+	error('LineWidthMin must be a numeric scalar > 0');
+      end
+    end
+   case 'linewidthmax'
+    opts.linemax = LocalToNum(value,auto.linemax);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.linemax)
+	error('LineWidthMax must be a numeric scalar > 0');
+      end
+    end
+   case 'linestylemap'
+    opts.stylemap = LocalCheckAuto(value,auto.stylemap);
+   case 'renderer'
+    opts.renderer = LocalCheckAuto(lower(value),auto.renderer);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~strcmp(opts.renderer,{'painters','zbuffer','opengl'})
+	error(['Renderer must be ''painters'', ''zbuffer'' or' ...
+	       ' ''opengl''.']);
+      end
+    end
+   case 'resolution'
+    opts.resolution = LocalToNum(value,auto.resolution);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~(isnumeric(value) & (prod(size(value)) == 1) & (value >= 0));
+	error('Resolution must be a numeric scalar >= 0');
+      end
+    end
+   case 'applystyle' % means to apply the options and not export
+    opts.applystyle = 1;
+   case 'reference'
+    if ischar(value)
+      if strcmp(value,'auto')
+	opts.refobj = auto.refobj;
+      else
+	opts.refobj = eval(value);
+      end
+    else
+      opts.refobj = value;
+    end
+    if ~LocalIsHG(opts.refobj,'axes')
+      error('Reference object must evaluate to an axes handle.');
+    end
+   case 'bounds'
+    opts.bounds = LocalCheckAuto(lower(value),auto.bounds);
+    explicitbounds = 1;
+    if ~strcmp(opts.bounds,{'tight','loose'})
+      error('Bounds must be ''tight'' or ''loose''.');
+    end
+   case 'lockaxes'
+    opts.lockaxes = LocalToNum(value,auto.lockaxes);
+   case 'separatetext'
+    opts.separatetext = LocalToNum(value,auto.separatetext);
+   otherwise
+    error(['Unrecognized option ' param '.']);
+  end
+end
+
+% make sure figure is up-to-date
+drawnow;
+
+allLines  = findall(H, 'type', 'line');
+allText   = findall(H, 'type', 'text');
+allAxes   = findall(H, 'type', 'axes');
+allImages = findall(H, 'type', 'image');
+allLights = findall(H, 'type', 'light');
+allPatch  = findall(H, 'type', 'patch');
+allSurf   = findall(H, 'type', 'surface');
+allRect   = findall(H, 'type', 'rectangle');
+allFont   = [allText; allAxes];
+allColor  = [allLines; allText; allAxes; allLights];
+allMarker = [allLines; allPatch; allSurf];
+allEdge   = [allPatch; allSurf];
+allCData  = [allImages; allPatch; allSurf];
+
+old.objs = {};
+old.prop = {};
+old.values = {};
+
+% Process format
+if strncmp(opts.format,'eps',3) & ~strcmp(opts.preview,'none')
+  args = {args{:}, ['-' opts.preview]};
+end
+
+hadError = 0;
+oldwarn = warning;
+try
+
+  % lock axes limits, ticks and labels if requested
+  if opts.lockaxes
+    old = LocalManualAxesMode(old, allAxes, 'TickMode');
+    old = LocalManualAxesMode(old, allAxes, 'TickLabelMode');
+    old = LocalManualAxesMode(old, allAxes, 'LimMode');
+  end  
+
+  % Process size parameters
+  figurePaperUnits = get(H, 'PaperUnits');
+  oldFigureUnits = get(H, 'Units');
+  oldFigPos = get(H,'Position');
+  set(H, 'Units', figurePaperUnits);
+  figPos = get(H,'Position');
+  refsize = figPos(3:4);
+  if opts.refobj ~= -1
+    oldUnits = get(opts.refobj, 'Units');
+    set(opts.refobj, 'Units', figurePaperUnits);
+    r = get(opts.refobj, 'Position');
+    refsize = r(3:4);
+    set(opts.refobj, 'Units', oldUnits);
+  end
+  aspectRatio = refsize(1)/refsize(2);
+  if (opts.width == -1) & (opts.height == -1)
+    opts.width = refsize(1);
+    opts.height = refsize(2);
+  elseif (opts.width == -1)
+    opts.width = opts.height * aspectRatio;
+  elseif (opts.height == -1)
+    opts.height = opts.width / aspectRatio;
+  end
+  wscale = opts.width/refsize(1);
+  hscale = opts.height/refsize(2);
+  sizescale = min(wscale,hscale);
+  old = LocalPushOldData(old,H,'PaperPositionMode', ...
+			 get(H,'PaperPositionMode'));
+  set(H, 'PaperPositionMode', 'auto');
+  newPos = [figPos(1) figPos(2)+figPos(4)*(1-hscale) ...
+	    wscale*figPos(3) hscale*figPos(4)];
+  set(H, 'Position', newPos);
+  set(H, 'Units', oldFigureUnits);
+  
+  % process line-style map
+  if ~isempty(opts.stylemap) & ~isempty(allLines)
+    oldlstyle = LocalGetAsCell(allLines,'LineStyle');
+    old = LocalPushOldData(old, allLines, {'LineStyle'}, ...
+			   oldlstyle);
+    newlstyle = oldlstyle;
+    if ischar(opts.stylemap) & strcmpi(opts.stylemap,'bw')
+      newlstyle = LocalMapColorToStyle(allLines);
+    else
+      try
+	newlstyle = feval(opts.stylemap,allLines);
+      catch
+	warning(['Skipping stylemap. ' lasterr]);
+      end
+    end
+    set(allLines,{'LineStyle'},newlstyle);
+  end
+
+  % Process rendering parameters
+  switch (opts.color)
+   case {'bw', 'gray'}
+    if ~strcmp(opts.color,'bw') & strncmp(opts.format,'eps',3)
+      opts.format = [opts.format 'c'];
+    end
+    args = {args{:}, ['-d' opts.format]};
+    
+    %compute and set gray colormap
+    oldcmap = get(H,'Colormap');
+    newgrays = 0.30*oldcmap(:,1) + 0.59*oldcmap(:,2) + 0.11*oldcmap(:,3);
+    newcmap = [newgrays newgrays newgrays];
+    old = LocalPushOldData(old, H, 'Colormap', oldcmap);
+    set(H, 'Colormap', newcmap);
+
+    %compute and set ColorSpec and CData properties
+    old = LocalUpdateColors(allColor, 'color', old);
+    old = LocalUpdateColors(allAxes, 'xcolor', old);
+    old = LocalUpdateColors(allAxes, 'ycolor', old);
+    old = LocalUpdateColors(allAxes, 'zcolor', old);
+    old = LocalUpdateColors(allMarker, 'MarkerEdgeColor', old);
+    old = LocalUpdateColors(allMarker, 'MarkerFaceColor', old);
+    old = LocalUpdateColors(allEdge, 'EdgeColor', old);
+    old = LocalUpdateColors(allEdge, 'FaceColor', old);
+    old = LocalUpdateColors(allCData, 'CData', old);
+    
+   case {'rgb','cmyk'}
+    if strncmp(opts.format,'eps',3)
+      opts.format = [opts.format 'c'];
+      args = {args{:}, ['-d' opts.format]};
+      if strcmp(opts.color,'cmyk')
+	args = {args{:}, '-cmyk'};
+      end
+    else
+      args = {args{:}, ['-d' opts.format]};
+    end
+   otherwise
+    error('Invalid Color parameter');
+  end
+  if (~isempty(opts.renderer))
+    args = {args{:}, ['-' opts.renderer]};
+  end
+  if (~isempty(opts.resolution)) | ~strncmp(opts.format,'eps',3)
+    if isempty(opts.resolution)
+      opts.resolution = 0;
+    end
+    args = {args{:}, ['-r' int2str(opts.resolution)]};
+  end
+
+  % Process font parameters
+  if ~isempty(opts.fontmode)
+    oldfonts = LocalGetAsCell(allFont,'FontSize');
+    oldfontunits = LocalGetAsCell(allFont,'FontUnits');
+    set(allFont,'FontUnits','points');
+    switch (opts.fontmode)
+     case 'fixed'
+      if (opts.fontsize == -1)
+	set(allFont,'FontSize',opts.defaultfontsize);
+      else
+	set(allFont,'FontSize',opts.fontsize);
+      end
+     case 'scaled'
+      if (opts.fontsize == -1)
+	scale = sizescale;
+      else
+	scale = opts.fontsize;
+      end
+      newfonts = LocalScale(oldfonts,scale,opts.fontmin,opts.fontmax);
+      set(allFont,{'FontSize'},newfonts);
+     otherwise
+      error('Invalid FontMode parameter');
+    end
+    old = LocalPushOldData(old, allFont, {'FontSize'}, oldfonts);
+    old = LocalPushOldData(old, allFont, {'FontUnits'}, oldfontunits);
+  end
+  if strcmp(opts.fontencoding,'adobe') & strncmp(opts.format,'eps',3)
+    args = {args{:}, '-adobecset'};
+  end
+
+  % Process line parameters
+  if ~isempty(opts.linemode)
+    oldlines = LocalGetAsCell(allMarker,'LineWidth');
+    old = LocalPushOldData(old, allMarker, {'LineWidth'}, oldlines);
+    switch (opts.linemode)
+     case 'fixed'
+      if (opts.linewidth == -1)
+	set(allMarker,'LineWidth',opts.defaultlinewidth);
+      else
+	set(allMarker,'LineWidth',opts.linewidth);
+      end
+     case 'scaled'
+      if (opts.linewidth == -1)
+	scale = sizescale;
+      else
+	scale = opts.linewidth;
+      end
+      newlines = LocalScale(oldlines, scale, opts.linemin, opts.linemax);
+      set(allMarker,{'LineWidth'},newlines);
+    end
+  end
+
+  % adjust figure bounds to surround axes
+  if strcmp(opts.bounds,'tight')
+    if (~strncmp(opts.format,'eps',3) & LocalHas3DPlot(allAxes)) | ...
+	  (strncmp(opts.format,'eps',3) & opts.separatetext)
+      if (explicitbounds == 1)
+	warning(['Cannot compute ''tight'' bounds. Using ''loose''' ...
+		 ' bounds.']);
+      end
+      opts.bounds = 'loose';
+    end
+  end
+  warning('off');
+  if ~isempty(allAxes)
+    if strncmp(opts.format,'eps',3)
+      if strcmp(opts.bounds,'loose')
+	args = {args{:}, '-loose'};
+      end
+      old = LocalPushOldData(old,H,'Position', oldFigPos);
+    elseif strcmp(opts.bounds,'tight')
+      oldaunits = LocalGetAsCell(allAxes,'Units');
+      oldapos = LocalGetAsCell(allAxes,'Position');
+      oldtunits = LocalGetAsCell(allText,'units');
+      oldtpos = LocalGetAsCell(allText,'Position');
+      set(allAxes,'units','points');
+      apos = LocalGetAsCell(allAxes,'Position');
+      oldunits = get(H,'Units');
+      set(H,'units','points');
+      origfr = get(H,'position');
+      fr = [];
+      for k=1:length(allAxes)
+	if ~strcmpi(get(allAxes(k),'Tag'),'legend')
+	  axesR = apos{k};
+	  r = LocalAxesTightBoundingBox(axesR, allAxes(k));
+	  r(1:2) = r(1:2) + axesR(1:2);
+	  fr = LocalUnionRect(fr,r);
+	end
+      end
+      if isempty(fr)
+	fr = [0 0 origfr(3:4)];
+      end
+      for k=1:length(allAxes)
+	ax = allAxes(k);
+	r = apos{k};
+	r(1:2) = r(1:2) - fr(1:2);
+	set(ax,'Position',r);
+      end
+      old = LocalPushOldData(old, allAxes, {'Position'}, oldapos);
+      old = LocalPushOldData(old, allText, {'Position'}, oldtpos);
+      old = LocalPushOldData(old, allText, {'Units'}, oldtunits);
+      old = LocalPushOldData(old, allAxes, {'Units'}, oldaunits);
+      old = LocalPushOldData(old, H, 'Position', oldFigPos);
+      old = LocalPushOldData(old, H, 'Units', oldFigureUnits);
+      r = [origfr(1) origfr(2)+origfr(4)-fr(4) fr(3:4)];
+      set(H,'Position',r);
+    else
+      args = {args{:}, '-loose'};
+      old = LocalPushOldData(old,H,'Position', oldFigPos);
+    end
+  end
+  
+  % Process text in a separate file if needed
+  if opts.separatetext & ~opts.applystyle
+    % First hide all text and export
+    oldtvis = LocalGetAsCell(allText,'visible');
+    set(allText,'visible','off');
+    oldax = LocalGetAsCell(allAxes,'XTickLabel',1);
+    olday = LocalGetAsCell(allAxes,'YTickLabel',1);
+    oldaz = LocalGetAsCell(allAxes,'ZTickLabel',1);
+    null = cell(length(oldax),1);
+    [null{:}] = deal([]);
+    set(allAxes,{'XTickLabel'},null);
+    set(allAxes,{'YTickLabel'},null);
+    set(allAxes,{'ZTickLabel'},null);
+    print(H, filename, args{:});
+    set(allText,{'Visible'},oldtvis);
+    set(allAxes,{'XTickLabel'},oldax);
+    set(allAxes,{'YTickLabel'},olday);
+    set(allAxes,{'ZTickLabel'},oldaz);
+    % Now hide all non-text and export as eps in painters
+    [path, name, ext] = fileparts(filename);
+    tfile = fullfile(path,[name '_t.eps']);
+    tfile2 = fullfile(path,[name '_t2.eps']);
+    foundRenderer = 0;
+    for k=1:length(args)
+      if strncmp('-d',args{k},2)
+	args{k} = '-deps';
+      elseif strncmp('-zbuffer',args{k},8) | ...
+	    strncmp('-opengl', args{k},6)
+	args{k} = '-painters';
+	foundRenderer = 1;
+      end
+    end
+    if ~foundRenderer
+      args = {args{:}, '-painters'};
+    end
+    allNonText = [allLines; allLights; allPatch; ...
+		  allImages; allSurf; allRect];
+    oldvis = LocalGetAsCell(allNonText,'visible');
+    oldc = LocalGetAsCell(allAxes,'color');
+    oldaxg = LocalGetAsCell(allAxes,'XGrid');
+    oldayg = LocalGetAsCell(allAxes,'YGrid');
+    oldazg = LocalGetAsCell(allAxes,'ZGrid');
+    [null{:}] = deal('off');
+    set(allAxes,{'XGrid'},null);
+    set(allAxes,{'YGrid'},null);
+    set(allAxes,{'ZGrid'},null);
+    set(allNonText,'Visible','off');
+    set(allAxes,'Color','none');
+    print(H, tfile2, args{:});
+    set(allNonText,{'Visible'},oldvis);
+    set(allAxes,{'Color'},oldc);
+    set(allAxes,{'XGrid'},oldaxg);
+    set(allAxes,{'YGrid'},oldayg);
+    set(allAxes,{'ZGrid'},oldazg);
+    %hack up the postscript file
+    fid1 = fopen(tfile,'w');
+    fid2 = fopen(tfile2,'r');
+    line = fgetl(fid2);
+    while ischar(line)
+      if strncmp(line,'%%Title',7)
+	fprintf(fid1,'%s\n',['%%Title: ', tfile]);
+      elseif (length(line) < 3) 
+	fprintf(fid1,'%s\n',line);
+      elseif ~strcmp(line(end-2:end),' PR') & ...
+	    ~strcmp(line(end-1:end),' L')
+	fprintf(fid1,'%s\n',line);
+      end
+      line = fgetl(fid2);
+    end
+    fclose(fid1);
+    fclose(fid2);
+    delete(tfile2);
+    
+  elseif ~opts.applystyle
+    drawnow;
+    print(H, filename, args{:});
+  end
+  warning(oldwarn);
+  
+catch
+  warning(oldwarn);
+  hadError = 1;
+end
+
+% Restore figure settings
+if opts.applystyle
+  varargout{1} = old;
+else
+  for n=1:length(old.objs)
+    if ~iscell(old.values{n}) & iscell(old.prop{n})
+      old.values{n} = {old.values{n}};
+    end
+    set(old.objs{n}, old.prop{n}, old.values{n});
+  end
+end
+
+if hadError
+  error(deblank(lasterr));
+end
+
+%
+%  Local Functions
+%
+
+function outData = LocalPushOldData(inData, objs, prop, values)
+outData.objs = {objs, inData.objs{:}};
+outData.prop = {prop, inData.prop{:}};
+outData.values = {values, inData.values{:}};
+
+function cellArray = LocalGetAsCell(fig,prop,allowemptycell);
+cellArray = get(fig,prop);
+if nargin < 3
+  allowemptycell = 0;
+end
+if ~iscell(cellArray) & (allowemptycell | ~isempty(cellArray))
+  cellArray = {cellArray};
+end
+
+function newArray = LocalScale(inArray, scale, minv, maxv)
+n = length(inArray);
+newArray = cell(n,1);
+for k=1:n
+  newArray{k} = min(maxv,max(minv,scale*inArray{k}(1)));
+end
+
+function gray = LocalMapToGray1(color)
+gray = color;
+if ischar(color)
+  switch color(1)
+   case 'y'
+    color = [1 1 0];
+   case 'm'
+    color = [1 0 1];
+   case 'c'
+    color = [0 1 1];
+   case 'r'
+    color = [1 0 0];
+   case 'g'
+    color = [0 1 0];
+   case 'b'
+    color = [0 0 1];
+   case 'w'
+    color = [1 1 1];
+   case 'k'
+    color = [0 0 0];
+  end
+end
+if ~ischar(color)
+  gray = 0.30*color(1) + 0.59*color(2) + 0.11*color(3);
+end
+
+function newArray = LocalMapToGray(inArray);
+n = length(inArray);
+newArray = cell(n,1);
+for k=1:n
+  color = inArray{k};
+  if ~isempty(color)
+    color = LocalMapToGray1(color);
+  end
+  if isempty(color) | ischar(color)
+    newArray{k} = color;
+  else
+    newArray{k} = [color color color];
+  end
+end
+
+function newArray = LocalMapColorToStyle(inArray);
+inArray = LocalGetAsCell(inArray,'Color');
+n = length(inArray);
+newArray = cell(n,1);
+styles = {'-','--',':','-.'};
+uniques = [];
+nstyles = length(styles);
+for k=1:n
+  gray = LocalMapToGray1(inArray{k});
+  if isempty(gray) | ischar(gray) | gray < .05
+    newArray{k} = '-';
+  else
+    if ~isempty(uniques) & any(gray == uniques)
+      ind = find(gray==uniques);
+    else
+      uniques = [uniques gray];
+      ind = length(uniques);
+    end
+    newArray{k} = styles{mod(ind-1,nstyles)+1};
+  end
+end
+
+function newArray = LocalMapCData(inArray);
+n = length(inArray);
+newArray = cell(n,1);
+for k=1:n
+  color = inArray{k};
+  if (ndims(color) == 3) & isa(color,'double')
+    gray = 0.30*color(:,:,1) + 0.59*color(:,:,2) + 0.11*color(:,:,3);
+    color(:,:,1) = gray;
+    color(:,:,2) = gray;
+    color(:,:,3) = gray;
+  end
+  newArray{k} = color;
+end
+
+function outData = LocalUpdateColors(inArray, prop, inData)
+value = LocalGetAsCell(inArray,prop);
+outData.objs = {inData.objs{:}, inArray};
+outData.prop = {inData.prop{:}, {prop}};
+outData.values = {inData.values{:}, value};
+if (~isempty(value))
+  if strcmp(prop,'CData') 
+    value = LocalMapCData(value);
+  else
+    value = LocalMapToGray(value);
+  end
+  set(inArray,{prop},value);
+end
+
+function bool = LocalIsPositiveScalar(value)
+bool = isnumeric(value) & ...
+       prod(size(value)) == 1 & ...
+       value > 0;
+
+function value = LocalToNum(value,auto)
+if ischar(value)
+  if strcmp(value,'auto')
+    value = auto;
+  else
+    value = str2num(value);
+  end
+end
+
+%convert a struct to {field1,val1,field2,val2,...}
+function c = LocalToCell(s)
+f = fieldnames(s);
+v = struct2cell(s);
+opts = cell(2,length(f));
+opts(1,:) = f;
+opts(2,:) = v;
+c = {opts{:}};
+
+function c = LocalIsHG(obj,hgtype)
+c = 0;
+if (length(obj) == 1) & ishandle(obj) 
+  c = strcmp(get(obj,'type'),hgtype);
+end
+
+function c = LocalHas3DPlot(a)
+zticks = LocalGetAsCell(a,'ZTickLabel');
+c = 0;
+for k=1:length(zticks)
+  if ~isempty(zticks{k})
+    c = 1;
+    return;
+  end
+end
+
+function r = LocalUnionRect(r1,r2)
+if isempty(r1)
+  r = r2;
+elseif isempty(r2)
+  r = r1;
+elseif max(r2(3:4)) > 0
+  left = min(r1(1),r2(1));
+  bot = min(r1(2),r2(2));
+  right = max(r1(1)+r1(3),r2(1)+r2(3));
+  top = max(r1(2)+r1(4),r2(2)+r2(4));
+  r = [left bot right-left top-bot];
+else
+  r = r1;
+end
+
+function c = LocalLabelsMatchTicks(labs,ticks)
+c = 0;
+try
+  t1 = num2str(ticks(1));
+  n = length(ticks);
+  tend = num2str(ticks(n));
+  c = strncmp(labs(1),t1,length(labs(1))) & ...
+      strncmp(labs(n),tend,length(labs(n)));
+end
+
+function r = LocalAxesTightBoundingBox(axesR, a)
+r = [];
+atext = findall(a,'type','text','visible','on');
+if ~isempty(atext)
+  set(atext,'units','points');
+  res=LocalGetAsCell(atext,'extent');
+  for n=1:length(atext)
+    r = LocalUnionRect(r,res{n});
+  end
+end
+if strcmp(get(a,'visible'),'on')
+  r = LocalUnionRect(r,[0 0 axesR(3:4)]);
+  oldunits = get(a,'fontunits');
+  set(a,'fontunits','points');
+  label = text(0,0,'','parent',a,...
+	       'units','points',...
+	       'fontsize',get(a,'fontsize'),...
+	       'fontname',get(a,'fontname'),...
+	       'fontweight',get(a,'fontweight'),...
+	       'fontangle',get(a,'fontangle'),...
+	       'visible','off');
+  fs = get(a,'fontsize');
+
+  % handle y axis tick labels
+  ry = [0 -fs/2 0 axesR(4)+fs];
+  ylabs = get(a,'yticklabels');
+  yticks = get(a,'ytick');
+  maxw = 0;
+  if ~isempty(ylabs)
+    for n=1:size(ylabs,1)
+      set(label,'string',ylabs(n,:));
+      ext = get(label,'extent');
+      maxw = max(maxw,ext(3));
+    end
+    if ~LocalLabelsMatchTicks(ylabs,yticks) & ...
+	  strcmp(get(a,'xaxislocation'),'bottom')
+      ry(4) = ry(4) + 1.5*ext(4);
+    end
+    if strcmp(get(a,'yaxislocation'),'left')
+      ry(1) = -(maxw+5);
+    else
+      ry(1) = axesR(3);
+    end
+    ry(3) = maxw+5;
+    r = LocalUnionRect(r,ry);
+  end
+
+  % handle x axis tick labels
+  rx = [0 0 0 fs+5];
+  xlabs = get(a,'xticklabels');
+  xticks = get(a,'xtick');
+  if ~isempty(xlabs)
+    if strcmp(get(a,'xaxislocation'),'bottom')
+      rx(2) = -(fs+5);
+      if ~LocalLabelsMatchTicks(xlabs,xticks);
+	rx(4) = rx(4) + 2*fs;
+	rx(2) = rx(2) - 2*fs;
+      end
+    else
+      rx(2) = axesR(4);
+      % exponent is still below axes
+      if ~LocalLabelsMatchTicks(xlabs,xticks);
+	rx(4) = rx(4) + axesR(4) + 2*fs;
+	rx(2) = -2*fs;
+      end
+    end
+    set(label,'string',xlabs(1,:));
+    ext1 = get(label,'extent');
+    rx(1) = -ext1(3)/2;
+    set(label,'string',xlabs(size(xlabs,1),:));
+    ext2 = get(label,'extent');
+    rx(3) = axesR(3) + (ext2(3) + ext1(3))/2;
+    r = LocalUnionRect(r,rx);
+  end
+  set(a,'fontunits',oldunits);
+  delete(label);
+end
+
+function c = LocalManualAxesMode(old, allAxes, base)
+xs = ['X' base];
+ys = ['Y' base];
+zs = ['Z' base];
+oldXMode = LocalGetAsCell(allAxes,xs);
+oldYMode = LocalGetAsCell(allAxes,ys);
+oldZMode = LocalGetAsCell(allAxes,zs);
+old = LocalPushOldData(old, allAxes, {xs}, oldXMode);
+old = LocalPushOldData(old, allAxes, {ys}, oldYMode);
+old = LocalPushOldData(old, allAxes, {zs}, oldZMode);
+set(allAxes,xs,'manual');
+set(allAxes,ys,'manual');
+set(allAxes,zs,'manual');
+c = old;
+
+function val = LocalCheckAuto(val, auto)
+if ischar(val) & strcmp(val,'auto')
+  val = auto;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/.svn/text-base/imxy.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function imxy(mat)
+imagesc(mat)
+axis xy
+set(gcf,'Color',[0 0 .001])
+set(gca,'XColor',[1 1 1] *.5,'YColor',[1 1 1] *.5)
+colormap(bone)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/.svn/text-base/printme.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function printme(width)
+
+set(gcf, 'PaperUnits', 'centimeters');
+papersize = get(gcf, 'PaperSize');
+paperratio = papersize(2) / papersize(1);
+set(gcf, 'PaperSize', [1 paperratio] * width);
+set(gcf, 'Renderer', 'painters')
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/.svn/text-base/rotateticklabel.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+function th=rotateticklabel(h,rot,demo)
+%ROTATETICKLABEL rotates tick labels
+%   TH=ROTATETICKLABEL(H,ROT) is the calling form where H is a handle to
+%   the axis that contains the XTickLabels that are to be rotated. ROT is
+%   an optional parameter that specifies the angle of rotation. The default
+%   angle is 90. TH is a handle to the text objects created. For long
+%   strings such as those produced by datetick, you may have to adjust the
+%   position of the axes so the labels don't get cut off.
+%
+%   Of course, GCA can be substituted for H if desired.
+%
+%   TH=ROTATETICKLABEL([],[],'demo') shows a demo figure.
+%
+%   Known deficiencies: if tick labels are raised to a power, the power
+%   will be lost after rotation.
+%
+%   See also datetick.
+
+%   Written Oct 14, 2005 by Andy Bliss
+%   Copyright 2005 by Andy Bliss
+
+%DEMO:
+if nargin==3
+    x=[now-.7 now-.3 now];
+    y=[20 35 15];
+    figure
+    plot(x,y,'.-')
+    datetick('x',0,'keepticks')
+    h=gca;
+    set(h,'position',[0.13 0.35 0.775 0.55])
+    rot=90;
+end
+
+%set the default rotation if user doesn't specify
+if nargin==1
+    rot=90;
+end
+%make sure the rotation is in the range 0:360 (brute force method)
+while rot>360
+    rot=rot-360;
+end
+while rot<0
+    rot=rot+360;
+end
+%get current tick labels
+a=get(h,'XTickLabel');
+%erase current tick labels from figure
+set(h,'XTickLabel',[]);
+%get tick label positions
+b=get(h,'XTick');
+c=get(h,'YTick');
+%make new tick labels
+if rot<180
+    th=text(b,repmat(c(1)-.1*(c(2)-c(1)),length(b),1),a,'HorizontalAlignment','right','rotation',rot);
+else
+    th=text(b,repmat(c(1)-.1*(c(2)-c(1)),length(b),1),a,'HorizontalAlignment','left','rotation',rot);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/.svn/text-base/uimage.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,132 @@
+function h = uimage(varargin)
+%UIMAGE  Display image with uneven axis.
+%   UIMAGE(X,Y,C) displays matrix C as an image, using the vectors X and
+%   Y to specify the X and Y coordinates. X and Y may be unevenly spaced
+%   vectors, but must be increasing. The size of C must be LENGTH(Y)*
+%   LENGTH(X). (Most probably you'll want to display C' instead of C).
+%
+%   Contrary to Matlab's original IMAGE function, here the vectors X and Y
+%   do not need to be linearly spaced. Whereas IMAGE linearly interpolates
+%   the X-axis between X(1) and X(end), ignoring all other values (idem
+%   for Y), UIMAGE allows for X and/or Y to be unevenly spaced vectors, by
+%   locally stretching the matrix C (ie, by duplicating some elements of C)
+%   for larger X and/or Y intervals.
+%
+%   The syntax for UIMAGE(X,Y,C,...) is the same as IMAGE(X,Y,C,...)
+%   (all the remaining arguments, eg 'PropertyName'-PropertyValue pairs,
+%   are passed to IMAGE). See IMAGE for details.
+%
+%   Use UIMAGESC to scale the data using the full colormap. The syntax for
+%   UIMAGESC(X,Y,C,...) is the same as IMAGESC(X,Y,C,...).
+%
+%   Typical uses:
+%      - Plotting a spatio-temporal diagram (T,X), with unevenly spaced
+%      time intervals for T (eg, when some values are missing, or when
+%      using a non-constant sampling rate).
+%      - Plotting a set of power spectra with frequency in log-scale.
+%
+%   h = UIMAGE(X,Y,C,...) returns a handle to the image.
+%
+%   Example:
+%     c = randn(50,20);         % Random 50x20 matrix
+%     x = logspace(1,3,50);     % log-spaced X-axis, between 10 and 1000
+%     y = linspace(3,8,20);     % lin-spaced Y-axis, between 3 and 8
+%     uimagesc(x,y,c');         % displays the matrix
+%
+%   F. Moisy
+%   Revision: 1.03,  Date: 2006/06/14.
+%
+%   See also IMAGE, IMAGESC, UIMAGESC.
+
+
+% History:
+% 2006/06/12: v1.00, first version.
+% 2006/06/14: v1.03, minor bug fixed; works in ML6.
+
+error(nargchk(3,inf,nargin));
+
+% maximum number of matrix elements to interpolate the uneven axis
+% (typically between 500 and 5000):
+nmax = 2000; 
+
+x = varargin{1};
+y = varargin{2};
+c = varargin{3};
+
+if any(diff(x)<=0) || any(diff(y)<=0)
+    error('The X and Y axis should be increasing.');
+end
+
+dx = min(diff(x));                   % smallest interval for X
+dy = min(diff(y));                   % smallest interval for Y
+
+% test if X and Y are linearly spaced (to within 10^-12):
+evenx = all(abs(diff(x)/dx-1)<1e-12);     % true if X is linearly spaced
+eveny = all(abs(diff(y)/dy-1)<1e-12);     % true if Y is linearly spaced
+
+
+if evenx && eveny         % X and Y both evenly spaced
+
+    xe = x;
+    ye = y;
+    ce = c;
+
+elseif evenx && ~eveny    % X even and Y uneven
+    
+    nx = length(x);
+    xe = x;
+
+    ny = ceil(1 + (y(end) - y(1))/dy);   % number of points for Y
+    ny = min(ny, nmax);
+    ye = linspace(y(1), y(end), ny);
+
+    ce = zeros(ny,nx);
+
+    for j=1:ny
+        indj = find(y<=ye(j));
+        ce(j,1:nx) = c(indj(end), 1:nx);
+    end;
+
+elseif ~evenx && eveny    % X uneven and Y even
+    
+    nx = ceil(1 + (x(end) - x(1))/dx);   % number of points for X
+    nx = min(nx, nmax);
+    xe = linspace(x(1), x(end), nx);
+
+    ny = length(y);
+    ye = y;
+
+    ce = zeros(ny,nx);
+
+    for i=1:nx
+        indi = find(x<=xe(i));
+        ce(1:ny,i) = c(1:ny, indi(end));
+    end;
+
+elseif ~evenx && ~eveny   % X and Y both uneven
+    
+    nx = ceil(1 + (x(end) - x(1))/dx);   % number of points for X
+    nx = min(nx, nmax);
+    xe = linspace(x(1), x(end), nx);
+
+    ny = ceil(1 + (y(end) - y(1))/dy);   % number of points for Y
+    ny = min(ny, nmax);
+    ye = linspace(y(1), y(end), ny);
+
+    ce = zeros(ny,nx);
+
+    for i=1:nx
+        for j=1:ny
+            indi = find(x<=xe(i));
+            indj = find(y<=ye(j));
+            ce(j,i) = c(indi(end), indj(end));
+        end;
+    end;
+
+end
+
+hh = image(xe, ye, ce, varargin{4:end});
+
+if nargout>0
+    h = hh;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/.svn/text-base/uimagesc.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+function h = uimagesc(varargin)
+%UIMAGESC  Display scaled image with uneven axis.
+%   UIMAGESC(...) is the same as UIMAGE(...) except the data is scaled
+%   to use the full colormap. See UIMAGE for details.
+%
+%   Note: UIMAGESC is based on Matlab's original IMAGESC, Revision 5.11.4.5.
+%   UIMAGESC simply calls UIMAGE with a scaled colormap.
+% 
+%   F. Moisy - adapted from TMW
+%   Revision: 1.01,  Date: 2006/06/13.
+%
+%   See also IMAGE, IMAGESC, UIMAGE.
+
+% History:
+% 2006/06/12: v1.00, first version.
+
+clim = [];
+switch (nargin),
+  case 0,
+    hh = uimage('CDataMapping','scaled');
+  case 1,
+    hh = uimage(varargin{1},'CDataMapping','scaled');
+  case 3,
+    hh = uimage(varargin{:},'CDataMapping','scaled');
+  otherwise,
+
+    % Determine if last input is clim
+    if isequal(size(varargin{end}),[1 2])
+      str = false(length(varargin),1);
+      for n=1:length(varargin)
+        str(n) = ischar(varargin{n});
+      end
+      str = find(str);
+      if isempty(str) || (rem(length(varargin)-min(str),2)==0),
+        clim = varargin{end};
+        varargin(end) = []; % Remove last cell
+      else
+        clim = [];
+      end
+    else
+      clim = [];
+    end
+    hh = uimage(varargin{:},'CDataMapping','scaled');
+end
+
+% Get the parent Axes of the image
+cax = ancestor(hh,'axes');
+
+if ~isempty(clim),
+  set(cax,'CLim',clim)
+elseif ~ishold(cax),
+  set(cax,'CLimMode','auto')
+end
+
+if nargout > 0
+    h = hh;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/addmax.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,19 @@
+function addmax(varargin)
+if length(varargin)>0 && strcmp(varargin,'rows')
+    dimension = 2;
+else
+    dimension = 1;
+end
+
+chil=get(gca,'children');
+z = get(chil(1),'CData');
+x = get(chil(1),'XData');
+[maxind, maxind] = max(z,[],dimension);
+
+if length(x) == 2
+    x = x(1):x(2);
+end
+
+hold on
+m = plot(x, maxind, '.k','Erasemode','xor')
+hold off
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/exportfig.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,991 @@
+function varargout = exportfig(varargin)
+%EXPORTFIG  Export a figure.
+%   EXPORTFIG(H, FILENAME) writes the figure H to FILENAME.  H is
+%   a figure handle and FILENAME is a string that specifies the
+%   name of the output file.
+%
+%   EXPORTFIG(H, FILENAME, OPTIONS) writes the figure H to FILENAME
+%   with options initially specified by the structure OPTIONS. The
+%   field names of OPTIONS must be legal parameters listed below
+%   and the field values must be legal values for the corresponding
+%   parameter. Default options can be set in releases prior to R12
+%   by storing the OPTIONS structure in the root object's appdata
+%   with the command 
+%      setappdata(0,'exportfigdefaults', OPTIONS) 
+%   and for releases after R12 by setting the preference with the
+%   command 
+%      setpref('exportfig', 'defaults', OPTIONS) 
+%
+%   EXPORTFIG(...,PARAM1,VAL1,PARAM2,VAL2,...) specifies
+%   parameters that control various characteristics of the output
+%   file. Any parameter value can be the string 'auto' which means
+%   the parameter uses the default factory behavior, overriding
+%   any other default for the parameter.
+%
+%   Format Paramter:
+%     'Format'  a string
+%          specifies the output format. Defaults to 'eps'. For a
+%          list of export formats type 'help print'.
+%     'Preview' one of the strings 'none', 'tiff'
+%          specifies a preview for EPS files. Defaults to 'none'.
+%
+%   Size Parameters:
+%     'Width'   a positive scalar
+%          specifies the width in the figure's PaperUnits
+%     'Height'  a positive scalar
+%          specifies the height in the figure's PaperUnits
+%     'Bounds' one of the strings 'tight', 'loose'
+%          specifies a tight or loose bounding box. Defaults to 'tight'.
+%     'Reference' an axes handle or a string
+%          specifies that the width and height parameters
+%          are relative to the given axes. If a string is
+%          specified then it must evaluate to an axes handle.
+%
+%     Specifying only one dimension sets the other dimension
+%     so that the exported aspect ratio is the same as the
+%     figure's or reference axes' current aspect ratio. 
+%     If neither dimension is specified the size defaults to 
+%     the width and height from the figure's or reference
+%     axes' size. Tight bounding boxes are only computed for
+%     2-D views and in that case the computed bounds enclose all
+%     text objects.
+%           
+%   Rendering Parameters:
+%     'Color'     one of the strings 'bw', 'gray', 'cmyk'
+%         'bw'    specifies that lines and text are exported in
+%                 black and all other objects in grayscale
+%         'gray'  specifies that all objects are exported in grayscale
+%         'rgb'   specifies that all objects are exported in color
+%                 using the RGB color space
+%         'cmyk'  specifies that all objects are exported in color
+%                 using the CMYK color space
+%     'Renderer'  one of 'painters', 'zbuffer', 'opengl'
+%         specifies the renderer to use
+%     'Resolution'   a positive scalar
+%         specifies the resolution in dots-per-inch.
+%     'LockAxes'  one of 0 or 1
+%         specifies that all axes limits and ticks should be fixed
+%         while exporting.
+%     
+%     The default color setting is 'bw'.
+%
+%   Font Parameters:
+%     'FontMode'     one of the strings 'scaled', 'fixed'
+%     'FontSize'     a positive scalar
+%          in 'scaled' mode multiplies with the font size of each
+%          text object to obtain the exported font size
+%          in 'fixed' mode specifies the font size of all text
+%          objects in points
+%     'DefaultFixedFontSize' a positive scalar
+%          in 'fixed' mode specified the default font size in
+%          points
+%     'FontSizeMin' a positive scalar
+%          specifies the minimum font size allowed after scaling
+%     'FontSizeMax' a positive scalar
+%          specifies the maximum font size allowed after scaling
+%     'FontEncoding' one of the strings 'latin1', 'adobe'
+%          specifies the character encoding of the font
+%     'SeparateText' one of 0 or 1
+%          specifies that the text objects are stored in separate
+%          file as EPS with the base filename having '_t' appended.
+%
+%     If FontMode is 'scaled' but FontSize is not specified then a
+%     scaling factor is computed from the ratio of the size of the
+%     exported figure to the size of the actual figure.
+%
+%     The default 'FontMode' setting is 'scaled'.
+%
+%   Line Width Parameters:
+%     'LineMode'     one of the strings 'scaled', 'fixed'
+%     'LineWidth'    a positive scalar
+%     'DefaultFixedLineWidth' a positive scalar
+%     'LineWidthMin' a positive scalar
+%          specifies the minimum line width allowed after scaling
+%     'LineWidthMax' a positive scalar
+%          specifies the maximum line width allowed after scaling
+%     The semantics of 'Line' parameters are exactly the
+%     same as the corresponding 'Font' parameters, except that
+%     they apply to line widths instead of font sizes.
+%
+%   Style Map Parameter:
+%     'LineStyleMap'    one of [], 'bw', or a function name or handle
+%          specifies how to map line colors to styles. An empty
+%          style map means styles are not changed. The style map
+%          'bw' is a built-in mapping that maps lines with the same
+%          color to the same style and otherwise cycles through the
+%          available styles. A user-specified map is a function
+%          that takes as input a cell array of line objects and
+%          outputs a cell array of line style strings. The default
+%          map is [].
+%      
+%   Examples:
+%     exportfig(gcf,'fig1.eps','height',3);
+%       Exports the current figure to the file named 'fig1.eps' with
+%       a height of 3 inches (assuming the figure's PaperUnits is 
+%       inches) and an aspect ratio the same as the figure's aspect
+%       ratio on screen.
+%
+%     opts = struct('FontMode','fixed','FontSize',10,'height',3);
+%     exportfig(gcf, 'fig2.eps', opts, 'height', 5);
+%       Exports the current figure to 'fig2.eps' with all
+%       text in 10 point fonts and with height 5 inches.
+%
+%   See also PREVIEWFIG, APPLYTOFIG, RESTOREFIG, PRINT.
+
+%  Copyright 2000 Ben Hinkle
+%  Email bug reports and comments to bhinkle@mathworks.com
+
+if (nargin < 2)
+  error('Too few input arguments');
+end
+
+% exportfig(H, filename, [options,] ...)
+H = varargin{1};
+if ~LocalIsHG(H,'figure')
+  error('First argument must be a handle to a figure.');
+end
+filename = varargin{2};
+if ~ischar(filename)
+  error('Second argument must be a string.');
+end
+paramPairs = {varargin{3:end}};
+if nargin > 2
+  if isstruct(paramPairs{1})
+    pcell = LocalToCell(paramPairs{1});
+    paramPairs = {pcell{:}, paramPairs{2:end}};
+  end
+end
+verstr = version;
+majorver = str2num(verstr(1));
+defaults = [];
+if majorver > 5
+  if ispref('exportfig','defaults')
+    defaults = getpref('exportfig','defaults');
+  end
+elseif exist('getappdata')
+  defaults = getappdata(0,'exportfigdefaults');
+end
+if ~isempty(defaults)
+  dcell = LocalToCell(defaults);
+  paramPairs = {dcell{:}, paramPairs{:}};
+end
+
+% Do some validity checking on param-value pairs
+if (rem(length(paramPairs),2) ~= 0)
+  error(['Invalid input syntax. Optional parameters and values' ...
+	 ' must be in pairs.']);
+end
+
+auto.format = 'eps';
+auto.preview = 'none';
+auto.width = -1;
+auto.height = -1;
+auto.color = 'bw';
+auto.defaultfontsize=10;
+auto.fontsize = -1;
+auto.fontmode='scaled';
+auto.fontmin = 8;
+auto.fontmax = 60;
+auto.defaultlinewidth = 1.0;
+auto.linewidth = -1;
+auto.linemode=[];
+auto.linemin = 0.5;
+auto.linemax = 100;
+auto.fontencoding = 'latin1';
+auto.renderer = [];
+auto.resolution = [];
+auto.stylemap = [];
+auto.applystyle = 0;
+auto.refobj = -1;
+auto.bounds = 'tight';
+explicitbounds = 0;
+auto.lockaxes = 1;
+auto.separatetext = 0;
+opts = auto;
+
+% Process param-value pairs
+args = {};
+for k = 1:2:length(paramPairs)
+  param = lower(paramPairs{k});
+  if ~ischar(param)
+    error('Optional parameter names must be strings');
+  end
+  value = paramPairs{k+1};
+  
+  switch (param)
+   case 'format'
+    opts.format = LocalCheckAuto(lower(value),auto.format);
+    if strcmp(opts.format,'preview')
+      error(['Format ''preview'' no longer supported. Use PREVIEWFIG' ...
+	     ' instead.']);
+    end
+   case 'preview'
+    opts.preview = LocalCheckAuto(lower(value),auto.preview);
+    if ~strcmp(opts.preview,{'none','tiff'})
+      error('Preview must be ''none'' or ''tiff''.');
+    end
+   case 'width'
+    opts.width = LocalToNum(value, auto.width);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.width)
+	error('Width must be a numeric scalar > 0');
+      end
+    end
+   case 'height'
+    opts.height = LocalToNum(value, auto.height);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if(~LocalIsPositiveScalar(opts.height))
+	error('Height must be a numeric scalar > 0');
+      end
+    end
+   case 'color'
+    opts.color = LocalCheckAuto(lower(value),auto.color);
+    if ~strcmp(opts.color,{'bw','gray','rgb','cmyk'})
+      error('Color must be ''bw'', ''gray'',''rgb'' or ''cmyk''.');
+    end
+   case 'fontmode'
+    opts.fontmode = LocalCheckAuto(lower(value),auto.fontmode);
+    if ~strcmp(opts.fontmode,{'scaled','fixed'})
+      error('FontMode must be ''scaled'' or ''fixed''.');
+    end
+   case 'fontsize'
+    opts.fontsize = LocalToNum(value,auto.fontsize);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.fontsize)
+	error('FontSize must be a numeric scalar > 0');
+      end
+    end
+   case 'defaultfixedfontsize'
+    opts.defaultfontsize = LocalToNum(value,auto.defaultfontsize);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.defaultfontsize)
+	error('DefaultFixedFontSize must be a numeric scalar > 0');
+      end
+    end
+   case 'fontsizemin'
+    opts.fontmin = LocalToNum(value,auto.fontmin);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.fontmin)
+	error('FontSizeMin must be a numeric scalar > 0');
+      end
+    end
+   case 'fontsizemax'
+    opts.fontmax = LocalToNum(value,auto.fontmax);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.fontmax)
+	error('FontSizeMax must be a numeric scalar > 0');
+      end
+    end
+   case 'fontencoding'
+    opts.fontencoding = LocalCheckAuto(lower(value),auto.fontencoding);
+    if ~strcmp(opts.fontencoding,{'latin1','adobe'})
+      error('FontEncoding must be ''latin1'' or ''adobe''.');
+    end
+   case 'linemode'
+    opts.linemode = LocalCheckAuto(lower(value),auto.linemode);
+    if ~strcmp(opts.linemode,{'scaled','fixed'})
+      error('LineMode must be ''scaled'' or ''fixed''.');
+    end
+   case 'linewidth'
+    opts.linewidth = LocalToNum(value,auto.linewidth);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.linewidth)
+	error('LineWidth must be a numeric scalar > 0');
+      end
+    end
+   case 'defaultfixedlinewidth'
+    opts.defaultlinewidth = LocalToNum(value,auto.defaultlinewidth);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.defaultlinewidth)
+	error(['DefaultFixedLineWidth must be a numeric scalar >' ...
+	       ' 0']);
+      end
+    end
+   case 'linewidthmin'
+    opts.linemin = LocalToNum(value,auto.linemin);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.linemin)
+	error('LineWidthMin must be a numeric scalar > 0');
+      end
+    end
+   case 'linewidthmax'
+    opts.linemax = LocalToNum(value,auto.linemax);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~LocalIsPositiveScalar(opts.linemax)
+	error('LineWidthMax must be a numeric scalar > 0');
+      end
+    end
+   case 'linestylemap'
+    opts.stylemap = LocalCheckAuto(value,auto.stylemap);
+   case 'renderer'
+    opts.renderer = LocalCheckAuto(lower(value),auto.renderer);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~strcmp(opts.renderer,{'painters','zbuffer','opengl'})
+	error(['Renderer must be ''painters'', ''zbuffer'' or' ...
+	       ' ''opengl''.']);
+      end
+    end
+   case 'resolution'
+    opts.resolution = LocalToNum(value,auto.resolution);
+    if ~ischar(value) | ~strcmp(value,'auto')
+      if ~(isnumeric(value) & (prod(size(value)) == 1) & (value >= 0));
+	error('Resolution must be a numeric scalar >= 0');
+      end
+    end
+   case 'applystyle' % means to apply the options and not export
+    opts.applystyle = 1;
+   case 'reference'
+    if ischar(value)
+      if strcmp(value,'auto')
+	opts.refobj = auto.refobj;
+      else
+	opts.refobj = eval(value);
+      end
+    else
+      opts.refobj = value;
+    end
+    if ~LocalIsHG(opts.refobj,'axes')
+      error('Reference object must evaluate to an axes handle.');
+    end
+   case 'bounds'
+    opts.bounds = LocalCheckAuto(lower(value),auto.bounds);
+    explicitbounds = 1;
+    if ~strcmp(opts.bounds,{'tight','loose'})
+      error('Bounds must be ''tight'' or ''loose''.');
+    end
+   case 'lockaxes'
+    opts.lockaxes = LocalToNum(value,auto.lockaxes);
+   case 'separatetext'
+    opts.separatetext = LocalToNum(value,auto.separatetext);
+   otherwise
+    error(['Unrecognized option ' param '.']);
+  end
+end
+
+% make sure figure is up-to-date
+drawnow;
+
+allLines  = findall(H, 'type', 'line');
+allText   = findall(H, 'type', 'text');
+allAxes   = findall(H, 'type', 'axes');
+allImages = findall(H, 'type', 'image');
+allLights = findall(H, 'type', 'light');
+allPatch  = findall(H, 'type', 'patch');
+allSurf   = findall(H, 'type', 'surface');
+allRect   = findall(H, 'type', 'rectangle');
+allFont   = [allText; allAxes];
+allColor  = [allLines; allText; allAxes; allLights];
+allMarker = [allLines; allPatch; allSurf];
+allEdge   = [allPatch; allSurf];
+allCData  = [allImages; allPatch; allSurf];
+
+old.objs = {};
+old.prop = {};
+old.values = {};
+
+% Process format
+if strncmp(opts.format,'eps',3) & ~strcmp(opts.preview,'none')
+  args = {args{:}, ['-' opts.preview]};
+end
+
+hadError = 0;
+oldwarn = warning;
+try
+
+  % lock axes limits, ticks and labels if requested
+  if opts.lockaxes
+    old = LocalManualAxesMode(old, allAxes, 'TickMode');
+    old = LocalManualAxesMode(old, allAxes, 'TickLabelMode');
+    old = LocalManualAxesMode(old, allAxes, 'LimMode');
+  end  
+
+  % Process size parameters
+  figurePaperUnits = get(H, 'PaperUnits');
+  oldFigureUnits = get(H, 'Units');
+  oldFigPos = get(H,'Position');
+  set(H, 'Units', figurePaperUnits);
+  figPos = get(H,'Position');
+  refsize = figPos(3:4);
+  if opts.refobj ~= -1
+    oldUnits = get(opts.refobj, 'Units');
+    set(opts.refobj, 'Units', figurePaperUnits);
+    r = get(opts.refobj, 'Position');
+    refsize = r(3:4);
+    set(opts.refobj, 'Units', oldUnits);
+  end
+  aspectRatio = refsize(1)/refsize(2);
+  if (opts.width == -1) & (opts.height == -1)
+    opts.width = refsize(1);
+    opts.height = refsize(2);
+  elseif (opts.width == -1)
+    opts.width = opts.height * aspectRatio;
+  elseif (opts.height == -1)
+    opts.height = opts.width / aspectRatio;
+  end
+  wscale = opts.width/refsize(1);
+  hscale = opts.height/refsize(2);
+  sizescale = min(wscale,hscale);
+  old = LocalPushOldData(old,H,'PaperPositionMode', ...
+			 get(H,'PaperPositionMode'));
+  set(H, 'PaperPositionMode', 'auto');
+  newPos = [figPos(1) figPos(2)+figPos(4)*(1-hscale) ...
+	    wscale*figPos(3) hscale*figPos(4)];
+  set(H, 'Position', newPos);
+  set(H, 'Units', oldFigureUnits);
+  
+  % process line-style map
+  if ~isempty(opts.stylemap) & ~isempty(allLines)
+    oldlstyle = LocalGetAsCell(allLines,'LineStyle');
+    old = LocalPushOldData(old, allLines, {'LineStyle'}, ...
+			   oldlstyle);
+    newlstyle = oldlstyle;
+    if ischar(opts.stylemap) & strcmpi(opts.stylemap,'bw')
+      newlstyle = LocalMapColorToStyle(allLines);
+    else
+      try
+	newlstyle = feval(opts.stylemap,allLines);
+      catch
+	warning(['Skipping stylemap. ' lasterr]);
+      end
+    end
+    set(allLines,{'LineStyle'},newlstyle);
+  end
+
+  % Process rendering parameters
+  switch (opts.color)
+   case {'bw', 'gray'}
+    if ~strcmp(opts.color,'bw') & strncmp(opts.format,'eps',3)
+      opts.format = [opts.format 'c'];
+    end
+    args = {args{:}, ['-d' opts.format]};
+    
+    %compute and set gray colormap
+    oldcmap = get(H,'Colormap');
+    newgrays = 0.30*oldcmap(:,1) + 0.59*oldcmap(:,2) + 0.11*oldcmap(:,3);
+    newcmap = [newgrays newgrays newgrays];
+    old = LocalPushOldData(old, H, 'Colormap', oldcmap);
+    set(H, 'Colormap', newcmap);
+
+    %compute and set ColorSpec and CData properties
+    old = LocalUpdateColors(allColor, 'color', old);
+    old = LocalUpdateColors(allAxes, 'xcolor', old);
+    old = LocalUpdateColors(allAxes, 'ycolor', old);
+    old = LocalUpdateColors(allAxes, 'zcolor', old);
+    old = LocalUpdateColors(allMarker, 'MarkerEdgeColor', old);
+    old = LocalUpdateColors(allMarker, 'MarkerFaceColor', old);
+    old = LocalUpdateColors(allEdge, 'EdgeColor', old);
+    old = LocalUpdateColors(allEdge, 'FaceColor', old);
+    old = LocalUpdateColors(allCData, 'CData', old);
+    
+   case {'rgb','cmyk'}
+    if strncmp(opts.format,'eps',3)
+      opts.format = [opts.format 'c'];
+      args = {args{:}, ['-d' opts.format]};
+      if strcmp(opts.color,'cmyk')
+	args = {args{:}, '-cmyk'};
+      end
+    else
+      args = {args{:}, ['-d' opts.format]};
+    end
+   otherwise
+    error('Invalid Color parameter');
+  end
+  if (~isempty(opts.renderer))
+    args = {args{:}, ['-' opts.renderer]};
+  end
+  if (~isempty(opts.resolution)) | ~strncmp(opts.format,'eps',3)
+    if isempty(opts.resolution)
+      opts.resolution = 0;
+    end
+    args = {args{:}, ['-r' int2str(opts.resolution)]};
+  end
+
+  % Process font parameters
+  if ~isempty(opts.fontmode)
+    oldfonts = LocalGetAsCell(allFont,'FontSize');
+    oldfontunits = LocalGetAsCell(allFont,'FontUnits');
+    set(allFont,'FontUnits','points');
+    switch (opts.fontmode)
+     case 'fixed'
+      if (opts.fontsize == -1)
+	set(allFont,'FontSize',opts.defaultfontsize);
+      else
+	set(allFont,'FontSize',opts.fontsize);
+      end
+     case 'scaled'
+      if (opts.fontsize == -1)
+	scale = sizescale;
+      else
+	scale = opts.fontsize;
+      end
+      newfonts = LocalScale(oldfonts,scale,opts.fontmin,opts.fontmax);
+      set(allFont,{'FontSize'},newfonts);
+     otherwise
+      error('Invalid FontMode parameter');
+    end
+    old = LocalPushOldData(old, allFont, {'FontSize'}, oldfonts);
+    old = LocalPushOldData(old, allFont, {'FontUnits'}, oldfontunits);
+  end
+  if strcmp(opts.fontencoding,'adobe') & strncmp(opts.format,'eps',3)
+    args = {args{:}, '-adobecset'};
+  end
+
+  % Process line parameters
+  if ~isempty(opts.linemode)
+    oldlines = LocalGetAsCell(allMarker,'LineWidth');
+    old = LocalPushOldData(old, allMarker, {'LineWidth'}, oldlines);
+    switch (opts.linemode)
+     case 'fixed'
+      if (opts.linewidth == -1)
+	set(allMarker,'LineWidth',opts.defaultlinewidth);
+      else
+	set(allMarker,'LineWidth',opts.linewidth);
+      end
+     case 'scaled'
+      if (opts.linewidth == -1)
+	scale = sizescale;
+      else
+	scale = opts.linewidth;
+      end
+      newlines = LocalScale(oldlines, scale, opts.linemin, opts.linemax);
+      set(allMarker,{'LineWidth'},newlines);
+    end
+  end
+
+  % adjust figure bounds to surround axes
+  if strcmp(opts.bounds,'tight')
+    if (~strncmp(opts.format,'eps',3) & LocalHas3DPlot(allAxes)) | ...
+	  (strncmp(opts.format,'eps',3) & opts.separatetext)
+      if (explicitbounds == 1)
+	warning(['Cannot compute ''tight'' bounds. Using ''loose''' ...
+		 ' bounds.']);
+      end
+      opts.bounds = 'loose';
+    end
+  end
+  warning('off');
+  if ~isempty(allAxes)
+    if strncmp(opts.format,'eps',3)
+      if strcmp(opts.bounds,'loose')
+	args = {args{:}, '-loose'};
+      end
+      old = LocalPushOldData(old,H,'Position', oldFigPos);
+    elseif strcmp(opts.bounds,'tight')
+      oldaunits = LocalGetAsCell(allAxes,'Units');
+      oldapos = LocalGetAsCell(allAxes,'Position');
+      oldtunits = LocalGetAsCell(allText,'units');
+      oldtpos = LocalGetAsCell(allText,'Position');
+      set(allAxes,'units','points');
+      apos = LocalGetAsCell(allAxes,'Position');
+      oldunits = get(H,'Units');
+      set(H,'units','points');
+      origfr = get(H,'position');
+      fr = [];
+      for k=1:length(allAxes)
+	if ~strcmpi(get(allAxes(k),'Tag'),'legend')
+	  axesR = apos{k};
+	  r = LocalAxesTightBoundingBox(axesR, allAxes(k));
+	  r(1:2) = r(1:2) + axesR(1:2);
+	  fr = LocalUnionRect(fr,r);
+	end
+      end
+      if isempty(fr)
+	fr = [0 0 origfr(3:4)];
+      end
+      for k=1:length(allAxes)
+	ax = allAxes(k);
+	r = apos{k};
+	r(1:2) = r(1:2) - fr(1:2);
+	set(ax,'Position',r);
+      end
+      old = LocalPushOldData(old, allAxes, {'Position'}, oldapos);
+      old = LocalPushOldData(old, allText, {'Position'}, oldtpos);
+      old = LocalPushOldData(old, allText, {'Units'}, oldtunits);
+      old = LocalPushOldData(old, allAxes, {'Units'}, oldaunits);
+      old = LocalPushOldData(old, H, 'Position', oldFigPos);
+      old = LocalPushOldData(old, H, 'Units', oldFigureUnits);
+      r = [origfr(1) origfr(2)+origfr(4)-fr(4) fr(3:4)];
+      set(H,'Position',r);
+    else
+      args = {args{:}, '-loose'};
+      old = LocalPushOldData(old,H,'Position', oldFigPos);
+    end
+  end
+  
+  % Process text in a separate file if needed
+  if opts.separatetext & ~opts.applystyle
+    % First hide all text and export
+    oldtvis = LocalGetAsCell(allText,'visible');
+    set(allText,'visible','off');
+    oldax = LocalGetAsCell(allAxes,'XTickLabel',1);
+    olday = LocalGetAsCell(allAxes,'YTickLabel',1);
+    oldaz = LocalGetAsCell(allAxes,'ZTickLabel',1);
+    null = cell(length(oldax),1);
+    [null{:}] = deal([]);
+    set(allAxes,{'XTickLabel'},null);
+    set(allAxes,{'YTickLabel'},null);
+    set(allAxes,{'ZTickLabel'},null);
+    print(H, filename, args{:});
+    set(allText,{'Visible'},oldtvis);
+    set(allAxes,{'XTickLabel'},oldax);
+    set(allAxes,{'YTickLabel'},olday);
+    set(allAxes,{'ZTickLabel'},oldaz);
+    % Now hide all non-text and export as eps in painters
+    [path, name, ext] = fileparts(filename);
+    tfile = fullfile(path,[name '_t.eps']);
+    tfile2 = fullfile(path,[name '_t2.eps']);
+    foundRenderer = 0;
+    for k=1:length(args)
+      if strncmp('-d',args{k},2)
+	args{k} = '-deps';
+      elseif strncmp('-zbuffer',args{k},8) | ...
+	    strncmp('-opengl', args{k},6)
+	args{k} = '-painters';
+	foundRenderer = 1;
+      end
+    end
+    if ~foundRenderer
+      args = {args{:}, '-painters'};
+    end
+    allNonText = [allLines; allLights; allPatch; ...
+		  allImages; allSurf; allRect];
+    oldvis = LocalGetAsCell(allNonText,'visible');
+    oldc = LocalGetAsCell(allAxes,'color');
+    oldaxg = LocalGetAsCell(allAxes,'XGrid');
+    oldayg = LocalGetAsCell(allAxes,'YGrid');
+    oldazg = LocalGetAsCell(allAxes,'ZGrid');
+    [null{:}] = deal('off');
+    set(allAxes,{'XGrid'},null);
+    set(allAxes,{'YGrid'},null);
+    set(allAxes,{'ZGrid'},null);
+    set(allNonText,'Visible','off');
+    set(allAxes,'Color','none');
+    print(H, tfile2, args{:});
+    set(allNonText,{'Visible'},oldvis);
+    set(allAxes,{'Color'},oldc);
+    set(allAxes,{'XGrid'},oldaxg);
+    set(allAxes,{'YGrid'},oldayg);
+    set(allAxes,{'ZGrid'},oldazg);
+    %hack up the postscript file
+    fid1 = fopen(tfile,'w');
+    fid2 = fopen(tfile2,'r');
+    line = fgetl(fid2);
+    while ischar(line)
+      if strncmp(line,'%%Title',7)
+	fprintf(fid1,'%s\n',['%%Title: ', tfile]);
+      elseif (length(line) < 3) 
+	fprintf(fid1,'%s\n',line);
+      elseif ~strcmp(line(end-2:end),' PR') & ...
+	    ~strcmp(line(end-1:end),' L')
+	fprintf(fid1,'%s\n',line);
+      end
+      line = fgetl(fid2);
+    end
+    fclose(fid1);
+    fclose(fid2);
+    delete(tfile2);
+    
+  elseif ~opts.applystyle
+    drawnow;
+    print(H, filename, args{:});
+  end
+  warning(oldwarn);
+  
+catch
+  warning(oldwarn);
+  hadError = 1;
+end
+
+% Restore figure settings
+if opts.applystyle
+  varargout{1} = old;
+else
+  for n=1:length(old.objs)
+    if ~iscell(old.values{n}) & iscell(old.prop{n})
+      old.values{n} = {old.values{n}};
+    end
+    set(old.objs{n}, old.prop{n}, old.values{n});
+  end
+end
+
+if hadError
+  error(deblank(lasterr));
+end
+
+%
+%  Local Functions
+%
+
+function outData = LocalPushOldData(inData, objs, prop, values)
+outData.objs = {objs, inData.objs{:}};
+outData.prop = {prop, inData.prop{:}};
+outData.values = {values, inData.values{:}};
+
+function cellArray = LocalGetAsCell(fig,prop,allowemptycell);
+cellArray = get(fig,prop);
+if nargin < 3
+  allowemptycell = 0;
+end
+if ~iscell(cellArray) & (allowemptycell | ~isempty(cellArray))
+  cellArray = {cellArray};
+end
+
+function newArray = LocalScale(inArray, scale, minv, maxv)
+n = length(inArray);
+newArray = cell(n,1);
+for k=1:n
+  newArray{k} = min(maxv,max(minv,scale*inArray{k}(1)));
+end
+
+function gray = LocalMapToGray1(color)
+gray = color;
+if ischar(color)
+  switch color(1)
+   case 'y'
+    color = [1 1 0];
+   case 'm'
+    color = [1 0 1];
+   case 'c'
+    color = [0 1 1];
+   case 'r'
+    color = [1 0 0];
+   case 'g'
+    color = [0 1 0];
+   case 'b'
+    color = [0 0 1];
+   case 'w'
+    color = [1 1 1];
+   case 'k'
+    color = [0 0 0];
+  end
+end
+if ~ischar(color)
+  gray = 0.30*color(1) + 0.59*color(2) + 0.11*color(3);
+end
+
+function newArray = LocalMapToGray(inArray);
+n = length(inArray);
+newArray = cell(n,1);
+for k=1:n
+  color = inArray{k};
+  if ~isempty(color)
+    color = LocalMapToGray1(color);
+  end
+  if isempty(color) | ischar(color)
+    newArray{k} = color;
+  else
+    newArray{k} = [color color color];
+  end
+end
+
+function newArray = LocalMapColorToStyle(inArray);
+inArray = LocalGetAsCell(inArray,'Color');
+n = length(inArray);
+newArray = cell(n,1);
+styles = {'-','--',':','-.'};
+uniques = [];
+nstyles = length(styles);
+for k=1:n
+  gray = LocalMapToGray1(inArray{k});
+  if isempty(gray) | ischar(gray) | gray < .05
+    newArray{k} = '-';
+  else
+    if ~isempty(uniques) & any(gray == uniques)
+      ind = find(gray==uniques);
+    else
+      uniques = [uniques gray];
+      ind = length(uniques);
+    end
+    newArray{k} = styles{mod(ind-1,nstyles)+1};
+  end
+end
+
+function newArray = LocalMapCData(inArray);
+n = length(inArray);
+newArray = cell(n,1);
+for k=1:n
+  color = inArray{k};
+  if (ndims(color) == 3) & isa(color,'double')
+    gray = 0.30*color(:,:,1) + 0.59*color(:,:,2) + 0.11*color(:,:,3);
+    color(:,:,1) = gray;
+    color(:,:,2) = gray;
+    color(:,:,3) = gray;
+  end
+  newArray{k} = color;
+end
+
+function outData = LocalUpdateColors(inArray, prop, inData)
+value = LocalGetAsCell(inArray,prop);
+outData.objs = {inData.objs{:}, inArray};
+outData.prop = {inData.prop{:}, {prop}};
+outData.values = {inData.values{:}, value};
+if (~isempty(value))
+  if strcmp(prop,'CData') 
+    value = LocalMapCData(value);
+  else
+    value = LocalMapToGray(value);
+  end
+  set(inArray,{prop},value);
+end
+
+function bool = LocalIsPositiveScalar(value)
+bool = isnumeric(value) & ...
+       prod(size(value)) == 1 & ...
+       value > 0;
+
+function value = LocalToNum(value,auto)
+if ischar(value)
+  if strcmp(value,'auto')
+    value = auto;
+  else
+    value = str2num(value);
+  end
+end
+
+%convert a struct to {field1,val1,field2,val2,...}
+function c = LocalToCell(s)
+f = fieldnames(s);
+v = struct2cell(s);
+opts = cell(2,length(f));
+opts(1,:) = f;
+opts(2,:) = v;
+c = {opts{:}};
+
+function c = LocalIsHG(obj,hgtype)
+c = 0;
+if (length(obj) == 1) & ishandle(obj) 
+  c = strcmp(get(obj,'type'),hgtype);
+end
+
+function c = LocalHas3DPlot(a)
+zticks = LocalGetAsCell(a,'ZTickLabel');
+c = 0;
+for k=1:length(zticks)
+  if ~isempty(zticks{k})
+    c = 1;
+    return;
+  end
+end
+
+function r = LocalUnionRect(r1,r2)
+if isempty(r1)
+  r = r2;
+elseif isempty(r2)
+  r = r1;
+elseif max(r2(3:4)) > 0
+  left = min(r1(1),r2(1));
+  bot = min(r1(2),r2(2));
+  right = max(r1(1)+r1(3),r2(1)+r2(3));
+  top = max(r1(2)+r1(4),r2(2)+r2(4));
+  r = [left bot right-left top-bot];
+else
+  r = r1;
+end
+
+function c = LocalLabelsMatchTicks(labs,ticks)
+c = 0;
+try
+  t1 = num2str(ticks(1));
+  n = length(ticks);
+  tend = num2str(ticks(n));
+  c = strncmp(labs(1),t1,length(labs(1))) & ...
+      strncmp(labs(n),tend,length(labs(n)));
+end
+
+function r = LocalAxesTightBoundingBox(axesR, a)
+r = [];
+atext = findall(a,'type','text','visible','on');
+if ~isempty(atext)
+  set(atext,'units','points');
+  res=LocalGetAsCell(atext,'extent');
+  for n=1:length(atext)
+    r = LocalUnionRect(r,res{n});
+  end
+end
+if strcmp(get(a,'visible'),'on')
+  r = LocalUnionRect(r,[0 0 axesR(3:4)]);
+  oldunits = get(a,'fontunits');
+  set(a,'fontunits','points');
+  label = text(0,0,'','parent',a,...
+	       'units','points',...
+	       'fontsize',get(a,'fontsize'),...
+	       'fontname',get(a,'fontname'),...
+	       'fontweight',get(a,'fontweight'),...
+	       'fontangle',get(a,'fontangle'),...
+	       'visible','off');
+  fs = get(a,'fontsize');
+
+  % handle y axis tick labels
+  ry = [0 -fs/2 0 axesR(4)+fs];
+  ylabs = get(a,'yticklabels');
+  yticks = get(a,'ytick');
+  maxw = 0;
+  if ~isempty(ylabs)
+    for n=1:size(ylabs,1)
+      set(label,'string',ylabs(n,:));
+      ext = get(label,'extent');
+      maxw = max(maxw,ext(3));
+    end
+    if ~LocalLabelsMatchTicks(ylabs,yticks) & ...
+	  strcmp(get(a,'xaxislocation'),'bottom')
+      ry(4) = ry(4) + 1.5*ext(4);
+    end
+    if strcmp(get(a,'yaxislocation'),'left')
+      ry(1) = -(maxw+5);
+    else
+      ry(1) = axesR(3);
+    end
+    ry(3) = maxw+5;
+    r = LocalUnionRect(r,ry);
+  end
+
+  % handle x axis tick labels
+  rx = [0 0 0 fs+5];
+  xlabs = get(a,'xticklabels');
+  xticks = get(a,'xtick');
+  if ~isempty(xlabs)
+    if strcmp(get(a,'xaxislocation'),'bottom')
+      rx(2) = -(fs+5);
+      if ~LocalLabelsMatchTicks(xlabs,xticks);
+	rx(4) = rx(4) + 2*fs;
+	rx(2) = rx(2) - 2*fs;
+      end
+    else
+      rx(2) = axesR(4);
+      % exponent is still below axes
+      if ~LocalLabelsMatchTicks(xlabs,xticks);
+	rx(4) = rx(4) + axesR(4) + 2*fs;
+	rx(2) = -2*fs;
+      end
+    end
+    set(label,'string',xlabs(1,:));
+    ext1 = get(label,'extent');
+    rx(1) = -ext1(3)/2;
+    set(label,'string',xlabs(size(xlabs,1),:));
+    ext2 = get(label,'extent');
+    rx(3) = axesR(3) + (ext2(3) + ext1(3))/2;
+    r = LocalUnionRect(r,rx);
+  end
+  set(a,'fontunits',oldunits);
+  delete(label);
+end
+
+function c = LocalManualAxesMode(old, allAxes, base)
+xs = ['X' base];
+ys = ['Y' base];
+zs = ['Z' base];
+oldXMode = LocalGetAsCell(allAxes,xs);
+oldYMode = LocalGetAsCell(allAxes,ys);
+oldZMode = LocalGetAsCell(allAxes,zs);
+old = LocalPushOldData(old, allAxes, {xs}, oldXMode);
+old = LocalPushOldData(old, allAxes, {ys}, oldYMode);
+old = LocalPushOldData(old, allAxes, {zs}, oldZMode);
+set(allAxes,xs,'manual');
+set(allAxes,ys,'manual');
+set(allAxes,zs,'manual');
+c = old;
+
+function val = LocalCheckAuto(val, auto)
+if ischar(val) & strcmp(val,'auto')
+  val = auto;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/imxy.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function imxy(mat)
+imagesc(mat)
+axis xy
+set(gcf,'Color',[0 0 .001])
+set(gca,'XColor',[1 1 1] *.5,'YColor',[1 1 1] *.5)
+colormap(bone)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/printme.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function printme(width)
+
+set(gcf, 'PaperUnits', 'centimeters');
+papersize = get(gcf, 'PaperSize');
+paperratio = papersize(2) / papersize(1);
+set(gcf, 'PaperSize', [1 paperratio] * width);
+set(gcf, 'Renderer', 'painters')
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/rotateticklabel.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,58 @@
+function th=rotateticklabel(h,rot,demo)
+%ROTATETICKLABEL rotates tick labels
+%   TH=ROTATETICKLABEL(H,ROT) is the calling form where H is a handle to
+%   the axis that contains the XTickLabels that are to be rotated. ROT is
+%   an optional parameter that specifies the angle of rotation. The default
+%   angle is 90. TH is a handle to the text objects created. For long
+%   strings such as those produced by datetick, you may have to adjust the
+%   position of the axes so the labels don't get cut off.
+%
+%   Of course, GCA can be substituted for H if desired.
+%
+%   TH=ROTATETICKLABEL([],[],'demo') shows a demo figure.
+%
+%   Known deficiencies: if tick labels are raised to a power, the power
+%   will be lost after rotation.
+%
+%   See also datetick.
+
+%   Written Oct 14, 2005 by Andy Bliss
+%   Copyright 2005 by Andy Bliss
+
+%DEMO:
+if nargin==3
+    x=[now-.7 now-.3 now];
+    y=[20 35 15];
+    figure
+    plot(x,y,'.-')
+    datetick('x',0,'keepticks')
+    h=gca;
+    set(h,'position',[0.13 0.35 0.775 0.55])
+    rot=90;
+end
+
+%set the default rotation if user doesn't specify
+if nargin==1
+    rot=90;
+end
+%make sure the rotation is in the range 0:360 (brute force method)
+while rot>360
+    rot=rot-360;
+end
+while rot<0
+    rot=rot+360;
+end
+%get current tick labels
+a=get(h,'XTickLabel');
+%erase current tick labels from figure
+set(h,'XTickLabel',[]);
+%get tick label positions
+b=get(h,'XTick');
+c=get(h,'YTick');
+%make new tick labels
+if rot<180
+    th=text(b,repmat(c(1)-.1*(c(2)-c(1)),length(b),1),a,'HorizontalAlignment','right','rotation',rot);
+else
+    th=text(b,repmat(c(1)-.1*(c(2)-c(1)),length(b),1),a,'HorizontalAlignment','left','rotation',rot);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/uimage.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,132 @@
+function h = uimage(varargin)
+%UIMAGE  Display image with uneven axis.
+%   UIMAGE(X,Y,C) displays matrix C as an image, using the vectors X and
+%   Y to specify the X and Y coordinates. X and Y may be unevenly spaced
+%   vectors, but must be increasing. The size of C must be LENGTH(Y)*
+%   LENGTH(X). (Most probably you'll want to display C' instead of C).
+%
+%   Contrary to Matlab's original IMAGE function, here the vectors X and Y
+%   do not need to be linearly spaced. Whereas IMAGE linearly interpolates
+%   the X-axis between X(1) and X(end), ignoring all other values (idem
+%   for Y), UIMAGE allows for X and/or Y to be unevenly spaced vectors, by
+%   locally stretching the matrix C (ie, by duplicating some elements of C)
+%   for larger X and/or Y intervals.
+%
+%   The syntax for UIMAGE(X,Y,C,...) is the same as IMAGE(X,Y,C,...)
+%   (all the remaining arguments, eg 'PropertyName'-PropertyValue pairs,
+%   are passed to IMAGE). See IMAGE for details.
+%
+%   Use UIMAGESC to scale the data using the full colormap. The syntax for
+%   UIMAGESC(X,Y,C,...) is the same as IMAGESC(X,Y,C,...).
+%
+%   Typical uses:
+%      - Plotting a spatio-temporal diagram (T,X), with unevenly spaced
+%      time intervals for T (eg, when some values are missing, or when
+%      using a non-constant sampling rate).
+%      - Plotting a set of power spectra with frequency in log-scale.
+%
+%   h = UIMAGE(X,Y,C,...) returns a handle to the image.
+%
+%   Example:
+%     c = randn(50,20);         % Random 50x20 matrix
+%     x = logspace(1,3,50);     % log-spaced X-axis, between 10 and 1000
+%     y = linspace(3,8,20);     % lin-spaced Y-axis, between 3 and 8
+%     uimagesc(x,y,c');         % displays the matrix
+%
+%   F. Moisy
+%   Revision: 1.03,  Date: 2006/06/14.
+%
+%   See also IMAGE, IMAGESC, UIMAGESC.
+
+
+% History:
+% 2006/06/12: v1.00, first version.
+% 2006/06/14: v1.03, minor bug fixed; works in ML6.
+
+error(nargchk(3,inf,nargin));
+
+% maximum number of matrix elements to interpolate the uneven axis
+% (typically between 500 and 5000):
+nmax = 2000; 
+
+x = varargin{1};
+y = varargin{2};
+c = varargin{3};
+
+if any(diff(x)<=0) || any(diff(y)<=0)
+    error('The X and Y axis should be increasing.');
+end
+
+dx = min(diff(x));                   % smallest interval for X
+dy = min(diff(y));                   % smallest interval for Y
+
+% test if X and Y are linearly spaced (to within 10^-12):
+evenx = all(abs(diff(x)/dx-1)<1e-12);     % true if X is linearly spaced
+eveny = all(abs(diff(y)/dy-1)<1e-12);     % true if Y is linearly spaced
+
+
+if evenx && eveny         % X and Y both evenly spaced
+
+    xe = x;
+    ye = y;
+    ce = c;
+
+elseif evenx && ~eveny    % X even and Y uneven
+    
+    nx = length(x);
+    xe = x;
+
+    ny = ceil(1 + (y(end) - y(1))/dy);   % number of points for Y
+    ny = min(ny, nmax);
+    ye = linspace(y(1), y(end), ny);
+
+    ce = zeros(ny,nx);
+
+    for j=1:ny
+        indj = find(y<=ye(j));
+        ce(j,1:nx) = c(indj(end), 1:nx);
+    end;
+
+elseif ~evenx && eveny    % X uneven and Y even
+    
+    nx = ceil(1 + (x(end) - x(1))/dx);   % number of points for X
+    nx = min(nx, nmax);
+    xe = linspace(x(1), x(end), nx);
+
+    ny = length(y);
+    ye = y;
+
+    ce = zeros(ny,nx);
+
+    for i=1:nx
+        indi = find(x<=xe(i));
+        ce(1:ny,i) = c(1:ny, indi(end));
+    end;
+
+elseif ~evenx && ~eveny   % X and Y both uneven
+    
+    nx = ceil(1 + (x(end) - x(1))/dx);   % number of points for X
+    nx = min(nx, nmax);
+    xe = linspace(x(1), x(end), nx);
+
+    ny = ceil(1 + (y(end) - y(1))/dy);   % number of points for Y
+    ny = min(ny, nmax);
+    ye = linspace(y(1), y(end), ny);
+
+    ce = zeros(ny,nx);
+
+    for i=1:nx
+        for j=1:ny
+            indi = find(x<=xe(i));
+            indj = find(y<=ye(j));
+            ce(j,i) = c(indi(end), indj(end));
+        end;
+    end;
+
+end
+
+hh = image(xe, ye, ce, varargin{4:end});
+
+if nargout>0
+    h = hh;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/figures/uimagesc.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,57 @@
+function h = uimagesc(varargin)
+%UIMAGESC  Display scaled image with uneven axis.
+%   UIMAGESC(...) is the same as UIMAGE(...) except the data is scaled
+%   to use the full colormap. See UIMAGE for details.
+%
+%   Note: UIMAGESC is based on Matlab's original IMAGESC, Revision 5.11.4.5.
+%   UIMAGESC simply calls UIMAGE with a scaled colormap.
+% 
+%   F. Moisy - adapted from TMW
+%   Revision: 1.01,  Date: 2006/06/13.
+%
+%   See also IMAGE, IMAGESC, UIMAGE.
+
+% History:
+% 2006/06/12: v1.00, first version.
+
+clim = [];
+switch (nargin),
+  case 0,
+    hh = uimage('CDataMapping','scaled');
+  case 1,
+    hh = uimage(varargin{1},'CDataMapping','scaled');
+  case 3,
+    hh = uimage(varargin{:},'CDataMapping','scaled');
+  otherwise,
+
+    % Determine if last input is clim
+    if isequal(size(varargin{end}),[1 2])
+      str = false(length(varargin),1);
+      for n=1:length(varargin)
+        str(n) = ischar(varargin{n});
+      end
+      str = find(str);
+      if isempty(str) || (rem(length(varargin)-min(str),2)==0),
+        clim = varargin{end};
+        varargin(end) = []; % Remove last cell
+      else
+        clim = [];
+      end
+    else
+      clim = [];
+    end
+    hh = uimage(varargin{:},'CDataMapping','scaled');
+end
+
+% Get the parent Axes of the image
+cax = ancestor(hh,'axes');
+
+if ~isempty(clim),
+  set(cax,'CLim',clim)
+elseif ~ishold(cax),
+  set(cax,'CLimMode','auto')
+end
+
+if nargout > 0
+    h = hh;
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/.svn/all-wcprops	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,47 @@
+K 25
+svn:wc:ra_dav:version-url
+V 51
+/svnroot/!svn/ver/5883/matlabtoolboxes/misc/general
+END
+dpcore.mexmac
+K 25
+svn:wc:ra_dav:version-url
+V 65
+/svnroot/!svn/ver/1425/matlabtoolboxes/misc/general/dpcore.mexmac
+END
+qnormalise.m
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svnroot/!svn/ver/1425/matlabtoolboxes/misc/general/qnormalise.m
+END
+filecollection.m
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svnroot/!svn/ver/5883/matlabtoolboxes/misc/general/filecollection.m
+END
+qnorm.m
+K 25
+svn:wc:ra_dav:version-url
+V 59
+/svnroot/!svn/ver/1425/matlabtoolboxes/misc/general/qnorm.m
+END
+dpfast.m
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svnroot/!svn/ver/1425/matlabtoolboxes/misc/general/dpfast.m
+END
+dpcore.c
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svnroot/!svn/ver/1425/matlabtoolboxes/misc/general/dpcore.c
+END
+dpcore.mexmaci
+K 25
+svn:wc:ra_dav:version-url
+V 66
+/svnroot/!svn/ver/1425/matlabtoolboxes/misc/general/dpcore.mexmaci
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/.svn/entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,266 @@
+10
+
+dir
+7329
+https://parrot.dcs.qmul.ac.uk/svnroot/matlabtoolboxes/misc/general
+https://parrot.dcs.qmul.ac.uk/svnroot
+
+
+
+2009-05-01T16:56:49.073671Z
+5883
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+214cd2a9-030a-0410-b9a1-da4e402363b6
+
+dpcore.mexmac
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+a5cf615458376a40e33d04f1f0b5019d
+2009-03-06T16:34:10.036388Z
+1425
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8772
+
+qnormalise.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+47bd4f0da774f49513f2ca2f913a4903
+2009-03-06T16:34:10.036388Z
+1425
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+464
+
+filecollection.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+eb91069ed44d03bfb421e392b9afafcd
+2009-05-01T16:56:49.073671Z
+5883
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+24223
+
+qnorm.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+02cb634d7cf6403e5ecfb93d6487fb3e
+2009-03-06T16:34:10.036388Z
+1425
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+237
+
+dpfast.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+75130f5b5398df7017be3aa23c7e9715
+2009-03-06T16:34:10.036388Z
+1425
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2317
+
+dpcore.c
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+c66b75d95a40cd9bc79422573d2800b7
+2009-03-06T16:34:10.036388Z
+1425
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3382
+
+dpcore.mexmaci
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+872c19b5d99ae0a72bb8df1deca0fefd
+2009-03-06T16:34:10.036388Z
+1425
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12696
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/.svn/prop-base/dpcore.mexmac.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/.svn/prop-base/dpcore.mexmaci.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,9 @@
+K 14
+svn:executable
+V 1
+*
+K 13
+svn:mime-type
+V 24
+application/octet-stream
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/.svn/text-base/dpcore.c.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,133 @@
+/*
+ *  dpcore.c
+ *  Core of dynamic programming/DTW calculation
+ * 2003-04-02 dpwe@ee.columbia.edu
+ * $Header: /Users/dpwe/projects/dtw/RCS/dpcore.c,v 1.3 2006/01/18 20:05:51 dpwe Exp $
+% Copyright (c) 2003-05 Dan Ellis <dpwe@ee.columbia.edu>
+% released under GPL - see file COPYRIGHT
+ */
+ 
+#include    <stdio.h>
+#include    <math.h>
+#include    <ctype.h>
+#include    "mex.h"
+
+/* #define DEBUG */
+
+#define INF HUGE_VAL
+
+void
+mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+    int 	i,j;
+    long   	pvl, pvb[16];
+
+#ifdef DEBUG
+    mexPrintf("dpcore: Got %d lhs args and %d rhs args.\n", 
+	      nlhs, nrhs); 
+    for (i=0;i<nrhs;i++) {
+	mexPrintf("RHArg #%d is size %d x %d\n", 
+		  (long)i, mxGetM(prhs[i]), mxGetN(prhs[i]));
+    }
+    for (i=0;i<nlhs;i++)
+	if (plhs[i]) {
+	    mexPrintf("LHArg #%d is size %d x %d\n", 
+		      (long)i, mxGetM(plhs[i]), mxGetN(plhs[i]));
+	}
+#endif /* DEBUG */
+
+    if (nrhs < 1){
+	mexPrintf("dpcore  [D,P] = dpcore(S[,C])  dynamic programming core\n");
+	mexPrintf("           Calculate the best cost to every point in score\n");
+	mexPrintf("           cost matrix S; return it in D along with traceback\n");
+	mexPrintf("           indices in P. Optional C defines allowable steps\n");
+	mexPrintf("           and costs; default [1 1 1.0;1 0 1.0;0 1 1.0]\n");
+	return;
+    }
+
+    if (nlhs > 0){
+	mxArray  *DMatrix, *PMatrix;
+	int rows, cols, i, j, k, tb;
+	double *pM, *pD, *pP, *pC;
+	double d1, d2, d3, v;
+	double *costs;
+	int *steps;
+	int ncosts;
+
+	rows = mxGetM(prhs[0]);
+	cols = mxGetN(prhs[0]);
+	pM = mxGetPr(prhs[0]);
+
+	DMatrix = mxCreateDoubleMatrix(rows, cols, mxREAL);
+	pD = mxGetPr(DMatrix);
+	PMatrix = mxCreateDoubleMatrix(rows, cols, mxREAL);
+	pP = mxGetPr(PMatrix);
+	plhs[0] = DMatrix;
+	if (nlhs > 1) {
+	    plhs[1] = PMatrix;
+	}
+
+	/* setup costs */
+	if (nrhs == 1) {
+	    /* default C matrix */
+	    int ii;
+
+	    ncosts = 3;
+	    costs = (double *)malloc(ncosts*sizeof(double));
+	    for (ii = 0; ii<ncosts; ++ii) costs[ii] = 1.0;
+	    steps = (int *)malloc(ncosts*2*sizeof(int));
+	    steps[0] = 1;	steps[1] = 1;
+	    steps[2] = 1;	steps[3] = 0;
+	    steps[4] = 0;	steps[5] = 1;
+	} else {
+	    int ii, crows, ccols;
+	    crows = mxGetM(prhs[1]);
+	    ccols = mxGetN(prhs[1]);
+	    pC = mxGetPr(prhs[1]);
+	    /* mexPrintf("C has %d rows and %d cols\n", crows, ccols); */
+	    if (ccols != 3) {
+		mexPrintf("Cost matrix must have 3 cols (i step, j step, cost factor)\n");
+		return;
+	    }
+	    ncosts = crows;
+	    costs = (double *)malloc(ncosts*sizeof(double));
+	    steps = (int *)malloc(ncosts*2*sizeof(int));
+	    for (ii = 0; ii < ncosts; ++ii) {
+		steps[2*ii] = (int)(pC[ii]);
+		steps[2*ii+1] = (int)(pC[ii+crows]);
+		costs[ii] = pC[ii+2*crows];
+		/* mexPrintf("step=%d,%d cost=%f\n", steps[2*ii],steps[2*ii+1],costs[ii]); */
+	    }
+	}
+
+
+	/* do dp */
+	v = 0;	
+	tb = 1;	/* value to use for 0,0 */
+	for (j = 0; j < cols; ++j) {
+	    for (i = 0; i < rows; ++i) {
+		d1 = pM[i + j*rows];
+		for (k = 0; k < ncosts; ++k) {
+		    if ( i >= steps[2*k] && j >= steps[2*k+1] ) {
+			d2 = costs[k]*d1 + pD[(i-steps[2*k]) + (j-steps[2*k+1])*rows];
+			if (d2 < v) {
+			    v = d2;
+			    tb = k+1;
+			}
+		    }
+		}
+
+		pD[i + j*rows] = v;
+		pP[i + j*rows] = (double)tb;
+		v = INF;
+	    }
+	}
+	free((void *)costs);
+	free((void *)steps);
+    }
+
+#ifdef DEBUG
+    mexPrintf("dpcore: returning...\n");
+#endif /* DEBUG */
+}
+
Binary file _misc/general/.svn/text-base/dpcore.mexmac.svn-base has changed
Binary file _misc/general/.svn/text-base/dpcore.mexmaci.svn-base has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/.svn/text-base/dpfast.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,92 @@
+function [p,q,D,sc] = dpfast(M,C,T,G)
+% [p,q,D,sc] = dpfast(M,C,T,G) 
+%    Use dynamic programming to find a min-cost path through matrix M.
+%    Return state sequence in p,q; full min cost matrix as D and 
+%    local costs along best path in sc.
+%    This version gives the same results as dp.m, but uses dpcore.mex
+%    to run ~200x faster.
+%    C is a step matrix, with rows (i step, j step, cost factor)
+%    Default is [1 1 1.0;0 1 1.0;1 0 1.0];
+%    Another good one is [1 1 1;1 0 1;0 1 1;1 2 2;2 1 2]
+%    T selects traceback origin: 0 is to any edge; 1 is top right (default);
+%    T > 1 finds path to min of anti-diagonal T points away from top-right.
+%    Optional G defines length of 'gulleys' for T=0 mode; default 0.5
+%    (i.e. accept path to only 50% of edge nearest top-right)
+% 2003-04-04,2005-04-04 dpwe@ee.columbia.edu $Header: /Users/dpwe/projects/dtw/RCS/dpfast.m,v 1.6 2008/03/14 14:40:50 dpwe Exp $
+
+% Copyright (c) 2003 Dan Ellis <dpwe@ee.columbia.edu>
+% released under GPL - see file COPYRIGHT
+
+if nargin < 2
+  % Default step / cost matrix
+  C = [1 1 1.0;0 1 1.0;1 0 1.0];
+end
+
+if nargin < 3
+  % Default: path to top-right
+  T = 1;
+end
+
+if nargin < 4
+  % how big are gulleys?
+  G = 0.5;  % half the extent
+end
+
+if sum(isnan(M(:)))>0
+  error('dpwe:dpfast:NAN','Error: Cost matrix includes NaNs');
+end
+
+if min(M(:)) < 0
+  disp('Warning: cost matrix includes negative values; results may not be what you expect');
+end
+
+[r,c] = size(M);
+
+% Core cumulative cost calculation coded as mex
+[D,phi] = dpcore(M,C);
+
+p = [];
+q = [];
+
+%% Traceback from top left?
+%i = r; 
+%j = c;
+
+if T == 0
+  % Traceback from lowest cost "to edge" (gulleys)
+  TE = D(r,:);
+  RE = D(:,c);
+  % eliminate points not in gulleys
+  TE(1:round((1-G)*c)) = max(max(D));
+  RE(1:round((1-G)*r)) = max(max(D));
+  if (min(TE) < min(RE))
+    i = r;
+    j = max(find(TE==min(TE)));
+  else
+    i = max(find(RE==min(RE)));
+    j = c;
+  end
+else
+  % Traceback from min of antidiagonal
+  %stepback = floor(0.1*c);
+  stepback = T;
+  slice = diag(fliplr(D),-(r-stepback));
+  [mm,ii] = min(slice);
+  i = r - stepback + ii;
+  j = c + 1 - ii;
+end
+
+p=i;
+q=j;
+
+sc = M(p,q);
+
+while i > 1 & j > 1
+%  disp(['i=',num2str(i),' j=',num2str(j)]);
+  tb = phi(i,j);
+  i = i - C(tb,1);
+  j = j - C(tb,2);
+  p = [i,p];
+  q = [j,q];
+  sc = [M(i,j),sc];
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/.svn/text-base/filecollection.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,360 @@
+function allfilenames = filecollection(coll, ext, varargin)
+
+nArg = length(varargin);
+% varargin
+if nArg > 0 && ~isempty(varargin{1})
+    data_dir = varargin{1};
+    if data_dir(end) == '/', data_dir = data_dir(1:end-1); end    
+else
+    data_dir = '/Volumes/data/Content/BeatlesWav';
+end
+if iscell(coll)
+    collec = coll;
+else
+    collec = {coll};
+end
+
+allfilenames = [];
+sla = '/';
+% data_dir = '/Volumes/data/Content/BeatlesWav';
+for iCollec = 1:length(collec)
+    switch collec{iCollec}
+        case 'omras2'
+            filenames = {...
+                ['/Users/matthiasmauch/Desktop/OMRAS2 demo/demo' ext]};
+        case 'testletitbe'
+            filenames = {...
+                [data_dir sla '12_-_Let_It_Be/06_-_Let_It_Be' ext]};
+        case 'teo'
+            filenames = {...
+                [data_dir sla 'nonBeatles/10 Teo Torriatte (Let Us Cling Together)' ext]};
+        case 'testsawher'
+            filenames = {...
+                [data_dir sla '01_-_Please_Please_Me/01_-_I_Saw_Her_Standing_There' ext]};
+            
+        case 'testlose' 
+            filenames = {...
+                [data_dir sla '05_-_Help!/06_-_You''re_Going_to_Lose_That_Girl' ext]};
+            
+        case 'testwords' 
+            filenames = {...
+                [data_dir sla '04_-_Beatles_For_Sale/09_-_Words_Of_Love' ext]};
+        case 'testyesterday'
+            filenames = {...
+                [data_dir sla '05_-_Help!/13_-_Yesterday' ext]};
+        case 'testcometogether' 
+            filenames = {...
+                [data_dir sla '11_-_Abbey_Road/01_-_Come_Together' ext]};
+        case 'testfriends' 
+            filenames = {...
+                [data_dir sla 'nonBeatles/15-Friends Will Be Friends' ext]};
+        case 'testfriends2' 
+            filenames = {...
+                ['/Volumes/Private/iTunes/iTunes Music/Queen/A Kind of Magic/05 Friends will be Friends' ext]};
+        case 'carole'
+            filenames = {...
+                [data_dir sla 'Carole King/Tapestry/06 Way Over Yonder' ext],...
+                [data_dir sla 'Carole King/Tapestry/05 Beautiful' ext],...
+                [data_dir sla 'Carole King/Tapestry/04 Home Again' ext],...
+                [data_dir sla 'Carole King/Tapestry/03 It''s Too Late' ext],...
+                [data_dir sla 'Carole King/Tapestry/02 So Far Away' ext],...
+                [data_dir sla 'Carole King/Tapestry/01 I Feel The Earth Move' ext],...
+                [data_dir sla 'Carole King/Tapestry/11 Tapestry' ext],...
+                [data_dir sla 'Carole King/Tapestry/10 Smackwater Jack' ext],...
+                [data_dir sla 'Carole King/Tapestry/09 Will You Love Me Tomorrow_' ext],...
+                [data_dir sla 'Carole King/Tapestry/08 Where You Lead' ext],...
+                [data_dir sla 'Carole King/Tapestry/07 You''ve Got A Friend' ext],...
+                [data_dir sla 'Carole King/Tapestry/14 Smackwater Jack [Live]' ext],...
+                [data_dir sla 'Carole King/Tapestry/13 Out In The Cold' ext],...
+                [data_dir sla 'Carole King/Tapestry/12 Feel Like A Natural Woman' ext]};
+        case 'u2'
+            filenames = {...
+                [data_dir sla 'U2/U218 Singles/02 Beautiful Day' ext]};
+        case 'dinverno'
+            filenames = { ...
+                ['/Volumes/Private/CubaseProjects/dinverno/Audio/dinverno_autumnleaves1' ext],...
+                ['/Volumes/Private/CubaseProjects/dinverno/Audio/dinverno_autumnleaves2' ext],...
+                ['/Volumes/Private/CubaseProjects/dinverno/Audio/dinverno_shookup1' ext],...
+                ['/Volumes/Private/CubaseProjects/dinverno/Audio/dinverno_helpfrommyfriends1' ext],...
+                ['/Volumes/Private/CubaseProjects/dinverno/Audio/dinverno_autumnleaves3' ext]};
+        case '01_-_Please_Please_Me'
+            filenames = {...
+                [data_dir sla '01_-_Please_Please_Me/01_-_I_Saw_Her_Standing_There' ext],...
+                [data_dir sla '01_-_Please_Please_Me/02_-_Misery' ext],...
+                [data_dir sla '01_-_Please_Please_Me/03_-_Anna_(Go_To_Him)' ext],...
+                [data_dir sla '01_-_Please_Please_Me/04_-_Chains' ext],...
+                [data_dir sla '01_-_Please_Please_Me/05_-_Boys' ext],...
+                [data_dir sla '01_-_Please_Please_Me/06_-_Ask_Me_Why' ext],...
+                [data_dir sla '01_-_Please_Please_Me/07_-_Please_Please_Me' ext],...
+                [data_dir sla '01_-_Please_Please_Me/08_-_Love_Me_Do' ext],...
+                [data_dir sla '01_-_Please_Please_Me/09_-_P._S._I_Love_You' ext],...
+                [data_dir sla '01_-_Please_Please_Me/10_-_Baby_It''s_You' ext],...
+                [data_dir sla '01_-_Please_Please_Me/11_-_Do_You_Want_To_Know_A_Secret' ext],...
+                ...[data_dir sla '01_-_Please_Please_Me/12_-_A_Taste_Of_Honey' ext],...
+                [data_dir sla '01_-_Please_Please_Me/13_-_There''s_A_Place' ext],...
+                [data_dir sla '01_-_Please_Please_Me/14_-_Twist_And_Shout' ext]};
+
+        case '02_-_With_the_Beatles'
+            filenames = {...
+                [data_dir sla '02_-_With_the_Beatles/01_-_It_Won''t_Be_Long' ext],...
+                [data_dir sla '02_-_With_the_Beatles/02_-_All_I''ve_Got_To_Do' ext],...
+                [data_dir sla '02_-_With_the_Beatles/03_-_All_My_Loving' ext],...
+                [data_dir sla '02_-_With_the_Beatles/04_-_Don''t_Bother_Me' ext],...
+                [data_dir sla '02_-_With_the_Beatles/05_-_Little_Child' ext],...
+                [data_dir sla '02_-_With_the_Beatles/06_-_Till_There_Was_You' ext],...
+                [data_dir sla '02_-_With_the_Beatles/07_-_Please_Mister_Postman' ext],...
+                [data_dir sla '02_-_With_the_Beatles/08_-_Roll_Over_Beethoven' ext],...
+                [data_dir sla '02_-_With_the_Beatles/09_-_Hold_Me_Tight' ext],...
+                ...[data_dir sla '02_-_With_the_Beatles/10_-_You_Really_Got_A_Hold_On_Me' ext],...
+                [data_dir sla '02_-_With_the_Beatles/11_-_I_Wanna_Be_Your_Man' ext],...
+                [data_dir sla '02_-_With_the_Beatles/12_-_Devil_In_Her_Heart' ext],...
+                [data_dir sla '02_-_With_the_Beatles/13_-_Not_A_Second_Time' ext],...
+                [data_dir sla '02_-_With_the_Beatles/14_-_Money' ext]};
+
+        case '03_-_A_Hard_Day''s_Night'
+            filenames = {...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/01_-_A_Hard_Day''s_Night' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/02_-_I_Should_Have_Known_Better' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/03_-_If_I_Fell' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/04_-_I''m_Happy_Just_To_Dance_With_You' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/05_-_And_I_Love_Her' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/06_-_Tell_Me_Why' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/07_-_Can''t_Buy_Me_Love' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/08_-_Any_Time_At_All' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/09_-_I''ll_Cry_Instead' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/10_-_Things_We_Said_Today' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/11_-_When_I_Get_Home' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/12_-_You_Can''t_Do_That' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/13_-_I''ll_Be_Back' ext]};
+
+
+        case '04_-_Beatles_for_Sale'
+            filenames = {...
+                [data_dir sla '04_-_Beatles_for_Sale/01_-_No_Reply' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/02_-_I''m_a_Loser' ext],...
+                ...[data_dir sla '04_-_Beatles_for_Sale/03_-_Baby''s_In_Black' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/04_-_Rock_and_Roll_Music' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/05_-_I''ll_Follow_the_Sun' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/06_-_Mr._Moonlight' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/07_-_Kansas_City-_Hey,_Hey,_Hey,_Hey' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/08_-_Eight_Days_a_Week' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/09_-_Words_of_Love' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/10_-_Honey_Don''t' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/11_-_Every_Little_Thing' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/12_-_I_Don''t_Want_to_Spoil_the_Party' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/13_-_What_You''re_Doing' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/14_-_Everybody''s_Trying_to_Be_My_Baby' ext]};
+
+
+        case '05_-_Help!'
+            filenames = {...
+                [data_dir sla '05_-_Help!/01_-_Help!' ext],...
+                [data_dir sla '05_-_Help!/02_-_The_Night_Before' ext],...
+                ...[data_dir sla '05_-_Help!/03_-_You''ve_Got_To_Hide_Your_Love_Away' ext],...
+                [data_dir sla '05_-_Help!/04_-_I_Need_You' ext],...
+                [data_dir sla '05_-_Help!/05_-_Another_Girl' ext],...
+                [data_dir sla '05_-_Help!/06_-_You''re_Going_to_Lose_That_Girl' ext],...
+                [data_dir sla '05_-_Help!/07_-_Ticket_To_Ride' ext],...
+                [data_dir sla '05_-_Help!/08_-_Act_Naturally' ext],...
+                [data_dir sla '05_-_Help!/09_-_It''s_Only_Love' ext],...
+                [data_dir sla '05_-_Help!/10_-_You_Like_Me_Too_Much' ext],...
+                [data_dir sla '05_-_Help!/11_-_Tell_Me_What_You_See' ext],...
+                [data_dir sla '05_-_Help!/12_-_I''ve_Just_Seen_a_Face' ext],...
+                [data_dir sla '05_-_Help!/13_-_Yesterday' ext],...
+                [data_dir sla '05_-_Help!/14_-_Dizzy_Miss_Lizzy' ext]};
+
+        case '06_-_Rubber_Soul'
+            filenames = {...
+                [data_dir sla '06_-_Rubber_Soul/01_-_Drive_My_Car' ext],...
+                ...            [data_dir sla '06_-_Rubber_Soul/02_-_Norwegian_Wood_(This_Bird_Has_Flown)' ext],...
+                [data_dir sla '06_-_Rubber_Soul/03_-_You_Won''t_See_Me' ext],...
+                [data_dir sla '06_-_Rubber_Soul/04_-_Nowhere_Man' ext],...
+                [data_dir sla '06_-_Rubber_Soul/05_-_Think_For_Yourself' ext],...
+                [data_dir sla '06_-_Rubber_Soul/06_-_The_Word' ext],...
+                [data_dir sla '06_-_Rubber_Soul/07_-_Michelle' ext],...
+                [data_dir sla '06_-_Rubber_Soul/08_-_What_Goes_On' ext],...
+                [data_dir sla '06_-_Rubber_Soul/09_-_Girl' ext],...
+                [data_dir sla '06_-_Rubber_Soul/10_-_I''m_Looking_Through_You' ext],...
+                [data_dir sla '06_-_Rubber_Soul/11_-_In_My_Life' ext],...
+                [data_dir sla '06_-_Rubber_Soul/12_-_Wait' ext],...
+                [data_dir sla '06_-_Rubber_Soul/13_-_If_I_Needed_Someone' ext],...
+                [data_dir sla '06_-_Rubber_Soul/14_-_Run_For_Your_Life' ext]};
+
+        case '07_-_Revolver'
+            filenames = {...
+                [data_dir sla '07_-_Revolver/01_-_Taxman' ext],...
+                [data_dir sla '07_-_Revolver/02_-_Eleanor_Rigby' ext],...
+                [data_dir sla '07_-_Revolver/03_-_I''m_Only_Sleeping' ext],...
+                ...[data_dir sla '07_-_Revolver/04_-_Love_You_To' ext],...
+                [data_dir sla '07_-_Revolver/05_-_Here,_There_And_Everywhere' ext],...
+                [data_dir sla '07_-_Revolver/06_-_Yellow_Submarine' ext],...
+                [data_dir sla '07_-_Revolver/07_-_She_Said_She_Said' ext],...
+                ...[data_dir sla '07_-_Revolver/08_-_Good_Day_Sunshine' ext],...
+                [data_dir sla '07_-_Revolver/09_-_And_Your_Bird_Can_Sing' ext],...
+                [data_dir sla '07_-_Revolver/10_-_For_No_One' ext],...
+                [data_dir sla '07_-_Revolver/11_-_Doctor_Robert' ext],...
+                [data_dir sla '07_-_Revolver/12_-_I_Want_To_Tell_You' ext],...
+                [data_dir sla '07_-_Revolver/13_-_Got_To_Get_You_Into_My_Life' ext],...
+                ...[data_dir sla '07_-_Revolver/14_-_Tomorrow_Never_Knows' ext]...
+                };
+
+        case  '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band'
+            filenames = {...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/01_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/02_-_With_A_Little_Help_From_My_Friends' ext],...
+                ...[data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/03_-_Lucy_In_The_Sky_With_Diamonds' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/04_-_Getting_Better' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/05_-_Fixing_A_Hole' ext],...
+                ...[data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/06_-_She''s_Leaving_Home' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/07_-_Being_For_The_Benefit_Of_Mr._Kite!' ext],...
+                ...[data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/08_-_Within_You_Without_You' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/09_-_When_I''m_Sixty-Four' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/10_-_Lovely_Rita' ext],...
+                ...[data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/11_-_Good_Morning_Good_Morning' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/12_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band_(Reprise)' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/13_-_A_Day_In_The_Life' ext]};
+
+        case '09_-_Magical_Mystery_Tour'
+            filenames = {...
+                [data_dir sla '09_-_Magical_Mystery_Tour/01_-_Magical_Mystery_Tour' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/02_-_The_Fool_On_The_Hill' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/03_-_Flying' ext],...
+                ...[data_dir sla '09_-_Magical_Mystery_Tour/04_-_Blue_Jay_Way' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/05_-_Your_Mother_Should_Know' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/06_-_I_Am_The_Walrus' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/07_-_Hello_Goodbye' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/08_-_Strawberry_Fields_Forever' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/09_-_Penny_Lane' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/10_-_Baby_You''re_A_Rich_Man' ext],...
+                ...[data_dir sla '09_-_Magical_Mystery_Tour/11_-_All_You_Need_Is_Love' ext] ...
+                };
+
+        case '10CD1_-_The_Beatles'
+            filenames = {...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_01_-_Back_in_the_USSR' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_02_-_Dear_Prudence' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_03_-_Glass_Onion' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_04_-_Ob-La-Di,_Ob-La-Da' ext],...
+                ...[data_dir sla '10CD1_-_The_Beatles/CD1_-_05_-_Wild_Honey_Pie' ext],...
+                ...[data_dir sla '10CD1_-_The_Beatles/CD1_-_06_-_The_Continuing_Story_of_Bungalow_Bill' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_07_-_While_My_Guitar_Gently_Weeps' ext],...
+                ...[data_dir sla '10CD1_-_The_Beatles/CD1_-_08_-_Happiness_is_a_Warm_Gun' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_09_-_Martha_My_Dear' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_10_-_I''m_So_Tired' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_11_-_Black_Bird' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_12_-_Piggies' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_13_-_Rocky_Raccoon' ext],...
+                ...[data_dir sla '10CD1_-_The_Beatles/CD1_-_14_-_Don''t_Pass_Me_By' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_15_-_Why_Don''t_We_Do_It_In_The_Road' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_16_-_I_Will' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_17_-_Julia' ext]};
+
+        case '10CD2_-_The_Beatles'
+            filenames = {...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_01_-_Birthday' ext],...
+                ...[data_dir sla '10CD2_-_The_Beatles/CD2_-_02_-_Yer_Blues' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_03_-_Mother_Nature''s_Son' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_04_-_Everybody''s_Got_Something_To_Hide_Except_Me_and_M' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_05_-_Sexy_Sadie' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_06_-_Helter_Skelter' ext],...
+                ...[data_dir sla '10CD2_-_The_Beatles/CD2_-_07_-_Long_Long_Long' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_08_-_Revolution_1' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_09_-_Honey_Pie' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_10_-_Savoy_Truffle' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_11_-_Cry_Baby_Cry' ext],...
+                ...[data_dir sla '10CD2_-_The_Beatles/CD2_-_12_-_Revolution_9' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_13_-_Good_Night' ext]};
+
+        case '11_-_Abbey_Road'
+            filenames = {...
+                [data_dir sla '11_-_Abbey_Road/01_-_Come_Together' ext],...
+                [data_dir sla '11_-_Abbey_Road/02_-_Something' ext],...
+                [data_dir sla '11_-_Abbey_Road/03_-_Maxwell''s_Silver_Hammer' ext],...
+                ...[data_dir sla '11_-_Abbey_Road/04_-_Oh!_Darling' ext],...
+                [data_dir sla '11_-_Abbey_Road/05_-_Octopus''s_Garden' ext],...
+                ...[data_dir sla '11_-_Abbey_Road/06_-_I_Want_You' ext],...
+                [data_dir sla '11_-_Abbey_Road/07_-_Here_Comes_The_Sun' ext],...
+                [data_dir sla '11_-_Abbey_Road/08_-_Because' ext],...
+                [data_dir sla '11_-_Abbey_Road/09_-_You_Never_Give_Me_Your_Money' ext],...
+                [data_dir sla '11_-_Abbey_Road/10_-_Sun_King' ext],...
+                [data_dir sla '11_-_Abbey_Road/11_-_Mean_Mr_Mustard' ext],...
+                [data_dir sla '11_-_Abbey_Road/12_-_Polythene_Pam' ext],...
+                [data_dir sla '11_-_Abbey_Road/13_-_She_Came_In_Through_The_Bathroom_Window' ext],...
+                [data_dir sla '11_-_Abbey_Road/14_-_Golden_Slumbers' ext],...
+                [data_dir sla '11_-_Abbey_Road/15_-_Carry_That_Weight' ext],...
+                [data_dir sla '11_-_Abbey_Road/16_-_The_End' ext],...
+                [data_dir sla '11_-_Abbey_Road/17_-_Her_Majesty' ext]};
+
+        case '12_-_Let_It_Be'
+            filenames = {...
+                ...[data_dir sla '12_-_Let_It_Be/01_-_Two_of_Us' ext],...
+                ...[data_dir sla '12_-_Let_It_Be/02_-_Dig_a_Pony' ext],...
+                [data_dir sla '12_-_Let_It_Be/03_-_Across_the_Universe' ext],...
+                ...            [data_dir sla '12_-_Let_It_Be/04_-_I_Me_Mine' ext],...
+                ...            [data_dir sla '12_-_Let_It_Be/05_-_Dig_It' ext],...
+                [data_dir sla '12_-_Let_It_Be/06_-_Let_It_Be' ext],...
+                [data_dir sla '12_-_Let_It_Be/07_-_Maggie_Mae' ext],...
+                [data_dir sla '12_-_Let_It_Be/08_-_I''ve_Got_A_Feeling' ext],...
+                [data_dir sla '12_-_Let_It_Be/09_-_One_After_909' ext],...
+                [data_dir sla '12_-_Let_It_Be/10_-_The_Long_and_Winding_Road' ext],...
+                [data_dir sla '12_-_Let_It_Be/11_-_For_You_Blue' ext],...
+                [data_dir sla '12_-_Let_It_Be/12_-_Get_Back' ext]};
+        case 'discarded'
+            filenames = {...
+                [data_dir sla '01_-_Please_Please_Me/12_-_A_Taste_Of_Honey' ext],...
+                [data_dir sla '02_-_With_the_Beatles/10_-_You_Really_Got_A_Hold_On_Me' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/03_-_Baby''s_In_Black' ext],...
+                [data_dir sla '05_-_Help!/03_-_You''ve_Got_To_Hide_Your_Love_Away' ext],...
+                [data_dir sla '06_-_Rubber_Soul/02_-_Norwegian_Wood_(This_Bird_Has_Flown)' ext],...
+                [data_dir sla '07_-_Revolver/04_-_Love_You_To' ext],...
+                [data_dir sla '07_-_Revolver/08_-_Good_Day_Sunshine' ext],...
+                [data_dir sla '07_-_Revolver/14_-_Tomorrow_Never_Knows' ext]...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/03_-_Lucy_In_The_Sky_With_Diamonds' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/06_-_She''s_Leaving_Home' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/08_-_Within_You_Without_You' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/11_-_Good_Morning_Good_Morning' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/04_-_Blue_Jay_Way' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/11_-_All_You_Need_Is_Love' ext] ...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_05_-_Wild_Honey_Pie' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_02_-_Yer_Blues' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_07_-_Long_Long_Long' ext],...
+                [data_dir sla '11_-_Abbey_Road/04_-_Oh!_Darling' ext],...
+                [data_dir sla '12_-_Let_It_Be/01_-_Two_of_Us' ext],...
+                [data_dir sla '12_-_Let_It_Be/02_-_Dig_a_Pony' ext],...
+                [data_dir sla '12_-_Let_It_Be/04_-_I_Me_Mine' ext],...
+                [data_dir sla '12_-_Let_It_Be/05_-_Dig_It' ext],...
+                [data_dir sla '11_-_Abbey_Road/06_-_I_Want_You' ext]...
+                    };
+        case 'notinMIREX'
+            filenames = {...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_06_-_The_Continuing_Story_of_Bungalow_Bill' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_14_-_Don''t_Pass_Me_By' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_08_-_Happiness_is_a_Warm_Gun' ext],...
+                    };
+        case 'revolution9'
+            filenames = {[data_dir sla '10CD2_-_The_Beatles/CD2_-_12_-_Revolution_9' ext]};
+        case 'leftovers'
+            filenames = {...
+                          [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/06_-_She''s_Leaving_Home' ext],...
+                          [data_dir sla '07_-_Revolver/04_-_Love_You_To' ext],...
+                };
+        case 'semma'
+            filenames = {...
+                [data_dir sla 'SeMMA/audio/Britney_Spear_##_Baby_Hit_Me_One_More_Time', ext],...
+                [data_dir sla 'SeMMA/audio/Bjork_##_Its_Oh_So_Quiet', ext],...
+                [data_dir sla 'SeMMA/audio/Alanis_Morissette_##_Thank_U', ext],...
+                [data_dir sla 'SeMMA/audio/Alanis_Morissette_##_Head_Over_Feet', ext],...
+                [data_dir sla 'SeMMA/audio/A_Ha_##_Take_On_Me', ext],...
+                [data_dir sla 'SeMMA/audio/The_Clash_##_Should_I_Stay_Or_Should_I_Go', ext],...
+                [data_dir sla 'SeMMA/audio/Spice_Girls_##_Wannabe', ext],...
+                [data_dir sla 'SeMMA/audio/Seal_##_Crazy', ext],...
+                [data_dir sla 'SeMMA/audio/Radiohead_##_Creep', ext],...
+                [data_dir sla 'SeMMA/audio/Oasis_##_Wonderwall', ext],...
+                [data_dir sla 'SeMMA/audio/Nirvana_##_Smells_Like_Teen_Spirit', ext],...
+                [data_dir sla 'SeMMA/audio/Deus_##_Suds_and_Soda', ext],...
+                [data_dir sla 'SeMMA/audio/Cranberries_##_Zombie', ext],...
+                [data_dir sla 'SeMMA/audio/Chumbawamba_##_Tubthumping', ext],...
+                };
+    end
+    allfilenames = [allfilenames,filenames];
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/.svn/text-base/qnorm.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function s = qnorm(inmat, varargin)
+dim = 1;
+if nargin > 1
+    q = varargin{1};
+    if nargin > 2
+        dim = varargin{2};
+    end
+else
+    q = 2;
+end
+if ~(q == Inf)
+    s = sum(inmat.^q,dim).^(1/q);
+else
+    s = max(inmat,[],dim);
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/.svn/text-base/qnormalise.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function [outmat, scale] = qnormalise(inmat, varargin)
+% qnormalise(inmat, q, dim) returns the field inmat normalised by the q
+% norm over dimension dim
+dim = 1;
+if nargin > 1
+    q = varargin{1};
+    if nargin > 2
+        dim = varargin{2};
+    end
+else
+    q = 2;
+end
+sizeInmat = size(inmat);
+nDim = length(sizeInmat);
+repeatpattern = [ones(1,dim-1) sizeInmat(dim) ones(1,nDim-dim)];
+scale = qnorm(inmat, q, dim);
+outmat = inmat ./ repmat(scale, repeatpattern);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/dpcore.c	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,133 @@
+/*
+ *  dpcore.c
+ *  Core of dynamic programming/DTW calculation
+ * 2003-04-02 dpwe@ee.columbia.edu
+ * $Header: /Users/dpwe/projects/dtw/RCS/dpcore.c,v 1.3 2006/01/18 20:05:51 dpwe Exp $
+% Copyright (c) 2003-05 Dan Ellis <dpwe@ee.columbia.edu>
+% released under GPL - see file COPYRIGHT
+ */
+ 
+#include    <stdio.h>
+#include    <math.h>
+#include    <ctype.h>
+#include    "mex.h"
+
+/* #define DEBUG */
+
+#define INF HUGE_VAL
+
+void
+mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
+{
+    int 	i,j;
+    long   	pvl, pvb[16];
+
+#ifdef DEBUG
+    mexPrintf("dpcore: Got %d lhs args and %d rhs args.\n", 
+	      nlhs, nrhs); 
+    for (i=0;i<nrhs;i++) {
+	mexPrintf("RHArg #%d is size %d x %d\n", 
+		  (long)i, mxGetM(prhs[i]), mxGetN(prhs[i]));
+    }
+    for (i=0;i<nlhs;i++)
+	if (plhs[i]) {
+	    mexPrintf("LHArg #%d is size %d x %d\n", 
+		      (long)i, mxGetM(plhs[i]), mxGetN(plhs[i]));
+	}
+#endif /* DEBUG */
+
+    if (nrhs < 1){
+	mexPrintf("dpcore  [D,P] = dpcore(S[,C])  dynamic programming core\n");
+	mexPrintf("           Calculate the best cost to every point in score\n");
+	mexPrintf("           cost matrix S; return it in D along with traceback\n");
+	mexPrintf("           indices in P. Optional C defines allowable steps\n");
+	mexPrintf("           and costs; default [1 1 1.0;1 0 1.0;0 1 1.0]\n");
+	return;
+    }
+
+    if (nlhs > 0){
+	mxArray  *DMatrix, *PMatrix;
+	int rows, cols, i, j, k, tb;
+	double *pM, *pD, *pP, *pC;
+	double d1, d2, d3, v;
+	double *costs;
+	int *steps;
+	int ncosts;
+
+	rows = mxGetM(prhs[0]);
+	cols = mxGetN(prhs[0]);
+	pM = mxGetPr(prhs[0]);
+
+	DMatrix = mxCreateDoubleMatrix(rows, cols, mxREAL);
+	pD = mxGetPr(DMatrix);
+	PMatrix = mxCreateDoubleMatrix(rows, cols, mxREAL);
+	pP = mxGetPr(PMatrix);
+	plhs[0] = DMatrix;
+	if (nlhs > 1) {
+	    plhs[1] = PMatrix;
+	}
+
+	/* setup costs */
+	if (nrhs == 1) {
+	    /* default C matrix */
+	    int ii;
+
+	    ncosts = 3;
+	    costs = (double *)malloc(ncosts*sizeof(double));
+	    for (ii = 0; ii<ncosts; ++ii) costs[ii] = 1.0;
+	    steps = (int *)malloc(ncosts*2*sizeof(int));
+	    steps[0] = 1;	steps[1] = 1;
+	    steps[2] = 1;	steps[3] = 0;
+	    steps[4] = 0;	steps[5] = 1;
+	} else {
+	    int ii, crows, ccols;
+	    crows = mxGetM(prhs[1]);
+	    ccols = mxGetN(prhs[1]);
+	    pC = mxGetPr(prhs[1]);
+	    /* mexPrintf("C has %d rows and %d cols\n", crows, ccols); */
+	    if (ccols != 3) {
+		mexPrintf("Cost matrix must have 3 cols (i step, j step, cost factor)\n");
+		return;
+	    }
+	    ncosts = crows;
+	    costs = (double *)malloc(ncosts*sizeof(double));
+	    steps = (int *)malloc(ncosts*2*sizeof(int));
+	    for (ii = 0; ii < ncosts; ++ii) {
+		steps[2*ii] = (int)(pC[ii]);
+		steps[2*ii+1] = (int)(pC[ii+crows]);
+		costs[ii] = pC[ii+2*crows];
+		/* mexPrintf("step=%d,%d cost=%f\n", steps[2*ii],steps[2*ii+1],costs[ii]); */
+	    }
+	}
+
+
+	/* do dp */
+	v = 0;	
+	tb = 1;	/* value to use for 0,0 */
+	for (j = 0; j < cols; ++j) {
+	    for (i = 0; i < rows; ++i) {
+		d1 = pM[i + j*rows];
+		for (k = 0; k < ncosts; ++k) {
+		    if ( i >= steps[2*k] && j >= steps[2*k+1] ) {
+			d2 = costs[k]*d1 + pD[(i-steps[2*k]) + (j-steps[2*k+1])*rows];
+			if (d2 < v) {
+			    v = d2;
+			    tb = k+1;
+			}
+		    }
+		}
+
+		pD[i + j*rows] = v;
+		pP[i + j*rows] = (double)tb;
+		v = INF;
+	    }
+	}
+	free((void *)costs);
+	free((void *)steps);
+    }
+
+#ifdef DEBUG
+    mexPrintf("dpcore: returning...\n");
+#endif /* DEBUG */
+}
+
Binary file _misc/general/dpcore.mexmac has changed
Binary file _misc/general/dpcore.mexmaci has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/dpfast.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,92 @@
+function [p,q,D,sc] = dpfast(M,C,T,G)
+% [p,q,D,sc] = dpfast(M,C,T,G) 
+%    Use dynamic programming to find a min-cost path through matrix M.
+%    Return state sequence in p,q; full min cost matrix as D and 
+%    local costs along best path in sc.
+%    This version gives the same results as dp.m, but uses dpcore.mex
+%    to run ~200x faster.
+%    C is a step matrix, with rows (i step, j step, cost factor)
+%    Default is [1 1 1.0;0 1 1.0;1 0 1.0];
+%    Another good one is [1 1 1;1 0 1;0 1 1;1 2 2;2 1 2]
+%    T selects traceback origin: 0 is to any edge; 1 is top right (default);
+%    T > 1 finds path to min of anti-diagonal T points away from top-right.
+%    Optional G defines length of 'gulleys' for T=0 mode; default 0.5
+%    (i.e. accept path to only 50% of edge nearest top-right)
+% 2003-04-04,2005-04-04 dpwe@ee.columbia.edu $Header: /Users/dpwe/projects/dtw/RCS/dpfast.m,v 1.6 2008/03/14 14:40:50 dpwe Exp $
+
+% Copyright (c) 2003 Dan Ellis <dpwe@ee.columbia.edu>
+% released under GPL - see file COPYRIGHT
+
+if nargin < 2
+  % Default step / cost matrix
+  C = [1 1 1.0;0 1 1.0;1 0 1.0];
+end
+
+if nargin < 3
+  % Default: path to top-right
+  T = 1;
+end
+
+if nargin < 4
+  % how big are gulleys?
+  G = 0.5;  % half the extent
+end
+
+if sum(isnan(M(:)))>0
+  error('dpwe:dpfast:NAN','Error: Cost matrix includes NaNs');
+end
+
+if min(M(:)) < 0
+  disp('Warning: cost matrix includes negative values; results may not be what you expect');
+end
+
+[r,c] = size(M);
+
+% Core cumulative cost calculation coded as mex
+[D,phi] = dpcore(M,C);
+
+p = [];
+q = [];
+
+%% Traceback from top left?
+%i = r; 
+%j = c;
+
+if T == 0
+  % Traceback from lowest cost "to edge" (gulleys)
+  TE = D(r,:);
+  RE = D(:,c);
+  % eliminate points not in gulleys
+  TE(1:round((1-G)*c)) = max(max(D));
+  RE(1:round((1-G)*r)) = max(max(D));
+  if (min(TE) < min(RE))
+    i = r;
+    j = max(find(TE==min(TE)));
+  else
+    i = max(find(RE==min(RE)));
+    j = c;
+  end
+else
+  % Traceback from min of antidiagonal
+  %stepback = floor(0.1*c);
+  stepback = T;
+  slice = diag(fliplr(D),-(r-stepback));
+  [mm,ii] = min(slice);
+  i = r - stepback + ii;
+  j = c + 1 - ii;
+end
+
+p=i;
+q=j;
+
+sc = M(p,q);
+
+while i > 1 & j > 1
+%  disp(['i=',num2str(i),' j=',num2str(j)]);
+  tb = phi(i,j);
+  i = i - C(tb,1);
+  j = j - C(tb,2);
+  p = [i,p];
+  q = [j,q];
+  sc = [M(i,j),sc];
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/filecollection.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,360 @@
+function allfilenames = filecollection(coll, ext, varargin)
+
+nArg = length(varargin);
+% varargin
+if nArg > 0 && ~isempty(varargin{1})
+    data_dir = varargin{1};
+    if data_dir(end) == '/', data_dir = data_dir(1:end-1); end    
+else
+    data_dir = '/Volumes/data/Content/BeatlesWav';
+end
+if iscell(coll)
+    collec = coll;
+else
+    collec = {coll};
+end
+
+allfilenames = [];
+sla = '/';
+% data_dir = '/Volumes/data/Content/BeatlesWav';
+for iCollec = 1:length(collec)
+    switch collec{iCollec}
+        case 'omras2'
+            filenames = {...
+                ['/Users/matthiasmauch/Desktop/OMRAS2 demo/demo' ext]};
+        case 'testletitbe'
+            filenames = {...
+                [data_dir sla '12_-_Let_It_Be/06_-_Let_It_Be' ext]};
+        case 'teo'
+            filenames = {...
+                [data_dir sla 'nonBeatles/10 Teo Torriatte (Let Us Cling Together)' ext]};
+        case 'testsawher'
+            filenames = {...
+                [data_dir sla '01_-_Please_Please_Me/01_-_I_Saw_Her_Standing_There' ext]};
+            
+        case 'testlose' 
+            filenames = {...
+                [data_dir sla '05_-_Help!/06_-_You''re_Going_to_Lose_That_Girl' ext]};
+            
+        case 'testwords' 
+            filenames = {...
+                [data_dir sla '04_-_Beatles_For_Sale/09_-_Words_Of_Love' ext]};
+        case 'testyesterday'
+            filenames = {...
+                [data_dir sla '05_-_Help!/13_-_Yesterday' ext]};
+        case 'testcometogether' 
+            filenames = {...
+                [data_dir sla '11_-_Abbey_Road/01_-_Come_Together' ext]};
+        case 'testfriends' 
+            filenames = {...
+                [data_dir sla 'nonBeatles/15-Friends Will Be Friends' ext]};
+        case 'testfriends2' 
+            filenames = {...
+                ['/Volumes/Private/iTunes/iTunes Music/Queen/A Kind of Magic/05 Friends will be Friends' ext]};
+        case 'carole'
+            filenames = {...
+                [data_dir sla 'Carole King/Tapestry/06 Way Over Yonder' ext],...
+                [data_dir sla 'Carole King/Tapestry/05 Beautiful' ext],...
+                [data_dir sla 'Carole King/Tapestry/04 Home Again' ext],...
+                [data_dir sla 'Carole King/Tapestry/03 It''s Too Late' ext],...
+                [data_dir sla 'Carole King/Tapestry/02 So Far Away' ext],...
+                [data_dir sla 'Carole King/Tapestry/01 I Feel The Earth Move' ext],...
+                [data_dir sla 'Carole King/Tapestry/11 Tapestry' ext],...
+                [data_dir sla 'Carole King/Tapestry/10 Smackwater Jack' ext],...
+                [data_dir sla 'Carole King/Tapestry/09 Will You Love Me Tomorrow_' ext],...
+                [data_dir sla 'Carole King/Tapestry/08 Where You Lead' ext],...
+                [data_dir sla 'Carole King/Tapestry/07 You''ve Got A Friend' ext],...
+                [data_dir sla 'Carole King/Tapestry/14 Smackwater Jack [Live]' ext],...
+                [data_dir sla 'Carole King/Tapestry/13 Out In The Cold' ext],...
+                [data_dir sla 'Carole King/Tapestry/12 Feel Like A Natural Woman' ext]};
+        case 'u2'
+            filenames = {...
+                [data_dir sla 'U2/U218 Singles/02 Beautiful Day' ext]};
+        case 'dinverno'
+            filenames = { ...
+                ['/Volumes/Private/CubaseProjects/dinverno/Audio/dinverno_autumnleaves1' ext],...
+                ['/Volumes/Private/CubaseProjects/dinverno/Audio/dinverno_autumnleaves2' ext],...
+                ['/Volumes/Private/CubaseProjects/dinverno/Audio/dinverno_shookup1' ext],...
+                ['/Volumes/Private/CubaseProjects/dinverno/Audio/dinverno_helpfrommyfriends1' ext],...
+                ['/Volumes/Private/CubaseProjects/dinverno/Audio/dinverno_autumnleaves3' ext]};
+        case '01_-_Please_Please_Me'
+            filenames = {...
+                [data_dir sla '01_-_Please_Please_Me/01_-_I_Saw_Her_Standing_There' ext],...
+                [data_dir sla '01_-_Please_Please_Me/02_-_Misery' ext],...
+                [data_dir sla '01_-_Please_Please_Me/03_-_Anna_(Go_To_Him)' ext],...
+                [data_dir sla '01_-_Please_Please_Me/04_-_Chains' ext],...
+                [data_dir sla '01_-_Please_Please_Me/05_-_Boys' ext],...
+                [data_dir sla '01_-_Please_Please_Me/06_-_Ask_Me_Why' ext],...
+                [data_dir sla '01_-_Please_Please_Me/07_-_Please_Please_Me' ext],...
+                [data_dir sla '01_-_Please_Please_Me/08_-_Love_Me_Do' ext],...
+                [data_dir sla '01_-_Please_Please_Me/09_-_P._S._I_Love_You' ext],...
+                [data_dir sla '01_-_Please_Please_Me/10_-_Baby_It''s_You' ext],...
+                [data_dir sla '01_-_Please_Please_Me/11_-_Do_You_Want_To_Know_A_Secret' ext],...
+                ...[data_dir sla '01_-_Please_Please_Me/12_-_A_Taste_Of_Honey' ext],...
+                [data_dir sla '01_-_Please_Please_Me/13_-_There''s_A_Place' ext],...
+                [data_dir sla '01_-_Please_Please_Me/14_-_Twist_And_Shout' ext]};
+
+        case '02_-_With_the_Beatles'
+            filenames = {...
+                [data_dir sla '02_-_With_the_Beatles/01_-_It_Won''t_Be_Long' ext],...
+                [data_dir sla '02_-_With_the_Beatles/02_-_All_I''ve_Got_To_Do' ext],...
+                [data_dir sla '02_-_With_the_Beatles/03_-_All_My_Loving' ext],...
+                [data_dir sla '02_-_With_the_Beatles/04_-_Don''t_Bother_Me' ext],...
+                [data_dir sla '02_-_With_the_Beatles/05_-_Little_Child' ext],...
+                [data_dir sla '02_-_With_the_Beatles/06_-_Till_There_Was_You' ext],...
+                [data_dir sla '02_-_With_the_Beatles/07_-_Please_Mister_Postman' ext],...
+                [data_dir sla '02_-_With_the_Beatles/08_-_Roll_Over_Beethoven' ext],...
+                [data_dir sla '02_-_With_the_Beatles/09_-_Hold_Me_Tight' ext],...
+                ...[data_dir sla '02_-_With_the_Beatles/10_-_You_Really_Got_A_Hold_On_Me' ext],...
+                [data_dir sla '02_-_With_the_Beatles/11_-_I_Wanna_Be_Your_Man' ext],...
+                [data_dir sla '02_-_With_the_Beatles/12_-_Devil_In_Her_Heart' ext],...
+                [data_dir sla '02_-_With_the_Beatles/13_-_Not_A_Second_Time' ext],...
+                [data_dir sla '02_-_With_the_Beatles/14_-_Money' ext]};
+
+        case '03_-_A_Hard_Day''s_Night'
+            filenames = {...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/01_-_A_Hard_Day''s_Night' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/02_-_I_Should_Have_Known_Better' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/03_-_If_I_Fell' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/04_-_I''m_Happy_Just_To_Dance_With_You' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/05_-_And_I_Love_Her' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/06_-_Tell_Me_Why' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/07_-_Can''t_Buy_Me_Love' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/08_-_Any_Time_At_All' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/09_-_I''ll_Cry_Instead' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/10_-_Things_We_Said_Today' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/11_-_When_I_Get_Home' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/12_-_You_Can''t_Do_That' ext],...
+                [data_dir sla '03_-_A_Hard_Day''s_Night/13_-_I''ll_Be_Back' ext]};
+
+
+        case '04_-_Beatles_for_Sale'
+            filenames = {...
+                [data_dir sla '04_-_Beatles_for_Sale/01_-_No_Reply' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/02_-_I''m_a_Loser' ext],...
+                ...[data_dir sla '04_-_Beatles_for_Sale/03_-_Baby''s_In_Black' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/04_-_Rock_and_Roll_Music' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/05_-_I''ll_Follow_the_Sun' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/06_-_Mr._Moonlight' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/07_-_Kansas_City-_Hey,_Hey,_Hey,_Hey' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/08_-_Eight_Days_a_Week' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/09_-_Words_of_Love' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/10_-_Honey_Don''t' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/11_-_Every_Little_Thing' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/12_-_I_Don''t_Want_to_Spoil_the_Party' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/13_-_What_You''re_Doing' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/14_-_Everybody''s_Trying_to_Be_My_Baby' ext]};
+
+
+        case '05_-_Help!'
+            filenames = {...
+                [data_dir sla '05_-_Help!/01_-_Help!' ext],...
+                [data_dir sla '05_-_Help!/02_-_The_Night_Before' ext],...
+                ...[data_dir sla '05_-_Help!/03_-_You''ve_Got_To_Hide_Your_Love_Away' ext],...
+                [data_dir sla '05_-_Help!/04_-_I_Need_You' ext],...
+                [data_dir sla '05_-_Help!/05_-_Another_Girl' ext],...
+                [data_dir sla '05_-_Help!/06_-_You''re_Going_to_Lose_That_Girl' ext],...
+                [data_dir sla '05_-_Help!/07_-_Ticket_To_Ride' ext],...
+                [data_dir sla '05_-_Help!/08_-_Act_Naturally' ext],...
+                [data_dir sla '05_-_Help!/09_-_It''s_Only_Love' ext],...
+                [data_dir sla '05_-_Help!/10_-_You_Like_Me_Too_Much' ext],...
+                [data_dir sla '05_-_Help!/11_-_Tell_Me_What_You_See' ext],...
+                [data_dir sla '05_-_Help!/12_-_I''ve_Just_Seen_a_Face' ext],...
+                [data_dir sla '05_-_Help!/13_-_Yesterday' ext],...
+                [data_dir sla '05_-_Help!/14_-_Dizzy_Miss_Lizzy' ext]};
+
+        case '06_-_Rubber_Soul'
+            filenames = {...
+                [data_dir sla '06_-_Rubber_Soul/01_-_Drive_My_Car' ext],...
+                ...            [data_dir sla '06_-_Rubber_Soul/02_-_Norwegian_Wood_(This_Bird_Has_Flown)' ext],...
+                [data_dir sla '06_-_Rubber_Soul/03_-_You_Won''t_See_Me' ext],...
+                [data_dir sla '06_-_Rubber_Soul/04_-_Nowhere_Man' ext],...
+                [data_dir sla '06_-_Rubber_Soul/05_-_Think_For_Yourself' ext],...
+                [data_dir sla '06_-_Rubber_Soul/06_-_The_Word' ext],...
+                [data_dir sla '06_-_Rubber_Soul/07_-_Michelle' ext],...
+                [data_dir sla '06_-_Rubber_Soul/08_-_What_Goes_On' ext],...
+                [data_dir sla '06_-_Rubber_Soul/09_-_Girl' ext],...
+                [data_dir sla '06_-_Rubber_Soul/10_-_I''m_Looking_Through_You' ext],...
+                [data_dir sla '06_-_Rubber_Soul/11_-_In_My_Life' ext],...
+                [data_dir sla '06_-_Rubber_Soul/12_-_Wait' ext],...
+                [data_dir sla '06_-_Rubber_Soul/13_-_If_I_Needed_Someone' ext],...
+                [data_dir sla '06_-_Rubber_Soul/14_-_Run_For_Your_Life' ext]};
+
+        case '07_-_Revolver'
+            filenames = {...
+                [data_dir sla '07_-_Revolver/01_-_Taxman' ext],...
+                [data_dir sla '07_-_Revolver/02_-_Eleanor_Rigby' ext],...
+                [data_dir sla '07_-_Revolver/03_-_I''m_Only_Sleeping' ext],...
+                ...[data_dir sla '07_-_Revolver/04_-_Love_You_To' ext],...
+                [data_dir sla '07_-_Revolver/05_-_Here,_There_And_Everywhere' ext],...
+                [data_dir sla '07_-_Revolver/06_-_Yellow_Submarine' ext],...
+                [data_dir sla '07_-_Revolver/07_-_She_Said_She_Said' ext],...
+                ...[data_dir sla '07_-_Revolver/08_-_Good_Day_Sunshine' ext],...
+                [data_dir sla '07_-_Revolver/09_-_And_Your_Bird_Can_Sing' ext],...
+                [data_dir sla '07_-_Revolver/10_-_For_No_One' ext],...
+                [data_dir sla '07_-_Revolver/11_-_Doctor_Robert' ext],...
+                [data_dir sla '07_-_Revolver/12_-_I_Want_To_Tell_You' ext],...
+                [data_dir sla '07_-_Revolver/13_-_Got_To_Get_You_Into_My_Life' ext],...
+                ...[data_dir sla '07_-_Revolver/14_-_Tomorrow_Never_Knows' ext]...
+                };
+
+        case  '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band'
+            filenames = {...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/01_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/02_-_With_A_Little_Help_From_My_Friends' ext],...
+                ...[data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/03_-_Lucy_In_The_Sky_With_Diamonds' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/04_-_Getting_Better' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/05_-_Fixing_A_Hole' ext],...
+                ...[data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/06_-_She''s_Leaving_Home' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/07_-_Being_For_The_Benefit_Of_Mr._Kite!' ext],...
+                ...[data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/08_-_Within_You_Without_You' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/09_-_When_I''m_Sixty-Four' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/10_-_Lovely_Rita' ext],...
+                ...[data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/11_-_Good_Morning_Good_Morning' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/12_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band_(Reprise)' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/13_-_A_Day_In_The_Life' ext]};
+
+        case '09_-_Magical_Mystery_Tour'
+            filenames = {...
+                [data_dir sla '09_-_Magical_Mystery_Tour/01_-_Magical_Mystery_Tour' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/02_-_The_Fool_On_The_Hill' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/03_-_Flying' ext],...
+                ...[data_dir sla '09_-_Magical_Mystery_Tour/04_-_Blue_Jay_Way' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/05_-_Your_Mother_Should_Know' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/06_-_I_Am_The_Walrus' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/07_-_Hello_Goodbye' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/08_-_Strawberry_Fields_Forever' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/09_-_Penny_Lane' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/10_-_Baby_You''re_A_Rich_Man' ext],...
+                ...[data_dir sla '09_-_Magical_Mystery_Tour/11_-_All_You_Need_Is_Love' ext] ...
+                };
+
+        case '10CD1_-_The_Beatles'
+            filenames = {...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_01_-_Back_in_the_USSR' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_02_-_Dear_Prudence' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_03_-_Glass_Onion' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_04_-_Ob-La-Di,_Ob-La-Da' ext],...
+                ...[data_dir sla '10CD1_-_The_Beatles/CD1_-_05_-_Wild_Honey_Pie' ext],...
+                ...[data_dir sla '10CD1_-_The_Beatles/CD1_-_06_-_The_Continuing_Story_of_Bungalow_Bill' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_07_-_While_My_Guitar_Gently_Weeps' ext],...
+                ...[data_dir sla '10CD1_-_The_Beatles/CD1_-_08_-_Happiness_is_a_Warm_Gun' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_09_-_Martha_My_Dear' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_10_-_I''m_So_Tired' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_11_-_Black_Bird' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_12_-_Piggies' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_13_-_Rocky_Raccoon' ext],...
+                ...[data_dir sla '10CD1_-_The_Beatles/CD1_-_14_-_Don''t_Pass_Me_By' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_15_-_Why_Don''t_We_Do_It_In_The_Road' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_16_-_I_Will' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_17_-_Julia' ext]};
+
+        case '10CD2_-_The_Beatles'
+            filenames = {...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_01_-_Birthday' ext],...
+                ...[data_dir sla '10CD2_-_The_Beatles/CD2_-_02_-_Yer_Blues' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_03_-_Mother_Nature''s_Son' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_04_-_Everybody''s_Got_Something_To_Hide_Except_Me_and_M' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_05_-_Sexy_Sadie' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_06_-_Helter_Skelter' ext],...
+                ...[data_dir sla '10CD2_-_The_Beatles/CD2_-_07_-_Long_Long_Long' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_08_-_Revolution_1' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_09_-_Honey_Pie' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_10_-_Savoy_Truffle' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_11_-_Cry_Baby_Cry' ext],...
+                ...[data_dir sla '10CD2_-_The_Beatles/CD2_-_12_-_Revolution_9' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_13_-_Good_Night' ext]};
+
+        case '11_-_Abbey_Road'
+            filenames = {...
+                [data_dir sla '11_-_Abbey_Road/01_-_Come_Together' ext],...
+                [data_dir sla '11_-_Abbey_Road/02_-_Something' ext],...
+                [data_dir sla '11_-_Abbey_Road/03_-_Maxwell''s_Silver_Hammer' ext],...
+                ...[data_dir sla '11_-_Abbey_Road/04_-_Oh!_Darling' ext],...
+                [data_dir sla '11_-_Abbey_Road/05_-_Octopus''s_Garden' ext],...
+                ...[data_dir sla '11_-_Abbey_Road/06_-_I_Want_You' ext],...
+                [data_dir sla '11_-_Abbey_Road/07_-_Here_Comes_The_Sun' ext],...
+                [data_dir sla '11_-_Abbey_Road/08_-_Because' ext],...
+                [data_dir sla '11_-_Abbey_Road/09_-_You_Never_Give_Me_Your_Money' ext],...
+                [data_dir sla '11_-_Abbey_Road/10_-_Sun_King' ext],...
+                [data_dir sla '11_-_Abbey_Road/11_-_Mean_Mr_Mustard' ext],...
+                [data_dir sla '11_-_Abbey_Road/12_-_Polythene_Pam' ext],...
+                [data_dir sla '11_-_Abbey_Road/13_-_She_Came_In_Through_The_Bathroom_Window' ext],...
+                [data_dir sla '11_-_Abbey_Road/14_-_Golden_Slumbers' ext],...
+                [data_dir sla '11_-_Abbey_Road/15_-_Carry_That_Weight' ext],...
+                [data_dir sla '11_-_Abbey_Road/16_-_The_End' ext],...
+                [data_dir sla '11_-_Abbey_Road/17_-_Her_Majesty' ext]};
+
+        case '12_-_Let_It_Be'
+            filenames = {...
+                ...[data_dir sla '12_-_Let_It_Be/01_-_Two_of_Us' ext],...
+                ...[data_dir sla '12_-_Let_It_Be/02_-_Dig_a_Pony' ext],...
+                [data_dir sla '12_-_Let_It_Be/03_-_Across_the_Universe' ext],...
+                ...            [data_dir sla '12_-_Let_It_Be/04_-_I_Me_Mine' ext],...
+                ...            [data_dir sla '12_-_Let_It_Be/05_-_Dig_It' ext],...
+                [data_dir sla '12_-_Let_It_Be/06_-_Let_It_Be' ext],...
+                [data_dir sla '12_-_Let_It_Be/07_-_Maggie_Mae' ext],...
+                [data_dir sla '12_-_Let_It_Be/08_-_I''ve_Got_A_Feeling' ext],...
+                [data_dir sla '12_-_Let_It_Be/09_-_One_After_909' ext],...
+                [data_dir sla '12_-_Let_It_Be/10_-_The_Long_and_Winding_Road' ext],...
+                [data_dir sla '12_-_Let_It_Be/11_-_For_You_Blue' ext],...
+                [data_dir sla '12_-_Let_It_Be/12_-_Get_Back' ext]};
+        case 'discarded'
+            filenames = {...
+                [data_dir sla '01_-_Please_Please_Me/12_-_A_Taste_Of_Honey' ext],...
+                [data_dir sla '02_-_With_the_Beatles/10_-_You_Really_Got_A_Hold_On_Me' ext],...
+                [data_dir sla '04_-_Beatles_for_Sale/03_-_Baby''s_In_Black' ext],...
+                [data_dir sla '05_-_Help!/03_-_You''ve_Got_To_Hide_Your_Love_Away' ext],...
+                [data_dir sla '06_-_Rubber_Soul/02_-_Norwegian_Wood_(This_Bird_Has_Flown)' ext],...
+                [data_dir sla '07_-_Revolver/04_-_Love_You_To' ext],...
+                [data_dir sla '07_-_Revolver/08_-_Good_Day_Sunshine' ext],...
+                [data_dir sla '07_-_Revolver/14_-_Tomorrow_Never_Knows' ext]...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/03_-_Lucy_In_The_Sky_With_Diamonds' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/06_-_She''s_Leaving_Home' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/08_-_Within_You_Without_You' ext],...
+                [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/11_-_Good_Morning_Good_Morning' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/04_-_Blue_Jay_Way' ext],...
+                [data_dir sla '09_-_Magical_Mystery_Tour/11_-_All_You_Need_Is_Love' ext] ...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_05_-_Wild_Honey_Pie' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_02_-_Yer_Blues' ext],...
+                [data_dir sla '10CD2_-_The_Beatles/CD2_-_07_-_Long_Long_Long' ext],...
+                [data_dir sla '11_-_Abbey_Road/04_-_Oh!_Darling' ext],...
+                [data_dir sla '12_-_Let_It_Be/01_-_Two_of_Us' ext],...
+                [data_dir sla '12_-_Let_It_Be/02_-_Dig_a_Pony' ext],...
+                [data_dir sla '12_-_Let_It_Be/04_-_I_Me_Mine' ext],...
+                [data_dir sla '12_-_Let_It_Be/05_-_Dig_It' ext],...
+                [data_dir sla '11_-_Abbey_Road/06_-_I_Want_You' ext]...
+                    };
+        case 'notinMIREX'
+            filenames = {...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_06_-_The_Continuing_Story_of_Bungalow_Bill' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_14_-_Don''t_Pass_Me_By' ext],...
+                [data_dir sla '10CD1_-_The_Beatles/CD1_-_08_-_Happiness_is_a_Warm_Gun' ext],...
+                    };
+        case 'revolution9'
+            filenames = {[data_dir sla '10CD2_-_The_Beatles/CD2_-_12_-_Revolution_9' ext]};
+        case 'leftovers'
+            filenames = {...
+                          [data_dir sla '08_-_Sgt._Pepper''s_Lonely_Hearts_Club_Band/06_-_She''s_Leaving_Home' ext],...
+                          [data_dir sla '07_-_Revolver/04_-_Love_You_To' ext],...
+                };
+        case 'semma'
+            filenames = {...
+                [data_dir sla 'SeMMA/audio/Britney_Spear_##_Baby_Hit_Me_One_More_Time', ext],...
+                [data_dir sla 'SeMMA/audio/Bjork_##_Its_Oh_So_Quiet', ext],...
+                [data_dir sla 'SeMMA/audio/Alanis_Morissette_##_Thank_U', ext],...
+                [data_dir sla 'SeMMA/audio/Alanis_Morissette_##_Head_Over_Feet', ext],...
+                [data_dir sla 'SeMMA/audio/A_Ha_##_Take_On_Me', ext],...
+                [data_dir sla 'SeMMA/audio/The_Clash_##_Should_I_Stay_Or_Should_I_Go', ext],...
+                [data_dir sla 'SeMMA/audio/Spice_Girls_##_Wannabe', ext],...
+                [data_dir sla 'SeMMA/audio/Seal_##_Crazy', ext],...
+                [data_dir sla 'SeMMA/audio/Radiohead_##_Creep', ext],...
+                [data_dir sla 'SeMMA/audio/Oasis_##_Wonderwall', ext],...
+                [data_dir sla 'SeMMA/audio/Nirvana_##_Smells_Like_Teen_Spirit', ext],...
+                [data_dir sla 'SeMMA/audio/Deus_##_Suds_and_Soda', ext],...
+                [data_dir sla 'SeMMA/audio/Cranberries_##_Zombie', ext],...
+                [data_dir sla 'SeMMA/audio/Chumbawamba_##_Tubthumping', ext],...
+                };
+    end
+    allfilenames = [allfilenames,filenames];
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/qnorm.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,15 @@
+function s = qnorm(inmat, varargin)
+dim = 1;
+if nargin > 1
+    q = varargin{1};
+    if nargin > 2
+        dim = varargin{2};
+    end
+else
+    q = 2;
+end
+if ~(q == Inf)
+    s = sum(inmat.^q,dim).^(1/q);
+else
+    s = max(inmat,[],dim);
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/general/qnormalise.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,17 @@
+function [outmat, scale] = qnormalise(inmat, varargin)
+% qnormalise(inmat, q, dim) returns the field inmat normalised by the q
+% norm over dimension dim
+dim = 1;
+if nargin > 1
+    q = varargin{1};
+    if nargin > 2
+        dim = varargin{2};
+    end
+else
+    q = 2;
+end
+sizeInmat = size(inmat);
+nDim = length(sizeInmat);
+repeatpattern = [ones(1,dim-1) sizeInmat(dim) ones(1,nDim-dim)];
+scale = qnorm(inmat, q, dim);
+outmat = inmat ./ repmat(scale, repeatpattern);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/kde.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,98 @@
+function [bandwidth,density,xmesh]=kde(data,n,MIN,MAX)
+% Reliable and extremely fast kernel density estimator for 1 dimensional data;
+%        Gaussian kernel is assumed and the bandwidth is chosen automatically;
+%
+% INPUTS:
+%     data    - a vector of data from which the density estimate is constructed;
+%   MIN, MAX  - defines the interval [MIN,MAX] on which the density estimate is constructed;
+%               the default values of MIN and MAX are: 
+%               MIN=min(data)-Range/100 and MAX=max(data)+Range/100, where Range=max(data)-min(data);   
+%          n  - the number of mesh points used in the uniform discretization of the
+%               interval [MIN, MAX]; n has to be a power of two; if n is not a power of two, then
+%               n is rounded up to the next power of two, i.e., n is set to n=2^ceil(log2(n));
+%               the default value of n is n=2^12;
+% OUTPUTS:
+%   bandwidth - the optimal bandwidth (Gaussian kernel assumed);
+%     density - column vector of length 'n' with the values of the density
+%               estimate at the grid points;
+%     xmesh   - the grid over which the density estimate is computed;
+%  Reference: Botev, Z. I.,
+%             "A Novel Nonparametric Density Estimator",Technical Report,The University of Queensland
+%             http://espace.library.uq.edu.au/view.php?pid=UQ:12535
+%
+%  Example:
+%    data=randn(1000,1); 
+%    [bandwidth,density,xmesh]=kde(data,2^12,min(data)-1,max(data)+1);
+%    plot(xmesh,density)
+
+data=data(:); %make data a column vector
+if nargin<2 % if n is not supplied switch to the default
+    n=2^12;
+end
+n=2^ceil(log2(n)); % round up n to the next power of 2;
+
+if nargin<4 %define the default  interval [MIN,MAX]
+    minimum=min(data); maximum=max(data);
+    Range=maximum-minimum;
+    MIN=minimum-Range/10; MAX=maximum+Range/10;
+end
+% set up the grid over which the density estimate is computed;
+R=MAX-MIN; dx=R/(n-1); xmesh=MIN+[0:dx:R]; N=length(data);
+%bin the data uniformly using the grid define above;
+initial_data=histc(data,xmesh)/N;
+a=dct1d(initial_data); % discrete cosine transform of initial data
+% now compute the optimal bandwidth^2 using the GCE method
+t_star=gce(a,n,N);
+% smooth the discrete cosine transform of initial data using t_star
+a_t=a.*exp(-[0:n-1]'.^2*pi^2*t_star/2);
+% now apply the inverse discrete cosine transform
+  if nargout>1
+    density=idct1d(a_t)/R;
+  end
+bandwidth=sqrt(t_star)*R;
+end
+function t_star=gce(a,n,N)
+a=a(2:end)/2;
+I=[1:n-1]'.^2;
+a2=a.^2;
+Var_a=zeros(n-1,1);
+Var_a(1:n/2-1)=(1/2+1/2*a(2:2:n-1)-a2(1:n/2-1))/N;
+
+t_star=fzero(@mise,[0,1]);
+NORM=2*pi^4*sum(I.^2.*a2.*exp(-I*pi^2*t_star));
+%NORM=.5*pi^4*sum([1:n-1]'.^4.*a_t(2:end).^2)/R^5;
+t_star=[2*N*sqrt(pi)*NORM]^(-2/5);
+    function  out=mise(t)
+
+        out=sum((a2+Var_a).*(1-exp(-I*pi^2*t/2)).^2./I)+...
+            sqrt(t/pi)/N*(pi^2/2)-sum(Var_a./I);
+    end
+end
+
+function data=dct1d(data)
+% computes the discrete cosine transform of the column vector data
+[nrows,ncols]= size(data);
+% Compute weights to multiply DFT coefficients
+weight = [1;2*(exp(-i*(1:nrows-1)*pi/(2*nrows))).'];
+% Re-order the elements of the columns of x
+data = [ data(1:2:end,:); data(end:-2:2,:) ];
+% Multiply FFT by weights:
+data= real(weight.* fft(data));
+end
+function out = idct1d(data)
+% computes the inverse discrete cosine transform
+[nrows,ncols]=size(data);
+% Compute weights
+weights = nrows*exp(i*(0:nrows-1)*pi/(2*nrows)).';
+% Compute x tilde using equation (5.93) in Jain
+data = real(ifft(weights.*data));
+% Re-order elements of each column according to equations (5.93) and
+% (5.94) in Jain
+out = zeros(nrows,1);
+out(1:2:nrows) = data(1:nrows/2);
+out(2:2:nrows) = data(nrows:-1:nrows/2+1);
+%   Reference: 
+%      A. K. Jain, "Fundamentals of Digital Image
+%      Processing", pp. 150-153.
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/probability/.svn/all-wcprops	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 55
+/svnroot/!svn/ver/1425/matlabtoolboxes/misc/probability
+END
+KLDiv.m
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svnroot/!svn/ver/1425/matlabtoolboxes/misc/probability/KLDiv.m
+END
+JSDiv.m
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svnroot/!svn/ver/1425/matlabtoolboxes/misc/probability/JSDiv.m
+END
+kde.m
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svnroot/!svn/ver/1425/matlabtoolboxes/misc/probability/kde.m
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/probability/.svn/entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,130 @@
+10
+
+dir
+7329
+https://parrot.dcs.qmul.ac.uk/svnroot/matlabtoolboxes/misc/probability
+https://parrot.dcs.qmul.ac.uk/svnroot
+
+
+
+2009-03-06T16:34:10.036388Z
+1425
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+214cd2a9-030a-0410-b9a1-da4e402363b6
+
+KLDiv.m
+file
+
+
+
+
+2010-04-07T10:16:14.000000Z
+283dfddcbfb2419c115d1fd071673485
+2009-03-06T16:34:10.036388Z
+1425
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+881
+
+JSDiv.m
+file
+
+
+
+
+2010-04-07T10:16:14.000000Z
+e64eca575121a7d8b4fd79b6224adbd9
+2009-03-06T16:34:10.036388Z
+1425
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+601
+
+kde.m
+file
+
+
+
+
+2010-04-07T10:16:14.000000Z
+2e692dc92798b5446318544dd2f9d684
+2009-03-06T16:34:10.036388Z
+1425
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3883
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/probability/.svn/prop-base/kde.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/probability/.svn/text-base/JSDiv.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+function dist=JSDiv(P,Q)
+% Jensen-Shannon divergence of two probability distributions
+%  dist = JSD(P,Q) Kullback-Leibler divergence of two discrete probability
+%  distributions
+%  P and Q  are automatically normalised to have the sum of one on rows
+% have the length of one at each 
+% P =  n x nbins
+% Q =  1 x nbins
+% dist = n x 1
+
+
+if size(P,2)~=size(Q,2)
+    error('the number of columns in P and Q should be the same');
+end
+
+% normalizing the P and Q
+Q = Q ./sum(Q);
+Q = repmat(Q,[size(P,1) 1]);
+P = P ./repmat(sum(P,2),[1 size(P,2)]);
+
+M = 0.5.*(P + Q);
+
+dist = 0.5.*KLDiv(P,M) + 0.5*KLDiv(Q,M);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/probability/.svn/text-base/KLDiv.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,35 @@
+function dist=KLDiv(P,Q)
+%  dist = KLDiv(P,Q) Kullback-Leibler divergence of two discrete probability
+%  distributions
+%  P and Q  are automatically normalised to have the sum of one on rows
+% have the length of one at each 
+% P =  n x nbins
+% Q =  1 x nbins or n x nbins(one to one)
+% dist = n x 1
+
+
+
+if size(P,2)~=size(Q,2)
+    error('the number of columns in P and Q should be the same');
+end
+
+if sum(~isfinite(P(:))) + sum(~isfinite(Q(:)))
+   error('the inputs contain non-finite values!') 
+end
+
+% normalizing the P and Q
+if size(Q,1)==1
+    Q = Q ./sum(Q);
+    P = P ./repmat(sum(P,2),[1 size(P,2)]);
+    dist =  sum(P.*log(P./repmat(Q,[size(P,1) 1])),2);
+    
+elseif size(Q,1)==size(P,1)
+    
+    Q = Q ./repmat(sum(Q,2),[1 size(Q,2)]);
+    P = P ./repmat(sum(P,2),[1 size(P,2)]);
+    dist =  sum(P.*log(P./Q),2);
+end
+
+% resolving the case when P(i)==0
+dist(isnan(dist))=0;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/probability/.svn/text-base/kde.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,98 @@
+function [bandwidth,density,xmesh]=kde(data,n,MIN,MAX)
+% Reliable and extremely fast kernel density estimator for 1 dimensional data;
+%        Gaussian kernel is assumed and the bandwidth is chosen automatically;
+%
+% INPUTS:
+%     data    - a vector of data from which the density estimate is constructed;
+%   MIN, MAX  - defines the interval [MIN,MAX] on which the density estimate is constructed;
+%               the default values of MIN and MAX are: 
+%               MIN=min(data)-Range/100 and MAX=max(data)+Range/100, where Range=max(data)-min(data);   
+%          n  - the number of mesh points used in the uniform discretization of the
+%               interval [MIN, MAX]; n has to be a power of two; if n is not a power of two, then
+%               n is rounded up to the next power of two, i.e., n is set to n=2^ceil(log2(n));
+%               the default value of n is n=2^12;
+% OUTPUTS:
+%   bandwidth - the optimal bandwidth (Gaussian kernel assumed);
+%     density - column vector of length 'n' with the values of the density
+%               estimate at the grid points;
+%     xmesh   - the grid over which the density estimate is computed;
+%  Reference: Botev, Z. I.,
+%             "A Novel Nonparametric Density Estimator",Technical Report,The University of Queensland
+%             http://espace.library.uq.edu.au/view.php?pid=UQ:12535
+%
+%  Example:
+%    data=randn(1000,1); 
+%    [bandwidth,density,xmesh]=kde(data,2^12,min(data)-1,max(data)+1);
+%    plot(xmesh,density)
+
+data=data(:); %make data a column vector
+if nargin<2 % if n is not supplied switch to the default
+    n=2^12;
+end
+n=2^ceil(log2(n)); % round up n to the next power of 2;
+
+if nargin<4 %define the default  interval [MIN,MAX]
+    minimum=min(data); maximum=max(data);
+    Range=maximum-minimum;
+    MIN=minimum-Range/10; MAX=maximum+Range/10;
+end
+% set up the grid over which the density estimate is computed;
+R=MAX-MIN; dx=R/(n-1); xmesh=MIN+[0:dx:R]; N=length(data);
+%bin the data uniformly using the grid define above;
+initial_data=histc(data,xmesh)/N;
+a=dct1d(initial_data); % discrete cosine transform of initial data
+% now compute the optimal bandwidth^2 using the GCE method
+t_star=gce(a,n,N);
+% smooth the discrete cosine transform of initial data using t_star
+a_t=a.*exp(-[0:n-1]'.^2*pi^2*t_star/2);
+% now apply the inverse discrete cosine transform
+  if nargout>1
+    density=idct1d(a_t)/R;
+  end
+bandwidth=sqrt(t_star)*R;
+end
+function t_star=gce(a,n,N)
+a=a(2:end)/2;
+I=[1:n-1]'.^2;
+a2=a.^2;
+Var_a=zeros(n-1,1);
+Var_a(1:n/2-1)=(1/2+1/2*a(2:2:n-1)-a2(1:n/2-1))/N;
+
+t_star=fzero(@mise,[0,1]);
+NORM=2*pi^4*sum(I.^2.*a2.*exp(-I*pi^2*t_star));
+%NORM=.5*pi^4*sum([1:n-1]'.^4.*a_t(2:end).^2)/R^5;
+t_star=[2*N*sqrt(pi)*NORM]^(-2/5);
+    function  out=mise(t)
+
+        out=sum((a2+Var_a).*(1-exp(-I*pi^2*t/2)).^2./I)+...
+            sqrt(t/pi)/N*(pi^2/2)-sum(Var_a./I);
+    end
+end
+
+function data=dct1d(data)
+% computes the discrete cosine transform of the column vector data
+[nrows,ncols]= size(data);
+% Compute weights to multiply DFT coefficients
+weight = [1;2*(exp(-i*(1:nrows-1)*pi/(2*nrows))).'];
+% Re-order the elements of the columns of x
+data = [ data(1:2:end,:); data(end:-2:2,:) ];
+% Multiply FFT by weights:
+data= real(weight.* fft(data));
+end
+function out = idct1d(data)
+% computes the inverse discrete cosine transform
+[nrows,ncols]=size(data);
+% Compute weights
+weights = nrows*exp(i*(0:nrows-1)*pi/(2*nrows)).';
+% Compute x tilde using equation (5.93) in Jain
+data = real(ifft(weights.*data));
+% Re-order elements of each column according to equations (5.93) and
+% (5.94) in Jain
+out = zeros(nrows,1);
+out(1:2:nrows) = data(1:nrows/2);
+out(2:2:nrows) = data(nrows:-1:nrows/2+1);
+%   Reference: 
+%      A. K. Jain, "Fundamentals of Digital Image
+%      Processing", pp. 150-153.
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/probability/JSDiv.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+function dist=JSDiv(P,Q)
+% Jensen-Shannon divergence of two probability distributions
+%  dist = JSD(P,Q) Kullback-Leibler divergence of two discrete probability
+%  distributions
+%  P and Q  are automatically normalised to have the sum of one on rows
+% have the length of one at each 
+% P =  n x nbins
+% Q =  1 x nbins
+% dist = n x 1
+
+
+if size(P,2)~=size(Q,2)
+    error('the number of columns in P and Q should be the same');
+end
+
+% normalizing the P and Q
+Q = Q ./sum(Q);
+Q = repmat(Q,[size(P,1) 1]);
+P = P ./repmat(sum(P,2),[1 size(P,2)]);
+
+M = 0.5.*(P + Q);
+
+dist = 0.5.*KLDiv(P,M) + 0.5*KLDiv(Q,M);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/probability/KLDiv.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,35 @@
+function dist=KLDiv(P,Q)
+%  dist = KLDiv(P,Q) Kullback-Leibler divergence of two discrete probability
+%  distributions
+%  P and Q  are automatically normalised to have the sum of one on rows
+% have the length of one at each 
+% P =  n x nbins
+% Q =  1 x nbins or n x nbins(one to one)
+% dist = n x 1
+
+
+
+if size(P,2)~=size(Q,2)
+    error('the number of columns in P and Q should be the same');
+end
+
+if sum(~isfinite(P(:))) + sum(~isfinite(Q(:)))
+   error('the inputs contain non-finite values!') 
+end
+
+% normalizing the P and Q
+if size(Q,1)==1
+    Q = Q ./sum(Q);
+    P = P ./repmat(sum(P,2),[1 size(P,2)]);
+    dist =  sum(P.*log(P./repmat(Q,[size(P,1) 1])),2);
+    
+elseif size(Q,1)==size(P,1)
+    
+    Q = Q ./repmat(sum(Q,2),[1 size(Q,2)]);
+    P = P ./repmat(sum(P,2),[1 size(P,2)]);
+    dist =  sum(P.*log(P./Q),2);
+end
+
+% resolving the case when P(i)==0
+dist(isnan(dist))=0;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/probability/kde.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,98 @@
+function [bandwidth,density,xmesh]=kde(data,n,MIN,MAX)
+% Reliable and extremely fast kernel density estimator for 1 dimensional data;
+%        Gaussian kernel is assumed and the bandwidth is chosen automatically;
+%
+% INPUTS:
+%     data    - a vector of data from which the density estimate is constructed;
+%   MIN, MAX  - defines the interval [MIN,MAX] on which the density estimate is constructed;
+%               the default values of MIN and MAX are: 
+%               MIN=min(data)-Range/100 and MAX=max(data)+Range/100, where Range=max(data)-min(data);   
+%          n  - the number of mesh points used in the uniform discretization of the
+%               interval [MIN, MAX]; n has to be a power of two; if n is not a power of two, then
+%               n is rounded up to the next power of two, i.e., n is set to n=2^ceil(log2(n));
+%               the default value of n is n=2^12;
+% OUTPUTS:
+%   bandwidth - the optimal bandwidth (Gaussian kernel assumed);
+%     density - column vector of length 'n' with the values of the density
+%               estimate at the grid points;
+%     xmesh   - the grid over which the density estimate is computed;
+%  Reference: Botev, Z. I.,
+%             "A Novel Nonparametric Density Estimator",Technical Report,The University of Queensland
+%             http://espace.library.uq.edu.au/view.php?pid=UQ:12535
+%
+%  Example:
+%    data=randn(1000,1); 
+%    [bandwidth,density,xmesh]=kde(data,2^12,min(data)-1,max(data)+1);
+%    plot(xmesh,density)
+
+data=data(:); %make data a column vector
+if nargin<2 % if n is not supplied switch to the default
+    n=2^12;
+end
+n=2^ceil(log2(n)); % round up n to the next power of 2;
+
+if nargin<4 %define the default  interval [MIN,MAX]
+    minimum=min(data); maximum=max(data);
+    Range=maximum-minimum;
+    MIN=minimum-Range/10; MAX=maximum+Range/10;
+end
+% set up the grid over which the density estimate is computed;
+R=MAX-MIN; dx=R/(n-1); xmesh=MIN+[0:dx:R]; N=length(data);
+%bin the data uniformly using the grid define above;
+initial_data=histc(data,xmesh)/N;
+a=dct1d(initial_data); % discrete cosine transform of initial data
+% now compute the optimal bandwidth^2 using the GCE method
+t_star=gce(a,n,N);
+% smooth the discrete cosine transform of initial data using t_star
+a_t=a.*exp(-[0:n-1]'.^2*pi^2*t_star/2);
+% now apply the inverse discrete cosine transform
+  if nargout>1
+    density=idct1d(a_t)/R;
+  end
+bandwidth=sqrt(t_star)*R;
+end
+function t_star=gce(a,n,N)
+a=a(2:end)/2;
+I=[1:n-1]'.^2;
+a2=a.^2;
+Var_a=zeros(n-1,1);
+Var_a(1:n/2-1)=(1/2+1/2*a(2:2:n-1)-a2(1:n/2-1))/N;
+
+t_star=fzero(@mise,[0,1]);
+NORM=2*pi^4*sum(I.^2.*a2.*exp(-I*pi^2*t_star));
+%NORM=.5*pi^4*sum([1:n-1]'.^4.*a_t(2:end).^2)/R^5;
+t_star=[2*N*sqrt(pi)*NORM]^(-2/5);
+    function  out=mise(t)
+
+        out=sum((a2+Var_a).*(1-exp(-I*pi^2*t/2)).^2./I)+...
+            sqrt(t/pi)/N*(pi^2/2)-sum(Var_a./I);
+    end
+end
+
+function data=dct1d(data)
+% computes the discrete cosine transform of the column vector data
+[nrows,ncols]= size(data);
+% Compute weights to multiply DFT coefficients
+weight = [1;2*(exp(-i*(1:nrows-1)*pi/(2*nrows))).'];
+% Re-order the elements of the columns of x
+data = [ data(1:2:end,:); data(end:-2:2,:) ];
+% Multiply FFT by weights:
+data= real(weight.* fft(data));
+end
+function out = idct1d(data)
+% computes the inverse discrete cosine transform
+[nrows,ncols]=size(data);
+% Compute weights
+weights = nrows*exp(i*(0:nrows-1)*pi/(2*nrows)).';
+% Compute x tilde using equation (5.93) in Jain
+data = real(ifft(weights.*data));
+% Re-order elements of each column according to equations (5.93) and
+% (5.94) in Jain
+out = zeros(nrows,1);
+out(1:2:nrows) = data(1:nrows/2);
+out(2:2:nrows) = data(nrows:-1:nrows/2+1);
+%   Reference: 
+%      A. K. Jain, "Fundamentals of Digital Image
+%      Processing", pp. 150-153.
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/tools/.svn/all-wcprops	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 49
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/tools
+END
+localmaxmin.m
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/tools/localmaxmin.m
+END
+getFileDependencies.m
+K 25
+svn:wc:ra_dav:version-url
+V 71
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/tools/getFileDependencies.m
+END
+localmax_logical.m
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svnroot/!svn/ver/1403/matlabtoolboxes/misc/tools/localmax_logical.m
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/tools/.svn/entries	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,130 @@
+10
+
+dir
+7329
+https://parrot.dcs.qmul.ac.uk/svnroot/matlabtoolboxes/misc/tools
+https://parrot.dcs.qmul.ac.uk/svnroot
+
+
+
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+214cd2a9-030a-0410-b9a1-da4e402363b6
+
+localmaxmin.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+ec04f41f5dc39d7c75360f48c3122936
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3662
+
+getFileDependencies.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+82970f27e19757664e2ed6c8128efb4d
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5564
+
+localmax_logical.m
+file
+
+
+
+
+2010-04-07T10:16:15.000000Z
+1164efb3815d15725ad3834ba7352af8
+2009-02-20T16:30:45.085047Z
+1403
+matthiasm
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+203
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/tools/.svn/prop-base/localmax_logical.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/tools/.svn/text-base/getFileDependencies.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,156 @@
+function list =  getFileDependencies(file)
+% searches the paths of the .m-Files the given file is using. This function
+% depends on the depfun-Function of Matlab. Though it is not guaranteed,
+% that all files will be found. E.g. files in evaluate-constructs won't be
+% found!!
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Parameters:
+%     - file: the file for which the dependencies should be searched. This
+%             could be only a string with the function-name, the filename
+%             or the path to a file.
+%
+% Returns:
+%     - list: a cell-Array with the paths to all files the given file uses
+%             as strings. list is -1 if an error occured while processing.
+%             See errormessage for details.
+%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% author:   Torsten Hopp
+% last change: 03.07.2007
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+% checking the input-parameter
+if(isempty(file))
+    disp('ERROR. Input Parameter is empty')
+    list = -1;
+    return;
+end
+if(~ischar(file))
+    disp('ERROR. Input Parameter is not char')
+    list = -1;
+    return;
+end
+
+
+% list: a cell-array for the result
+list = {which(file)};
+% fileList: array of strings to search in the current iteration
+fileList = list;
+
+% While new files where found in last iteration
+while (~isempty(fileList))
+    fileListSize = length(fileList);
+    newOnes = [];
+    newCounter = 1;
+    currentFileList = fileList;
+    fileList = [];
+
+    % running trough the current file list
+    for k=1:fileListSize
+        % calling depfun. -toponly indicates non-recursive search. -quiet
+        % suppresses output to command line
+        templist = depfun(currentFileList{k},'-toponly','-quiet');
+
+        % the first file is already included 
+        templist(1) = []; 
+        
+        % calling the helper-function to delete files which contain
+        % <matlabroot> in the path from the list.
+        templist = deleteMatlabFiles(templist);
+
+        listSize = length(list);
+        tempListSize = length(templist);
+
+        % excluding first iteration with this if-clause
+        if(listSize > 1)
+
+            % comparing lists --> Searching for files that are not in the
+            % list yet
+            for i=1:tempListSize
+                contained = 0;
+                j=1;
+                % first condition stops comparing if something was found.
+                while contained == 0 & j<=listSize
+                    if((strcmp(templist{i},list{j})==1) )
+                        contained = 1;
+                    end
+                    j = j+1;
+                end
+
+                % if file isn't in the list yet...
+                if(contained == 0)
+
+                    % add it to a cellArray for new filenames...
+                    % if-clause excludes first run with empty
+                    % newOnes-variable
+                    if(~isempty(newOnes))
+
+                        % if not first run: comparing the filename with the
+                        % filenames that are in the newOnes-List to avoid
+                        % double-enties
+                        a = strfind(newOnes,templist{i});
+                        counter = 0;
+                        for p=1:length(a)
+                            if(~isempty(a{p}))
+                                counter = counter +1;
+                            end
+                        end
+                        % if not found in list: add it to the list!
+                        if(counter==0)
+                            newOnes{newCounter} = templist{i};
+                            newCounter = newCounter + 1;
+                        end
+                    else
+                        % if list is empty: add it without checking!
+                        newOnes{newCounter} = templist{i};
+                        newCounter = newCounter + 1;
+                    end
+                end
+            end
+
+            % if new filenames where found in this run...
+            if(~isempty(newOnes))
+                % ... search the new found files in the next iteration
+                fileList = [fileList newOnes];
+                % ... add the new found files to the list
+                list(length(list)+1:length(list)+length(newOnes)) = newOnes;
+                newOnes = [];
+                newCounter = 1;
+            end
+        else
+            % if first iteration: set the first-level dependecies as
+            % filelist for next iteration and add them to the list.
+            fileList = templist;
+            list = [list; templist];
+        end
+    end
+end
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% HELPER FUNCTIONS                                                        %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+function rList = deleteMatlabFiles(pList)
+% deletes filenames with matlabroot in path from the given list.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Parameters:
+%     - pList: a cell-Array of filenames as string
+%
+% Returns:
+%     - rList: a cell-Array of filenames as string
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+excludedDir = matlabroot;
+indexes = strfind(pList,excludedDir);
+keepIndexes = cellfun(@isempty,indexes);
+rList = pList(keepIndexes);
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/tools/.svn/text-base/localmax_logical.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function lm = localmax_logical(mat,n)
+
+diffmat = [mat(1,:)*0; sign(diff(mat))]; % !!!! attention rethink the 0!!!!!
+convolver = -[ones(n,1);-ones(n,1)];
+lm = conv2(diffmat,convolver,'same') == 2 * n;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/tools/.svn/text-base/localmaxmin.m.svn-base	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,124 @@
+function [x,n]=localmaxmin(y,xn)
+%LOCALMAXMIN(Y) Local Maxima and Minima.
+% X = LOCALMAXMIN(Y) or LOCALMAXMIN(Y,'max') for vector Y returns a logical
+% vector X the same size as Y such that Y(X) contains the local maxima in Y.
+%
+% N = LOCALMAXMIN(Y,'min') for vector Y returns a logical vector N the same
+% size as Y such that Y(N) contains the local minima in Y.
+%
+% [X,N] = LOCALMAXMIN(Y) for vector Y returns logical vectors X and N such
+% that Y(X) contains the local maxima and Y(N) contains the local minima.
+%
+% When Y is a matrix, outputs are logical array(s) the same size as Y, and
+% the minima and/or maxima are computed down the rows of each column in Y.
+%
+% See also MAX, MIN.
+
+% D.C. Hanselman, University of Maine, Orono, ME 04469
+% MasteringMatlab@yahoo.com
+% Mastering MATLAB 7
+% 2006-03-08
+
+mm=['min';'max'];
+if nargin==1
+   xn='max';
+elseif nargin~=2
+   error('localmaxmin:NotEnoughInputArguments',...
+         'One or Two Input Arguments Required.')
+end
+if ~ischar(xn) || isempty(strcmp(xn,mm))
+   error('localmaxmin:UnknownArgument','Unknown Second Input Argument.')
+end
+if ~isnumeric(y) || ~isreal(y)
+   error('localmaxmin:IncorrectDataType','Y Must be Real Valued.')
+end
+ysiz=size(y);
+isrow=ysiz(1)==1;
+if isrow % if row, convert to column for now
+   y=y';
+   ysiz(1)=ysiz(2);
+   ysiz(2)=1;
+end
+if ysiz(1)<4
+   error('localmaxmin:InsufficientData','Y Must Have at Least 4 Elements.')
+end
+x=false(ysiz);
+   
+sdiff=sign(diff(y));
+zdiff=sdiff==0;
+idz=find(sum(zdiff)); % columns where zero differences appear
+
+if strcmp(xn,'min') || nargout==2   % get minima
+   x(2:end-1,:)=diff(sdiff)==2;
+   x(1,:)=sdiff(1,:)>0;
+   x(end,:)=sdiff(end,:)<0;
+   if any(zdiff)
+      ir=1:ysiz(1);
+      for k=idz % handle columns with zero differences
+         itmp=ir;
+         itmp(zdiff(:,k))=[];
+         if all(sdiff(:,k)==0) % entire column is flat
+            x(:,k)=true;
+         else
+            tmp=diff(sign(diff(y(itmp,k))))==2;
+            x(itmp(tmp)+1,k)=true;
+            if sdiff(1,k)==0
+               nr=find(sdiff(:,k)>0,1);
+               nf=find(sdiff(:,k)<0,1);
+               if ~(isempty(nr)||isempty(nf))
+                  x(1,k)=nr<nf;
+               end
+            end
+            if sdiff(end,k)==0
+               nr=find(sdiff(:,k)>0,1,'last');
+               nf=find(sdiff(:,k)<0,1,'last');
+               if ~(isempty(nr)||isempty(nf))
+                  x(end,k)=nr<nf;
+               end
+            end
+         end
+      end
+   end
+   if isrow
+      x=x.';
+   end
+   if nargout==2
+      n=x;
+   end
+end
+if strcmp(xn,'max') || nargout==2 % get maxima
+   x=false(ysiz);
+   x(2:end-1,:)=diff(sdiff)==-2;
+   x(1,:)=sdiff(1,:)<0;
+   x(end,:)=sdiff(end,:)>0;
+   if any(zdiff)
+      ir=1:ysiz(1);
+      for k=idz % handle columns with zero differences
+         itmp=ir;
+         itmp(zdiff(:,k))=[];
+         if all(sdiff(:,k)==0) % entire column is flat
+            x(:,k)=true;
+         else
+            tmp=diff(sign(diff(y(itmp,k))))==-2;
+            x(itmp(tmp)+1,k)=true;
+            if sdiff(1,k)==0
+               nr=find(sdiff(:,k)>0,1);
+               nf=find(sdiff(:,k)<0,1);
+               if ~(isempty(nr)||isempty(nf))
+                  x(1,k)=nr>nf;
+               end
+            end
+            if sdiff(end,k)==0
+               nr=find(sdiff(:,k)>0,1,'last');
+               nf=find(sdiff(:,k)<0,1,'last');
+               if ~(isempty(nr)||isempty(nf))
+                  x(end,k)=nr>nf;
+               end
+            end
+         end
+      end
+   end
+   if isrow
+      x=x';
+   end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/tools/getFileDependencies.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,156 @@
+function list =  getFileDependencies(file)
+% searches the paths of the .m-Files the given file is using. This function
+% depends on the depfun-Function of Matlab. Though it is not guaranteed,
+% that all files will be found. E.g. files in evaluate-constructs won't be
+% found!!
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% Parameters:
+%     - file: the file for which the dependencies should be searched. This
+%             could be only a string with the function-name, the filename
+%             or the path to a file.
+%
+% Returns:
+%     - list: a cell-Array with the paths to all files the given file uses
+%             as strings. list is -1 if an error occured while processing.
+%             See errormessage for details.
+%
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% author:   Torsten Hopp
+% last change: 03.07.2007
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+% checking the input-parameter
+if(isempty(file))
+    disp('ERROR. Input Parameter is empty')
+    list = -1;
+    return;
+end
+if(~ischar(file))
+    disp('ERROR. Input Parameter is not char')
+    list = -1;
+    return;
+end
+
+
+% list: a cell-array for the result
+list = {which(file)};
+% fileList: array of strings to search in the current iteration
+fileList = list;
+
+% While new files where found in last iteration
+while (~isempty(fileList))
+    fileListSize = length(fileList);
+    newOnes = [];
+    newCounter = 1;
+    currentFileList = fileList;
+    fileList = [];
+
+    % running trough the current file list
+    for k=1:fileListSize
+        % calling depfun. -toponly indicates non-recursive search. -quiet
+        % suppresses output to command line
+        templist = depfun(currentFileList{k},'-toponly','-quiet');
+
+        % the first file is already included 
+        templist(1) = []; 
+        
+        % calling the helper-function to delete files which contain
+        % <matlabroot> in the path from the list.
+        templist = deleteMatlabFiles(templist);
+
+        listSize = length(list);
+        tempListSize = length(templist);
+
+        % excluding first iteration with this if-clause
+        if(listSize > 1)
+
+            % comparing lists --> Searching for files that are not in the
+            % list yet
+            for i=1:tempListSize
+                contained = 0;
+                j=1;
+                % first condition stops comparing if something was found.
+                while contained == 0 & j<=listSize
+                    if((strcmp(templist{i},list{j})==1) )
+                        contained = 1;
+                    end
+                    j = j+1;
+                end
+
+                % if file isn't in the list yet...
+                if(contained == 0)
+
+                    % add it to a cellArray for new filenames...
+                    % if-clause excludes first run with empty
+                    % newOnes-variable
+                    if(~isempty(newOnes))
+
+                        % if not first run: comparing the filename with the
+                        % filenames that are in the newOnes-List to avoid
+                        % double-enties
+                        a = strfind(newOnes,templist{i});
+                        counter = 0;
+                        for p=1:length(a)
+                            if(~isempty(a{p}))
+                                counter = counter +1;
+                            end
+                        end
+                        % if not found in list: add it to the list!
+                        if(counter==0)
+                            newOnes{newCounter} = templist{i};
+                            newCounter = newCounter + 1;
+                        end
+                    else
+                        % if list is empty: add it without checking!
+                        newOnes{newCounter} = templist{i};
+                        newCounter = newCounter + 1;
+                    end
+                end
+            end
+
+            % if new filenames where found in this run...
+            if(~isempty(newOnes))
+                % ... search the new found files in the next iteration
+                fileList = [fileList newOnes];
+                % ... add the new found files to the list
+                list(length(list)+1:length(list)+length(newOnes)) = newOnes;
+                newOnes = [];
+                newCounter = 1;
+            end
+        else
+            % if first iteration: set the first-level dependecies as
+            % filelist for next iteration and add them to the list.
+            fileList = templist;
+            list = [list; templist];
+        end
+    end
+end
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% HELPER FUNCTIONS                                                        %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+function rList = deleteMatlabFiles(pList)
+% deletes filenames with matlabroot in path from the given list.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% Parameters:
+%     - pList: a cell-Array of filenames as string
+%
+% Returns:
+%     - rList: a cell-Array of filenames as string
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+excludedDir = matlabroot;
+indexes = strfind(pList,excludedDir);
+keepIndexes = cellfun(@isempty,indexes);
+rList = pList(keepIndexes);
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/tools/localmax_logical.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,5 @@
+function lm = localmax_logical(mat,n)
+
+diffmat = [mat(1,:)*0; sign(diff(mat))]; % !!!! attention rethink the 0!!!!!
+convolver = -[ones(n,1);-ones(n,1)];
+lm = conv2(diffmat,convolver,'same') == 2 * n;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_misc/tools/localmaxmin.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,124 @@
+function [x,n]=localmaxmin(y,xn)
+%LOCALMAXMIN(Y) Local Maxima and Minima.
+% X = LOCALMAXMIN(Y) or LOCALMAXMIN(Y,'max') for vector Y returns a logical
+% vector X the same size as Y such that Y(X) contains the local maxima in Y.
+%
+% N = LOCALMAXMIN(Y,'min') for vector Y returns a logical vector N the same
+% size as Y such that Y(N) contains the local minima in Y.
+%
+% [X,N] = LOCALMAXMIN(Y) for vector Y returns logical vectors X and N such
+% that Y(X) contains the local maxima and Y(N) contains the local minima.
+%
+% When Y is a matrix, outputs are logical array(s) the same size as Y, and
+% the minima and/or maxima are computed down the rows of each column in Y.
+%
+% See also MAX, MIN.
+
+% D.C. Hanselman, University of Maine, Orono, ME 04469
+% MasteringMatlab@yahoo.com
+% Mastering MATLAB 7
+% 2006-03-08
+
+mm=['min';'max'];
+if nargin==1
+   xn='max';
+elseif nargin~=2
+   error('localmaxmin:NotEnoughInputArguments',...
+         'One or Two Input Arguments Required.')
+end
+if ~ischar(xn) || isempty(strcmp(xn,mm))
+   error('localmaxmin:UnknownArgument','Unknown Second Input Argument.')
+end
+if ~isnumeric(y) || ~isreal(y)
+   error('localmaxmin:IncorrectDataType','Y Must be Real Valued.')
+end
+ysiz=size(y);
+isrow=ysiz(1)==1;
+if isrow % if row, convert to column for now
+   y=y';
+   ysiz(1)=ysiz(2);
+   ysiz(2)=1;
+end
+if ysiz(1)<4
+   error('localmaxmin:InsufficientData','Y Must Have at Least 4 Elements.')
+end
+x=false(ysiz);
+   
+sdiff=sign(diff(y));
+zdiff=sdiff==0;
+idz=find(sum(zdiff)); % columns where zero differences appear
+
+if strcmp(xn,'min') || nargout==2   % get minima
+   x(2:end-1,:)=diff(sdiff)==2;
+   x(1,:)=sdiff(1,:)>0;
+   x(end,:)=sdiff(end,:)<0;
+   if any(zdiff)
+      ir=1:ysiz(1);
+      for k=idz % handle columns with zero differences
+         itmp=ir;
+         itmp(zdiff(:,k))=[];
+         if all(sdiff(:,k)==0) % entire column is flat
+            x(:,k)=true;
+         else
+            tmp=diff(sign(diff(y(itmp,k))))==2;
+            x(itmp(tmp)+1,k)=true;
+            if sdiff(1,k)==0
+               nr=find(sdiff(:,k)>0,1);
+               nf=find(sdiff(:,k)<0,1);
+               if ~(isempty(nr)||isempty(nf))
+                  x(1,k)=nr<nf;
+               end
+            end
+            if sdiff(end,k)==0
+               nr=find(sdiff(:,k)>0,1,'last');
+               nf=find(sdiff(:,k)<0,1,'last');
+               if ~(isempty(nr)||isempty(nf))
+                  x(end,k)=nr<nf;
+               end
+            end
+         end
+      end
+   end
+   if isrow
+      x=x.';
+   end
+   if nargout==2
+      n=x;
+   end
+end
+if strcmp(xn,'max') || nargout==2 % get maxima
+   x=false(ysiz);
+   x(2:end-1,:)=diff(sdiff)==-2;
+   x(1,:)=sdiff(1,:)<0;
+   x(end,:)=sdiff(end,:)>0;
+   if any(zdiff)
+      ir=1:ysiz(1);
+      for k=idz % handle columns with zero differences
+         itmp=ir;
+         itmp(zdiff(:,k))=[];
+         if all(sdiff(:,k)==0) % entire column is flat
+            x(:,k)=true;
+         else
+            tmp=diff(sign(diff(y(itmp,k))))==-2;
+            x(itmp(tmp)+1,k)=true;
+            if sdiff(1,k)==0
+               nr=find(sdiff(:,k)>0,1);
+               nf=find(sdiff(:,k)<0,1);
+               if ~(isempty(nr)||isempty(nf))
+                  x(1,k)=nr>nf;
+               end
+            end
+            if sdiff(end,k)==0
+               nr=find(sdiff(:,k)>0,1,'last');
+               nf=find(sdiff(:,k)<0,1,'last');
+               if ~(isempty(nr)||isempty(nf))
+                  x(end,k)=nr>nf;
+               end
+            end
+         end
+      end
+   end
+   if isrow
+      x=x';
+   end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_parameters/param_mirex.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,66 @@
+function param = param_mirex(chromafilename)
+param = param_skeleton();
+param.beattype = 'auto';
+param.metafilename = chromafilename;
+
+param.dsp.extractiontype = 'vampprecalculated';
+param.dsp.resampleto = 11025;
+param.dsp.blocksize = 4096;
+param.dsp.hopsize = 512;
+param.dsp.nSbin = 3;
+param.dsp.nrmsmoothlen = 1; % no norm smoothing
+param.dsp.separatenormalising = true;
+param.dsp.mutesilent = true;
+param.dsp.norm = 'max';
+param.dsp.nochord05 = true;
+
+param.newchroma.whitemethod = 'standardize';
+param.newchroma.paling = [];
+param.newchroma.partials1 = 0.6;
+param.newchroma.partials2 = 0.6;
+
+param.dbn.infermpe = true;
+param.dbn.name = 'ISMIR_2010'; % name of the model 
+param.dbn.nMeter = 1; % number of different meters
+param.dbn.nMetpos = 4; % number of metric positions (in the different meters)
+param.dbn.nBass = 13; 
+param.dbn.keyset = 'majorminor';
+param.dbn.keynames = {'C','Db','D','Eb','E','F','F#','G','Ab','A','Bb','B',...
+    'C:minor','Db:minor','D:minor','Eb:minor','E:minor','F:minor','F#:minor','G:minor','Ab:minor','A:minor','Bb:minor','B:minor'}; % set of key names 
+param.dbn.lilykeynames = {'c \major','des \major','d \major','es \major','e \major','f \major','fis \major','g \major','aes \major','a \major','bes \major','b \major',...
+    'c \minor','des \minor','d \minor','es \minor','e \minor','f \minor','fis \minor','g \minor','aes \minor','a \minor','bes \minor','b \minor'}; % set of key names 
+param.dbn.key_c = 4.83; % strange variable c for expert function
+param.dbn.nKey = 24;
+param.dbn.chordclassset = {'','/3','/5',':maj6',':maj7',':min',':7',':min7',':dim',':aug','N'}; % set of chord classes
+% param.dbn.nChord = 121;
+param.dbn.chordpcs = []; % chord pitch class set (binary vector of length 12)
+param.dbn.basshaschordnotes = true;
+param.dbn.chromavar = 0.2; % variance of the chroma vector, applicable in manually set model
+param.dbn.basschromavar = 0.1; % same as above for the bass
+param = add_chords(param); % adding chord parameters
+param.dbn.beattrans = 0.95; % transition probability to next beat (manually set)
+param.dbn.keychange = 0.08; % key change probability (manually set)
+param.dbn.nominalbass = 0.8; % probability of nominal bass pc sounding on first beat of chord
+param.dbn.nominalbass_inner = 0.8; % as above, but on the rest of the beats of a chord
+param.dbn.chordchange = 1 - [.5 .1 .4 .1]; % one minus prob of chord change at different beats
+param.dbn.inferencebypart = true;
+
+param.seg.type = 'auto'; % segmentation with editor intervention, or no segmentation, etc.
+param.seg.quantile = .1;
+param.seg.editor = false;
+param.seg.beat_pairs = false;
+param.seg.medfilt_length = 5;
+param.seg.barline_spacing = 1;
+param.seg.thresh_beat = .85;
+param.seg.minlength = 28;
+param.seg.maxlength = 128;
+param.seg.standardise = false;
+param.seg.thresh_seg = .8;
+param.seg.precalc = 0;
+param.seg.newcheck = false;
+% param.seg.inferencebypart = true;
+if param.seg.newcheck
+    param.seg.segext = '.seg';
+else
+    param.seg.segext = '.segold';
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_parameters/param_segmentation.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,66 @@
+function param = param_segmentation(chromafilename)
+param = param_skeleton();
+param.beattype = 'auto';
+param.metafilename = chromafilename;
+
+param.dsp.extractiontype = 'vampprecalculated';
+param.dsp.resampleto = 11025;
+param.dsp.blocksize = 4096;
+param.dsp.hopsize = 512;
+param.dsp.nSbin = 3;
+param.dsp.nrmsmoothlen = 1; % no norm smoothing
+param.dsp.separatenormalising = true;
+param.dsp.mutesilent = true;
+param.dsp.norm = 'max';
+param.dsp.nochord05 = true;
+
+param.newchroma.whitemethod = 'standardize';
+param.newchroma.paling = [];
+param.newchroma.partials1 = 0.6;
+param.newchroma.partials2 = 0.6;
+
+param.dbn.infermpe = true;
+param.dbn.name = 'ISMIR_2010'; % name of the model 
+param.dbn.nMeter = 1; % number of different meters
+param.dbn.nMetpos = 4; % number of metric positions (in the different meters)
+param.dbn.nBass = 13; 
+param.dbn.keyset = 'majorminor';
+param.dbn.keynames = {'C','Db','D','Eb','E','F','F#','G','Ab','A','Bb','B',...
+    'C:minor','Db:minor','D:minor','Eb:minor','E:minor','F:minor','F#:minor','G:minor','Ab:minor','A:minor','Bb:minor','B:minor'}; % set of key names 
+param.dbn.lilykeynames = {'c \major','des \major','d \major','es \major','e \major','f \major','fis \major','g \major','aes \major','a \major','bes \major','b \major',...
+    'c \minor','des \minor','d \minor','es \minor','e \minor','f \minor','fis \minor','g \minor','aes \minor','a \minor','bes \minor','b \minor'}; % set of key names 
+param.dbn.key_c = 4.83; % strange variable c for expert function
+param.dbn.nKey = 24;
+param.dbn.chordclassset = {'','/3','/5',':maj6',':maj7',':min',':7',':min7',':dim',':aug','N'}; % set of chord classes
+% param.dbn.nChord = 121;
+param.dbn.chordpcs = []; % chord pitch class set (binary vector of length 12)
+param.dbn.basshaschordnotes = true;
+param.dbn.chromavar = 0.2; % variance of the chroma vector, applicable in manually set model
+param.dbn.basschromavar = 0.1; % same as above for the bass
+param = add_chords(param); % adding chord parameters
+param.dbn.beattrans = 0.95; % transition probability to next beat (manually set)
+param.dbn.keychange = 0.08; % key change probability (manually set)
+param.dbn.nominalbass = 0.8; % probability of nominal bass pc sounding on first beat of chord
+param.dbn.nominalbass_inner = 0.8; % as above, but on the rest of the beats of a chord
+param.dbn.chordchange = 1 - [.5 .1 .4 .1]; % one minus prob of chord change at different beats
+param.dbn.inferencebypart = true;
+
+param.seg.type = 'auto'; % segmentation with editor intervention, or no segmentation, etc.
+param.seg.quantile = .1;
+param.seg.editor = false;
+param.seg.beat_pairs = false;
+param.seg.medfilt_length = 5;
+param.seg.barline_spacing = 1;
+param.seg.thresh_beat = .85;
+param.seg.minlength = 28;
+param.seg.maxlength = 128;
+param.seg.standardise = false;
+param.seg.thresh_seg = .8;
+param.seg.precalc = 0;
+param.seg.newcheck = false;
+% param.seg.inferencebypart = true;
+if param.seg.newcheck
+    param.seg.segext = '.seg';
+else
+    param.seg.segext = '.segold';
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_parameters/param_skeleton.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,65 @@
+function param = param_skeleton()
+% Algorithm parameter skeleton for Matthias Mauch's thesis code
+% Parameters concerning input, output and verbosity are not in here.
+param.beattype = 'auto';
+param.dsp.extractiontype = '';
+param.dsp.resampleto = [];
+param.dsp.blocksize = [];
+param.dsp.hopsize = [];
+param.dsp.fmin = [];
+param.dsp.fmax = [];
+param.dsp.nSbin = [];
+param.dsp.noterange = [];
+param.dsp.minMidinote = [];
+param.dsp.maxMidinote = [];
+param.dsp.medfiltlength = []; % length of a median filter in frames
+param.dsp.nrmsmoothlen = [];
+param.dsp.bassbin13 = true; % is there a thirteenth bin corresponding to "no bass"
+param.dsp.norm = 'max';
+param.dsp.separatenormalising = true;
+param.dsp.mutesilent = false;
+param.dsp.manualbeats = false;
+param.dsp.nochord05 = false;
+
+param.newchroma.partials1 = 0.6;
+param.newchroma.partials2 = 0.6;
+param.newchroma.standardise = true;
+param.newchroma.whitemethod = 'standardize';
+
+param.dbn.name = ''; % name of the model 
+param.dbn.nMeter = []; % number of different meters
+param.dbn.nMetpos = []; % number of metric positions (in the different meters)
+param.dbn.nBass = [];
+param.dbn.keyset = {}; % set of key names 
+param.dbn.key_c = []; % strange variable c for expert function
+param.dbn.nKey = [];
+param.dbn.chordclassset = {}; % set of chord classes
+param.dbn.nChord = [];
+param.dbn.chordpcs = []; % chord pitch class set (binary vector of length 12)
+param.dbn.chordbassnotes = [];
+param.dbn.basshaschordnotes = false;
+param.dbn.chromavar = []; % variance of the chroma vector, applicable in manually set model
+param.dbn.basschromavar = []; % same as above for the bass
+param.dbn.beattrans = []; % transition probability to next beat (manually set)
+param.dbn.keychange = []; % key change probability (manually set)
+param.dbn.nominalbass = []; % probability of nominal bass pc sounding on first beat of chord
+param.dbn.nominalbass_inner = []; % as above, but on the rest of the beats of a chord
+param.dbn.chordchange = []; % one minus prob of chord change at different beats
+param.dbn.infermpe = true;
+param.dbn.inferencebypart = false;
+
+param.seg.type = ''; % "standard" segmentation, with automatic "editor" intervention, "none", or "manual" segmentation, tc.
+param.seg.beattype = ''; % what kind of beat tracking
+param.seg.chroma = ''; % what kind of chroma (not just wide or treble, but also which techinque)
+param.seg.quantile = []; % quantile as in ISMIR paper equation (3)
+param.seg.editor = false; % if true, look for frequent sub-segments
+param.seg.beat_pairs = false; % pairing up beats for decreased chance of random match
+param.seg.medfilt_length = []; % length of median filter over similarity matrix
+param.seg.barline_spacing = []; %
+param.seg.thresh_beat = []; % beat similarity has to be at least this
+param.seg.minlength = []; % min length of segment
+param.seg.maxlength = []; % max length of segment
+param.seg.dynamic = false; % use dynamic time warping
+param.seg.standardise = false; % 
+param.seg.thresh_seg = []; % take segments over this threshold (in units above std)
+param.seg.inferenceoverlap = 8;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_segmentation/integratesmallparts.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+function song = integratesmallparts(song)
+
+parts = song.parts;
+nParts = numel(parts);
+
+
+
+%% break up parts (every part will have one instance)
+iNewpart = 0;
+partindices = [];
+for iPart = 1:nParts
+    parts(iPart).nInd = length(parts(iPart).indices);
+    for iInstance = 1:parts(iPart).nInd
+        iNewpart = iNewpart + 1;
+        newparts(iNewpart) = parts(iPart);
+        newparts(iNewpart).indices = parts(iPart).indices(iInstance);
+        newparts(iNewpart).nInd = 1;
+        partindices = [partindices; parts(iPart).indices(iInstance)];
+    end
+end
+nNewparts = numel(newparts);
+
+%% sort the parts in order of occurrence
+[sortind, sortind] = sort(partindices);
+for iNewpart = 1:nNewparts 
+    sortednewparts(iNewpart) = newparts(sortind(iNewpart));
+end
+
+%%
+eraselist = [];
+for iNewpart = 2:nNewparts
+    if sortednewparts(iNewpart).n < 12
+        eraselist = [eraselist; iNewpart];
+        sortednewparts(iNewpart-1).n = ...
+            sortednewparts(iNewpart-1).n + sortednewparts(iNewpart).n;
+    end
+end
+
+sortednewparts(eraselist) = [];
+song.integratedparts = sortednewparts;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_segmentation/makeparts.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,44 @@
+function outparts = makeparts(beattimes,segtimes,seglevel)
+
+parts = struct('n',[], 'indices',[], 'letter', [],'level',[]);
+nPart = 0;
+nSeg = size(segtimes,1);
+
+for iSeg = 1:nSeg
+    newpart = true;
+%     tempbeat = struct([]);
+    segbeats = find(mean(beattimes,2) >= segtimes(iSeg,1) & mean(beattimes,2) < segtimes(iSeg,2));
+    lenSegbeats = length(segbeats);
+    for iPart = 1:nPart
+        if seglevel(iSeg) == parts(iPart).level && lenSegbeats == parts(iPart).n
+            parts(iPart).indices = [parts(iPart).indices segbeats(1)];
+%             parts(iPart).beat = [parts(iPart).beat tempbeat];
+            newpart = false;
+            break;
+        else
+            newpart = true;
+        end
+    end
+    if newpart && ~isempty(segbeats)
+        nPart = nPart + 1;
+        parts(nPart).indices = segbeats(1);
+        parts(nPart).n = lenSegbeats;
+        parts(nPart).level = seglevel(iSeg);
+%         parts(nPart).beat = tempbeat;
+    end
+    
+end
+partnind = zeros(nPart,1);
+partlen = zeros(nPart,1);
+for iPart = 1:nPart
+    partnind(iPart) = length(parts(iPart).indices);
+    partlen(iPart) = parts(iPart).n;
+end
+[partind,partind] = sort(partnind.*partlen,'descend');
+letters = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U'};
+outparts = parts;
+for iPart = 1:nPart
+    kPart = partind(iPart);
+    parts(kPart).letter = letters{iPart};
+    outparts(iPart) = parts(kPart);
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_segmentation/maxfilt1.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,8 @@
+function outmat = maxfilt1(inmat, len)
+outmat = inmat;
+for i = find(sum(inmat)>0)
+    indi = max(1,i-len):min(size(inmat,2),i+len-1);
+    temp = inmat(indi,:);
+    outmat(i,:) = max(temp,[],1);
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_segmentation/mergenulls.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,24 @@
+function parts = mergenulls(parts)
+
+for iPart = 1:length(parts)
+    newparts = [];
+    if parts(iPart).letter == '-'
+        parts(iPart).indices = sort(parts(iPart).indices);
+        newpartind = 0;
+        indices = [-1 parts(iPart).indices];
+        for iInd = 2:length(indices)
+            if indices(iInd) - indices(iInd-1) > 1
+                newpartind = newpartind + 1;
+                newparts(newpartind).letter = ['n' num2str(newpartind)];
+                newparts(newpartind).n = 1;
+                newparts(newpartind).indices = indices(iInd);
+                newparts(newpartind).level = 0;                
+            else
+                newparts(newpartind).n = newparts(newpartind).n + 1;
+            end
+        end
+        parts(iPart) = [];
+        parts = [parts  newparts];
+    end
+end
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_segmentation/nullpart.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,11 @@
+function np = nullpart(parts, barlines)
+nullindices = ones(size(barlines));
+for iPart = 1:length(parts)
+    for iIndex = 1:length(parts(iPart).indices)
+        nullindices(parts(iPart).indices(iIndex)+(0:parts(iPart).n-1)) = 0;
+    end
+end
+np.n = 1;
+np.indices = find(nullindices);
+np.letter = '-';
+np.level = 0;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_segmentation/parts2csv.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,31 @@
+function parts2csv(song, filename, varargin)
+if nargin > 2 && strcmp(varargin{1}, 'integrated')
+    parts = song.integratedparts;
+else 
+    parts = song.parts;
+end
+
+beattimes = song.beattimes;
+% beattimes = [0; beattimes];
+indices = [];
+levels = [];
+letters = {};
+
+for iPart = 1:length(parts)
+    for iInstance = 1:length(parts(iPart).indices)
+       indices = [indices parts(iPart).indices(iInstance)];
+       levels = [levels parts(iPart).level];
+       letters = [letters parts(iPart).letter];
+    end
+end
+
+[sorted, sortind] = sort(indices);
+
+f = fopen(filename,'w');
+
+for iSeg = 1:length(indices)
+    fprintf(f,'%1.2f,%1.3f,"%s"\n',beattimes(sorted(iSeg)),levels(sortind(iSeg)),letters{sortind(iSeg)});
+end
+
+fclose(f);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_segmentation/parts2mirex.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,36 @@
+function parts2mirex(song, filename, varargin)
+if nargin > 2 && strcmp(varargin{1}, 'integrated')
+    parts = song.integratedparts;
+else 
+    parts = song.parts;
+end
+
+beattimes = song.beattimes;
+% beattimes = [0; beattimes];
+startIndex = [];
+letters = {};
+
+for iPart = 1:length(parts)
+    for iInstance = 1:length(parts(iPart).indices)
+       startIndex = [startIndex parts(iPart).indices(iInstance)];
+       letters = [letters parts(iPart).letter];
+    end
+end
+
+[sorted, sortind] = sort(startIndex);
+endIndex = zeros(length(sorted),1);
+for iIndex = 1:length(sorted)-1;
+    endIndex(iIndex) = sorted(iIndex+1);
+end
+endIndex(end) = length(beattimes);
+
+f = fopen(filename,'w');
+
+fprintf(f,'0.000 %1.3f "%s"\n',beattimes(endIndex(1)),letters{sortind(1)});
+for iSeg = 2:length(sorted)-1
+    fprintf(f,'%1.3f %1.3f "%s"\n',beattimes(sorted(iSeg)),beattimes(endIndex(iSeg)),letters{sortind(iSeg)});
+end
+fprintf(f,'%1.3f %1.3f "%s"\n',beattimes(sorted(end)),song.t(end),letters{sortind(end)});
+
+fclose(f);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_segmentation/segmentation_auto.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,180 @@
+function song = segmentation_auto(song, param, varargin)
+
+
+%% calculating similarity matrix
+% exp of minus the cosine distance
+
+if any(strcmp(fieldnames(song.syncchroma),'wide'))
+	v = song.syncchroma.wide;
+else
+	v = song.syncchroma.treble + song.syncchroma.bass(:,1:12) * 0.8;
+end
+nBeat = song.nBeat;
+flatPCP = std(v')<.000001;
+v(flatPCP,1) = 1000; % arbitrary
+simmat0 = squareform(pdist(v,'correlation'));
+% simmat0(flatPCP,:) = 2;
+% simmat0(:,flatPCP) = 2;
+% simmat = qnormalise(exp(-simmat0),inf,1);
+% simmat(flatPCP,:) = 0;
+% simmat(:,flatPCP) = 0;
+
+simmat0(flatPCP,:) = 1;
+simmat0(:,flatPCP) = 1;
+simmat = 1-simmat0/2;
+simmat(flatPCP,:) = 0;
+simmat(:,flatPCP) = 0;
+
+%%
+median_simmat = zeros(size(simmat));
+for  i = 1:nBeat
+    temp1 = diag(medfilt1(diag(simmat,i-1),param.seg.medfilt_length,[],1),i-1);
+    median_simmat = median_simmat + temp1;
+end
+median_simmat = median_simmat + median_simmat' - diag(diag(median_simmat));
+median_simmat(isnan(median_simmat)) = 0;
+%%median_simmat = (median_simmat - mean(median_simmat(:)))/std(median_simmat(:));
+%%%%%%%% ATTENTION!!!!!!!! using MEDIAN %%%%%%%%%%%%%
+% median_simmat = (median_simmat - median(median_simmat(:)))/std(median_simmat(:));
+if param.seg.standardise
+    med_median_simmat = repmat(median(median_simmat),nBeat,1);
+    std_median_simmat = repmat(std(median_simmat),nBeat,1);
+    median_simmat = (median_simmat - med_median_simmat) ./ std_median_simmat;
+end
+%% get bar boundaries!!!
+
+potential_duplicates = triu(median_simmat > param.seg.thresh_beat);
+
+%%
+partlengths = param.seg.minlength:4:param.seg.maxlength;
+nPartlengths = length(partlengths);
+
+% initialise arrays
+simArray = zeros(nBeat,nBeat,nPartlengths);
+decisionArray2 = zeros(nBeat,nBeat,nPartlengths);
+
+
+
+fprintf(1,'\n');
+fprintf(2,'    ');
+for iLength = 1:nPartlengths
+    len = partlengths(iLength);
+    nUsedBeat = nBeat - len + 1; % number of potential rep beginnings: they can't overlap at the end of the song
+    fprintf(1,'\rLength: %1.0d',len)
+    fprintf(2,'\b\b\b\b%3.0f%%',iLength/nPartlengths*100);
+    for iBeat = 1:nUsedBeat % looping over all columns (arbitrarily chosen columns)
+        help2 = find(potential_duplicates(1:nUsedBeat,iBeat));
+        for kBeat = help2' % check only potential duplicates
+            % measure how well two length len segments go together
+            simArray(iBeat,kBeat,iLength) = ...
+                quantile(diag(median_simmat(iBeat+(0:len-1),kBeat+(0:len-1))),param.seg.quantile);
+        end
+    end
+    simArray(1:nUsedBeat,1:nUsedBeat,iLength) = simArray(1:nUsedBeat,1:nUsedBeat,iLength) ...
+        + simArray(1:nUsedBeat,1:nUsedBeat,iLength)' ...
+        - eye(nUsedBeat) .* simArray(1:nUsedBeat,1:nUsedBeat,iLength);
+
+    simArray(:,:,iLength) = conv2(simArray(:,:,iLength),[.01 .98 .01], 'same');
+    % take only over-average bars that do not overlap
+    for iBeat = 1:nUsedBeat
+        temp = simArray(:,iBeat,iLength) > param.seg.thresh_seg;
+        decisionArray2(temp,iBeat,iLength) = ...
+            simArray(temp,iBeat,iLength);
+    end
+    decisionArray2(:,:,iLength) = decisionArray2(:,:,iLength) .* (decisionArray2(:,:,iLength) >= maxfilt1(decisionArray2(:,:,iLength),len-1));
+    decisionArray2(:,:,iLength) = decisionArray2(:,:,iLength) .* decisionArray2(:,:,iLength)';
+%     potential_duplicates = triu(simArray(:,:,iLength) > param.seg.thresh_seg * 0.7);
+    potential_duplicates = potential_duplicates .* (simArray(:,:,iLength) > param.seg.thresh_seg);
+end
+%% milk the data
+
+bestvals = [];
+for iLength = 1:nPartlengths
+    currLogicSum = sum(decisionArray2(:,:,iLength)>0,2);
+    for iBeat = 1:nBeat
+        if currLogicSum(iBeat) > 1.0
+            currSum = (mean(decisionArray2(decisionArray2(:,iBeat,iLength)>0,iBeat,iLength)))/2;
+            bestvals = [bestvals; (currLogicSum(iBeat)-1) * partlengths(iLength), currSum, iLength, iBeat, currLogicSum(iBeat)];
+        end
+    end
+end
+%%
+%%
+% make a table of all valid sets of parts
+partletters = {'A','B','C','D','E','F','G', 'H','I','J','K','L','M','N','O','P','Q','R','S'};
+valid_sets = ones(1,size(bestvals,1));
+parts = [];
+if ~isempty(bestvals)
+    bestvals(:,2) = bestvals(:,2) / max(bestvals(:,2)*2);
+    bestvals(:,1) = bestvals(:,1) + bestvals(:,2);
+    bestvals(:,2) = [];
+
+    for kSeg = 1:7
+        currbestvals = bestvals(logical(valid_sets),:);
+        [m,i] = max(currbestvals(:,1));
+        if isempty(m)
+            break
+        end
+
+        bestLength = partlengths(currbestvals(i,2));
+        bestIndices = decisionArray2(currbestvals(i,3),:,currbestvals(i,2));
+        islands = conv2(1*(bestIndices > 0), [zeros(1,bestLength-1) ones(1,bestLength)], 'same');
+        %%
+        if param.seg.newcheck
+            iBetter = i;
+            bestSubval = 0;
+            subm1 = find(currbestvals(:,4) > currbestvals(i,4)); % has to have more part instances
+            for kSub = 1:length(subm1)
+                iSub = subm1(kSub);
+                subIndices = decisionArray2(currbestvals(iSub,3),:,currbestvals(iSub,2));
+                subLength = partlengths(currbestvals(iSub,2));
+                subIslands = conv2(1*(subIndices > 0), [zeros(1,subLength-1) ones(1,subLength)], 'same');
+                if sum(islands.*subIslands) == currbestvals(i,4) * subLength ...
+                        && currbestvals(iSub,1) > bestSubval
+                    iBetter = iSub;
+                    bestSubval = currbestvals(iSub,1);
+                end
+            end
+            i = iBetter;
+            bestLength = partlengths(currbestvals(i,2));
+            bestIndices = decisionArray2(currbestvals(i,3),:,currbestvals(i,2));
+            islands = conv2(1*(bestIndices > 0), [zeros(1,bestLength-1) ones(1,bestLength)], 'same');
+        end
+        %%
+        part.n = bestLength;
+        part.indices = find(bestIndices);
+        part.letter = partletters{kSeg};
+        part.level = kSeg;
+        parts = [parts part];
+
+        for iSet = find(valid_sets)
+            currislands = conv2(2*(decisionArray2(bestvals(iSet,3),:,bestvals(iSet,2)) > 0), ...
+                [zeros(1,partlengths(bestvals(iSet,2))-1) ones(1,partlengths(bestvals(iSet,2)))], 'same');
+            if any(islands .* currislands > 0)
+                valid_sets(iSet) = false;
+            else
+                %             stem(islands+currislands*.5)
+                %             aaa = 1;
+            end
+        end
+    end
+else
+    part.n = nBeat;
+    part.indices = 1;
+    part.letter = 'A';
+    part.level = 1;
+    parts = [parts part];
+end
+
+parts = [parts, nullpart(parts,1:nBeat)];
+if param.seg.editor
+    [pa, ta] = partarray(parts);
+    parts = editorssearch(pa, ta, parts);
+    parts = [parts, nullpart(parts,1:nBeat)];
+end
+parts = mergenulls(parts);
+
+song.parts = parts;
+% song.parts
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_segmentation/segmentation_main.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,6 @@
+function song = segmentation_main(song, param)
+switch param.seg.type
+    case 'none'
+        song.segments = [1, song.nBeat];
+    otherwise
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_song/song_beat.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,20 @@
+function song = song_beat(song, param)
+switch param.beattype
+    case 'auto'
+        rhythm = getmeasures4(fullfile(song.wavpath, [song.filenametrunk, '.wav']));
+        beattimes = rhythm.beats';
+
+        [sz, fs] = wavread(fullfile(song.wavpath, [song.filenametrunk, '.wav']),'size');
+        songLength = sz(1)/fs;
+
+        song.beattimes  = [beattimes, [beattimes(2:end); songLength]];
+        song.nBeat = size(song.beattimes,1);
+    case 'autoprecalculated'
+        load(param.metafilename);
+        song.beattimes = beattimes_auto;
+        song.nBeat = size(song.beattimes,1);
+    case 'manual'
+        load(param.metafilename);
+        song.beattimes = beattimes_manual;
+        song.nBeat = size(song.beattimes,1);
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_song/song_chroma.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,3 @@
+function song = song_chroma(song, param)
+% fprintf(1,'loading wave: %s\n',fullfile(song.wavpath, [song.filenametrunk, '.wav']));
+[song.chroma, song.t] = chroma_main(fullfile(song.wavpath, [song.filenametrunk, '.wav']), param);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_song/song_segchroma.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,31 @@
+function song = song_segchroma(song, param)
+switch param.seg.type
+    case 'none' % no segmentation, segchroma equals syncchroma
+        song.segchroma = song.syncchroma;
+    otherwise
+        song = overlaychroma(song, param);
+end
+
+function song = overlaychroma(song,param)
+song.segchroma.treble = zeros(size(song.syncchroma.treble));
+song.segchroma.bass = zeros(size(song.syncchroma.bass));
+nPart = numel(song.parts);
+for iPart = 1:nPart
+    song.parts(iPart).nInd = length(song.parts(iPart).indices);
+    for iOccur = 1:song.parts(iPart).nInd
+        iStartIndex = song.parts(iPart).indices(iOccur);
+        iEndIndex = iStartIndex + song.parts(iPart).n - 1;
+        for kOccur = 1:song.parts(iPart).nInd
+            kStartIndex = song.parts(iPart).indices(kOccur);
+            kEndIndex = kStartIndex + song.parts(iPart).n - 1;
+            song.segchroma.treble(iStartIndex:iEndIndex,:) = ...
+                song.segchroma.treble(iStartIndex:iEndIndex,:) + ...
+                song.syncchroma.treble(kStartIndex:kEndIndex,:);
+            song.segchroma.bass(iStartIndex:iEndIndex,:) = ...
+                song.segchroma.bass(iStartIndex:iEndIndex,:) + ...
+                song.syncchroma.bass(kStartIndex:kEndIndex,:);
+        end
+    end
+end
+song.segchroma.treble = qnormalise(song.segchroma.treble,inf,2);
+song.segchroma.bass = qnormalise(song.segchroma.bass,inf,2);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_song/song_segment.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,12 @@
+function song = song_segment(song, param)
+switch param.seg.type
+    case 'none'
+
+    case 'auto'
+        song = segmentation_auto(song,param);
+    case 'autoprecalculated'
+        song = segmentation_autoprecalculated(song,param);
+    case 'manual'
+        song = segmentation_manual(song,param);
+    otherwise
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_song/song_skeleton.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,18 @@
+function song = song_skeleton(filename)
+
+[song.wavpath, song.filenametrunk] = fileparts(filename);
+song.chordgroundtruthpath = '';
+song.beatgroundtruthpath = '';
+song.t = [];
+song.beattimes = [];
+song.nBeat = [];
+song.chroma = [];
+song.syncchroma = [];
+song.segments = [];
+song.beatchords = {};
+song.beatbass = {};
+song.beatmetpos = [];
+song.beatkey = [];
+song.chordgroundtruth.times = [];
+song.chordgroundtruth.label = {};
+song.beatgroundtruth.times = [];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_song/song_syncchroma.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,86 @@
+function song = song_syncchroma(song, param)
+
+[song.syncchroma.treble, treblenrm] = syncchroma(song.chroma.treble, song.beattimes, song.t);
+[song.syncchroma.bass, bassnrm] = syncchroma(song.chroma.bass, song.beattimes, song.t(:));
+
+song.syncchroma.bass(isnan(sum(song.syncchroma.bass,2)),:) = 1;
+song.syncchroma.treble(isnan(sum(song.syncchroma.treble,2)),:) = 1;
+
+song.syncchroma.bass(sum(song.syncchroma.bass,2)<.01,:) = 1;
+song.syncchroma.treble(sum(song.syncchroma.treble,2)<.01,:) = 1;
+
+bcnrm = qnorm(song.syncchroma.bass,1,2);
+if param.dsp.bassbin13 % if the model requires a thirteenth bass bin
+    bc = qnormalise(song.syncchroma.bass,1,2);
+    bc13 = (12 * max(bc,[],2)).^(-2) .* bcnrm;
+    bc13(isnan(bc13)) = 1;
+    song.syncchroma.bass = [song.syncchroma.bass, bc13];
+end
+
+switch param.dsp.norm
+    case 'max'
+        song.syncchroma.bass = qnormalise(song.syncchroma.bass,inf,2);
+        song.syncchroma.treble = qnormalise(song.syncchroma.treble,inf,2);
+    case 'L1'
+        song.syncchroma.bass = qnormalise(song.syncchroma.bass,1,2);
+        song.syncchroma.treble = qnormalise(song.syncchroma.treble,1,2);
+    case 'L2'
+        disp('L2 norm')
+        song.syncchroma.bass = qnormalise(song.syncchroma.bass,2,2);
+        song.syncchroma.treble = qnormalise(song.syncchroma.treble,2,2);
+    case 'standardize'
+        song.syncchroma.bass = standardize(song.syncchroma.bass);
+        song.syncchroma.treble = standardize(song.syncchroma.treble);
+    case 'meta'
+        song.syncchroma.bass = qnormalise(song.syncchroma.bass,inf,2);
+        disp('no standardization for treble chroma; max normalisation for bass')
+    otherwise
+        'blub'
+end
+
+% make all NaNs to 1
+song.syncchroma.bass(isnan(sum(song.syncchroma.bass,2)),:) = 1;
+song.syncchroma.treble(isnan(sum(song.syncchroma.treble,2)),:) = 1;
+% aah, what does this do???
+% song.syncchroma.bass(sum(song.syncchroma.bass,2) < 1,:) = 1;
+% song.syncchroma.treble(sum(song.syncchroma.treble,2) < 1,:) = 1;
+
+
+
+
+% below "wide" chroma processing, that's neglected ...
+% try
+%     [song.syncchroma.wide, widenrm] = syncchroma(song.chroma.wide, song.beattimes, song.t);
+%     for iBeat = 1:song.nBeat
+%         song.syncchroma.wide(iBeat,:) = song.syncchroma.wide(iBeat,:) / widenrm(iBeat);
+%     end
+% catch
+%     warning('could not find wide chroma');
+% end
+
+
+
+function [bc, nrm] = syncchroma(chromag,beats,frame_t)
+% assigning beats to frames
+nBeat = size(beats,1);
+nFrame = length(frame_t);
+
+bc = ones(nBeat,size(chromag,1));
+chromag(:,isnan(sum(chromag))) = 1;
+
+if size(beats,2) < 2
+    for iBeat = 1:nBeat-1
+        currind = find(frame_t >= beats(iBeat) & frame_t < beats(iBeat+1));
+        bc(iBeat,:) = median(chromag(:,currind),2);
+%         if ~any(isnan(bc(iBeat,:)))
+%             bc(iBeat,:) = bc(iBeat,:)/max(bc(iBeat,:));
+%         end
+    end
+else
+    for iBeat = 1:nBeat
+        currind = find(frame_t >= beats(iBeat,1) & frame_t < beats(iBeat,2));
+        bc(iBeat,:) = median(chromag(:,currind),2)';
+    end
+end
+nrm = qnorm(bc,inf,2);
+% bc = qnormalise(bc,inf,2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_song/song_syncchroma_special.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,95 @@
+function song = song_syncchroma_special(song, param)
+
+[song.syncchroma.treble, treblenrm, beats] = syncchroma(song.chroma.treble, song.beattimes, song.t);
+[song.syncchroma.bass, bassnrm] = syncchroma(song.chroma.bass, song.beattimes, song.t(:));
+
+song.syncchroma.bass(isnan(sum(song.syncchroma.bass,2)),:) = 1;
+song.syncchroma.treble(isnan(sum(song.syncchroma.treble,2)),:) = 1;
+
+song.syncchroma.bass(sum(song.syncchroma.bass,2)<.01,:) = 1;
+song.syncchroma.treble(sum(song.syncchroma.treble,2)<.01,:) = 1;
+
+bcnrm = qnorm(song.syncchroma.bass,1,2);
+if param.dsp.bassbin13 % if the model requires a thirteenth bass bin
+    bc = qnormalise(song.syncchroma.bass,1,2);
+    bc13 = (12 * max(bc,[],2)).^(-2) .* bcnrm;
+    bc13(isnan(bc13)) = 1;
+    song.syncchroma.bass = [song.syncchroma.bass, bc13];
+end
+
+switch param.dsp.norm
+    case 'max'
+        song.syncchroma.bass = qnormalise(song.syncchroma.bass,inf,2);
+        song.syncchroma.treble = qnormalise(song.syncchroma.treble,inf,2);
+    case 'L1'
+        song.syncchroma.bass = qnormalise(song.syncchroma.bass,1,2);
+        song.syncchroma.treble = qnormalise(song.syncchroma.treble,1,2);
+    case 'L2'
+        song.syncchroma.bass = qnormalise(song.syncchroma.bass,2,2);
+        song.syncchroma.treble = qnormalise(song.syncchroma.treble,2,2);
+    case 'standardize'
+        song.syncchroma.bass = standardize(song.syncchroma.bass);
+        song.syncchroma.treble = standardize(song.syncchroma.treble);
+    case 'meta'
+        song.syncchroma.bass = qnormalise(song.syncchroma.bass,inf,2);
+        disp('no standardization for treble chroma; max normalisation for bass')
+    otherwise
+        'blub'
+end
+
+% make all NaNs to 1
+song.syncchroma.bass(isnan(sum(song.syncchroma.bass,2)),:) = 1;
+song.syncchroma.treble(isnan(sum(song.syncchroma.treble,2)),:) = 1;
+% aah, what does this do???
+% song.syncchroma.bass(sum(song.syncchroma.bass,2) < 1,:) = 1;
+% song.syncchroma.treble(sum(song.syncchroma.treble,2) < 1,:) = 1;
+
+
+
+
+% below "wide" chroma processing, that's neglected ...
+try
+    [song.syncchroma.wide, widenrm] = syncchroma(song.chroma.wide, song.beattimes, song.t);
+    for iBeat = 1:song.nBeat
+        song.syncchroma.wide(iBeat,:) = song.syncchroma.wide(iBeat,:) / widenrm(iBeat);
+    end
+catch
+    warning('could not find wide chroma');
+end
+
+
+
+function [bc, nrm, beats] = syncchroma(chromag,beats,frame_t)
+% assigning beats to frames
+nBeat = size(beats,1);
+nFrame = length(frame_t);
+
+bc = ones(nBeat,size(chromag,1));
+chromag(:,isnan(sum(chromag))) = 1;
+% first beat
+currind = find(frame_t >= beats(1,1) & frame_t < beats(1,2));
+bc(1,:) = median(chromag(:,currind),2)';
+for iBeat = 2:nBeat
+%     prestarttimes = [beats(iBeat - 1,1), beats(iBeat,1), beats(iBeat,2)];
+%     starttimes = (prestarttimes + beats(iBeat,1))/2;
+    starttimes = beats(iBeat,1) + [-.1 -.05 0 .05 .1];
+    entro = 0;
+    for iST = 1:5
+        currind1 = find(frame_t >= beats(iBeat - 1,1) & frame_t < starttimes(iST));
+        currind2 = find(frame_t >= starttimes(iST) & frame_t < beats(iBeat,2));
+        vec = [ mean(chromag(:,currind2),2)'];
+        vec = vec/sum(vec);
+        vec = vec(vec>0);
+        ent = -vec * log2(vec');
+        if  ent > entro 
+            entro = ent;
+            beats(iBeat - 1, 2) = starttimes(iST);
+            beats(iBeat, 1) = starttimes(iST);
+        end
+    end
+    currind = find(frame_t >= beats(iBeat,1) & frame_t < beats(iBeat,2));
+    bc(iBeat,:) = median(chromag(:,currind),2)';
+end
+
+nrm = qnorm(bc,inf,2);
+% bc = qnormalise(bc,inf,2);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_writetools/chordroot_spelling.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,64 @@
+function rootspelling = chordroot_spelling(key, root, degrees)
+
+temp = strsplit(':', key);
+keyroot = temp{1};
+if length(temp) > 1
+    keymode = temp{2};
+else
+    keymode = 'major';
+end
+
+
+
+% major scale
+scale{1} = [0 2 4 5 7 9 11];
+% harmonic minor scale
+scale{2} = [0 2 3 5 7 8 11];
+
+diatonic = {'C','D','E','F','G','A','B'};
+keymode_number = find(strcmp({'major','minor'},keymode));
+
+if ischar(root)
+    rootdegree = find(strcmp(diatonic,root(1)));
+    rootpc = scale{1}(strcmp(diatonic,root(1))) + length(strfind(root,'#')) - length(strfind(root,'b'));
+else
+    [rootdegree, rootdegree]= min(abs(scale{1}-root));
+    rootpc = root;
+end
+
+
+deg = [];
+pcs = [];
+for ii = 1:length(degrees)
+    deg = [deg mod(rootdegree + str2num(degrees{ii}(end)) - 2,7)+1];
+    pcs = [pcs mod(rootpc + degree2semitone(degrees{ii}),12)];
+end
+
+keyrootpc = scale{1}(strcmp(diatonic,keyroot(1))) + length(strfind(keyroot,'#')) - length(strfind(keyroot,'b'));
+keydegree = find(strcmp(diatonic,keyroot(1)));
+
+scalesemitone = circshift(mod(scale{keymode_number} + keyrootpc,12),[0 keydegree-1]);
+
+fit = [0 0 0];
+
+for deviation = -1:1 % test if the best degree is lower, just right or higher
+    currdeg = mod(deg+deviation-1,7) + 1;
+    chordaccidentals = mod(scalesemitone(currdeg) - pcs + 12 + 6,12) - 6;
+    fit(deviation+2) = sum(abs(chordaccidentals));
+end
+[bestfitval, bestfit] = min(fit);
+bestrootdegree = mod(rootdegree + bestfit - 2 - 1,7) + 1;
+bestrootaccidentals = mod(rootpc - scale{1}(bestrootdegree)+6,12)-6;
+switch bestrootaccidentals
+    case -2 
+        suff = 'bb';
+    case -1
+        suff = 'b';
+    case 0
+        suff = '';
+    case 2 
+        suff = '##';
+    case 1
+        suff = '#';
+end
+rootspelling = [diatonic{bestrootdegree}, suff];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_writetools/keynroot2notetext.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,40 @@
+function outnote = keynroot2notetext(key,root,type)
+
+switch type
+    case 'normal'
+        if root ~= 13
+            scale{1} = {'A','Bb','B','C','C#','D','D#','E','F','F#','G','G#'};
+            scale{2} = {'Bb','B','C','Db','D','Eb','E','F','Gb','G','Ab','A'};
+            scale{3} = {'B','C','C#','D','D#','E','F','F#','G','G#','A','A#'};
+            scale{4} = {'C','C#','D','Eb','E','F','F#','G','Ab','A','Bb','B'};
+            scale{5} = {'Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B','C'};
+            scale{6} = {'D','D#','E','F','F#','G','G#','A','Bb','B','C','C#'};
+            scale{7} = {'Eb','E','F','Gb','G','Ab','A','Bb','B','C','Db','D'};
+            scale{8} = {'E','F','F#','G','G#','A','Bb','B','C','C#','D','D#'};
+            scale{9} = {'F','Gb','G','Ab','A','Bb','B','C','Db','D','Eb','E'};
+            scale{10} = {'Gb','G','Ab','A','Bb','Cb','C','Db','D','Eb','E','F'};
+            scale{11} = {'G','G#','A','Bb','B','C','C#','D','D#','E','F','F#'};
+            scale{12} = {'Ab','A','Bb','B','C','Db','D','Eb','E','F','Gb','G'};
+            outnote = scale{key}{mod(root - key,12)+1};
+        else
+            outnote = '';
+        end
+    case 'lily'
+        if root ~= 13
+            scale{1} = {'a','bes','b','c','cis','d','dis','e','f','fis','g','gis'};
+            scale{2} = {'bes','b','c','des','d','es','e','f','ges','g','as','a'};
+            scale{3} = {'b','c','cis','d','dis','e','f','fis','g','gis','a','ais'};
+            scale{4} = {'c','cis','d','es','e','f','fis','g','as','a','bes','b'};
+            scale{5} = {'des','d','es','e','f','ges','g','as','a','bes','b','c'};
+            scale{6} = {'d','dis','e','f','fis','g','gis','a','bes','b','c','cis'};
+            scale{7} = {'es','e','f','ges','g','as','a','bes','b','c','des','d'};
+            scale{8} = {'e','f','fis','g','gis','a','bes','b','c','cis','d','dis'};
+            scale{9} = {'f','ges','g','as','a','bes','b','c','des','d','es','e'};
+            scale{10} = {'ges','g','as','a','bes','ces','c','des','d','es','e','f'};
+            scale{11} = {'g','gis','a','bes','b','c','cis','d','dis','e','f','fis'};
+            scale{12} = {'as','a','bes','b','c','des','d','es','e','f','ges','g'};
+            outnote = scale{key}{mod(root - key,12)+1};
+        else
+            outnote = 'r';
+        end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_writetools/spellnote.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,69 @@
+function outnote = spellnote(key,root,varargin)
+if nargin > 2
+    type = varargin{1};
+else
+    type = 'normal';
+end
+
+switch type
+    case 'normal'
+        if root ~= 13
+            scale{1} = {'C','C#','D','Eb','E','F','F#','G','Ab','A','Bb','B'};
+            scale{2} = {'Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B','C'};
+            scale{3} = {'D','D#','E','F','F#','G','G#','A','Bb','B','C','C#'};
+            scale{4} = {'Eb','E','F','Gb','G','Ab','A','Bb','B','C','Db','D'};
+            scale{5} = {'E','F','F#','G','G#','A','Bb','B','C','C#','D','D#'};
+            scale{6} = {'F','Gb','G','Ab','A','Bb','B','C','Db','D','Eb','E'};
+            scale{7} = {'Gb','G','Ab','A','Bb','Cb','C','Db','D','Eb','E','F'};
+            scale{8} = {'G','G#','A','Bb','B','C','C#','D','D#','E','F','F#'};
+            scale{9} = {'Ab','A','Bb','B','C','Db','D','Eb','E','F','Gb','G'};
+            scale{10} = {'A','Bb','B','C','C#','D','D#','E','F','F#','G','G#'};
+            scale{11} = {'Bb','B','C','Db','D','Eb','E','F','Gb','G','Ab','A'};
+            scale{12} = {'B','C','C#','D','D#','E','F','F#','G','G#','A','A#'};
+            scale{13} = {'Eb','E','F','Gb','G','Ab','A','Bb','B','C','Db','D'};
+            scale{14} = {'E','F','F#','G','G#','A','Bb','B','C','C#','D','D#'};
+            scale{15} = {'F','Gb','G','Ab','A','Bb','B','C','Db','D','Eb','E'};
+            scale{16} = {'Gb','G','Ab','A','Bb','Cb','C','Db','D','Eb','E','F'};
+            scale{17} = {'G','G#','A','Bb','B','C','C#','D','D#','E','F','F#'};
+            scale{18} = {'Ab','A','Bb','B','C','Db','D','Eb','E','F','Gb','G'};
+            scale{19} = {'A','Bb','B','C','C#','D','D#','E','F','F#','G','G#'};
+            scale{20} = {'Bb','B','C','Db','D','Eb','E','F','Gb','G','Ab','A'};
+            scale{21} = {'B','C','C#','D','D#','E','F','F#','G','G#','A','A#'};
+            scale{22} = {'C','C#','D','Eb','E','F','F#','G','Ab','A','Bb','B'};
+            scale{23} = {'Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B','C'};
+            scale{24} = {'D','D#','E','F','F#','G','G#','A','Bb','B','C','C#'};
+            outnote = scale{key}{mod(root - key,12)+1};
+        else
+            outnote = '';
+        end
+    case 'lily'
+        if root ~= 13
+            scale{1} = {'c','cis','d','es','e','f','fis','g','as','a','bes','b'};
+            scale{2} = {'des','d','es','e','f','ges','g','as','a','bes','b','c'};
+            scale{3} = {'d','dis','e','f','fis','g','gis','a','bes','b','c','cis'};
+            scale{4} = {'es','e','f','ges','g','as','a','bes','b','c','des','d'};
+            scale{5} = {'e','f','fis','g','gis','a','bes','b','c','cis','d','dis'};
+            scale{6} = {'f','ges','g','as','a','bes','b','c','des','d','es','e'};
+            scale{7} = {'ges','g','as','a','bes','ces','c','des','d','es','e','f'};
+            scale{8} = {'g','gis','a','bes','b','c','cis','d','dis','e','f','fis'};
+            scale{9} = {'as','a','bes','b','c','des','d','es','e','f','ges','g'};
+            scale{10} = {'a','bes','b','c','cis','d','dis','e','f','fis','g','gis'};
+            scale{11} = {'bes','b','c','des','d','es','e','f','ges','g','as','a'};
+            scale{12} = {'b','c','cis','d','dis','e','f','fis','g','gis','a','ais'};
+            scale{13} = {'es','e','f','ges','g','as','a','bes','b','c','des','d'};
+            scale{14} = {'e','f','fis','g','gis','a','bes','b','c','cis','d','dis'};
+            scale{15} = {'f','ges','g','as','a','bes','b','c','des','d','es','e'};
+            scale{16} = {'ges','g','as','a','bes','ces','c','des','d','es','e','f'};
+            scale{17} = {'g','gis','a','bes','b','c','cis','d','dis','e','f','fis'};
+            scale{18} = {'as','a','bes','b','c','des','d','es','e','f','ges','g'};
+            scale{19} = {'a','bes','b','c','cis','d','dis','e','f','fis','g','gis'};
+            scale{20} = {'bes','b','c','des','d','es','e','f','ges','g','as','a'};
+            scale{21} = {'b','c','cis','d','dis','e','f','fis','g','gis','a','ais'};
+            scale{22} = {'c','cis','d','es','e','f','fis','g','as','a','bes','b'};
+            scale{23} = {'des','d','es','e','f','ges','g','as','a','bes','b','c'};
+            scale{24} = {'d','dis','e','f','fis','g','gis','a','bes','b','c','cis'};
+            outnote = scale{key}{mod(root - key,12)+1};
+        else
+            outnote = 'r';
+        end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_writetools/write_song.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,174 @@
+function write_song(song, bnet, param, outfilename, filetype, verbose)
+
+prelabels = {'C','Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B','N'};
+chordindex = bnet.names('chord');
+metposindex = bnet.names('metpos');
+if param.dbn.nKey > 0
+    keyindex = bnet.names('key');
+end
+
+switch filetype
+    case 'chordlab'
+        chordsequence = [song.mpe{chordindex,:}];
+        oldchord = 0;
+        oldlabel ='N';
+        outfile = fopen(outfilename,'w');
+        if verbose
+            fprintf(1, '0.0 ');
+        end
+        fprintf(outfile, '0.0 ');
+        for iChord= 1:length(chordsequence)
+            newchord = song.mpe{chordindex, iChord};
+            if newchord ~= oldchord
+                if param.dbn.nKey > 0
+                    keylabel = param.dbn.keynames{song.mpe{keyindex,iChord}};
+                else
+                    keylabel = 'C';
+                end
+                if ischar(param.dbn.chordnames{newchord})
+                    prelabel = ['C',param.dbn.chordnames{newchord}];
+                    [c.rootnote, c.shorthand, c.degreelist, c.bassdegree, success, error] =...
+                        getchordinfo(prelabel);
+                    c.string = addshort2list(c.shorthand, c.degreelist);
+                    label = [chordroot_spelling(keylabel, param.dbn.chordrootnotes(newchord)-1 ,strsplit(',',c.string)),param.dbn.chordnames{newchord}];
+                else
+                    label = 'N';
+                end
+                if verbose
+                    fprintf(1,'%0.3f %s\n%0.3f ', song.beattimes(iChord,1), oldlabel,song.beattimes(iChord,1));
+                end
+                fprintf(outfile,'%0.3f %s\n%0.3f ', song.beattimes(iChord,1), oldlabel,song.beattimes(iChord,1));
+                oldlabel = label;
+            end
+            oldchord = newchord;
+        end
+        if verbose
+            fprintf(1,'%0.3f %s', song.beattimes(iChord,2), oldlabel);
+        end
+        fprintf(outfile,'%0.3f %s', song.beattimes(iChord,2), oldlabel);
+        fclose(outfile);
+    case 'keylab'
+        keysequence = [song.mpe{keyindex,:}];
+        oldkey = 0;
+        oldlabel ='N';
+        outfile = fopen(outfilename,'w');
+        if verbose
+            fprintf(1, '0.0 ');
+        end
+        fprintf(outfile, '0.0 ');
+        for iKey = 1:length(keysequence)
+            newkey = song.mpe{keyindex, iKey};
+            if newkey ~= oldkey
+                keylabel = param.dbn.keynames{song.mpe{keyindex,iKey}};
+                if verbose
+                    fprintf(1,'%0.3f %s\n%0.3f ', song.beattimes(iKey,1), oldlabel,song.beattimes(iKey,1));
+                end
+                fprintf(outfile,'%0.3f %s\n%0.3f ', song.beattimes(iKey,1), oldlabel,song.beattimes(iKey,1));
+                oldlabel = keylabel;
+            end
+            oldkey = newkey;
+        end
+        if verbose
+            fprintf(1,'%0.3f %s', song.beattimes(iKey,2), oldlabel);
+        end
+        fprintf(outfile,'%0.3f %s', song.beattimes(iKey,2), oldlabel);
+        fclose(outfile);
+    case 'lilypond'
+        bassindex = bnet.names('bass');
+        lilychordnames = repmat(param.dbn.lilytypechordnames,[1,12]);
+        lilychordnames{numel(lilychordnames)+1} = '';
+
+        chordsequence = [song.mpe{chordindex,:}];
+
+        nBeat = length(chordsequence);
+
+        keysequence = [song.mpe{keyindex,:}];
+
+        label = cell(nBeat,1);
+        keylabel = cell(nBeat,1);
+
+        metpossequence = [song.mpe{metposindex,:}];
+        oldchord = 0;
+        oldkey = 0;
+        oldbass = 0;
+        oldlabel ='';
+        oldkeylabel = '';
+        oldbasslabel = '';
+
+        outfile = fopen(outfilename,'w');
+        if verbose
+            fprintf(1, '0.0 ');
+        end
+        fprintf(outfile, '0.0 ');
+        chordcount = 0;
+        basscount = 0;
+        chordduration = 0;
+        bassduration = 0;
+        for iBeat= 1:length(chordsequence)
+            newchord = song.mpe{chordindex, iBeat};
+            newkey = song.mpe{keyindex, iBeat};
+            newbass = song.mpe{bassindex, iBeat};
+            newmetpos = song.mpe{metposindex, iBeat};
+            if param.dbn.nKey > 0
+                prekeylabel = param.dbn.keynames{song.mpe{keyindex,iBeat}};
+            else
+                prekeylabel = 'C';
+            end
+            if newchord ~= oldchord  || newmetpos == 1
+                % get the chord name
+                chordcount = chordcount + 1;
+                if ischar(param.dbn.chordnames{newchord})
+                    prelabel = ['C',param.dbn.chordnames{newchord}];
+                    [c.rootnote, c.shorthand, c.degreelist, c.bassdegree, success, error] =...
+                        getchordinfo(prelabel);
+                    if isempty(c.bassdegree)
+                        preroot = spellnote(newkey, param.dbn.chordrootnotes(newchord));
+                        label{iBeat} = [preroot,lilychordnames{newchord}];
+                    else
+                        preroot = spellnote(newkey, param.dbn.chordrootnotes(newchord));
+                        temp = degree2note(c.bassdegree,preroot);
+                        bass = ['/',temp{1}];
+                        label{iBeat} = [preroot ,lilychordnames{newchord},bass];
+                    end
+                else
+                    label{iBeat} = 'nc';
+                end
+                label{iBeat} = strrep(label{iBeat},'#','is');
+                label{iBeat} = strrep(label{iBeat},'b','es');
+                label{iBeat} = lower(label{iBeat});
+
+%                 oldlabel = label{iBeat};
+                chordduration = 1;
+            else
+                chordduration = chordduration + 1;
+            end
+            if oldkey ~= newkey
+                keylabel{iBeat} = param.dbn.lilykeynames{song.mpe{keyindex,iBeat}};
+                keylabel{iBeat} = strrep(keylabel{iBeat},'#','is');
+                keylabel{iBeat} = strrep(keylabel{iBeat},'b','es');
+                keylabel{iBeat} = lower(keylabel{iBeat});
+                oldkeylabel = keylabel{iBeat};
+            end
+            if oldbass ~= newbass || newmetpos == 1
+                basscount = basscount + 1;
+                if basscount > 1
+                    basslabelduration{basscount-1} = bassduration;
+                end
+                basslabel{basscount} = spellnote(newkey, param.dbn.chordbassnotes(newbass),'lily');
+                bassduration = 1;
+            else
+                bassduration = bassduration + 1;
+            end
+            oldbass = newbass;
+            oldkey = newkey;
+            oldchord = newchord;
+        end
+
+        % finish off the durations etc
+        basslabelduration{basscount} = bassduration;
+        
+        fclose(outfile);
+        for iLabel = 1:numel(basslabel)
+            fprintf(1,'%10s %4.0f\n', basslabel{iLabel}, basslabelduration{iLabel})
+        end
+end
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/_writetools/write_song2.m	Fri Apr 11 15:54:25 2014 +0100
@@ -0,0 +1,226 @@
+function write_song2(song, bnet, param, outfilename, filetype, verbose)
+
+prelabels = {'C','Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B','N'};
+chordindex = bnet.names('chord');
+metposindex = bnet.names('metpos');
+if param.dbn.nKey > 0
+    keyindex = bnet.names('key');
+end
+
+switch filetype
+    case 'chordlab'
+        chordsequence = [song.mpe{chordindex,:}];
+        oldchord = 0;
+        oldlabel ='N';
+        outfile = fopen(outfilename,'w');
+        if verbose
+            fprintf(1, '0.0 ');
+        end
+        fprintf(outfile, '0.0 ');
+        for iChord= 1:length(chordsequence)
+            newchord = song.mpe{chordindex, iChord};
+            if newchord ~= oldchord
+                if param.dbn.nKey > 0
+                    keylabel = param.dbn.keynames{song.mpe{keyindex,iChord}};
+                else
+                    keylabel = 'C';
+                end
+                if ischar(param.dbn.chordnames{newchord})
+                    prelabel = ['C',param.dbn.chordnames{newchord}];
+                    [c.rootnote, c.shorthand, c.degreelist, c.bassdegree, success, error] =...
+                        getchordinfo(prelabel);
+                    c.string = addshort2list(c.shorthand, c.degreelist);
+                    label = [chordroot_spelling(keylabel, param.dbn.chordrootnotes(newchord)-1 ,strsplit(',',c.string)),param.dbn.chordnames{newchord}];
+                else
+                    label = 'N';
+                end
+                if verbose
+                    fprintf(1,'%0.3f %s\n%0.3f ', song.beattimes(iChord,1), oldlabel,song.beattimes(iChord,1));
+                end
+                fprintf(outfile,'%0.3f %s\n%0.3f ', song.beattimes(iChord,1), oldlabel,song.beattimes(iChord,1));
+                oldlabel = label;
+            end
+            oldchord = newchord;
+        end
+        if verbose
+            fprintf(1,'%0.3f %s', song.beattimes(iChord,2), oldlabel);
+        end
+        fprintf(outfile,'%0.3f %s', song.beattimes(iChord,2), oldlabel);
+        fclose(outfile);
+    case 'keylab'
+        keysequence = [song.mpe{keyindex,:}];
+        oldkey = 0;
+        oldlabel ='N';
+        outfile = fopen(outfilename,'w');
+        if verbose
+            fprintf(1, '0.0 ');
+        end
+        fprintf(outfile, '0.0 ');
+        for iKey = 1:length(keysequence)
+            newkey = song.mpe{keyindex, iKey};
+            if newkey ~= oldkey
+                keylabel = param.dbn.keynames{song.mpe{keyindex,iKey}};
+                if verbose
+                    fprintf(1,'%0.3f %s\n%0.3f ', song.beattimes(iKey,1), oldlabel,song.beattimes(iKey,1));
+                end
+                fprintf(outfile,'%0.3f %s\n%0.3f ', song.beattimes(iKey,1), oldlabel,song.beattimes(iKey,1));
+                oldlabel = keylabel;
+            end
+            oldkey = newkey;
+        end
+        if verbose
+            fprintf(1,'%0.3f %s', song.beattimes(iKey,2), oldlabel);
+        end
+        fprintf(outfile,'%0.3f %s', song.beattimes(iKey,2), oldlabel);
+        fclose(outfile);
+    case 'lilypond'
+        bassindex = bnet.names('bass');
+        lilychordnames = repmat(param.dbn.lilytypechordnames,[1,12]);
+        lilychordnames{numel(lilychordnames)+1} = '';
+
+        chordsequence = [song.mpe{chordindex,:}];
+
+        nBeat = length(chordsequence);
+
+        keysequence = [song.mpe{keyindex,:}];
+
+%         label = cell(nBeat,1);
+%         keylabel = cell(nBeat,1);
+
+        metpossequence = [song.mpe{metposindex,:}];
+        oldchord = 0;
+        oldkey = 0;
+        oldbass = 0;
+
+
+
+        chordcount = 0;
+        basscount = 0;
+        chordduration = 1;
+        bassduration = 1;
+        
+        % time signature stuff
+        partial = find(metpossequence == 1,1)-1;
+        if partial > 0
+            partial = ['\partial ' lilylength(partial)];
+        else 
+            partial = '';
+        end
+        barlines = find(metpossequence == 1);
+        timesig = diff(barlines); % for barlines, not beats
+        ind = min(length(timesig),union(find(timesig~=4),find(timesig~=4)+1));
+        non4timesig = barlines(ind);  % in beats
+        timesig = timesig(ind);
+        
+        % chord and bass loop
+
+        for iBeat= 1:length(chordsequence)
+            newchord = song.mpe{chordindex, iBeat};
+            newkey = song.mpe{keyindex, iBeat};
+            newbass = song.mpe{bassindex, iBeat};
+            newmetpos = song.mpe{metposindex, iBeat};
+            if param.dbn.nKey > 0
+                prekeylabel = param.dbn.keynames{song.mpe{keyindex,iBeat}};
+            else
+                prekeylabel = 'C';
+            end
+            if newchord ~= oldchord  || newmetpos == 1 || chordduration == 4
+                % get the chord name
+                chordcount = chordcount + 1;
+                if iBeat > 1
+                    chordlabelduration(chordcount-1) = chordduration;
+                end
+                if ischar(param.dbn.chordnames{newchord})
+                    preroot = spellnote(newkey, param.dbn.chordrootnotes(newchord),'lily');
+                    root{chordcount} = preroot;
+                    if isempty(strfind(param.dbn.chordnames{newchord},'/'))
+                        label{chordcount} = lilychordnames{newchord};
+                    else
+                        bass = spellnote(newkey, param.dbn.chordbassnotes(newchord),'lily');
+                        label{chordcount} = [strrep(lilychordnames{newchord},' ',''),'/',bass];
+                    end
+                else
+                    root{chordcount} = 'r';
+                    label{chordcount} = '';
+                end
+                chordbeat(chordcount) = iBeat;
+
+%                 oldlabel = label{iBeat};
+                chordduration = 1;
+            else
+                chordduration = chordduration + 1;
+            end
+            if oldkey ~= newkey
+                keylabel{iBeat} = param.dbn.lilykeynames{song.mpe{keyindex,iBeat}};
+%                 keylabel{iBeat} = strrep(keylabel{iBeat},'#','is');
+%                 keylabel{iBeat} = strrep(keylabel{iBeat},'b','es');
+%                 keylabel{iBeat} = lower(keylabel{iBeat});
+%                 oldkeylabel = keylabel{iBeat};
+            end
+            if oldbass ~= newbass || newmetpos == 1 || bassduration == 4
+                basscount = basscount + 1;
+                if iBeat > 1
+                    basslabelduration(basscount-1) = bassduration;
+                end
+                basslabel{basscount} = spellnote(newkey, param.dbn.chordbassnotes(newbass),'lily');
+                bassbeat(basscount) = iBeat;
+                bassduration = 1;
+            else                
+                bassduration = bassduration + 1;
+            end
+
+            oldbass = newbass;
+            oldkey = newkey;
+            oldchord = newchord;
+        end
+        
+
+        % finish off the durations etc
+        basslabelduration(basscount) = bassduration;
+        chordlabelduration(chordcount) = chordduration;
+
+        
+        chord_string = 'chordsymb = { \chordmode { ';
+        bass_string = 'bassnotes = { \override TextScript #''box-padding = #.7 \override TextScript #''font-size = #-3 \override TextScript #''thickness = #.03 \clef bass';
+        for iBeat = 1:nBeat
+            chordind = find(chordbeat == iBeat);
+            bassind = find(bassbeat == iBeat);
+            timesigind = find(non4timesig == iBeat);
+            if ~(iBeat > numel(keylabel) || isempty(keylabel{iBeat}))
+                chord_string = [chord_string sprintf('  } \\key %s \\chordmode { ', keylabel{iBeat})];
+                bass_string = [bass_string sprintf(' \\key %s', keylabel{iBeat})];
+            end
+            if ~isempty(chordind)
+                if ~isempty(timesigind)
+                    chord_string = [chord_string sprintf(' \\time %0.0f/4',timesig(timesigind))];
+                end
+                chord_string = [chord_string sprintf(' %s%s%s',root{chordind}, lilylength(chordlabelduration(chordind)), label{chordind})];
+            end
+            if ~isempty(bassind)
+                bass_string = [bass_string sprintf(' %s%s',basslabel{bassind},lilylength(basslabelduration(bassind)))];
+
+            end
+                
+
+        end
+        fid = fopen(outfilename);
+        fprintf(fid,'\\header{title = "%s"}\n%s}}\n%s\n}\n<<\n\\new ChordNames {\n\\set chordChanges = ##t\n%s\n\\chordsymb\n\n}\n\\new Voice {\n\\chordsymb\n}\n\\new Voice {\n\\bassnotes\n}\n>>\n\\version "2.10.33"\n',...
+            song.filenametrunk, chord_string, bass_string, partial);
+        fclose(fid);
+        if verbose
+            fprintf(1,'\\header{title = "%s"}\n%s}}\n%s\n}\n<<\n\\new ChordNames {\n\\set chordChanges = ##t\n%s\n\\chordsymb\n\n}\n\\new Voice {\n\\chordsymb\n}\n\\new Voice {\n\\bassnotes\n}\n>>\n\\version "2.10.33"\n',...
+                song.filenametrunk, chord_string, bass_string, partial);
+        end
+end
+
+function L = lilylength(beats)
+switch beats
+    case 1
+        L = '4';
+    case 2
+        L = '2';
+    case 3
+        L = '2.';
+    case 4
+        L = '1';
+end
\ No newline at end of file