73 auto const mass_sum = std::accumulate( masses.begin(), masses.end(), 0.0 );
77 auto link_masses = std::vector<double>( sample.
tree().
link_count(), -1.0 );
82 if( tree_it.is_last_iteration() ) {
89 auto const cur_idx = tree_it.link().index();
90 auto const out_idx = tree_it.link().outer().index();
93 assert( link_masses[ cur_idx ] < 0.0 );
94 assert( link_masses[ out_idx ] < 0.0 );
104 assert( tree_it.edge().primary_link().index() == out_idx );
105 assert( tree_it.edge().secondary_link().index() == cur_idx );
108 if(
is_leaf( tree_it.link() )) {
109 link_masses[ cur_idx ] = 0.0;
117 double round_sum = 0.0;
120 auto round_link = &tree_it.link().next();
121 while( round_link != &tree_it.link() ) {
124 assert( link_masses[ round_link->index() ] >= 0.0 );
128 round_sum += mass_sum - link_masses[ round_link->index() ];
131 round_link = &round_link->next();
135 link_masses[ cur_idx ] = std::max( 0.0, round_sum );
140 link_masses[out_idx] = std::max(
142 mass_sum - link_masses[ cur_idx ] - masses[ tree_it.edge().index() ]
146 assert( link_masses[cur_idx] > -1.0 );
147 assert( link_masses[out_idx] > -1.0 );
151 auto const imbalance = link_masses[cur_idx] - link_masses[out_idx];
153 auto const normalizer = mass_sum - masses[ tree_it.edge().index() ];
154 assert( normalizer > 0.0 );
155 vec[ tree_it.edge().index() ] = imbalance / normalizer;
157 vec[ tree_it.edge().index() ] = imbalance;
174 if( samples.
size() == 0 ) {
180 throw std::runtime_error(
181 "Cannot calculate Edge PCA on trees that have a different topology."
185 assert( samples.
size() > 0 );
188 if( include_leaves ) {
192 #pragma omp parallel for
193 for(
size_t s = 0; s < samples.
size(); ++s ) {
194 auto const& smp = samples[s];
206 !
is_leaf( samples[s].tree().edge_at(i).secondary_node() ) ||
210 imbalance_matrix( s, i ) = imbalance_vec[ i ];
214 return imbalance_matrix;
224 #pragma omp parallel for
225 for(
size_t s = 0; s < samples.
size(); ++s ) {
226 auto const& smp = samples[s];
238 imbalance_matrix( s, i ) = imbalance_vec[ idx ];
242 return imbalance_matrix;
254 throw std::runtime_error(
"Argument for kappa must be non-negative." );
260 for(
auto& elem : imbalance_matrix ) {
272 for(
auto& elem : imbalance_matrix ) {
273 elem =
static_cast<double>(
utils::signum( elem )) * std::pow( std::abs( elem ), kappa );
284 if( samples.
size() == 0 ) {
290 assert( samples.
size() > 0 );
291 assert( imbalance_matrix.rows() == samples.
size() );
304 std::vector<size_t> edge_indices;
305 for(
auto const& not_filt : not_filtered_indices ) {
308 assert( edge_indices.size() == imbalance_matrix.cols() );
311 if( components == 0 || components > imbalance_matrix.cols() ) {
312 components = imbalance_matrix.cols();
319 assert( pca.eigenvalues.size() == components );
320 assert( pca.eigenvectors.rows() == edge_indices.size() );
321 assert( pca.eigenvectors.cols() == components );
322 assert( pca.projection.rows() == samples.
size() );
323 assert( pca.projection.cols() == components );
329 result.
projection = std::move( pca.projection );