void TensorProductBasis<BASIS0,BASIS1>::decompose(const InfiniteVector<double, Index>& c, const int j0, InfiniteVector<double, Index>& d) const { InfiniteVector<double, Index> help; for (typename InfiniteVector<double, Index>::const_iterator it(c.begin()), itend(c.end()); it != itend; ++it) { decompose_1(it.index(), j0, help); // calls help.clear() first d.add(*it, help); } }
void TensorProductBasis<BASIS0,BASIS1>::decompose_1(const Index& lambda, const int j0, InfiniteVector<double, Index>& c) const { assert(lambda.j() >= j0); c.clear(); if (lambda.index0().e() != 0 || lambda.index1().e() != 0) { // the true wavelet coefficients don't have to be modified c.set_coefficient(lambda, 1.0); } else { // a generator on a (possibly) fine level if (lambda.j() == j0) { // generators from the coarsest level can be copied c.set_coefficient(lambda, 1.0); } else { // j>j0, perform multiscale decomposition typedef typename BASIS0::Index Index0; typedef typename BASIS1::Index Index1; InfiniteVector<double,Index0> c1; InfiniteVector<double,Index1> c2; basis0().decompose_1(lambda.index0(), lambda.j()-1, c1); basis1().decompose_1(lambda.index1(), lambda.j()-1, c2); for (typename InfiniteVector<double,Index0>::const_iterator it1(c1.begin()), it1end(c1.end()); it1 != it1end; ++it1) for (typename InfiniteVector<double,Index1>::const_iterator it2(c2.begin()), it2end(c2.end()); it2 != it2end; ++it2) { // if (it1.index().e() == 0 && it2.index().e() == 0) { // generators have to be refined further InfiniteVector<double,Index> d; decompose_1(Index(it1.index(), it2.index()), j0, d); c.add(*it1 * *it2, d); // } else // c.set_coefficient(Index(this, it1.index(), it2.index()), *it1 * *it2); } } } }
int decompose_n(const Event_Signal *asig, /* observed signals*/ Event_Signal *bsig, /* fitted signals*/ int nseg, int *seg, int coalesce, Interaction *ints, double *t0, double *chisq_out) /* parameters */ { /* performs the adaptive grid search algorithm for three-segment events, optionally followed by constrained least-squares returns number of best-fit interactions found ints[] array is set to contain the resulting best-fit multi-interaction */ double chisq2; int i, j, m, n, jseg, jfit, jint, segsave, best, shift_t0; float e1, e2; Event_Signal asig_temp; Interaction f_ints[4*MAX_SEGS][3*MAX_SEGS]; /* test/fitted interactions */ Event_Signal f_bsig[4*MAX_SEGS]; /* calculated/fitted event data */ double f_t0[4*MAX_SEGS], chisq[4*MAX_SEGS]; int nints[4*MAX_SEGS]; /* put segments in order of decreasing energy */ for (i=1; i<nseg; i++) { for (j=i; j>0 && asig->seg_energy[seg[j-1]] < asig->seg_energy[seg[j]]; j--) { segsave = seg[j-1]; seg[j-1] = seg[j]; seg[j] = segsave; } } /* start off with a simple nseg-interaction fit, one in each hit segment */ for (i=0; i<nseg; i++) { f_ints[0][i].seg = seg[i]; f_ints[0][i].pos = -1; f_ints[0][i].r = maxir[seg[i]]/2; f_ints[0][i].p = maxip[seg[i]]/2; f_ints[0][i].z = maxiz[seg[i]]/2; f_ints[0][i].e = asig->seg_energy[seg[i]] / asig->total_energy; } nints[0] = nseg; f_t0[0] = 0; chisq[0] = fitter(asig, &f_bsig[0], f_ints[0], &f_t0[0], nseg, 0); best = 0; asig_temp = *asig; jfit = 1; /* loop throught the hit segments, trying to add interactions one at a time if the net energy gets too small, then quit */ for (jseg=0; jseg<nseg && asig->seg_energy[seg[jseg]] > 120.0; jseg++) { /* ---------------------------------------------- now add a second interaction to the jseg-th segment; first subtract the calculated signal for the other segments from the observed signal */ jint = nints[best] - nseg + jseg; for (i=0; i<jint; i++) { f_ints[jfit][i] = f_ints[best][i]; } for (i=jint + 1; i<nints[best]; i++) { f_ints[jfit][i-1] = f_ints[best][i]; } eval_int_pos(asig, bsig, f_ints[jfit], f_t0[best], nints[best]-1); for (i=0; i<MEAS_SEGS; i++) { for (j=0; j<TIME_STEPS; j++) { asig_temp.signal[i][j] -= bsig->signal[i][j]; } } /* shift the remaining signal to bring t0 close to zero */ shift_t0 = f_t0[best] - 1.0; if (shift_t0 > 0) { if (!quiet) printf("*----* shifting t0 by %d\n", shift_t0); for (i=0; i<MEAS_SEGS; i++) { for (j=0; j<TIME_STEPS-shift_t0; j++) { asig_temp.signal[i][j] = asig_temp.signal[i][j+shift_t0]; } for (j=TIME_STEPS-shift_t0; j<TIME_STEPS-1; j++) { asig_temp.signal[i][j] = asig_temp.signal[i][TIME_STEPS-1]; } } } else { shift_t0 = 0; } /* do 2-interation grid search in segment seg[jseg] */ /* CHECKME min. energy fract */ if (2 != decompose_1(&asig_temp, &f_bsig[jfit], seg[jseg], &f_ints[jfit][jint], &f_t0[jfit], &chisq[jfit], 0, 0, 1, 0, 0, 0, 0, 0, 0.01)) { printf("*** ACK! decompose_1 gave number of interactions != 2...\n" " ... expect a crash very soon ...\n"); } if (!quiet) { printf("** grid1[%d]: chisq, pars: %7.4f", jseg, chisq[jfit]); for (i=jint; i<jint+2; i++) printf(", %6.3f %6.3f %6.3f %6.3f", f_ints[jfit][i].r, f_ints[jfit][i].p, f_ints[jfit][i].z, f_ints[jfit][i].e); printf("\n"); } for (i=jint + 1; i<nints[best]; i++) { f_ints[jfit][i+1] = f_ints[best][i]; } f_t0[jfit] = (f_t0[jfit] + f_t0[best] + (double) shift_t0)/2.0; nints[jfit] = nints[best] + 1; chisq2 = eval_int_pos(asig, &f_bsig[jfit], f_ints[jfit], f_t0[jfit], nints[jfit]); if (!quiet) { if (fabs(chisq[jfit]-chisq2) < 0.00001) { printf("***** chisq[%d] == chisq2: %f %f\n", jfit, chisq[jfit], chisq2); } else { printf("***** chisq[%d] != chisq2: %f %f\n", jfit, chisq[jfit], chisq2); } } chisq[jfit] = chisq2; if (chisq[jfit] < PENALTY3 * chisq[best]) best = jfit; /* do nonlinear least-squares fit with the extra interaction(s)*/ for (i=0; i<nints[jfit]; i++) { f_ints[jfit+1][i] = f_ints[jfit][i]; } /* f_t0[jfit+1] = f_t0[jfit]; */ f_t0[jfit+1] = f_t0[best]; nints[jfit+1] = nints[jfit]; jfit++; chisq[jfit] = fitter(asig, &f_bsig[jfit], f_ints[jfit], &f_t0[jfit], nints[jfit], 0); if (chisq[jfit] < PENALTY4 * chisq[best]) best = jfit; if (!quiet) { printf("**>>> jint, jfit, best, chisq[best], nints[best] : %d %d %d %f %d\n", jint, jfit, best, chisq[best], nints[best]); } jfit++; } if (coalesce) { /* Try coalescing interactions, accepting/rejecting by chisq value */ /* loop throught the hit segments, looking for double interactions */ for (jseg=0; jseg<nseg; jseg++) { m = n = -1; for (i = 0; i < nints[best]; i++) { f_ints[jfit][i] = f_ints[best][i]; if (f_ints[best][i].seg == seg[jseg]) { if (m < 0) { m = i; } else { n = i; break; } } } if (n >= 0) { /* have found 2 interactions in this seg */ if (!quiet) printf("*** Try a coalescence fit for seg %d, ints %d, %d\n", seg[jseg], m, n); e1 = f_ints[best][m].e; e2 = f_ints[best][n].e; f_ints[jfit][m].r = (e1*f_ints[best][m].r + e2*f_ints[best][n].r) / (e1+e2); f_ints[jfit][m].p = (e1*f_ints[best][m].p + e2*f_ints[best][n].p) / (e1+e2); f_ints[jfit][m].z = (e1*f_ints[best][m].z + e2*f_ints[best][n].z) / (e1+e2); f_ints[jfit][m].e = e1+e2; for (i = n; i < nints[best]-1; i++) { f_ints[jfit][i] = f_ints[best][i+1]; } f_t0[jfit] = f_t0[best]; nints[jfit] = nints[best] - 1; chisq[jfit] = fitter(asig, &f_bsig[jfit], f_ints[jfit], &f_t0[jfit], nints[jfit], 0); if (PENALTY3 * chisq[jfit] <= chisq[best]) best = jfit; if (!quiet) { printf("**>>> jfit, best, chisq[best], nints[best] : %d %d %f %d\n", jfit, best, chisq[best], nints[best]); } jfit++; } } } /* do a final fit with tighter convergence criteria */ for (i=0; i<nints[best]; i++) { f_ints[jfit][i] = f_ints[best][i]; } f_t0[jfit] = f_t0[best]; nints[jfit] = nints[best]; chisq[jfit] = fitter(asig, &f_bsig[jfit], f_ints[jfit], &f_t0[jfit], nints[jfit], 1); if (chisq[jfit] < chisq[best]) best = jfit; *bsig = f_bsig[best]; *t0 = f_t0[best]; *chisq_out = chisq[best]; for (i=0; i<nints[best]; i++) { ints[i] = f_ints[best][i]; } return nints[best]; } /* decompose_n */
struct crys_intpts *dl_decomp(struct decomp_state *di, Event_Signal *asig, postprocCnt *postCnt) { /*** dl_decomp modified to return a crystal event regardless of its ability to decompose. If an event cannot be decomposed an empty crys_intpts struct is allocated with on its type and pad fileds set. The pad field is 0 if event met standard decomp criteria or set to the following values if not: pad = 1 a null pointer was passed to dl_decomp() = 2 total energy below threshold = 3 no net charge segments in evt = 4 too many net charge segments = 5 chi^2 is bad following decomp (in this case crys_intpts is non-zero but post-processing step is not applied) */ struct crys_intpts *ci; double xfinal[MAX_PARS], yfinal[MAX_PARS], zfinal[MAX_PARS], efinal[MAX_PARS]; int sfinal[MAX_PARS]; /* keep track of segments hit */ double esum, chisq, chisq2, t0; int nseg, nints, found, i, ii, t, seg[TOT_SEGS]; Basis_Point *b; simpleInteraction ints[MAX_SEGS]; /* for single interaction search */ int stat; ci = (struct crys_intpts*) Calloc(1, sizeof(struct crys_intpts)); /* ci->type = 0xabcd1234; */ ci->type = 0xabcd5678; /* assert(asig != 0); */ if (!asig) { printf("NULL asig\n"); ci->pad = 1; /* Null pointer */ return ci; } ci->timestamp = asig->time; for (i = 0; i < 4; i++) { ci->core_e[i] = asig->core_e[i]; } ci->tot_e = asig->total_energy; ci->prestep = asig->prestep; ci->poststep = asig->poststep; if (asig->total_energy < 20.0) { printf("low total energy\n"); ci->pad = 2; /* Total energy below threshold */ return ci; } /* set bad segment signals to zero */ for (i=0; bad_segs[i]>=0; i++) { ii = bad_segs[i]; for (t=0; t<TIME_STEPS; t++) asig->signal[ii][t] = 0.0f; asig->seg_energy[ii] = 0.0f; } /* determine which segments have net energy */ nseg = 0; esum = 0.0; for (i = 0; i < TOT_SEGS; i++) { seg[i] = 0; if (asig->seg_energy[i] > 30.0) { esum += asig->seg_energy[i]; seg[nseg++] = i; } } if (nseg == 0) { di->err->nonet++; printf("no net\n"); ci->pad = 3; /* No net charge segments */ return ci; } if (nseg > MAX_SEGS) { di->err->toomanynet++; printf("too many net - nseg = %d\n", nseg); ci->pad = 4; /* Too many net charge segments */ for (i = 0; i < MAX_INTPTS; i++) { ci->intpts[i].seg = i; ci->intpts[i].seg_ener = asig->seg_energy[i]; } return ci; } /* remove for high-rate runs with cc pileup */ // if (fabs(esum - asig->total_energy) > 90.0) { // di->err->sumener++; // printf("bad sum\n"); // return 0; // } (void) memset(di->bsig, 0, sizeof(Event_Signal)); (void) memset(di->ints, 0, 2 * MAX_SEGS * sizeof(Interaction)); #ifdef ONEINT //printf("nseg=%d\n", nseg); if (nseg >= 1 && nseg <= 4) { stat = normDiag(asig, nseg, seg); if (badTrPred(asig, nseg, seg)) { fprintf(stderr, "bad net segment trace\n"); ci->pad = 40; /* oneInt search failed - bad net trace */ return ci; } //stat = oneIntSearchIter(asig, di->bsig, nseg, seg, ints, &chisq); stat = oneIntSearch2(asig, di->bsig, nseg, seg, ints, &chisq); if (stat != 0) { ci->pad = 41; /* oneInt search failed */ return ci; } /* employ no post-processng, output ci directly */ ci->num = nseg; ci->tot_e = asig->total_energy; for (i = 0, ci->baseline = 0.0; i < 20; i++) { /* calc baseline */ ci->baseline += (float) asig->signal[36][i]; } ci->baseline /= 20.0; ci->chisq = chisq; ci->norm_chisq = 0; ci->timestamp = asig->time; assert(b != 0); for (i = 0; i < nseg; i++) { ci->intpts[i].x = ints[i].x; ci->intpts[i].y = ints[i].y; ci->intpts[i].z = ints[i].z; ci->intpts[i].e = asig->seg_energy[seg[i]]; ci->intpts[i].seg = seg[i]; ci->intpts[i].seg_ener = asig->seg_energy[seg[i]]; } ci->pad = 42; /* properly decomposed oneInt event */ return ci; } ci->pad = 43; /* numNet out of range */ return ci; #else /* branch according to number of hit segments */ if (nseg == 1) { nints = decompose_1(asig, di->bsig, seg[0], di->ints, &t0, &chisq, 0, 1, 1, 1, 1, 1, 1, 1, 0.1); } else { printf("nseg >1\n"); nints = decompose_n(asig, di->bsig, nseg, seg, 1, di->ints, &t0, &chisq); } #endif /* no need to have such cut here */ if (chisq > 99.9) { di->err->badchisq++; ci->pad = 5; /* Chi squared is bad */ // return ci; } di->cnt++; /* post_process the results ppflag = 2; -- combine interactions in the same seg based on energy or distance ppflag = 1; -- do not combine interactions in the same seg based on energy or distance */ found = postprocess_events(di->ints, nints, asig->total_energy, 2, di->coal_dist, xfinal, yfinal, zfinal, efinal, sfinal, postCnt); chisq2 = chisq / (float) (MEAS_SEGS * TIME_STEPS); chisq2 /= (4.0 / asig->total_energy) * (4.0 / asig->total_energy); /* crytal evt always returned, alloc crys_intpt at beginning of routine */ // ci = (struct crys_intpts*) Calloc(1, sizeof(struct crys_intpts)); // ci->type = 0xabcd1234; ci->num = found; ci->tot_e = asig->total_energy; /* calc baseline */ for (i = 0, ci->baseline = 0.0; i < 20; i++) { ci->baseline += (float) asig->signal[36][i]; } ci->baseline /= 20.0; #ifdef TIMEOFFSET /* DCR: add in saved offset coming from time alignment of signals in preproc */ t0 += asig->time_offset; ci->intpts[MAX_INTPTS-1].z = asig->time_offset; /* DCR UGLY hack; saves offset for comparing time spectra resolutions downstream; this line can be removed without changing proper functionality! */ #endif ci->t0 = t0; ci->chisq = chisq; ci->norm_chisq = chisq2; #ifdef TIMESTAMP ci->timestamp = asig->time; #endif for (i = 0; i < found; i++) { ci->intpts[i].x = xfinal[i]; ci->intpts[i].y = yfinal[i]; ci->intpts[i].z = zfinal[i]; ci->intpts[i].e = efinal[i]; ci->intpts[i].seg = sfinal[i]; ci->intpts[i].seg_ener = asig->seg_energy[sfinal[i]]; } if (dump_mat) { int j; for(i=0; i<4096; i++) { di->mat[i] = 0; } for (i=0; i<MEAS_SEGS; i++) { for (j=0; j<TIME_STEPS; j++) { di->mat[50*i + j] = lrintf(asig->signal[i][j] * 10000.0f); di->mat[2000 + 50*i + j] = lrintf(di->bsig->signal[i][j] * 10000.0f); } } di->pos = *ci; } return ci; } /* dl_decomp */