| 660 | } |
| 661 | |
| 662 | int get_csp (const double *data, const double *labels, int n_epochs, int n_channels, int n_times, |
| 663 | double *output_w, double *output_d) |
| 664 | { |
| 665 | if ((!data) || (!labels) || n_epochs <= 0 || n_channels <= 0 || n_times <= 0) |
| 666 | { |
| 667 | data_logger->error ("Invalid function arguments provided. Please verify that all integer " |
| 668 | "arguments are positive and data and labels arrays aren't empty."); |
| 669 | return (int)BrainFlowExitCodes::INVALID_ARGUMENTS_ERROR; |
| 670 | } |
| 671 | try |
| 672 | { |
| 673 | Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> sum1 ( |
| 674 | n_channels, n_channels); |
| 675 | Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> sum2 ( |
| 676 | n_channels, n_channels); |
| 677 | |
| 678 | sum1.setZero (); |
| 679 | sum2.setZero (); |
| 680 | |
| 681 | int n_class1 = 0; |
| 682 | int n_class2 = 0; |
| 683 | |
| 684 | // Compute an averaged covariance matrix for each class |
| 685 | for (int e = 0; e < n_epochs; e++) |
| 686 | { |
| 687 | Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> X ( |
| 688 | n_channels, n_times); |
| 689 | for (int c = 0; c < n_channels; c++) |
| 690 | { |
| 691 | for (int t = 0; t < n_times; t++) |
| 692 | { |
| 693 | X (c, t) = data[e * n_channels * n_times + c * n_times + t]; |
| 694 | } |
| 695 | } |
| 696 | |
| 697 | // center data |
| 698 | for (int i = 0; i < n_channels; i++) |
| 699 | { |
| 700 | double ctr = X.row (i).mean (); |
| 701 | for (int j = 0; j < n_times; j++) |
| 702 | { |
| 703 | X (i, j) -= ctr; |
| 704 | } |
| 705 | } |
| 706 | |
| 707 | // For centered data cov(X) = (X * X_T) / n |
| 708 | switch (int (labels[e])) |
| 709 | { |
| 710 | case 0: |
| 711 | sum1 += ((X * X.transpose ()).eval ()) / double (n_times); |
| 712 | n_class1++; |
| 713 | break; |
| 714 | case 1: |
| 715 | sum2 += ((X * X.transpose ()).eval ()) / double (n_times); |
| 716 | n_class2++; |
| 717 | break; |
| 718 | default: |
| 719 | data_logger->error ("Invalid class label. Current class label: {}", labels[e]); |