/* This is for multi-channel "sounds" like EEG signals. The cross-correlation between channel i and channel j is defined as sum(k=1..nsamples, (z[i][k] - mean[i])(z[j][k + tau] - mean[j]))*samplingTime */ autoCrossCorrelationTable Sound_to_CrossCorrelationTable (Sound me, double startTime, double endTime, double lagStep) { try { if (endTime <= startTime) { startTime = my xmin; endTime = my xmax; } long lag = (long) floor (lagStep / my dx); // ppgb: voor al dit soort dingen geldt: waarom afronden naar beneden? long i1 = Sampled_xToNearestIndex (me, startTime); if (i1 < 1) { i1 = 1; } long i2 = Sampled_xToNearestIndex (me, endTime); if (i2 > my nx) { i2 = my nx; } i2 -= lag; long nsamples = i2 - i1 + 1; if (nsamples <= my ny) { Melder_throw (U"Not enough samples, choose a longer interval."); } autoCrossCorrelationTable thee = CrossCorrelationTable_create (my ny); NUMcrossCorrelate_rows (my z, my ny, i1, i2, lag, thy data, thy centroid, my dx); thy numberOfObservations = nsamples; return thee; } catch (MelderError) { Melder_throw (me, U": CrossCorrelationTable not created."); } }
/* This is for multi-channel "sounds" like EEG signals. The cross-correlation between channel i and channel j is defined as sum(k=1..nsamples, (z[i][k] - mean[i])(z[j][k + tau] - mean[j]))*samplingTime */ CrossCorrelationTable Sound_to_CrossCorrelationTable (Sound me, double startTime, double endTime, double lagTime) { try { if (endTime <= startTime) { startTime = my xmin; endTime = my xmax; } long lag = lagTime / my dx; long i1 = Sampled_xToNearestIndex (me, startTime); if (i1 < 1) { i1 = 1; } long i2 = Sampled_xToNearestIndex (me, endTime); if (i2 > my nx) { i2 = my nx; } i2 -= lag; long nsamples = i2 - i1 + 1; if (nsamples <= my ny) { Melder_throw ("Not enough samples, choose a longer interval."); } autoCrossCorrelationTable thee = CrossCorrelationTable_create (my ny); NUMcrossCorrelate_rows (my z, my ny, i1, i2, lag, thy data, thy centroid, my dx); thy numberOfObservations = nsamples; return thee.transfer(); } catch (MelderError) { Melder_throw (me, ": CrossCorrelationTable not created."); } }
autoCrossCorrelationTable CrossCorrelationTable_and_Diagonalizer_diagonalize (CrossCorrelationTable me, Diagonalizer thee) { try { if (my numberOfRows != thy numberOfRows) { Melder_throw (U"The CrossCorrelationTable and the Diagonalizer matrix dimensions must be equal."); } autoCrossCorrelationTable him = CrossCorrelationTable_create (my numberOfColumns); NUMdmatrices_multiply_VCVp (his data, thy data, my numberOfColumns, my numberOfColumns, my data, 1); return him; } catch (MelderError) { Melder_throw (U"CrossCorrelationTable not diagonalized."); } }
/* * Generate n different cct's that have a common diagonalizer. */ autoCrossCorrelationTables CrossCorrelationTables_createTestSet (long dimension, long n, int firstPositiveDefinite, double sigma) { try { // Start with a square matrix with random gaussian elements and make its singular value decomposition UDV' // The V matrix will be the common diagonalizer matrix that we use. autoNUMmatrix<double> d (1, dimension, 1, dimension); for (long i = 1; i <= dimension; i++) { // Generate the rotation matrix for (long j = 1; j <= dimension; j++) { d[i][j] = NUMrandomGauss (0, 1); } } autoNUMmatrix<double> v (1, dimension, 1, dimension); autoSVD svd = SVD_create_d (d.peek(), dimension, dimension); autoCrossCorrelationTables me = CrossCorrelationTables_create (); for (long i = 1; i <= dimension; i++) { for (long j = 1; j <= dimension; j++) { d[i][j] = 0; } } // Start with a diagonal matrix D and calculate V'DV for (long k = 1; k <= n; k++) { autoCrossCorrelationTable ct = CrossCorrelationTable_create (dimension); double low = k == 1 && firstPositiveDefinite ? 0.1 : -1; for (long i = 1; i <= dimension; i++) { d[i][i] = NUMrandomUniform (low, 1); } for (long i = 1; i <= dimension; i++) { for (long j = 1; j <= dimension; j++) { v[i][j] = NUMrandomGauss (svd -> v[i][j], sigma); } } // we need V'DV, however our V has eigenvectors row-wise -> VDV' NUMdmatrices_multiply_VCVp (ct -> data, v.peek(), dimension, dimension, d.peek(), 1); Collection_addItem_move (me.peek(), ct.move()); } return me; } catch (MelderError) { Melder_throw (U"CrossCorrelationTables test set not created."); } }
/* Calculate the CrossCorrelationTable between the channels of two multichannel sounds irrespective of the domains. * Both sounds are treated as if their domain runs from 0 to duration. * Outside the chosen interval the sounds are assumed to be zero */ autoCrossCorrelationTable Sounds_to_CrossCorrelationTable_combined (Sound me, Sound thee, double relativeStartTime, double relativeEndTime, double lagStep) { try { if (my dx != thy dx) { Melder_throw (U"Sampling frequencies must be equal."); } if (relativeEndTime <= relativeStartTime) { relativeStartTime = my xmin; relativeEndTime = my xmax; } long ndelta = (long) floor (lagStep / my dx), nchannels = my ny + thy ny; long i1 = Sampled_xToNearestIndex (me, relativeStartTime); if (i1 < 1) { i1 = 1; } long i2 = Sampled_xToNearestIndex (me, relativeEndTime); if (i2 > my nx) { i2 = my nx; } i2 -= ndelta; long nsamples = i2 - i1 + 1; if (nsamples <= nchannels) { Melder_throw (U"Not enough samples"); } autoCrossCorrelationTable him = CrossCorrelationTable_create (nchannels); autoNUMvector<double *> data (1, nchannels); for (long i = 1; i <= my ny; i++) { data[i] = my z[i]; } for (long i = 1; i <= thy ny; i++) { data[i + my ny] = thy z[i]; } NUMcrossCorrelate_rows (data.peek(), nchannels, i1, i2, ndelta, his data, his centroid, my dx); his numberOfObservations = nsamples; return him; } catch (MelderError) { Melder_throw (me, U": CrossCorrelationTable not created."); } }
autoCrossCorrelationTable CrossCorrelationTable_createSimple (char32 *covars, char32 *centroid, long numberOfSamples) { try { long dimension = Melder_countTokens (centroid); long ncovars = Melder_countTokens (covars); long ncovars_wanted = dimension * (dimension + 1) / 2; if (ncovars != ncovars_wanted) Melder_throw (U"The number of matrix elements and the number of " U"centroid elements are not in concordance. There should be \"d(d+1)/2\" matrix values and \"d\" centroid values."); autoCrossCorrelationTable me = CrossCorrelationTable_create (dimension); // Construct the full matrix from the upper-diagonal elements long inum = 1, irow = 1; for (char32 *token = Melder_firstToken (covars); token != nullptr && inum <= ncovars_wanted; token = Melder_nextToken (), inum++) { double number; long nmissing = (irow - 1) * irow / 2; long inumc = inum + nmissing; irow = (inumc - 1) / dimension + 1; long icol = ( (inumc - 1) % dimension) + 1; Interpreter_numericExpression (nullptr, token, &number); my data[irow][icol] = my data[icol][irow] = number; if (icol == dimension) { irow++; } } inum = 1; for (char32 *token = Melder_firstToken (centroid); token != nullptr && inum <= dimension; token = Melder_nextToken (), inum++) { double number; Interpreter_numericExpression (nullptr, token, &number); my centroid[inum] = number; } my numberOfObservations = numberOfSamples; return me; } catch (MelderError) { Melder_throw (U"CrossCorrelationTable not created."); } }