11package org .jlab .detector .serial ;
22
3+ import java .util .Arrays ;
4+ import java .util .List ;
5+ import java .util .ListIterator ;
36import java .util .TreeMap ;
47import java .util .TreeSet ;
8+ import java .util .stream .Collectors ;
59import org .jlab .detector .calib .utils .ConstantsManager ;
610import org .jlab .detector .decode .CLASDecoder ;
11+ import org .jlab .detector .helicity .HelicityBit ;
712import org .jlab .detector .helicity .HelicitySequence ;
13+ import org .jlab .detector .helicity .HelicitySequenceDelayed ;
814import org .jlab .detector .helicity .HelicityState ;
15+ import org .jlab .detector .scalers .DaqScalers ;
916import org .jlab .detector .scalers .DaqScalersSequence ;
1017import org .jlab .jnp .hipo4 .data .Bank ;
1118import org .jlab .jnp .hipo4 .data .Event ;
19+ import org .jlab .jnp .hipo4 .data .Schema ;
1220import org .jlab .jnp .hipo4 .data .SchemaFactory ;
1321import org .jlab .jnp .hipo4 .io .HipoWriterSorted ;
1422
1927public class SerialHoncho {
2028
2129 static final String [] TAG1BANKS = {"RUN::scaler" ,"HEL::scaler" ,"RAW::scaler" ,"RAW::epics" ,"HEL::flip" ,"COAT::config" };
22-
2330 SchemaFactory schema ;
24- Bank [] tag1banks ;
25- Bank runConfig ;
26- Bank helicityAdc ;
31+ Schema [] tag1banks ;
32+ Schema runConfig ;
33+ Schema recEvent ;
34+ Schema helScaler ;
35+ Schema helicityAdc ;
2736 ConstantsManager conman ;
28- TreeMap <Integer ,Integer > eventUnix ;
29- TreeSet <HelicityState > helicities ;
30- DaqScalersSequence scalers ;
31-
37+ volatile TreeMap <Integer ,Integer > eventUnix ;
38+ volatile HelicitySequence helicitySequence ;
39+ volatile TreeSet <HelicityState > helicities ;
40+ volatile DaqScalersSequence scalers ;
41+ int run = 0 ;
42+
3243 public SerialHoncho (SchemaFactory schema ) {
3344 this .schema = schema ;
3445 conman = new ConstantsManager ();
3546 conman .init ("/runcontrol/hwp" ,"/runcontrol/helicity" );
36- runConfig = new Bank (schema .getSchema ("RUN::config" ));
37- helicityAdc = new Bank (schema .getSchema ("HEL::adc" ));
38- helicities = new TreeSet <>();
47+ runConfig = schema .getSchema ("RUN::config" );
48+ recEvent = schema .getSchema ("REC::Event" );
49+ helicityAdc = schema .getSchema ("HEL::adc" );
50+ helScaler = schema .getSchema ("HEL::scaler" );
3951 scalers = new DaqScalersSequence (schema );
52+ helicities = new TreeSet <>();
4053 eventUnix = new TreeMap <>();
41- tag1banks = new Bank [TAG1BANKS .length ];
54+ tag1banks = new Schema [TAG1BANKS .length ];
4255 for (int i =0 ; i <tag1banks .length ; ++i )
43- tag1banks [i ] = new Bank ( schema .getSchema (TAG1BANKS [i ]) );
56+ tag1banks [i ] = schema .getSchema (TAG1BANKS [i ]);
4457 }
4558
46- public synchronized Event read (Event event ) {
47- scalers .add (event );
48- event .read (runConfig );
49- event .read (helicityAdc );
50- if (runConfig .getRows () > 0 ) {
51- int unix = runConfig .getInt ("unixtime" ,0 );
52- int evno = runConfig .getInt ("event" ,0 );
53- if (unix > 0 && evno > 0 ) eventUnix .put (evno , unix );
59+ /**
60+ * Register an event's serial data and return a (possibly empty) tag-1 event.
61+ * @param event
62+ * @return new tag-1 event
63+ */
64+ public Event read (Event event ) {
65+ Bank cfg = new Bank (runConfig );
66+ Bank hel = new Bank (helicityAdc );
67+ event .read (cfg );
68+ event .read (hel );
69+ read (event , cfg , hel );
70+ return CLASDecoder .createTaggedEvent (event , cfg , createTaggedBanks (tag1banks ));
71+ }
72+
73+ /**
74+ * Modify a physics event's helicity and charge information.
75+ * @param event
76+ */
77+ public void process (Event event ) {
78+ Bank cfg = new Bank (runConfig );
79+ Bank evt = new Bank (recEvent );
80+ event .read (cfg );
81+ event .read (evt );
82+ if (cfg .getRows () > 0 ) {
83+ processEventUnix (event , cfg );
84+ if (evt .getRows () > 0 ) {
85+ event .remove (evt .getSchema ());
86+ processHelicity (event , cfg , evt );
87+ processScalers (cfg , evt );
88+ event .write (evt );
89+ }
5490 }
55- helicities .add (HelicityState .createFromFadcBank (helicityAdc , runConfig , conman ));
56- return CLASDecoder .createTaggedEvent (event , runConfig , tag1banks );
5791 }
5892
59- public void finish (HipoWriterSorted writer ) {
60- writer .addEvent (getUnixEvent (runConfig ),1 );
61- HelicitySequence .writeFlips (schema , writer , helicities );
93+ /**
94+ * Add helicity and unixtime sequence banks.
95+ * @param writer
96+ */
97+ public void closure (HipoWriterSorted writer ) {
98+ Bank cfg = new Bank (runConfig , 1 );
99+ cfg .putInt ("run" ,0 ,run );
100+ writer .addEvent (getUnixEvent (cfg ),1 );
101+ helicitySequence .writeFlips (writer , 1 );
62102 }
63103
104+ /**
105+ * Zero all the sequences.
106+ */
64107 public void clear () {
65- while (helicities .size () > 100 ) helicities .pollFirst ();
66- scalers .clear (100 );
108+ eventUnix .clear ();
109+ helicities .clear ();
110+ scalers .clear ();
111+ helicitySequence = null ;
112+ }
113+
114+ public TreeSet <HelicityState > getHelicities () {
115+ return helicities ;
116+ }
117+
118+ public DaqScalersSequence getScalers () {
119+ return scalers ;
120+ }
121+
122+ public ConstantsManager getConstantsManager () {
123+ return conman ;
124+ }
125+
126+ public SchemaFactory getSchemaFactory () {
127+ return schema ;
128+ }
129+
130+ public void updateHelicitySequence () {
131+ helicitySequence = new HelicitySequenceDelayed (
132+ conman .getConstants (run , "/runcontrol/helicity" ).getIntValue ("delay" ,0 ,0 ,0 ));
133+ helicitySequence .addStream (helicities );
67134 }
68135
69- Event getUnixEvent (Bank config ) {
136+ void read (Event event , Bank runConfig , Bank helicityAdc ) {
137+ scalers .add (event );
138+ helicities .add (HelicityState .createFromFadcBank (helicityAdc , runConfig , conman ));
139+ prune ();
140+ if (runConfig .getRows () > 0 ) {
141+ int r = runConfig .getInt ("run" , 0 );
142+ if (r > 0 ) {
143+ if (r != run ) {
144+ clear ();
145+ run = r ;
146+ }
147+ }
148+ if (run > 0 ) {
149+ int unix = runConfig .getInt ("unixtime" ,0 );
150+ int evno = runConfig .getInt ("event" ,0 );
151+ if (unix > 0 && evno > 0 ) eventUnix .put (evno , unix );
152+ }
153+ }
154+ }
155+
156+ void prune () {
157+ // Estimated size of HelicityState is ~22 bytes.
158+ // 1 million states, ~22 MB, 1 minute at 10 kHz trigger.
159+ if (helicities .size () > 2e6 )
160+ pruneHelicities (helicities , (int )1e6 );
161+ // Assuming scalers are 50x larger.
162+ // 10,000 events is 2.7 hours at 1 Hz.
163+ if (scalers .size () > 2e4 )
164+ scalers .clear ((int )1e4 );
165+ }
166+
167+ Event getUnixEvent (Bank runConfig ) {
70168 Bank unix = new Bank (schema .getSchema ("RUN::unix" ));
71169 unix .setRows (eventUnix .size ());
72170 int row = 0 ;
@@ -76,24 +174,69 @@ Event getUnixEvent(Bank config) {
76174 row ++;
77175 }
78176 Event e = new Event ();
79- e .write (config );
177+ e .write (runConfig );
80178 e .write (unix );
81179 return e ;
82180 }
83181
84- public DaqScalersSequence getScalers () {
85- return scalers ;
182+ int getUnixTime (Bank runConfig ) {
183+ if (runConfig .getRows () < 1 ) {
184+ Integer key = eventUnix .floorKey (runConfig .getInt ("event" ,0 ));
185+ if (key != null ) {
186+ Integer unix = eventUnix .get (key );
187+ if (unix != null ) return unix ;
188+ }
189+ }
190+ return 0 ;
86191 }
87-
88- public TreeSet <HelicityState > getHelicities () {
89- return helicities ;
192+
193+ void processEventUnix (Event event , Bank runConfig ) {
194+ int ut = getUnixTime (runConfig );
195+ event .remove (runConfig .getSchema ());
196+ runConfig .putInt ("unixtime" , 0 , ut );
197+ event .write (runConfig );
90198 }
91199
92- public ConstantsManager getConstantsManager () {
93- return conman ;
200+ void processScalers (Bank runConfig , Bank recEvent ) {
201+ DaqScalers ds = scalers .get (runConfig .getLong ("timestamp" , 0 ));
202+ if (ds != null ) {
203+ recEvent .putFloat ("beamCharge" ,0 , (float ) ds .dsc2 .getBeamChargeGated ());
204+ recEvent .putDouble ("liveTime" ,0 ,ds .dsc2 .getLivetime ());
205+ }
94206 }
95207
96- public SchemaFactory getSchemaFactory () {
97- return schema ;
208+ void processHelicity (Event event , Bank runConfig , Bank recEvent ) {
209+ HelicityBit hb = helicitySequence .search (runConfig .getLong ("timestamp" , 0 ));
210+ HelicityBit hbraw = helicitySequence .getHalfWavePlate () ? HelicityBit .getFlipped (hb ) : hb ;
211+ recEvent .putByte ("helicity" ,0 ,hb .value ());
212+ recEvent .putByte ("helicityRaw" ,0 ,hbraw .value ());
213+ Bank scaler = new Bank (helScaler );
214+ event .read (scaler );
215+ if (scaler .getRows ()>0 ) {
216+ event .remove (helScaler );
217+ SerialUtil .assignScalerHelicity (runConfig .getLong ("timestamp" ,0 ), scaler , helicitySequence );
218+ event .write (scaler );
219+ }
98220 }
221+
222+ static void pruneHelicities (TreeSet <HelicityState > helicities , int depth ) {
223+ HelicityState prev = null ;
224+ ListIterator <HelicityState > iter = (ListIterator )helicities .iterator ();
225+ final int size = helicities .size ();
226+ while (iter .hasNext () && iter .nextIndex () < size -depth ) {
227+ HelicityState next = iter .next ();
228+ if (prev != null && prev == next )
229+ helicities .remove (next );
230+ }
231+ }
232+
233+ static Bank [] createTaggedBanks (Schema [] tag1banks ) {
234+ List <Bank > lbank = Arrays .asList (tag1banks ).stream ().map (s -> new Bank (s )).collect (Collectors .toList ());
235+ ListIterator <Bank > ibank = lbank .listIterator ();
236+ Bank [] banks = new Bank [lbank .size ()];
237+ while (ibank .hasNext ())
238+ banks [ibank .nextIndex ()] = ibank .next ();
239+ return banks ;
240+ }
241+
99242}
0 commit comments