Moved WorkManager to fx

This commit is contained in:
Alexander Nozik 2017-03-20 08:37:04 +03:00
parent ab006cb10f
commit 583ed5d63c
17 changed files with 89 additions and 851 deletions

View File

@ -7,12 +7,15 @@
package inr.numass.scripts package inr.numass.scripts
import hep.dataforge.grind.Grind import hep.dataforge.grind.Grind
import hep.dataforge.tables.DataPoint
import inr.numass.storage.NMPoint import inr.numass.storage.NMPoint
import inr.numass.storage.NumassData import inr.numass.storage.NumassData
import inr.numass.storage.NumassDataLoader import inr.numass.storage.NumassDataLoader
import inr.numass.storage.RawNMPoint
import inr.numass.utils.NMEventGeneratorWithPulser import inr.numass.utils.NMEventGeneratorWithPulser
import inr.numass.utils.PileUpSimulator import inr.numass.utils.PileUpSimulator
import inr.numass.utils.TritiumUtils import inr.numass.utils.TritiumUtils
import inr.numass.utils.UnderflowCorrection
import org.apache.commons.math3.random.JDKRandomGenerator import org.apache.commons.math3.random.JDKRandomGenerator
rnd = new JDKRandomGenerator(); rnd = new JDKRandomGenerator();
@ -37,12 +40,37 @@ List<NMPoint> pileup = new ArrayList<>();
lowerChannel = 400; lowerChannel = 400;
upperChannel = 1800; upperChannel = 1800;
PileUpSimulator buildSimulator(NMPoint point, double cr, NMPoint reference = null, double scale = 1d) { PileUpSimulator buildSimulator(NMPoint point, double cr, NMPoint reference = null, boolean extrapolate = true, double scale = 1d) {
def cfg = Grind.buildMeta(cr: cr) { def cfg = Grind.buildMeta(cr: cr) {
pulser(mean: 3450, sigma: 86.45, freq: 66.43) pulser(mean: 3450, sigma: 86.45, freq: 66.43)
} }
NMEventGeneratorWithPulser generator = new NMEventGeneratorWithPulser(rnd, cfg) NMEventGeneratorWithPulser generator = new NMEventGeneratorWithPulser(rnd, cfg)
generator.loadSpectrum(point, reference, lowerChannel, upperChannel);
if (extrapolate) {
double[] chanels = new double[RawNMPoint.MAX_CHANEL];
double[] values = new double[RawNMPoint.MAX_CHANEL];
DataPoint fitResult = new UnderflowCorrection().fitPoint(point, 400, 600, 1800, 20);
def amp = fitResult.getDouble("amp")
def sigma = fitResult.getDouble("expConst")
if (sigma > 0) {
for (int i = 0; i < upperChannel; i++) {
chanels[i] = i;
if (i < lowerChannel) {
values[i] = point.getLength()*amp * Math.exp((i as double) / sigma)
} else {
values[i] = Math.max(0, point.getCountInChanel(i) - (reference == null ? 0 : reference.getCountInChanel(i)));
}
}
generator.loadSpectrum(chanels, values)
} else {
generator.loadSpectrum(point, reference, lowerChannel, upperChannel);
}
} else {
generator.loadSpectrum(point, reference, lowerChannel, upperChannel);
}
return new PileUpSimulator(point.length * scale, rnd, generator).withUset(point.uset).generate(); return new PileUpSimulator(point.length * scale, rnd, generator).withUset(point.uset).generate();
} }
@ -53,7 +81,7 @@ double adjustCountRate(PileUpSimulator simulator, NMPoint point) {
} }
data.NMPoints.forEach { point -> data.NMPoints.forEach { point ->
double cr = TritiumUtils.countRateWithDeadTime(point, lowerChannel, upperChannel, 6.2e-6); double cr = TritiumUtils.countRateWithDeadTime(point, lowerChannel, upperChannel, 6.55e-6);
PileUpSimulator simulator = buildSimulator(point, cr); PileUpSimulator simulator = buildSimulator(point, cr);

View File

@ -45,6 +45,7 @@ public class Numass {
public static void printDescription(Context context, boolean allowANSI) throws DescriptorException { public static void printDescription(Context context, boolean allowANSI) throws DescriptorException {
PrintWriter writer = new PrintWriter(context.io().out()); PrintWriter writer = new PrintWriter(context.io().out());
DescriptorFormatter formatter = new TextDescriptorFormatter(writer, allowANSI); DescriptorFormatter formatter = new TextDescriptorFormatter(writer, allowANSI);
writer.println("***Data description***"); writer.println("***Data description***");
writer.print(" "); writer.print(" ");

View File

@ -60,6 +60,7 @@ import java.util.Arrays;
*/ */
@TypedActionDef(name = "showLoss", inputType = FitState.class, outputType = FitState.class, @TypedActionDef(name = "showLoss", inputType = FitState.class, outputType = FitState.class,
info = "Show loss spectrum for fit with loss model. Calculate excitation to ionisation ratio.") info = "Show loss spectrum for fit with loss model. Calculate excitation to ionisation ratio.")
@Deprecated
public class ShowLossSpectrumAction extends OneToOneAction<FitState, FitState> { public class ShowLossSpectrumAction extends OneToOneAction<FitState, FitState> {
private static final String[] names = {"X", "exPos", "ionPos", "exW", "ionW", "exIonRatio"}; private static final String[] names = {"X", "exPos", "ionPos", "exW", "ionW", "exIonRatio"};

View File

@ -68,10 +68,7 @@ public class NMEventGenerator implements Supplier<NMEvent> {
distribution = d; distribution = d;
} }
public void loadSpectrum(Map<Double, Double> spectrum, int minChanel, int maxChanel) { public void loadSpectrum(Map<Double, Double> spectrum) {
assert minChanel >= 0;
assert maxChanel <= RawNMPoint.MAX_CHANEL;
double[] chanels = new double[spectrum.size()]; double[] chanels = new double[spectrum.size()];
double[] values = new double[spectrum.size()]; double[] values = new double[spectrum.size()];
int i = 0; int i = 0;
@ -82,6 +79,10 @@ public class NMEventGenerator implements Supplier<NMEvent> {
distribution = new EnumeratedRealDistribution(chanels, values); distribution = new EnumeratedRealDistribution(chanels, values);
} }
public void loadSpectrum(double[] channels, double[] values) {
distribution = new EnumeratedRealDistribution(channels, values);
}
public void loadSpectrum(NMPoint point) { public void loadSpectrum(NMPoint point) {
double[] chanels = new double[RawNMPoint.MAX_CHANEL]; double[] chanels = new double[RawNMPoint.MAX_CHANEL];
double[] values = new double[RawNMPoint.MAX_CHANEL]; double[] values = new double[RawNMPoint.MAX_CHANEL];
@ -118,6 +119,7 @@ public class NMEventGenerator implements Supplier<NMEvent> {
distribution = new EnumeratedRealDistribution(chanels, values); distribution = new EnumeratedRealDistribution(chanels, values);
} }
protected NMEvent nextEvent(NMEvent prev) { protected NMEvent nextEvent(NMEvent prev) {
short chanel; short chanel;

View File

@ -5,7 +5,9 @@
*/ */
package inr.numass.utils; package inr.numass.utils;
import hep.dataforge.tables.DataPoint;
import hep.dataforge.tables.ListTable; import hep.dataforge.tables.ListTable;
import hep.dataforge.tables.MapPoint;
import hep.dataforge.tables.Table; import hep.dataforge.tables.Table;
import inr.numass.storage.NMPoint; import inr.numass.storage.NMPoint;
import org.apache.commons.math3.analysis.ParametricUnivariateFunction; import org.apache.commons.math3.analysis.ParametricUnivariateFunction;
@ -23,6 +25,8 @@ import java.util.stream.Collectors;
*/ */
public class UnderflowCorrection { public class UnderflowCorrection {
private static String[] pointNames = {"U", "amp", "expConst", "correction"};
// private final static int CUTOFF = -200; // private final static int CUTOFF = -200;
// public double get(Logable log, Meta meta, NMPoint point) { // public double get(Logable log, Meta meta, NMPoint point) {
@ -49,25 +53,28 @@ public class UnderflowCorrection {
// } // }
// } // }
public Table fitAllPoints(Iterable<NMPoint> data, int xLow, int xHigh, int binning) { // public Table fitAllPoints(Iterable<NMPoint> data, int xLow, int xHigh, int binning) {
ListTable.Builder builder = new ListTable.Builder("U", "amp", "expConst"); // ListTable.Builder builder = new ListTable.Builder("U", "amp", "expConst");
for (NMPoint point : data) { // for (NMPoint point : data) {
double[] fitRes = getUnderflowExpParameters(point, xLow, xHigh, binning); // double[] fitRes = getUnderflowExpParameters(point, xLow, xHigh, binning);
builder.row(point.getUset(), fitRes[0], fitRes[1]); // builder.row(point.getUset(), fitRes[0], fitRes[1]);
} // }
return builder.build(); // return builder.build();
// }
public DataPoint fitPoint(NMPoint point, int xLow, int xHigh, int upper, int binning) {
double norm = ((double) point.getCountInWindow(xLow, upper)) / point.getLength();
double[] fitRes = getUnderflowExpParameters(point, xLow, xHigh, binning);
double a = fitRes[0];
double sigma = fitRes[1];
return new MapPoint(pointNames,point.getUset(), a, sigma, a * sigma * Math.exp(xLow / sigma) / norm + 1d);
} }
public Table fitAllPoints(Iterable<NMPoint> data, int xLow, int xHigh, int upper, int binning) { public Table fitAllPoints(Iterable<NMPoint> data, int xLow, int xHigh, int upper, int binning) {
ListTable.Builder builder = new ListTable.Builder("U", "amp", "expConst", "correction"); ListTable.Builder builder = new ListTable.Builder(pointNames);
for (NMPoint point : data) { for (NMPoint point : data) {
double norm = ((double) point.getCountInWindow(xLow, upper)) / point.getLength(); builder.row(fitPoint(point,xLow,xHigh,upper,binning));
double[] fitRes = getUnderflowExpParameters(point, xLow, xHigh, binning);
double a = fitRes[0];
double sigma = fitRes[1];
//builder.row(point.getUset(), a, sigma, (a * sigma * (Math.exp(xLow / sigma) - 1) - a*xLow) / norm + 1d);
builder.row(point.getUset(), a, sigma, a * sigma * Math.exp(xLow / sigma) / norm + 1d);
} }
return builder.build(); return builder.build();
} }

View File

@ -1,449 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.workbench;
import hep.dataforge.actions.Action;
import hep.dataforge.actions.ActionManager;
import hep.dataforge.actions.ActionStateListener;
import hep.dataforge.actions.ActionUtils;
import hep.dataforge.context.Context;
import hep.dataforge.context.Global;
import hep.dataforge.data.DataNode;
import hep.dataforge.data.FileDataFactory;
import hep.dataforge.description.ActionDescriptor;
import hep.dataforge.description.DescriptorUtils;
import hep.dataforge.exceptions.NameNotFoundException;
import hep.dataforge.fx.FXDataOutputPane;
import hep.dataforge.fx.FXReportListener;
import hep.dataforge.fx.configuration.MetaEditor;
import hep.dataforge.fx.fragments.FragmentWindow;
import hep.dataforge.fx.fragments.LogFragment;
import hep.dataforge.fx.work.WorkManagerFragment;
import hep.dataforge.io.IOManager;
import hep.dataforge.io.MetaFileReader;
import hep.dataforge.meta.ConfigChangeListener;
import hep.dataforge.meta.Configuration;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.plots.PlotFrame;
import hep.dataforge.plots.PlotHolder;
import hep.dataforge.plots.PlotsPlugin;
import hep.dataforge.utils.ContextMetaFactory;
import hep.dataforge.values.Value;
import inr.numass.NumassIO;
import inr.numass.NumassProperties;
import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.stage.FileChooser;
import org.controlsfx.control.StatusBar;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* FXML Controller class
*
* @author Alexander Nozik
*/
public class NumassWorkbenchController implements Initializable, StagePaneHolder, ActionStateListener, PlotHolder {
Context parentContext;
ContextMetaFactory<Context> contextFactory;
List<MetaEditor> actionEditors = new ArrayList<>();
MetaEditor dataEditor;
Context context;
Configuration dataConfig;
Configuration actionsConfig;
Map<String, StagePane> stages = new ConcurrentHashMap<>();
WorkManagerFragment processWindow;
FXDataOutputPane logPane;
BooleanProperty isRunning = new SimpleBooleanProperty(false);
@FXML
private StatusBar statusBar;
@FXML
private TabPane stagesPane;
@FXML
private Accordion metaContainer;
@FXML
private Tab logTab;
@FXML
private ToggleButton runButton;
@FXML
private ToggleButton consoleButton;
@FXML
private ToggleButton processButton;
@Override
public void clearStage(String stageName) {
StagePane sp = stages.get(stageName);
if (sp != null) {
sp.closeAll();
Tab t = findTabWithName(stagesPane, stageName);
stagesPane.getTabs().remove(t);
stages.remove(stageName);
}
}
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
logPane = new FXDataOutputPane();
logTab.setContent(logPane.getRoot());
LogFragment consoleWindow = new LogFragment();
new FragmentWindow(consoleWindow).bindTo(consoleButton);
consoleWindow.addRootLogHandler();
consoleWindow.hookStd();
processWindow = new WorkManagerFragment();
new FragmentWindow(processWindow).bindTo(processButton);
isRunning.addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
runButton.setSelected(newValue);
if (newValue) {
runButton.setText("Stop");
} else {
runButton.setText("Run");
}
});
}
public Context getContext() {
if (context == null) {
throw new RuntimeException("Context not defined");
} else {
return context;
}
}
/**
* Setup context for current run
*
* @param config
*/
private void buildContext(Meta config) {
// close existing context
if (this.context != null) {
try {
this.context.close();
} catch (Exception ex) {
context.getLogger().error("Failed to close context", ex);
}
}
// building context using provided factory
this.context = this.contextFactory.build(parentContext, config);
// attachig visual process manager
processWindow.setManager(context.getWorkManager());
// setting io manager
context.setIO(new WorkbenchIOManager(new NumassIO(), this));
buildContextPane();
context.getLog().addListener(new FXReportListener(logPane));
// display plots iside workbench
PlotsPlugin.buildFrom(context).setPlotHolder(this);
}
private Tab findTabWithName(TabPane pane, String name) {
return pane.getTabs().stream().filter((t) -> t.getText().equals(name)).findFirst().orElse(null);
}
/**
* build or get tabPane for a given stage
*
* @param stage
* @return
*/
@Override
public synchronized StagePane getStagePane(String stage) {
if (!stages.containsKey(stage)) {
Tab stageTab = new Tab(stage);
StagePane stageTabPane = new StagePane();
stageTab.setContent(stageTabPane);
stages.put(stage, stageTabPane);
Platform.runLater(() -> stagesPane.getTabs().add(stageTab));
return stageTabPane;
} else {
return stages.get(stage);
}
}
private List<ActionDescriptor> listActions() {
return ActionManager.buildFrom(getContext()).list();
}
private ActionDescriptor getDescriptorForAction(String actionType) {
return listActions().stream().filter((a) -> a.getName().equals(actionType)).findFirst().orElse(null);
}
private void buildContextPane() {
Configuration contextValues = new Configuration("context");
//TODO add asMeta method to Context and replace map here
context.getProperties().entrySet().stream().forEach((item) -> {
contextValues.setValue(item.getKey(), item.getValue());
});
contextValues.addObserver(new ConfigChangeListener() {
@Override
public void notifyValueChanged(String name, Value oldItem, Value newItem) {
context.putValue(name, newItem);
}
@Override
public void notifyElementChanged(String name, List<? extends Meta> oldItem, List<? extends Meta> newItem) {
}
});
MetaEditor contextEditor = MetaEditor.build(contextValues, null);
contextEditor.geTable().setShowRoot(false);
TitledPane contextPane = new TitledPane("Context", contextEditor);
metaContainer.getPanes().add(contextPane);
}
public void loadConfig(Meta config) {
cleanUp();
buildContext(config);
//loading data configuration
if (config.hasMeta("data")) {
dataConfig = new Configuration(config.getMeta("data"));
//replacing file name value with appropriate nodes
if (dataConfig.hasValue("file")) {
Value fileValue = dataConfig.getValue("file");
dataConfig.removeValue("file");
fileValue.listValue().stream().forEach((fileName) -> {
dataConfig.putNode(new MetaBuilder("file")
.putValue("path", fileName));
});
}
dataEditor = MetaEditor.build(dataConfig,
DescriptorUtils.buildDescriptor(
DescriptorUtils.findAnnotatedElement("class::hep.dataforge.data.FileDataFactory")
));
dataEditor.geTable().setShowRoot(false);
metaContainer.getPanes().add(new TitledPane("Data", dataEditor));
}
//loading actions configuration
actionsConfig = new Configuration("actionlist");
List<Configuration> actions = config.getMetaList("action").stream()
.map(m -> new Configuration(m)).collect(Collectors.toList());
actionsConfig.attachNodeItem("action", actions);
int counter = 0;
for (Configuration action : actions) {
counter++;
MetaEditor actionEditor = new MetaEditor();
//Freezing actions names
// rootItem.setFrozenValuePredicate((c, n) -> c.getName().equals("action") && n.equals("type"));
actionEditor.setRoot(action, getDescriptorForAction(action.getString("type")));
actionEditors.add(actionEditor);
String actionTitle = String.format("action [%d]: %s", counter, action.getString("type"));
TitledPane actionPane = new TitledPane(actionTitle, actionEditor);
metaContainer.getPanes().add(actionPane);
}
runButton.setDisable(false);
}
private void clearAllStages() {
logPane.clear();
stages.keySet().stream().forEach((stageName) -> {
clearStage(stageName);
});
}
/**
* Clean up results and configuration panes
*/
private synchronized void cleanUp() {
//clear previus action panes
if (processWindow.getManager() != null) {
processWindow.getManager().cleanup();
}
metaContainer.getPanes().clear();
clearAllStages();
actionsConfig = null;
dataConfig = null;
}
@FXML
private void onLoadConfigClick(ActionEvent event) {
statusBar.setText("Loading configuration file...");
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open Configuration File");
String storageRoot = NumassProperties.getNumassProperty("numass.workbench.root");
if (storageRoot == null || !new File(storageRoot).exists()) {
fileChooser.setInitialDirectory(new File(".").getAbsoluteFile());
} else {
fileChooser.setInitialDirectory(new File(storageRoot));
}
File cfgFile = fileChooser.showOpenDialog(((Node) event.getTarget()).getScene().getWindow());
if (cfgFile != null) {
NumassProperties.setNumassProperty("numass.workbench.root", cfgFile.getParentFile().getAbsolutePath());
try {
Meta cfg = MetaFileReader.read(cfgFile).build();
this.loadConfig(cfg);
getContext().putValue(IOManager.ROOT_DIRECTORY_CONTEXT_KEY, cfgFile.getParentFile().toString());
} catch (IOException | ParseException ex) {
context.getLogger().error("Error reading configuration file", ex);
}
statusBar.setText("Configuration file loaded");
} else {
statusBar.setText("Loading configuration file canceled");
}
}
@FXML
private void onRunButtonClick(ActionEvent event) {
if (!isRunning.get()) {
if (context != null && !actionsConfig.isEmpty()) {
statusBar.setText("Starting action execution");
runActions();
}
} else {
this.context.getWorkManager().shutdown();
}
}
public Meta getDataConfiguration() {
return dataConfig == null ? Meta.empty() : new MetaBuilder(dataConfig).substituteValues(getContext()).build();
}
public Meta getActionConfiguration() {
return actionsConfig == null ? Meta.empty() : new MetaBuilder(actionsConfig).substituteValues(getContext()).build();
}
@SuppressWarnings("unchecked")
public void runActions() {
clearAllStages();
// processWindow.show();
new Thread(() -> {
Platform.runLater(() -> {
isRunning.set(true);
statusBar.setProgress(-1);
});
DataNode data = new FileDataFactory().build(getContext(), getDataConfiguration());
try {
ActionUtils.runAction(getContext(), data, getActionConfiguration()).computeAll();
Platform.runLater(() -> statusBar.setText("Execution complete"));
} catch (Exception ex) {
if (ex instanceof java.util.concurrent.CancellationException) {
//cach cancelation exception
Global.instance().getLogger().info("Interrupted by user");
Platform.runLater(() -> {
statusBar.setText("Execution interrupted by user");
});
} else {
//cach all other exceptions
Global.instance().getLogger().error("Exception while executing action chain", ex);
ex.printStackTrace(System.err);
Platform.runLater(() -> {
//printing stack trace to the default output
statusBar.setText("Execution failed");
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Exception!");
alert.setHeaderText("Action execution failure");
alert.setContentText(ex.getMessage());
alert.show();
});
}
} finally {
Platform.runLater(() -> {
isRunning.set(false);
statusBar.setProgress(0);
});
}
}, "actions").start();
}
public void setParentContext(Context parentContext) {
this.parentContext = parentContext;
}
public void setContextFactory(ContextMetaFactory<Context> contextFactory) {
this.contextFactory = contextFactory;
}
@Override
public void notifyActionStarted(Action action, Object argument) {
Platform.runLater(() -> statusBar.setText(String.format("Action '%s' started", action.getName())));
}
@Override
public void notifyActionFinished(Action action, Object result) {
Platform.runLater(() -> statusBar.setText(String.format("Action '%s' fineshed", action.getName())));
}
@Override
public void notifyAcionProgress(Action action, double progress, String message) {
Platform.runLater(() -> {
statusBar.setText(String.format("%s: %s started", action.getName(), message));
if (progress > 0) {
statusBar.setProgress(progress);
}
});
}
@Override
public PlotFrame buildPlotFrame(String stage, String name, Meta annotation) {
return getStagePane(stage).buildPlotOutput(name, annotation);
}
@Override
public PlotFrame getPlotFrame(String stage, String name) throws NameNotFoundException {
StagePane pane = getStagePane(stage);
Tab tab = findTabWithName(pane, "image::" + name);
if (tab != null && tab instanceof PlotOutputTab) {
return ((PlotOutputTab) tab).getFrame();
} else {
return null;
}
}
@Override
public boolean hasPlotFrame(String stage, String name) {
StagePane pane = getStagePane(stage);
Tab tab = findTabWithName(pane, "image::" + name);
return (tab != null && tab instanceof PlotOutputTab);
}
}

View File

@ -1,37 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.workbench;
import hep.dataforge.names.Named;
import javafx.scene.control.Tab;
/**
* A tab which contains output of task or action.
*
* @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a>
*/
public abstract class OutputTab extends Tab implements Named {
private String name;
public OutputTab(String name) {
super(name);
}
public OutputTab(String name, String title) {
super(title);
this.name = name;
}
@Override
public String getName() {
return name;
}
public abstract void close();
public abstract void clear();
}

View File

@ -1,50 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.workbench;
import hep.dataforge.meta.Meta;
import hep.dataforge.plots.fx.PlotContainer;
import hep.dataforge.plots.jfreechart.JFreeChartFrame;
public class PlotOutputTab extends OutputTab {
private final JFreeChartFrame frame;
public PlotOutputTab(String name, Meta meta) {
super(name);
PlotContainer container = new PlotContainer();
frame = new JFreeChartFrame(meta);
container.setPlot(frame);
// AnchorPane pane = new AnchorPane();
// frame = new JFreeChartFrame(name, meta).display(pane);
setContent(container.getRoot());
}
public PlotOutputTab(String name, String title, Meta meta) {
super(name, title);
PlotContainer container = new PlotContainer();
frame = new JFreeChartFrame(meta);
container.setPlot(frame);
setContent(container.getRoot());
}
@Override
public void close() {
}
@Override
public void clear() {
}
public JFreeChartFrame getFrame() {
return frame;
}
}

View File

@ -1,75 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.workbench;
import hep.dataforge.fx.FXUtils;
import hep.dataforge.meta.Meta;
import hep.dataforge.names.Named;
import hep.dataforge.plots.PlotFrame;
import javafx.application.Platform;
import javafx.scene.control.TabPane;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a>
*/
public class StagePane extends TabPane implements Named {
private String name;
private final Map<String, OutputTab> tabs = new HashMap<>();
@Override
public String getName() {
return name;
}
public void closeAll() {
tabs.values().stream().map((tab) -> {
tab.close();
return tab;
}).forEach((tab) -> {
Platform.runLater(() -> getTabs().remove(tab));
});
}
public synchronized void closeTab(String name) {
FXUtils.runNow(() -> {
tabs.get(name).close();
getTabs().remove(tabs.get(name));
tabs.remove(name);
});
}
public synchronized TextOutputTab buildTextOutput(String name) {
TextOutputTab out = new TextOutputTab(name);
FXUtils.runNow(() -> {
if (tabs.containsKey(name)) {
tabs.get(name).close();
getTabs().remove(tabs.get(name));
tabs.replace(name, out);
}
getTabs().add(out);
});
return out;
}
public synchronized PlotFrame buildPlotOutput(String name, Meta meta) {
PlotOutputTab out = new PlotOutputTab("plot::" + name, meta);
FXUtils.runNow(() -> {
if (tabs.containsKey(name)) {
tabs.get(name).close();
getTabs().remove(tabs.get(name));
tabs.replace(name, out);
}
getTabs().add(out);
});
return out.getFrame();
}
}

View File

@ -1,15 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.workbench;
/**
*
* @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a>
*/
public interface StagePaneHolder {
StagePane getStagePane(String stageName);
void clearStage(String stageName);
}

View File

@ -1,51 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.workbench;
import hep.dataforge.fx.FXDataOutputPane;
import javafx.event.Event;
import java.io.OutputStream;
/**
* A text output tab. Basically it is attached to IOManager::onComplete
*
* @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a>
*/
public class TextOutputTab extends OutputTab {
private final FXDataOutputPane out;
/**
* Create new stream output tab
*
* @param name
* @param stream outputStream to which output should be redirected after
* displaying in window
*/
public TextOutputTab(String name) {
super(name);
// onComplete = new DataOutputPane();
out = new FXDataOutputPane();
setContent(out.getRoot());
setOnClosed((Event event) -> close());
}
@Override
public void clear() {
out.clear();
}
@Override
public final void close() {
clear();
}
public OutputStream getStream() {
return out.getStream();
}
}

View File

@ -1,62 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.workbench;
import hep.dataforge.context.Global;
import inr.numass.Numass;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import java.io.IOException;
import java.text.ParseException;
/**
*
* @author Alexander Nozik
*/
public class Workbench extends Application {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws IOException, ParseException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/NumassWorkbench.fxml"));
Parent parent = loader.load();
Scene scene = new Scene(parent, 800, 600);
NumassWorkbenchController controller = loader.getController();
controller.setContextFactory(Numass::buildContext);
primaryStage.setTitle("Numass workbench");
primaryStage.setScene(scene);
primaryStage.show();
scene.getWindow().setOnCloseRequest((WindowEvent event) -> {
try {
controller.getContext().getWorkManager().getRoot().cancel(true);
} catch (Exception e) {
}
});
}
@Override
public void stop() throws Exception {
Global.instance().close();
super.stop();
}
}

View File

@ -1,65 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.workbench;
import hep.dataforge.io.BasicIOManager;
import hep.dataforge.io.IOManager;
import hep.dataforge.names.Name;
import org.apache.commons.io.output.TeeOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
/**
* An IOManager wrapper that redirects output to appropriate FX components
* @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a>
*/
public class WorkbenchIOManager extends BasicIOManager {
private final IOManager manager;
private final StagePaneHolder holder;
public WorkbenchIOManager(IOManager manager, StagePaneHolder holder) {
this.manager = manager;
this.holder = holder;
}
@Override
public File getFile(String path) {
return manager.getFile(path);
}
@Override
public File getRootDirectory() {
return manager.getRootDirectory();
}
@Override
public InputStream in() {
return manager.in();
}
@Override
public InputStream in(String path) {
return manager.in(path);
}
@Override
public OutputStream out(Name stage, Name name) {
//split output between parent output and holder output
OutputStream primary = holder.getStagePane(stage.toString()).buildTextOutput(name.toString()).getStream();
OutputStream secondary = manager.out(stage, name);
return new TeeOutputStream(primary, secondary);
}
@Override
public OutputStream out() {
return manager.out();
// return new ConsoleStream(holder.getLogArea(), new PrintStream(manager.onComplete()));
}
}

View File

@ -1,14 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.workbench;
/**
*
* @author <a href="mailto:altavir@gmail.com">Alexander Nozik</a>
*/
public class WorkbenchUtils {
}

View File

@ -20,8 +20,9 @@ import hep.dataforge.context.Global;
import hep.dataforge.exceptions.StorageException; import hep.dataforge.exceptions.StorageException;
import hep.dataforge.fx.fragments.FragmentWindow; import hep.dataforge.fx.fragments.FragmentWindow;
import hep.dataforge.fx.fragments.LogFragment; import hep.dataforge.fx.fragments.LogFragment;
import hep.dataforge.fx.work.Work;
import hep.dataforge.fx.work.WorkManager;
import hep.dataforge.fx.work.WorkManagerFragment; import hep.dataforge.fx.work.WorkManagerFragment;
import hep.dataforge.goals.Work;
import inr.numass.NumassProperties; import inr.numass.NumassProperties;
import inr.numass.storage.NumassData; import inr.numass.storage.NumassData;
import inr.numass.storage.NumassStorage; import inr.numass.storage.NumassStorage;
@ -85,6 +86,8 @@ public class MainViewerController implements Initializable {
@FXML @FXML
private ToggleButton processManagerButton; private ToggleButton processManagerButton;
private WorkManager workManager;
public static MainViewerController build(NumassStorage root) { public static MainViewerController build(NumassStorage root) {
MainViewerController res = new MainViewerController(); MainViewerController res = new MainViewerController();
res.setRootStorage(root); res.setRootStorage(root);
@ -102,9 +105,10 @@ public class MainViewerController implements Initializable {
@Override @Override
public void initialize(URL url, ResourceBundle rb) { public void initialize(URL url, ResourceBundle rb) {
LogFragment logFragment = new LogFragment(); LogFragment logFragment = new LogFragment();
logFragment.hookStd(); logFragment.addRootLogHandler();
//logFragment.hookStd();
new FragmentWindow(logFragment).bindTo(consoleButton); new FragmentWindow(logFragment).bindTo(consoleButton);
new FragmentWindow(WorkManagerFragment.attachToContext(Global.instance())).bindTo(processManagerButton); new FragmentWindow(new WorkManagerFragment(getWorkManager())).bindTo(processManagerButton);
mspController = new MspViewController(getContext()); mspController = new MspViewController(getContext());
this.mspTab.setContent(mspController.getRoot()); this.mspTab.setContent(mspController.getRoot());
@ -131,7 +135,7 @@ public class MainViewerController implements Initializable {
} }
private void loadDirectory(String path) { private void loadDirectory(String path) {
getContext().getWorkManager().startWork("viewer.loadDirectory", (Work work) -> { getWorkManager().startWork("viewer.loadDirectory", (Work work) -> {
work.setTitle("Load storage (" + path + ")"); work.setTitle("Load storage (" + path + ")");
work.setProgress(-1); work.setProgress(-1);
work.setStatus("Building numass storage tree..."); work.setStatus("Building numass storage tree...");
@ -151,10 +155,18 @@ public class MainViewerController implements Initializable {
return Global.instance(); return Global.instance();
} }
private synchronized WorkManager getWorkManager() {
if(workManager == null) {
workManager = new WorkManager();
workManager.startGlobal();
}
return workManager;
}
public void setRootStorage(NumassStorage root) { public void setRootStorage(NumassStorage root) {
getContext().getWorkManager().cleanup(); getWorkManager().cleanup();
getContext().getWorkManager().startWork("viewer.storage.load", (Work callback) -> { getWorkManager().startWork("viewer.storage.load", (Work callback) -> {
callback.setTitle("Fill data to UI (" + root.getName() + ")"); callback.setTitle("Fill data to UI (" + root.getName() + ")");
callback.setProgress(-1); callback.setProgress(-1);
Platform.runLater(() -> statusBar.setProgress(-1)); Platform.runLater(() -> statusBar.setProgress(-1));

View File

@ -16,7 +16,7 @@
package inr.numass.viewer; package inr.numass.viewer;
import hep.dataforge.exceptions.StorageException; import hep.dataforge.exceptions.StorageException;
import hep.dataforge.goals.Work; import hep.dataforge.fx.work.Work;
import inr.numass.storage.NumassData; import inr.numass.storage.NumassData;
import inr.numass.storage.NumassStorage; import inr.numass.storage.NumassStorage;
import javafx.application.Platform; import javafx.application.Platform;

View File

@ -22,7 +22,8 @@ package inr.numass.viewer;
*/ */
import hep.dataforge.context.Context; import hep.dataforge.context.Context;
import hep.dataforge.goals.Work; import hep.dataforge.fx.work.Work;
import hep.dataforge.fx.work.WorkManager;
import hep.dataforge.io.ColumnedDataWriter; import hep.dataforge.io.ColumnedDataWriter;
import hep.dataforge.meta.Meta; import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder; import hep.dataforge.meta.MetaBuilder;
@ -211,10 +212,14 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
return data; return data;
} }
private WorkManager getWorkManager(){
return context.getPlugin(WorkManager.class);
}
public void loadData(NumassData data) { public void loadData(NumassData data) {
this.data = data; this.data = data;
if (data != null) { if (data != null) {
context.getWorkManager().<List<NMPoint>>startWork("viewer.numass.load", (Work callback) -> { getWorkManager().<List<NMPoint>>startWork("viewer.numass.load", (Work callback) -> {
callback.setTitle("Load numass data (" + data.getName() + ")"); callback.setTitle("Load numass data (" + data.getName() + ")");
points = data.getNMPoints(); points = data.getNMPoints();
@ -239,7 +244,7 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
} }
private void setupHVPane(Supplier<Table> hvData) { private void setupHVPane(Supplier<Table> hvData) {
context.getWorkManager().startWork("viewer.numass.hv", (Work callback) -> { getWorkManager().startWork("viewer.numass.hv", (Work callback) -> {
Table t = hvData.get(); Table t = hvData.get();
Platform.runLater(() -> { Platform.runLater(() -> {
if (t != null) { if (t != null) {
@ -343,7 +348,7 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
detectorPlot.removePlot(); detectorPlot.removePlot();
} }
context.getWorkManager().startWork("viewer.numass.load.detector", (Work callback) -> { getWorkManager().startWork("viewer.numass.load.detector", (Work callback) -> {
Meta plottableConfig = new MetaBuilder("plot") Meta plottableConfig = new MetaBuilder("plot")
.setValue("connectionType", "step") .setValue("connectionType", "step")
.setValue("thickness", 2) .setValue("thickness", 2)