public static SampleValue MassCompileSample(Symbol outSymbol, SampleValue inSample, Netlist netlist, Style style) { //inSample.Consume(null, 0, null, netlist, style); // this prevents simulating a sample and its massaction version in succession List <ReactionValue> inReactions = inSample.RelevantReactions(netlist, style); CRN inCrn = new CRN(inSample, inReactions); Gui.Log(Environment.NewLine + inCrn.FormatNice(style)); (Lst <Polynomize.ODE> odes, Lst <Polynomize.Equation> eqs) = Polynomize.FromCRN(inCrn); (Lst <Polynomize.PolyODE> polyOdes, Lst <Polynomize.Equation> polyEqs) = Polynomize.PolynomizeODEs(odes, eqs.Reverse(), style); Gui.Log("Polynomize:" + Environment.NewLine + Polynomize.PolyODE.Format(polyOdes, style) + "Initial:" + Environment.NewLine + Polynomize.Equation.Format(polyEqs, style)); (Lst <Polynomize.PolyODE> posOdes, Lst <Polynomize.Equation> posEqs, Dictionary <Symbol, SpeciesFlow> dict, Lst <Positivize.Subst> substs) = Positivize.PositivizeODEs(polyOdes, polyEqs, style); Gui.Log("Positivize:" + Environment.NewLine + Polynomize.PolyODE.Format(posOdes, style) + "Initial:" + Environment.NewLine + Polynomize.Equation.Format(posEqs, style)); Lst <ReactionValue> outReactions = Hungarize.ToReactions(posOdes, style); Gui.Log("Hungarize:" + Environment.NewLine + outReactions.FoldR((r, s) => { return(r.FormatNormal(style) + Environment.NewLine + s); }, "") + "Initial:" + Environment.NewLine + Polynomize.Equation.Format(posEqs, style)); SampleValue outSample = new SampleValue(outSymbol, new StateMap(outSymbol, new List <SpeciesValue> { }, new State(0, lna: inSample.stateMap.state.lna)), new NumberValue(inSample.Volume()), new NumberValue(inSample.Temperature()), produced: true); netlist.Emit(new SampleEntry(outSample)); posOdes.Each(ode => { Flow initFlow = Polynomize.Equation.ToFlow(ode.var, posEqs, style).Normalize(style); double init; if (initFlow is NumberFlow num) { init = num.value; } else { throw new Error("Cannot generate a simulatable sample because initial values contain constants (but the symbolic version has been generated assuming constants are nonnegative)."); } if (init < 0) { throw new Error("Negative initial value of Polynomized ODE for: " + Polynomize.Lookup(ode.var, eqs, style).Format(style) + " = " + init + Environment.NewLine + Polynomize.Equation.Format(eqs, style)); } outSample.stateMap.AddDimensionedSpecies(new SpeciesValue(ode.var.species, -1.0), init, 0.0, "M", outSample.Volume(), style); }); outReactions.Each(reaction => { netlist.Emit(new ReactionEntry(reaction)); }); substs.Each(subst => { ReportEntry report = new ReportEntry(null, OpFlow.Op(subst.plus, "-", subst.minus), null, outSample); outSample.AddReport(report); }); foreach (KeyValuePair <Symbol, SpeciesFlow> keypair in dict) { ReportEntry report = new ReportEntry(null, keypair.Value, null, outSample); outSample.AddReport(report); } ; return(outSample); }
public static (string[] series, string[] seriesLNA) GenerateSeries(List <ReportEntry> reports, Noise noise, Style style) { if (!style.chartOutput) { return(null, null); } string[] seriesLNA = new string[reports.Count]; // can contain nulls if series are duplicates paletteNo = (reports.Count - 1) % palette.Length; // because we scan palette backwards for (int i = reports.Count - 1; i >= 0; i--) // add series backwards so that Red is in front // generate LNA-dependent series { ReportEntry entry = reports[i]; bool noisePlottable = (noise != Noise.None) && entry.flow.HasStochasticVariance() && !entry.flow.HasNullVariance(); if (noisePlottable) { string reportName = (entry.asLabel != null) ? entry.asLabel : entry.flow.TopFormat(style.RestyleAsNumberFormat("G4")); string seriesName = reportName + Gui.StringOfNoise(noise); seriesLNA[i] = KChartHandler.ChartAddSeries(seriesName, entry.flow, palette[paletteNo % palette.Length], noise); // could be null } paletteNo--; if (paletteNo < 0) { paletteNo += palette.Length; // decrement out here to keep colors coordinated } } string[] series = new string[reports.Count]; // can contain nulls if series are duplicates paletteNo = (reports.Count - 1) % palette.Length; // because we scan palette backwards for (int i = reports.Count - 1; i >= 0; i--) // add series backwards so that Red is in front // generate deterministic series { ReportEntry entry = reports[i]; bool meanPlottable = (noise == Noise.None && entry.flow.HasDeterministicValue()) || ((noise != Noise.None) && entry.flow.HasStochasticMean()); bool noisePlottable = (noise != Noise.None) && entry.flow.HasStochasticVariance() && !entry.flow.HasNullVariance(); if (meanPlottable) { string reportName = (entry.asLabel != null) ? entry.asLabel : entry.flow.TopFormat(style.RestyleAsNumberFormat("G4")); string seriesName = reportName + (noisePlottable ? Gui.StringOfNoise(Noise.None) : ""); // do postfix mu if there is no sigma plot for it //string seriesName = reportName + ((noise == Noise.None) ? "" : Gui.StringOfNoise(Noise.None)); // previous version series[i] = KChartHandler.ChartAddSeries(seriesName, entry.flow, palette[paletteNo % palette.Length], Noise.None); // could be null } paletteNo--; if (paletteNo < 0) { paletteNo += palette.Length; // decrement out here to keep colors coordinated } } return(series, seriesLNA); }