Commit in lcsim/src/org/lcsim/recon/vertexing/pixsim on MAIN
FastAnalogElectronics.java+349added 1.1
New kind of electronics

lcsim/src/org/lcsim/recon/vertexing/pixsim
FastAnalogElectronics.java added at 1.1
diff -N FastAnalogElectronics.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ FastAnalogElectronics.java	10 Feb 2011 22:29:51 -0000	1.1
@@ -0,0 +1,349 @@
+package org.lcsim.recon.vertexing.pixsim;
+import java.util.*;
+import org.lcsim.event.*;
+import org.lcsim.event.base.*;
+
+
+/**
+ * @author Nick Sinev
+ */
+
+public class FastAnalogElectronics extends BasePixelElectronics
+{
+  int window = 1;    // sensitive window expressed in clock intervals
+  int reset_int = 1; // number of BC between resets. Charge between resets is accumulated.
+
+  public FastAnalogElectronics()
+  {
+   this(IlcOption.NOMINAL);
+  }
+
+  public FastAnalogElectronics(IlcOption opt)
+  {
+   super();
+   name="FastAnalogElectronics";
+   option = opt; 
+   if(option == IlcOption.SHORT_INT)
+   {
+    bunch_interval = cons.BunchIntervalA;
+    n_bunches = cons.NumberOfBunchesInTrainA;
+   }
+   if(option == IlcOption.LONG_INT)
+   {
+    bunch_interval = cons.BunchIntervalB;
+    n_bunches = cons.NumberOfBunchesInTrainB;
+   }
+   if(option == IlcOption.CLIC)
+   {
+    bunch_interval = cons.BunchIntervalC;
+    n_bunches = cons.NumberOfBunchesInTrainC;
+    window=n_bunches;
+    reset_int=window;
+   }
+   bunch_per_clock = 1;     
+   clocks_per_bunch = 1; 
+   clock_period = bunch_interval * bunch_per_clock;  
+   useCDS = false;                 
+   addNoiseHits = false;
+   read_during_train = true;
+  }
+
+  int n_buffers = 1;
+  double train_duration = n_bunches * bunch_interval;
+  double bandwidth = 1.E7; // comparator bandwidth - define how many noise samples per second will be generated.
+
+ 
+  public void processSensor(IPixilatedSensor sens, int bc)
+  {
+   boolean sdebug = ((PixilatedSensor) sens).ddebug;
+   int acc_strt = bc-1;
+   int acc_end = bc+window;
+   if(bunch_per_clock > 1)
+   {
+    acc_strt = (int) Math.floor((double)(bc-1)/(double) bunch_per_clock);
+    acc_end = (int) Math.floor((double)(bc)/(double) bunch_per_clock) + window;
+    clock_period = bunch_interval * bunch_per_clock;
+   } 
+   if(clocks_per_bunch > 1)
+   {
+    acc_strt = bc*clocks_per_bunch - 1;
+    acc_end =  bc*clocks_per_bunch + window;
+    clock_period = bunch_interval/clocks_per_bunch;
+   }
+   int snr = sens.getNRows();
+   int snc = sens.getNColumns();
+   int nars = 0;
+   if(addNoiseHits) generateNoise(sens);  
+   List<ActivePixel> sens_pixs = sens.getActivePixels();
+   for(ActivePixel pix:sens_pixs)
+   {
+    double dtf = 0.;
+    boolean first = true;
+    int prow = (int) (pix.row);
+    int pcol = (int) (pix.column);
+    int[] tstmps = new int[n_buffers];
+    int[] aadc = new int[n_buffers];
+    ResetInterval[] fri = new ResetInterval[n_buffers];
+    int buf = 0;
+    int acharge = 0; 
+    List<ChargeTrain> ctrains = pix.getChargeTrains();
+    List<SimTrackerHit> simhits = new ArrayList<SimTrackerHit>();
+    int min_bc=n_bunches; 
+    int max_bc = 0;
+    for(ChargeTrain ct:ctrains)
+    {
+     int ctbc = ct.getBeamCrossing();
+     if(ctbc < min_bc) min_bc=ctbc;
+     if(ctbc > max_bc) max_bc=ctbc;
+     double dt = ct.getTimeBin();
+     if(first)
+     {
+      dtf = dt;
+      first = false;
+      if(dt < 0.1e-10) System.out.println("Time bin in charge train is too small! :"+dt);
+     }
+     if(Math.abs(1. - dtf/dt) > 1.e-6)
+     {
+      System.out.println("Non-equal time bins in charge trains! Correct it!");
+      return;
+     } 
+    } //end for(ChargeTrain ct:ctrains)
+    List<NoiseHit> n_hits = pix.noise_hits;
+    int nnhts = 0;
+    if((n_hits != null) && (!first))
+    {
+     nnhts = n_hits.size();
+     for(NoiseHit nh:n_hits)
+     {
+      int nbc = (int) Math.floor(nh.getTime()/bunch_interval);
+      if(nbc < min_bc) min_bc = nbc;
+      if(nbc > max_bc) max_bc = nbc;
+     }
+    }
+    if(!first)
+    { 
+    int n_bns_pri = (int) Math.floor((reset_int*bunch_interval)/dtf) + 1;
+    if(n_bns_pri < 1) 
+     System.out.println("n_bns_pri="+n_bns_pri+" from reset_int="+reset_int+" and bunch_int="+bunch_interval+"with dtf="+dtf); 
+    Vector actrsts = new Vector();
+    for(int i=min_bc; i<max_bc+1; i++)
+    {
+     if(i%reset_int == 0)
+     {
+      boolean active = false;
+      ResetInterval ari = null;
+      double strtri = i*bunch_interval;
+      double endri =  (i+reset_int)*bunch_interval;
+      for(ChargeTrain ct:ctrains)
+      {
+       double strttr = ct.getBeamCrossing() * bunch_interval;
+       double endtr = strttr + ct.getCharge().length * dtf;
+       if(((strttr >= strtri) && (strttr < endri)) || ((endtr >= strtri) && (endtr < endri))) active=true;
+       if(((strtri >= strttr) && (strtri < endtr)) || ((endri >= strttr) && (endri < endtr))) active=true;
+      }
+      if(active) ari= new ResetInterval(i,n_bns_pri); 
+      if(n_hits != null)
+      {
+       for(NoiseHit nh:n_hits)
+       {
+        double nht = nh.getTime();
+        if((nht >= strtri) && (nht < endri))
+        {
+         if(ari != null) ari.addNoiseHit(nh); 
+         else
+         {
+          ari = new ResetInterval(i,n_bns_pri);
+          ari.addNoiseHit(nh);
+         } 
+        }
+       }
+      }
+      if(ari != null) actrsts.addElement(ari);
+     } 
+    } // end for(int i=min_bc; i<max_bc+1; i++)
+    int narsts = actrsts.size();
+    for(int i=0; i<narsts; i++)
+    {
+     ResetInterval ari = (ResetInterval) actrsts.get(i);
+     int rbc = ari.getBunchCrossing();
+     double strtri = rbc*bunch_interval; 
+     double endri =  (rbc+reset_int)*bunch_interval;
+     for(ChargeTrain ct:ctrains)
+     {
+      boolean active = false;
+      double strttr = ct.getBeamCrossing() * bunch_interval;
+      double endtr = strttr + ct.getCharge().length * dtf;
+      if(((strttr >= strtri) && (strttr < endri)) || ((endtr >= strtri) && (endtr < endri))) active=true;
+      if(((strtri >= strttr) && (strtri < endtr)) || ((endri >= strttr) && (endri < endtr))) active=true;
+      if(active)
+      {
+       short[] chbns = ct.getCharge();
+       SimTrackerHit shit = ct.getSimTrackerHit();
+       ari.addSimHit(shit);
+       double toff = strttr - strtri;
+       int boff = (int) Math.floor(toff/dtf);
+       for(int j=0; j<chbns.length; j++)
+       {
+        int k = j+boff;
+        if((k>=0) && (k<n_bns_pri)) ari.addCharge(chbns[j],k);
+       } 
+      }
+     }
+    } // end for(int i=0; i<narsts; i++)
+    for(int i=0; i<narsts; i++)
+    {
+     ResetInterval ari = (ResetInterval) actrsts.get(i);
+     int rbc = ari.getBunchCrossing();
+     double strtri = rbc*bunch_interval; 
+     double endri =  (rbc+reset_int)*bunch_interval;
+     List<NoiseHit> no_hts = ari.getNoiseHits();
+     nnhts = no_hts.size();
+     int[] nht_bns = null;
+     double tf = 0.;
+     if(nnhts > 0)
+     {
+      nht_bns=new int[nnhts];
+      for(int j=0; j<nnhts; j++)
+      {
+       tf = no_hts.get(j).getTime()-strtri;
+       nht_bns[j]=(int) Math.floor(tf/dtf);
+      }
+     } 
+     boolean fired = false;
+     int act_thr = (int) (pixel_threshold * adc_scale + noise_level * rnd.nextGaussian());
+     int asig = 0;
+     int[] chacc = ari.getCharge();
+     for(int j=0; j<chacc.length; j++)
+     {
+      if(nnhts > 0)
+      {
+       for(int k=0; k<nnhts; k++)
+       {
+        if(j==nht_bns[k])
+        {
+         tf = strtri + j*dtf;
+         if(buf<n_buffers)
+         {
+          int tstm = (int) Math.floor(tf/clock_period);
+          tstmps[buf]=tstm;
+          fri[buf] = ari;
+          buf++;
+         }  
+        } 
+       }
+      }
+      asig+=chacc[j];
+      if(!fired && (asig >= act_thr))
+      {
+       fired=true;
+       tf = strtri + j*dtf+dtf*((double)(act_thr-asig+chacc[j])/(double)chacc[j]);
+       if(buf<n_buffers)
+       {
+        int tstm = (int) Math.floor(tf/clock_period);
+//        System.out.println("tf= "+tf+" tstm="+tstm+" asig="+asig+" chacc[j]="+chacc[j]);
+        tstmps[buf]=tstm;
+        fri[buf]=ari;
+        buf++;
+       }  
+      }
+     } // end for(int j=0; j<chacc.length; j++)
+     double sig = (double) asig + noise_level * rnd.nextGaussian(); 
+     if(buf > 0) aadc[buf-1] = (int) (Math.floor(sig/adc_scale));
+    } // for(int i=0; i<narsts; i++)
+    }
+    for(int i=0; i<buf; i++)
+    {
+     int tstm = tstmps[i];
+     ResetInterval ari = fri[i];
+     if((tstm>=acc_strt) && (tstm <= acc_end))
+     {
+      short[] adc = new short[3];
+      adc[0]=(short) aadc[i];
+      adc[1]=(short) (tstm>>16);
+      adc[2]=(short) (tstm & 0x7fff);
+      long cellid = sens.getCellID(prow,pcol);
+      RawTrackerHit rhit = new BaseRawTrackerHit(bc,cellid,adc,ari.getSimHits(),sens.getParent());
+      sens.addRawHit(rhit);
+     } 
+    }
+   } // end for(ActivePixel pix:sens_pixs)
+  } // end function processSensor(IPixilatedSensor sens, int bc)
+
+
+  private void generateNoise(IPixilatedSensor sens)
+  {
+   int snr = sens.getNRows();
+   int snc = sens.getNColumns();
+   int np = snc*snr;
+   double thr = pixel_threshold * adc_scale;
+   double ttnf = thr/noise_level;
+   double abtpr = erprob.getProbability(ttnf);
+   int nnhits = (int) (np * bandwidth * train_duration * abtpr);
+   System.out.println("Generating "+nnhits+" noise hits for sensor with "+np+" pixels"); 
+   for(int hn = 0; hn < nnhits; hn++)
+   {
+    double nht = train_duration * rnd.nextDouble();
+    short nhr = (short) Math.floor(snr * rnd.nextDouble());
+    short nhc = (short) Math.floor(snc * rnd.nextDouble());
+    int npid = ActivePixel.id(nhr,nhc);
+    boolean newap = true;
+    List<ActivePixel> pixels = sens.getActivePixels();
+    for(ActivePixel ap:pixels)
+    {
+     if(ap.ID == npid)
+     {
+      newap = false;
+      ap.addNoiseHit(new NoiseHit(nht));
+     }
+    }
+    if(newap)
+    {
+     ActivePixel nap = new ActivePixel();
+     nap.row = nhr;
+     nap.column = nhc;
+     nap.addNoiseHit(new NoiseHit(nht));
+     sens.addActivePixel(nap);
+    }
+   }   
+  }
+
+  private class ResetInterval
+  {
+   int BC=0;
+   int[] charge = null;
+   List<NoiseHit> noise_hits = new ArrayList<NoiseHit>();
+   List<SimTrackerHit> simhits = new ArrayList<SimTrackerHit>();
+
+   public ResetInterval(int bc, int nbins)
+   {
+    BC = bc;
+    charge = new int[nbins];
+    for(int i=0; i<nbins; i++) charge[i]=0;
+   }
+
+   public void addCharge(short ch, int ind)
+   {
+    if((ind >=0) && (ind<charge.length)) charge[ind]+=ch;
+   }
+
+   public void addNoiseHit(NoiseHit nh)
+   {
+    noise_hits.add(nh);
+   }
+
+   public void addSimHit(SimTrackerHit sh)
+   {
+    if(!simhits.contains(sh)) simhits.add(sh);
+   }
+
+   public List<SimTrackerHit> getSimHits() { return simhits; }
+ 
+   public List<NoiseHit> getNoiseHits() { return noise_hits; }
+
+   public int[] getCharge() { return charge; }
+
+   public int getBunchCrossing() { return BC; }
+   
+  }  
+ 
+}
CVSspam 0.2.8