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
import hep.dataforge.grind.Grind
import hep.dataforge.tables.DataPoint
import inr.numass.storage.NMPoint
import inr.numass.storage.NumassData
import inr.numass.storage.NumassDataLoader
import inr.numass.storage.RawNMPoint
import inr.numass.utils.NMEventGeneratorWithPulser
import inr.numass.utils.PileUpSimulator
import inr.numass.utils.TritiumUtils
import inr.numass.utils.UnderflowCorrection
import org.apache.commons.math3.random.JDKRandomGenerator
rnd = new JDKRandomGenerator();
@ -37,12 +40,37 @@ List<NMPoint> pileup = new ArrayList<>();
lowerChannel = 400;
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) {
pulser(mean: 3450, sigma: 86.45, freq: 66.43)
}
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();
}
@ -53,7 +81,7 @@ double adjustCountRate(PileUpSimulator simulator, NMPoint 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);

View File

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

View File

@ -60,6 +60,7 @@ import java.util.Arrays;
*/
@TypedActionDef(name = "showLoss", inputType = FitState.class, outputType = FitState.class,
info = "Show loss spectrum for fit with loss model. Calculate excitation to ionisation ratio.")
@Deprecated
public class ShowLossSpectrumAction extends OneToOneAction<FitState, FitState> {
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;
}
public void loadSpectrum(Map<Double, Double> spectrum, int minChanel, int maxChanel) {
assert minChanel >= 0;
assert maxChanel <= RawNMPoint.MAX_CHANEL;
public void loadSpectrum(Map<Double, Double> spectrum) {
double[] chanels = new double[spectrum.size()];
double[] values = new double[spectrum.size()];
int i = 0;
@ -82,6 +79,10 @@ public class NMEventGenerator implements Supplier<NMEvent> {
distribution = new EnumeratedRealDistribution(chanels, values);
}
public void loadSpectrum(double[] channels, double[] values) {
distribution = new EnumeratedRealDistribution(channels, values);
}
public void loadSpectrum(NMPoint point) {
double[] chanels = 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);
}
protected NMEvent nextEvent(NMEvent prev) {
short chanel;

View File

@ -5,7 +5,9 @@
*/
package inr.numass.utils;
import hep.dataforge.tables.DataPoint;
import hep.dataforge.tables.ListTable;
import hep.dataforge.tables.MapPoint;
import hep.dataforge.tables.Table;
import inr.numass.storage.NMPoint;
import org.apache.commons.math3.analysis.ParametricUnivariateFunction;
@ -23,6 +25,8 @@ import java.util.stream.Collectors;
*/
public class UnderflowCorrection {
private static String[] pointNames = {"U", "amp", "expConst", "correction"};
// private final static int CUTOFF = -200;
// 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) {
ListTable.Builder builder = new ListTable.Builder("U", "amp", "expConst");
for (NMPoint point : data) {
double[] fitRes = getUnderflowExpParameters(point, xLow, xHigh, binning);
builder.row(point.getUset(), fitRes[0], fitRes[1]);
}
return builder.build();
// public Table fitAllPoints(Iterable<NMPoint> data, int xLow, int xHigh, int binning) {
// ListTable.Builder builder = new ListTable.Builder("U", "amp", "expConst");
// for (NMPoint point : data) {
// double[] fitRes = getUnderflowExpParameters(point, xLow, xHigh, binning);
// builder.row(point.getUset(), fitRes[0], fitRes[1]);
// }
// 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) {
ListTable.Builder builder = new ListTable.Builder("U", "amp", "expConst", "correction");
ListTable.Builder builder = new ListTable.Builder(pointNames);
for (NMPoint point : data) {
double norm = ((double) point.getCountInWindow(xLow, upper)) / point.getLength();
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);
builder.row(fitPoint(point,xLow,xHigh,upper,binning));
}
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.fx.fragments.FragmentWindow;
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.goals.Work;
import inr.numass.NumassProperties;
import inr.numass.storage.NumassData;
import inr.numass.storage.NumassStorage;
@ -85,6 +86,8 @@ public class MainViewerController implements Initializable {
@FXML
private ToggleButton processManagerButton;
private WorkManager workManager;
public static MainViewerController build(NumassStorage root) {
MainViewerController res = new MainViewerController();
res.setRootStorage(root);
@ -102,9 +105,10 @@ public class MainViewerController implements Initializable {
@Override
public void initialize(URL url, ResourceBundle rb) {
LogFragment logFragment = new LogFragment();
logFragment.hookStd();
logFragment.addRootLogHandler();
//logFragment.hookStd();
new FragmentWindow(logFragment).bindTo(consoleButton);
new FragmentWindow(WorkManagerFragment.attachToContext(Global.instance())).bindTo(processManagerButton);
new FragmentWindow(new WorkManagerFragment(getWorkManager())).bindTo(processManagerButton);
mspController = new MspViewController(getContext());
this.mspTab.setContent(mspController.getRoot());
@ -131,7 +135,7 @@ public class MainViewerController implements Initializable {
}
private void loadDirectory(String path) {
getContext().getWorkManager().startWork("viewer.loadDirectory", (Work work) -> {
getWorkManager().startWork("viewer.loadDirectory", (Work work) -> {
work.setTitle("Load storage (" + path + ")");
work.setProgress(-1);
work.setStatus("Building numass storage tree...");
@ -151,10 +155,18 @@ public class MainViewerController implements Initializable {
return Global.instance();
}
private synchronized WorkManager getWorkManager() {
if(workManager == null) {
workManager = new WorkManager();
workManager.startGlobal();
}
return workManager;
}
public void setRootStorage(NumassStorage root) {
getContext().getWorkManager().cleanup();
getContext().getWorkManager().startWork("viewer.storage.load", (Work callback) -> {
getWorkManager().cleanup();
getWorkManager().startWork("viewer.storage.load", (Work callback) -> {
callback.setTitle("Fill data to UI (" + root.getName() + ")");
callback.setProgress(-1);
Platform.runLater(() -> statusBar.setProgress(-1));

View File

@ -16,7 +16,7 @@
package inr.numass.viewer;
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.NumassStorage;
import javafx.application.Platform;

View File

@ -22,7 +22,8 @@ package inr.numass.viewer;
*/
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.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
@ -211,10 +212,14 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
return data;
}
private WorkManager getWorkManager(){
return context.getPlugin(WorkManager.class);
}
public void loadData(NumassData data) {
this.data = data;
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() + ")");
points = data.getNMPoints();
@ -239,7 +244,7 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
}
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();
Platform.runLater(() -> {
if (t != null) {
@ -343,7 +348,7 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
detectorPlot.removePlot();
}
context.getWorkManager().startWork("viewer.numass.load.detector", (Work callback) -> {
getWorkManager().startWork("viewer.numass.load.detector", (Work callback) -> {
Meta plottableConfig = new MetaBuilder("plot")
.setValue("connectionType", "step")
.setValue("thickness", 2)