Beispiel #1
0
        /// <summary>
        /// Start an assay on every instrument connected, this is for a single interval only
        /// The LMMM does just one assay from it's POV, and needs to be retold by DAQ here to do the next interval
        /// </summary>
        private int StartLM_SRAssay()
        {
            collog.TraceEvent(LogLevels.Info, 0, "Starting assay...");

            CurState.Measurement.CurrentRepetition++;
            CurState.State = DAQInstrState.ReceivingData;

            numTotalBytes = 0;

            collectingFileData = NC.App.AppContext.LiveFileWrite;

            CurState.StampAssayTime();
            CurState.GenDateTimePrefix(NC.App.AppContext.RootLoc);

            foreach (Instrument active in Instruments.Active)
            {
                if (active is SRInstrument)
                {
                    ctrllog.TraceEvent(LogLevels.Verbose, 999333, "Got SR {0} here", (active as SRInstrument).id.Identifier());
                }
                active.DAQState = DAQInstrState.ReceivingData;

                Cycle cycle = new Cycle(ctrllog);
                cycle.SetUpdatedDataSourceId(active.id); // where the cycle came from, but with updated timestamp
                CurState.Measurement.Add(cycle);         // todo: this mixes the cycles from the different instruments onto one list, gotta change this now that we are at more than one instrument, well you can simply write iterators that select on specific instrument Ids, over the entire list, or use LINQ select * where dsid == whatever syntax on the list
                ctrllog.TraceEvent(LogLevels.Verbose, 93939, "Cycle {0} init", cycle.seq);

                // devnote: file writing is selectable via the UI, and raw analysis should be independently
                // start the file capture
                if (active is LMInstrument)
                {
                    NCCFile.INeutronDataFile f = (active as LMInstrument).PrepOutputFile(CurState.currentDataFilenamePrefix, Instruments.Active.IndexOf(active), collog);
                    active.RDT.StartCycle(cycle, f); // internal handler needs access to the file handle for PTR-32 and MCA-527, but not for LMMM
                    ctrllog.TraceEvent(LogLevels.Verbose, 93939, "Cycle {0}, {1}", cycle.seq, string.IsNullOrEmpty(f.Filename) ? string.Empty: "output file name " + f.Filename);
                }
                else
                {
                    active.RDT.StartCycle(cycle);
                }

                if (CurState.Measurement.CurrentRepetition == 1)
                {
                    //  devnote: with more than one active, these need to be revisited
                    if (active is LMInstrument)
                    {
                        (active as LMInstrument).RDT.SetupCountingAnalyzerHandler(NC.App.Config, active.id.source.TimeBase(active.id.SRType));
                        (active as LMInstrument).RDT.PrepareAndStartCountingAnalyzers(CurState.Measurement.AnalysisParams);
                    }

                    // todo: Measurement Detector List exists but is not integrated with associated Instrument objects here
                    if (active is SRInstrument)
                    {
                        // kick off the thread to try and init the SR
                        SRWrangler.StartSRActionAndWait((active as SRInstrument).id, SRTakeDataHandler.SROp.InitializeSR);
                    }
                    else if (active is LMInstrument && active.id.SRType == InstrType.LMMM)
                    {
                        LMMMComm.FormatAndSendLMMMCommand(LMMMLingo.Tokens.prep, 0, Instruments.All.IndexOf(active));                         // send this config message to this LMMM
                    }

                    // devnote: index might be wrong if some of multiple LMs are disabled via UI. This will require a revisit at integration time
                }
            }

            NC.App.Loggers.Flush();
            FireEvent(EventType.ActionInProgress, this);
            Thread.Sleep(250); // LMMM only: wait for last send to finish, todo could we use EventHandler<SocketAsyncEventArgs> Completed here?

            // PTR-32/MCA-527
            // This loop works for PTR-32 and MCA-527 instruments, based on an improved instrument and control design

            // devnote: rewrite SR and LMMM sections below to use the StartAssay virtual method abstraction for measurement control
            foreach (Instrument instrument in Instruments.Active)
            {
                try {
                    instrument.StartAssay(CurState.Measurement);
                }
                catch (Exception ex) {
                    collog.TraceException(ex);
                }
            }

            // The following sections are for SR and LMMM
            // LMMM
            if (Instruments.Active.HasLMMM()) // send to a plurality of thresholding units, err, I mean, LMMM Instruments
            {
                if (CurState.broadcastGo)     // send go
                {
                    // this has to be sent separately, because linux control is looking for the Arm alone.
                    LMMMComm.FormatAndSendLMMMCommand(LMMMLingo.Tokens.arm); // send to all active

                    Thread.Sleep(250);                                       // allow linux code to setup waiting socket.

                    // broadcast go message to all NCC.App.Config.Net.Subnet addresses. This is the instrument group.
                    LMMMComm.PostLMMMCommand(LMMMLingo.Tokens.go, true);
                }
                else
                {
                    LMMMComm.FormatAndSendLMMMCommand(LMMMLingo.Tokens.go);                     // send to all active
                }
            }

            // SR
            bool srgood = false, hasSR = false;
            // send the start DAQ to every active SR, probably better to do this in the event handler not here
            IEnumerator iter = Instruments.Active.GetSREnumerator();

            while (iter.MoveNext())
            {
                hasSR = true;
                SRInstrument sri = (SRInstrument)iter.Current;
                int          srStatus = 0, measStatus = 0;
                SRWrangler.GetLastStatus(sri.id, ref srStatus, ref measStatus);

                if (measStatus != INCCSR.SUCCESS) // failure means we cannot see or use the SR, so go to the next one, whereas success means it initialized correctly in the InitializeSR step
                {
                    sri.DAQState = DAQInstrState.Offline;
                    continue;
                }

                int status = SRWrangler.StartSRActionAndWait(sri.id, SRTakeDataHandler.SROp.StartSRDAQ); // NEXT: check if pending here is going to be an issue
                if (status == INCCSR.MEAS_CONTINUE)                                                      // the SR started
                {
                    srgood = true;
                    SRWrangler.SetAction(sri.id, SRTakeDataHandler.SROp.WaitForResults); // event handler will pick up results when the internal timer polling in the thread detects results and fires the event
                }
            }
            // need a better test in here to skip all this startup stuff when the SR/LM/cycle init failed
            if (Instruments.Active.Count < 1)
            {
                CurState.Measurement.CurrentRepetition--;
                ctrllog.TraceEvent(LogLevels.Warning, 46, "No active instruments available now");
            }
            else if (hasSR && !srgood)
            {
                CurState.Measurement.CurrentRepetition--;
                ctrllog.TraceEvent(LogLevels.Warning, 46, "No Shift Register is available now");
            }
            else
            {
                if (CurState.Measurement.CurrentRepetition == 1)
                {
                    if (Instruments.Active.Count > 1)
                    {
                        if (Instruments.Active.Count != Instruments.All.Count)
                        {
                            ctrllog.TraceInformation("Using " + Instruments.Active.Count + " of " + Instruments.All.Count + " instruments");
                        }
                        else
                        {
                            ctrllog.TraceInformation("Using " + Instruments.Active.Count + " instruments");
                        }
                    }
                    else
                    {
                        ctrllog.TraceInformation("Using one instrument");
                    }
                }

                string str = "Assay cycle " + CurState.Measurement.CurrentRepetition + " of ";
                if (CurState.Measurement.RequestedRepetitions == 0)
                {
                    str += "a continuous assay starting";
                }
                else
                {
                    str += (CurState.Measurement.RequestedRepetitions + " cycles starting");
                }
                ctrllog.TraceInformation(str);
            }
            if (Instruments.Active.Count > 0)
            {
                FireEvent(EventType.ActionInProgress, this);
                collog.TraceEvent(LogLevels.Verbose, 0, "Started assay with {0} instrument{1}", Instruments.Active.Count, (Instruments.Active.Count > 1 ? "s" : ""));
            }
            return(Instruments.Active.Count);
        }