// ======== On Switched To ========= // public override void OnSwitchedTo() { MainTabbedPage.OnAnySwitchedTo(this); MainTabbedPage.theModelEntryPage.SyncNoisePicker(noisePicker); if (!Exec.IsExecuting() && // we could be waiting on a continuation! StartAction would switch us right back to this page even if it does not start a thread! currentModelInfo != MainTabbedPage.theModelEntryPage.modelInfo) // forkWorker: we can compute the chart concurrently { MainTabbedPage.theModelEntryPage.StartAction(forkWorker: true, switchToChart: false, switchToOutput: false, autoContinue: false); } KChartHandler.ChartUpdate(null); }
public void OnLegendClick(KSeries[] legend, KSeries series) { if (guiControls.IsShiftDown()) { KChartHandler.ShiftInvertVisible(series.name); foreach (var seriesI in legend) { seriesI.lineButton.SetLegendImage(seriesI); } } else { KChartHandler.InvertVisible(series.name); series.lineButton.SetLegendImage(series); // accessing the shared series data structure! } KChartHandler.VisibilityRemember(); KChartHandler.ChartUpdate(null); // cannot provide style: would have to marshall it throug KGui but is ok to update }
private static IEnumerable <SolPoint> SolutionGererator( Func <double, double, Vector, Func <double, Vector, Vector>, IEnumerable <SolPoint> > Solver, State initialState, double initialTime, double finalTime, Func <double, Vector, Vector> Flux, bool nonTrivialSolution, Style style) { IEnumerable <SolPoint> solution; if (nonTrivialSolution) { try { IEnumerable <SolPoint> solver = Solver(initialTime, finalTime, initialState.ToArray(), Flux); solution = OdeHelpers.SolveTo(solver, finalTime); } catch (Error e) { throw new Error(e.Message); } catch (Exception e) { KChartHandler.ChartUpdate(style, false); throw new Error("ODE Solver FAILED: " + e.Message); } } else // build a dummy point series, in case we want to report and plot just some numerical expressions { List <SolPoint> list = new List <SolPoint> { }; // SolPoint constructor was changed to public from internal if (finalTime <= initialTime) { list.Add(new SolPoint(initialTime, initialState.ToArray())); } else { for (double t = initialTime; t <= finalTime; t += ((finalTime - initialTime) / 1000.0)) { list.Add(new SolPoint(t, initialState.ToArray())); } } solution = list; } return(solution); }
public CollectionView LegendView() { CollectionView collectionView = new CollectionView() { //ItemsLayout = ListItemsLayout.VerticalList, // can also be set to a vertical grid ItemsLayout = new GridItemsLayout(2, ItemsLayoutOrientation.Vertical), SelectionMode = SelectionMode.Single, }; // collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys"); // a binding for the ItemSource, but we give keep regenerating it collectionView.ItemsSource = new ObservableCollection <LegendItem>(); // CollectionView contains LegendItems with bindings set in ItemTemplate collectionView.ItemTemplate = new DataTemplate(() => { // CollectionView contains LegendItems with bindings set in ItemTemplate Grid grid = new Grid { Padding = 2 }; grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(LegendItemHeight) }); grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); // grid.ColumnDefinitions.Add(new ColumnDefinition { Width = 50 }); //it is definitely labels that flash a gray box when updated BoxView box = new BoxView { VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center }; // needed, otherwise the default .Fill option ignores HeightRequest box.SetBinding(BoxView.ColorProperty, "Color"); // property of LegendItem box.SetBinding(BoxView.HeightRequestProperty, "Height"); // property of LegendItem box.SetBinding(BoxView.WidthRequestProperty, "Width"); // property of LegendItem Label nameLabel = new Label { FontSize = LegendFontSize, FontAttributes = FontAttributes.Bold }; nameLabel.SetBinding(Label.TextProperty, "Name"); // property of LegendItem grid.Children.Add(box, 0, 0); grid.Children.Add(nameLabel, 1, 0); // grid.Children.Add(new Label { Text = "xxx" }, 2, 0); //it is definitely labels that flash a gray box when updated return(grid); }); collectionView.SelectionChanged += (object sender, SelectionChangedEventArgs args) => { LegendItem item = collectionView.SelectedItem as LegendItem; if (item != null) { KChartHandler.InvertVisible(item.Name); KChartHandler.VisibilityRemember(); KChartHandler.ChartUpdate(null); KGui.gui.GuiLegendUpdate(); collectionView.SelectedItem = null; // avoid some visible flashing of the selection } }; return(collectionView); }
Integrate(Func <double, double, Vector, Func <double, Vector, Vector>, IEnumerable <SolPoint> > Solver, State initialState, double initialTime, double finalTime, Func <double, Vector, Vector> Flux, SampleValue sample, List <ReportEntry> reports, Noise noise, bool nonTrivialSolution, Style style) { double redrawTick = initialTime; double redrawStep = (finalTime - initialTime) / 50; double densityTick = initialTime; double densityStep = (finalTime - initialTime) / 1000; int pointsCounter = 0; int renderedCounter = 0; double lastTime = finalTime; State lastState = null; if (initialState.NaN()) { Gui.Log("Initial state contains NaN."); return(lastTime, lastState); } KChartHandler.ChartClearData(style); (string[] series, string[] seriesLNA) = GenerateSeries(reports, noise, style); KChartHandler.LegendUpdate(style); KScoreHandler.ScoreUpdate(); IEnumerable <SolPoint> solution = SolutionGererator(Solver, initialState, initialTime, finalTime, Flux, nonTrivialSolution, style); List <TriggerEntry> triggers = sample.Triggers(style); bool[] triggered = new bool[triggers.Count]; for (int i = 0; i < triggers.Count; i++) { triggered[i] = false; } // BEGIN foreach (SolPoint solPoint in solution) -- done by hand to catch exceptions in MoveNext() SolPoint solPoint = new SolPoint(initialTime, initialState.Clone().ToArray()); bool hasSolPoint = false; var enumerator = solution.GetEnumerator(); do { // Handle triggers first, they can apply to the initial state if (triggers.Count > 0) { State state = null; // allocated on need from solPoint State modifiedState = null; // allocated on need from state for (int i = 0; i < triggers.Count; i++) { if (triggered[i] == false) { TriggerEntry trigger = triggers[i]; if (state == null) { state = new State(sample.Count(), lna: noise != Noise.None).InitAll(solPoint.X); } if (trigger.condition.ObserveBool(sample, solPoint.T, state, Flux, style)) { if (modifiedState == null) { modifiedState = state.Clone(); } double rawValue = trigger.assignment.ObserveMean(sample, solPoint.T, state, Flux, style); double assignment = trigger.sample.stateMap.NormalizeDimension(trigger.target, rawValue, trigger.dimension, trigger.sample.Volume(), style); int index = sample.stateMap.IndexOf(trigger.target.symbol); modifiedState.SetMean(index, assignment); if (noise != Noise.None && trigger.assignmentVariance != null) { double rawValueVariance = trigger.assignmentVariance.ObserveMean(sample, solPoint.T, state, Flux, style); double assignmentVariance = trigger.sample.stateMap.NormalizeDimension(trigger.target, rawValueVariance, trigger.dimension, trigger.sample.Volume(), style); modifiedState.SetCovar(index, index, assignmentVariance); } triggered[i] = true; } } } if (modifiedState != null) //restart the solver { State newState = modifiedState; // new State(sample.Count(), lna: noise != Noise.None).InitAll(modifiedState.ToArray()); solution = SolutionGererator(Solver, newState, solPoint.T, finalTime, Flux, nonTrivialSolution, style); enumerator = solution.GetEnumerator(); } } try { if (!enumerator.MoveNext()) { break; } solPoint = enumerator.Current; // get next step of integration from solver hasSolPoint = true; } catch (ConstantEvaluation e) { // stop simulation but allow execution to proceed Gui.Log("Simulation stopped and ignored: cannot evaluate constant '" + e.Message + "'"); return(lastTime, lastState); } catch (Error e) { throw new Error(e.Message); } catch (Exception e) { KChartHandler.ChartUpdate(style, false); throw new Error("ODE Solver FAILED: " + e.Message); } pointsCounter++; // LOOP BODY of foreach (SolPoint solPoint in solution): if (!Exec.IsExecuting()) { KChartHandler.ChartUpdate(style); throw new ExecutionEnded(""); } // break; if (style.chartOutput) // Plot the new solution point { if (solPoint.T >= densityTick) // avoid drawing too many points { State state = new State(sample.Count(), lna: noise != Noise.None).InitAll(solPoint.X); for (int i = 0; i < reports.Count; i++) { if (series[i] != null) // if a series was actually generated from this report // generate deterministic series { if ((noise == Noise.None && reports[i].flow.HasDeterministicValue()) || (noise != Noise.None && reports[i].flow.HasStochasticMean())) { double mean = reports[i].flow.ObserveMean(sample, solPoint.T, state, Flux, style); KChartHandler.ChartAddPoint(series[i], solPoint.T, mean, 0.0, Noise.None); } // generate LNA-dependent series if (noise != Noise.None && reports[i].flow.HasStochasticVariance() && !reports[i].flow.HasNullVariance()) { double mean = reports[i].flow.ObserveMean(sample, solPoint.T, state, Flux, style); double variance = reports[i].flow.ObserveVariance(sample, solPoint.T, state, style); KChartHandler.ChartAddPoint(seriesLNA[i], solPoint.T, mean, variance, noise); } } } renderedCounter++; densityTick += densityStep; } if (solPoint.T >= redrawTick) // avoid redrawing the plot too often { KChartHandler.ChartUpdate(style, incremental: true); redrawTick += redrawStep; } } lastTime = solPoint.T; // END foreach (SolPoint solPoint in solution) } while (true); if (hasSolPoint) { lastState = new State(sample.Count(), lna: noise != Noise.None).InitAll(solPoint.X); } KChartHandler.ChartUpdate(style, incremental: false); return(lastTime, lastState); }