/// <summary> /// ResetForConcatenation() clears metadata for a new experiment, /// but preserves present histogram array so subsequent data can be added. /// </summary> public void ResetForConcatenation() { int i; RossiAlphaCircularNeutronEvent thisEvent, nextEvent; #if USE_SPINTIME spinTimeTotal = 0; spinTimeReady = false; #endif //break the circular references, so garbage collector will do its thing nextEvent = theEventCircularLinkedList; while (nextEvent != null) { thisEvent = nextEvent; nextEvent = thisEvent.next; thisEvent.next = null; } //create the circular linked list theEventCircularLinkedList = new RossiAlphaCircularNeutronEvent(0); //create the first element in the list startOfList = theEventCircularLinkedList; //set the head of the list to this first element endOfList = theEventCircularLinkedList; //set the tail of thelist to this first element for (i = 1; i < RawAnalysisProperties.circularListBlockIncrement; i++) //as a starter, put RawAnalysisProperties.circularListBlockIncrement structures in the list { endOfList.next = new RossiAlphaCircularNeutronEvent(i); //create the next new struct at the end of the tail endOfList = endOfList.next; //move the tail to this new stuct } numObjectsInCircularLinkedList = RawAnalysisProperties.circularListBlockIncrement; endOfList.next = startOfList; //close the loop, connecting the tail back to the head endOfList = startOfList; //set the head and tail to the first empty structure numCircuits = 0; isReadyToAnalyze = true; }
public RossiAlphaCircularNeutronEvent(int identifyingNumber) { //initialize the linked-list information next = null; //store the identifier for this structure serialNumber = identifyingNumber; }
public RossiAlphaCircularStackAnalysis(UInt64 gateWidth) { int i; isReadyToAnalyze = false; #if USE_SPINTIME spinTimeTotal = 0; spinTimeStart = 0; spinTimeReady = false; #endif rossiAlphaGateWidth = gateWidth; rossiAlphaWindowWidth = ((UInt64)(RawAnalysisProperties.numRAGatesPerWindow)) * gateWidth; totalRossiAlphaAnalysisTime = 0; for (i = 0; i < RawAnalysisProperties.numRAGatesPerWindow; i++) { neutronsPerRossiAlphaGate[i] = 0; } //initialize the event inputs inputEventTime = new UInt64[RawAnalysisProperties.maxEventsPerBlock]; inputEventNeutrons = new UInt32[RawAnalysisProperties.maxEventsPerBlock]; inputEventNumNeutrons = new UInt32[RawAnalysisProperties.maxEventsPerBlock]; numEventsThisBlock = 0; //create the circular linked list theEventCircularLinkedList = new RossiAlphaCircularNeutronEvent(0); //create the first element in the list startOfList = theEventCircularLinkedList; //set the head of the list to this first element endOfList = theEventCircularLinkedList; //set the tail of thelist to this first element for (i = 1; i < RawAnalysisProperties.circularListBlockIncrement; i++) //as a starter, put RawAnalysisProperties.circularListBlockIncrement structures in the list { endOfList.next = new RossiAlphaCircularNeutronEvent(i); //create the next new struct at the end of the tail endOfList = endOfList.next; //move the tail to this new stuct } numObjectsInCircularLinkedList = RawAnalysisProperties.circularListBlockIncrement; endOfList.next = startOfList; //close the loop, connecting the tail back to the head endOfList = startOfList; //set the head and tail to the first empty structure numCircuits = 0; //Set Up the RAC BackgroundWorker keepRunning = true; isReadyToAnalyze = false; RACWorker = new BackgroundWorker(); RACWorker.WorkerSupportsCancellation = false; //it either processes a neutron event, or it doesn't. RACWorker.DoWork += new DoWorkEventHandler(RACWorker_DoWork); RACWorker.RunWorkerAsync(); //pause until the RAcWorker is working while (RACWorker.IsBusy == false) { Thread.Sleep(1); } }
/// <summary> /// ResetCompletely() clears results and sets metadata for new data, /// such as running a new experiment or reading a new NCD file /// </summary> public void ResetCompletely(bool closeCounters) { int i; RossiAlphaCircularNeutronEvent thisEvent, nextEvent; #if USE_SPINTIME spinTimeTotal = 0; spinTimeReady = false; #endif for (i = 0; i < RawAnalysisProperties.numRAGatesPerWindow; i++) { neutronsPerRossiAlphaGate[i] = 0; } //break the circular references, so garbage collector will do its thing nextEvent = theEventCircularLinkedList; while (nextEvent != null) { thisEvent = nextEvent; nextEvent = thisEvent.next; thisEvent.next = null; } theEventCircularLinkedList = null; startOfList = null; endOfList = null; numObjectsInCircularLinkedList = 0; if (closeCounters) { keepRunning = false; isReadyToAnalyze = false; waitingForMessage.Set(); } else { //create the circular linked list theEventCircularLinkedList = new RossiAlphaCircularNeutronEvent(0); //create the first element in the list startOfList = theEventCircularLinkedList; //set the head of the list to this first element endOfList = theEventCircularLinkedList; //set the tail of thelist to this first element for (i = 1; i < RawAnalysisProperties.circularListBlockIncrement; i++) //as a starter, put RawAnalysisProperties.circularListBlockIncrement structures in the list { endOfList.next = new RossiAlphaCircularNeutronEvent(i); //create the next new struct at the end of the tail endOfList = endOfList.next; //move the tail to this new stuct } numObjectsInCircularLinkedList = RawAnalysisProperties.circularListBlockIncrement; endOfList.next = startOfList; //close the loop, connecting the tail back to the head endOfList = startOfList; //set the head and tail to the first empty structure numCircuits = 0; isReadyToAnalyze = true; } }
void RACWorker_DoWork(object sender, DoWorkEventArgs e) { ulong deltaTimeInQueue; string threadName = "RossiAlphaAnalyzer_" + rossiAlphaGateWidth; Thread.CurrentThread.Name = threadName; #if USE_SPINTIME spinTimeReady = false; #endif while (keepRunning == true) { isReadyToAnalyze = true; #if USE_SPINTIME if (spinTimeReady) { StartSpinCount(); } #endif waitingForMessage.Wait(); //wait for some other thread to place neutron data in this object and signal this worker to analyze #if USE_SPINTIME if (spinTimeReady) { EndSpinCount(); } else { spinTimeReady = true; } #endif if (keepRunning == true) { int i, j; ulong eventTime; uint eventNeutrons; uint eventNumNeutrons; RossiAlphaCircularNeutronEvent anEvent; RossiAlphaCircularNeutronEvent nextEvent; for (j = 0; j < numEventsThisBlock && !csa.IsQuitRequested; j++) { eventTime = inputEventTime[j]; eventNeutrons = inputEventNeutrons[j]; eventNumNeutrons = inputEventNumNeutrons[j]; //fill in these new data at the tail of the circular linked list, //remembering that endOfNeutronEventList points to the next EMPTY struct in the list //INCLUDING at the beginning when the head and tail point to the same struct endOfList.FillEventWithData(eventTime, eventNeutrons, eventNumNeutrons); //check to see if the circular list will overflow if (endOfList.next.serialNumber == startOfList.serialNumber) { //if stack would overflow, add RawAnalysisProperties.circularListBlockIncrement neutron events at this spot in the stack... anEvent = endOfList; nextEvent = endOfList.next; for (i = 0; i < RawAnalysisProperties.circularListBlockIncrement; i++) { anEvent.next = new RossiAlphaCircularNeutronEvent(i + numObjectsInCircularLinkedList); anEvent = anEvent.next; } anEvent.next = nextEvent; //patch the circular linked list back together numObjectsInCircularLinkedList += RawAnalysisProperties.circularListBlockIncrement; //increase the record of the number of structs in the circular list } //move endOfNeutronEventList to the next empty struct endOfList = endOfList.next; //for fun, count how many times we have lapped the circular list in this experiment if (endOfList.serialNumber == 0) { numCircuits++; } //see if oldest event in the queue is expiring, //and while there are expiring events calculate the RossiAlpha statistics for those events deltaTimeInQueue = eventTime - startOfList.eventTime; while (deltaTimeInQueue > rossiAlphaWindowWidth) { //record the time of the expiring gate from the startOfList event, the total measured time for this experiment totalRossiAlphaAnalysisTime = startOfList.eventTime + rossiAlphaWindowWidth; //do RossiAlpha analysis here, accumulating statistics //add up how many neutrons there were in each RossiAlpha gate from the time of the expiring event int whichBin; ulong deltaTime; //skip the event at the head of the list. //To match data from the legacy code, start with the neutron event following this expiring head event. anEvent = startOfList.next; while (anEvent.serialNumber != endOfList.serialNumber) //...that is, until we reach the end of the list... { //Find the lowest bin with end time greater than the time of anEvent. deltaTime = anEvent.eventTime - startOfList.eventTime; whichBin = (int)(Math.Ceiling((double)deltaTime / (double)rossiAlphaGateWidth) + 0.1); if (whichBin < RawAnalysisProperties.numRAGatesPerWindow) //then this event falls into a bin; add this event's neutrons to that bin { neutronsPerRossiAlphaGate[whichBin] += anEvent.numNeutrons; //go to the next event anEvent = anEvent.next; } else { anEvent = endOfList; //abort the loop by going to the end of the list } } //remove expiring oldest event from the stack startOfList = startOfList.next; //re-calculate the delta time in the stack deltaTimeInQueue = eventTime - startOfList.eventTime; } //END of handling an individual NeutronEvent if (csa.IsQuitRequested) break; } //END of handling this block of events //prepare this thread's wait condition so will wait for a message //before telling master thread this thread's analysis is complete waitingForMessage.Reset(); } //END of if(keepRunning) else { //The master thread has cleared the keepRunning flag, so this worker is exiting //Do any cleanup etc. here. } } //END of while(keepRunning) }
public RossiAlphaCircularStackAnalysis(UInt64 gateWidth) { int i; isReadyToAnalyze = false; #if USE_SPINTIME spinTimeTotal = 0; spinTimeStart = 0; spinTimeReady = false; #endif rossiAlphaGateWidth = gateWidth; rossiAlphaWindowWidth = ((UInt64)(RawAnalysisProperties.numRAGatesPerWindow)) * gateWidth; totalRossiAlphaAnalysisTime = 0; for (i = 0; i < RawAnalysisProperties.numRAGatesPerWindow; i++) { neutronsPerRossiAlphaGate[i] = 0; } //initialize the event inputs inputEventTime = new ulong[RawAnalysisProperties.maxEventsPerBlock]; inputEventNeutrons = new uint[RawAnalysisProperties.maxEventsPerBlock]; inputEventNumNeutrons = new uint[RawAnalysisProperties.maxEventsPerBlock]; numEventsThisBlock = 0; //create the circular linked list theEventCircularLinkedList = new RossiAlphaCircularNeutronEvent(0); //create the first element in the list startOfList = theEventCircularLinkedList; //set the head of the list to this first element endOfList = theEventCircularLinkedList; //set the tail of thelist to this first element for (i = 1; i < RawAnalysisProperties.circularListBlockIncrement; i++) //as a starter, put RawAnalysisProperties.circularListBlockIncrement structures in the list { endOfList.next = new RossiAlphaCircularNeutronEvent(i); //create the next new struct at the end of the tail endOfList = endOfList.next; //move the tail to this new stuct } numObjectsInCircularLinkedList = RawAnalysisProperties.circularListBlockIncrement; endOfList.next = startOfList; //close the loop, connecting the tail back to the head endOfList = startOfList; //set the head and tail to the first empty structure numCircuits = 0; //Set Up the RAC BackgroundWorker keepRunning = true; isReadyToAnalyze = false; RACWorker = new BackgroundWorker(); RACWorker.WorkerSupportsCancellation = false; //it either processes a neutron event, or it doesn't. RACWorker.DoWork += new DoWorkEventHandler(RACWorker_DoWork); RACWorker.RunWorkerAsync(); //pause until the RAcWorker is working while (RACWorker.IsBusy == false) { Thread.Sleep(1); } }
void RACWorker_DoWork(object sender, DoWorkEventArgs e) { UInt64 deltaTimeInQueue; String threadName = "RossiAlphaAnalyzer_" + rossiAlphaGateWidth; Thread.CurrentThread.Name = threadName; #if USE_SPINTIME spinTimeReady = false; #endif while (keepRunning == true) { isReadyToAnalyze = true; #if USE_SPINTIME if (spinTimeReady) { StartSpinCount(); } #endif waitingForMessage.Wait(); //wait for some other thread to place neutron data in this object and signal this worker to analyze #if USE_SPINTIME if (spinTimeReady) { EndSpinCount(); } else { spinTimeReady = true; } #endif if (keepRunning == true) { UInt64 eventTime; UInt32 eventNeutrons; UInt32 eventNumNeutrons; int j; for (j = 0; j < numEventsThisBlock; j++) { eventTime = inputEventTime[j]; eventNeutrons = inputEventNeutrons[j]; eventNumNeutrons = inputEventNumNeutrons[j]; //fill in these new data at the tail of the circular linked list, //remembering that endOfNeutronEventList points to the next EMPTY struct in the list //INCLUDING at the beginning when the head and tail point to the same struct endOfList.FillEventWithData(eventTime, eventNeutrons, eventNumNeutrons); //check to see if the circular list will overflow if (endOfList.next.serialNumber == startOfList.serialNumber) { int i; RossiAlphaCircularNeutronEvent anEvent; RossiAlphaCircularNeutronEvent nextEvent; //if stack would overflow, add RawAnalysisProperties.circularListBlockIncrement neutron events at this spot in the stack... anEvent = endOfList; nextEvent = endOfList.next; for (i = 0; i < RawAnalysisProperties.circularListBlockIncrement; i++) { anEvent.next = new RossiAlphaCircularNeutronEvent(i + numObjectsInCircularLinkedList); anEvent = anEvent.next; } anEvent.next = nextEvent; //patch the circular linked list back together numObjectsInCircularLinkedList += RawAnalysisProperties.circularListBlockIncrement; //increase the record of the number of structs in the circular list } //move endOfNeutronEventList to the next empty struct endOfList = endOfList.next; //for fun, count how many times we have lapped the circular list in this experiment if (endOfList.serialNumber == 0) { numCircuits++; } //see if oldest event in the queue is expiring, //and while there are expiring events calculate the RossiAlpha statistics for those events deltaTimeInQueue = eventTime - startOfList.eventTime; while (deltaTimeInQueue > rossiAlphaWindowWidth) { //record the time of the expiring gate from the startOfList event, the total measured time for this experiment totalRossiAlphaAnalysisTime = startOfList.eventTime + rossiAlphaWindowWidth; //do RossiAlpha analysis here, accumulating statistics //add up how many neutrons there were in each RossiAlpha gate from the time of the expiring event int whichBin; UInt64 deltaTime; RossiAlphaCircularNeutronEvent anEvent; //skip the event at the head of the list. //To match data from the legacy code, start with the neutron event following this expiring head event. anEvent = startOfList.next; while (anEvent.serialNumber != endOfList.serialNumber) //...that is, until we reach the end of the list... { //Find the lowest bin with end time greater than the time of anEvent. deltaTime = anEvent.eventTime - startOfList.eventTime; whichBin = (int)(Math.Ceiling((double)deltaTime / (double)rossiAlphaGateWidth) + 0.1); if (whichBin < RawAnalysisProperties.numRAGatesPerWindow) //then this event falls into a bin; add this event's neutrons to that bin { neutronsPerRossiAlphaGate[whichBin] += anEvent.numNeutrons; //go to the next event anEvent = anEvent.next; } else { anEvent = endOfList; //abort the loop by going to the end of the list } } //remove expiring oldest event from the stack startOfList = startOfList.next; //re-calculate the delta time in the stack deltaTimeInQueue = eventTime - startOfList.eventTime; } //END of handling an individual NeutronEvent } //END of handling this block of events //prepare this thread's wait condition so will wait for a message //before telling master thread this thread's analysis is complete waitingForMessage.Reset(); } //END of if(keepRunning) else { //The master thread has cleared the keepRunning flag, so this worker is exiting //Do any cleanup etc. here. } } //END of while(keepRunning) }