public override StreamStatusBlock ConvertDataBuffer(int bytecount) { StreamStatusBlock ssb = null; // NEXT: detect end of stream and build ssb // URGENT: this rework might mess end up the stream end check, and could blow here // The analyzer code uses the list lengths to know when to stop counting neutrons. The buffer may be n, but the last neutron is in n - k. if (channels.Length < neutronEventArray.Count) { neutronEventArray.RemoveRange(channels.Length - 1, neutronEventArray.Count - channels.Length); } else if (channels.Length > neutronEventArray.Count) { neutronEventArray.AddRange(new uint[channels.Length - neutronEventArray.Count]); } if (times.Length < timeArray.Count) { timeArray.RemoveRange(times.Length - 1, timeArray.Count - times.Length); } else if (times.Length > timeArray.Count) { timeArray.AddRange(new ulong[channels.Length - neutronEventArray.Count]); } //Array.Resize(ref neutronEventArray, channels.Length); //Array.Resize(ref timeArray, times.Length); string msg = PrepRawStreams(num: (ulong)bytecount, combineDuplicateHits: mergeDuplicatesTimeChannelHits); return(ssb); }
/// <summary> /// Tailored only for LMMM/NPOD! /// this looks at the status block content and sets the cycle status; Rates, Assay Cancelled, Status, are the three I've seen in data so far /// </summary> /// <param name="sb"></param> /// <param name="text"></param> /// <param name="stat"></param> public void ParseStatusBlock(StreamStatusBlock sb, Cycle cycle) { //'Assay Cancelled. ' == Cancelled, // Completed == status block found at end of file or at cycle finish time // 'Rates = 0,0,0,0,1,6,0,54,0,0,0,0,1071,546,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0' == Rates (see e.g. GDND/2010_10_20_155930_0.ncd) CycleDAQStatus stat = CycleDAQStatus.UnspecifiedTruncation; string text = ""; if (sb != null) { sb.Decode(State.rawDataBuff); if (!String.IsNullOrEmpty(sb.msg)) { if (text.StartsWith("Assay Cancelled.")) // dev note: string constants that should live in the LMMMLingo class. { stat = CycleDAQStatus.Cancelled; } else if (text.StartsWith("Rates =")) { stat = CycleDAQStatus.Rates; } else { stat = CycleDAQStatus.Completed; } } else { stat = CycleDAQStatus.UnspecifiedTruncation; } } cycle.DaqStatus = stat; cycle.Message = text; }
/// <summary> /// Convert a buffer of unprocessed tuples to time and hit streams, then send the converted streams to the counting task /// </summary> /// <param name="buffer"></param> /// <param name="idx"></param> /// <param name="bytecount"></param> /// <returns>A StatusBlock is returned at the end of a cycle File or DAQ</returns> public StreamStatusBlock PassBufferToTheCounters(byte[] buffer, int idx, int bytecount) { // dev note: if reading from socket stream, consider if socket return is larger than max buffer in here, what to do? // dev note: this buff copy is pointless in the single-threaded model Buffer.BlockCopy(buffer, idx, State.rawDataBuff, 0, bytecount); // copy from the asynch socket caller StreamStatusBlock endofdata = null; if (state.NumValuesParsed >= (State.maxValuesInBuffer - (bytecount / 8))) // if limit will reach with this new data buffer of size bytecount, then must startnewbuffer here, AND must pass the "nearly full" stream buffers to the counters { logger.TraceEvent(LogLevels.Verbose, 644, state.NumValuesParsed + " >= " + (State.maxValuesInBuffer - (bytecount / 8)) + " starting new internal buffer"); if (State.usingStreamRawAnalysis) { State.Sup.HandleAnArrayOfNeutronEvents(State.timeArray, State.neutronEventArray, (int)state.NumValuesParsed); } StartNewBuffer(); // resets stream IO buffer indexing and moves accumulated data to cycle logger.Flush(); } endofdata = State.ConvertDataBuffer(bytecount); if (NumProcessedRawDataBuffers > 0) { logger.TraceEvent(LogLevels.Verbose, 222, "{0}: Completed with {1} events", NumProcessedRawDataBuffers, state.NumValuesParsed); } if (State.usingStreamRawAnalysis && (endofdata != null)) { State.Sup.HandleAnArrayOfNeutronEvents(State.timeArray, State.neutronEventArray, (int)State.NumValuesParsed); } // logger.TraceEvent(LogLevels.Verbose, 224, "{0}: Worked {1} bytes", NumProcessedRawDataBuffers, bytecount); return(endofdata); }
public override StreamStatusBlock ConvertDataBuffer(int bytecount) { StreamStatusBlock ssb = null; // NEXT: detect end of stream and build ssb string msg = PrepRawStreams((ulong)bytecount, chnbytes); return(ssb); }
/// <summary> /// file-based buffer processing /// </summary> /// <param name="bytecount"></param> /// <returns></returns> public StreamStatusBlock PassBufferToTheCounters(int bytecount) { StreamStatusBlock endofdata = null; logger.TraceEvent(LogLevels.Verbose, 220, "{0}: Starting data conversion on file stream. . .", NumProcessedRawDataBuffers); endofdata = state.ConvertDataBuffer(bytecount); if (NumProcessedRawDataBuffers > 0) { logger.TraceEvent(LogLevels.Verbose, 222, "{0}: Completed with {1} events", NumProcessedRawDataBuffers, state.NumValuesParsed); } if (State.usingStreamRawAnalysis) // process by data blocks, e.g. buffered transfer underlying a stream. { State.Sup.HandleAnArrayOfNeutronEvents(State.timeArray, State.neutronEventArray, (int)state.NumValuesParsed); } // logger.TraceEvent(LogLevels.Verbose, 224, "{0}: Worked {1} bytes", NumProcessedRawDataBuffers, bytecount);//, state.stopWatch.ElapsedTicks); return(endofdata); }
private StreamStatusBlock ExtractStatusBlock(ref int index, int bytecount) { int statusindex = index + 4; UInt32[] messagelength = new UInt32[1]; Buffer.BlockCopy(rawDataBuff, index, messagelength, 0, 4); // get length bytes uint len = messagelength[0]; len = ((0x000000FF) & (len >> 24) //shift byte 1 to byte 4 and mask it | (0x0000FF00) & (len >> 8) //shift byte 2 to byte 3 and mask it | (0x00FF0000) & (len << 8) //shift byte 3 to byte 2 and mask it | (0xFF000000) & (len << 24)); //shift byte 4 to byte 1 and mask it StreamStatusBlock res = new StreamStatusBlock(); // this sets up the SB for decoding later res.msglen = (int)len; res.index = statusindex; index = (int)bytecount; // set index to length of buffer, so loop will exit. return(res); }
public void PlaceStatusTextOnCurrentCycle(StreamStatusBlock sb) { ParseStatusBlock(sb, Cycle); }
// non-null StatusBlock returned when end of data encountered during processing public override StreamStatusBlock ConvertDataBuffer(int bytecount) { UInt32[] uintHolder1 = new UInt32[1]; UInt32[] uintHolder2 = new UInt32[1]; int index = 0; //index into the active buffer of bytes from the last read StreamStatusBlock res = null; // logger.TraceEvent(LogLevels.Verbose, 221, "{0}: Processing {1} bytes", numbuff, bytecount); /* * case 0: UInt32 /= 0 is time, then next uint is channel hits * case 1: UInt32 == 0 means end of data file, next uint is length of subsequent terminating ASCII message * case 2: UInt32 == 0 means veto, following uint is skipped * case 3: if gen2 flag is set we do an expensive examination for "trigger" because the null byte tests for gen3 do not work * */ while (index < bytecount) { //if ((index % (16 * 8192)) == 0) // dev note: could, maybe even should, flush log here based on some configurable modulus //{ // NC.App.Loggers.Flush(); //} // dev note: review this code to move all un-needed steps, even copies Buffer.BlockCopy(rawDataBuff, index, uintHolder1, 0, 4); index += 4; Buffer.BlockCopy(rawDataBuff, index, uintHolder2, 0, 4); //get time of event from array index += 4; if (uintHolder1[0] == 0) { if (uintHolder2[0] == 0) // 8 null bytes means end of the cycle { res = ExtractStatusBlock(ref index, bytecount); //logger.TraceEvent(LogLevels.Verbose, 8888, "{0}: END-OF-CYCLE BLOCK!", state.NumValuesParsed); } else // it is a veto, and TDB set flag to find its pair { // dev note: do something with the veto time in uintHolder2[0] //logger.TraceEvent(LogLevels.Info, 8888, "{0}: Veto!", state.NumValuesParsed); } } else if (includingGen2 && // unsure of best way to find these older files, so I look for the word "triggers", for a three step logical check ((uintHolder1[0] == 0x67697274) && (uintHolder2[0] == 0x73726567))) // girt sreg { res = new StreamStatusBlock(); res.index = index - 8; uint messagelength = (uint)(bytecount - res.index); res.msglen = (int)((0x000000FF) & (messagelength >> 24) //shift byte 1 to byte 4 and mask it | (0x0000FF00) & (messagelength >> 8) //shift byte 2 to byte 3 and mask it | (0x00FF0000) & (messagelength << 8) //shift byte 3 to byte 2 and mask it | (0xFF000000) & (messagelength << 24)); //shift byte 4 to byte 1 and mask it logger.TraceEvent(LogLevels.Verbose, 219, "todo gen2: for gen 2 we improperly parsed the preceding 8 bytes 0x0002 0x000+ or 0x0002 0x000-, so need to back it out of the counts, and moreover there may be other end patterns I haven't seen yet for gen 2 files."); } else //should have a valid pair of UInt32s. Swap byte order for first value, and read and swap bytes for next value. { UInt32 aValue, swapped; //swap endianness of neutron event, already parsed from array... aValue = uintHolder1[0]; swapped = ((0x000000FF) & (aValue >> 24) //shift byte 1 to byte 4 and mask it | (0x0000FF00) & (aValue >> 8) //shift byte 2 to byte 3 and mask it | (0x00FF0000) & (aValue << 8) //shift byte 3 to byte 2 and mask it | (0xFF000000) & (aValue << 24)); //shift byte 4 to byte 1 and mask it neutronEventArray[(int)NumValuesParsed] = swapped; for (short i = 0; i < NC.ChannelCount; i++) // count channel hits here { if ((swapped & chnmask[i]) != 0) { hitsPerChn[i]++; NumTotalsEncountered++; } } //swap endianness of time of event, note: times are cumulative ticks, not deltas aValue = uintHolder2[0]; swapped = ((0x000000FF) & (aValue >> 24) //shift byte 1 to byte 4 and mask it | (0x0000FF00) & (aValue >> 8) //shift byte 2 to byte 3 and mask it | (0x00FF0000) & (aValue << 8) //shift byte 3 to byte 2 and mask it | (0xFF000000) & (aValue << 24)); //shift byte 4 to byte 1 and mask it if (swapped < lastValue) //then we have wrapped around, so increment the wraparoundoffset by 33 bits { wraparoundOffset += 0x100000000; // max clock } lastValue = swapped; //store the time in the array, adding the wraparoundOffset in case the UInt32 has overflowed (which it will every 429.4967... seconds) timeArray[(int)NumValuesParsed] = wraparoundOffset + ((UInt64)swapped); if (!usingStreamRawAnalysis) // drop them in, one by one { Sup.HandleANeutronEvent(timeArray[(int)NumValuesParsed], neutronEventArray[(int)NumValuesParsed]); } NumValuesParsed++; } } return(res); }
/// <summary> /// Tailored only for LMMM/NPOD! /// this looks at the status block content and sets the cycle status; Rates, Assay Cancelled, Status, are the three I've seen in data so far /// </summary> /// <param name="sb"></param> /// <param name="text"></param> /// <param name="stat"></param> public void ParseStatusBlock(StreamStatusBlock sb, Cycle cycle) { //'Assay Cancelled. ' == Cancelled, // Completed == status block found at end of file or at cycle finish time // 'Rates = 0,0,0,0,1,6,0,54,0,0,0,0,1071,546,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0' == Rates (see e.g. GDND/2010_10_20_155930_0.ncd) CycleDAQStatus stat = CycleDAQStatus.UnspecifiedTruncation; string text = ""; if (sb != null) { sb.Decode(State.rawDataBuff); if (!String.IsNullOrEmpty(sb.msg)) // dev note: this needs expansion to support other data stream end conditions, not just the orignal LMMM { if (text.StartsWith("Assay Cancelled.")) // dev note: string constants that should live in the LMMMLingo class. stat = CycleDAQStatus.Cancelled; else if (text.StartsWith("Rates =")) stat = CycleDAQStatus.Rates; else stat = CycleDAQStatus.Completed; } else { stat = CycleDAQStatus.UnspecifiedTruncation; } } cycle.DaqStatus = stat; cycle.Message = text; }
private StreamStatusBlock ExtractStatusBlock(ref int index, int bytecount) { int statusindex = index + 4; UInt32[] messagelength = new UInt32[1]; Buffer.BlockCopy(rawDataBuff, index, messagelength, 0, 4); // get length bytes uint len = messagelength[0]; len = ((0x000000FF) & (len >> 24) //shift byte 1 to byte 4 and mask it | (0x0000FF00) & (len >> 8) //shift byte 2 to byte 3 and mask it | (0x00FF0000) & (len << 8) //shift byte 3 to byte 2 and mask it | (0xFF000000) & (len << 24)); //shift byte 4 to byte 1 and mask it StreamStatusBlock res = new StreamStatusBlock(); // this sets up the SB for decoding later res.msglen = (int)len; res.index = statusindex; index = (int)bytecount; // set index to length of buffer, so loop will exit. return res; }
// non-null StatusBlock returned when end of data encountered during processing public override StreamStatusBlock ConvertDataBuffer(int bytecount) { UInt32[] uintHolder1 = new UInt32[1]; UInt32[] uintHolder2 = new UInt32[1]; int index = 0; //index into the active buffer of bytes from the last read StreamStatusBlock res = null; // logger.TraceEvent(LogLevels.Verbose, 221, "{0}: Processing {1} bytes", numbuff, bytecount); /* * case 0: UInt32 /= 0 is time, then next uint is channel hits * case 1: UInt32 == 0 means end of data file, next uint is length of subsequent terminating ASCII message * case 2: UInt32 == 0 means veto, following uint is skipped * case 3: if gen2 flag is set we do an expensive examination for "trigger" because the null byte tests for gen3 do not work * */ while (index < bytecount) { //if ((index % (16 * 8192)) == 0) // dev note: could, maybe even should, flush log here based on some configurable modulus //{ // NC.App.Loggers.Flush(); //} // dev note: review this code to remove all un-needed steps, even copies Buffer.BlockCopy(rawDataBuff, index, uintHolder1, 0, 4); index += 4; Buffer.BlockCopy(rawDataBuff, index, uintHolder2, 0, 4); //get time of event from array index += 4; if (uintHolder1[0] == 0) { if (uintHolder2[0] == 0) // 8 null bytes means end of the cycle { res = ExtractStatusBlock(ref index, bytecount); //logger.TraceEvent(LogLevels.Verbose, 8888, "{0}: END-OF-CYCLE BLOCK!", state.NumValuesParsed); } else // it is a veto, and TDB set flag to find its pair { // dev note: do something with the veto time in uintHolder2[0] //logger.TraceEvent(LogLevels.Info, 8888, "{0}: Veto!", state.NumValuesParsed); } } else if (includingGen2 && // unsure of best way to find these older files, so I look for the word "triggers", for a three step logical check ((uintHolder1[0] == 0x67697274) && (uintHolder2[0] == 0x73726567))) // girt sreg { res = new StreamStatusBlock(); res.index = index - 8; uint messagelength = (uint)(bytecount - res.index); res.msglen = (int)((0x000000FF) & (messagelength >> 24) //shift byte 1 to byte 4 and mask it | (0x0000FF00) & (messagelength >> 8) //shift byte 2 to byte 3 and mask it | (0x00FF0000) & (messagelength << 8) //shift byte 3 to byte 2 and mask it | (0xFF000000) & (messagelength << 24)); //shift byte 4 to byte 1 and mask it logger.TraceEvent(LogLevels.Verbose, 219, "todo gen2: for gen 2 we improperly parsed the preceding 8 bytes 0x0002 0x000+ or 0x0002 0x000-, so need to back it out of the counts, and moreover there may be other end patterns I haven't seen yet for gen 2 files."); } else //should have a valid pair of UInt32s. Swap byte order for first value, and read and swap bytes for next value. { UInt32 aValue, swapped; //swap endianness of neutron event, already parsed from array... aValue = uintHolder1[0]; swapped = ((0x000000FF) & (aValue >> 24) //shift byte 1 to byte 4 and mask it | (0x0000FF00) & (aValue >> 8) //shift byte 2 to byte 3 and mask it | (0x00FF0000) & (aValue << 8) //shift byte 3 to byte 2 and mask it | (0xFF000000) & (aValue << 24)); //shift byte 4 to byte 1 and mask it neutronEventArray[(int)NumValuesParsed] = swapped; for (short i = 0; i < NC.ChannelCount; i++) // count channel hits here { if ((swapped & chnmask[i]) != 0) { hitsPerChn[i]++; NumTotalsEncountered++; } } //swap endianness of time of event, note: times are cumulative ticks, not deltas aValue = uintHolder2[0]; swapped = ((0x000000FF) & (aValue >> 24) //shift byte 1 to byte 4 and mask it | (0x0000FF00) & (aValue >> 8) //shift byte 2 to byte 3 and mask it | (0x00FF0000) & (aValue << 8) //shift byte 3 to byte 2 and mask it | (0xFF000000) & (aValue << 24)); //shift byte 4 to byte 1 and mask it if (swapped < lastValue) //then we have wrapped around, so increment the wraparoundoffset by 33 bits { wraparoundOffset += 0x100000000; // max clock } lastValue = swapped; //store the time in the array, adding the wraparoundOffset in case the UInt32 has overflowed (which it will every 429.4967... seconds) timeArray[(int)NumValuesParsed] = wraparoundOffset + ((UInt64)swapped); if (!usingStreamRawAnalysis) // drop them in, one by one Sup.HandleANeutronEvent(timeArray[(int)NumValuesParsed], neutronEventArray[(int)NumValuesParsed]); NumValuesParsed++; } } return res; }