/** * \brief Chops the data into stationary segments based on Bayesian change point analysis * * This function splits data into two (and recursively runs on those two segments) if it is found that the odds ratio * for them being from two independent Gaussian distributions is greater than a certain threshold. * * The threshold for the natural logarithm of the odds ratio is empirically set to be * \f[ * T = 4.07 + 1.33\log{}_{10}{N}, * \f] * where \f$N\f$ is the length in samples of the dataset. This is based on Monte Carlo simulations of * many realisations of Gaussian noise for data of different lengths. The threshold comes from a linear * fit to the log odds ratios required to give a 1% chance of splitting Gaussian data (drawn from a single * distribution) for data of various lengths. Note, however, that this relation is not good for stretches of data * with lengths of less than about 30 points, and in fact is rather consevative for such short stretches * of data, i.e. such short stretches of data will require relatively larger odds ratios for splitting than * longer stretches. * * \param data [in] A complex data vector * \param chunkMin [in] The minimum allowed segment length * * \return A vector of segment lengths * * \sa find_change_point */ UINT4Vector *chop_data( gsl_vector_complex *data, UINT4 chunkMin ){ UINT4Vector *chunkIndex = NULL; UINT4 length = (UINT4)data->size; REAL8 logodds = 0.; UINT4 changepoint = 0; REAL8 threshold = 0.; /* may need tuning or setting globally */ chunkIndex = XLALCreateUINT4Vector( 1 ); changepoint = find_change_point( data, &logodds, chunkMin ); /* threshold scaling for a 0.5% false alarm probability of splitting Gaussian data */ threshold = 4.07 + 1.33*log10((REAL8)length); if ( logodds > threshold ){ UINT4Vector *cp1 = NULL; UINT4Vector *cp2 = NULL; gsl_vector_complex_view data1 = gsl_vector_complex_subvector( data, 0, changepoint ); gsl_vector_complex_view data2 = gsl_vector_complex_subvector( data, changepoint, length-changepoint ); UINT4 i = 0, l = 0; cp1 = chop_data( &data1.vector, chunkMin ); cp2 = chop_data( &data2.vector, chunkMin ); l = cp1->length + cp2->length; chunkIndex = XLALResizeUINT4Vector( chunkIndex, l ); /* combine new chunks */ for (i = 0; i < cp1->length; i++) { chunkIndex->data[i] = cp1->data[i]; } for (i = 0; i < cp2->length; i++) { chunkIndex->data[i+cp1->length] = cp2->data[i] + changepoint; } XLALDestroyUINT4Vector( cp1 ); XLALDestroyUINT4Vector( cp2 ); } else{ chunkIndex->data[0] = length; } return chunkIndex; }
int print_Lcurve(const char *filename, poltor_workspace *w) { int s = 0; FILE *fp; const size_t p = w->p; double rnorm, Lnorm; gsl_vector_complex_view v = gsl_vector_complex_subvector(w->rhs, 0, p); size_t i; fp = fopen(filename, "a"); if (!fp) { fprintf(stderr, "print_Lcurve: unable to open %s: %s\n", filename, strerror(errno)); return -1; } /* construct A and b, and calculate chi^2 = ||b - A c||^2 */ poltor_build_ls(0, w); rnorm = sqrt(w->chisq); /* compute v = L c; L is stored in w->L by poltor_solve() */ for (i = 0; i < p; ++i) { gsl_complex ci = gsl_vector_complex_get(w->c, i); double li = gsl_vector_get(w->L, i); gsl_complex val = gsl_complex_mul_real(ci, li); gsl_vector_complex_set(&v.vector, i, val); } /* compute || L c || */ Lnorm = gsl_blas_dznrm2(&v.vector); fprintf(fp, "%.12e %.12e %.6e %.6e %.6e\n", log(rnorm), log(Lnorm), w->alpha_int, w->alpha_sh, w->alpha_tor); printcv_octave(w->residuals, "r"); printcv_octave(w->c, "c"); printv_octave(w->L, "L"); fclose(fp); return s; } /* print_Lcurve() */
int lls_complex_fold(const gsl_matrix_complex *A, const gsl_vector_complex *b, lls_complex_workspace *w) { const size_t n = A->size1; if (A->size2 != w->p) { fprintf(stderr, "lls_complex_fold: A has wrong size2\n"); return GSL_EBADLEN; } else if (n != b->size) { fprintf(stderr, "lls_complex_fold: b has wrong size\n"); return GSL_EBADLEN; } else { int s = 0; double bnorm; #if 0 size_t i; gsl_vector_view wv = gsl_vector_subvector(w->w_robust, 0, n); if (w->niter > 0) { gsl_vector_complex_view rc = gsl_vector_complex_subvector(w->r_complex, 0, n); gsl_vector_view rv = gsl_vector_subvector(w->r, 0, n); /* calculate residuals with previously computed coefficients: r = b - A c */ gsl_vector_complex_memcpy(&rc.vector, b); gsl_blas_zgemv(CblasNoTrans, GSL_COMPLEX_NEGONE, A, w->c, GSL_COMPLEX_ONE, &rc.vector); /* compute Re(r) */ for (i = 0; i < n; ++i) { gsl_complex ri = gsl_vector_complex_get(&rc.vector, i); gsl_vector_set(&rv.vector, i, GSL_REAL(ri)); } /* calculate weights with robust weighting function */ gsl_multifit_robust_weights(&rv.vector, &wv.vector, w->robust_workspace_p); } else gsl_vector_set_all(&wv.vector, 1.0); /* compute final weights as product of input and robust weights */ gsl_vector_mul(wts, &wv.vector); #endif /* AHA += A^H A, using only the upper half of the matrix */ s = gsl_blas_zherk(CblasUpper, CblasConjTrans, 1.0, A, 1.0, w->AHA); if (s) return s; /* AHb += A^H b */ s = gsl_blas_zgemv(CblasConjTrans, GSL_COMPLEX_ONE, A, b, GSL_COMPLEX_ONE, w->AHb); if (s) return s; /* bHb += b^H b */ bnorm = gsl_blas_dznrm2(b); w->bHb += bnorm * bnorm; fprintf(stderr, "norm(AHb) = %.12e, bHb = %.12e\n", gsl_blas_dznrm2(w->AHb), w->bHb); if (!gsl_finite(w->bHb)) { fprintf(stderr, "bHb is NAN\n"); exit(1); } return s; } } /* lls_complex_fold() */
int gsl_linalg_hermtd_decomp (gsl_matrix_complex * A, gsl_vector_complex * tau) { if (A->size1 != A->size2) { GSL_ERROR ("hermitian tridiagonal decomposition requires square matrix", GSL_ENOTSQR); } else if (tau->size + 1 != A->size1) { GSL_ERROR ("size of tau must be (matrix size - 1)", GSL_EBADLEN); } else { const size_t N = A->size1; size_t i; const gsl_complex zero = gsl_complex_rect (0.0, 0.0); const gsl_complex one = gsl_complex_rect (1.0, 0.0); const gsl_complex neg_one = gsl_complex_rect (-1.0, 0.0); for (i = 0 ; i < N - 1; i++) { gsl_vector_complex_view c = gsl_matrix_complex_column (A, i); gsl_vector_complex_view v = gsl_vector_complex_subvector (&c.vector, i + 1, N - (i + 1)); gsl_complex tau_i = gsl_linalg_complex_householder_transform (&v.vector); /* Apply the transformation H^T A H to the remaining columns */ if ((i + 1) < (N - 1) && !(GSL_REAL(tau_i) == 0.0 && GSL_IMAG(tau_i) == 0.0)) { gsl_matrix_complex_view m = gsl_matrix_complex_submatrix (A, i + 1, i + 1, N - (i+1), N - (i+1)); gsl_complex ei = gsl_vector_complex_get(&v.vector, 0); gsl_vector_complex_view x = gsl_vector_complex_subvector (tau, i, N-(i+1)); gsl_vector_complex_set (&v.vector, 0, one); /* x = tau * A * v */ gsl_blas_zhemv (CblasLower, tau_i, &m.matrix, &v.vector, zero, &x.vector); /* w = x - (1/2) tau * (x' * v) * v */ { gsl_complex xv, txv, alpha; gsl_blas_zdotc(&x.vector, &v.vector, &xv); txv = gsl_complex_mul(tau_i, xv); alpha = gsl_complex_mul_real(txv, -0.5); gsl_blas_zaxpy(alpha, &v.vector, &x.vector); } /* apply the transformation A = A - v w' - w v' */ gsl_blas_zher2(CblasLower, neg_one, &v.vector, &x.vector, &m.matrix); gsl_vector_complex_set (&v.vector, 0, ei); } gsl_vector_complex_set (tau, i, tau_i); } return GSL_SUCCESS; } }