protected void ConstructContextContent(INCCStyleSection sec, Detector det)
        {
            sec.AddTwo("Facility:", meas.AcquireState.facility.Name);
            sec.AddTwo("Material balance area:", meas.AcquireState.mba.Name);
            sec.AddTwo("Detector type:", det.Id.Type); // todo: revisit this, there can be multiple detectors because there can be multiple physical and virtual SR Params used to create results
            sec.AddTwo("Detector id:", det.Id.DetectorId);
            sec.AddTwo("Electronics id:", det.Id.ElectronicsId);
            sec.AddTwo("Inventory change code:", meas.AcquireState.inventory_change_code);
            sec.AddTwo("I/O code:", meas.AcquireState.io_code);
            sec.AddTwo("Measurement date:", meas.MeasDate.ToString("yy.MM.dd     HH:mm:ss"));
            sec.AddTwo("Results file name:", meas.INCCResultsFileNames[meas.INCCResultsFileNames.Count - 1]);
            sec.AddTwo("Inspection number:", meas.AcquireState.campaign_id);

            if (AssaySelector.ForMass(meas.MeasOption) || meas.MeasOption == AssaySelector.MeasurementOption.rates)
            {
                /* item id only if an assay, calibration, holdup or rates only */
                //todo: need to check why item_id not stored in Measurement object directly....hn 5.14.2015
                // it is located on the AcquireParameters
                sec.AddTwo("Item id:", meas.AcquireState.item_id); // or       sec.AddTwo("Item id:",m.AcquireState.item);
            }
            if (AssaySelector.HasStratum(meas.MeasOption))
            {
                sec.AddTwo("Stratum id:", meas.AcquireState.stratum_id.Name);
                if (meas.Stratum != null)
                {
                    sec.AddTwo("Bias uncertainty:", meas.Stratum.bias_uncertainty);
                    sec.AddTwo("Random uncertainty:", meas.Stratum.random_uncertainty);
                    sec.AddTwo("Systematic uncertainty:", meas.Stratum.systematic_uncertainty);
                    sec.AddTwo("Relative std deviation:", meas.Stratum.relative_std_dev);
                }
                else
                {
                    sec.AddTwo("Bias uncertainty:", "0.0000");
                    sec.AddTwo("Random uncertainty:", "0.0000");
                    sec.AddTwo("Systematic uncertainty:", "0.0000");
                    sec.AddTwo("Relative std deviation:", "0.0000");
                }
            }
            if (AssaySelector.ForMass(meas.MeasOption))
            {
                sec.AddTwo("Material type:", meas.AcquireState.item_type);
                sec.AddTwo("Original declared mass:", meas.AcquireState.mass);
            }
            sec.AddTwo("Measurement option:", meas.MeasOption.PrintName());
            if (AssaySelector.DougsBasics(meas.MeasOption))
            {           /* well configuration */
                sec.AddTwo("Detector configuration:", meas.AcquireState.well_config.ToString());
            }
            sec.AddTwo("Data source:", det.Id.source.ToString());
            sec.AddTwo("QC tests:", meas.AcquireState.qc_tests ? "On" : "Off");
            ErrorCalculationTechnique ect = meas.AcquireState.error_calc_method.Override(meas.MeasOption, det.Id.SRType);

            if (ect != ErrorCalculationTechnique.None)
            {
                sec.AddTwo("Error calculation:", ect.ToString() + " method");
            }
            sec.AddTwo("Accidentals method:", meas.Tests.accidentalsMethod != AccidentalsMethod.None ? (meas.Tests.accidentalsMethod.ToString() + "d") : "Not set");
            sec.AddTwo("Inspector name:", meas.AcquireState.user_id);
            sec.AddTwo("Passive comment:", meas.AcquireState.comment);
        }
 protected void ConstructSRSection(INCCStyleSection sec, Multiplicity mu, Detector det)
 {
     // if this is based on a virtual SR then show it
     if (det.Id.source.UsingVirtualSRCounting(det.Id.SRType))
     {
         sec.AddTwo(" Virtual shift register:", mu.ToString());
     }
     sec.AddTwo("Predelay:", mu.SR.predelayMS);
     sec.AddTwo("Gate length:", mu.SR.gateLengthMS);
     if (det.Id.SRType == InstrType.DGSR)
     {
         sec.AddTwo("Gate length2:", mu.SR.gateLengthMS);
     }
     sec.AddIntegerRow("High voltage:", (Int32)mu.SR.highVoltage);
     sec.SetFPCurrentFormatPrecision(4);
     sec.AddTwo("Die away time:", mu.SR.dieAwayTimeMS);
     sec.AddTwo("Efficiency:", mu.SR.efficiency);
     sec.AddTwo("Multiplicity deadtime:", mu.SR.deadTimeCoefficientMultiplicityinNanoSecs);
     sec.AddTwo("Coefficient A deadtime:", mu.SR.deadTimeCoefficientAinMicroSecs);
     sec.AddTwo("Coefficient B deadtime:", mu.SR.deadTimeCoefficientBinPicoSecs);
     sec.AddTwo("Coefficient C deadtime:", mu.SR.deadTimeCoefficientCinNanoSecs);
     sec.AddTwo("Doubles gate fraction:", mu.SR.doublesGateFraction);
     sec.AddTwo("Triples gate fraction:", mu.SR.triplesGateFraction);
 }
        protected Section ConstructReportSection(INCCReportSection section, MeasOptionSelector moskey, INCCResult ir, Detector det)
        {
            INCCStyleSection sec = null;
            try
            {
                switch (section)
                {

                    // NEXT: in progress, an identical copy of full INCC report sections
                    case INCCReportSection.SummedRawData:
                        sec = new INCCStyleSection(null, 1, INCCStyleSection.ReportSection.Summary);
                        sec.SetFPCurrentFormatPrecision(0);
                        sec.AddHeader(String.Format("{0} summed raw data",meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected()?"Active":"Passive"));  // section header
                        sec.AddNumericRow("Shift register singles sum:", meas.SinglesSum);
                        sec.AddNumericRow("Shift register reals + accidentals sum:", ir.RASum);
                        sec.AddNumericRow("Shift register accidentals sum:", ir.ASum);
                        if (!det.Id.source.UsingVirtualSRCounting(det.Id.SRType))
                        {
                            sec.AddNumericRow("Shift register 1st scaler sum:", ir.S1Sum);
                            sec.AddNumericRow("Shift register 2nd scaler sum:", ir.S2Sum);
                        }
                        break;

                    case INCCReportSection.SummedRA:
                        sec = new INCCStyleSection(null, 1, INCCStyleSection.ReportSection.MultiColumn);
                        sec.AddHeader(String.Format("{0} summed multiplicity distributions",meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected()?"Active":"Passive"));  // section header
                        int[] srawidths = new int[] { 5, 12, 12 };
                        int minbin, maxbin;
                        minbin = Math.Min(ir.RAMult.Length, ir.NormedAMult.Length);
                        maxbin = Math.Max(ir.RAMult.Length, ir.NormedAMult.Length);
                        sec.AddColumnRowHeader(new string[] { " ", "R+A sums", "A sums" }, srawidths);
                        for (int i = 0; i < minbin; i++)
                            sec.AddColumnRow(new ulong[] { (ulong)i, ir.RAMult[i], ir.NormedAMult[i] }, srawidths);
                        for (int i = minbin; i < maxbin; i++)  // check for uneven column
                        {
                            ulong[] potential = new ulong[3];
                            potential[0] = (ulong)i;
                            if (i < ir.RAMult.Length)
                                potential[1] = ir.RAMult[i];
                            if (i < ir.NormedAMult.Length)
                                potential[2] = ir.NormedAMult[i];
                            sec.AddColumnRow(potential, srawidths);
                        }
                        break;

                    case INCCReportSection.MassResults:
                        sec = new INCCStyleSection(null, 1, INCCStyleSection.ReportSection.MethodResults);
                        //Results are not always passive. Boo.
                        sec.AddHeader(String.Format("{0} Results",meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected()?"Active":"Passive"));  // section header
                        sec.AddNumericRow("Singles:", ir.DeadtimeCorrectedSinglesRate);
                        sec.AddNumericRow("Doubles:", ir.DeadtimeCorrectedDoublesRate);
                        sec.AddNumericRow("Triples:", ir.DeadtimeCorrectedTriplesRate);
                        //changed to DTC rates.  Raw rates meaningless here hn 11.5.2014
                        //sec.AddNumericRow("Quads:", mcr.DeadtimeCorrectedQuadsRate); // todo: quads delayed until pents are ready per DN
                        if (!det.Id.source.UsingVirtualSRCounting(det.Id.SRType))
                        {
                            sec.AddNumericRow("Scaler 1:", ir.Scaler1);
                            sec.AddNumericRow("Scaler 2:", ir.Scaler2);
                        }

                        //if (det.Id.SRType >= LMDAQ.InstrType.NPOD)
                        //{
                        //    sec.Add(new Row()); // blank line
                        //    sec.AddNumericRow("Dyt. Singles:", ir.DytlewskiCorrectedSinglesRate);
                        //    sec.AddNumericRow("Dyt. Doubles:", ir.DytlewskiCorrectedDoublesRate);
                        //    sec.AddNumericRow("Dyt. Triples:", ir.DytlewskiCorrectedTriplesRate);
                        //}
                        break;
                    case INCCReportSection.MethodResultsAndParams:
                        // ir contains the measurement option-specific results: empty for rates and holdup, and also empty for calib and verif, the method-focused analyses, 
                        // but values are present for initial, normalization, precision, and should be present for background for the tm bkg results 
                        List<Row> rl = ir.ToLines(meas);
                        sec = new INCCStyleSection(null, 0, INCCStyleSection.ReportSection.MethodResults);
                        sec.AddRange(rl);

                        switch (meas.MeasOption)
                        {
                            case AssaySelector.MeasurementOption.background:
                                if (meas.Background.TMBkgParams.ComputeTMBkg)
                                    ctrllog.TraceEvent(LogLevels.Warning, 82010, "Background truncated multiplicity"); // todo: present the tm bkg results on m.Background
                                break;
                            case AssaySelector.MeasurementOption.initial:
                            case AssaySelector.MeasurementOption.normalization:
                            case AssaySelector.MeasurementOption.precision:
                                break;
                            case AssaySelector.MeasurementOption.verification:
                            case AssaySelector.MeasurementOption.calibration:
                                {
                                    INCCMethodResults imrs;
                                    bool beendonegot = meas.INCCAnalysisResults.TryGetINCCResults(moskey.MultiplicityParams, out imrs);
                                    if (beendonegot && imrs.Count > 0) // should be true for verification and calibration
                                    {
                                        // we've got a distinct detector id and material type on the methods, so that is the indexer here
                                        Dictionary<AnalysisMethod, INCCMethodResult> amimr = imrs[meas.INCCAnalysisState.Methods.selector];

                                        // now get an enumerator over the map of method results
                                        Dictionary<AnalysisMethod, INCCMethodResult>.Enumerator ai = amimr.GetEnumerator();
                                        while (ai.MoveNext())
                                        {
                                            INCCMethodResult imr = ai.Current.Value;
                                            // show the primaryMethod
                                            if (ai.Current.Key.Equals(imrs.primaryMethod))
                                            {
                                                sec.Add(new Row());
                                                Row rh = new Row();
                                                rh.Add(0, "            PRIMARY RESULT");
                                                sec.Add(rh);
                                            }
                                            rl = imr.ToLines(meas);
                                            sec.AddRange(rl);
                                            // todo: optional use of END_PRIMARY_RESULT as in some INCC report formats, but not others
                                        }
                                    }
                                }
                                break;
                            case AssaySelector.MeasurementOption.rates:
                            case AssaySelector.MeasurementOption.holdup:
                            case AssaySelector.MeasurementOption.unspecified:
                            default: // nothing new to present with these
                                break;
                        }
                        break;
                    case INCCReportSection.RawCycles:
                        sec = new INCCStyleSection(null, 1, INCCStyleSection.ReportSection.MultiColumn);
                        sec.AddHeader(String.Format("{0} cycle raw data",meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected()?"Active":"Passive"));  // section header
                        int[] crdwidths = new int[] { 5, 10, 10, 10, 10, 10, 10 };
                        sec.AddColumnRowHeader(new string[] { "Cycle", "Singles", "R+A  ", "A    ", "Scaler1", "Scaler2", "QC Tests" }, crdwidths);
                        foreach (Cycle cyc in meas.Cycles)
                        {
                            // if no results on the cycle, these map indexers throw
                            if (cyc.CountingAnalysisResults.GetResultsCount(typeof(Multiplicity)) > 0)                            // if no results on the cycle, these map indexers throw
                            {
                                MultiplicityCountingRes mcr = (MultiplicityCountingRes)cyc.CountingAnalysisResults[moskey.MultiplicityParams];
                                sec.AddCycleColumnRow(cyc.seq,
                                    new ulong[] { (ulong)mcr.Totals, (ulong)mcr.RASum, (ulong)mcr.ASum, (ulong)mcr.Scaler1.v, (ulong)mcr.Scaler2.v },
                                    meas.AcquireState.qc_tests?cyc.QCStatus(moskey.MultiplicityParams).INCCString():"Off", crdwidths);
                            }
                        }
                        break;
                    case INCCReportSection.DTCRateCycles:
                       
                        sec = new INCCStyleSection(null, 1, INCCStyleSection.ReportSection.MultiColumn);
                        sec.AddHeader(String.Format("{0} cycle DTC rate data",meas.AcquireState.well_config == WellConfiguration.Active?"Active":"Passive"));  // section header
                        int[] crawidths = new int[] { 5, 13, 13, 13, 13, 10 };
                        sec.AddColumnRowHeader(new string[] { "Cycle", "Singles", "Doubles", "Triples", "Mass", "QC Tests" }, crawidths);
                        
                        foreach (Cycle cyc in meas.Cycles)
                        {
                            if (cyc.CountingAnalysisResults.GetResultsCount(typeof(Multiplicity)) > 0)                            // if no results on the cycle, these map indexers throw
                            {
                                MultiplicityCountingRes mcr = (MultiplicityCountingRes)cyc.CountingAnalysisResults[moskey.MultiplicityParams];
                                //These debug rows show raw rates for comparison hn 10.30
                                //sec.AddCycleColumnRow(cyc.seq,
                                    //Again, could be wrong.
                                //    new double[] { mcr.RawSinglesRate.v, mcr.RawDoublesRate.v, -1, -1 },
                                //     cyc.QCStatus(moskey.MultiplicityParams).INCCString(), crawidths); 
                                    //Again, could be wrong.
                               // TODO: Am actually printing out the DTC rates per cycle.  This seems to work in all cases EXCEPT "precision" hn 11.5
                                sec.AddCycleColumnRow(cyc.seq,
                                     // Using the corrected rates!
                                     new double[] { mcr.DeadtimeCorrectedSinglesRate.v, mcr.DeadtimeCorrectedDoublesRate.v, mcr.DeadtimeCorrectedTriplesRate.v, mcr.mass/*Mass*/ },
                                      meas.AcquireState.qc_tests?cyc.QCStatus(moskey.MultiplicityParams).INCCString():"Off", crawidths);
                            }
                        }
                        break;
                    case INCCReportSection.MultiplicityDistributions:
                        sec = new INCCStyleSection(null, 1, INCCStyleSection.ReportSection.MultiColumn);
                        sec.AddHeader(String.Format("{0} multiplicity distributions for each cycle",meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected()?"Active":"Passive"));  // section header
                        int[] csrawidths = new int[] { 6, 12, 12 };
                        foreach (Cycle cyc in meas.Cycles)
                        {
                            if (cyc.CountingAnalysisResults.GetResultsCount(typeof(Multiplicity)) > 0)                            // if no results on the cycle, these map indexers throw
                            {
                                MultiplicityCountingRes mcr = (MultiplicityCountingRes)cyc.CountingAnalysisResults[moskey.MultiplicityParams];
                                minbin = Math.Min(mcr.RAMult.Length, mcr.NormedAMult.Length);
                                maxbin = Math.Max(mcr.RAMult.Length, mcr.NormedAMult.Length);
                                sec.AddColumnRowHeader(new string[] { "Cycle " + cyc.seq, "R+A ", "A   " }, csrawidths);
                                for (int i = 0; i < minbin; i++)
                                    sec.AddColumnRow(new ulong[] { (ulong)i, mcr.RAMult[i], mcr.NormedAMult[i] }, csrawidths);
                                for (int i = minbin; i < maxbin; i++)  // check for uneven column
                                {
                                    ulong[] potential = new ulong[3];
                                    potential[0] = (ulong)i;
                                    if (i < mcr.RAMult.Length)
                                        potential[1] = mcr.RAMult[i];
                                    if (i < mcr.NormedAMult.Length)
                                        potential[2] = mcr.NormedAMult[i];
                                    sec.AddColumnRow(potential, csrawidths);
                                }
                            }
                            sec.Add(new Row());// blank
                        }
                        break;
                    default:
                        break;
                }
            }
            catch (Exception e)
            {
                ctrllog.TraceException(e);
            }
            return sec;
        }
        protected void ConstructContextContent(INCCStyleSection sec, Detector det)
        {

            sec.AddTwo("Facility:", meas.AcquireState.facility.Name);
            sec.AddTwo("Material balance area:", meas.AcquireState.mba.Name);
            sec.AddTwo("Detector type:", det.Id.Type); // todo: revisit this, there can be multiple detectors because there can be multiple physical and virtual SR Params used to create results
            sec.AddTwo("Detector id:", det.Id.DetectorId);
            sec.AddTwo("Electronics id:", det.Id.ElectronicsId);
            sec.AddTwo("Inventory change code:", meas.AcquireState.inventory_change_code);
            sec.AddTwo("I/O code:", meas.AcquireState.io_code);
            sec.AddTwo("Measurement date:", meas.MeasDate.ToString("yy.MM.dd     HH:mm:ss"));
            sec.AddTwo("Results file name:", meas.INCCResultsFileNames[meas.INCCResultsFileNames.Count - 1]);
            sec.AddTwo("Inspection number:", meas.AcquireState.campaign_id);

            if (AssaySelector.ForMass(meas.MeasOption) || meas.MeasOption == AssaySelector.MeasurementOption.rates)
                /* item id only if an assay, calibration, holdup or rates only */
                //todo: need to check why item_id not stored in Measurement object directly....hn 5.14.2015
                // it is located on the AcquireParameters 
                sec.AddTwo("Item id:", meas.AcquireState.item_id); // or       sec.AddTwo("Item id:",m.AcquireState.item);
            if (AssaySelector.HasStratum(meas.MeasOption))
            {
                sec.AddTwo("Stratum id:", meas.AcquireState.stratum_id.Name);
                if (meas.Stratum != null)
                {
                    sec.AddTwo("Bias uncertainty:", meas.Stratum.bias_uncertainty);
                    sec.AddTwo("Random uncertainty:", meas.Stratum.random_uncertainty);
                    sec.AddTwo("Systematic uncertainty:", meas.Stratum.systematic_uncertainty);
                    sec.AddTwo("Relative std deviation:", meas.Stratum.relative_std_dev);
                }
                else
                {
                    sec.AddTwo("Bias uncertainty:", "0.0000");
                    sec.AddTwo("Random uncertainty:", "0.0000");
                    sec.AddTwo("Systematic uncertainty:", "0.0000");
                    sec.AddTwo("Relative std deviation:", "0.0000");
                }
            }
            if (AssaySelector.ForMass(meas.MeasOption))
            {
                sec.AddTwo("Material type:", meas.AcquireState.item_type);
                sec.AddTwo("Original declared mass:", meas.AcquireState.mass);
            }
            sec.AddTwo("Measurement option:", meas.MeasOption.PrintName());
            if (AssaySelector.DougsBasics(meas.MeasOption))
            {           /* well configuration */
                sec.AddTwo("Detector configuration:", meas.AcquireState.well_config.ToString());
            }
            sec.AddTwo("Data source:", det.Id.source.ToString());
            sec.AddTwo("QC tests:", meas.AcquireState.qc_tests ? "On" : "Off");
            ErrorCalculationTechnique ect = meas.AcquireState.error_calc_method.Override(meas.MeasOption, det.Id.SRType);
            if (ect != ErrorCalculationTechnique.None)
                sec.AddTwo("Error calculation:", ect.ToString() + " method");
            sec.AddTwo("Accidentals method:", meas.Tests.accidentalsMethod != AccidentalsMethod.None ? (meas.Tests.accidentalsMethod.ToString() + "d") : "Not set");
            sec.AddTwo("Inspector name:", meas.AcquireState.user_id);
            sec.AddTwo("Passive comment:", meas.AcquireState.comment);
        }
 protected void ConstructSRSection(INCCStyleSection sec, Multiplicity mu, Detector det)
 {
     // if this is based on a virtual SR then show it
     if (det.Id.source.UsingVirtualSRCounting(det.Id.SRType))
         sec.AddTwo(" Virtual shift register:", mu.ToString());
     sec.AddTwo("Predelay:", mu.SR.predelayMS);
     sec.AddTwo("Gate length:", mu.SR.gateLengthMS);
     if (det.Id.SRType == InstrType.DGSR)
         sec.AddTwo("Gate length2:", mu.SR.gateLengthMS); 
     sec.AddIntegerRow("High voltage:", (Int32)mu.SR.highVoltage);
     sec.SetFPCurrentFormatPrecision(4);
     sec.AddTwo("Die away time:", mu.SR.dieAwayTimeMS);
     sec.AddTwo("Efficiency:", mu.SR.efficiency);
     sec.AddTwo("Multiplicity deadtime:", mu.SR.deadTimeCoefficientMultiplicityinNanoSecs);
     sec.AddTwo("Coefficient A deadtime:", mu.SR.deadTimeCoefficientAinMicroSecs);
     sec.AddTwo("Coefficient B deadtime:", mu.SR.deadTimeCoefficientBinPicoSecs);
     sec.AddTwo("Coefficient C deadtime:", mu.SR.deadTimeCoefficientCinNanoSecs);
     sec.AddTwo("Doubles gate fraction:", mu.SR.doublesGateFraction);
     sec.AddTwo("Triples gate fraction:", mu.SR.triplesGateFraction);
 }
        protected Section ConstructReportSection(INCCReportSection section, Detector det, MeasOptionSelector moskey = null)
        {
            INCCStyleSection sec = null;
            try
            {
                switch (section)
                {
                    case INCCReportSection.Header:
                        sec = new INCCStyleSection(null, 1);
                        sec.AddHeader(N.App.Name + " " + N.App.Config.VersionString);  // section header
                        break;
                    case INCCReportSection.Context:
                        sec = new INCCStyleSection(null, 1);
                        ConstructContextContent(sec, det);
                        break;
                    case INCCReportSection.Isotopics:
                        if (AssaySelector.ForMass(meas.MeasOption))
                        {
                            sec = new INCCStyleSection(null, 1);
                            sec.SetFPCurrentFormatPrecision(4);
                            Isotopics curiso = Isotopics.update_isotopics(1.0, meas.MeasDate, meas.Isotopics, meas.logger, N.App.AppContext.INCCParity);
                            if (curiso == null)
                            {
                                curiso = new Isotopics();
                                meas.Isotopics.CopyTo(curiso);
                                ctrllog.TraceEvent(LogLevels.Warning, 82034,  "Using incorrect updated defaults for " + meas.Isotopics.id);
                            }
                            sec.AddTwo("Isotopics id:", meas.Isotopics.id);
                            sec.AddTwo("Isotopics source code:", meas.Isotopics.source_code.ToString());
                            sec.AddDualNumericRow("Pu238:", meas.Isotopics[Isotope.pu238], curiso[Isotope.pu238]);
                            sec.AddDualNumericRow("Pu239:", meas.Isotopics[Isotope.pu239], curiso[Isotope.pu239]);
                            sec.AddDualNumericRow("Pu240:", meas.Isotopics[Isotope.pu240], curiso[Isotope.pu240]);
                            sec.AddDualNumericRow("Pu241:", meas.Isotopics[Isotope.pu241], curiso[Isotope.pu241]);
                            sec.AddDualNumericRow("Pu242:", meas.Isotopics[Isotope.pu242], curiso[Isotope.pu242]);
                            sec.AddDualDateOnlyRow("Pu date:", meas.Isotopics.pu_date, curiso.pu_date);
                            sec.AddDualNumericRow("Am241:", meas.Isotopics[Isotope.am241], curiso[Isotope.am241]);
                            sec.AddDualDateOnlyRow("Am date:", meas.Isotopics.am_date, curiso.am_date);
                            // dev note: here is where the alternative K vals are added in the Euratom version
                        }
                        break;
                    case INCCReportSection.ShiftRegister:
                        sec = new INCCStyleSection(null, 1);
                        ConstructSRSection(sec, moskey.MultiplicityParams, det);
                        break;
                    case INCCReportSection.Adjustments:
                        sec = new INCCStyleSection(null, 1);
                        if (AssaySelector.ForMass(meas.MeasOption) || meas.MeasOption == AssaySelector.MeasurementOption.rates)
                        {
                            ushort push = sec.FPFormatPrecision;
                            sec.SetFPCurrentFormatPrecision(4);
                            sec.AddNumericRow("Normalization constant:", meas.Norm.currNormalizationConstant);
                            sec.SetFPCurrentFormatPrecision(push);
                        }
                        if (AssaySelector.UsesBackground(meas.MeasOption))
                        {
                            sec.AddNumericRow("Passive singles bkgrnd:", meas.Background.DeadtimeCorrectedSinglesRate);
                            sec.AddNumericRow("Passive doubles bkgrnd:", meas.Background.DeadtimeCorrectedDoublesRate);
                            sec.AddNumericRow("Passive triples bkgrnd:", meas.Background.DeadtimeCorrectedTriplesRate);

                            if (det.Id.SRType <= InstrType.AMSR)
                            {
                                sec.AddNumericRow("Passive scaler1 bkgrnd:", meas.Background.Scaler1.v);
                                sec.AddNumericRow("Passive scaler2 bkgrnd:", meas.Background.Scaler2.v);
                            }

                            sec.AddNumericRow("Active singles bkgrnd:", meas.Background.INCCActive.Singles);
                            sec.AddNumericRow("Active doubles bkgrnd:", meas.Background.INCCActive.Doubles);
                            sec.AddNumericRow("Active triples bkgrnd:", meas.Background.INCCActive.Triples);
                            if (det.Id.SRType <= InstrType.AMSR)
                            {
                                sec.AddNumericRow("Passive scaler1 bkgrnd:", meas.Background.INCCActive.Scaler1Rate);
                                sec.AddNumericRow("Passive scaler2 bkgrnd:", meas.Background.INCCActive.Scaler2Rate);
                            }
                        }
                        break;
                    case INCCReportSection.CycleSummary:
                        sec = new INCCStyleSection(null, 1);
                        sec.AddIntegerRow(String.Format("Number {0} cycles:",meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected()?"Active":"Passive"), (int)meas.Cycles.GetValidCycleCountForThisKey(moskey.MultiplicityParams)); //det.MultiplicityParams)); // could also use CycleList length but CycleList can be longer when a reanalysis occurs and the analysis processing stops short of the end of the list due to modified termination conditions
                        sec.AddNumericRow("Count time (sec):", (meas.Cycles.Count > 0 ? meas.Cycles[0].TS.TotalSeconds : 0.0));
                        break;

                    case INCCReportSection.Messages:
                        List<MeasurementMsg> sl = null;
                        bool found = meas.Messages.TryGetValue(moskey.MultiplicityParams, out sl);
                        if (found)
                        {
                            sec = new INCCStyleSection(null, 1);
                            sec.AddHeader(String.Format("{0} messages", meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected() ? "Active" : "Passive"));  /// todo: is there an active messages section header analog?
                            foreach (MeasurementMsg m in sl)
                            {
                                Row r = new Row();
                                r.Add(0, m.text);  // expand to log style with toString?
                                sec.Add(r);
                            }
                        }
                        break;
                    case INCCReportSection.Reference:
                        sec = new INCCStyleSection(null, 1);
                        sec.AddHeader("Counting results, summaries and cycle counts file name");  // section header
                        Row resline = new Row(); resline.Add(0, "  " + meas.ResultsFileName);
                        sec.Add(resline);
                        break;
                    default:
                        break;
                }
            }
            catch (Exception e)
            {
                ctrllog.TraceException(e);
            }
            return sec;
        }
        protected Section ConstructReportSection(INCCReportSection section, MeasOptionSelector moskey, INCCResult ir, Detector det)
        {
            INCCStyleSection sec = null;

            try
            {
                switch (section)
                {
                // NEXT: in progress, an identical copy of full INCC report sections
                case INCCReportSection.SummedRawData:
                    sec = new INCCStyleSection(null, 1, INCCStyleSection.ReportSection.Summary);
                    sec.SetFPCurrentFormatPrecision(0);
                    sec.AddHeader(String.Format("{0} summed raw data", meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected()?"Active":"Passive"));     // section header
                    sec.AddNumericRow("Shift register singles sum:", meas.SinglesSum);
                    sec.AddNumericRow("Shift register reals + accidentals sum:", ir.RASum);
                    sec.AddNumericRow("Shift register accidentals sum:", ir.ASum);
                    if (!det.Id.source.UsingVirtualSRCounting(det.Id.SRType))
                    {
                        sec.AddNumericRow("Shift register 1st scaler sum:", ir.S1Sum);
                        sec.AddNumericRow("Shift register 2nd scaler sum:", ir.S2Sum);
                    }
                    break;

                case INCCReportSection.SummedRA:
                    sec = new INCCStyleSection(null, 1, INCCStyleSection.ReportSection.MultiColumn);
                    sec.AddHeader(String.Format("{0} summed multiplicity distributions", meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected()?"Active":"Passive"));     // section header
                    int[] srawidths = new int[] { 5, 12, 12 };
                    int   minbin, maxbin;
                    minbin = Math.Min(ir.RAMult.Length, ir.NormedAMult.Length);
                    maxbin = Math.Max(ir.RAMult.Length, ir.NormedAMult.Length);
                    sec.AddColumnRowHeader(new string[] { " ", "R+A sums", "A sums" }, srawidths);
                    for (int i = 0; i < minbin; i++)
                    {
                        sec.AddColumnRow(new ulong[] { (ulong)i, ir.RAMult[i], ir.NormedAMult[i] }, srawidths);
                    }
                    for (int i = minbin; i < maxbin; i++)      // check for uneven column
                    {
                        ulong[] potential = new ulong[3];
                        potential[0] = (ulong)i;
                        if (i < ir.RAMult.Length)
                        {
                            potential[1] = ir.RAMult[i];
                        }
                        if (i < ir.NormedAMult.Length)
                        {
                            potential[2] = ir.NormedAMult[i];
                        }
                        sec.AddColumnRow(potential, srawidths);
                    }
                    break;

                case INCCReportSection.MassResults:
                    sec = new INCCStyleSection(null, 1, INCCStyleSection.ReportSection.MethodResults);
                    //Results are not always passive. Boo.
                    sec.AddHeader(String.Format("{0} Results", meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected()?"Active":"Passive"));     // section header
                    sec.AddNumericRow("Singles:", ir.DeadtimeCorrectedSinglesRate);
                    sec.AddNumericRow("Doubles:", ir.DeadtimeCorrectedDoublesRate);
                    sec.AddNumericRow("Triples:", ir.DeadtimeCorrectedTriplesRate);
                    //changed to DTC rates.  Raw rates meaningless here hn 11.5.2014
                    //sec.AddNumericRow("Quads:", mcr.DeadtimeCorrectedQuadsRate); // todo: quads delayed until pents are ready per DN
                    if (!det.Id.source.UsingVirtualSRCounting(det.Id.SRType))
                    {
                        sec.AddNumericRow("Scaler 1:", ir.Scaler1);
                        sec.AddNumericRow("Scaler 2:", ir.Scaler2);
                    }

                    //if (det.Id.SRType >= LMDAQ.InstrType.NPOD)
                    //{
                    //    sec.Add(new Row()); // blank line
                    //    sec.AddNumericRow("Dyt. Singles:", ir.DytlewskiCorrectedSinglesRate);
                    //    sec.AddNumericRow("Dyt. Doubles:", ir.DytlewskiCorrectedDoublesRate);
                    //    sec.AddNumericRow("Dyt. Triples:", ir.DytlewskiCorrectedTriplesRate);
                    //}
                    break;

                case INCCReportSection.MethodResultsAndParams:
                    // ir contains the measurement option-specific results: empty for rates and holdup, and also empty for calib and verif, the method-focused analyses,
                    // but values are present for initial, normalization, precision, and should be present for background for the tm bkg results
                    List <Row> rl = ir.ToLines(meas);
                    sec = new INCCStyleSection(null, 0, INCCStyleSection.ReportSection.MethodResults);
                    sec.AddRange(rl);

                    switch (meas.MeasOption)
                    {
                    case AssaySelector.MeasurementOption.background:
                        if (meas.Background.TMBkgParams.ComputeTMBkg)
                        {
                            ctrllog.TraceEvent(LogLevels.Warning, 82010, "Background truncated multiplicity");         // todo: present the tm bkg results on m.Background
                        }
                        break;

                    case AssaySelector.MeasurementOption.initial:
                    case AssaySelector.MeasurementOption.normalization:
                    case AssaySelector.MeasurementOption.precision:
                        break;

                    case AssaySelector.MeasurementOption.verification:
                    case AssaySelector.MeasurementOption.calibration:
                    {
                        INCCMethodResults imrs;
                        bool beendonegot = meas.INCCAnalysisResults.TryGetINCCResults(moskey.MultiplicityParams, out imrs);
                        if (beendonegot && imrs.Count > 0)             // should be true for verification and calibration
                        {
                            // we've got a distinct detector id and material type on the methods, so that is the indexer here
                            Dictionary <AnalysisMethod, INCCMethodResult> amimr = imrs[meas.INCCAnalysisState.Methods.selector];

                            // now get an enumerator over the map of method results
                            Dictionary <AnalysisMethod, INCCMethodResult> .Enumerator ai = amimr.GetEnumerator();
                            while (ai.MoveNext())
                            {
                                INCCMethodResult imr = ai.Current.Value;
                                // show the primaryMethod
                                if (ai.Current.Key.Equals(imrs.primaryMethod))
                                {
                                    sec.Add(new Row());
                                    Row rh = new Row();
                                    rh.Add(0, "            PRIMARY RESULT");
                                    sec.Add(rh);
                                }
                                rl = imr.ToLines(meas);
                                sec.AddRange(rl);
                                // todo: optional use of END_PRIMARY_RESULT as in some INCC report formats, but not others
                            }
                        }
                    }
                    break;

                    case AssaySelector.MeasurementOption.rates:
                    case AssaySelector.MeasurementOption.holdup:
                    case AssaySelector.MeasurementOption.unspecified:
                    default:         // nothing new to present with these
                        break;
                    }
                    break;

                case INCCReportSection.RawCycles:
                    sec = new INCCStyleSection(null, 1, INCCStyleSection.ReportSection.MultiColumn);
                    sec.AddHeader(String.Format("{0} cycle raw data", meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected()?"Active":"Passive"));     // section header
                    int[] crdwidths = new int[] { 5, 10, 10, 10, 10, 10, 10 };
                    sec.AddColumnRowHeader(new string[] { "Cycle", "Singles", "R+A  ", "A    ", "Scaler1", "Scaler2", "QC Tests" }, crdwidths);
                    foreach (Cycle cyc in meas.Cycles)
                    {
                        // if no results on the cycle, these map indexers throw
                        if (cyc.CountingAnalysisResults.GetResultsCount(typeof(Multiplicity)) > 0)                                // if no results on the cycle, these map indexers throw
                        {
                            MultiplicityCountingRes mcr = (MultiplicityCountingRes)cyc.CountingAnalysisResults[moskey.MultiplicityParams];
                            sec.AddCycleColumnRow(cyc.seq,
                                                  new ulong[] { (ulong)mcr.Totals, (ulong)mcr.RASum, (ulong)mcr.ASum, (ulong)mcr.Scaler1.v, (ulong)mcr.Scaler2.v },
                                                  meas.AcquireState.qc_tests?cyc.QCStatus(moskey.MultiplicityParams).INCCString():"Off", crdwidths);
                        }
                    }
                    break;

                case INCCReportSection.DTCRateCycles:

                    sec = new INCCStyleSection(null, 1, INCCStyleSection.ReportSection.MultiColumn);
                    sec.AddHeader(String.Format("{0} cycle DTC rate data", meas.AcquireState.well_config == WellConfiguration.Active?"Active":"Passive"));     // section header
                    int[] crawidths = new int[] { 5, 13, 13, 13, 13, 10 };
                    sec.AddColumnRowHeader(new string[] { "Cycle", "Singles", "Doubles", "Triples", "Mass", "QC Tests" }, crawidths);

                    foreach (Cycle cyc in meas.Cycles)
                    {
                        if (cyc.CountingAnalysisResults.GetResultsCount(typeof(Multiplicity)) > 0)                                // if no results on the cycle, these map indexers throw
                        {
                            MultiplicityCountingRes mcr = (MultiplicityCountingRes)cyc.CountingAnalysisResults[moskey.MultiplicityParams];
                            //These debug rows show raw rates for comparison hn 10.30
                            //sec.AddCycleColumnRow(cyc.seq,
                            //Again, could be wrong.
                            //    new double[] { mcr.RawSinglesRate.v, mcr.RawDoublesRate.v, -1, -1 },
                            //     cyc.QCStatus(moskey.MultiplicityParams).INCCString(), crawidths);
                            //Again, could be wrong.
                            // TODO: Am actually printing out the DTC rates per cycle.  This seems to work in all cases EXCEPT "precision" hn 11.5
                            sec.AddCycleColumnRow(cyc.seq,
                                                  // Using the corrected rates!
                                                  new double[] { mcr.DeadtimeCorrectedSinglesRate.v, mcr.DeadtimeCorrectedDoublesRate.v, mcr.DeadtimeCorrectedTriplesRate.v, mcr.mass /*Mass*/ },
                                                  meas.AcquireState.qc_tests?cyc.QCStatus(moskey.MultiplicityParams).INCCString():"Off", crawidths);
                        }
                    }
                    break;

                case INCCReportSection.MultiplicityDistributions:
                    sec = new INCCStyleSection(null, 1, INCCStyleSection.ReportSection.MultiColumn);
                    sec.AddHeader(String.Format("{0} multiplicity distributions for each cycle", meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected()?"Active":"Passive"));     // section header
                    int[] csrawidths = new int[] { 6, 12, 12 };
                    foreach (Cycle cyc in meas.Cycles)
                    {
                        if (cyc.CountingAnalysisResults.GetResultsCount(typeof(Multiplicity)) > 0)                                // if no results on the cycle, these map indexers throw
                        {
                            MultiplicityCountingRes mcr = (MultiplicityCountingRes)cyc.CountingAnalysisResults[moskey.MultiplicityParams];
                            minbin = Math.Min(mcr.RAMult.Length, mcr.NormedAMult.Length);
                            maxbin = Math.Max(mcr.RAMult.Length, mcr.NormedAMult.Length);
                            sec.AddColumnRowHeader(new string[] { "Cycle " + cyc.seq, "R+A ", "A   " }, csrawidths);
                            for (int i = 0; i < minbin; i++)
                            {
                                sec.AddColumnRow(new ulong[] { (ulong)i, mcr.RAMult[i], mcr.NormedAMult[i] }, csrawidths);
                            }
                            for (int i = minbin; i < maxbin; i++)      // check for uneven column
                            {
                                ulong[] potential = new ulong[3];
                                potential[0] = (ulong)i;
                                if (i < mcr.RAMult.Length)
                                {
                                    potential[1] = mcr.RAMult[i];
                                }
                                if (i < mcr.NormedAMult.Length)
                                {
                                    potential[2] = mcr.NormedAMult[i];
                                }
                                sec.AddColumnRow(potential, csrawidths);
                            }
                        }
                        sec.Add(new Row());    // blank
                    }
                    break;

                default:
                    break;
                }
            }
            catch (Exception e)
            {
                ctrllog.TraceException(e);
            }
            return(sec);
        }
        protected Section ConstructReportSection(INCCReportSection section, Detector det, MeasOptionSelector moskey = null)
        {
            INCCStyleSection sec = null;

            try
            {
                switch (section)
                {
                case INCCReportSection.Header:
                    sec = new INCCStyleSection(null, 1);
                    sec.AddHeader(N.App.Name + " " + N.App.Config.VersionString);      // section header
                    break;

                case INCCReportSection.Context:
                    sec = new INCCStyleSection(null, 1);
                    ConstructContextContent(sec, det);
                    break;

                case INCCReportSection.Isotopics:
                    if (AssaySelector.ForMass(meas.MeasOption))
                    {
                        sec = new INCCStyleSection(null, 1);
                        sec.SetFPCurrentFormatPrecision(4);
                        Isotopics curiso = Isotopics.update_isotopics(1.0, meas.MeasDate, meas.Isotopics, meas.logger, N.App.AppContext.INCCParity);
                        if (curiso == null)
                        {
                            curiso = new Isotopics();
                            meas.Isotopics.CopyTo(curiso);
                            ctrllog.TraceEvent(LogLevels.Warning, 82034, "Using incorrect updated defaults for " + meas.Isotopics.id);
                        }
                        sec.AddTwo("Isotopics id:", meas.Isotopics.id);
                        sec.AddTwo("Isotopics source code:", meas.Isotopics.source_code.ToString());
                        sec.AddDualNumericRow("Pu238:", meas.Isotopics[Isotope.pu238], curiso[Isotope.pu238]);
                        sec.AddDualNumericRow("Pu239:", meas.Isotopics[Isotope.pu239], curiso[Isotope.pu239]);
                        sec.AddDualNumericRow("Pu240:", meas.Isotopics[Isotope.pu240], curiso[Isotope.pu240]);
                        sec.AddDualNumericRow("Pu241:", meas.Isotopics[Isotope.pu241], curiso[Isotope.pu241]);
                        sec.AddDualNumericRow("Pu242:", meas.Isotopics[Isotope.pu242], curiso[Isotope.pu242]);
                        sec.AddDualDateOnlyRow("Pu date:", meas.Isotopics.pu_date, curiso.pu_date);
                        sec.AddDualNumericRow("Am241:", meas.Isotopics[Isotope.am241], curiso[Isotope.am241]);
                        sec.AddDualDateOnlyRow("Am date:", meas.Isotopics.am_date, curiso.am_date);
                        // dev note: here is where the alternative K vals are added in the Euratom version
                    }
                    break;

                case INCCReportSection.ShiftRegister:
                    sec = new INCCStyleSection(null, 1);
                    ConstructSRSection(sec, moskey.MultiplicityParams, det);
                    break;

                case INCCReportSection.Adjustments:
                    sec = new INCCStyleSection(null, 1);
                    if (AssaySelector.ForMass(meas.MeasOption) || meas.MeasOption == AssaySelector.MeasurementOption.rates)
                    {
                        ushort push = sec.FPFormatPrecision;
                        sec.SetFPCurrentFormatPrecision(4);
                        sec.AddNumericRow("Normalization constant:", meas.Norm.currNormalizationConstant);
                        sec.SetFPCurrentFormatPrecision(push);
                    }
                    if (AssaySelector.UsesBackground(meas.MeasOption))
                    {
                        sec.AddNumericRow("Passive singles bkgrnd:", meas.Background.DeadtimeCorrectedSinglesRate);
                        sec.AddNumericRow("Passive doubles bkgrnd:", meas.Background.DeadtimeCorrectedDoublesRate);
                        sec.AddNumericRow("Passive triples bkgrnd:", meas.Background.DeadtimeCorrectedTriplesRate);

                        if (det.Id.SRType <= InstrType.AMSR)
                        {
                            sec.AddNumericRow("Passive scaler1 bkgrnd:", meas.Background.Scaler1.v);
                            sec.AddNumericRow("Passive scaler2 bkgrnd:", meas.Background.Scaler2.v);
                        }

                        sec.AddNumericRow("Active singles bkgrnd:", meas.Background.INCCActive.Singles);
                        sec.AddNumericRow("Active doubles bkgrnd:", meas.Background.INCCActive.Doubles);
                        sec.AddNumericRow("Active triples bkgrnd:", meas.Background.INCCActive.Triples);
                        if (det.Id.SRType <= InstrType.AMSR)
                        {
                            sec.AddNumericRow("Passive scaler1 bkgrnd:", meas.Background.INCCActive.Scaler1Rate);
                            sec.AddNumericRow("Passive scaler2 bkgrnd:", meas.Background.INCCActive.Scaler2Rate);
                        }
                    }
                    break;

                case INCCReportSection.CycleSummary:
                    sec = new INCCStyleSection(null, 1);
                    sec.AddIntegerRow(String.Format("Number {0} cycles:", meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected()?"Active":"Passive"), (int)meas.Cycles.GetValidCycleCountForThisKey(moskey.MultiplicityParams));    //det.MultiplicityParams)); // could also use CycleList length but CycleList can be longer when a reanalysis occurs and the analysis processing stops short of the end of the list due to modified termination conditions
                    sec.AddNumericRow("Count time (sec):", (meas.Cycles.Count > 0 ? meas.Cycles[0].TS.TotalSeconds : 0.0));
                    break;

                case INCCReportSection.Messages:
                    List <MeasurementMsg> sl = null;
                    bool found = meas.Messages.TryGetValue(moskey.MultiplicityParams, out sl);
                    if (found)
                    {
                        sec = new INCCStyleSection(null, 1);
                        sec.AddHeader(String.Format("{0} messages", meas.INCCAnalysisState.Methods.HasActiveSelected() || meas.INCCAnalysisState.Methods.HasActiveMultSelected() ? "Active" : "Passive"));      /// todo: is there an active messages section header analog?
                        foreach (MeasurementMsg m in sl)
                        {
                            Row r = new Row();
                            r.Add(0, m.text);      // expand to log style with toString?
                            sec.Add(r);
                        }
                    }
                    break;

                case INCCReportSection.Reference:
                    sec = new INCCStyleSection(null, 1);
                    sec.AddHeader("Counting results, summaries and cycle counts file name");      // section header
                    Row resline = new Row(); resline.Add(0, "  " + meas.ResultsFileName);
                    sec.Add(resline);
                    break;

                default:
                    break;
                }
            }
            catch (Exception e)
            {
                ctrllog.TraceException(e);
            }
            return(sec);
        }