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);
	  }
      }
    }
  }
Exemple #3
0
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 */
Exemple #4
0
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 */