Initial commit for new gradle model

This commit is contained in:
Alexander Nozik 2015-12-18 16:20:47 +03:00
commit dc5a97c002
210 changed files with 24428 additions and 0 deletions

12
.hgignore Normal file
View File

@ -0,0 +1,12 @@
syntax: glob
*.orig
*.orig.*
*.chg.*
*.rej
*.conflict
build/*
target/*
.gradle/*
.nb-gradle/*
.idea/
*.iml

42
build.gradle Normal file
View File

@ -0,0 +1,42 @@
apply plugin: 'base'
apply plugin: 'project-report'
apply plugin: 'build-dashboard'
htmlDependencyReport {
projects = project.allprojects
}
File dataforgeDir = new File(rootDir,'../dataforge');
if(dataforgeDir.exists()){
rootProject.ext.dataforgeLocal = true;
}
subprojects{
if(path.startsWith(':dataforge')){
apply from: new File(dataforgeDir, 'dataforge.gradle')
}
if(path.startsWith(':numass')){
apply from: rootProject.file('numass.gradle')
}
}
buildscript {
repositories { jcenter() }
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.+'
}
}
//task mergedJavadoc(type: Javadoc, description: 'Creates Javadoc from all the projects.') {
// title = 'All modules'
// destinationDir = new File(project.buildDir, 'merged-javadoc')
//
// // Note: The closures below are executed lazily.
// source {
// subprojects*.sourceSets*.main*.allSource
// }
// classpath.from {
// subprojects*.configurations*.compile*.copyRecursive({!(it instanceof ProjectDependency)})*.resolve()
// }
//}

View File

@ -0,0 +1,2 @@
apply plugin: 'base' // To add "clean" task to the root project.

View File

@ -0,0 +1,17 @@
apply plugin: 'application'
if (!hasProperty('mainClass')) {
ext.mainClass = 'inr.numass.cryotemp.PKT8App'
}
mainClassName = mainClass
//mainClassName = "inr.numass.readvac.Main"
dependencies {
compile 'commons-cli:commons-cli:1.3'
compile 'de.jensd:shichimifx:1.0.5'
compile project(':dataforge-control')
compile project(':dataforge-storage')
compile project(':dataforge-plots')
}

View File

@ -0,0 +1,85 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.cryotemp;
import ch.qos.logback.classic.Level;
import hep.dataforge.exceptions.ControlException;
import hep.dataforge.storage.commons.StoragePlugin;
import java.io.IOException;
import java.util.Locale;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.slf4j.LoggerFactory;
/**
*
* @author darksnake
*/
public class PKT8App extends Application {
PKT8MainViewController controller;
@Override
public void start(Stage primaryStage) throws IOException, ControlException {
Locale.setDefault(Locale.US);// чтобы отделение десятичных знаков было точкой
ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
rootLogger.setLevel(Level.INFO);
new StoragePlugin().startGlobal();
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/PKT8MainView.fxml"));
Parent parent = loader.load();
controller = loader.getController();
// Meta deviceMeta = XMLMetaConverter.fromStream(getClass().getResourceAsStream("/defaultConfig.xml"));
// controller.setupDevice(deviceMeta);
Scene scene = new Scene(parent, 600, 400);
primaryStage.setTitle("PKT8 cryogenic temperature viewer");
primaryStage.setScene(scene);
primaryStage.setMinHeight(400);
primaryStage.setMinWidth(600);
// primaryStage.setResizable(false);
primaryStage.show();
}
@Override
public void stop() throws Exception {
super.stop();
if(controller!=null){
controller.close();
controller = null;
}
// System.exit(0);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}

View File

@ -0,0 +1,418 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.cryotemp;
import hep.dataforge.content.Named;
import hep.dataforge.context.Context;
import hep.dataforge.control.collectors.RegularPointCollector;
import hep.dataforge.control.devices.DataDevice;
import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.control.ports.TcpPortHandler;
import hep.dataforge.data.DataFormatBuilder;
import hep.dataforge.exceptions.ControlException;
import hep.dataforge.exceptions.PortException;
import hep.dataforge.exceptions.StorageException;
import hep.dataforge.meta.Annotated;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.storage.api.PointLoader;
import hep.dataforge.storage.api.Storage;
import hep.dataforge.storage.commons.LoaderFactory;
import hep.dataforge.values.Value;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
/**
* A device controller for Dubna PKT 8 cryogenic thermometry device
*
* @author Alexander Nozik
*/
public class PKT8Device extends DataDevice<PKT8Device.PKT8Measurement> implements PortHandler.PortController {
private static final String[] CHANNEL_DESIGNATIONS = {"a", "b", "c", "d", "e", "f", "g", "h"};
private PointLoader pointLoader;
private RegularPointCollector collector;
private boolean isStarted = false;
private PortHandler handler;
private int sps = -1;
private int pga = -1;
private int abuf = -1;
/**
* The key is the letter (a,b,c,d...) as in measurements
*/
private final Map<String, PKT8Channel> channels = new HashMap<>();
public PKT8Device(String name, Context context, Meta annotation) {
super(name, context, annotation);
}
/**
* Start measurement
*
* @throws ControlException
*/
@Override
public void doStart(Meta measurement) throws ControlException {
// Meta meta = new MetaChain("device", measurement.meta(),meta());
if (!isStarted) {
//setup storage
try {
Storage storage = getPrimaryStorage(measurement);
String suffix = Integer.toString((int) Instant.now().toEpochMilli());
// Building data format
DataFormatBuilder formatBuilder = new DataFormatBuilder()
.addTime("timestamp");
List<String> names = new ArrayList<>();
for (PKT8Channel channel : this.channels.values()) {
formatBuilder.addNumber(channel.getName());
names.add(channel.getName());
}
this.pointLoader = LoaderFactory.buildPointLoder(storage, "cryotemp_" + suffix, "", "timestamp", formatBuilder.build());
Duration duration = Duration.parse(meta().getString("averagingDuration", "PT30S"));
collector = new RegularPointCollector((dp) -> {
if (pointLoader != null) {
try {
getLogger().debug("Point measurement complete. Pushing...");
pointLoader.push(dp);
} catch (StorageException ex) {
getLogger().error("Error while pushing point to loader", ex);
}
}
}, duration, names);
} catch (StorageException ex) {
getLogger().error("Can't setup storage", ex);
}
handler.send("s");
isStarted = true;
}
}
@Override
public void init() throws ControlException {
//read channel configuration
if (meta().hasNode("channel")) {
for (Meta node : meta().getNodes("channel")) {
String designation = node.getString("designation", "default");
this.channels.put(designation, new PKT8Channel(node));
}
} else {
//set default channel configuration
for (String designation : CHANNEL_DESIGNATIONS) {
channels.put(designation, new PKT8Channel(designation));
}
getLogger().warn("No channels defined in configuration");
}
//setup connection
if (meta().hasNode("debug")) {
handler = new PKT8VirtualPort("PKT8", meta().getNode("debug"));
} else {
String ip = this.meta().getString("connection.ip", "127.0.0.1");
int port = this.meta().getInt("connection.port", 4001);
handler = new TcpPortHandler(ip, port, getName());
}
handler.setDelimeter("\n");
handler.holdBy(this);
handler.open();
handler.send("p");
handler.sendAndWait("p", null, 1000);
//update parameters from meta
if (meta().hasValue("pga")) {
getLogger().info("Setting dynamic range to " + meta().getInt("pga"));
String response = handler.sendAndWait("g" + meta().getInt("pga"), null, 400).trim();
if (response.contains("=")) {
this.pga = Integer.parseInt(response.substring(4));
} else {
getLogger().error("Setting pga failsed with message: " + response);
}
}
setSPS(meta().getInt("sps", 0));
setBUF(meta().getInt("abuf", 100));
super.init();
}
@Override
public void shutdown() throws ControlException {
stop();
try {
this.handler.unholdBy(this);
this.handler.close();
} catch (Exception ex) {
throw new ControlException(ex);
}
super.shutdown();
}
private void setSPS(int sps) throws PortException {
getLogger().info("Setting sampling rate to " + spsToStr(sps));
String response = handler.sendAndWait("v" + sps, null, 400).trim();
if (response.contains("=")) {
this.sps = Integer.parseInt(response.substring(4));
getLogger().info("successfully sampling rate to {}", spsToStr(this.sps));
} else {
getLogger().error("Setting sps failsed with message: " + response);
}
}
public Collection<PKT8Channel> getChanels() {
return this.channels.values();
}
private void setBUF(int buf) throws PortException {
getLogger().info("Setting avaraging buffer size to " + buf);
String response = handler.sendAndWait("b" + buf, null, 400).trim();
if (response.contains("=")) {
this.abuf = Integer.parseInt(response.substring(14));
getLogger().info("successfully set buffer size to {}", this.abuf);
} else {
getLogger().error("Setting averaging buffer failsed with message: " + response);
}
}
@Override
public void doStop() throws ControlException {
handler.send("p");
isStarted = false;
if (collector != null) {
collector.cancel();
}
}
public void changeParameters(int sps, int abuf) {
this.executor.submit(() -> {
try {
stop();
//setting sps
setSPS(sps);
//setting buffer
setBUF(abuf);
start();
} catch (ControlException ex) {
getLogger().error("Control error", ex);
}
});
}
@Override
public void accept(String message) {
String trimmed = message.trim();
if (isStarted) {
if (trimmed.equals("stopped")) {
isStarted = false;
getLogger().info("Measurement paused");
} else {
String designation = trimmed.substring(0, 1);
double rawValue = Double.parseDouble(trimmed.substring(1)) / 100;
if (channels.containsKey(designation)) {
PKT8Channel channel = channels.get(designation);
notifyMeasurementComplete(channel.getName(), rawValue, channel.getTemperature(rawValue));
collector.put(channel.getName(), channel.getTemperature(rawValue));
} else {
notifyMeasurementComplete(designation, rawValue, -1);
}
}
}
}
private void notifyMeasurementComplete(String channel, double rawValue, double temperature) {
measurementResult(null, new PKT8Measurement(channel, rawValue, temperature));
}
@Override
public void error(String errorMessage, Throwable error) {
}
/**
* '0' : 2,5 SPS '1' : 5 SPS '2' : 10 SPS '3' : 25 SPS '4' : 50 SPS '5' :
* 100 SPS '6' : 500 SPS '7' : 1 kSPS '8' : 3,75 kSPS
*
* @param sps
* @return
*/
private String spsToStr(int sps) {
switch (sps) {
case 0:
return "2,5 SPS";
case 1:
return "5 SPS";
case 2:
return "10 SPS";
case 3:
return "25 SPS";
case 4:
return "50 SPS";
case 5:
return "100 SPS";
case 6:
return "500 SPS";
case 7:
return "1 kSPS";
case 8:
return "3.75 kSPS";
default:
return "unknown value";
}
}
/**
* '0' : ± 5 В '1' : ± 2,5 В '2' : ± 1,25 В '3' : ± 0,625 В '4' : ± 312.5 мВ
* '5' : ± 156,25 мВ '6' : ± 78,125 мВ
*
* @param sps
* @return
*/
private String pgaToStr(int sps) {
switch (sps) {
case 0:
return "± 5 V";
case 1:
return "± 2,5 V";
case 2:
return "± 1,25 V";
case 3:
return "± 0,625 V";
case 4:
return "± 312.5 mV";
case 5:
return "± 156,25 mV";
case 6:
return "± 78,125 mV";
default:
return "unknown value";
}
}
public String getSPS() {
return spsToStr(sps);
}
public String getPGA() {
return pgaToStr(pga);
}
public String getABUF() {
return Integer.toString(abuf);
}
public class PKT8Channel implements Named, Annotated {
private final Meta meta;
private final Function<Double, Double> transformation;
public PKT8Channel(String name) {
this.meta = new MetaBuilder("channel")
.putValue("name", name);
transformation = (d) -> d;
}
public PKT8Channel(Meta meta) {
this.meta = meta;
String transformationType = meta.getString("transformationType", "default");
if (meta.hasValue("coefs")) {
switch (transformationType) {
case "default":
case "hyperbolic":
List<Value> coefs = meta.getValue("coefs").listValue();
double r0 = meta.getDouble("r0", 1000);
transformation = (r) -> {
if (coefs == null) {
return -1d;
} else {
double res = 0;
for (int i = 0; i < coefs.size(); i++) {
res += coefs.get(i).doubleValue() * Math.pow(r0 / r, i);
}
return res;
}
};
break;
default:
throw new RuntimeException("Unknown transformation type");
}
} else {
//identity transformation
transformation = (d) -> d;
}
}
@Override
public String getName() {
return meta().getString("name");
}
@Override
public Meta meta() {
return meta;
}
public String description() {
return meta().getString("description", "");
}
/**
*
* @param r negative if temperature transformation not defined
* @return
*/
public double getTemperature(double r) {
return transformation.apply(r);
}
}
public static class PKT8Measurement {
public String channel;
public double rawValue;
public double temperature;
public PKT8Measurement(String channel, double rawValue, double temperature) {
this.channel = channel;
this.rawValue = rawValue;
this.temperature = temperature;
}
}
}

View File

@ -0,0 +1,276 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.cryotemp;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.AppenderBase;
import de.jensd.shichimifx.utils.SplitPaneDividerSlider;
import hep.dataforge.context.GlobalContext;
import hep.dataforge.control.devices.Device;
import hep.dataforge.control.devices.DeviceListener;
import hep.dataforge.control.devices.MeasurementDevice;
import hep.dataforge.control.devices.MeasurementListener;
import hep.dataforge.exceptions.ControlException;
import hep.dataforge.io.MetaFileReader;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.meta.MetaUtils;
import hep.dataforge.plots.XYPlotFrame;
import hep.dataforge.plots.data.DynamicPlottable;
import hep.dataforge.plots.data.DynamicPlottableSet;
import hep.dataforge.plots.jfreechart.JFreeChartFrame;
import hep.dataforge.values.Value;
import inr.numass.cryotemp.PKT8Device.PKT8Measurement;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.ParseException;
import java.time.Instant;
import java.util.Collection;
import java.util.ResourceBundle;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.AnchorPane;
import javafx.stage.FileChooser;
/**
* FXML Controller class
*
* @author darksnake
*/
public class PKT8MainViewController implements Initializable, DeviceListener, MeasurementListener<PKT8Measurement>, AutoCloseable {
public static final String DEFAULT_CONFIG_LOCATION = "devices.xml";
private PKT8Device device;
private XYPlotFrame plotFrame;
private DynamicPlottableSet plottables;
private Meta currentPlotConfig;
@FXML
private Button loadConfigButton;
@FXML
private SplitPane consoleSplitPane;
@FXML
private TextArea logArea;
@FXML
private ToggleButton startStopButton;
@FXML
private AnchorPane plotArea;
@FXML
private ToggleButton consoleButton;
@Override
public void close() throws Exception {
if (device != null) {
device.stop();
device.shutdown();
}
}
/**
* Initializes the controller class.
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
setupPlotFrame(null);
SplitPaneDividerSlider slider = new SplitPaneDividerSlider(consoleSplitPane, 0, SplitPaneDividerSlider.Direction.DOWN);
consoleButton.selectedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
slider.setAimContentVisible(newValue);
});
slider.setAimContentVisible(false);
}
@FXML
private void onLoadConfigClick(ActionEvent event) throws IOException, ParseException, ControlException {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open configuration file");
fileChooser.setInitialFileName(DEFAULT_CONFIG_LOCATION);
fileChooser.setInitialDirectory(GlobalContext.instance().io().getRootDirectory());
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("xml", "*.xml", "*.XML"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("json", "*.json", "*.JSON"));
// fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("all", "*.*"));
File cfgFile = fileChooser.showOpenDialog(loadConfigButton.getScene().getWindow());
if (cfgFile != null) {
setConfig(MetaFileReader.read(cfgFile));
}
}
private void loadTestConfig() throws ControlException {
try {
Meta testConfig = MetaFileReader
.read(new File(getClass().getResource("/config/defaultConfig.xml").toURI()));
setConfig(testConfig);
} catch (URISyntaxException | IOException | ParseException ex) {
throw new Error(ex);
}
}
public String getDeviceName() {
return "PKT8";
}
public void setConfig(Meta config) throws ControlException {
if (config.hasNode("plotConfig")) {
Meta plotConfig = MetaUtils.findNodeByValue(config, "plotConfig", "device", getDeviceName());
if (plotConfig == null) {
plotConfig = config.getNode("plotConfig");
}
setupPlotFrame(plotConfig.getNode("plotFrame", null));
currentPlotConfig = plotConfig;
}
if (config.hasNode("device")) {
Meta deviceMeta = MetaUtils.findNodeByValue(config, "device", "name", Value.of(getDeviceName()));
setupDevice(deviceMeta);
} else {
setupDevice(config);
}
}
/**
* Set o reset plot area
*/
private void setupPlotFrame(Meta plotFrameMeta) {
plottables = new DynamicPlottableSet();
plotArea.getChildren().clear();
Meta plotConfig;
if (plotFrameMeta != null) {
plotConfig = new MetaBuilder(plotFrameMeta)
.setValue("xAxis.timeAxis", true);
} else {
plotConfig = new MetaBuilder("plotFrame")
.setValue("xAxis.timeAxis", true);
}
plotFrame = new JFreeChartFrame("plot", plotConfig, plotArea);
}
public void setupDevice(Meta deviceMeta) throws ControlException {
if (device != null) {
device.stop();
device.shutdown();
}
this.device = new PKT8Device("PKT8", GlobalContext.instance(), deviceMeta);
device.addDeviceListener(this);
device.addMeasurementListener(this);
logArea.appendText("Starting log...\n");
Appender<ILoggingEvent> appender = new AppenderBase<ILoggingEvent>() {
// private final DateTimeFormatter formatter = DateTimeFormatter.ISO_TIME;
@Override
protected void append(ILoggingEvent e) {
logArea.appendText(String.format("%s > (%s) [%s] %s%n",
e.getLoggerName(),
Instant.now().toString(),
e.getLevel(),
e.getFormattedMessage()));
}
};
appender.start();
device.getLogger().addAppender(appender);
device.init();
}
@Override
public void notifyDeviceInitialized(Device device) {
Collection<PKT8Device.PKT8Channel> channels = this.device.getChanels();
for (PKT8Device.PKT8Channel channel : channels) {
if (!plottables.hasPlottable(channel.getName())) {
//plot config from device configuration
Meta deviceLineMeta = channel.meta().getNode("plot", channel.meta());
//Do not use view config here, it is applyed separately
DynamicPlottable plottable = new DynamicPlottable(channel.getName(), deviceLineMeta);
plottables.addPlottable(plottable);
plotFrame.add(plottable);
}
}
startStopButton.setDisable(false);
if (currentPlotConfig != null) {
applyViewConfig(currentPlotConfig);
}
}
public void applyViewConfig(Meta viewConfig) {
plottables.applyConfig(viewConfig);
}
@Override
public void notifyDeviceShutdown(Device device) {
startStopButton.setDisable(true);
}
@Override
public void notifyDeviceStateChanged(Device device, String name, Value oldState, Value newState) {
}
// @Override
// public void sendMessage(Device device, int priority, Meta message) {
// String tag = message.getString("tag", "");
// logArea.appendText(String.format("%s > (%s) [%s] %s%n", device.getName(), Instant.now().toString(), tag, message));
// }
@Override
public void notifyMeasurementStarted(MeasurementDevice device, Meta measurement) {
}
@Override
public void notifyMeasurementStopped(MeasurementDevice device) {
}
@Override
public void notifyMeasurementResult(MeasurementDevice device, Meta measurement, PKT8Measurement measurementResult) {
plottables.put(measurementResult.channel, measurementResult.temperature);
}
@FXML
private void onStartStopClick(ActionEvent event) {
if (device != null) {
try {
if (startStopButton.isSelected()) {
device.start();
} else {
//in case device started
device.stop();
}
} catch (ControlException ex) {
}
}
}
}

View File

@ -0,0 +1,87 @@
/*
* 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.cryotemp;
import hep.dataforge.control.ports.VirtualPort;
import hep.dataforge.exceptions.PortException;
import hep.dataforge.meta.Annotated;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaUtils;
import hep.dataforge.values.Value;
import java.time.Duration;
import java.util.Random;
/**
*
* @author Alexander Nozik
*/
public class PKT8VirtualPort extends VirtualPort implements Annotated {
private final Meta meta;
private final Random generator = new Random();
public PKT8VirtualPort(String portName, Meta meta) {
super(portName);
this.meta = meta;
}
@Override
public Meta meta() {
return meta;
}
@Override
protected void evaluateRequest(String request) {
switch (request) {
case "s":
String[] letters = {"a", "b", "c", "d", "e", "f", "g", "h"};
for (String letter : letters) {
Meta channelMeta = MetaUtils.findNodeByValue(meta(), "channel", "letter", Value.of(letter));
double average;
double sigma;
if (channelMeta != null) {
average = channelMeta.getDouble("av", 1200);
sigma = channelMeta.getDouble("sigma", 50);
} else {
average = 1200d;
sigma = 50d;
}
this.planRegularResponse(
() -> {
double res = average + generator.nextGaussian() * sigma;
//TODO convert double value to formatted string
return letter + "000120000\n";
},
Duration.ZERO, Duration.ofSeconds(5), letter, "measurement"
);
}
return;
case "p":
cancelByTag("measurement");
this.recievePhrase("stopped\n\r");
return;
}
}
@Override
public void open() throws PortException {
}
@Override
public boolean isOpen() {
return true;
}
@Override
public void close() throws Exception {
cancelByTag("measurement");
}
}

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<device>
<storage path="D:\\temp\\cryo"/>
<connection ip="192.168.111.137" port="4001"/>
<abuf>120</abuf>
<channel designation="a" name="a-channel" r0="1000" transformationType="hyperbolic" coefs="[1.0,1.0]" color="black"/>
<channel designation="b" name="b-channel" r0="1000" transformationType="hyperbolic" coefs="[1.1,1.1]"/>
<channel designation="c" name="c-channel" r0="1000" transformationType="hyperbolic" coefs="[1.2,1.0]" thickness="2"/>
<channel designation="d" name="d-channel" r0="1000" transformationType="hyperbolic" coefs="[1.3,1.0]"/>
<plotConfig>
<eachPlot thickness="4"/>
<plot name = "c-channel" color="magenta"/>
</plotConfig>
</device>

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2015 Alexander Nozik.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="inr.numass.cryotemp.PKT8MainViewController">
<children>
<SplitPane fx:id="consoleSplitPane" dividerPositions="0.8" layoutX="184.0" layoutY="62.0" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="40.0">
<items>
<AnchorPane fx:id="plotArea" minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0" />
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="94.0" prefWidth="598.0">
<children>
<TextArea fx:id="logArea" editable="false" layoutX="38.0" layoutY="-75.0" prefHeight="200.0" prefWidth="200.0" wrapText="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
<ToolBar prefHeight="40.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<ToggleButton fx:id="startStopButton" disable="true" mnemonicParsing="false" onAction="#onStartStopClick" prefWidth="50.0" text="Start" />
<Separator orientation="VERTICAL" />
<Button fx:id="loadConfigButton" mnemonicParsing="false" onAction="#onLoadConfigClick" text="Load config" />
<ToggleButton fx:id="consoleButton" contentDisplay="CENTER" mnemonicParsing="false" text="Console" />
</items>
</ToolBar>
</children>
</AnchorPane>

View File

@ -0,0 +1,26 @@
apply plugin: 'application'
version = "0.2.5"
if (!hasProperty('mainClass')) {
ext.mainClass = 'inr.numass.control.magnet.fx.MagnetControllerApp'
}
mainClassName = mainClass
dependencies {
compile 'ch.qos.logback:logback-classic:1.1.0+'
compile 'org.scream3r:jssc:2.8.0'
compile project(':dataforge-control')
}
task talkToServer(type: JavaExec) {
description 'Console talk to remote server'
// Set main property to name of Groovy script class.
main = 'inr.numass.control.magnet.Talk'
// Set classpath for running the Groovy script.
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
standardOutput = System.out
}

View File

@ -0,0 +1,444 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.magnet;
import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.control.ports.PortTimeoutException;
import hep.dataforge.exceptions.PortException;
import java.text.DecimalFormat;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.slf4j.LoggerFactory;
/**
*
*
* @author Polina
*/
public class MagnetController implements PortHandler.PortController {
public static double CURRENT_PRECISION = 0.01;
// public static double CURRENT_STEP = 0.05;
public static int DEFAULT_DELAY = 1;
public static int DEFAULT_MONITOR_DELAY = 2000;
public static double MAX_STEP_SIZE = 0.2;
public static double MIN_UP_STEP_SIZE = 0.005;
public static double MIN_DOWN_STEP_SIZE = 0.05;
public static double MAX_SPEED = 5d; // 5 A per minute
private static final DecimalFormat LAMBDAformat = new DecimalFormat("###.##");
/**
* Method converts double to LAMBDA string
*
* @param d double that should be converted to string
* @return string
*/
private static String d2s(double d) {
return LAMBDAformat.format(d);
}
private final String name;
private final PortHandler port;
private final int address;
private volatile double current = 0;
private int timeout = 200;
private Future monitorTask;
private Future updateTask;
protected MagnetStateListener listener;
private Instant lastUpdate = null;
private double speed = MAX_SPEED;
private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
/**
* This method creates an element of class MegnetController with exact
* parameters. If you have two parameters for your method - the next
* constructor will be used.
*
* @param name
* @param port number of COM-port on your computer that you want to use
* @param address number of TDK - Lambda
* @param timeout waiting time for response
*/
public MagnetController(String name, PortHandler port, int address, int timeout) {
this.name = name;
this.port = port;
this.port.setDelimeter("\r");//PENDING меняем состояние внешнего объекта?
this.address = address;
this.timeout = timeout;
}
public MagnetController(PortHandler port, int address, int timeout) {
this(null, port, address, timeout);
}
public MagnetController(PortHandler port, int address) {
this(null, port, address);
}
public MagnetController(String name, PortHandler port, int address) {
this(name, port, address, 300);
}
public void setListener(MagnetStateListener listener) {
this.listener = listener;
}
public double getMeasuredI() {
return current;
}
@Override
public void accept(String message) {
}
@Override
public void error(String errorMessage, Throwable error) {
if (this.listener != null) {
listener.error(getName(), errorMessage, error);
} else {
LoggerFactory.getLogger(getClass()).error(errorMessage, error);
}
}
private String talk(String request) throws PortException {
try {
return port.sendAndWait(request + "\r", null, timeout).trim();
} catch (PortTimeoutException tex) {
//Single retry on timeout
LoggerFactory.getLogger(getClass()).warn("A timeout exception for request '" + request + "'. Making another atempt.");
return port.sendAndWait(request + "\r", null, timeout).trim();
}
}
private String getState(String name) throws PortException {
String res = talk(name + "?");
return res;
}
private boolean setState(String name, String state) throws PortException {
String res = talk(name + " " + state);
return "OK".equals(res);
}
private boolean setState(String name, int state) throws PortException {
String res = talk(name + " " + state);
return "OK".equals(res);
}
private boolean setState(String name, double state) throws PortException {
String res = talk(name + " " + d2s(state));
return "OK".equals(res);
}
/**
* Extract number from LAMBDA response
*
* @param str
* @return
*/
private double s2d(String str) {
return Double.valueOf(str);
}
private double getCurrent() throws PortException {
if (!setADR()) {
if (listener != null) {
listener.error(getName(), "Can't set address", null);
}
throw new PortException("Can't set address");
}
return s2d(getState("MC"));
}
protected void setCurrent(double current) throws PortException {
if (!setState("PC", current)) {
error("Can't set the current", null);
} else {
lastUpdate = Instant.now();
}
}
private boolean setADR() throws PortException {
if (setState("ADR", getAddress())) {
if (listener != null) {
listener.addressChanged(getName(), address);
}
return true;
} else {
return false;
}
}
/**
* Gets status of magnet for current moment
*
* @return status of magnet
* @throws inr.numass.control.magnet.PortException
*/
private MagnetStatus getStatus() throws PortException {
try {
port.holdBy(MagnetController.this);
if (!setADR()) {
return MagnetStatus.off();
}
boolean out;
out = "ON".equals(talk("OUT?"));
double measuredCurrent = s2d(getState("MC"));
this.current = measuredCurrent;
double setCurrent = s2d(getState("PC"));
double measuredVoltage = s2d(getState("MV"));
double setVoltage = s2d(getState("PV"));
MagnetStatus monitor = new MagnetStatus(out, measuredCurrent, setCurrent, measuredVoltage, setVoltage);
if (listener != null) {
listener.acceptStatus(getName(), monitor);
}
return monitor;
} finally {
port.unholdBy(MagnetController.this);
}
}
/**
* Cancel current update task
*/
public void stopUpdateTask() {
if (updateTask != null) {
updateTask.cancel(false);
lastUpdate = null;
if (listener != null) {
listener.updateTaskStateChanged(getName(), false);
}
}
}
public void startUpdateTask(double targetI) {
startUpdateTask(targetI, DEFAULT_DELAY);
}
/**
* Start recursive updates of current with given delays between updates. If
* delay is 0 then updates are made immediately.
*
* @param targetI
* @param delay
*/
public void startUpdateTask(double targetI, int delay) {
assert delay > 0;
stopUpdateTask();
Runnable call = () -> {
try {
port.holdBy(MagnetController.this);
double measuredI = getCurrent();
this.current = measuredI;
if (listener != null) {
listener.acceptMeasuredI(getName(), measuredI);
}
if (Math.abs(measuredI - targetI) > CURRENT_PRECISION) {
double nextI = nextI(measuredI, targetI);
if (listener != null) {
listener.acceptNextI(getName(), nextI);
}
setCurrent(nextI);
} else {
stopUpdateTask();
}
} catch (PortException ex) {
error("Error in update task", ex);
stopUpdateTask();
} finally {
port.unholdBy(MagnetController.this);
}
};
updateTask = scheduler.scheduleWithFixedDelay(call, 0, delay, TimeUnit.MILLISECONDS);
if (listener != null) {
listener.updateTaskStateChanged(getName(), true);
}
}
public void setOutputMode(boolean out) throws PortException {
try {
port.holdBy(MagnetController.this);
if (!setADR()) {
throw new RuntimeException();
}
int outState;
if (out) {
outState = 1;
} else {
outState = 0;
}
if (!setState("OUT", outState)) {
if (listener != null) {
listener.error(getName(), "Can't set output mode", null);
}
} else if (listener != null) {
listener.outputModeChanged(getName(), out);
}
} finally {
port.unholdBy(MagnetController.this);
}
}
private double nextI(double measuredI, double targetI) {
assert measuredI != targetI;
double step;
if (lastUpdate == null) {
step = MIN_UP_STEP_SIZE;
} else {
//Choose optimal speed but do not exceed maximum speed
step = Math.min(MAX_STEP_SIZE,
(double) lastUpdate.until(Instant.now(), ChronoUnit.MILLIS) / 60000d * getSpeed());
}
double res;
if (targetI > measuredI) {
step = Math.max(MIN_UP_STEP_SIZE, step);
res = Math.min(targetI, measuredI + step);
} else {
step = Math.max(MIN_DOWN_STEP_SIZE, step);
res = Math.max(targetI, measuredI - step);
}
// не вводится ток меньше 0.5
if (res < 0.5 && targetI > CURRENT_PRECISION) {
return 0.5;
} else if (res < 0.5 && targetI < CURRENT_PRECISION) {
return 0;
} else {
return res;
}
}
/**
* Cancel current monitoring task
*/
public void stopMonitorTask() {
if (monitorTask != null) {
monitorTask.cancel(false);
if (listener != null) {
listener.monitorTaskStateChanged(getName(), false);
}
}
}
public String getName() {
if (this.name == null || this.name.isEmpty()) {
return "LAMBDA " + getAddress();
} else {
return this.name;
}
}
public void startMonitorTask() {
startMonitorTask(DEFAULT_MONITOR_DELAY);
}
/**
* Start monitoring task which checks for magnet status and then waits for
* fixed time.
*
* @param delay an interval between scans in milliseconds
*/
public void startMonitorTask(int delay) {
assert delay >= 1000;
stopMonitorTask();
Runnable call = () -> {
try {
getStatus();
} catch (PortException ex) {
error("Port connection exception during status measurement", ex);
stopMonitorTask();
}
};
monitorTask = scheduler.scheduleWithFixedDelay(call, 0, delay, TimeUnit.MILLISECONDS);
if (listener != null) {
listener.monitorTaskStateChanged(getName(), true);
}
}
public String request(String message) {
try {
port.holdBy(this);
try {
if (!setADR()) {
throw new Error();
}
return talk(message);
} finally {
port.unholdBy(this);
}
} catch (PortException ex) {
error("Can not send message to the port", ex);
return null;
}
}
/**
* @return the address
*/
public int getAddress() {
return address;
}
/**
* Get current change speed in Amper per minute
*
* @return
*/
public double getSpeed() {
return speed;
}
/**
* Set current change speed in Amper per minute
*
* @param speed
*/
public void setSpeed(double speed) {
this.speed = speed;
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.magnet;
/**
*
* @author Alexander Nozik
*/
public interface MagnetStateListener {
void acceptStatus(String name, MagnetStatus state);
void acceptNextI(String name, double nextI);
void acceptMeasuredI(String name, double measuredI);
default void displayState(String state){
}
default void error(String name, String errorMessage, Throwable throwable){
throw new RuntimeException(errorMessage, throwable);
}
default void monitorTaskStateChanged(String name, boolean monitorTaskRunning) {
}
default void updateTaskStateChanged(String name, boolean updateTaskRunning) {
}
default void outputModeChanged(String name, boolean out) {
}
default void addressChanged(String name, int address) {
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.magnet;
/**
*
* @author Polina
*/
public class MagnetStatus {
private boolean on;
private final boolean out;
private final double measuredCurrent;
private final double setCurrent;
private final double measuredVoltage;
private final double setVoltage;
public MagnetStatus(boolean isOut, double measuredCurrent, double setCurrent, double measuredVoltage, double setVoltage) {
this.on = true;
this.out = isOut;
this.measuredCurrent = measuredCurrent;
this.setCurrent = setCurrent;
this.measuredVoltage = measuredVoltage;
this.setVoltage = setVoltage;
}
public static MagnetStatus off() {
MagnetStatus res = new MagnetStatus(false, 0, 0, 0, 0);
res.on = false;
return res;
}
/**
* @return the isOn
*/
public boolean isOn() {
return on;
}
/**
* @return the isOut
*/
public boolean isOutputOn() {
return out;
}
/**
* @return the measuredCurrent
*/
public double getMeasuredCurrent() {
return measuredCurrent;
}
/**
* @return the setCurrent
*/
public double getSetCurrent() {
return setCurrent;
}
/**
* @return the measuredVoltage
*/
public double getMeasuredVoltage() {
return measuredVoltage;
}
/**
* @return the setVoltage
*/
public double getSetVoltage() {
return setVoltage;
}
}

View File

@ -0,0 +1,101 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.magnet;
import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.exceptions.PortException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
import org.slf4j.LoggerFactory;
/**
*
* @author Polina
*/
public class SafeMagnetController extends MagnetController {
private final Set<SafeMagnetCondition> safeConditions = new HashSet<>();
public SafeMagnetController(String name, PortHandler port, int address, int timeout, SafeMagnetCondition... safeConditions) {
super(name, port, address, timeout);
this.safeConditions.addAll(Arrays.asList(safeConditions));
}
public SafeMagnetController(String name, PortHandler port, int address, SafeMagnetCondition... safeConditions) {
super(name, port, address);
this.safeConditions.addAll(Arrays.asList(safeConditions));
}
public void addSafeCondition(Predicate<Double> condition, boolean isBlocking){
this.safeConditions.add(new SafeMagnetCondition() {
@Override
public boolean isSafe(int address, double current) {
return condition.test(current);
}
@Override
public boolean isBloking() {
return isBlocking;
}
});
}
/**
* Add symmetric non-blocking conditions to ensure currents in two magnets have difference within given tolerance.
* @param controller
* @param tolerance
*/
public void bindTo(SafeMagnetController controller, double tolerance){
this.addSafeCondition((I)->Math.abs(controller.getMeasuredI() - I) <= tolerance, false);
controller.addSafeCondition((I)->Math.abs(this.getMeasuredI() - I) <= tolerance, false);
}
@Override
protected void setCurrent(double current) throws PortException {
for (SafeMagnetCondition condition : safeConditions) {
if (!condition.isSafe(getAddress(), current)) {
if (condition.isBloking()) {
condition.onFail();
throw new RuntimeException("Can't set current. Condition not satisfied.");
} else {
if(listener!= null){
listener.displayState("BOUND");
}
return;
}
}
}
super.setCurrent(current);
}
public static interface SafeMagnetCondition {
boolean isSafe(int address, double current);
default boolean isBloking() {
return true;
}
default void onFail() {
LoggerFactory.getLogger(getClass()).error("Can't set current. Condition not satisfied.");
}
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.magnet;
import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.control.ports.ComPortHandler;
import jssc.SerialPortException;
/**
*
* @author Alexander Nozik
*/
public class SetCurrent {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws SerialPortException {
if (args.length < 3) {
throw new IllegalArgumentException("Wrong number of parameters");
}
String comName = args[0];
int lambdaaddress = Integer.valueOf(args[1]);
double current = Double.valueOf(args[2]);
PortHandler handler = new ComPortHandler(comName);
MagnetController controller = new MagnetController(handler, lambdaaddress);
controller.startUpdateTask(current, 500);
}
}

View File

@ -0,0 +1,75 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.magnet;
import ch.qos.logback.classic.Level;
import hep.dataforge.control.ports.PortFactory;
import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.exceptions.PortException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.time.Duration;
import java.time.Instant;
import java.util.Locale;
import org.slf4j.LoggerFactory;
/**
*
* @author Alexander Nozik
*/
public class Talk {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws Exception {
Locale.setDefault(Locale.US);
ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
rootLogger.setLevel(Level.INFO);
String portName = "/dev/ttyr00";
if (args.length > 0) {
portName = args[0];
}
PortHandler handler;
handler = PortFactory.buildPort(portName);
handler.setPhraseCondition((String str) -> str.endsWith("\r"));
// MagnetController controller = new MagnetController(handler, 1);
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.printf("INPUT > ");
String nextString = reader.readLine();
while (!"exit".equals(nextString)) {
try {
Instant start = Instant.now();
String answer = handler.sendAndWait(nextString + "\r", null, 1000);
//String answer = controller.request(nextString);
System.out.printf("ANSWER (latency = %s): %s;%n", Duration.between(start, Instant.now()), answer.trim());
} catch (PortException ex) {
ex.printStackTrace();
}
System.out.printf("INPUT > ");
nextString = reader.readLine();
}
handler.close();
}
}

View File

@ -0,0 +1,91 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.magnet;
import hep.dataforge.control.ports.PortHandler;
import java.util.Locale;
/**
*
* @author Alexander Nozik
*/
public class TestController {
/**
* @param args the command line arguments
* @throws java.lang.Exception
*/
public static void main(String[] args) throws Exception {
Locale.setDefault(Locale.US);// чтобы отделение десятичных знаков было точкой
// ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
// rootLogger.setLevel(Level.INFO);
PortHandler handler;
MagnetController firstController;
MagnetController secondController;
// String comName = "COM12";
// handler = new ComPortHandler(comName);
handler = new VirtualLambdaPort("COM12", 1, 2, 3, 4);
firstController = new MagnetController(handler, 1);
// secondController = new MagnetController(handler, 4);
secondController = new SafeMagnetController("TEST", handler, 4, (int address, double current) -> current < 1.0);
MagnetStateListener listener = new MagnetStateListener() {
@Override
public void acceptStatus(String name, MagnetStatus state) {
System.out.printf("%s (%s): Im = %f, Um = %f, Is = %f, Us = %f;%n",
name,
state.isOutputOn(),
state.getMeasuredCurrent(),
state.getMeasuredVoltage(),
state.getSetCurrent(),
state.getSetVoltage()
);
}
@Override
public void acceptNextI(String name, double nextI) {
System.out.printf("%s: nextI = %f;%n", name, nextI);
}
@Override
public void acceptMeasuredI(String name, double measuredI) {
System.out.printf("%s: measuredI = %f;%n", name, measuredI);
}
};
firstController.setListener(listener);
secondController.setListener(listener);
try {
firstController.startMonitorTask(2000);
secondController.startMonitorTask(2000);
secondController.setOutputMode(true);
secondController.startUpdateTask(2.0, 1000);
System.in.read();
firstController.stopMonitorTask();
secondController.stopMonitorTask();
secondController.stopUpdateTask();
secondController.setOutputMode(false);
} finally {
// handler.close();
}
}
}

View File

@ -0,0 +1,117 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.magnet;
import ch.qos.logback.classic.Level;
import hep.dataforge.control.ports.PortHandler;
import java.util.Locale;
import org.slf4j.LoggerFactory;
/**
*
* @author Alexander Nozik
*/
public class TestSynch {
private static double firstCurrent = 0;
/**
* @param args the command line arguments
* @throws java.lang.Exception
*/
public static void main(String[] args) throws Exception {
Locale.setDefault(Locale.US);// чтобы отделение десятичных знаков было точкой
ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
rootLogger.setLevel(Level.INFO);
PortHandler handler;
MagnetController firstController;
MagnetController secondController;
// String comName = "COM12";
// handler = new ComPortHandler(comName);
handler = new VirtualLambdaPort("COM12", 1, 2, 3, 4);
firstController = new MagnetController(handler, 1);
// secondController = new MagnetController(handler, 2);
secondController = new SafeMagnetController("TEST", handler, 2,
new SafeMagnetController.SafeMagnetCondition() {
// @Override
// public boolean isBloking() {
// return false;
// }
@Override
public void onFail() {
java.awt.Toolkit.getDefaultToolkit().beep();
}
@Override
public boolean isSafe(int address, double current) {
return Math.abs(current - firstCurrent) <= 0.2;
}
});
MagnetStateListener listener = new MagnetStateListener() {
@Override
public void acceptStatus(String name, MagnetStatus state) {
System.out.printf("%s (%s): Im = %f, Um = %f, Is = %f, Us = %f;%n",
name,
state.isOutputOn(),
state.getMeasuredCurrent(),
state.getMeasuredVoltage(),
state.getSetCurrent(),
state.getSetVoltage()
);
}
@Override
public void acceptNextI(String name, double nextI) {
System.out.printf("%s: nextI = %f;%n", name, nextI);
}
@Override
public void acceptMeasuredI(String name, double measuredI) {
System.out.printf("%s: measuredI = %f;%n", name, measuredI);
}
};
firstController.setListener(listener);
secondController.setListener(listener);
try {
firstController.startMonitorTask(2000);
secondController.startMonitorTask(2000);
secondController.setOutputMode(true);
firstController.setOutputMode(true);
firstController.startUpdateTask(1.0, 10);
secondController.startUpdateTask(2.0, 10);
System.in.read();
firstController.stopMonitorTask();
secondController.stopMonitorTask();
secondController.stopUpdateTask();
firstController.stopUpdateTask();
secondController.setOutputMode(false);
firstController.setOutputMode(false);
System.exit(0);
} finally {
// handler.close();
}
}
}

View File

@ -0,0 +1,180 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.magnet;
import hep.dataforge.meta.Meta;
import hep.dataforge.control.ports.VirtualPort;
import hep.dataforge.exceptions.PortException;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.LoggerFactory;
/**
*
* @author Alexander Nozik
*/
public class VirtualLambdaPort extends VirtualPort {
private static final Duration latency = Duration.ofMillis(50);
private volatile int currentAddress = -1;
private Map<Integer, VirtualMagnetStatus> magnets = new HashMap<>();
public VirtualLambdaPort(String portName, Map<Integer, Double> magnets) {
super(portName);
magnets.entrySet().stream().forEach((entry) -> {
this.magnets.put(entry.getKey(), new VirtualMagnetStatus(entry.getValue()));
});
}
public VirtualLambdaPort(String portName, int... magnets) {
super(portName);
for (int magnet : magnets) {
this.magnets.put(magnet, new VirtualMagnetStatus(0.01));
}
}
@Override
protected void evaluateRequest(String request) {
String comand;
String value = "";
String[] split = request.split(" ");
if (split.length == 1) {
comand = request;
} else {
comand = split[0];
value = split[1];
}
try {
evaluateRequest(comand.trim(), value.trim());
} catch (RuntimeException ex) {
recievePhrase("FAIL");//TODO какая команда правильная?
LoggerFactory.getLogger(getClass()).error("Request evaluation failure", ex);
}
}
private void sendOK() {
planResponse("OK", latency);
}
private void evaluateRequest(String comand, String value) {
switch (comand) {
case "ADR":
int address = Integer.parseInt(value);
if (magnets.containsKey(address)) {
currentAddress = address;
sendOK();
}
return;
case "ADR?":
planResponse(Integer.toString(currentAddress), latency);
return;
case "OUT":
int state = Integer.parseInt(value);
currentMagnet().out = (state == 1);
sendOK();
return;
case "OUT?":
boolean out = currentMagnet().out;
if (out) {
planResponse("ON", latency);
} else {
planResponse("OFF", latency);
}
return;
case "PC":
double current = Double.parseDouble(value);
if (current < 0.5) {
current = 0;
}
currentMagnet().current = current;
sendOK();
return;
case "PC?":
planResponse(Double.toString(currentMagnet().current), latency);
return;
case "MC?":
planResponse(Double.toString(currentMagnet().current), latency);
return;
case "PV?":
planResponse(Double.toString(currentMagnet().voltage()), latency);
return;
case "MV?":
planResponse(Double.toString(currentMagnet().voltage()), latency);
return;
default:
LoggerFactory.getLogger(getClass()).warn("Unknown comand {}", comand);
}
}
private VirtualMagnetStatus currentMagnet() {
if (currentAddress < 0) {
throw new RuntimeException();
}
return magnets.get(currentAddress);
}
@Override
public void close() throws Exception {
}
@Override
public void open() throws PortException {
}
@Override
public boolean isOpen() {
return true;
}
@Override
public Meta meta() {
return Meta.buildEmpty("virtualPort");
}
private class VirtualMagnetStatus {
public VirtualMagnetStatus(double resistance) {
this.resistance = resistance;
this.on = true;
this.out = false;
this.current = 0;
}
public VirtualMagnetStatus(double resistance, boolean on, boolean out, double current) {
this.resistance = resistance;
this.on = on;
this.out = out;
this.current = current;
}
private final double resistance;
private boolean on;
private boolean out;
private double current;
public double voltage() {
return current * resistance;
}
}
}

View File

@ -0,0 +1,137 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.magnet.fx;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.FileAppender;
import hep.dataforge.control.ports.PortFactory;
import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.exceptions.ControlException;
import inr.numass.control.magnet.MagnetController;
import inr.numass.control.magnet.SafeMagnetController;
import inr.numass.control.magnet.VirtualLambdaPort;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.slf4j.ILoggerFactory;
import org.slf4j.LoggerFactory;
/**
*
* @author Alexander Nozik
*/
public class MagnetControllerApp extends Application {
PortHandler handler;
SafeMagnetController sourceController;
SafeMagnetController pinchController;
SafeMagnetController conusController;
SafeMagnetController detectorController;
List<SafeMagnetController> controllers = new ArrayList<>();
@Override
public void start(Stage primaryStage) throws IOException, ControlException {
Locale.setDefault(Locale.US);// чтобы отделение десятичных знаков было точкой
ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
String logLevel = getParameters().getNamed().getOrDefault("logLevel","INFO");
rootLogger.setLevel(Level.valueOf(logLevel));
String logFile = getParameters().getNamed().get("logFile");
if(logFile!=null){
FileAppender<ILoggingEvent> appender = new FileAppender<>();
appender.setFile(logFile);
appender.setContext(rootLogger.getLoggerContext());
appender.start();
rootLogger.addAppender(appender);
}
String portName = getParameters().getNamed().getOrDefault("port","virtual");
if(portName.equals("virtual")){
handler = new VirtualLambdaPort("COM12", 1, 2, 3, 4);
} else {
handler = PortFactory.buildPort(portName);
//TODO add meta reader here
}
sourceController = new SafeMagnetController("SOURCE", handler, 1);
pinchController = new SafeMagnetController("PINCH", handler, 2);
conusController = new SafeMagnetController("CONUS", handler, 3);
detectorController = new SafeMagnetController("DETECTOR", handler, 4);
conusController.bindTo(pinchController, 30.0);
controllers.add(sourceController);
sourceController.setSpeed(4d);
controllers.add(pinchController);
controllers.add(conusController);
controllers.add(detectorController);
boolean showConfirmation = Boolean.parseBoolean(getParameters().getNamed().getOrDefault("confirmOut","false"));
VBox vbox = new VBox(5);
double height = 0;
double width = 0;
for (MagnetController controller : controllers) {
MagnetControllerComponent comp = MagnetControllerComponent.build(controller);
width = Math.max(width, comp.getPrefWidth());
height += comp.getPrefHeight()+5;
if(!showConfirmation){
comp.setShowConfirmation(showConfirmation);
}
vbox.getChildren().add(comp);
}
Scene scene = new Scene(vbox, width, height);
primaryStage.setTitle("Numass magnet view");
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
}
@Override
public void stop() throws Exception {
super.stop(); //To change body of generated methods, choose Tools | Templates.
for (MagnetController magnet : controllers) {
magnet.stopMonitorTask();
magnet.stopUpdateTask();
}
if(handler.isOpen()){
handler.close();
}
System.exit(0);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}

View File

@ -0,0 +1,300 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.magnet.fx;
import hep.dataforge.exceptions.PortException;
import inr.numass.control.magnet.MagnetController;
import inr.numass.control.magnet.MagnetStateListener;
import inr.numass.control.magnet.MagnetStatus;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* FXML Controller class
*
* @author Alexander Nozik
*/
public class MagnetControllerComponent extends AnchorPane implements Initializable, MagnetStateListener {
private MagnetController magnetController;
private Logger logger;
private boolean showConfirmation = true;
public static MagnetControllerComponent build(MagnetController magnetController) {
MagnetControllerComponent component = new MagnetControllerComponent();
FXMLLoader loader = new FXMLLoader(magnetController.getClass().getResource("/fxml/SingleMagnet.fxml"));
loader.setRoot(component);
loader.setController(component);
try {
loader.load();
} catch (Exception ex) {
LoggerFactory.getLogger("FX").error("Error during fxml initialization", ex);
throw new Error(ex);
}
component.setMagnetController(magnetController);
return component;
}
@FXML
private Label labelI;
@FXML
private Label labelU;
@FXML
private TextField targetIField;
@FXML
private Label magnetName;
@FXML
private ToggleButton monitorButton;
@FXML
private Label statusLabel;
@FXML
private ToggleButton setButton;
@FXML
private TextField magnetSpeedField;
// public MagnetControllerComponent(MagnetController magnetController) {
// FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/SingleMagnet.fxml"));
//
// loader.setRoot(this);
// loader.setController(this);
//
// try {
// loader.load();
// } catch (IOException ex) {
// throw new RuntimeException(ex);
// }
// setMagnetController(magnetController);
// }
/**
* Initializes the controller class.
*
* @param url
* @param rb
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
targetIField.textProperty().addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
if (!newValue.matches("\\d*(\\.)?\\d*")) {
targetIField.setText(oldValue);
}
});
magnetSpeedField.textProperty().addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
if (!newValue.matches("\\d*(\\.)?\\d*")) {
magnetSpeedField.setText(oldValue);
}
});
}
public void setShowConfirmation(boolean showConfirmation) {
this.showConfirmation = showConfirmation;
}
@FXML
private void onOutToggle(ActionEvent event) {
try {
setOutput(setButton.isSelected());
} catch (PortException ex) {
error(this.magnetController.getName(), null, ex);
}
}
private double getTargetI() {
return Double.parseDouble(targetIField.getText());
}
private void setOutput(boolean outputOn) throws PortException {
if (outputOn) {
if (showConfirmation) {
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setContentText("Изменение токов в сверхпроводящих магнитах можно производить только при выключенном напряжении на спектрометре."
+ "\nВы уверены что напряжение выключено?");
alert.setHeaderText("Проверьте напряжение на спектрометре!");
alert.setHeight(150);
alert.setTitle("Внимание!");
alert.getButtonTypes().clear();
alert.getButtonTypes().addAll(ButtonType.YES, ButtonType.CANCEL);
if (alert.showAndWait().orElse(ButtonType.CANCEL).equals(ButtonType.YES)) {
startCurrentChange();
} else {
setButton.setSelected(false);
}
} else {
startCurrentChange();
}
} else {
getMagnetController().stopUpdateTask();
targetIField.setDisable(false);
magnetSpeedField.setDisable(false);
}
}
private void startCurrentChange() throws PortException {
double speed = Double.parseDouble(magnetSpeedField.getText());
if (speed > 0 && speed <= 7) {
magnetController.setSpeed(speed);
magnetSpeedField.setDisable(true);
getMagnetController().setOutputMode(true);
getMagnetController().startUpdateTask(getTargetI());
} else {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setContentText(null);
alert.setHeaderText("Недопустимое значение скорости изменения тока");
alert.setTitle("Ошибка!");
alert.show();
setButton.setSelected(false);
magnetSpeedField.setText(Double.toString(magnetController.getSpeed()));
}
}
@FXML
private void onMonitorToggle(ActionEvent event) {
if (monitorButton.isSelected()) {
getMagnetController().startMonitorTask();
} else {
getMagnetController().stopMonitorTask();
this.labelU.setText("----");
}
}
@Override
public void error(String name, String errorMessage, Throwable throwable) {
Platform.runLater(() -> {
this.statusLabel.setText("ERROR");
this.statusLabel.setTextFill(Color.RED);
});
this.logger.error("ERROR: {}", errorMessage, throwable);
// MagnetStateListener.super.error(address, errorMessage, throwable); //To change body of generated methods, choose Tools | Templates.
}
/**
* @return the magnetController
*/
public MagnetController getMagnetController() {
if (magnetController == null) {
throw new RuntimeException("Magnet controller not defined");
}
return magnetController;
}
/**
* @param magnetController the magnetController to set
*/
private void setMagnetController(MagnetController magnetController) {
this.magnetController = magnetController;
logger = LoggerFactory.getLogger("lambda." + magnetController.getName());
magnetController.setListener(this);
magnetName.setText(magnetController.getName());
magnetSpeedField.setText(Double.toString(this.magnetController.getSpeed()));
}
@Override
public void acceptStatus(String name, MagnetStatus state) {
Platform.runLater(() -> {
this.labelI.setText(Double.toString(state.getMeasuredCurrent()));
this.labelU.setText(Double.toString(state.getMeasuredVoltage()));
outputModeChanged(name, state.isOutputOn());
getLogger().info(String.format("%s (%s): Im = %f, Um = %f, Is = %f, Us = %f;",
name,
state.isOutputOn(),
state.getMeasuredCurrent(),
state.getMeasuredVoltage(),
state.getSetCurrent(),
state.getSetVoltage()
));
});
}
@Override
public void acceptNextI(String name, double nextI) {
getLogger().debug("{}: nextI = {};", name, nextI);
}
@Override
public void acceptMeasuredI(String name, double measuredI) {
getLogger().debug("{}: measuredI = {};", name, measuredI);
Platform.runLater(() -> {
this.labelI.setText(Double.toString(measuredI));
});
}
@Override
public void outputModeChanged(String name, boolean out) {
Platform.runLater(() -> {
if (out) {
this.statusLabel.setText("OK");
this.statusLabel.setTextFill(Color.BLUE);
} else {
this.statusLabel.setText("OFF");
this.statusLabel.setTextFill(Color.BLACK);
}
});
}
@Override
public void updateTaskStateChanged(String name, boolean updateTaskRunning) {
this.setButton.setSelected(updateTaskRunning);
targetIField.setDisable(updateTaskRunning);
}
@Override
public void monitorTaskStateChanged(String name, boolean monitorTaskRunning) {
this.monitorButton.setScaleShape(monitorTaskRunning);
}
/**
* @return the logger
*/
public Logger getLogger() {
return logger;
}
// /**
// * @param logger the logger to set
// */
// public void setLogger(PrintStream logger) {
// this.logger = logger;
// }
@Override
public void displayState(String state) {
Platform.runLater(() -> this.statusLabel.setText(state));
}
}

View File

@ -0,0 +1,22 @@
/*
* 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.control.magnet.fx;
/**
*
* @author darksnake
*/
public class TestApp {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
MagnetControllerApp.main(new String[]{"--port=192.168.111.31:4001"});
//MagnetControllerApp.main(new String[]{"--port=192.168.111.31:4001", "--logLevel=DEBUG"});
}
}

View File

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2015 Alexander Nozik.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?import javafx.scene.text.*?>
<?import javafx.scene.shape.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<fx:root id="SingleMagnetPanel" minHeight="-Infinity" minWidth="-Infinity" prefHeight="175.0" prefWidth="280.0" type="AnchorPane" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
<children>
<VBox prefHeight="175.0" prefWidth="270.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<HBox alignment="CENTER" style="-fx-background-color: LIGHTGREEN;">
<children>
<Label fx:id="magnetName" alignment="CENTER" contentDisplay="CENTER" layoutX="74.0" prefHeight="28.0" prefWidth="167.0" text="Name">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Label>
</children>
</HBox>
<Separator prefWidth="200.0" />
<Pane prefHeight="35.0" prefWidth="250.0">
<children>
<Label layoutX="14.0" layoutY="8.0" text="Status:">
<font>
<Font size="14.0" />
</font>
</Label>
<Label fx:id="statusLabel" alignment="CENTER" layoutX="67.0" layoutY="4.0" prefHeight="27.0" prefWidth="80.0" text="INIT" textFill="GRAY">
<font>
<Font name="System Bold" size="18.0" />
</font>
</Label>
<TextField fx:id="magnetSpeedField" layoutX="173.0" layoutY="4.0" prefHeight="26.0" prefWidth="49.0" />
<Label layoutX="230.0" layoutY="9.0" text="A/min" />
</children>
</Pane>
<Separator prefWidth="200.0" />
<HBox prefHeight="50.0" prefWidth="250.0">
<children>
<Pane prefHeight="50.0" prefWidth="135.0" style="-fx-border-color: RED; -fx-border-radius: 6;">
<children>
<Label layoutX="14.0" layoutY="13.0" text="I">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
<Label fx:id="labelI" alignment="CENTER_RIGHT" layoutX="40.0" layoutY="13.0" prefHeight="25.0" prefWidth="80.0" text="?" textFill="RED">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
</children>
<HBox.margin>
<Insets />
</HBox.margin>
</Pane>
<Separator orientation="VERTICAL" prefHeight="200.0">
<padding>
<Insets right="1.0" />
</padding>
</Separator>
<Pane layoutX="10.0" layoutY="10.0" prefHeight="50.0" prefWidth="135.0" style="-fx-border-color: BLUE; -fx-border-radius: 6;">
<children>
<Label layoutX="14.0" layoutY="13.0" text="U">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
<Label fx:id="labelU" alignment="CENTER_RIGHT" layoutX="40.0" layoutY="13.0" prefHeight="25.0" prefWidth="80.0" text="?" textAlignment="JUSTIFY" textFill="BLUE">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
</children>
<HBox.margin>
<Insets />
</HBox.margin>
</Pane>
</children>
</HBox>
<Separator prefWidth="200.0" />
<Pane prefHeight="50.0" prefWidth="250.0" style="-fx-border-color: GREEN; -fx-border-radius: 6;">
<children>
<Label layoutX="9.0" layoutY="15.0" text="I target">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
<TextField fx:id="targetIField" layoutX="83.0" layoutY="13.0" prefHeight="25.0" prefWidth="55.0" text="0.0" />
<ToggleButton fx:id="setButton" layoutX="160.0" layoutY="13.0" mnemonicParsing="false" onAction="#onOutToggle" text="Set" />
<ToggleButton fx:id="monitorButton" contentDisplay="RIGHT" layoutX="199.0" layoutY="13.0" mnemonicParsing="false" onAction="#onMonitorToggle" prefHeight="26.0" prefWidth="70.0" text="Monitor" />
</children>
<VBox.margin>
<Insets />
</VBox.margin>
</Pane>
<Separator prefWidth="250.0" />
</children>
<padding>
<Insets bottom="1.0" left="1.0" right="1.0" top="1.0" />
</padding>
</VBox>
</children>
</fx:root>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="LAMBDA" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} %msg%n</pattern>
</encoder>
</appender>
<logger name="lambda" level="INFO" additivity="false">
<appender-ref ref="LAMBDA" />
</logger>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@ -0,0 +1,17 @@
apply plugin: 'application'
version = "0.2.2"
if (!hasProperty('mainClass')) {
ext.mainClass = 'inr.numass.control.msp.fx.MspApp'
}
mainClassName = mainClass
dependencies {
compile 'ch.qos.logback:logback-classic:1.1.0+'
compile 'org.scream3r:jssc:2.8.0'
compile project(':dataforge-plots')
compile project(':dataforge-storage')
compile project(':dataforge-control')
}

View File

@ -0,0 +1,446 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.msp;
import hep.dataforge.context.Context;
import hep.dataforge.context.GlobalContext;
import hep.dataforge.control.devices.DataDevice;
import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.control.ports.TcpPortHandler;
import hep.dataforge.data.DataFormat;
import hep.dataforge.data.DataFormatBuilder;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.exceptions.ControlException;
import hep.dataforge.exceptions.PortException;
import hep.dataforge.exceptions.StorageException;
import hep.dataforge.meta.Meta;
import hep.dataforge.storage.api.PointLoader;
import hep.dataforge.storage.api.Storage;
import hep.dataforge.storage.commons.LoaderFactory;
import hep.dataforge.storage.commons.StoragePlugin;
import hep.dataforge.storage.loaders.ChainPointLoader;
import java.time.Instant;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.ConcurrentSkipListMap;
import org.slf4j.LoggerFactory;
/**
*
* @author Alexander Nozik
*/
public class MspDevice extends DataDevice implements PortHandler.PortController {
// private static final String PEAK_SET_PATH = "peakJump.peak";
private static final int TIMEOUT = 200;
//storage
// /**
// * Separate storage configuration for backup storage.
// */
// private Meta backupStorage;
private PointLoader peakJumpLoader;
//port handler
private TcpPortHandler handler;
//listener
private MspListener mspListener;
private String sensorName = null;
private boolean isSelected = false;
private boolean isControlled = false;
private boolean isFilamentOn = false;
// private boolean isScanning = false;
private final Map<Integer, Double> measurement = new ConcurrentSkipListMap<>();
private Map<Integer, String> peakMap;
public MspDevice(String name, Meta annotation) {
super(name, GlobalContext.instance(), annotation);
}
public MspDevice(String name, Context context, Meta config) {
super(name, context, config);
}
@Override
public void init() throws ControlException {
super.init();
String ip = meta().getString("connection.ip", "127.0.0.1");
int port = meta().getInt("connection.port", 10014);
getLogger().info("Connection to MKS mass-spectrometer on {}:{}...", ip, port);
handler = new TcpPortHandler(ip, port, "msp");
handler.setDelimeter("\r\r");
}
/**
* Startup MSP: get available sensors, select sensor and control.
*
* @param measurement
* @throws hep.dataforge.exceptions.PortException
*/
@Override
public void doStart(Meta measurement) throws ControlException {
if (!isControlled) {
if (handler.isLocked()) {
LoggerFactory.getLogger(getClass()).error("Trying to init MSP controller on locked port. Breaking the lock.");
handler.breakHold();
}
handler.holdBy(this);
MspResponse response = sendAndWait("Sensors");
if (response.isOK()) {
this.sensorName = response.get(2, 1);
} else {
error(response.errorDescription(), null);
return;
}
//PENDING определеить в конфиге номер прибора
response = sendAndWait("Select", sensorName);
if (response.isOK()) {
this.isSelected = true;
} else {
error(response.errorDescription(), null);
return;
}
response = sendAndWait("Control", "inr.numass.msp", "1.0");
if (response.isOK()) {
this.isControlled = true;
} else {
error(response.errorDescription(), null);
}
}
createPeakJumpMeasurement(buildMeasurementLaminate(measurement).getNode("peakJump"));
this.peakJumpLoader = getPeakJumpLoader(measurement);
}
// public void setStorageConfig(Meta storageConfig, List<String> peaks) throws StorageException {
// Storage storage = getContext().provide("storage", StoragePlugin.class).buildStorage(storageConfig);
// String suffix = Integer.toString((int) Instant.now().toEpochMilli());
//
// this.peakJumpLoader = LoaderFactory.buildPointLoder(storage, "msp" + suffix, "", "timestamp", DataFormat.forNames(10, peaks));
// }
private PointLoader getPeakJumpLoader(Meta measurement) {
if (peakJumpLoader == null) {
try {
// StoragePlugin plugin = getContext().provide("storage", StoragePlugin.class);
Storage primaryStorage = getPrimaryStorage(measurement);
if (peakMap == null) {
throw new IllegalStateException("Peak map is not initialized");
}
DataFormatBuilder builder = new DataFormatBuilder().addTime("timestamp");
for (String peakName : this.peakMap.values()) {
builder.addNumber(peakName);
}
DataFormat format = builder.build();
//TODO Переделать!!!
String run = meta().getString("numass.run","");
String suffix = Integer.toString((int) Instant.now().toEpochMilli());
peakJumpLoader = LoaderFactory
.buildPointLoder(primaryStorage, "msp" + suffix, run, "timestamp", format);
try {
Storage secondaryStorage = getSecondaryStorage(measurement);
if (secondaryStorage != null) {
PointLoader backupLoader = LoaderFactory
.buildPointLoder(secondaryStorage, "msp" + suffix, run, "timestamp", format);
peakJumpLoader = new ChainPointLoader(peakJumpLoader, backupLoader);
}
} catch (Exception ex) {
getLogger().error("Failed to initialize backup peak jump loader", ex);
}
} catch (StorageException ex) {
getLogger().error("Failed to initialize primary peak jump loader", ex);
return null;
}
}
return peakJumpLoader;
}
public void setListener(MspListener listener) {
this.mspListener = listener;
}
private void send(String command, Object... parameters) throws PortException {
String request = buildCommand(command, parameters);
if (mspListener != null) {
mspListener.acceptRequest(request);
}
handler.send(request);
}
private String buildCommand(String command, Object... parameters) {
StringBuilder builder = new StringBuilder(command);
for (Object par : parameters) {
builder.append(String.format(" \"%s\"", par.toString()));
}
builder.append("\n");
return builder.toString();
}
/**
* Send specific command and wait for its results (the result must begin
* with command name)
*
* @param commandName
* @param paremeters
* @return
* @throws PortException
*/
public MspResponse sendAndWait(String commandName, Object... paremeters) throws PortException {
String request = buildCommand(commandName, paremeters);
if (mspListener != null) {
mspListener.acceptRequest(request);
}
String response = handler.sendAndWait(
request,
(String str) -> str.trim().startsWith(commandName),
TIMEOUT
);
return new MspResponse(response);
}
@Override
public synchronized void accept(String message) {
if (mspListener != null) {
mspListener.acceptMessage(message.trim());
}
MspResponse response = new MspResponse(message);
switch (response.getCommandName()) {
// all possible async messages
case "FilamentStatus":
String status = response.get(0, 2);
isFilamentOn = status.equals("ON");
if (this.mspListener != null) {
this.mspListener.acceptFillamentStateChange(status);
}
break;
case "MassReading":
double mass = Double.parseDouble(response.get(0, 1));
double value = Double.parseDouble(response.get(0, 2));
this.measurement.put((int) Math.floor(mass + 0.5), value);
break;
case "StartingScan":
if (this.mspListener != null && !measurement.isEmpty() && isFilamentOn) {
if (peakMap == null) {
throw new IllegalStateException("Peal map is not initialized");
}
mspListener.acceptMeasurement(measurement);
Instant time = Instant.now();
MapDataPoint point = new MapDataPoint();
point.putValue("timestamp", time);
for (Map.Entry<Integer, Double> entry : measurement.entrySet()) {
double val = entry.getValue();
point.putValue(peakMap.get(entry.getKey()), val);
}
if (peakJumpLoader != null) {
try {
peakJumpLoader.push(point);
} catch (StorageException ex) {
getLogger().error("Push to repo failed", ex);
}
}
}
measurement.clear();
int numScans = Integer.parseInt(response.get(0, 3));
if (numScans == 0) {
try {
send("ScanResume", 2);
//FIXME обработать ошибку связи
} catch (PortException ex) {
error(null, ex);
}
}
break;
}
}
public boolean isSelected() {
return isSelected;
}
public boolean isControlled() {
return isControlled;
}
public boolean isFilamentOn() {
return isFilamentOn;
}
// public boolean isIsScanning() {
// return isScanning;
// }
/**
* Turn filament on or off
*
* @return
*
* @param filamentOn
* @throws hep.dataforge.exceptions.PortException
*/
public boolean setFileamentOn(boolean filamentOn) throws PortException {
if (filamentOn) {
return sendAndWait("FilamentControl", "On").isOK();
} else {
return sendAndWait("FilamentControl", "Off").isOK();
}
}
/**
* Create measurement with parameters and return its name
*
* @param an
* @return
* @throws hep.dataforge.exceptions.PortException
*/
private void createPeakJumpMeasurement(Meta an) throws ControlException {
String name = "peakJump";//an.getString("measurementNAmname", "default");
String filterMode = an.getString("filterMode", "PeakAverage");
int accuracy = an.getInt("accuracy", 5);
//PENDING вставить остальные параметры?
sendAndWait("MeasurementRemove", name);
if (sendAndWait("AddPeakJump", name, filterMode, accuracy, 0, 0, 0).isOK()) {
peakMap = new LinkedHashMap<>();
for (Meta peak : an.getNodes("peak")) {
peakMap.put(peak.getInt("mass"), peak.getString("name", peak.getString("mass")));
if (!sendAndWait("MeasurementAddMass", peak.getString("mass")).isOK()) {
throw new ControlException("Can't add mass to measurement measurement for msp");
}
}
} else {
throw new ControlException("Can't create measurement for msp");
}
}
public boolean startPeakJumpMeasurement() throws PortException {
if (!isFilamentOn()) {
error("Can't start measurement. Filament is not turned on.", null);
}
if (!sendAndWait("ScanAdd", "peakJump").isOK()) {
return false;
}
return sendAndWait("ScanStart", 2).isOK();
}
public boolean stopMeasurement() throws PortException {
return sendAndWait("ScanStop").isOK();
}
@Override
public void doStop() throws PortException {
stopMeasurement();
setFileamentOn(false);
sendAndWait("Release");
handler.unholdBy(this);
handler.close();
}
@Override
public void error(String errorMessage, Throwable error) {
if (mspListener != null) {
mspListener.error(errorMessage, error);
} else {
if (error != null) {
throw new RuntimeException(error);
} else {
throw new RuntimeException(errorMessage);
}
}
}
/**
* The MKS response as two-dimensional array of strings
*/
public static class MspResponse {
private final List<List<String>> data = new ArrayList<>();
public MspResponse(String response) {
String rx = "[^\"\\s]+|\"(\\\\.|[^\\\\\"])*\"";
Scanner scanner = new Scanner(response.trim());
while (scanner.hasNextLine()) {
List<String> line = new ArrayList<>();
String next = scanner.findWithinHorizon(rx, 0);
while (next != null) {
line.add(next);
next = scanner.findInLine(rx);
}
data.add(line);
}
}
public String getCommandName() {
return this.get(0, 0);
}
public boolean isOK() {
return "OK".equals(this.get(0, 1));
}
public int errorCode() {
if (isOK()) {
return -1;
} else {
return Integer.parseInt(get(1, 1));
}
}
public String errorDescription() {
if (isOK()) {
return null;
} else {
return get(2, 1);
}
}
public String get(int lineNo, int columnNo) {
return data.get(lineNo).get(columnNo);
}
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.msp;
import java.util.Map;
/**
*
* @author darksnake
*/
public interface MspListener {
void error(String errorMessage, Throwable error);
void acceptMeasurement(Map<Integer, Double> point);
void acceptMessage(String message);
void acceptRequest(String message);
default void acceptFillamentStateChange(String fillamentState){
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.msp;
import hep.dataforge.exceptions.PortException;
import java.io.IOException;
/**
*
* @author darksnake
*/
public class MspTest {
/**
* @param args the command line arguments
* @throws hep.dataforge.exceptions.PortException
*/
public static void main(String[] args) throws PortException, IOException, InterruptedException {
// Locale.setDefault(Locale.US);// чтобы отделение десятичных знаков было точкой
// ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
// rootLogger.setLevel(Level.INFO);
//
// MspListener listener = new MspListener() {
//
// @Override
// public void acceptMeasurement(Map<Double, Double> measurement) {
// final StringBuilder mesString = new StringBuilder("[");
// measurement.forEach((Double key, Double value) -> mesString.append(String.format("%g:%g,", key, value)));
// mesString.deleteCharAt(mesString.length() - 1);
// mesString.append("]");
// System.out.println("MEASUREMENT: " + mesString);
// }
//
// @Override
// public void acceptMessage(String message) {
// System.out.println("RECIEVE: " + message);
// }
//
// @Override
// public void acceptRequest(String message) {
// System.out.println("SEND: " + message);
// }
//
// @Override
// public void error(String errorMessage, Throwable error) {
// System.out.println("ERROR: " + errorMessage);
// if (error != null) {
// error.printStackTrace();
// }
// }
// };
//
// MspDevice controller = new MspDevice("127.0.0.1", 10014, listener);
// try {
// controller.init();
// String name = controller.createMeasurement("default", 2, 4, 18, 28);
// controller.setFileamentOn(true);
//
// controller.startMeasurement(name);
// BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
// reader.readLine();
// } finally {
// controller.stop();
// System.exit(0);
// }
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.msp.fx;
import ch.qos.logback.classic.Level;
import hep.dataforge.context.GlobalContext;
import hep.dataforge.storage.commons.StoragePlugin;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.slf4j.LoggerFactory;
/**
*
* @author darksnake
*/
public class MspApp extends Application {
MspViewController controller;
@Override
public void start(Stage primaryStage) throws IOException {
Locale.setDefault(Locale.US);// чтобы отделение десятичных знаков было точкой
ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
rootLogger.setLevel(Level.INFO);
new StoragePlugin().startGlobal();
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/MspView.fxml"));
Parent parent = loader.load();
controller = loader.getController();
try {
String configPath = getParameters().getNamed().get("config");
if (configPath != null) {
File configFile = new File(configPath);
controller.setDeviceConfig(GlobalContext.instance(), configFile);
}
} catch (Exception ex) {
LoggerFactory.getLogger(getClass()).error("Failed to load predefined configuration", ex);
}
Scene scene = new Scene(parent, 600, 400);
primaryStage.setTitle("Numass mass-spectrometer view");
primaryStage.setScene(scene);
primaryStage.setMinHeight(400);
primaryStage.setMinWidth(600);
// primaryStage.setResizable(false);
primaryStage.show();
}
@Override
public void stop() throws Exception {
super.stop(); //To change body of generated methods, choose Tools | Templates.
controller.disconnect();
System.exit(0);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}

View File

@ -0,0 +1,341 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.msp.fx;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.meta.ConfigChangeListener;
import hep.dataforge.meta.Configuration;
import hep.dataforge.context.Context;
import hep.dataforge.context.GlobalContext;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.exceptions.ControlException;
import hep.dataforge.exceptions.PortException;
import hep.dataforge.io.MetaFileReader;
import hep.dataforge.plots.data.DynamicPlottable;
import hep.dataforge.plots.data.DynamicPlottableSet;
import hep.dataforge.plots.jfreechart.JFreeChartFrame;
import hep.dataforge.values.Value;
import inr.numass.control.msp.MspDevice;
import inr.numass.control.msp.MspListener;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.ParseException;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Slider;
import javafx.scene.control.TextArea;
import javafx.scene.control.ToggleButton;
import javafx.scene.input.DragEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.stage.FileChooser;
import org.slf4j.LoggerFactory;
/**
* FXML Controller class
*
* @author darksnake
*/
public class MspViewController implements Initializable, MspListener {
public static final String MSP_DEVICE_TYPE = "msp";
public static final String DEFAULT_CONFIG_LOCATION = "msp-config.xml";
private MspDevice device;
private Configuration viewConfig;
private JFreeChartFrame plotFrame;
private final DynamicPlottableSet plottables = new DynamicPlottableSet();
private final String mspName = "msp";
@FXML
private Slider autoRangeSlider;
@FXML
private ToggleButton fillamentButton;
@FXML
private Circle fillamentIndicator;
@FXML
private TextArea logArea;
@FXML
private ToggleButton plotButton;
@FXML
private AnchorPane plotPane;
@FXML
private Button loadConfigButton;
private final ConfigChangeListener viewConfigObserver = new ConfigChangeListener() {
@Override
public void notifyElementChanged(String name, List<? extends Meta> oldItem, List<? extends Meta> newItem) {
updatePlot();
}
@Override
public void notifyValueChanged(String name, Value oldItem, Value newItem) {
updatePlot();
}
};
public MspViewController() {
}
public Configuration getViewConfig() {
if (viewConfig == null) {
viewConfig = new Configuration(getDevice().meta().getNode("peakJump"));
viewConfig.addObserver(viewConfigObserver);
LoggerFactory.getLogger(getClass()).warn("Could not find view configuration. Using default view configuration instead.");
}
return viewConfig;
}
public void setViewConfig(Meta viewConfig) {
this.viewConfig = new Configuration(viewConfig);
this.viewConfig.addObserver(viewConfigObserver);
}
private MspDevice getDevice() {
if (this.device == null) {
showError("Device configuration not found. Using default configuration.");
Meta defaultDeviceConfig;
try {
defaultDeviceConfig = MetaFileReader
.read(new File(getClass().getResource("/config/msp-config.xml").toURI()));
} catch (IOException | URISyntaxException | ParseException ex) {
throw new Error(ex);
}
setDeviceConfig(GlobalContext.instance(), defaultDeviceConfig);
}
return device;
}
public void setDeviceConfig(Context context, Meta config) {
Meta mspConfig = null;
if (config.hasNode("device")) {
for (Meta d : config.getNodes("device")) {
if (d.getString("type", "unknown").equals(MSP_DEVICE_TYPE)
&& d.getString("name", "msp").equals(this.mspName)) {
mspConfig = d;
}
}
} else if (config.hasNode("peakJump")) {
mspConfig = config;
}
if (mspConfig != null) {
this.device = new MspDevice(mspName, context, mspConfig);
try {
getDevice().setListener(this);
getDevice().init();
getDevice().start();
} catch (ControlException ex) {
showError(String.format("Can't connect to %s:%d. The port is either busy or not the MKS mass-spectrometer port",
config.getString("connection.ip", "127.0.0.1"),
config.getInt("connection.port", 10014)));
throw new RuntimeException("Can't connect to device");
}
} else {
showError("Can't find device description in given confgiuration");
throw new RuntimeException();
}
if (config.hasNode("plots.msp")) {
setViewConfig(config.getNode("plots.msp"));
}
updatePlot();
}
public void setDeviceConfig(Context context, File cfgFile) {
try {
Meta deviceConfig = MetaFileReader.instance().read(context, cfgFile, null);
setDeviceConfig(context, deviceConfig);
} catch (IOException | ParseException ex) {
showError("Can't load configuration file");
}
}
public void initPlot() {
Meta plotConfig = new MetaBuilder("plotFrame")
.setNode(new MetaBuilder("yAxis")
.setValue("logAxis", true)
.setValue("axisTitle", "partial pressure")
.setValue("axisUnits", "mbar")
)
.setValue("xAxis.timeAxis", true);
this.plotFrame = new JFreeChartFrame(mspName, plotConfig, plotPane);
updatePlot();
// this.plot = DynamicPlot.attachToFX(plotPane, new AnnotationBuilder("plot-config").putValue("logY", true).build());
// plot.setAutoRange(30 * 60);
}
public void updatePlot() {
if (plotFrame == null) {
initPlot();
}
Meta config = getViewConfig();
if (config.hasNode("plotFrame")) {
this.plotFrame.updateConfig(config.getNode("plotFrame"));
}
if (config.hasNode("peakJump.line")) {
for (Meta an : config.getNodes("peakJump.line")) {
String mass = an.getString("mass");
if (!this.plottables.hasPlottable(mass)) {
DynamicPlottable newPlottable = new DynamicPlottable(mass, an, mass);
this.plottables.addPlottable(newPlottable);
plotFrame.add(newPlottable);
} else {
plottables.getPlottable(mass).updateConfig(an);
}
}
} else {
showError("No peaks defined in config");
throw new RuntimeException();
}
}
@Override
public void acceptMeasurement(Map<Integer, Double> measurement) {
MapDataPoint point = new MapDataPoint();
for (Map.Entry<Integer, Double> entry : measurement.entrySet()) {
Double val = entry.getValue();
if (val <= 0) {
val = Double.NaN;
}
point.putValue(Integer.toString(entry.getKey()), val);
}
plottables.put(point);
}
@Override
public void acceptMessage(String message) {
Platform.runLater(() -> {
logArea.appendText("RECIEVE: " + message + "\r\n");
});
}
@Override
public void acceptRequest(String message) {
Platform.runLater(() -> {
logArea.appendText("SEND: " + message + "\r\n");
});
}
@Override
public void error(String errorMessage, Throwable error) {
Platform.runLater(() -> {
logArea.appendText("ERROR: " + errorMessage + "\r\n");
showError(errorMessage);
});
}
/**
* Initializes the controller class.
*
* @param url
* @param rb
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
}
@FXML
private void onAutoRangeChange(DragEvent event) {
plottables.setMaxAge((int) (this.autoRangeSlider.getValue() * 60 * 1000));
}
@FXML
private void onFillamentToggle(ActionEvent event) throws PortException {
getDevice().setFileamentOn(fillamentButton.isSelected());
}
@FXML
private void onLoadConfig(ActionEvent event) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open Resource File");
fileChooser.setInitialFileName(DEFAULT_CONFIG_LOCATION);
fileChooser.setInitialDirectory(GlobalContext.instance().io().getRootDirectory());
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("xml", "*.xml", "*.XML"));
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("all", "*.*"));
File cfgFile = fileChooser.showOpenDialog(loadConfigButton.getScene().getWindow());
if (cfgFile != null) {
setDeviceConfig(GlobalContext.instance(), cfgFile);
}
}
@FXML
private void onPlotToggle(ActionEvent event) throws PortException {
if (plotButton.isSelected()) {
getDevice().startPeakJumpMeasurement();
} else {
getDevice().stopMeasurement();
}
}
private void showError(String message) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle("Error!");
alert.setHeaderText(null);
alert.setContentText(message);
alert.showAndWait();
}
private void showInfo(String message) {
}
public void disconnect() throws IOException, PortException, ControlException {
getDevice().stop();
}
@Override
public void acceptFillamentStateChange(String fillamentState) {
Platform.runLater(() -> {
switch (fillamentState) {
case "ON":
this.fillamentIndicator.setFill(Paint.valueOf("red"));
break;
case "OFF":
this.fillamentIndicator.setFill(Paint.valueOf("blue"));
break;
case "WARM-UP":
case "COOL-DOWN":
this.fillamentIndicator.setFill(Paint.valueOf("yellow"));
break;
}
});
}
}

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2015 Alexander Nozik.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<config>
<device type="msp" name="msp">
<storage path="D:/temp/test" />
<connection ip="127.0.0.1" port="10014"/>
<peakJump>
<peak mass="2"/>
<peak mass="3"/>
<peak mass="4"/>
<peak mass="6"/>
<peak mass="12"/>
<peak mass="14"/>
<peak mass="18"/>
<peak mass="28"/>
<peak mass="32"/>
</peakJump>
</device>
<plots>
<msp>
<peakJump>
<line mass="2" title="hydrogen" color="black" thickness="6"/>
<line mass="6" title="tritium" thickness="4"/>
<line mass="18" title="water" />
<line mass="32" title="oxygen"/>
</peakJump>
</msp>
</plots>
</config>

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2015 Alexander Nozik.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<?import javafx.scene.effect.*?>
<?import javafx.scene.paint.*?>
<?import javafx.scene.shape.*?>
<?import javafx.scene.chart.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="400.0" minWidth="600.0" prefHeight="480.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="inr.numass.control.msp.fx.MspViewController">
<children>
<SplitPane dividerPositions="0.8" minHeight="400.0" minWidth="600.0" orientation="VERTICAL" prefHeight="200.0" prefWidth="160.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<AnchorPane minHeight="300.0" minWidth="300.0" prefHeight="100.0" prefWidth="160.0">
<children>
<ToolBar layoutX="130.0" prefHeight="50.0" prefWidth="200.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<items>
<ToggleButton fx:id="fillamentButton" mnemonicParsing="false" onAction="#onFillamentToggle" text="Fillament" />
<Circle fx:id="fillamentIndicator" fill="GRAY" radius="10.0" stroke="BLACK" strokeType="INSIDE" />
<Separator orientation="VERTICAL" prefHeight="20.0" />
<ToggleButton fx:id="plotButton" mnemonicParsing="false" onAction="#onPlotToggle" text="Aquire" />
<Button fx:id="loadConfigButton" mnemonicParsing="false" onAction="#onLoadConfig" text="Load config" />
<Separator orientation="VERTICAL" prefHeight="20.0" />
<Label text="Autorange (min):" />
<Slider fx:id="autoRangeSlider" max="210.0" min="10.0" onDragDone="#onAutoRangeChange" showTickLabels="true" showTickMarks="true" snapToTicks="true" value="30.0" />
<Separator orientation="VERTICAL" prefHeight="20.0" />
</items>
</ToolBar>
<AnchorPane fx:id="plotPane" layoutX="144.0" layoutY="82.0" minHeight="400.0" minWidth="600.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="50.0" />
</children>
</AnchorPane>
<AnchorPane maxHeight="200.0" minHeight="0.0" minWidth="0.0" prefHeight="100.0" prefWidth="160.0">
<children>
<TextArea fx:id="logArea" editable="false" maxHeight="200.0" minHeight="0.0" prefHeight="200.0" prefWidth="200.0" wrapText="true" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</items>
</SplitPane>
</children>
</AnchorPane>

View File

@ -0,0 +1,38 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.control.msp;
/**
*
* @author Alexander Nozik
*/
public class TestScanner {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
MspDevice.MspResponse response = new MspDevice.MspResponse(
"FilamentStatus 1 ON\n"
+ "Trip None \n"
+ "Drive Off\n"
+ "EmissionTripState OK\n"
+ "ExternalTripState OK \n"
+ "RVCTripState OK");
System.out.println(response.get(2, 1));
}
}

View File

@ -0,0 +1,18 @@
apply plugin: 'application'
version = "0.3.1"
if (!hasProperty('mainClass')) {
ext.mainClass = 'inr.numass.readvac.Main'
}
mainClassName = mainClass
dependencies {
compile 'ch.qos.logback:logback-classic:1.1.0+'
compile 'org.scream3r:jssc:2.8.0'
compile 'commons-cli:commons-cli:1.3'
compile project(':dataforge-plots')
compile project(':dataforge-storage')
compile project(':dataforge-control')
}

View File

@ -0,0 +1,193 @@
/*
* 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.readvac;
import hep.dataforge.context.Context;
import hep.dataforge.control.devices.AbstractMeasurementDevice;
import hep.dataforge.control.ports.ComPortHandler;
import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.description.NodeDef;
import hep.dataforge.description.ValueDef;
import hep.dataforge.exceptions.ControlException;
import hep.dataforge.exceptions.PortException;
import hep.dataforge.meta.Meta;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jssc.SerialPortException;
/**
*
* @author Alexander Nozik
*/
@NodeDef(name = "mks", target = "metod::inr.numass.readvac.getQuery")
@ValueDef(name = "port")
@ValueDef(name = "delay")
public class MKSVacuumeterDevice extends AbstractMeasurementDevice<Double> implements PortHandler.PortController {
// private static final String QUERY = "@253PR5?;FF";
private static final String DELIMETER = ";FF";
PortHandler handler;
public MKSVacuumeterDevice(String name, Context context, Meta annotation) {
super(name, context, annotation);
}
private int timeout() {
return meta().getInt("timeout", 400);
}
private void initHandler() throws PortException {
try {
String com = meta().getString("port");
handler = new ComPortHandler(com);
handler.setDelimeter(DELIMETER);
} catch (SerialPortException ex) {
throw new PortException("Can't init port");
}
}
/**
* Get pressure query string. The default is "@253PR5?;FF"
*
* @return
*/
@ValueDef(name = "address")
@ValueDef(name = "channel")
protected String getQuery() {
String deviceAddres = meta().getString("mks.address", "253");
String channelNumber = meta().getString("mks.channel", "5");
return String.format("@%sPR%s?;FF", deviceAddres, channelNumber);
}
@Override
protected void doStart(Meta measurement) throws ControlException {
Meta meta = buildMeasurementLaminate(measurement);
initHandler();
setState("connection", checkConnection());
if (isConnected()) {
setState("power", getPowerState());
int delay = meta.getInt("delay", 5000);
executor.scheduleWithFixedDelay(() -> {
Double val = read();
measurementResult(null, val);
}, 0, delay, TimeUnit.MILLISECONDS);
} else {
getLogger().warn("No connection for " + getName());
}
}
@Override
protected void doStop() throws ControlException {
setPowerState(false);
try {
handler.close();
} catch (Exception ex) {
getLogger().error("Can not close the port", ex);
}
}
private Double read() {
if (handler == null) {
setState("connection", false);
return null;
}
try {
String answer = talk(getQuery());
if (answer == null || answer.isEmpty()) {
setState("connection", false);
return null;
}
double res = Double.parseDouble(answer);
if (res <= 0) {
return null;
} else {
return res;
}
} catch (ControlException ex) {
setState("connection", false);
return null;
}
}
private String talk(String request) throws ControlException {
String answer = handler.sendAndWait(request, timeout());
// if (answer.isEmpty()) {
// throw new ControlException("No answer from " + getName());
// }
Matcher match = Pattern.compile("@253ACK(.*);FF").matcher(answer);
if (match.matches()) {
return match.group(1);
} else {
throw new ControlException(answer);
}
}
private boolean getPowerState() throws ControlException {
String answer = talk("@253FP?;FF");
return answer.equals("ON");
}
private boolean checkConnection() {
try {
return !talk("@253T?;FF").isEmpty();
} catch (ControlException ex) {
return false;
}
}
public boolean isConnected() {
return getState("connection").booleanValue();
}
public boolean isPowerOn() {
return getState("power").booleanValue();
}
/**
* Set cathode power state and return result
*
* @param state
* @return
* @throws ControlException
*/
public void setPowerState(boolean state) throws ControlException {
boolean powerState = getPowerState();
if (state != powerState) {
if (state == true) {
String ans = talk("@253ENC!OFF;FF");
if (!ans.equals("OFF")) {
getLogger().warn("The @253ENC!OFF;FF command is not working");
}
ans = talk("@253FP!ON;FF");
if (!ans.equals("ON")) {
throw new ControlException("Can't set cathod power state");
}
} else {
String ans = talk("@253FP!OFF;FF");
if (!ans.equals("OFF")) {
throw new ControlException("Can't set cathod power state");
}
}
setState("power", getPowerState());
}
}
@Override
public void accept(String message) {
//ignore async responses
}
@Override
public void error(String errorMessage, Throwable error) {
getLogger().error(errorMessage, error);
}
}

View File

@ -0,0 +1,131 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.readvac;
import hep.dataforge.meta.Meta;
import hep.dataforge.context.Context;
import hep.dataforge.context.GlobalContext;
import static hep.dataforge.context.GlobalContext.out;
import hep.dataforge.io.MetaFileReader;
import hep.dataforge.storage.api.Storage;
import hep.dataforge.storage.commons.StoragePlugin;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
/**
*
* @author Darksnake
*/
public class Main {
static String name;
// static volatile boolean stopFlag = false;
/**
* @param args the command line arguments
* @throws java.lang.Exception
*/
public static void main(String[] args) throws Exception {
Locale.setDefault(Locale.US);
new StoragePlugin().startGlobal();
Meta config = getAnnotation(args);
runConfig(config);
// System.exit(0);//на всякий случай, чтобы закрыть все боковые потоки
}
public static void runConfig(Meta config) throws Exception {
// VACManager daemon;
// //Определяем, является считывает ли сервер из файла или из com порта
// boolean direct = config.getBoolean("direct", true);
//Префикс сеанса
String prefix = config.getString("run", name);
Storage server = setupServer(GlobalContext.instance(), config);
// if (direct) {
// daemon = VACManager.fromSerial(server, getSerialConfig(config), prefix);
// } else {
// daemon = VACManager.fromDirectory(server, getDataPath(config), prefix);
// }
VACManager daemon = VACManager.fromSerial(server, prefix, getSerialConfig(config));
daemon.start();
}
private static Meta getSerialConfig(Meta config) {
return config.getNode("serialconfig", config);
}
private static Storage setupServer(Context context, Meta config) {
Meta storageConfig = config.getNode("storage");
return context.provide("storage", StoragePlugin.class).buildStorage(storageConfig);
}
// private static String getDataPath(Meta config) {
// return config.getString("datapath", "D:\\temp\\test");
// }
private static Options prepareOptions() {
Options options = new Options();
options.addOption("c", "config", true, "Configuration file path");
// options.addOption("d", "dir", true, "Directory with data files");
options.addOption("n", "name", true, "Run name");
options.addOption("h", "home", true, "Working directory");
// options.addOption("t", "target", true, "Target data file");
return options;
}
private static Meta getAnnotation(String[] cli) throws IOException, ParseException, java.text.ParseException {
String configPath;
Options options = prepareOptions();
if (cli.length == 0) {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("java -jar readVAC.jar [OPTIONS]", options);
out().println("Trying to use default config location...");
configPath = "vac-config.xml";
} else {
CommandLineParser parser = new DefaultParser();
CommandLine line;
// parse the command line arguments
line = parser.parse(options, cli);
if (line.hasOption("h")) {
System.setProperty("user.dir", line.getOptionValue("h"));
}
if (line.hasOption("n")) {
name = line.getOptionValue("n");
}
configPath = line.getOptionValue("c", "config.xml");
}
File configFile = new File(configPath);
return MetaFileReader.read(configFile);
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.readvac;
/**
*
* @author Darksnake
*/
class P1ControlException extends Exception {
/**
* Creates a new instance of <code>p1ControlException</code> without detail
* message.
*/
public P1ControlException() {
}
/**
* Constructs an instance of <code>p1ControlException</code> with the
* specified detail message.
*
* @param msg the detail message.
*/
public P1ControlException(String msg) {
super(msg);
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.readvac;
/**
*
* @author Darksnake
*/
public class ResponseParseException extends Exception {
String response;
public ResponseParseException(String response) {
this.response = response;
}
public ResponseParseException(String response, String message) {
super(message);
this.response = response;
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.readvac;
import java.io.IOException;
import java.io.OutputStream;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.Utilities;
import org.slf4j.LoggerFactory;
/**
*
* @author Darksnake
*/
public class TextAreaOutputStream extends OutputStream {
private static final int MAXLINES = 500;
private final JTextArea textArea;
private final StringBuilder sb = new StringBuilder();
private final String title;
// public static IOManager getTextAreaIO(Context context, JTextArea area){
// return new BasicIOManager(context, new TextAreaOutputStream(area, "system"));
// }
public TextAreaOutputStream(final JTextArea textArea, String title) {
this.textArea = textArea;
this.title = title;
sb.append(title).append("> ");
}
@Override
public void flush() {
}
@Override
public void close() {
}
@Override
public void write(int b) throws IOException {
if (b == '\r') {
return;
}
if (b == '\n') {
final String text = sb.toString() + "\n";
SwingUtilities.invokeLater(() -> {
textArea.append(text);
while (textArea.getLineCount() >= MAXLINES) {
try {
textArea.getDocument().remove(0, Utilities.getRowEnd(textArea, 1));
} catch (BadLocationException ex) {
LoggerFactory.getLogger(getClass()).error(null, ex);
break;
}
}
});
sb.setLength(0);
sb.append(title).append("> ");
return;
}
sb.append((char) b);
}
}

View File

@ -0,0 +1,412 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.readvac;
import hep.dataforge.meta.Meta;
import hep.dataforge.data.DataPoint;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.values.Value;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Iterator;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jssc.SerialPort;
import jssc.SerialPortException;
import jssc.SerialPortTimeoutException;
import org.slf4j.LoggerFactory;
/**
*
* @author Darksnake
*/
public class VACDeviceReader implements Iterator<DataPoint>, AutoCloseable {
// private int timeout = 100;
private final int maxChars = 50;
private static final String CM32Query = "MES R PM 1\r\n";
private static final String MQuery = ":010300000002FA\r\n";
private static final String P1Query = "@253PR5?;FF";
SerialPort p2Port;
SerialPort p3Port;
SerialPort p1Port;
SerialPort pxPort;
Lock p1Lock;
Lock p2Lock;
Lock p3Lock;
Lock pxLock;
Meta p1Config;
Meta p2Config;
Meta p3Config;
Meta pxConfig;
private boolean p1PowerOn = false;
public VACDeviceReader(String p2, String p3, String p1, String px) throws SerialPortException {
setupPorts(p2, p3, p1, px);
}
public VACDeviceReader(Meta serialConfig) throws SerialPortException {
String p2 = serialConfig.getString("P2", null);
String p3 = serialConfig.getString("P3", null);
String p1 = serialConfig.getString("P1", null);
String px = serialConfig.getString("Px", p1);
// this.timeout = serialConfig.getInt("timeout", timeout);
setupPorts(p2, p3, p1, px);
}
public boolean setP1PowerStateOn(boolean state) throws SerialPortException, ResponseParseException, P1ControlException {
p1PowerOn = getP1PowerState();
if (state == p1PowerOn) {
//Возвращаем то, что есть
return p1PowerOn;
} else {
if (state == true) {
// String ans = talkMKS(p1Port, "@253ENC!OFF;FF");
// if (!ans.equals("OFF")) {
// LoggerFactory.getLogger(getClass()).warn("The @253ENC!OFF;FF command is not working");
// }
String ans = talkMKS(p1Port, "@253FP!ON;FF");
if (!ans.equals("ON")) {
throw new P1ControlException("Can't set P1 cathod power state");
}
} else {
String ans = talkMKS(p1Port, "@253FP!OFF;FF");
if (!ans.equals("OFF")) {
throw new P1ControlException("Can't set P1 cathod power state");
}
}
p1PowerOn = getP1PowerState();
return p1PowerOn;
}
}
public boolean isP1Available() {
try {
return !talkMKS(p1Port, "@253T?;FF").isEmpty();
} catch (SerialPortException | ResponseParseException ex) {
return false;
}
}
private String talkMKS(SerialPort port, String request) throws SerialPortException, ResponseParseException {
try {
p1Lock.lock();
if (!port.isOpened()) {
port.openPort();
}
port.purgePort(SerialPort.PURGE_RXCLEAR | SerialPort.PURGE_TXCLEAR);
port.writeString(request);
LoggerFactory.getLogger(port.getPortName()).info("send> " + request.trim());
String answer = readPort(p1Port, ";FF", 100);
LoggerFactory.getLogger(port.getPortName()).info("recieve> " + answer.trim());
if (answer.isEmpty()) {
throw new ResponseParseException(answer);
}
Matcher match = Pattern.compile("@253ACK(.*);FF").matcher(answer);
if (match.matches()) {
return match.group(1);
} else {
throw new ResponseParseException(answer);
}
} finally {
p1Lock.unlock();
}
}
public boolean getP1PowerState() throws SerialPortException, ResponseParseException {
String answer = talkMKS(p1Port, "@253FP?;FF");
return answer.equals("ON");
}
/**
* Считываем строку из порта пока не найдем delimeter или не потратим
* timeout времени. Если случается таймаут, то возвращается null
*
* @param port
* @param delimeter
* @return
* @throws SerialPortException
*/
private String readPort(SerialPort port, String delimeter, int timeout) throws SerialPortException {
String res = new String();
Instant start = Instant.now();
port.purgePort(SerialPort.PURGE_RXCLEAR | SerialPort.PURGE_TXCLEAR);
while (res.length() < maxChars) {
try {
res += port.readString(1, timeout);
} catch (SerialPortTimeoutException ex) {
return "";
}
if (start.until(Instant.now(), ChronoUnit.MILLIS) > timeout) {
return "";
}
if (res.endsWith(delimeter)) {
return res;
}
}
return "";
}
@Override
public void close() throws Exception {
if (p1Port.isOpened()) {
p1Port.closePort();
}
if (pxPort.isOpened()) {
pxPort.closePort();
}
if (p2Port.isOpened()) {
p2Port.closePort();
}
if (p3Port.isOpened()) {
p3Port.closePort();
}
try {
this.setP1PowerStateOn(false);
} catch (P1ControlException ex) {
LoggerFactory.getLogger(getClass()).warn("Can't turn of the power on P1");
}
}
private void setupPorts(String p2, String p3, String p1, String px) {
try {
if (p2 == null) {
p2Port = null;
} else {
p2Port = new SerialPort(p2);
p2Port.openPort();
p2Port.setParams(2400, 8, 1, 0);
p2Lock = new ReentrantLock();
}
} catch (SerialPortException ex) {
p2Port = null;
LoggerFactory.getLogger(getClass()).error("Can't open " + p2, ex);
}
try {
if (p3 == null) {
p3Port = null;
} else {
p3Port = new SerialPort(p3);
p3Port.openPort();
p3Port.setParams(2400, 8, 1, 0);
p3Lock = new ReentrantLock();
}
} catch (SerialPortException ex) {
p2Port = null;
LoggerFactory.getLogger(getClass()).error("Can't open " + p3, ex);
}
try {
if (p1 == null) {
p1Port = null;
} else {
p1Port = new SerialPort(p1);
p1Port.openPort();
p1Port.setParams(9600, 8, 1, 0);
p1Lock = new ReentrantLock();
}
} catch (SerialPortException ex) {
p2Port = null;
LoggerFactory.getLogger(getClass()).error("Can't open " + p1, ex);
}
if (px == null) {
pxPort = null;
} else {
if (px.equals(p1)) {
pxPort = p1Port;
pxLock = p1Lock;
} else {
try {
pxPort = new SerialPort(px);
pxPort.openPort();
pxPort.setParams(9600, 8, 1, 0);
pxLock = new ReentrantLock();
} catch (SerialPortException ex) {
p2Port = null;
LoggerFactory.getLogger(getClass()).error("Can't open " + px, ex);
}
}
}
}
private Value readCM(SerialPort port) {
try {
if (!port.isOpened()) {
port.openPort();
}
port.purgePort(SerialPort.PURGE_RXCLEAR | SerialPort.PURGE_TXCLEAR);
port.writeString(CM32Query);
LoggerFactory.getLogger(port.getPortName()).info("send> " + CM32Query.trim());
// try {
// Thread.sleep(200);
// } catch (InterruptedException ex) {
// Logger.getLogger(VACDeviceReader.class.getName()).log(Level.SEVERE, null, ex);
// }
String answer = readPort(port, "T--", 400);
LoggerFactory.getLogger(port.getPortName()).info("recieve> " + answer.trim());
if (answer.isEmpty()) {
return Value.of("EMPTY");
}
if (answer.indexOf("PM1:mbar") < -1) {
return Value.of("PARSE");
}
if (answer.substring(14, 17).equals("OFF")) {
return Value.of("OFF");
}
return Value.of(Double.parseDouble(answer.substring(14, 17) + answer.substring(19, 23)));
} catch (SerialPortException ex) {
return Value.of("COM_ERR");
}/* catch (SerialPortTimeoutException ex) {
return Value.of("COM_TIMEOUT");
}*/
}
private Value readP1() {
if (p1Port == null) {
return Value.of("NO_CON");
}
try {
String answer = talkMKS(p1Port, P1Query);
if (answer == null || answer.isEmpty()) {
return Value.of("EMPTY");
}
double res = Double.parseDouble(answer);
if (res <= 0) {
return Value.of("OFF");
} else {
return Value.of(res);
}
} catch (SerialPortException ex) {
return Value.of("COM_ERR");
} catch (ResponseParseException ex) {
return Value.of("PARSE");
}
}
private Value readPx() {
if (pxPort == null) {
return Value.of("NO_CON");
}
try {
if (!pxPort.isOpened()) {
pxPort.openPort();
}
pxPort.purgePort(SerialPort.PURGE_RXCLEAR | SerialPort.PURGE_TXCLEAR);
pxPort.writeString(MQuery);
LoggerFactory.getLogger(pxPort.getPortName()).info("send> " + MQuery.trim());
String answer = readPort(pxPort, "\r\n", 100);
LoggerFactory.getLogger(pxPort.getPortName()).info("recieve> " + answer.trim());
if (answer.isEmpty()) {
return Value.of("EMPTY");
}
Matcher match = Pattern.compile(":010304(\\w{4})(\\w{4})..\r\n").matcher(answer);
if (match.matches()) {
double base = (double) (Integer.parseInt(match.group(1), 16)) / 10d;
int exp = Integer.parseInt(match.group(2), 16);
if (exp > 32766) {
exp = exp - 65536;
}
BigDecimal res = BigDecimal.valueOf(base * Math.pow(10, exp));
res = res.setScale(4, RoundingMode.CEILING);
return Value.of(res);
} else {
return Value.of("PARSE");
}
} catch (SerialPortException ex) {
return Value.of("COM_ERR");
}
}
private Value readP2() {
if (p2Port == null) {
return Value.of("NO_CON");
}
try {
p2Lock.lock();
return readCM(p2Port);
} finally {
p2Lock.unlock();
}
}
private Value readP3() {
if (p3Port == null) {
return Value.of("NO_CON");
}
try {
p3Lock.lock();
return readCM(p3Port);
} finally {
p3Lock.unlock();
}
}
@Override
public boolean hasNext() {
return true;
}
@Override
public DataPoint next() {
Value p1 = readP1();
Value p2 = readP2();
Value p3 = readP3();
Value px = readPx();
Value time = Value.of(Instant.now().truncatedTo(ChronoUnit.SECONDS));
return new MapDataPoint(VACManager.names, time, p1, p2, p3, px);
}
}
//P2, P3:
//Q:"MES R PM 1\r\n"
//A:"PM1:mbar : 2.3 E-03:T--
//"
//
//P1:
//Q:"@253PR4?;FF"
//A:"@253ACK3.891E+1;FF"
//
//Px:
//Q:":010300000002FA\r\n"
//A:":0103040014FFFEE7"
//нужно брать символы с 8 по 12

View File

@ -0,0 +1,142 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.readvac;
import hep.dataforge.data.DataParser;
import hep.dataforge.data.DataPoint;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.io.LineIterator;
import java.io.File;
import java.io.FileNotFoundException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* @author Darksnake
*/
public class VACFileReader implements Iterator<DataPoint> {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss");//14.04.2014 21:30:10
public static VACFileReader fromDirectory(String dir) throws FileNotFoundException {
File directory = new File(dir);
String[] list = directory.list((File dir1, String name) -> name.startsWith("VacTMS") && name.endsWith(".txt"));
if(list.length == 0){
throw new FileNotFoundException("Data files not found in the given directory");
}
Arrays.sort(list);
return new VACFileReader(new File(directory,list[list.length-1]));
}
public static VACFileReader fromFile(String file) throws FileNotFoundException {
return new VACFileReader(new File(file));
}
private final LineIterator iterator;
private final DataParser parser;
private VACFileReader(File vacFile) throws FileNotFoundException {
this.iterator = new LineIterator(vacFile);
iterator.next();
parser = new LikhovidVACParser();
}
public VACFileReader(File vacFile, DataParser parser) throws FileNotFoundException {
this.iterator = new LineIterator(vacFile);
iterator.next();
this.parser = parser;
}
public DataPoint get(Instant time) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
public DataPoint getLast() {
DataPoint point = null;
while (hasNext()) {
point = next();
}
return point;
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public DataPoint next() {
if (iterator.hasNext()) {
return parser.parse(iterator.next());
} else {
return null;
}
}
public List<DataPoint> updateFrom(Instant from) {
List<DataPoint> res = new ArrayList<>();
while (iterator.hasNext()) {
DataPoint point = next();
if (point != null && point.getValue("timestamp").timeValue().isAfter(from)) {
res.add(point);
}
}
return res;
}
public List<DataPoint> updateFrom() {
List<DataPoint> res = new ArrayList<>();
while (iterator.hasNext()) {
DataPoint point = next();
if (point != null) {
res.add(point);
}
}
return res;
}
private static class LikhovidVACParser implements DataParser {
static final Pattern pattern = Pattern.compile("(\\S* \\S*)\\s*(\\S*);\\s*(\\S*)\\s*(\\S*)\\s*(\\S*)");
@Override
public DataPoint parse(String str) {
Matcher matcher = pattern.matcher(str);
if(!matcher.matches()){
return null;
}
LocalDateTime dt = LocalDateTime.parse(matcher.group(1), formatter);
Instant time = dt.toInstant(ZoneOffset.ofHours(0));
String p1 = matcher.group(2);
String p2 = matcher.group(3);
String p3 = matcher.group(4);
String px = matcher.group(5);
return new MapDataPoint(VACManager.names, new Object[]{time, p1, p2, p3, px});
}
}
}

View File

@ -0,0 +1,395 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.9" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
<Properties>
<Property name="defaultCloseOperation" type="int" value="2"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[800, 180]"/>
</Property>
<Property name="name" type="java.lang.String" value="mainFrame" noResource="true"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[1052, 600]"/>
</Property>
</Properties>
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleParent" type="javax.accessibility.Accessible" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="Form"/>
</Property>
</AccessibilityProperties>
<SyntheticProperties>
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
<SyntheticProperty name="generateCenter" type="boolean" value="false"/>
</SyntheticProperties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,0,-33,0,0,4,28"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout">
<Property name="axis" type="int" value="1"/>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="valuesPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.BevelBorderInfo">
<BevelBorder/>
</Border>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 90]"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="15" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="jLabel5" max="32767" attributes="0"/>
<Component id="timeLabel" pref="180" max="32767" attributes="0"/>
</Group>
<EmptySpace pref="122" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="p1Label" max="32767" attributes="0"/>
<Component id="jLabel1" min="-2" pref="81" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="104" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="p2Label" alignment="0" max="32767" attributes="0"/>
<Component id="jLabel2" alignment="0" min="-2" pref="81" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="104" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="p3Label" alignment="0" max="32767" attributes="0"/>
<Component id="jLabel3" alignment="0" min="-2" pref="81" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="106" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="pxLabel" alignment="0" max="32767" attributes="0"/>
<Component id="jLabel4" alignment="0" min="-2" pref="81" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="53" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="jLabel4" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="pxLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="103" groupAlignment="1" attributes="0">
<Group type="102" attributes="0">
<Component id="jLabel3" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="p3Label" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="p2Label" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel5" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="p1Label" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="timeLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="0"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="P1"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="p1Label">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="1"/>
</Property>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" id="red" palette="1" red="ff" type="palette"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="EMPTY"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="0"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="P2"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="p2Label">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="1"/>
</Property>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ff" green="0" id="blue" palette="1" red="0" type="palette"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="EMPTY"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel3">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="0"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="P3"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="p3Label">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="1"/>
</Property>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="ff" id="green" palette="1" red="0" type="palette"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="EMPTY"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel4">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="0"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="Px"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="pxLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="1"/>
</Property>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="ff" green="0" id="magenta" palette="1" red="ff" type="palette"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="EMPTY"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="timeLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="1"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="EMPTY"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel5">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="24" style="0"/>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" value="time"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="optionsPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.BevelBorderInfo">
<BevelBorder/>
</Border>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 50]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 50]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[1052, 50]"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
<Component id="jLabel6" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="delayBox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="32" max="-2" attributes="0"/>
<Component id="jLabel7" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="rangeBox" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="427" max="32767" attributes="0"/>
<Component id="p1Power" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="60" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel7" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="rangeBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="delayBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel6" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="p1Power" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="40" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel6">
<Properties>
<Property name="text" type="java.lang.String" value="&#x427;&#x430;&#x441;&#x442;&#x43e;&#x442;&#x430; &#x43e;&#x431;&#x43d;&#x43e;&#x432;&#x43b;&#x435;&#x43d;&#x438;&#x44f; (&#x441;):"/>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="delayBox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="5">
<StringItem index="0" value="1"/>
<StringItem index="1" value="5"/>
<StringItem index="2" value="10"/>
<StringItem index="3" value="30"/>
<StringItem index="4" value="60"/>
</StringArray>
</Property>
<Property name="selectedIndex" type="int" value="1"/>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="delayBoxItemStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JComboBox" name="rangeBox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="5">
<StringItem index="0" value="10"/>
<StringItem index="1" value="30"/>
<StringItem index="2" value="60"/>
<StringItem index="3" value="180"/>
<StringItem index="4" value="300"/>
</StringArray>
</Property>
<Property name="selectedIndex" type="int" value="2"/>
<Property name="toolTipText" type="java.lang.String" value=""/>
</Properties>
<Events>
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="rangeBoxItemStateChanged"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="rangeBoxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="jLabel7">
<Properties>
<Property name="text" type="java.lang.String" value="&#x41c;&#x430;&#x43a;&#x441;&#x438;&#x43c;&#x430;&#x43b;&#x44c;&#x43d;&#x44b;&#x439; &#x434;&#x438;&#x430;&#x43f;&#x430;&#x437;&#x43e;&#x43d; (&#x43c;&#x438;&#x43d;):"/>
</Properties>
</Component>
<Component class="javax.swing.JToggleButton" name="p1Power">
<Properties>
<Property name="text" type="java.lang.String" value="&#x425;&#x43e;&#x43b;&#x43e;&#x434;&#x43d;&#x44b;&#x439; &#x43a;&#x430;&#x442;&#x43e;&#x434; &#x43d;&#x430; P1"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="p1PowerActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JSplitPane" name="split">
<Properties>
<Property name="orientation" type="int" value="0"/>
<Property name="resizeWeight" type="double" value="1.0"/>
<Property name="alignmentX" type="float" value="0.5"/>
<Property name="alignmentY" type="float" value="0.5"/>
<Property name="oneTouchExpandable" type="boolean" value="true"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="chartPannel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.BevelBorderInfo">
<BevelBorder/>
</Border>
</Property>
<Property name="autoscrolls" type="boolean" value="true"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="top"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
</Container>
<Container class="javax.swing.JScrollPane" name="scroll">
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="bottom"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="consoleBox">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="columns" type="int" value="20"/>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="5"/>
</Properties>
<AccessibilityProperties>
<Property name="AccessibleContext.accessibleParent" type="javax.accessibility.Accessible" editor="org.netbeans.modules.form.ComponentChooserEditor">
<ComponentRef name="split"/>
</Property>
</AccessibilityProperties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,542 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.readvac;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import ch.qos.logback.core.encoder.EchoEncoder;
import ch.qos.logback.core.encoder.Encoder;
import hep.dataforge.context.GlobalContext;
import hep.dataforge.data.DataPoint;
import hep.dataforge.io.BasicIOManager;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.plots.data.DynamicPlottable;
import hep.dataforge.plots.data.DynamicPlottableSet;
import hep.dataforge.plots.jfreechart.JFreeChartFrame;
import hep.dataforge.values.Value;
import hep.dataforge.values.ValueType;
import java.awt.Dimension;
import java.awt.event.WindowEvent;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import javax.swing.AbstractButton;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import org.jfree.chart.axis.LogarithmicAxis;
import org.jfree.chart.plot.XYPlot;
import org.slf4j.LoggerFactory;
/**
*
* @author Darksnake
*/
public class VACFrame extends javax.swing.JFrame {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
public static VACFrame display(VACManager daemon) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(VACFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
VACFrame frame = new VACFrame();
frame.daemon = daemon;
boolean p1Available = daemon.p1Available();
frame.p1Power.setEnabled(p1Available);
if (p1Available) {
try {
frame.updateP1PowerState(daemon.getP1PowerState());
} catch (P1ControlException ex) {
LoggerFactory.getLogger("COM-P1").error(ex.getMessage());
}
} else {
frame.p1Power.setText("P1 недоступен");
}
frame.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(WindowEvent winEvt) {
try {
daemon.close();
} catch (Exception ex) {
LoggerFactory.getLogger(VACFrame.class).error(null, ex);
}
System.exit(0);
}
});
// /* Create and displayPoint the form */
// SwingUtilities.invokeLater(() -> {
// frame.setVisible(true);
//// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// });
frame.setVisible(true);
return frame;
}
private VACManager daemon;
private JFreeChartFrame plotFrame;
private DynamicPlottableSet plottables;
// private int savedSplitHeight = 600;
/**
* Creates new form VACFrame
*/
private VACFrame() {
setTitle("Numass vacuum measurement view");
initComponents();
split.getRightComponent().setMinimumSize(new Dimension());
split.setDividerLocation(1.0);
GlobalContext.instance().attachIoManager(new BasicIOManager(new TextAreaOutputStream(consoleBox, "CONSOLE")));
JTextAreaAppender app = new JTextAreaAppender(consoleBox);
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
app.setContext(lc);
app.start();
lc.getLogger("ROOT").addAppender(app);
plottables = setupPlot();
displayChart();
}
private DynamicPlottableSet setupPlot() {
DynamicPlottable p1 = DynamicPlottable.build("P1", "timestamp", "pressure", "RED", 2.5);
DynamicPlottable p2 = DynamicPlottable.build("P2", "timestamp", "pressure", "BLUE", 2.5);
DynamicPlottable p3 = DynamicPlottable.build("P3", "timestamp", "pressure", "GREEN", 2.5);
DynamicPlottable px = DynamicPlottable.build("Px", "timestamp", "pressure", "MAGENTA", 2.5);
return new DynamicPlottableSet(p1, p2, p3, px);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
valuesPanel = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
p1Label = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
p2Label = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
p3Label = new javax.swing.JLabel();
jLabel4 = new javax.swing.JLabel();
pxLabel = new javax.swing.JLabel();
timeLabel = new javax.swing.JLabel();
jLabel5 = new javax.swing.JLabel();
optionsPanel = new javax.swing.JPanel();
jLabel6 = new javax.swing.JLabel();
delayBox = new javax.swing.JComboBox();
rangeBox = new javax.swing.JComboBox();
jLabel7 = new javax.swing.JLabel();
p1Power = new javax.swing.JToggleButton();
split = new javax.swing.JSplitPane();
chartPannel = new javax.swing.JPanel();
scroll = new javax.swing.JScrollPane();
consoleBox = new javax.swing.JTextArea();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setMinimumSize(new java.awt.Dimension(800, 180));
setName("mainFrame"); // NOI18N
setPreferredSize(new java.awt.Dimension(1052, 600));
getContentPane().setLayout(new javax.swing.BoxLayout(getContentPane(), javax.swing.BoxLayout.Y_AXIS));
valuesPanel.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
valuesPanel.setMinimumSize(new java.awt.Dimension(0, 90));
jLabel1.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel1.setText("P1");
p1Label.setFont(new java.awt.Font("Tahoma", 1, 24)); // NOI18N
p1Label.setForeground(java.awt.Color.red);
p1Label.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
p1Label.setText("EMPTY");
jLabel2.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel2.setText("P2");
p2Label.setFont(new java.awt.Font("Tahoma", 1, 24)); // NOI18N
p2Label.setForeground(java.awt.Color.blue);
p2Label.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
p2Label.setText("EMPTY");
jLabel3.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel3.setText("P3");
p3Label.setFont(new java.awt.Font("Tahoma", 1, 24)); // NOI18N
p3Label.setForeground(java.awt.Color.green);
p3Label.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
p3Label.setText("EMPTY");
jLabel4.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel4.setText("Px");
pxLabel.setFont(new java.awt.Font("Tahoma", 1, 24)); // NOI18N
pxLabel.setForeground(java.awt.Color.magenta);
pxLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
pxLabel.setText("EMPTY");
timeLabel.setFont(new java.awt.Font("Tahoma", 1, 24)); // NOI18N
timeLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
timeLabel.setText("EMPTY");
jLabel5.setFont(new java.awt.Font("Tahoma", 0, 24)); // NOI18N
jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
jLabel5.setText("time");
javax.swing.GroupLayout valuesPanelLayout = new javax.swing.GroupLayout(valuesPanel);
valuesPanel.setLayout(valuesPanelLayout);
valuesPanelLayout.setHorizontalGroup(
valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(valuesPanelLayout.createSequentialGroup()
.addGap(15, 15, 15)
.addGroup(valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(jLabel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(timeLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 180, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 122, Short.MAX_VALUE)
.addGroup(valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(p1Label, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 104, Short.MAX_VALUE)
.addGroup(valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(p2Label, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 104, Short.MAX_VALUE)
.addGroup(valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(p3Label, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 106, Short.MAX_VALUE)
.addGroup(valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(pxLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 81, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(53, Short.MAX_VALUE))
);
valuesPanelLayout.setVerticalGroup(
valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(valuesPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(valuesPanelLayout.createSequentialGroup()
.addComponent(jLabel4)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pxLabel))
.addGroup(valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(valuesPanelLayout.createSequentialGroup()
.addComponent(jLabel3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(p3Label))
.addGroup(valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(valuesPanelLayout.createSequentialGroup()
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(p2Label))
.addGroup(valuesPanelLayout.createSequentialGroup()
.addGroup(valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(jLabel5))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(valuesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(p1Label)
.addComponent(timeLabel))))))
.addContainerGap())
);
getContentPane().add(valuesPanel);
optionsPanel.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
optionsPanel.setMaximumSize(new java.awt.Dimension(32767, 50));
optionsPanel.setMinimumSize(new java.awt.Dimension(0, 50));
optionsPanel.setPreferredSize(new java.awt.Dimension(1052, 50));
jLabel6.setText("Частота обновления (с):");
delayBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1", "5", "10", "30", "60" }));
delayBox.setSelectedIndex(1);
delayBox.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
delayBoxItemStateChanged(evt);
}
});
rangeBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "10", "30", "60", "180", "300" }));
rangeBox.setSelectedIndex(2);
rangeBox.setToolTipText("");
rangeBox.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
rangeBoxItemStateChanged(evt);
}
});
rangeBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
rangeBoxActionPerformed(evt);
}
});
jLabel7.setText("Максимальный диапазон (мин):");
p1Power.setText("Холодный катод на P1");
p1Power.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
p1PowerActionPerformed(evt);
}
});
javax.swing.GroupLayout optionsPanelLayout = new javax.swing.GroupLayout(optionsPanel);
optionsPanel.setLayout(optionsPanelLayout);
optionsPanelLayout.setHorizontalGroup(
optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(optionsPanelLayout.createSequentialGroup()
.addGap(4, 4, 4)
.addComponent(jLabel6)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(delayBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(32, 32, 32)
.addComponent(jLabel7)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(rangeBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 427, Short.MAX_VALUE)
.addComponent(p1Power)
.addGap(60, 60, 60))
);
optionsPanelLayout.setVerticalGroup(
optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(optionsPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(optionsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel7)
.addComponent(rangeBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(delayBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel6)
.addComponent(p1Power))
.addGap(40, 40, 40))
);
getContentPane().add(optionsPanel);
split.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
split.setResizeWeight(1.0);
split.setAlignmentX(0.5F);
split.setAlignmentY(0.5F);
split.setOneTouchExpandable(true);
chartPannel.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED));
chartPannel.setAutoscrolls(true);
chartPannel.setLayout(new java.awt.BorderLayout());
split.setTopComponent(chartPannel);
consoleBox.setEditable(false);
consoleBox.setColumns(20);
consoleBox.setLineWrap(true);
consoleBox.setRows(5);
scroll.setViewportView(consoleBox);
consoleBox.getAccessibleContext().setAccessibleParent(split);
split.setBottomComponent(scroll);
getContentPane().add(split);
getAccessibleContext().setAccessibleParent(this);
pack();
}// </editor-fold>//GEN-END:initComponents
private void delayBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_delayBoxItemStateChanged
setTimerInterval(Integer.parseInt((String) evt.getItem()));
}//GEN-LAST:event_delayBoxItemStateChanged
private void rangeBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_rangeBoxItemStateChanged
setAutoRange(Integer.parseInt((String) evt.getItem()) * 60);
}//GEN-LAST:event_rangeBoxItemStateChanged
private void p1PowerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_p1PowerActionPerformed
AbstractButton abstractButton = (AbstractButton) evt.getSource();
daemon.stop();
boolean selected = abstractButton.getModel().isSelected();
try {
updateP1PowerState(daemon.setP1PowerStateOn(selected));
} catch (P1ControlException ex) {
LoggerFactory.getLogger(getClass()).error(ex.getMessage());
try {
updateP1PowerState(daemon.getP1PowerState());
} catch (P1ControlException ex1) {
LoggerFactory.getLogger(getClass()).error(ex1.getMessage());
}
}
daemon.start();
}//GEN-LAST:event_p1PowerActionPerformed
private void rangeBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rangeBoxActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_rangeBoxActionPerformed
private void updateP1PowerState(boolean state) {
p1Power.setSelected(state);
if (state) {
p1Power.setText("P1 включен");
} else {
p1Power.setText("P1 выключен");
}
}
public void setTimerInterval(int seconds) {
daemon.setTimerInterval(seconds * 1000);
}
public void setAutoRange(int seconds) {
plottables.setMaxAge(seconds * 1000);
}
private void displayChart() {
SwingUtilities.invokeLater(() -> {
Meta plotConfig = new MetaBuilder("plotFrame")
.setNode(new MetaBuilder("yAxis")
.setValue("logAxis", true)
.setValue("axisTitle", "pressure")
.setValue("axisUnits", "mbar")
)
.setValue("xAxis.timeAxis", true);
this.plotFrame = new JFreeChartFrame("pressures", plotConfig, chartPannel);
XYPlot xyPlot = plotFrame.getChart().getXYPlot();
LogarithmicAxis logAxis = new LogarithmicAxis("Pressure (mbar)");
// logAxis.setTickUnit(new NumberTickUnit(2));
logAxis.setMinorTickCount(10);
logAxis.setExpTickLabelsFlag(true);
logAxis.setMinorTickMarksVisible(true);
xyPlot.setRangeAxis(logAxis);
// xyPlot.getRenderer().setBaseStroke(new BasicStroke(3));
// xyPlot.setBackgroundPaint(Color.WHITE);
// xyPlot.setRangeGridlinesVisible(true);
// xyPlot.setRangeGridlinePaint(Color.BLACK);
//
// xyPlot.setRangeMinorGridlinesVisible(true);
// xyPlot.setRangeMinorGridlinePaint(Color.BLACK);
//adding data to the frame
plotFrame.addAll(plottables);
});
validate();
// pack();
}
private void setMaxAge(int seconds) {
plottables.setMaxAge(seconds * 1000);
}
public void displayPoint(DataPoint point) {
SwingUtilities.invokeLater(() -> {
plottables.put(point);
timeLabel.setText(formatter
.format(LocalDateTime
.ofInstant(point.getValue("timestamp").timeValue(), ZoneId.of("UTC"))));
p1Label.setText(normalize(point.getValue("P1")));
p2Label.setText(normalize(point.getValue("P2")));
p3Label.setText(normalize(point.getValue("P3")));
pxLabel.setText(normalize(point.getValue("Px")));
});
}
private String normalize(Value val) {
if (val.valueType() == ValueType.NUMBER) {
return String.format("%.2e", val.doubleValue());
} else {
return String.format("%s", val.stringValue());
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel chartPannel;
private javax.swing.JTextArea consoleBox;
private javax.swing.JComboBox delayBox;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel7;
private javax.swing.JPanel optionsPanel;
private javax.swing.JLabel p1Label;
private javax.swing.JToggleButton p1Power;
private javax.swing.JLabel p2Label;
private javax.swing.JLabel p3Label;
private javax.swing.JLabel pxLabel;
private javax.swing.JComboBox rangeBox;
private javax.swing.JScrollPane scroll;
private javax.swing.JSplitPane split;
private javax.swing.JLabel timeLabel;
private javax.swing.JPanel valuesPanel;
// End of variables declaration//GEN-END:variables
private class JTextAreaAppender extends AppenderBase<ILoggingEvent> {
private Encoder<ILoggingEvent> encoder = new EchoEncoder<ILoggingEvent>();
private ByteArrayOutputStream out = new ByteArrayOutputStream();
private JTextArea textArea;
public JTextAreaAppender(JTextArea textArea) {
this.textArea = textArea;
}
@Override
public void start() {
try {
encoder.init(out);
} catch (IOException e) {
}
super.start();
}
@Override
public void append(ILoggingEvent event) {
try {
encoder.doEncode(event);
out.flush();
String line = out.toString();
textArea.append(line);
out.reset();
} catch (IOException e) {
}
}
}
}

View File

@ -0,0 +1,223 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.readvac;
import hep.dataforge.data.DataFormatBuilder;
import hep.dataforge.meta.Meta;
import hep.dataforge.data.DataPoint;
import hep.dataforge.exceptions.StorageException;
import hep.dataforge.storage.api.PointLoader;
import hep.dataforge.storage.api.Storage;
import hep.dataforge.storage.commons.LoaderFactory;
import hep.dataforge.values.ValueType;
import java.time.Instant;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.SwingUtilities;
import jssc.SerialPortException;
import org.slf4j.LoggerFactory;
/**
*
* @author Darksnake
*/
public class VACManager implements AutoCloseable {
public static String[] names = {"timestamp", "P1", "P2", "P3", "Px"};
private VACFrame frame;
private Timer timer;
private int timerInterval = 5000;
// private boolean isValuesShowing;
// private boolean isLogShowing;
private final PointLoader loader;
private VACDeviceReader device;
private final Iterator<DataPoint> reader; // Чтение из файла или непосредтсвенно с прибора
private Instant lastUpdate;
// public static VACManager fromDirectory(Storage server, String sourceDir, String runPrefix) throws StorageException, FileNotFoundException {
// return new VACManager(setupLoader(server, runPrefix), VACFileReader.fromDirectory(sourceDir));
// }
public static VACManager fromSerial(Storage server, String run, Meta serialConfig) throws StorageException, SerialPortException {
return new VACManager(setupLoader(server, run), new VACDeviceReader(serialConfig));
}
public VACManager(PointLoader loader, Iterator<DataPoint> reader) {
this.loader = loader;
this.reader = reader;
showPlot();
}
public VACManager(PointLoader loader, VACDeviceReader reader) {
this.loader = loader;
this.reader = reader;
this.device = reader;
showPlot();
}
private static PointLoader setupLoader(Storage storage, String run) throws StorageException {
return LoaderFactory.buildPointLoder(storage, "vactms", run, "timestamp",
new DataFormatBuilder(names)
.setFormat("timestamp", ValueType.TIME)
.build());
}
/**
* @return the timerInterval
*/
public int getTimerInterval() {
return timerInterval;
}
/**
* Интервал в милисекундах
*
* @param millis
*/
public void setTimerInterval(int millis) {
this.timerInterval = millis;
//Перезапускаем таймер, чтобы обновились интервалы
stop();
start();
// setAutoRange(millis*500);
}
public void start() {
timer = new Timer("UpdateTimer");
timer.scheduleAtFixedRate(getTimerTask(), 0, getTimerInterval());
}
public void stop() {
timer.cancel();
}
@Override
public void close() throws Exception {
stop();
if (device != null) {
device.close();
}
loader.close();
}
public final void showPlot() {
if (frame != null) {
if (frame.isDisplayable()) {
frame.setVisible(true);
} else {
//Подчищаем неправильно закрытые окна
frame.dispose();
frame = null;
}
}
if (frame == null) {
SwingUtilities.invokeLater(() -> {
frame = VACFrame.display(VACManager.this);
});
}
}
public DataPoint readPoint() {
return reader.next();
}
public boolean hasNextPoint() {
return reader.hasNext();
}
/**
* Пропускаем все точки, до определенного момента. Возвращаем последнюю
* точку в списке, или первую, время которой больше, чем у заданной
*
* @param time
* @return
*/
public DataPoint skipUntil(Instant time) {
if (reader.hasNext()) {
DataPoint point = reader.next();
while (point.getValue("timestamp").timeValue().isBefore(time) && reader.hasNext()) {
point = reader.next();
}
return point;
} else {
return null;
}
}
public boolean p1Available() {
return (device != null) && (device.isP1Available());
}
public boolean getP1PowerState() throws P1ControlException {
try {
if (device == null) {
throw new P1ControlException("P1 control is not initialized");
}
return device.getP1PowerState();
} catch (SerialPortException | ResponseParseException ex) {
throw new P1ControlException("Can't read P1 answer");
}
}
public boolean setP1PowerStateOn(boolean state) throws P1ControlException {
try {
if (device == null) {
throw new P1ControlException("P1 control is not initialized");
}
return device.setP1PowerStateOn(state);
} catch (SerialPortException | ResponseParseException ex) {
throw new P1ControlException("Can't read P1 answer");
}
}
private TimerTask getTimerTask() {
return new TimerTask() {
@Override
public void run() {
try {
// while (hasNextPoint()) {
if (hasNextPoint()) {
DataPoint point = readPoint();
// На всякий случай берем время на секунду назад, чтобы не было накладок с пропусками
// DataPoint point = skipUntil(Instant.now().minusSeconds(1));
//Проверяем, что точка получена
if (point != null) {
//Если точка старая, то не обновляем ничего
Instant pointTime = point.getValue("timestamp").timeValue();
if (lastUpdate != null && pointTime.isAfter(lastUpdate)) {
loader.push(point);
if (frame != null) {
frame.displayPoint(point);
}
}
lastUpdate = pointTime;
}
}
} catch (Exception ex) {
LoggerFactory.getLogger(VACManager.class).error("Unexpected error during point aquisition", ex);
}
}
};
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<config>
<storage path="/home/numass-storage/"/>
<serialconfig P1="/dev/ttyUSB0" P2="/dev/ttyS5" P3="/dev/ttyS4" Px="/dev/ttyUSB1"/>
<run>12_2015.test</run>
</config>

View File

@ -0,0 +1,45 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.readvac;
/**
*
* @author Darksnake
*/
public class TestMain {
/**
* @param args the command line arguments
* @throws java.lang.Exception
*/
public static void main(String[] args) throws Exception {
// File serverDir = new File("d:\\temp\\test\\remote\\");
// NetworkListner listner = new NetworkListner(new FileDataServer(serverDir, null), null);
// listner.start();
// Annotation config = new XMLAnnotationParser().fromStream(null, TestMain.class.getResourceAsStream("testConfig.xml"));
// Main.runConfig(config);
//
// Runtime.getRuntime().addShutdownHook(new Thread(() -> {
// try {
// listner.close();
// } catch (IOException ex) {
// LoggerFactory.getLogger("test").error(null, ex);
// }
// }));
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.readvac;
/**
*
* @author Darksnake
*/
public class TestRemote {
/**
* @param args the command line arguments
* @throws java.lang.Exception
*/
public static void main(String[] args) throws Exception {
// Annotation config = new XMLAnnotationParser().fromStream(null, TestRemote.class.getResourceAsStream("testConfig.xml"));
// Main.runConfig(config);
// System.exit(0);
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.readvac;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
/**
*
* @author Darksnake
*/
public class TimeShiftTest {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Instant now = Instant.now();
System.out.println(now.toString());
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt.toString());
System.out.println(ldt.toInstant(ZoneOffset.ofHours(1)).toString());
ZonedDateTime zdt = ZonedDateTime.now();
System.out.println(zdt.toString());
System.out.println(zdt.toInstant());
System.out.println(ZoneId.systemDefault().getRules().toString());
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<config>
<storage path="/home/numass-storage/"/>
<serialconfig P1="/dev/ttyUSB0" P2="/dev/ttyS5" P3="/dev/ttyS4" Px="/dev/ttyUSB1"/>
<run>12_2015</run>
</config>

47
numass-main/build.gradle Normal file
View File

@ -0,0 +1,47 @@
apply plugin: 'application'
if (!hasProperty('mainClass')) {
ext.mainClass = 'inr.numass.Main'
}
mainClassName = mainClass
description = """The main head of all numass projects"""
ext{
defaultNumassPath = 'D:\\loss-2011\\'
}
dependencies {
compile group: 'commons-cli', name: 'commons-cli', version:'1.+'
compile group: 'commons-io', name: 'commons-io', version:'2.+'
compile project(':dataforge-fitting:dataforge-minuit')
compile project(':dataforge-fx')
compile project(':dataforge-grind')
compile project(':dataforge-plots')
}
task runNumass(dependsOn: classes, type : JavaExec){
main mainClass
classpath = sourceSets.main.runtimeClasspath
workingDir defaultNumassPath
description "run Main method in the current numass working directory"
group "numass"
}
task debugNumass(dependsOn: classes, type: JavaExec) {
main mainClass
classpath = sourceSets.main.runtimeClasspath
workingDir defaultNumassPath
ignoreExitValue = true
debug = true
description "debug Main method in the current numass working directory"
group "numass"
}
task listActions(dependsOn: classes, type: JavaExec) {
main mainClass
args "-lc"
classpath = sourceSets.main.runtimeClasspath
description "print a list of available actions as via -lc command line parameter"
group "numass"
}

View File

@ -0,0 +1,15 @@
#
# Copyright 2015 Alexander Nozik.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

View File

@ -0,0 +1,94 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts
import hep.dataforge.datafitter.ParamSet
import hep.dataforge.io.FittingIOUtils
import hep.dataforge.io.PrintFunction
import hep.dataforge.maths.NamedDoubleArray
import hep.dataforge.maths.NamedDoubleSet
import hep.dataforge.maths.NamedMatrix
import hep.dataforge.plots.PlotFrame
import hep.dataforge.plots.data.PlottableFunction
import hep.dataforge.plots.jfreechart.JFreeChartFrame
import inr.numass.actions.ShowLossSpectrumAction;
import inr.numass.models.ExperimentalVariableLossSpectrum
import inr.numass.models.LossCalculator
import org.apache.commons.math3.analysis.UnivariateFunction
NamedDoubleSet transformOldMeans(NamedDoubleSet old){
String[] names = ["exPos", "ionPos", "exW", "ionW", "exIonRatio"];
double[] values = new double[5];
values[0] = old.getValue("loss_pos1");
values[1] = old.getValue("loss_pos2");
values[2] = old.getValue("loss_w1");
values[3] = old.getValue("loss_w2");
values[4] = old.getValue("loss_A1") / old.getValue("loss_A2");
return new NamedDoubleArray(names, values);
}
ParamSet transformOldParams(ParamSet old){
String[] names = ["exPos", "ionPos", "exW", "ionW", "exIonRatio"];
ParamSet res = new ParamSet(names);
res.setPar("exPos", old.getValue("loss_pos1"), old.getError("loss_pos1"));
res.setPar("ionPos", old.getValue("loss_pos2"), old.getError("loss_pos2"));
res.setPar("exW", old.getValue("loss_w1"), old.getError("loss_w1"));
res.setPar("ionW", old.getValue("loss_w2"), old.getError("loss_w2"));
double ratioValue = old.getValue("loss_A1") / old.getValue("loss_A2");
double a1RelErr = old.getError("loss_A1") / old.getValue("loss_A1");
double a2RelErr = old.getError("loss_A2") / old.getValue("loss_A2");
double ratioErr = Math.sqrt(a1RelErr*a1RelErr + a2RelErr*a2RelErr)*ratioValue;
res.setPar("exIonRatio", ratioValue, ratioErr);
return res;
}
PrintWriter out = new PrintWriter(System.out);
String name = "log14_h2_new"
//String name = "log18_long"
//String name = "log25_long"
OldFitResultReader reader = new OldFitResultReader();
reader.readFile(new File("C:\\Users\\darksnake\\Dropbox\\Numass\\Analysis\\loss-2014_november\\old_loss\\results\\final\\${name}.txt"));
double threshold = 17d;
ParamSet means = transformOldParams (reader.getParamSet());
double ionRatio = ShowLossSpectrumAction.calcultateIonRatio(means, threshold);
NamedMatrix cov = NamedMatrix.diagonal(means.getParErrors());
double ionRatioError = ShowLossSpectrumAction.calultateIonRatioError(name, means, cov, threshold);
println String.format("The ionization ratio (using threshold %f) is %f%n", threshold, ionRatio);
println String.format("The ionization ratio standard deviation (using threshold %f) is %f%n", threshold, ionRatioError);
println "*** FIT RESULT ***"
FittingIOUtils.printParamSet(out, means);
println means.toString();
UnivariateFunction scatterFunction = LossCalculator.getSingleScatterFunction(means);
PlotFrame frame = JFreeChartFrame.drawFrame("Differential scattering crossection for "+name, null);
frame.add(new PlottableFunction("Cross-section", null, scatterFunction, 0, 100, 1000));
PrintFunction.printFunctionSimple(out, scatterFunction, 0, 100, 500);

View File

@ -0,0 +1,115 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts
import hep.dataforge.datafitter.ParamSet
import hep.dataforge.maths.integration.RiemanIntegrator
import hep.dataforge.maths.integration.UnivariateIntegrator
import hep.dataforge.plots.PlotFrame
import hep.dataforge.plots.data.PlottableFunction
import hep.dataforge.plots.jfreechart.JFreeChartFrame
import org.apache.commons.math3.analysis.UnivariateFunction
import org.apache.commons.math3.analysis.solvers.BisectionSolver
import inr.numass.models.LossCalculator
import inr.numass.models.ResolutionFunction
import inr.numass.NumassContext
ParamSet params = new ParamSet()
.setParValue("exPos", 12.76)
.setParValue("ionPos", 13.95)
.setParValue("exW", 1.2)
.setParValue("ionW", 13.5)
.setParValue("exIonRatio", 4.55)
UnivariateFunction scatterFunction = LossCalculator.getSingleScatterFunction(params);
PlotFrame frame = JFreeChartFrame.drawFrame("Differential scatter function", null);
frame.add(new PlottableFunction("differential", null, scatterFunction, 0, 100, 400));
UnivariateIntegrator integrator = NumassContext.defaultIntegrator;
double border = 13.6;
UnivariateFunction ratioFunction = {e->integrator.integrate(scatterFunction, 0 , e) / integrator.integrate(scatterFunction, e, 100)}
double ratio = ratioFunction.value(border);
println "The true excitation to ionization ratio with border energy $border is $ratio";
double resolution = 1.5d;
def X = 0.527;
LossCalculator calculator = new LossCalculator();
List<Double> lossProbs = calculator.getGunLossProbabilities(X);
UnivariateFunction newScatterFunction = { double d ->
double res = scatterFunction.value(d);
for(i = 1; i < lossProbs.size(); i++){
res += lossProbs.get(i) * calculator.getLossValue(i, d, 0);
}
return res;
}
UnivariateFunction resolutionValue = {double e ->
if (e <= 0d) {
return 0d;
} else if (e >= resolution) {
return 1d;
} else {
return e/resolution;
}
};
UnivariateFunction integral = {double u ->
if(u <= 0d){
return 0d;
} else {
UnivariateFunction integrand = {double e -> resolutionValue.value(u-e) * newScatterFunction.value(e)};
return integrator.integrate(integrand, 0d, u)
}
}
frame.add(new PlottableFunction("integral", null, integral, 0, 100, 800));
BisectionSolver solver = new BisectionSolver(1e-3);
UnivariateFunction integralShifted = {u ->
def integr = integral.value(u);
return integr/(1-integr) - ratio;
}
double integralBorder = solver.solve(400, integralShifted, 10d, 20d);
println "The integral border is $integralBorder";
double newBorder = 14.43
double integralValue = integral.value(newBorder);
double err = Math.abs(integralValue/(1-integralValue)/ratio - 1d)
println "The relative error ic case of using $newBorder instead of real one is $err";

View File

@ -0,0 +1,18 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts
inr.numass.context.Main.main("-lc")

View File

@ -0,0 +1,29 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts
import hep.dataforge.actions.Pack
import hep.dataforge.datafitter.FitTaskResult
import inr.numass.Main
import inr.numass.NumassContext
//Main.main("-lc")
NumassContext context = new NumassContext();
context.putValue("integralThreshold", 15d);
Pack resultPack = Main.run(context, "-c","D:\\sterile-new\\loss2014-11\\d2_19_1.xml")
FitTaskResult result = resultPack.getData().value()
result.print(new PrintWriter(System.out))

View File

@ -0,0 +1,41 @@
/*
* 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.scripts
import hep.dataforge.maths.integration.GaussRuleIntegrator;
import hep.dataforge.maths.integration.UnivariateIntegrator;
import inr.numass.models.LossCalculator;
import org.apache.commons.math3.analysis.UnivariateFunction
UnivariateIntegrator integrator = new GaussRuleIntegrator(400);
def exPos = 12.878;
def ionPos = 13.86;
def exW = 1.32;
def ionW = 12.47;
def exIonRatio = 3.96;
def cutoff = 25d
UnivariateFunction loss = LossCalculator.getSingleScatterFunction(exPos, ionPos, exW, ionW, exIonRatio);
println integrator.integrate(loss,0,600);
println integrator.integrate(loss,0,cutoff);
println integrator.integrate(loss,cutoff,600d);
println (integrator.integrate(loss,0,cutoff) + integrator.integrate(loss,cutoff,3000d));
//double tailValue = (Math.atan((ionPos-cutoff)*2d/ionW) + 0.5*Math.PI)*ionW/2;
//println tailValue
//println integrator.integrate(loss,0,100);
//println integrator.integrate(loss,100,600);
//def lorentz = {eps->
// double z = 4 * (eps - ionPos) * (eps - ionPos);
// 1 / (1 + z / ionW / ionW);
//}
//
//println(integrator.integrate(lorentz, cutoff, 800))

View File

@ -0,0 +1,110 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts
import hep.dataforge.datafitter.ParamSet
import hep.dataforge.maths.NamedDoubleArray
import hep.dataforge.maths.NamedDoubleSet
import hep.dataforge.maths.NamedMatrix
import java.util.regex.Pattern
import org.apache.commons.math3.linear.Array2DRowRealMatrix
import org.apache.commons.math3.linear.RealMatrix
import java.util.Scanner
import java.util.regex.Matcher
/**
*
* @author darksnake
*/
class OldFitResultReader {
private static Pattern meanPattern = ~/\"(?<name>.*)\"\s*:\s*(?<value>[\d.]*)\s*/;
private NamedDoubleSet means;
private RealMatrix covariance;
void readMeans(String input){
Scanner scan = new Scanner(input);
List<String> names = new ArrayList<>();
List<Double> values = new ArrayList<>();
while(scan.hasNextLine()){
String nextLine = scan.nextLine();
if(!nextLine.isEmpty()){
Matcher match = meanPattern.matcher(nextLine);
match.matches();
names << match.group("name");
values << Double.parseDouble(match.group("value"));
}
}
this.means = new NamedDoubleArray(names.toArray(new String[names.size()]), values.toArray(new double[values.size()]));
}
void readCovariance(String input){
Scanner scan = new Scanner(input);
List<List<Double>> matrix = new ArrayList<>();
while(scan.hasNextLine()){
String nextLine = scan.nextLine();
if(!nextLine.isEmpty()){
Scanner lineScan = new Scanner(nextLine);
List<Double> line = new ArrayList<>();
while(lineScan.hasNextDouble()){
line << lineScan.nextDouble();
}
matrix << line;
}
}
Array2DRowRealMatrix result = new Array2DRowRealMatrix(matrix.size(),matrix.size());
for(int i = 0; i< matrix.size; i++){
List<Double> line = matrix.get(i);
for(int j = 0; j< matrix.size; j++){
result.setEntry(i,j,line[j]);
}
}
this.covariance = result;
}
void readFile(File file){
String text = file.getText();
Pattern pattern = Pattern.compile(/.*The best fit values are:\s*(?<parameters>.*)Covariation marix:\s*(?<covariance>.*)Best Likelihood logarithm/, Pattern.DOTALL);
List results = text.findAll(pattern);
String res = results.get(results.size()-1);
Matcher match = pattern.matcher(res);
match.matches();
readMeans(match.group("parameters"));
readCovariance(match.group("covariance"));
}
NamedDoubleSet getMeans(){
return means;
}
ParamSet getParamSet(){
ParamSet res = new ParamSet();
NamedMatrix cov = getCovariance();
for(String name: means.names()){
res.setPar(name, means.getValue(name), Math.sqrt(Math.abs(cov.getElement(name, name))));
}
return res;
}
NamedMatrix getCovariance(){
return new NamedMatrix(covariance, means.namesAsArray());
}
}

View File

@ -0,0 +1,112 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts;
import hep.dataforge.context.GlobalContext;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.datafitter.FitManager;
import hep.dataforge.datafitter.FitState;
import hep.dataforge.datafitter.MINUITPlugin
import hep.dataforge.datafitter.ParamSet;
import hep.dataforge.datafitter.models.XYModel;
import hep.dataforge.likelihood.BayesianManager
import inr.numass.data.SpectrumDataAdapter
import inr.numass.models.BetaSpectrum;
import inr.numass.models.ModularSpectrum;
import inr.numass.models.ModularTritiumSpectrum
import inr.numass.models.NBkgSpectrum;
import inr.numass.models.RangedNamedSetSpectrum;
import inr.numass.models.ResolutionFunction
import static inr.numass.utils.OldDataReader.readData;
import java.io.File;
import java.io.PrintWriter;
import java.util.Locale;
import org.apache.commons.math3.analysis.BivariateFunction
import inr.numass.models.ResolutionFunction
PrintWriter out = GlobalContext.out();
Locale.setDefault(Locale.US);
new MINUITPlugin().startGlobal();
FitManager fm = new FitManager();
// setSeed(543982);
File fssfile = new File("c:\\Users\\Darksnake\\Dropbox\\PlayGround\\FS.txt");
BivariateFunction resolution = new ResolutionFunction(2.28e-4);
resolution.setTailFunction(ResolutionFunction.getRealTail())
ModularTritiumSpectrum sp = new ModularTritiumSpectrum(resolution, 18395d, 18580d, fssfile);
sp.setCaching(false);
//RangedNamedSetSpectrum beta = new BetaSpectrum(fssfile);
//ModularSpectrum sp = new ModularSpectrum(beta, 2.28e-4, 18395d, 18580d);
// ModularTritiumSpectrum beta = new ModularTritiumSpectrum(2.28e-4, 18395d, 18580d, "d:\\PlayGround\\FS.txt");
NBkgSpectrum spectrum = new NBkgSpectrum(sp);
XYModel model = new XYModel("tritium", spectrum, new SpectrumDataAdapter());
ParamSet allPars = new ParamSet();
allPars.setParValue("N", 602533.94);
//значение 6е-6 соответствует полной интенстивности 6е7 распадов в секунду
//Проблема была в переполнении счетчика событий в генераторе. Заменил на long. Возможно стоит поставить туда число с плавающей точкой
allPars.setParError("N", 1000);
allPars.setParDomain("N", 0d, Double.POSITIVE_INFINITY);
allPars.setParValue("bkg", 0.012497889);
allPars.setParError("bkg", 1e-4);
allPars.setParValue("E0", 18575.986);
allPars.setParError("E0", 0.05);
allPars.setParValue("mnu2", 0d);
allPars.setParError("mnu2", 1d);
allPars.setParValue("msterile2", 50 * 50);
allPars.setParValue("U2", 0);
allPars.setParError("U2", 1e-2);
allPars.setParDomain("U2", -1d, 1d);
allPars.setParValue("X", 0.47);
allPars.setParError("X", 0.014);
allPars.setParDomain("X", 0d, Double.POSITIVE_INFINITY);
allPars.setParValue("trap", 1d);
allPars.setParError("trap", 0.2d);
allPars.setParDomain("trap", 0d, Double.POSITIVE_INFINITY);
ListDataSet data = readData("c:\\Users\\Darksnake\\Dropbox\\PlayGround\\RUN23.DAT", 18400d);
FitState state = fm.buildState(data, model, allPars);
FitState res = fm.runDefaultTask(state, "E0", "N", "bkg");
res = fm.runDefaultTask(res, "E0", "N", "bkg", "U2");
res.print(out);
//spectrum.counter.print(out);
//
//// fm.setPriorProb(new GaussianPrior("X", 0.47, 0.47*0.03));
//// fm.setPriorProb(new MultivariateGaussianPrior(allPars.getSubSet("X","trap")));
//res = fm.runTask(res, "MINUIT", "run", "E0", "N", "bkg", "mnu2");
////
//res.print(out);
//sp.setCaching(true);
//sp.setSuppressWarnings(true);
//
//BayesianManager bm = new BayesianManager();
//bm.printMarginalLikelihood(out, "U2", res, ["E0", "N", "bkg", "U2", "X"], 10000);
// PrintNamed.printLike2D(Out.out, "like", res, "N", "E0", 30, 60, 2);

View File

@ -0,0 +1,52 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts;
import hep.dataforge.plots.jfreechart.JFreeChartFrame;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import org.slf4j.LoggerFactory;
/**
* A basic plot viewer for serialized JFreeChart plots
*
* @author Darksnake
*/
public class PlotViewer {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
if (args.length > 0) {
for (String arg : args) {
File ser = new File(arg);
try {
FileInputStream stream = new FileInputStream(ser);
ObjectInputStream ostr = new ObjectInputStream(stream);
JFreeChartFrame.deserialize(ostr);
} catch (IOException ex) {
LoggerFactory.getLogger(PlotViewer.class).error("IO error during deserialization", ex);
} catch (ClassNotFoundException ex) {
LoggerFactory.getLogger(PlotViewer.class).error("Wrong serialized content type", ex);
}
}
}
}
}

View File

@ -0,0 +1,46 @@
/*
* 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.scripts
import inr.numass.models.LossCalculator
LossCalculator loss = new LossCalculator();
def X = 0.6
def lossProbs = loss.getGunLossProbabilities(X);
printf("%8s\t%8s\t%8s\t%8s\t%n",
"eps",
"p1",
"p2",
"p3"
)
def singleScatter = loss.getSingleScatterFunction();
for(double d = 0; d < 30; d += 0.3){
double ei = 18500;
double ef = ei-d;
printf("%8f\t%8f\t%8f\t%8f\t%n",
d,
lossProbs[1]*loss.getLossValue(1,ei,ef),
lossProbs[2]*loss.getLossValue(2,ei,ef),
lossProbs[3]*loss.getLossValue(3,ei,ef)
)
}
for(double d = 30; d < 100; d += 1){
double ei = 18500;
double ef = ei-d;
printf("%8f\t%8f\t%8f\t%8f\t%n",
d,
lossProbs[1]*loss.getLossValue(1,ei,ef),
lossProbs[2]*loss.getLossValue(2,ei,ef),
lossProbs[3]*loss.getLossValue(3,ei,ef)
)
}

View File

@ -0,0 +1,92 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts;
import hep.dataforge.context.GlobalContext;
import static hep.dataforge.context.GlobalContext.out;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.datafitter.FitManager;
import hep.dataforge.datafitter.FitState;
import hep.dataforge.datafitter.FitTask;
import hep.dataforge.datafitter.ParamSet;
import hep.dataforge.datafitter.models.XYModel;
import hep.dataforge.exceptions.NamingException;
import inr.numass.data.SpectrumDataAdapter;
import inr.numass.data.SpectrumGenerator;
import inr.numass.models.ModularTritiumSpectrum;
import inr.numass.models.NBkgSpectrum;
import inr.numass.utils.DataModelUtils;
import java.io.FileNotFoundException;
import java.util.Locale;
import static java.util.Locale.setDefault;
/**
*
* @author Darksnake
*/
setDefault(Locale.US);
GlobalContext global = GlobalContext.instance();
// global.loadModule(new MINUITModule());
FitManager fm = new FitManager();
ModularTritiumSpectrum beta = new ModularTritiumSpectrum(9e-5, 14390d, 19001d, null);
beta.setCaching(false);
NBkgSpectrum spectrum = new NBkgSpectrum(beta);
XYModel model = new XYModel("tritium", spectrum, new SpectrumDataAdapter());
ParamSet allPars = new ParamSet();
allPars.setParValue("N", 3e5);
//значение 6е-6 соответствует полной интенстивности 6е7 распадов в секунду
//Проблема была в переполнении счетчика событий в генераторе. Заменил на long. Возможно стоит поставить туда число с плавающей точкой
allPars.setParError("N", 6);
allPars.setParDomain("N", 0d, Double.POSITIVE_INFINITY);
allPars.setParValue("bkg", 2d);
allPars.setParError("bkg", 0.03);
allPars.setParValue("E0", 18575.0);
allPars.setParError("E0", 2);
allPars.setParValue("mnu2", 0d);
allPars.setParError("mnu2", 1d);
allPars.setParValue("msterile2", 1000 * 1000);
allPars.setParValue("U2", 0);
allPars.setParError("U2", 1e-4);
allPars.setParDomain("U2", -1d, 1d);
allPars.setParValue("X", 0);
allPars.setParError("X", 0.01);
allPars.setParDomain("X", 0d, Double.POSITIVE_INFINITY);
allPars.setParValue("trap", 0);
allPars.setParError("trap", 0.01d);
allPars.setParDomain("trap", 0d, Double.POSITIVE_INFINITY);
// PrintNamed.printSpectrum(GlobalContext.out(), spectrum, allPars, 0.0, 18700.0, 600);
//String fileName = "d:\\PlayGround\\merge\\scans.out";
// String configName = "d:\\PlayGround\\SCAN.CFG";
// ListDataSet config = OldDataReader.readConfig(configName);
SpectrumGenerator generator = new SpectrumGenerator(model, allPars, 12316);
ListDataSet data = generator.generateData(DataModelUtils.getUniformSpectrumConfiguration(13500d, 18200, 1e6, 60));
// data = data.filter("X", Value.of(15510.0), Value.of(18610.0));
// allPars.setParValue("X", 0.4);
FitState state = fm.buildState(data, model, allPars);
FitState res = fm.runTask(state, "QOW", FitTask.TASK_RUN, "N", "bkg", "E0", "U2");
res.print(out());

View File

@ -0,0 +1,42 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts
import static groovy.io.FileType.*
import org.apache.commons.io.FilenameUtils
File dir = new File("D:\\loss-2014\\");
File resultDir = new File(dir, ".dataforge\\showLoss\\");
if(!resultDir.exists()){
resultDir.mkdirs()
}
File resultFile = new File(resultDir,"summary");
resultFile.setText("name\tX\tX_err\texPos\texPos_err\tionPos\tionPos_err\texW\texW_err\tionW\tionW_err\texIonRatio\texIonRatio_err\tionRatio\tionRatioErr\tchi\r\n");
dir.eachFileMatch FILES, {it ==~ /[dh]2_\d\d_\d(?:_bkg)?\.xml/}, {
try{
inr.numass.Main.main("-c", it.getAbsolutePath())
File outFile = new File(resultDir, FilenameUtils.getBaseName(it.getName())+"_loss.out")
resultFile.append(outFile.readLines().get(50));
resultFile.append("\r\n");
} catch(Exception ex){
ex.printStackTrace();
}
}

View File

@ -0,0 +1,112 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts;
import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.context.GlobalContext;
import hep.dataforge.datafitter.ParamSet;
import inr.numass.data.SpectrumInformation;
import inr.numass.models.ModularTritiumSpectrum;
import inr.numass.models.NBkgSpectrum;
import inr.numass.models.ResolutionFunction;
import java.util.HashMap;
import java.util.Locale;
import static java.util.Locale.setDefault;
import java.util.Map;
import org.apache.commons.math3.analysis.UnivariateFunction;
setDefault(Locale.US);
GlobalContext global = GlobalContext.instance();
// global.loadModule(new MINUIT());
// FitManager fm = new FitManager("data 2013");
UnivariateFunction reolutionTail = {x ->
if (x > 1500) {
return 0.98;
} else //Intercept = 1.00051, Slope = -1.3552E-5
{
return 1.00051 - 1.3552E-5 * x;
}
};
ModularTritiumSpectrum beta = new ModularTritiumSpectrum(
new ResolutionFunction(8.3e-5, reolutionTail), 14490d, 19001d, null);
beta.setCaching(false);
NBkgSpectrum spectrum = new NBkgSpectrum(beta);
// XYModel model = new XYModel("tritium", spectrum);
ParamSet allPars = new ParamSet();
allPars.setParValue("N", 3090.1458);
//значение 6е-6 соответствует полной интенстивности 6е7 распадов в секунду
//Проблема была в переполнении счетчика событий в генераторе. Заменил на long. Возможно стоит поставить туда число с плавающей точкой
allPars.setParError("N", 6);
allPars.setParDomain("N", 0d, Double.POSITIVE_INFINITY);
allPars.setParValue("bkg", 2.2110028);
allPars.setParError("bkg", 0.03);
allPars.setParValue("E0", 18580.742);
allPars.setParError("E0", 2);
allPars.setParValue("mnu2", 0d);
allPars.setParError("mnu2", 1d);
allPars.setParValue("msterile2", 1000 * 1000);
allPars.setParValue("U2", 0);
allPars.setParError("U2", 1e-4);
allPars.setParDomain("U2", -1d, 1d);
allPars.setParValue("X", 1.0);
allPars.setParError("X", 0.01);
allPars.setParDomain("X", 0d, Double.POSITIVE_INFINITY);
allPars.setParValue("trap", 1.0d);
allPars.setParError("trap", 0.01d);
allPars.setParDomain("trap", 0d, Double.POSITIVE_INFINITY);
SpectrumInformation sign = new SpectrumInformation(spectrum);
// double Elow = 14000d;
// double Eup = 18600d;
// int numpoints = (int) ((Eup - Elow) / 50);
// double time = 1e6 / numpoints;
// DataSet config = getUniformSpectrumConfiguration(Elow, Eup, time, numpoints);
// NamedMatrix infoMatrix = sign.getInformationMatrix(allPars, config,"U2","E0","N");
//
// PrintNamed.printNamedMatrix(Out.out, infoMatrix);
// NamedMatrix cov = sign.getExpetedCovariance(allPars, config,"U2","E0","N");
//
// PrintWriter out = GlobalContext.out();
//
// printNamedMatrix(out, cov);
//
// cov = sign.getExpetedCovariance(allPars, config,"U2","E0","N","X");
//
// printNamedMatrix(out, cov);
//PlotManager pm = new PlotManager();
Map<String, UnivariateFunction> functions = new HashMap<>();
functions.put("U2", sign.getSignificanceFunction(allPars, "U2", "U2"));
// functions.put("UX", sign.getSignificanceFunction(allPars, "U2", "X"));
functions.put("X", sign.getSignificanceFunction(allPars, "X", "X"));
functions.put("trap", sign.getSignificanceFunction(allPars, "trap", "trap"));
functions.put("E0", sign.getSignificanceFunction(allPars, "E0", "E0"));
MetaBuilder builder = new MetaBuilder("significance");
builder.putValue("from", 14000d);
builder.putValue("to", 18500d);
pm.plotFunction(builder.build(), functions);
// printFuntionSimple(out(), func, 14000d, 18600d, 200);

View File

@ -0,0 +1,100 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts;
import hep.dataforge.context.GlobalContext;
import static hep.dataforge.context.GlobalContext.out;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.datafitter.FitManager;
import hep.dataforge.datafitter.FitState;
import hep.dataforge.datafitter.FitTask;
import hep.dataforge.datafitter.MINUITPlugin
import hep.dataforge.datafitter.ParamSet;
import hep.dataforge.datafitter.models.XYModel;
import hep.dataforge.exceptions.NamingException;
import hep.dataforge.exceptions.PackFormatException;
import inr.numass.data.SpectrumDataAdapter;
import inr.numass.data.SpectrumGenerator;
import inr.numass.models.ModularTritiumSpectrum;
import inr.numass.models.NBkgSpectrum;
import inr.numass.utils.DataModelUtils;
import hep.dataforge.plotfit.PlotFitResultAction;
import java.io.FileNotFoundException;
import java.util.Locale;
import static java.util.Locale.setDefault;
/**
*
* @author Darksnake
*/
setDefault(Locale.US);
new MINUITPlugin().startGlobal();
// global.loadModule(new MINUITModule());
FitManager fm = new FitManager();
ModularTritiumSpectrum beta = new ModularTritiumSpectrum(8.3e-5, 14390d, 19001d, null);
beta.setCaching(false);
NBkgSpectrum spectrum = new NBkgSpectrum(beta);
XYModel model = new XYModel("tritium", spectrum, new SpectrumDataAdapter());
ParamSet allPars = new ParamSet();
allPars.setParValue("N", 3e5);
//значение 6е-6 соответствует полной интенстивности 6е7 распадов в секунду
//Проблема была в переполнении счетчика событий в генераторе. Заменил на long. Возможно стоит поставить туда число с плавающей точкой
allPars.setParError("N", 6);
allPars.setParDomain("N", 0d, Double.POSITIVE_INFINITY);
allPars.setParValue("bkg", 2d);
allPars.setParError("bkg", 0.03);
allPars.setParValue("E0", 18575.0);
allPars.setParError("E0", 2);
allPars.setParValue("mnu2", 0d);
allPars.setParError("mnu2", 1d);
allPars.setParValue("msterile2", 1000 * 1000);
allPars.setParValue("U2", 0);
allPars.setParError("U2", 1e-4);
allPars.setParDomain("U2", -1d, 1d);
allPars.setParValue("X", 0);
allPars.setParError("X", 0.01);
allPars.setParDomain("X", 0d, Double.POSITIVE_INFINITY);
allPars.setParValue("trap", 0);
allPars.setParError("trap", 0.01d);
allPars.setParDomain("trap", 0d, Double.POSITIVE_INFINITY);
// PrintNamed.printSpectrum(GlobalContext.out(), spectrum, allPars, 0.0, 18700.0, 600);
//String fileName = "d:\\PlayGround\\merge\\scans.out";
// String configName = "d:\\PlayGround\\SCAN.CFG";
// ListDataSet config = OldDataReader.readConfig(configName);
SpectrumGenerator generator = new SpectrumGenerator(model, allPars, 12316);
ListDataSet data = generator.generateData(DataModelUtils.getUniformSpectrumConfiguration(13500d, 18200, 1e6, 60));
// data = data.filter("X", Value.of(15510.0), Value.of(18610.0));
// allPars.setParValue("X", 0.4);
FitState state = FitManager.buildState(data, model, allPars);
new PlotFitResultAction(GlobalContext.instance(), null).runOne(state);
FitState res = fm.runTask(state, "QOW", FitTask.TASK_RUN, "N", "bkg", "E0", "U2");
res.print(out());

View File

@ -0,0 +1,71 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts;
import hep.dataforge.context.GlobalContext;
import hep.dataforge.datafitter.FitManager;
import hep.dataforge.datafitter.ParamSet;
import hep.dataforge.datafitter.models.XYModel;
import hep.dataforge.exceptions.NamingException;
import hep.dataforge.io.PrintNamed;
import inr.numass.data.SpectrumDataAdapter;
import inr.numass.models.GunSpectrum;
import inr.numass.models.NBkgSpectrum;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.Locale;
import static java.util.Locale.setDefault;
setDefault(Locale.US);
GlobalContext global = GlobalContext.instance();
// global.loadModule(new MINUITModule());
FitManager fm = new FitManager();
GunSpectrum gsp = new GunSpectrum();
NBkgSpectrum spectrum = new NBkgSpectrum(gsp);
XYModel model = new XYModel("gun", spectrum, new SpectrumDataAdapter());
ParamSet allPars = new ParamSet()
.setPar("N", 1e3, 1e2)
.setPar("pos", 18500, 0.1)
.setPar("bkg", 50, 1)
.setPar("resA", 5.3e-5, 1e-5)
.setPar("sigma", 0.3, 0.03);
PrintNamed.printSpectrum(new PrintWriter(System.out), spectrum, allPars, 18495, 18505, 100);
allPars.setParValue("sigma", 0.6);
PrintNamed.printSpectrum(new PrintWriter(System.out), spectrum, allPars, 18495, 18505, 100);
// //String fileName = "d:\\PlayGround\\merge\\scans.out";
//// String configName = "d:\\PlayGround\\SCAN.CFG";
//// ListDataSet config = OldDataReader.readConfig(configName);
// SpectrumGenerator generator = new SpectrumGenerator(model, allPars, 12316);
//
// ListDataSet data = generator.generateData(DataModelUtils.getUniformSpectrumConfiguration(18495, 18505, 20, 20));
//
//// data = data.filter("X", Value.of(15510.0), Value.of(18610.0));
//// allPars.setParValue("X", 0.4);
// FitState state = FitTaskManager.buildState(data, model, allPars);
//
// FitState res = fm.runTask(state, "QOW", FitTask.TASK_RUN, "N", "bkg", "pos", "sigma");
//
// res.print(out());

View File

@ -0,0 +1,110 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts;
import hep.dataforge.context.GlobalContext;
import static hep.dataforge.context.GlobalContext.out;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.datafitter.FitManager;
import hep.dataforge.datafitter.FitState;
import hep.dataforge.datafitter.FitTask;
import hep.dataforge.datafitter.MINUITPlugin
import hep.dataforge.datafitter.ParamSet;
import hep.dataforge.datafitter.models.XYModel;
import hep.dataforge.exceptions.NamingException;
import hep.dataforge.exceptions.PackFormatException;
import inr.numass.data.SpectrumDataAdapter;
import inr.numass.data.SpectrumGenerator;
import inr.numass.models.ModularTritiumSpectrum;
import inr.numass.models.NBkgSpectrum;
import inr.numass.models.ResolutionFunction
import inr.numass.utils.DataModelUtils;
import hep.dataforge.plotfit.PlotFitResultAction;
import hep.dataforge.plots.PlotFrame
import hep.dataforge.plots.data.PlottableFunction
import hep.dataforge.plots.jfreechart.JFreeChartFrame
import java.io.FileNotFoundException;
import java.util.Locale;
import org.apache.commons.math3.analysis.BivariateFunction
import static java.util.Locale.setDefault;
/**
*
* @author Darksnake
*/
setDefault(Locale.US);
new MINUITPlugin().startGlobal();
FitManager fm = new FitManager();
BivariateFunction resolution = new ResolutionFunction(8.3e-5);
ModularTritiumSpectrum beta = new ModularTritiumSpectrum(resolution, 13490d, 18575d, null);
beta.setCaching(false);
NBkgSpectrum spectrum = new NBkgSpectrum(beta);
XYModel model = new XYModel("tritium", spectrum, new SpectrumDataAdapter());
ParamSet allPars = new ParamSet();
allPars.setPar("N", 6e5, 10, 0, Double.POSITIVE_INFINITY);
allPars.setPar("bkg", 2d, 0.1 );
allPars.setPar("E0", 18575.0, 0.05 );
allPars.setPar("mnu2", 0, 1);
def mster = 3000;// Mass of sterile neutrino in eV
allPars.setPar("msterile2", mster**2, 1);
allPars.setPar("U2", 0, 1e-4);
allPars.setPar("X", 0, 0.05, 0d, Double.POSITIVE_INFINITY);
allPars.setPar("trap", 0, 0.01, 0d, Double.POSITIVE_INFINITY);
SpectrumGenerator generator = new SpectrumGenerator(model, allPars, 12316);
ListDataSet data = generator.generateData(DataModelUtils.getUniformSpectrumConfiguration(14000d, 18200, 1e6, 60));
// data = data.filter("X", Value.of(15510.0), Value.of(18610.0));
allPars.setParValue("U2", 0);
FitState state = FitManager.buildState(data, model, allPars);
//new PlotFitResultAction(GlobalContext.instance(), null).runOne(state);
//double delta = 4e-6;
//resolution.setTailFunction{double E, double U ->
// 1-delta*(E-U);
//}
resolution.setTailFunction(ResolutionFunction.getRealTail())
PlotFrame frame = JFreeChartFrame.drawFrame("Transmission function", null);
frame.add(new PlottableFunction("transmission",null, {U -> resolution.value(18500,U)},13500,18505,500));
FitState res = fm.runTask(state, "QOW", FitTask.TASK_RUN, "N", "bkg", "E0", "U2", "trap");
res.print(out());

View File

@ -0,0 +1,71 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts
import hep.dataforge.maths.integration.UnivariateIntegrator
import hep.dataforge.plots.data.PlottableFunction
import hep.dataforge.plots.jfreechart.JFreeChartFrame
import inr.numass.models.ExperimentalVariableLossSpectrum
import org.apache.commons.math3.analysis.UnivariateFunction
import inr.numass.NumassContext
import hep.dataforge.datafitter.ParamSet
import hep.dataforge.io.PrintFunction
//double exPos = 12.94
//double exW = 1.31
//double ionPos = 14.13
//double ionW = 12.79
//double exIonRatio = 0.6059
ParamSet params = new ParamSet()
.setParValue("shift",0)
.setParValue("X", 0.4)
.setParValue("exPos", 12.94)
.setParValue("ionPos", 15.6)
.setParValue("exW", 1.31)
.setParValue("ionW", 12.79)
.setParValue("exIonRatio", 0.6059)
ExperimentalVariableLossSpectrum lsp = new ExperimentalVariableLossSpectrum(19005, 8e-5, 19010,0.2);
JFreeChartFrame frame = JFreeChartFrame.drawFrame("Experimental Loss Test", null);
UnivariateIntegrator integrator = NumassContext.defaultIntegrator
UnivariateFunction exFunc = lsp.excitation(params.getValue("exPos"), params.getValue("exW"));
frame.add(new PlottableFunction("ex", null, exFunc, 0d, 50d, 500));
println "excitation norm factor " + integrator.integrate(exFunc, 0, 50)
UnivariateFunction ionFunc = lsp.ionization(params.getValue("ionPos"), params.getValue("ionW"));
frame.add(new PlottableFunction("ion", null, ionFunc, 0d, 50d, 500));
println "ionization norm factor " + integrator.integrate(ionFunc, 0, 200)
UnivariateFunction sumFunc = lsp.singleScatterFunction(params);
frame.add(new PlottableFunction("sum", null, sumFunc, 0d, 50d, 500));
println "sum norm factor " + integrator.integrate(sumFunc, 0, 100)
PrintFunction.printFunctionSimple(new PrintWriter(System.out), sumFunc, 0d, 50d, 100)
JFreeChartFrame integerFrame = JFreeChartFrame.drawFrame("Experimental Loss Test", null);
UnivariateFunction integr = { d-> lsp.value(d,params)}
integerFrame.add(new PlottableFunction("integr", null, integr, 18950d, 19005d, 500));

View File

@ -0,0 +1,46 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts
import hep.dataforge.plots.data.PlottableFunction
import hep.dataforge.plots.jfreechart.JFreeChartFrame
import org.apache.commons.math3.analysis.UnivariateFunction
def lorenz = {x, x0, gama -> 1/(3.14*gama*(1+(x-x0)*(x-x0)/gama/gama))}
def excitationSpectrum = {Map<Double,Double> lines, double gama ->
UnivariateFunction function = {x->
double res = 0;
lines.each{k,v -> res += lorenz(x,k,gama)*v};
return res;
}
return function;
}
def lines =
[
12.6:0.5,
12.4:0.3,
12.2:0.2
]
UnivariateFunction excitation = excitationSpectrum(lines,0.08)
JFreeChartFrame frame = JFreeChartFrame.drawFrame("theoretical loss spectrum", null);
frame.add(new PlottableFunction("excitation", null, excitation, 0d, 20d, 500));

View File

@ -0,0 +1,122 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.scripts;
import hep.dataforge.context.GlobalContext;
import hep.dataforge.data.DataSet;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.datafitter.FitManager;
import hep.dataforge.datafitter.FitState;
import hep.dataforge.datafitter.ParamSet;
import hep.dataforge.datafitter.models.XYModel;
import hep.dataforge.likelihood.BayesianManager
import static hep.dataforge.maths.RandomUtils.setSeed;
import inr.numass.data.SpectrumGenerator;
import inr.numass.models.ModularTritiumSpectrum;
import inr.numass.models.NBkgSpectrum;
import static inr.numass.utils.DataModelUtils.getUniformSpectrumConfiguration;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
PrintWriter out = GlobalContext.out();
FitManager fm = new FitManager();
setSeed(543982);
// TritiumSpectrum beta = new TritiumSpectrum(2e-4, 13995d, 18580d);
File fssfile = new File("c:\\Users\\Darksnake\\Dropbox\\PlayGround\\FS.txt");
ModularTritiumSpectrum beta = new ModularTritiumSpectrum(8.3e-5, 14400d, 19010d, null);
beta.setCaching(false);
NBkgSpectrum spectrum = new NBkgSpectrum(beta);
XYModel model = new XYModel("tritium", spectrum);
ParamSet allPars = new ParamSet();
allPars.setParValue("N", 6e5);
//значение 6е-6 соответствует полной интенстивности 6е7 распадов в секунду
//Проблема была в переполнении счетчика событий в генераторе. Заменил на long. Возможно стоит поставить туда число с плавающей точкой
allPars.setParError("N", 25);
allPars.setParDomain("N", 0d, Double.POSITIVE_INFINITY);
allPars.setParValue("bkg", 5);
allPars.setParError("bkg", 1e-3);
allPars.setParValue("E0", 18575d);
allPars.setParError("E0", 0.1);
allPars.setParValue("mnu2", 0d);
allPars.setParError("mnu2", 1d);
allPars.setParValue("msterile2", 1000 * 1000);
allPars.setParValue("U2", 0);
allPars.setParError("U2", 1e-4);
allPars.setParDomain("U2", 0d, 1d);
allPars.setParValue("X", 0.0);
allPars.setParDomain("X", 0d, Double.POSITIVE_INFINITY);
allPars.setParValue("trap", 1d);
allPars.setParError("trap", 0.01d);
allPars.setParDomain("trap", 0d, Double.POSITIVE_INFINITY);
// PlotManager pm = new PlotManager();
// String plotTitle = "Tritium spectrum";
// pm.plotFunction(FunctionUtils.getSpectrumFunction(spectrum, allPars), 14000, 18600, 500,plotTitle, null);
// PrintNamed.printSpectrum(Out.out, beta.trapping, allPars, 14000d, 18600d, 500);
// double e = 18570d;
// trans.alpha = 1e-4;
// trans.plotTransmission(System.out, allPars, e, e-1000d, e+100d, 200);
SpectrumGenerator generator = new SpectrumGenerator(model, allPars);
// ColumnedDataFile file = new ColumnedDataFile("d:\\PlayGround\\RUN36.cfg");
// ListDataSet config = file.getDataSet("time","X");
double Elow = 14000d;
double Eup = 18600d;
int numpoints = (int) ((Eup - Elow) / 50);
double time = 1e6 / numpoints; // 3600 / numpoints;
DataSet config = getUniformSpectrumConfiguration(Elow, Eup, time, numpoints);
// config.addAll(DataModelUtils.getUniformSpectrumConfiguration(Eup, Elow, time, numpoints));// в обратную сторону
ListDataSet data = generator.generateData(config);
// plotTitle = "Generated tritium spectrum data";
// pm.plotXYScatter(data, "X", "Y",plotTitle, null);
// bareBeta.setFSS("D:\\PlayGround\\FSS.dat");
// data = tritiumUtils.applyDrift(data, 2.8e-6);
FitState state = fm.buildState(data, model, allPars);
// fm.checkDerivs();
// res.print(Out.out);
// fm.checkFitDerivatives();
FitState res = fm.runDefaultTask(state, "U2", "N", "trap");
res.print(out);
// res = fm.runFrom(res);
// res = fm.generateErrorsFrom(res);
beta.setCaching(true);
beta.setSuppressWarnings(true);
BayesianManager bm = new BayesianManager();
// bm.setPriorProb(new OneSidedUniformPrior("trap", 0, true));
// bm.setPriorProb(new GaussianPrior("trap", 1d, 0.002));
// bm.printMarginalLikelihood(Out.out,"U2", res);
FitState conf = bm.getConfidenceInterval("U2", res, ["U2", "N", "trap"]);
// plotTitle = String.format("Marginal likelihood for parameter \'%s\'", "U2");
// pm.plotFunction(bm.getMarginalLikelihood("U2", res), 0, 2e-3, 40,plotTitle, null);
conf.print(out);
// PrintNamed.printLogProbRandom(Out.out, res, 5000,0.5d, "E0","N");
spectrum.counter.print(out);

View File

@ -0,0 +1,109 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package hep.dataforge.plotfit;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.meta.Meta;
import hep.dataforge.context.Context;
import hep.dataforge.data.DataPoint;
import hep.dataforge.data.DataSet;
import hep.dataforge.data.XYDataAdapter;
import hep.dataforge.datafitter.FitState;
import hep.dataforge.datafitter.models.XYModel;
import hep.dataforge.description.NodeDef;
import hep.dataforge.description.ValueDef;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.exceptions.ContentException;
import hep.dataforge.io.log.Logable;
import hep.dataforge.plots.PlotFrame;
import hep.dataforge.plots.PlotsPlugin;
import hep.dataforge.plots.XYPlotFrame;
import hep.dataforge.plots.data.PlottableData;
import hep.dataforge.plots.data.PlottableFunction;
import hep.dataforge.plots.jfreechart.JFreeChartFrame;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.math3.analysis.UnivariateFunction;
/**
*
* @author darksnake
*/
@TypedActionDef(name = "plotFit", description = "Plot fit result", inputType = FitState.class, outputType = FitState.class)
@NodeDef(name = "adapter", info = "adapter for DataSet being fitted. By default is taken from model.")
@ValueDef(name = "plotTitle", def = "", info = "The title of the plot.")
public class PlotFitResultAction extends OneToOneAction<FitState, FitState> {
public PlotFitResultAction(Context context, Meta annotation) {
super(context, annotation);
}
@Override
protected FitState execute(Logable log, Meta metaData, FitState input){
DataSet data = input.getDataSet();
if(!(input.getModel() instanceof XYModel)){
log.logError("The fit model should be instance of XYModel for this action. Action failed!");
return input;
}
XYModel model = (XYModel)input.getModel();
XYDataAdapter adapter;
if (metaData.hasNode("adapter")){
adapter = new XYDataAdapter(metaData.getNode("adapter"));
} else if(input.getModel() instanceof XYModel){
adapter = model.getAdapter();
} else throw new ContentException("No adapter defined for data interpretation");
UnivariateFunction function = (double x) -> model.getSpectrum().value(x, input.getParameters());
XYPlotFrame frame = (XYPlotFrame) PlotsPlugin.buildFrom(getContext()).buildPlotFrame(getName(), input.getName(), metaData);
//JFreeChartFrame.drawFrame(reader.getString("plotTitle", "Fit result plot for "+input.getName()), null);
double[] x = new double[data.size()];
// double[] y = new double[data.size()];
double xMin = Double.POSITIVE_INFINITY;
double xMax = Double.NEGATIVE_INFINITY;
List<DataPoint> points = new ArrayList<>();
for (int i = 0; i < data.size(); i++) {
x[i] = adapter.getX(data.get(i)).doubleValue();
// y[i] = adapter.getY(data.get(i));
points.add(adapter.mapToDefault(data.get(i)));
if(x[i]<xMin){
xMin = x[i];
}
if(x[i]>xMax){
xMax = x[i];
}
}
frame.add(new PlottableFunction("fit", null, function, points, "x"));
frame.add(new PlottableData("data", null, points));
return input;
}
}

View File

@ -0,0 +1,200 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass;
import hep.dataforge.actions.ActionResult;
import static hep.dataforge.actions.RunManager.executeXML;
import hep.dataforge.context.Context;
import static hep.dataforge.context.GlobalContext.out;
import hep.dataforge.data.DataManager;
import hep.dataforge.datafitter.MINUITPlugin;
import hep.dataforge.io.IOManager;
import static inr.numass.NumassContext.printDescription;
import inr.numass.workbench.Workbench;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Locale;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
import static java.util.Locale.setDefault;
/**
*
*/
public class Main {
public static void main(String[] args) throws Exception {
setDefault(Locale.US);
NumassContext context = new NumassContext();
context.loadPlugin(new MINUITPlugin());
run(context, args);
}
@SuppressWarnings("deprecation")
public static ActionResult run(NumassContext context, String[] args) throws Exception {
Logger logger = LoggerFactory.getLogger("numass-main");
Options options = prepareOptions();
CommandLineParser parser = new BasicParser();
CommandLine line;
try {
// parse the command line arguments
line = parser.parse(options, args);
} catch (ParseException exp) {
// oops, something went wrong
logger.error("Command line error. Reason: " + exp.getMessage());
return ActionResult.empty();
}
if (line.hasOption("lc")) {
printDescription(context, true);
return ActionResult.empty();
} else if (line.hasOption("l")) {
printDescription(context, false);
return ActionResult.empty();
}
String cfgPath;
if (args.length == 0) {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("java -jar DataReader.jar [OPTIONS]", options);
out().println("Trying to use default config location...");
}
if (line.hasOption("c")) {
cfgPath = line.getOptionValue("c");
if (cfgPath == null) {
logger.info("Configutation path not provided.");
return ActionResult.empty();
}
File config = context.io().getFile(cfgPath);
if (!config.exists()) {
throw new FileNotFoundException("Configuration file not found");
}
context.putValue(IOManager.ROOT_DIRECTORY_CONTEXT_KEY, config.getParentFile().toString());
applyCLItoContext(line, context);
return executeXML(context, config);
} else {
Workbench.main(args);
return null;
}
}
public static void applyCLItoContext(CommandLine line, Context context) throws FileNotFoundException {
File workDir = new File(context.getString(IOManager.ROOT_DIRECTORY_CONTEXT_KEY));
if (line.hasOption("h")) {
workDir = new File(line.getOptionValue("h"));
context.putValue(IOManager.ROOT_DIRECTORY_CONTEXT_KEY, workDir.toString());
}
if (line.hasOption("d")) {
String dataPath = line.getOptionValue("d");
File dataDir = new File(dataPath);
if (!dataDir.isAbsolute()) {
dataDir = new File(workDir, dataPath);
}
if (dataDir.exists() && dataDir.isDirectory()) {
context.putValue(DataManager.DATA_DIR, dataDir.getAbsolutePath());
} else {
throw new FileNotFoundException("Data directory not found");
}
}
if (line.hasOption("o")) {
String outPath = line.getOptionValue("o");
File outDir = new File(outPath);
if (!outDir.isAbsolute()) {
outDir = new File(workDir, outPath);
}
if (!outDir.exists()) {
outDir.mkdirs();
}
context.putValue(NumassIO.NUMASS_OUTPUT_CONTEXT_KEY, outDir.toString());
}
}
private static Options prepareOptions() {
Options options = new Options();
options.addOption("c", "config", true, "Configuration file path. "
+ "If this option is not present, than workbench is launched and all other parameters are ignored.");
options.addOption("h", "home", true,
"Working directory (by default the working directory is the directory where config file is placed)");
options.addOption("d", "data", true, "Data directory (absolute or relative to working directory)");
options.addOption("o", "out", true, "Output directory (absolute or relative to working directory)");
options.addOption("l", "list", false, "List of available actions");
options.addOption("lc", "list-color", false, "List of available actions with ANSI coloring");
return options;
}
private static String getFilePathFromDialog(String homeDir) throws FileNotFoundException {
//TODO переместить в IOManager
JFrame frame = new JFrame("Chose a configuration file");
JFileChooser fc = new JFileChooser(homeDir);
FileFilter xmlFilter = new FileNameExtensionFilter("XML files", "XML", "xml");
// fc.addChoosableFileFilter(xmlFilter);
fc.setFileFilter(xmlFilter);
int returnVal = fc.showOpenDialog(frame);
File file;
if (returnVal == JFileChooser.APPROVE_OPTION) {
file = fc.getSelectedFile();
frame.dispose();
return file.getAbsolutePath();
} else {
frame.dispose();
return null;
}
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass;
import hep.dataforge.actions.ActionManager;
import hep.dataforge.context.Context;
import hep.dataforge.description.ActionDescriptor;
import hep.dataforge.description.DescriptorFormatter;
import hep.dataforge.description.DescriptorUtils;
import hep.dataforge.description.TextDescriptorFormatter;
import hep.dataforge.exceptions.DescriptorException;
import hep.dataforge.maths.integration.GaussRuleIntegrator;
import hep.dataforge.maths.integration.UnivariateIntegrator;
import hep.dataforge.meta.Meta;
import java.io.PrintWriter;
/**
*
* @author Darksnake
*/
public class NumassContext extends Context {
public static UnivariateIntegrator defaultIntegrator = new GaussRuleIntegrator(300);
public static UnivariateIntegrator highDensityIntegrator = new GaussRuleIntegrator(500);
public NumassContext(Context parent, Meta config) {
super(parent, "numass", config);
init();
}
public NumassContext(Context parent) {
super(parent, "numass");
init();
}
public NumassContext() {
super("numass");
init();
}
private void init() {
attachIoManager(new NumassIO());
loadPlugin("inr.numass: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(" ");
formatter.showDescription(
DescriptorUtils.buildDescriptor(
DescriptorUtils.findAnnotatedElement("method::hep.dataforge.data.DataManager.read")
));
writer.println("***Allowed actions***");
for (ActionDescriptor descriptor : ActionManager.buildFrom(context).listActions()) {
writer.print(" ");
formatter.showDescription(descriptor);
}
writer.println("***End of actions list***");
writer.flush();
}
}

View File

@ -0,0 +1,131 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass;
import hep.dataforge.data.BinaryData;
import hep.dataforge.data.FileData;
import hep.dataforge.io.BasicIOManager;
import hep.dataforge.meta.Meta;
import hep.dataforge.names.Name;
import inr.numass.data.NumassDataReader;
import inr.numass.data.NumassPawReader;
import inr.numass.data.RawNMFile;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.io.output.TeeOutputStream;
/**
*
* @author Darksnake
*/
public class NumassIO extends BasicIOManager {
public static final String NUMASS_OUTPUT_CONTEXT_KEY = "numass.outputDir";
@Override
public OutputStream out(Name stage, Name name) {
List<String> tokens = new ArrayList<>();
if (getContext().hasValue("numass.path")) {
String path = getContext().getString("numass.path");
if (path.contains(".")) {
tokens.addAll(Arrays.asList(path.split(".")));
} else {
tokens.add(path);
}
}
if (stage != null) {
tokens.addAll(Arrays.asList(stage.asArray()));
}
String dirName = String.join(File.separator, tokens);
String fileName = name.removeNameSpace().toString() + ".out";
return buildOut(getOutputDir(), dirName, fileName);
}
private File getOutputDir() {
String outputDirPath = getContext().getString(NUMASS_OUTPUT_CONTEXT_KEY, ".dataforge");
File res = new File(getRootDirectory(), outputDirPath);
if (!res.exists()) {
res.mkdir();
}
return res;
}
protected OutputStream buildOut(File parentDir, String dirName, String fileName) {
File outputFile;
if (!parentDir.exists()) {
throw new RuntimeException("Working directory does not exist");
}
if (dirName != null && !dirName.isEmpty()) {
parentDir = new File(parentDir, dirName);
if (!parentDir.exists()) {
parentDir.mkdirs();
}
}
// String output = source.meta().getString("output", this.meta().getString("output", fileName + ".out"));
outputFile = new File(parentDir, fileName);
try {
if (getContext().getBoolean("numass.consoleOutput", false)) {
return new TeeOutputStream(new FileOutputStream(outputFile), System.out);
} else {
return new FileOutputStream(outputFile);
}
} catch (FileNotFoundException ex) {
throw new RuntimeException(ex);
}
}
public static RawNMFile readAsDat(BinaryData source, Meta config) {
try {
return new NumassDataReader(source, config).read();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
public static RawNMFile readAsPaw(BinaryData source) {
try {
return new NumassPawReader().readPaw(source.getInputStream(), source.getName());
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
public static RawNMFile getNumassData(FileData source, Meta config) {
RawNMFile dataFile;
switch (source.getExtension()) {
case "paw":
dataFile = readAsPaw(source);
break;
case "dat":
dataFile = readAsDat(source, config);
break;
default:
throw new RuntimeException("Wrong file format");
}
return dataFile;
}
}

View File

@ -0,0 +1,275 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass;
import hep.dataforge.actions.ActionManager;
import hep.dataforge.context.BasicPlugin;
import hep.dataforge.context.Context;
import hep.dataforge.context.PluginDef;
import hep.dataforge.data.DataAdapter;
import hep.dataforge.data.XYDataAdapter;
import hep.dataforge.datafitter.FitManager;
import hep.dataforge.datafitter.FitPlugin;
import hep.dataforge.datafitter.models.Model;
import hep.dataforge.datafitter.models.ModelManager;
import hep.dataforge.datafitter.models.WeightedXYModel;
import hep.dataforge.datafitter.models.XYModel;
import hep.dataforge.meta.Meta;
import hep.dataforge.plotfit.PlotFitResultAction;
import hep.dataforge.plots.PlotDataAction;
import inr.numass.actions.AdjustErrorsAction;
import inr.numass.actions.FindBorderAction;
import inr.numass.actions.MergeDataAction;
import inr.numass.actions.MonitorCorrectAction;
import inr.numass.actions.PrepareDataAction;
import inr.numass.actions.ReadNumassDataAction;
import inr.numass.actions.ShowLossSpectrumAction;
import inr.numass.actions.ShowSpectrumAction;
import inr.numass.actions.SlicingAction;
import inr.numass.actions.SummaryAction;
import inr.numass.models.BetaSpectrum;
import inr.numass.models.CustomNBkgSpectrum;
import inr.numass.models.EmpiricalLossSpectrum;
import inr.numass.models.ExperimentalVariableLossSpectrum;
import inr.numass.models.GaussSourceSpectrum;
import inr.numass.models.GunSpectrum;
import inr.numass.models.ModularSpectrum;
import inr.numass.models.NBkgSpectrum;
import inr.numass.models.RangedNamedSetSpectrum;
import inr.numass.models.ResolutionFunction;
import inr.numass.models.TransmissionInterpolator;
import inr.numass.models.VariableLossSpectrum;
import org.apache.commons.math3.analysis.BivariateFunction;
import org.apache.commons.math3.analysis.UnivariateFunction;
/**
*
* @author Alexander Nozik
*/
@PluginDef(group = "inr.numass", name = "numass",
dependsOn = {"hep.dataforge:MINUIT", "hep.dataforge:plots"},
description = "Numass data analysis tools")
public class NumassPlugin extends BasicPlugin {
@Override
public void apply(Context context) {
FitManager fm = context.provide("hep.dataforge:fitting", FitPlugin.class).getFitManager();
ModelManager mm = fm.getModelManager();
loadModels(mm);
ActionManager actions = ActionManager.buildFrom(context);
actions.registerAction(SlicingAction.class);
actions.registerAction(ShowSpectrumAction.class);
actions.registerAction(PrepareDataAction.class);
actions.registerAction(ReadNumassDataAction.class);
actions.registerAction(MergeDataAction.class);
actions.registerAction(FindBorderAction.class);
actions.registerAction(MonitorCorrectAction.class);
actions.registerAction(SummaryAction.class);
actions.registerAction(PlotDataAction.class);
actions.registerAction(PlotFitResultAction.class);
actions.registerAction(ShowLossSpectrumAction.class);
actions.registerAction(AdjustErrorsAction.class);
}
@Override
public void clean(Context context) {
}
/**
* Load all numass model factories
*
* @param manager
*/
private void loadModels(ModelManager manager) {
manager.addModel("modularbeta", (context, an) -> {
double A = an.getDouble("resolution", 8.3e-5);//8.3e-5
double from = an.getDouble("from", 14400d);
double to = an.getDouble("to", 19010d);
RangedNamedSetSpectrum beta = new BetaSpectrum(context.io().getFile("FS.txt"));
ModularSpectrum sp = new ModularSpectrum(beta, A, from, to);
sp.setCaching(false);
NBkgSpectrum spectrum = new NBkgSpectrum(sp);
return new XYModel("tritium", spectrum, getAdapter(an));
});
manager.addModel("scatter", (context, an) -> {
double A = an.getDouble("resolution", 8.3e-5);//8.3e-5
double from = an.getDouble("from", 0);
double to = an.getDouble("to", 0);
ModularSpectrum sp;
if (from == to) {
sp = new ModularSpectrum(new GaussSourceSpectrum(), A);
} else {
sp = new ModularSpectrum(new GaussSourceSpectrum(), A, from, to);
}
NBkgSpectrum spectrum = new NBkgSpectrum(sp);
sp.setCaching(false);
return new XYModel("scatter", spectrum, getAdapter(an));
});
manager.addModel("scatter-empiric", (context, an) -> {
double eGun = an.getDouble("eGun", 19005d);
TransmissionInterpolator interpolator = buildInterpolator(context, an, eGun);
EmpiricalLossSpectrum loss = new EmpiricalLossSpectrum(interpolator, eGun + 5);
NBkgSpectrum spectrum = new NBkgSpectrum(loss);
double weightReductionFactor = an.getDouble("weightReductionFactor", 2.0);
return new WeightedXYModel("scatter-empiric", spectrum, getAdapter(an), (dp) -> weightReductionFactor);
});
manager.addModel("scatter-empiric-variable", (context, an) -> {
double eGun = an.getDouble("eGun", 19005d);
//build transmisssion with given data, annotation and smoothing
UnivariateFunction interpolator = buildInterpolator(context, an, eGun);
VariableLossSpectrum loss = VariableLossSpectrum.withData(interpolator, eGun + 5);
double tritiumBackground = an.getDouble("tritiumBkg", 0);
NBkgSpectrum spectrum;
if (tritiumBackground == 0) {
spectrum = new NBkgSpectrum(loss);
} else {
spectrum = CustomNBkgSpectrum.tritiumBkgSpectrum(loss, tritiumBackground);
}
double weightReductionFactor = an.getDouble("weightReductionFactor", 2.0);
Model res = new WeightedXYModel("scatter-variable", spectrum, getAdapter(an), (dp) -> weightReductionFactor);
res.configure(an);
return res;
});
manager.addModel("scatter-analytic-variable", (context, an) -> {
double eGun = an.getDouble("eGun", 19005d);
VariableLossSpectrum loss = VariableLossSpectrum.withGun(eGun + 5);
double tritiumBackground = an.getDouble("tritiumBkg", 0);
NBkgSpectrum spectrum;
if (tritiumBackground == 0) {
spectrum = new NBkgSpectrum(loss);
} else {
spectrum = CustomNBkgSpectrum.tritiumBkgSpectrum(loss, tritiumBackground);
}
return new XYModel("scatter-variable", spectrum, getAdapter(an));
});
manager.addModel("scatter-empiric-experimental", (context, an) -> {
double eGun = an.getDouble("eGun", 19005d);
//build transmisssion with given data, annotation and smoothing
UnivariateFunction interpolator = buildInterpolator(context, an, eGun);
double smoothing = an.getDouble("lossSmoothing", 0.3);
VariableLossSpectrum loss = ExperimentalVariableLossSpectrum.withData(interpolator, eGun + 5, smoothing);
NBkgSpectrum spectrum = new NBkgSpectrum(loss);
double weightReductionFactor = an.getDouble("weightReductionFactor", 2.0);
Model res = new WeightedXYModel("scatter-empiric-experimental", spectrum, getAdapter(an), (dp) -> weightReductionFactor);
res.configure(an);
return res;
});
manager.addModel("modularbeta-unadeabatic", (context, an) -> {
double A = an.getDouble("resolution", 8.3e-5);//8.3e-5
double from = an.getDouble("from", 14400d);
double to = an.getDouble("to", 19010d);
BivariateFunction reolutionTail = (double E, double U) -> {
double x = E - U;
if (x > 1500) {
return 0.98;
} else //Intercept = 1.00051, Slope = -1.3552E-5
{
return 1.00051 - 1.3552E-5 * x;
}
};
RangedNamedSetSpectrum beta = new BetaSpectrum(context.io().getFile("FS.txt"));
ModularSpectrum sp = new ModularSpectrum(beta, new ResolutionFunction(A, reolutionTail), from, to);
sp.setCaching(false);
NBkgSpectrum spectrum = new NBkgSpectrum(sp);
return new XYModel("tritium", spectrum, getAdapter(an));
});
manager.addModel("gun", (context, an) -> {
GunSpectrum gsp = new GunSpectrum();
double tritiumBackground = an.getDouble("tritiumBkg", 0);
NBkgSpectrum spectrum;
if (tritiumBackground == 0) {
spectrum = new NBkgSpectrum(gsp);
} else {
spectrum = CustomNBkgSpectrum.tritiumBkgSpectrum(gsp, tritiumBackground);
}
return new XYModel("gun", spectrum, getAdapter(an));
});
}
private TransmissionInterpolator buildInterpolator(Context context, Meta an, double eGun) {
String transXName = an.getString("transXName", "Uset");
String transYName = an.getString("transYName", "CR");
double stitchBorder = an.getDouble("stitchBorder", eGun - 7);
int nSmooth = an.getInt("nSmooth", 15);
double w = an.getDouble("w", 0.8);
if (an.hasValue("transFile")) {
String transmissionFile = an.getString("transFile");
return TransmissionInterpolator
.fromFile(context, transmissionFile, transXName, transYName, nSmooth, w, stitchBorder);
} else if (an.hasNode("transBuildAction")) {
Meta transBuild = an.getNode("transBuildAction");
try {
return TransmissionInterpolator.fromAction((Context) context,
transBuild, transXName, transYName, nSmooth, w, stitchBorder);
} catch (InterruptedException ex) {
throw new RuntimeException("Transmission build failed");
}
} else {
throw new RuntimeException("Transmission declaration not found");
}
}
private XYDataAdapter getAdapter(Meta an) {
if (an.hasNode(DataAdapter.DATA_ADAPTER_ANNOTATION_NAME)) {
return new XYDataAdapter(an.getNode(DataAdapter.DATA_ADAPTER_ANNOTATION_NAME));
} else {
return new XYDataAdapter("Uread", "CR", "CRerr");
}
}
}

View File

@ -0,0 +1,87 @@
/*
* 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.actions;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.context.Context;
import hep.dataforge.data.DataPoint;
import hep.dataforge.data.DataSet;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.io.log.Logable;
import hep.dataforge.meta.Meta;
import java.util.ArrayList;
import java.util.List;
/**
* Adjust errors for all numass points in the dataset
*
* @author Alexander Nozik <altavir@gmail.com>
*/
@TypedActionDef(name = "adjustErrors", inputType = DataSet.class, outputType = DataSet.class)
public class AdjustErrorsAction extends OneToOneAction<DataSet, DataSet> {
public AdjustErrorsAction(Context context, Meta annotation) {
super(context, annotation);
}
@Override
protected DataSet execute(Logable log, Meta meta, DataSet input) {
List<DataPoint> points = new ArrayList<>();
for (DataPoint dp : input) {
points.add(evalPoint(meta, dp));
}
return new ListDataSet(input.getName(), input.meta(), points, input.getDataFormat());
}
private DataPoint evalPoint(Meta meta, DataPoint dp) {
if (meta.hasNode("point")) {
for (Meta pointMeta : meta.getNodes("point")) {
if (pointMeta.getDouble("Uset") == dp.getDouble("Uset")) {
return adjust(dp, pointMeta);
}
}
}
if (meta.hasNode("range")) {
for (Meta rangeMeta : meta.getNodes("range")) {
double from = rangeMeta.getDouble("from", 0);
double to = rangeMeta.getDouble("to", Double.POSITIVE_INFINITY);
double u = rangeMeta.getDouble("Uset");
if (rangeMeta.getDouble("Uset") == dp.getDouble("Uset")) {
return adjust(dp, rangeMeta);
}
}
}
if (meta.hasNode("all")) {
return adjust(dp, meta.getNode("all"));
}
return dp;
}
private DataPoint adjust(DataPoint dp, Meta config) {
MapDataPoint res = new MapDataPoint(dp);
if (res.hasValue("CRerr")) {
double instability = 0;
if (dp.hasValue("CR")) {
instability = dp.getDouble("CR") * config.getDouble("instability", 0);
}
double factor = config.getDouble("factor", 1d);
double base = config.getDouble("base", 0);
double adjusted = res.getDouble("CRerr") * factor + instability + base;
res.putValue("CRerr", adjusted);
} else {
throw new RuntimeException("The value CRerr is not found in the data point!");
}
return res;
}
}

View File

@ -0,0 +1,86 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.actions;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.values.Value;
import inr.numass.data.NMFile;
import inr.numass.data.NMPoint;
import java.util.HashMap;
import java.util.Map;
/**
*
* @author Darksnake
*/
public class BorderData extends ListDataSet {
private final static String[] names = {"U", "80%", "90%", "95%", "99%"};
private final static double[] percents = {0.8, 0.9, 0.95, 0.99};
public static double getNorm(Map<Double, Double> spectrum, int lower, int upper) {
double res = 0;
for (Map.Entry<Double, Double> entry : spectrum.entrySet()) {
if ((entry.getKey() >= lower) && (entry.getKey() <= upper)) {
res += entry.getValue();
}
}
return res;
}
public BorderData(NMFile file, int upper, int lower, NMPoint reference) {
super(names);
if (upper <= lower) {
throw new IllegalArgumentException();
}
fill(file, lower, upper, reference);
}
private void fill(NMFile file, int lower, int upper, NMPoint reference) {
for (NMPoint point : file.getNMPoints()) {
if ((reference != null) && (point.getUset() == reference.getUset())) {
continue;
}
//создаем основу для будущей точки
HashMap<String, Value> map = new HashMap<>();
map.put(names[0], Value.of(point.getUset()));
Map<Double, Double> spectrum;
if (reference != null) {
spectrum = point.getMapWithBinning(reference, 0);
} else {
spectrum = point.getMapWithBinning(0, true);
}
double norm = getNorm(spectrum, lower, upper);
double counter = 0;
int chanel = upper;
while (chanel > lower) {
chanel--;
counter += spectrum.get((double) chanel);
for (int i = 0; i < percents.length; i++) {
if (counter / norm > percents[i]) {
if (!map.containsKey(names[i + 1])) {
map.put(names[i + 1], Value.of(chanel));
}
}
}
}
this.add(new MapDataPoint(map));
}
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.actions;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.meta.Meta;
import hep.dataforge.description.ValueDef;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.context.Context;
import hep.dataforge.exceptions.ContentException;
import hep.dataforge.io.log.Logable;
import inr.numass.data.RawNMFile;
import inr.numass.data.RawNMPoint;
import inr.numass.debunch.DebunchReport;
import inr.numass.debunch.FrameAnalizer;
import java.io.PrintWriter;
/**
*
* @author Darksnake
*/
@TypedActionDef(name = "debunch", inputType = RawNMFile.class, outputType = RawNMFile.class)
@ValueDef(name = "upperchanel", type = "NUMBER", def = "4095", info = "An upper chanel for debuncing")
@ValueDef(name = "lowerchanel", type = "NUMBER", def = "0", info = "A lower chanel for debuncing")
@ValueDef(name = "rejectprob", type = "NUMBER", def = "1e-5", info = "Rejection probability")
@ValueDef(name = "framelength", type = "NUMBER", def = "5", info = "Frame length in seconds")
@ValueDef(name = "maxcr", type = "NUMBER", def = "100", info = "Maximum count rate for debunching")
public class DebunchAction extends OneToOneAction<RawNMFile,RawNMFile> {
public DebunchAction(Context context, Meta an) {
super(context, an);
}
@Override
protected RawNMFile execute(Logable log, Meta reader, RawNMFile source) throws ContentException {
log.log("File {} started", source.getName());
int upper = source.meta().getInt("upperchanel", this.meta().getInt("upperchanel", RawNMPoint.MAX_CHANEL));
int lower = source.meta().getInt("lowerchanel", this.meta().getInt("lowerchanel", 0));
double rejectionprob = source.meta().getDouble("rejectprob", this.meta().getDouble("rejectprob", 1e-5));
double framelength = source.meta().getDouble("framelength", this.meta().getDouble("framelength", 5));
double maxCR = source.meta().getDouble("maxcr", this.meta().getDouble("maxcr", 100d));
RawNMFile res = new RawNMFile(source.getName());
res.setHead(source.getHead());
source.getData().stream().map((point) -> {
double cr = point.selectChanels(lower, upper).getCR();
if (cr < maxCR) {
DebunchReport report = new FrameAnalizer(rejectionprob, framelength, lower, upper).debunchPoint(point);
log.log("Debunching file '{}', point '{}': {} percent events {} percent time in bunches",
source.getName(), point.getUset(), report.eventsFiltred() * 100, report.timeFiltred() * 100);
point = report.getPoint();
}
return point;
}).forEach((point) -> {
res.putPoint(point);
});
log.log("File {} completed", source.getName());
log.getLog().print(new PrintWriter(buildActionOutput(source)));
// res.configure(source.meta());
return res;
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.actions;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.meta.Meta;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.context.Context;
import hep.dataforge.exceptions.ContentException;
import hep.dataforge.io.ColumnedDataWriter;
import hep.dataforge.io.log.Logable;
import inr.numass.data.NMFile;
import inr.numass.data.NMPoint;
import java.io.OutputStream;
/**
*
* @author Darksnake
*/
@TypedActionDef(name = "findBorder", inputType = NMFile.class, outputType = NMFile.class)
public class FindBorderAction extends OneToOneAction<NMFile, NMFile> {
public FindBorderAction(Context context, Meta an) {
super(context, an);
}
@Override
protected NMFile execute(Logable log, Meta reader, NMFile source) throws ContentException {
log.log("File {} started", source.getName());
int upperBorder = meta().getInt("upper", 4096);
int lowerBorder = meta().getInt("lower", 0);
double substractReference = meta().getDouble("reference", 0);
NMPoint referencePoint = null;
if (substractReference > 0) {
referencePoint = source.getByUset(substractReference);
if (referencePoint == null) {
log.log("Reference point {} not found", substractReference);
}
}
BorderData bData = new BorderData(source, upperBorder, lowerBorder, referencePoint);
OutputStream stream = buildActionOutput(source);
ColumnedDataWriter.writeDataSet(stream, bData, String.format("%s : lower = %d upper = %d", source.getName(), lowerBorder, upperBorder));
log.log("File {} completed", source.getName());
return source;
}
}

View File

@ -0,0 +1,200 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.actions;
import hep.dataforge.actions.ManyToOneAction;
import hep.dataforge.meta.Meta;
import hep.dataforge.content.NamedGroup;
import hep.dataforge.content.GroupBuilder;
import hep.dataforge.description.NodeDef;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.context.Context;
import hep.dataforge.data.DataPoint;
import hep.dataforge.data.DataSet;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.io.ColumnedDataWriter;
import hep.dataforge.io.log.Logable;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author Darksnake
*/
@TypedActionDef(name = "merge", inputType = DataSet.class, outputType = DataSet.class, description = "Merge different numass data files into one.")
@NodeDef(name = "grouping", info = "The defenition of grouping rule for this merge", target = "method::hep.dataforge.content.GroupBuilder.byAnnotation")
//@Parameter(name = "groupBy", def = "mergeTag", info = "Defines the name of the value by which grouping is made. The value is supposed to be a String, but in practice could be any type which could be converted to String.")
public class MergeDataAction extends ManyToOneAction<DataSet, DataSet> {
public static final String MERGE_NAME = "mergeName";
public static String[] parnames = {"Uset", "Uread", "Length", "Total", "Window", "Corrected", "CR", "CRerr"};
public MergeDataAction(Context context, Meta an) {
super(context, an);
}
@Override
protected List<NamedGroup<DataSet>> buildGroups(Meta reader, List<DataSet> input) {
List<NamedGroup<DataSet>> groups;
if (reader.hasNode("grouping")) {
groups = super.buildGroups(reader, input);
} else {
groups = GroupBuilder.byValue(MERGE_NAME, reader.getString(MERGE_NAME, "merge")).group(input);
}
return groups;
}
@Override
protected DataSet execute(Logable log, Meta reader, NamedGroup<DataSet> input) {
return mergeOne(log, input.getName(), input.asList());
// List<DataSet> res = new ArrayList<>();
// for (NamedGroup<DataSet> group : groups) {
// res.add(mergeOne(log, group.getName(), group.asList()));
// }
// return new ContentList<>(input.getName(), DataSet.class, res);
}
private DataSet mergeOne(Logable log, String fileName, List<DataSet> files) {
DataSet[] data = new DataSet[files.size()];
String head = "Numass data merge\n";
String numassPath = "";
/*
* Проверяем являются ли пути одинаковыми у всех файлов
* TODO не изящное решение
*/
for (int i = 0; i < files.size(); i++) {
data[i] = files.get(i);
head += "\t" + data[i].getName() + "\n";
if (numassPath != null) {
String newPath = data[i].meta().getString("numass.path", null);
if (numassPath.isEmpty()) {
numassPath = newPath;
} else {
if (!numassPath.equals(newPath)) {
numassPath = null;
}
}
}
}
DataSet res = mergeDataSets(fileName, data);
/*
* Указываем путь только если он одинаковый для всех входных файлов
*/
if (numassPath != null) {
res.configure(res.meta().getBuilder().putValue("numass.path", numassPath).build());
}
res = res.sort("Uset", true);
OutputStream stream = buildActionOutput(res);
ColumnedDataWriter.writeDataSet(stream, res, head);
return res;
}
// private Map<String, List<DataSet>> buildMergeGroups(String mergeBy, NamedGroup<DataSet> input) {
// Map<String, List<DataSet>> map = new HashMap<>();
// for (DataSet ds : input) {
// String tag = ds.meta().getString(mergeBy, meta().getString(mergeBy, "merge"));
// if (!map.containsKey(tag)) {
// map.put(tag, new ArrayList<>());
// }
// map.get(tag).add(ds);
// }
// return map;
// }
private DataPoint mergeDataPoints(DataPoint dp1, DataPoint dp2) {
if (dp1 == null) {
return dp2;
}
if (dp2 == null) {
return dp1;
}
double Uset = dp1.getValue(parnames[0]).doubleValue();
//усредняем измеренное напряжение
double Uread = (dp1.getValue(parnames[1]).doubleValue() + dp2.getValue(parnames[1]).doubleValue()) / 2;
double t1 = dp1.getValue("Length").doubleValue();
double t2 = dp2.getValue("Length").doubleValue();
double time = t1 + t2;
long total = dp1.getValue(parnames[3]).intValue() + dp2.getValue(parnames[3]).intValue();
long wind = dp1.getValue(parnames[4]).intValue() + dp2.getValue(parnames[4]).intValue();
double corr = dp1.getValue(parnames[5]).doubleValue() + dp2.getValue(parnames[5]).doubleValue();
double cr1 = dp1.getValue("CR").doubleValue();
double cr2 = dp2.getValue("CR").doubleValue();
double cr = (cr1 * t1 + cr2 * t2) / (t1 + t2);
double err1 = dp1.getDouble("CRerr");
double err2 = dp2.getDouble("CRerr");
// абсолютные ошибки складываются квадратично
double crErr = Math.sqrt(err1 * err1 * t1 * t1 + err2 * err2 * t2 * t2) / time;
MapDataPoint map = new MapDataPoint(parnames, Uset, Uread, time, total, wind, corr, cr, crErr);
if (dp1.names().contains("relCR") && dp2.names().contains("relCR")) {
double relCR = (dp1.getDouble("relCR") + dp2.getDouble("relCR")) / 2;
map.putValue("relCR", relCR);
map.putValue("relCRerr", crErr * relCR / cr);
}
return map;
}
private DataSet mergeDataSets(String name, DataSet... ds) {
//Сливаем все точки в один набор данных
Map<Double, List<DataPoint>> points = new LinkedHashMap<>();
for (DataSet d : ds) {
if (!d.getDataFormat().contains(parnames)) {
throw new IllegalArgumentException();
}
for (DataPoint dp : d) {
double uset = dp.getValue(parnames[0]).doubleValue();
if (!points.containsKey(uset)) {
points.put(uset, new ArrayList<>());
}
points.get(uset).add(dp);
}
}
List<DataPoint> res = new ArrayList<>();
for (Map.Entry<Double, List<DataPoint>> entry : points.entrySet()) {
DataPoint curPoint = null;
for (DataPoint newPoint : entry.getValue()) {
curPoint = mergeDataPoints(curPoint, newPoint);
}
res.add(curPoint);
}
return new ListDataSet(name, null, res);
}
}

View File

@ -0,0 +1,182 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.actions;
import hep.dataforge.actions.ActionResult;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.meta.Meta;
import hep.dataforge.context.Context;
import hep.dataforge.data.DataPoint;
import hep.dataforge.data.DataSet;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.description.ValueDef;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.exceptions.ContentException;
import hep.dataforge.io.ColumnedDataWriter;
import hep.dataforge.io.log.Logable;
import hep.dataforge.values.Value;
import java.io.OutputStream;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
*
* @author Darksnake
*/
@TypedActionDef(name = "monitor", inputType = DataSet.class, outputType = DataSet.class)
@ValueDef(name = "monitorPoint", type = "UMBER", required = true, info = "The Uset for monitor point")
@ValueDef(name = "monitorFile", info = "The outputfile for monitor points", def = "monitor.out")
@ValueDef(name = "calculateRelative", info = "Calculate count rate relative to average monitor point", def = "false")
public class MonitorCorrectAction extends OneToOneAction<DataSet, DataSet> {
private static final String[] monitorNames = {"Timestamp", "Total", "CR", "CRerr"};
CopyOnWriteArrayList<DataPoint> monitorPoints = new CopyOnWriteArrayList<>();
public MonitorCorrectAction(Context context, Meta an) {
super(context, an);
}
@Override
protected DataSet execute(Logable log, Meta reader, DataSet sourceData) throws ContentException {
double monitor = reader.getDouble("monitorPoint", Double.NaN);
TreeMap<LocalDateTime, DataPoint> index = getMonitorIndex(monitor, sourceData);
if (index.isEmpty()) {
log.logError("No monitor points found");
return sourceData;
}
double norm = 0;
double totalAv = 0;
String head = "";
head += String.format("%20s\t%10s\t%s%n", "Timestamp", "Total", "CR in window");
for (DataPoint dp : index.values()) {
head += String.format("%20s\t%10d\t%g%n", getTime(dp).toString(), getTotal(dp), getCR(dp));
norm += getCR(dp) / index.size();
totalAv += getTotal(dp) / index.size();
monitorPoints.add(dp);
}
head += String.format("%20s\t%10g\t%g%n", "Average", totalAv, norm);
List<DataPoint> dataList = new ArrayList<>();
for (DataPoint dp : sourceData) {
MapDataPoint point = new MapDataPoint(dp);
point.putValue("Monitor", 1.0);
if (!isMonitorPoint(monitor, dp) || index.isEmpty()) {
LocalDateTime time = getTime(dp);
Entry<LocalDateTime, DataPoint> previousMonitor = index.floorEntry(time);
Entry<LocalDateTime, DataPoint> nextMonitor = index.ceilingEntry(time);
if (previousMonitor == null) {
previousMonitor = nextMonitor;
}
if (nextMonitor == null) {
nextMonitor = previousMonitor;
}
double p;
// p = (getTime(dp).toEpochMilli() - previousMonitor.getKey().toEpochMilli())/
p = 0.5;
double corrFactor = (getCR(previousMonitor.getValue()) * p + getCR(nextMonitor.getValue()) * (1 - p)) / norm;
double corrErr = previousMonitor.getValue().getValue("CRerr").doubleValue() / getCR(previousMonitor.getValue());
double pointErr = dp.getValue("CRerr").doubleValue() / getCR(dp);
double err = Math.sqrt(corrErr * corrErr + pointErr * pointErr) * getCR(dp);
if (dp.names().contains("Monitor")) {
point.putValue("Monitor", Value.of(dp.getValue("Monitor").doubleValue() / corrFactor));
} else {
point.putValue("Monitor", corrFactor);
}
point.putValue("CR", Value.of(dp.getValue("CR").doubleValue() / corrFactor));
point.putValue("Window", Value.of(dp.getValue("Window").doubleValue() / corrFactor));
point.putValue("Corrected", Value.of(dp.getValue("Corrected").doubleValue() / corrFactor));
point.putValue("CRerr", Value.of(err));
}
if (meta().getBoolean("calculateRelative", false)) {
point.putValue("relCR", point.getValue("CR").doubleValue() / norm);
point.putValue("relCRerr", point.getValue("CRerr").doubleValue() / norm);
}
dataList.add(point);
}
// DataFormat format;
//
// if (!dataList.isEmpty()) {
// //Генерируем автоматический формат по первой строчке
// format = DataFormat.of(dataList.get(0));
// } else {
// format = DataFormat.of(parnames);
// }
DataSet data = new ListDataSet(sourceData.getName(), sourceData.meta(), dataList);
OutputStream stream = buildActionOutput(data);
ColumnedDataWriter.writeDataSet(stream, data, head);
return data;
}
@Override
protected void afterAction(ActionResult<DataSet> pack) throws ContentException {
printMonitorData();
super.afterAction(pack);
}
private void printMonitorData() {
String monitorFileName = meta().getString("monitorFile", "monitor");
OutputStream stream = buildActionOutput(monitorFileName);
ListDataSet data = new ListDataSet("monitor", null, monitorPoints);
ColumnedDataWriter.writeDataSet(stream, data.sort("Timestamp", true), "Monitor points", monitorNames);
}
private boolean isMonitorPoint(double monitor, DataPoint point) {
return point.getValue("Uset").doubleValue() == monitor;
}
private LocalDateTime getTime(DataPoint point) {
return LocalDateTime.ofInstant(point.getValue("Timestamp").timeValue(), ZoneId.of("GMT+3"));
}
private int getTotal(DataPoint point) {
return point.getValue("Total").intValue();
}
private double getCR(DataPoint point) {
return point.getValue("CR").doubleValue();
}
private TreeMap<LocalDateTime, DataPoint> getMonitorIndex(double monitor, Iterable<DataPoint> data) {
TreeMap<LocalDateTime, DataPoint> res = new TreeMap<>();
for (DataPoint dp : data) {
if (isMonitorPoint(monitor, dp)) {
res.put(getTime(dp), dp);
}
}
return res;
}
}

View File

@ -0,0 +1,125 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.actions;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.meta.Meta;
import hep.dataforge.description.ValueDef;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.context.Context;
import hep.dataforge.data.DataFormat;
import hep.dataforge.data.DataPoint;
import hep.dataforge.data.DataSet;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.exceptions.ContentException;
import hep.dataforge.io.ColumnedDataWriter;
import hep.dataforge.io.XMLMetaWriter;
import hep.dataforge.io.log.Logable;
import inr.numass.data.NMFile;
import inr.numass.data.NMPoint;
import inr.numass.data.RawNMPoint;
import java.io.OutputStream;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Darksnake
*/
@TypedActionDef(name = "prepareData", inputType = NMFile.class, outputType = DataSet.class)
@ValueDef(name = "lowerWindow", type = "NUMBER", def = "0", info = "Base for the window lowerWindow bound")
@ValueDef(name = "lowerWindowSlope", type = "NUMBER", def = "0", info = "Slope for the window lowerWindow bound")
@ValueDef(name = "upperWindow", type = "NUMBER", info = "Upper bound for window")
@ValueDef(name = "deadTime", type = "NUMBER", def = "0", info = "Dead time in us")
public class PrepareDataAction extends OneToOneAction<NMFile, DataSet> {
public static String[] parnames = {"Uset", "Uread", "Length", "Total", "Window", "Corrected", "CR", "CRerr", "Timestamp"};
public PrepareDataAction(Context context, Meta an) {
super(context, an);
}
private int getLowerBorder(Meta source, double Uset) throws ContentException {
double b = source.getDouble("lowerWindow", this.meta().getDouble("lowerWindow", 0));
double a = source.getDouble("lowerWindowSlope", this.meta().getDouble("lowerWindowSlope", 0));
return (int) (b + Uset * a);
}
@Override
protected ListDataSet execute(Logable log, Meta reader, NMFile dataFile) throws ContentException {
// log.logString("File %s started", dataFile.getName());
int upper = dataFile.meta().getInt("upperWindow", this.meta().getInt("upperWindow", RawNMPoint.MAX_CHANEL - 1));
double deadTime = dataFile.meta().getDouble("deadTime", this.meta().getDouble("deadTime", 0));
// double bkg = source.meta().getDouble("background", this.meta().getDouble("background", 0));
List<DataPoint> dataList = new ArrayList<>();
for (NMPoint point : dataFile.getNMPoints()) {
long total = point.getEventsCount();
double Uset = point.getUset();
double Uread = point.getUread();
double time = point.getLength();
int a = getLowerBorder(dataFile.meta(), Uset);
int b = Math.min(upper, RawNMPoint.MAX_CHANEL);
// analyzer.setMonitorCorrector(corrector);
long wind = point.getCountInWindow(a, b);
double corr = point.getCountRate(a, b, deadTime) * point.getLength();// - bkg * (b - a);
double cr = point.getCountRate(a, b, deadTime);
double crErr = point.getCountRateErr(a, b, deadTime);
Instant timestamp = point.getAbsouteTime().toInstant(ZoneOffset.UTC);
dataList.add(new MapDataPoint(parnames, new Object[]{Uset, Uread, time, total, wind, corr, cr, crErr, timestamp}));
}
DataFormat format;
if (!dataList.isEmpty()) {
//Генерируем автоматический формат по первой строчке
format = DataFormat.forPoint(dataList.get(0));
} else {
format = DataFormat.forNames(8, parnames);
}
// AnnotationBuilder builder = dataFile.meta().getBuilder();
String head;
if (dataFile.getHead() != null) {
head = dataFile.getHead();
// builder.putValue("datafilehead",head);
} else {
head = dataFile.getName();
}
head = head + "\n" + new XMLMetaWriter().writeString(meta(), null) + "\n";
ListDataSet data = new ListDataSet(dataFile.getName(), dataFile.meta(), dataList, format);
OutputStream stream = buildActionOutput(data);
ColumnedDataWriter.writeDataSet(stream, data, head);
// log.logString("File %s completed", dataFile.getName());
return data;
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.actions;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.meta.Meta;
import hep.dataforge.description.NodeDef;
import hep.dataforge.description.ValueDef;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.context.Context;
import hep.dataforge.data.FileData;
import hep.dataforge.exceptions.ContentException;
import hep.dataforge.io.log.Logable;
import static inr.numass.NumassIO.getNumassData;
import inr.numass.data.NMFile;
import inr.numass.data.RawNMFile;
/**
*
* @author Darksnake
*/
@TypedActionDef(name = "readData",
inputType = FileData.class, outputType = NMFile.class, description = "Read binary numass data file")
@ValueDef(name = "fileName", info = "The name of the file. By default equals file name.")
@ValueDef(name = "HVdev", info = "Divider for HV measurements. Should be set to 1.0 for numass data 2014",
def = "2.468555393226049", type = "NUMBER")
@ValueDef(name = "noUset", info = "If 'true', then Uset = Uread")
@NodeDef(name = "debunch", target = "class::inr.numass.actions.DebunchAction", info = "If given, governs debunching")
public class ReadNumassDataAction extends OneToOneAction<FileData, NMFile> {
public ReadNumassDataAction(Context context, Meta an) {
super(context, an);
}
@Override
protected NMFile execute(Logable log, Meta reader, FileData source) throws ContentException {
// log.logString("File '%s' started", source.getName());
RawNMFile raw = getNumassData(source, meta());
if (meta().getBoolean("paw", false)) {
raw.generatePAW(buildActionOutput(source.getName() + ".paw"));
}
if(meta().hasNode("debunch")){
DebunchAction debunch = new DebunchAction(getContext(), meta().getNode("debunch"));
raw = debunch.execute(log, null, raw);
}
NMFile result = new NMFile(raw);
return result;
}
}

View File

@ -0,0 +1,283 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.actions;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.meta.Meta;
import hep.dataforge.context.Context;
import hep.dataforge.data.DataSet;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.datafitter.FitState;
import hep.dataforge.datafitter.FitTaskResult;
import hep.dataforge.datafitter.Param;
import hep.dataforge.datafitter.ParamSet;
import hep.dataforge.datafitter.models.Histogram;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.io.ColumnedDataWriter;
import hep.dataforge.io.log.Logable;
import hep.dataforge.io.PrintFunction;
import hep.dataforge.maths.GridCalculator;
import hep.dataforge.maths.NamedDoubleSet;
import hep.dataforge.maths.NamedMatrix;
import hep.dataforge.maths.integration.UnivariateIntegrator;
import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.plots.PlotFrame;
import hep.dataforge.plots.PlotsPlugin;
import hep.dataforge.plots.XYPlotFrame;
import hep.dataforge.plots.data.PlottableData;
import hep.dataforge.plots.data.PlottableFunction;
import hep.dataforge.simulation.GaussianParameterGenerator;
import inr.numass.NumassContext;
import inr.numass.models.ExperimentalVariableLossSpectrum;
import inr.numass.models.LossCalculator;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.util.Arrays;
import org.apache.commons.math3.analysis.UnivariateFunction;
import org.apache.commons.math3.analysis.interpolation.LinearInterpolator;
import org.apache.commons.math3.analysis.interpolation.UnivariateInterpolator;
import org.apache.commons.math3.stat.StatUtils;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import org.slf4j.LoggerFactory;
/**
*
* @author darksnake
*/
@TypedActionDef(name = "showLoss", inputType = FitState.class, outputType = FitState.class,
description = "Show loss spectrum for fit with loss model. Calculate excitation to ionisation ratio.")
public class ShowLossSpectrumAction extends OneToOneAction<FitState, FitState> {
private static final String[] names = {"X", "exPos", "ionPos", "exW", "ionW", "exIonRatio"};
public ShowLossSpectrumAction(Context context, Meta annotation) {
super(context, annotation);
}
@Override
protected FitState execute(Logable log, Meta reader, FitState input) {
ParamSet pars = input.getParameters();
if (!pars.names().contains(names)) {
LoggerFactory.getLogger(getClass()).error("Wrong input FitState. Must be loss spectrum fit.");
throw new RuntimeException("Wrong input FitState");
}
UnivariateFunction scatterFunction;
boolean calculateRatio = false;
XYPlotFrame frame = (XYPlotFrame) PlotsPlugin.buildFrom(getContext())
.buildPlotFrame(getName(), input.getName()+".loss",
new MetaBuilder("plot")
.setValue("plotTitle", "Differential scattering crossection for " + input.getName())
);
switch (input.getModel().getName()) {
case "scatter-variable":
scatterFunction = LossCalculator.getSingleScatterFunction(pars);
calculateRatio = true;
LossCalculator.plotScatter(frame, pars);
break;
case "scatter-empiric-experimental":
scatterFunction = new ExperimentalVariableLossSpectrum.Loss(0.3).total(pars);
frame.add(new PlottableFunction("Cross-section", null, scatterFunction, 0, 100, 1000));
break;
default:
throw new RuntimeException("Can work only with variable loss spectra");
}
double threshold = 0;
double ionRatio = -1;
double ionRatioError = -1;
if (calculateRatio) {
threshold = reader.getDouble("ionThreshold", 17);
ionRatio = calcultateIonRatio(pars, threshold);
log.log("The ionization ratio (using threshold {}) is {}", threshold, ionRatio);
ionRatioError = calultateIonRatioError(input, threshold);
log.log("the ionization ration standard deviation (using threshold {}) is {}", threshold, ionRatioError);
}
if (reader.getBoolean("printResult", false)) {
PrintWriter writer = new PrintWriter(new OutputStreamWriter(buildActionOutput(input), Charset.forName("UTF-8")));
// writer.println("*** FIT PARAMETERS ***");
input.print(writer);
// for (Param param : pars.getSubSet(names).getParams()) {
// writer.println(param.toString());
// }
// writer.println();
// out.printf("Chi squared over degrees of freedom: %g/%d = %g", input.getChi2(), input.ndf(), chi2 / this.ndf());
writer.println();
writer.println("*** LOSS SPECTRUM INFORMATION ***");
writer.println();
if (calculateRatio) {
writer.printf("The ionization ratio (using threshold %f) is %f%n", threshold, ionRatio);
writer.printf("The ionization ratio standard deviation (using threshold %f) is %f%n", threshold, ionRatioError);
writer.println();
}
// double integralThreshold = reader.getDouble("numass.eGun", 19005d) - reader.getDouble("integralThreshold", 14.82);
// double integralRatio = calculateIntegralExIonRatio(input.getDataSet(), input.getParameters().getValue("X"), integralThreshold);
// writer.printf("The excitation to ionization ratio from integral spectrum (using threshold %f) is %f%n", integralThreshold, integralRatio);
writer.println();
writer.println("*** SUMMARY ***");
writer.printf("%s\t", "name");
for (String parName : names) {
writer.printf("%s\t%s\t", parName, parName + "_err");
}
if (calculateRatio) {
writer.printf("%s\t", "ionRatio");
writer.printf("%s\t", "ionRatioErr");
}
writer.printf("%s%n", "chi2");
writer.printf("%s\t", input.getName());
for (Param param : pars.getSubSet(names).getParams()) {
writer.printf("%f\t%f\t", param.value(), param.getErr());
}
if (calculateRatio) {
writer.printf("%f\t", ionRatio);
writer.printf("%f\t", ionRatioError);
}
writer.printf("%f%n", input.getChi2() / ((FitTaskResult) input).ndf());
writer.println();
writer.println("***LOSS SPECTRUM***");
writer.println();
PrintFunction.printFunctionSimple(writer, scatterFunction, 0, 100, 500);
if (meta().getBoolean("showSpread", false)) {
writer.println("***SPECTRUM SPREAD***");
writer.println();
ParamSet parameters = input.getParameters().getSubSet(new String[]{"exPos", "ionPos", "exW", "ionW", "exIonRatio"});
NamedMatrix covariance = input.getCovariance();
DataSet spreadData = generateSpread(writer, input.getName(), parameters, covariance);
ColumnedDataWriter.writeDataSet(System.out, spreadData, "", spreadData.getDataFormat().asArray());
}
}
return input;
}
public static double calcultateIonRatio(NamedDoubleSet set, double threshold) {
UnivariateIntegrator integrator = NumassContext.highDensityIntegrator;
UnivariateFunction integrand = LossCalculator.getSingleScatterFunction(set);
return 1d - integrator.integrate(integrand, 5d, threshold);
}
private double calculateIntegralExIonRatio(DataSet data, double X, double integralThreshold) {
double scatterProb = 1 - Math.exp(-X);
double[] x = data.getColumn("Uset").asList().stream().mapToDouble((val) -> val.doubleValue()).toArray();
double[] y = data.getColumn("CR").asList().stream().mapToDouble((val) -> val.doubleValue()).toArray();
double yMax = StatUtils.max(y);
UnivariateInterpolator interpolator = new LinearInterpolator();
UnivariateFunction interpolated = interpolator.interpolate(x, y);
double thresholdValue = interpolated.value(integralThreshold);
double one = 1 - X * Math.exp(-X);
double ionProb = (one - thresholdValue / yMax);
double exProb = (thresholdValue / yMax - one + scatterProb);
return exProb / ionProb;
}
public double calultateIonRatioError(FitState state, double threshold) {
ParamSet parameters = state.getParameters().getSubSet(new String[]{"exPos", "ionPos", "exW", "ionW", "exIonRatio"});
NamedMatrix covariance = state.getCovariance();
return calultateIonRatioError(state.getName(), parameters, covariance, threshold);
}
@SuppressWarnings("Unchecked")
public double calultateIonRatioError(String name, NamedDoubleSet parameters, NamedMatrix covariance, double threshold) {
int number = 10000;
double[] res = new GaussianParameterGenerator(parameters, covariance)
.generate(number)
.stream()
.mapToDouble((vector) -> calcultateIonRatio(vector, threshold))
.filter(d -> !Double.isNaN(d))
.toArray();
Histogram hist = new Histogram("ionRatio", 0.3, 0.5, 0.002);
hist.fill(res);
XYPlotFrame frame = (XYPlotFrame) PlotsPlugin.buildFrom(getContext())
.buildPlotFrame(getName(), name+".ionRatio",
new MetaBuilder("plot").setValue("plotTitle", "Ion ratio Distribution for " + name)
);
// XYPlotFrame frame = JFreeChartFrame.drawFrame("Ion ratio Distribution for " + name, null);
frame.add(new PlottableData(hist, "binCenter", "count"));
return new DescriptiveStatistics(res).getStandardDeviation();
}
public static DataSet generateSpread(PrintWriter writer, String name, NamedDoubleSet parameters, NamedMatrix covariance) {
int numCalls = 1000;
int gridPoints = 200;
double a = 8;
double b = 32;
double[] grid = GridCalculator.getUniformUnivariateGrid(a, b, gridPoints);
double[] upper = new double[gridPoints];
double[] lower = new double[gridPoints];
double[] dispersion = new double[gridPoints];
double[] central = new double[gridPoints];
UnivariateFunction func = LossCalculator.getSingleScatterFunction(parameters);
for (int j = 0; j < gridPoints; j++) {
central[j] = func.value(grid[j]);
}
Arrays.fill(upper, Double.NEGATIVE_INFINITY);
Arrays.fill(lower, Double.POSITIVE_INFINITY);
Arrays.fill(dispersion, 0);
GaussianParameterGenerator generator = new GaussianParameterGenerator(parameters, covariance);
for (int i = 0; i < numCalls; i++) {
func = LossCalculator.getSingleScatterFunction(generator.generate());
for (int j = 0; j < gridPoints; j++) {
double val = func.value(grid[j]);
upper[j] = Math.max(upper[j], val);
lower[j] = Math.min(lower[j], val);
dispersion[j] += (val - central[j]) * (val - central[j]) / numCalls;
}
}
String[] pointNames = {"e", "central", "lower", "upper", "dispersion"};
ListDataSet res = new ListDataSet("spread", pointNames);
for (int i = 0; i < gridPoints; i++) {
res.add(new MapDataPoint(pointNames, grid[i], central[i], lower[i], upper[i], dispersion[i]));
}
return res;
}
}

View File

@ -0,0 +1,174 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.actions;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.context.Context;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.exceptions.ContentException;
import hep.dataforge.io.ColumnedDataWriter;
import hep.dataforge.io.log.Logable;
import hep.dataforge.meta.Meta;
import hep.dataforge.plots.jfreechart.JFreeChartFrame;
import inr.numass.data.ESpectrum;
import inr.numass.data.NMFile;
import inr.numass.data.NMPoint;
import java.awt.Color;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleEdge;
/**
*
* @author Darksnake
*/
@TypedActionDef(name = "showSpectrum", inputType = NMFile.class, outputType = NMFile.class)
public class ShowSpectrumAction extends OneToOneAction<NMFile, NMFile> {
public ShowSpectrumAction(Context context, Meta an) {
super(context, an);
}
@Override
protected NMFile execute(Logable log, Meta reader, NMFile source) throws ContentException {
log.log("File {} started", source.getName());
List<NMPoint> printPoints = new ArrayList<>();
List<NMPoint> showPoints = new ArrayList<>();
for (NMPoint point : source.getNMPoints()) {
if (toPrint(point)) {
printPoints.add(point);
}
if (toShow(point)) {
showPoints.add(point);
}
}
int chanelsPerBin = meta().getInt("binning", 1); // биннинг
boolean normalize = meta().getBoolean("normalize", false); // нормировка на время набора точки
if (showPoints.size() > 0) {
showSpectra(showPoints, source.getName(), chanelsPerBin, normalize);
}
if (printPoints.size() > 0) {
ESpectrum data = new ESpectrum(source.getName(), printPoints, chanelsPerBin, normalize);
OutputStream stream = buildActionOutput(data);
ColumnedDataWriter.writeDataSet(stream, data, source.getName());
}
log.log("File {} completed", source.getName());
return source;
}
private boolean toPrint(NMPoint point) throws ContentException {
Meta root = this.meta();
if (root.hasNode("print")) {
List<? extends Meta> cfg = meta().getNodes("print");
boolean res = false;
for (Meta e : cfg) {
double from = e.getDouble("from", 0);
double to = e.getDouble("to", Double.POSITIVE_INFINITY);
res = res || ((point.getUset() >= from) && (point.getUset() <= to));
}
return res;
} else {
return root.getBoolean("print", false);
}
}
private boolean toShow(NMPoint point) throws ContentException {
Meta root = this.meta();
if (root.hasNode("show")) {
List<? extends Meta> cfg = meta().getNodes("show");
boolean res = false;
for (Meta e : cfg) {
double from = e.getDouble("from", 0);
double to = e.getDouble("to", Double.POSITIVE_INFINITY);
res = res || ((point.getUset() >= from) && (point.getUset() <= to));
}
return res;
} else {
return root.getBoolean("show", false);
}
}
private static void showSpectra(List<NMPoint> points, String head, int binning, boolean normalize) {
XYSeriesCollection dataset = new XYSeriesCollection();
for (NMPoint point : points) {
Map<Double, Double> spectrum = point.getMapWithBinning(binning, normalize);
String serName = Double.toString(point.getUset());
XYSeries ser;
if (dataset.getSeriesIndex(serName) >= 0) {
serName = serName + " " + Integer.toString(points.indexOf(point));
}
ser = new XYSeries(serName);
for (Map.Entry<Double, Double> sp : spectrum.entrySet()) {
ser.add(sp.getKey(), sp.getValue());
}
dataset.addSeries(ser);
}
showSpectra(dataset, head, binning, normalize);
}
private static void showSpectra(XYSeriesCollection dataset, String head, int binning, boolean normalize) {
String axisName = "count";
if (normalize) {
axisName += " rate";
} else {
axisName += " number";
}
if (binning != 1) {
axisName += " per " + binning + " chanels";
}
JFreeChartFrame frame = JFreeChartFrame.drawFrame(head, null);
frame.getYAxisConfig().putValue("title", axisName);
JFreeChart chart = frame.getChart();
chart.getXYPlot().setDataset(dataset);
chart.getXYPlot().setRenderer(new XYLineAndShapeRenderer(true, false));
chart.getLegend().setPosition(RectangleEdge.RIGHT);
chart.getXYPlot().setDomainGridlinesVisible(true);
chart.getXYPlot().setRangeGridlinesVisible(true);
chart.getXYPlot().setDomainGridlinePaint(Color.BLACK);
chart.getXYPlot().setRangeGridlinePaint(Color.BLACK);
}
}

View File

@ -0,0 +1,91 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.actions;
import hep.dataforge.data.DataFormat;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.values.Value;
import inr.numass.data.NMFile;
import inr.numass.data.NMPoint;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.math3.util.Pair;
/**
*
* @author Darksnake
*/
public class SlicedData extends ListDataSet {
private static final String TNAME = "Time";
//format = {U,username1,username2, ...}
private static final String UNAME = "U";
private static DataFormat prepateFormat(Map<String,Pair<Integer,Integer>> intervals){
ArrayList<String> names = new ArrayList<>(intervals.keySet());
names.add(0, TNAME);
names.add(0, UNAME);
return DataFormat.forNames(8, names);
}
public SlicedData(NMFile file, Map<String,Pair<Integer,Integer>> intervals, boolean normalize) {
super(prepateFormat(intervals));
fill(file, intervals, normalize);
}
private void fill(NMFile file, Map<String,Pair<Integer,Integer>> intervals, boolean normalize){
for (NMPoint point : file.getNMPoints()) {
//создаем основу для будущей точки
HashMap<String,Value> map = new HashMap<>();
//Кладем напряжение
map.put(UNAME, Value.of(point.getUset()));
double t = point.getLength();
map.put(TNAME, Value.of(t));
for (Map.Entry<String, Pair<Integer, Integer>> entry : intervals.entrySet()) {
String name = entry.getKey();
Pair<Integer, Integer> pair = entry.getValue();
int a = pair.getFirst();
int b = pair.getSecond();
int count;
// проверяем порядок границ и переворачиваем если нужно
if(b>a){
count = point.getCountInWindow(a, b);
} else if(b<a) {
count = point.getCountInWindow(b, a);
} else{
count = point.getCountInChanel(a);
}
//пихаем все в map
if(normalize){
map.put(name, Value.of(count/t));
} else {
map.put(name, Value.of(count));
}
}
this.add(new MapDataPoint(map));
}
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.actions;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.context.Context;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.exceptions.ContentException;
import hep.dataforge.io.ColumnedDataWriter;
import hep.dataforge.io.log.Logable;
import hep.dataforge.meta.Meta;
import inr.numass.data.NMFile;
import inr.numass.data.RawNMPoint;
import java.io.OutputStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.math3.util.Pair;
/**
*
* @author Darksnake
*/
@TypedActionDef(name = "slicing", inputType = NMFile.class, outputType = NMFile.class)
public class SlicingAction extends OneToOneAction<NMFile, NMFile> {
public static final String name = "slicing";
public SlicingAction(Context context, Meta an) {
super(context, an);
}
@Override
public String getName() {
return name;
}
@Override
protected NMFile execute(Logable log, Meta reader, NMFile source) throws ContentException {
boolean normalize;
Map<String, Pair<Integer, Integer>> slicingConfig;
LinkedHashMap<String, Pair<Integer, Integer>> res = new LinkedHashMap<>();
List<? extends Meta> list = meta().getNode("sliceconfig").getNodes("slicepoint");
for (Meta slice : list) {
String title = slice.getString("title", slice.getName());
int from = slice.getInt("from", 0);
int to = slice.getInt("to", RawNMPoint.MAX_CHANEL);
res.put(title, new Pair<>(from, to));
}
slicingConfig = res;
normalize = meta().getBoolean("normalize", false);
if (slicingConfig == null) {
throw new RuntimeException("Slice configuration not defined");
}
log.log("File {} started", source.getName());
SlicedData sData = new SlicedData(source, slicingConfig, normalize);
OutputStream stream = buildActionOutput(source);
ColumnedDataWriter.writeDataSet(stream, sData, null);
log.log("File {} completed", source.getName());
return source;
}
}

View File

@ -0,0 +1,117 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.actions;
import hep.dataforge.actions.ManyToOneAction;
import hep.dataforge.meta.Meta;
import hep.dataforge.content.NamedGroup;
import hep.dataforge.content.GroupBuilder;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.context.Context;
import hep.dataforge.data.DataFormat;
import hep.dataforge.data.DataPoint;
import hep.dataforge.data.DataSet;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.values.Value;
import hep.dataforge.datafitter.FitState;
import hep.dataforge.io.ColumnedDataWriter;
import hep.dataforge.io.log.Logable;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
/**
*
* @author Darksnake
*/
@TypedActionDef(name = "summary", inputType = FitState.class, outputType = DataSet.class, description = "Generate summary for fit results of different datasets.")
public class SummaryAction extends ManyToOneAction<FitState, DataSet> {
public static final String SUMMARY_NAME = "sumName";
public SummaryAction(Context context, Meta annotation) {
super(context, annotation);
}
@Override
protected List<NamedGroup<FitState>> buildGroups(Meta reader, List<FitState> input) {
List<NamedGroup<FitState>> groups;
if (reader.hasNode("grouping")) {
groups = super.buildGroups(reader, input);
} else {
groups = GroupBuilder.byValue(SUMMARY_NAME, reader.getString(SUMMARY_NAME, "summary")).group(input);
}
return groups;
}
@Override
protected DataSet execute(Logable log, Meta reader, NamedGroup<FitState> input){
String[] parNames = meta().getStringArray("parnames");
String[] names = new String[2 * parNames.length + 2];
names[0] = "file";
for (int i = 0; i < parNames.length; i++) {
names[2 * i + 1] = parNames[i];
names[2 * i + 2] = parNames[i] + "Err";
}
names[names.length - 1] = "chi2";
// boolean calculateWAV = meta().getBoolean("wav", true);
String fileName = reader.getString(SUMMARY_NAME, "summary");
ListDataSet res = new ListDataSet(fileName, DataFormat.forNames(8, names));
double[] weights = new double[parNames.length];
Arrays.fill(weights, 0);
double[] av = new double[parNames.length];
Arrays.fill(av, 0);
for (FitState state : input) {
Value[] values = new Value[names.length];
values[0] = Value.of(state.getName());
for (int i = 0; i < parNames.length; i++) {
Value val = Value.of(state.getParameters().getValue(parNames[i]));
values[2 * i + 1] = val;
Value err = Value.of(state.getParameters().getError(parNames[i]));
values[2 * i + 2] = err;
double weight = 1 / err.doubleValue() / err.doubleValue();
av[i] += val.doubleValue() * weight;
weights[i] += weight;
}
values[values.length - 1] = Value.of(state.getChi2());
DataPoint point = new MapDataPoint(names, values);
res.add(point);
}
Value[] averageValues = new Value[names.length];
averageValues[0] = Value.of("average");
averageValues[averageValues.length - 1] = Value.of(0);
for (int i = 0; i < parNames.length; i++) {
averageValues[2 * i + 1] = Value.of(av[i] / weights[i]);
averageValues[2 * i + 2] = Value.of(1 / Math.sqrt(weights[i]));
}
res.add(new MapDataPoint(names, averageValues));
OutputStream stream = buildActionOutput(res);
ColumnedDataWriter.writeDataSet(stream, res, fileName);
return res;
}
}

View File

@ -0,0 +1,89 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data;
import hep.dataforge.data.DataFormat;
import hep.dataforge.data.ListDataSet;
import hep.dataforge.data.MapDataPoint;
import hep.dataforge.values.Value;
import hep.dataforge.values.ValueFormat;
import hep.dataforge.values.ValueFormatFactory;
import hep.dataforge.values.ValueType;
import hep.dataforge.io.ColumnedDataWriter;
import java.io.OutputStream;
import static java.lang.String.format;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static java.lang.String.format;
/**
*
* @author Darksnake
*/
public class ESpectrum extends ListDataSet {
private final static String binCenter = "chanel";
private static DataFormat prepareFormat(List<NMPoint> points) {
// ArrayList<String> names = new ArrayList<>();
// names.add(binCenter);
Map<String, ValueFormat> format = new LinkedHashMap<>();
format.put(binCenter, ValueFormatFactory.forType(ValueType.STRING));
for (NMPoint point : points) {
// names.add(format("%.3f", point.getUread()));
format.put(format("%.3f", point.getUread()), ValueFormatFactory.fixedWidth(10));
}
return new DataFormat(format);
}
int binning = 1;
public ESpectrum(String name, List<NMPoint> points, int binning, boolean normalize) {
super(name, prepareFormat(points));
this.binning = binning;
fill(points, normalize);
}
private void fill(List<NMPoint> points, boolean normalize) {
assert !points.isEmpty();
List<Map<Double, Double>> spectra = new ArrayList<>();
for (NMPoint numassPoint : points) {
spectra.add(numassPoint.getMapWithBinning(binning, normalize));
}
for (Double x : spectra.get(0).keySet()) {
Map<String, Value> res = new HashMap<>();
res.put(binCenter, Value.of(x));
for (int j = 0; j < points.size(); j++) {
res.put(format("%.3f", points.get(j).getUread()), Value.of(spectra.get(j).get(x)));
}
this.add(new MapDataPoint(res));
}
}
public void printToFile(OutputStream stream) {
ColumnedDataWriter.writeDataSet(stream, this, null);
// new ColumnedDataWriter(stream, this.getDataFormat().asArray()).writeDataSet(this, null);
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data;
import static java.lang.Math.max;
/**
* инструменты для работы с энергитическим спектром (который в каналах)
* @author Darksnake
*/
public class ESpectrumUtils {
public static int[] substract(int[] sp1, int[] sp2) {
return substract(sp1, sp2, 0, sp1.length);
}
public static int[] substract(int[] sp1, int[] sp2, int from, int to) {
assert sp1.length == sp2.length;
assert to >= from;
assert to <= sp1.length;
int[] res = new int[sp1.length];
for (int i = from; i < to; i++) {
res[i] = max(0, sp1[i]-sp2[i]);
}
return res;
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data;
import hep.dataforge.context.GlobalContext;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.ParseException;
import java.time.LocalDateTime;
import static java.time.temporal.ChronoUnit.SECONDS;
import java.util.ArrayList;
import java.util.List;
/**
* Заплатка для задания поправки на масс-спектрометр
*
* @author Darksnake
*/
public class MonitorCorrector {
private final double average;
private final List<MonitorPoint> list;
public MonitorCorrector(String path) throws ParseException, IOException {
this(GlobalContext.instance().io().getFile(path));
}
public MonitorCorrector(File monitorFile) throws ParseException, IOException {
list = new ArrayList<>();
BufferedReader reader = new BufferedReader(new FileReader(monitorFile));
// Scanner sc = new Scanner(monitorFile);
double sum = 0;
String str = reader.readLine();
while ((str!=null)&&(!str.isEmpty())) {
MonitorPoint point = new MonitorPoint(str);
str = reader.readLine();
list.add(point);
sum += point.getMonitorValue();
}
average = sum / list.size();
}
/**
* возвращает ближайшую по времени точку
*
* @param time
* @return
*/
public MonitorPoint findNearestMonitorPoint(LocalDateTime time) {
MonitorPoint nearest = this.list.get(0);
for (MonitorPoint point : this.list) {
if (Math.abs(point.getTime().until(time, SECONDS))
< Math.abs(nearest.getTime().until(time, SECONDS))) {
nearest = point;
}
}
return nearest;
}
public double getCorrection(LocalDateTime start, double length) {
LocalDateTime finish = start.plusSeconds((long) length);
return (findNearestMonitorPoint(start).getMonitorValue() + findNearestMonitorPoint(finish).getMonitorValue()) / 2 / average;
}
public double getCorrectionError(LocalDateTime start, double length) {
LocalDateTime finish = start.plusSeconds((long) length);
return (findNearestMonitorPoint(start).getMonitorError() + findNearestMonitorPoint(finish).getMonitorError()) / 2 / average;
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.util.Scanner;
/**
*
* @author Darksnake
*/
public class MonitorPoint {
// private static SimpleDateFormat format = new SimpleDateFormat("yyyy:MM:dd:HH:mm:ss");
private final double monitorError;
private final double monitorValue;
private final LocalDateTime time;
public MonitorPoint(LocalDateTime time, double monitorValue, double monitorError) {
this.time = time;
this.monitorValue = monitorValue;
this.monitorError = monitorError;
}
public MonitorPoint(String str) throws ParseException {
Scanner sc = new Scanner(str);
String datestr = sc.next();
//using ISO-8601
time = LocalDateTime.parse(datestr);
monitorValue = sc.nextDouble();
if (sc.hasNextDouble()) {
monitorError = sc.nextDouble();
} else {
monitorError = 0;
}
}
/**
* @return the monitorError
*/
public double getMonitorError() {
return monitorError;
}
/**
* @return the monitorValue
*/
public double getMonitorValue() {
return monitorValue;
}
/**
* @return the time
*/
public LocalDateTime getTime() {
return time;
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data;
/**
*
* @author Darksnake
*/
public class NMEvent implements Cloneable{
protected final short chanel;
protected final double time;
public NMEvent(short chanel, double time) {
this.chanel = chanel;
this.time = time;
}
@Override
public NMEvent clone() {
return new NMEvent(chanel, time);
}
/**
* @return the chanel
*/
public short getChanel() {
return chanel;
}
/**
* @return the time
*/
public double getTime(){
return time;
}
}

View File

@ -0,0 +1,120 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data;
import hep.dataforge.content.AbstractContent;
import hep.dataforge.description.ValueDef;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
/**
*
* Объект, содержащий только спектры, но не сами события
*
* @author Darksnake
*/
@ValueDef(name = "numass.path", info = "Path to this data file in numass repository.")
@ValueDef(name = "numass.name", info = "The name of this data file.")
public class NMFile extends AbstractContent implements NumassData {
public static NMFile readStream(InputStream is, String fname, Meta config) throws IOException{
return new NMFile(new NumassDataReader(is, fname, config).read());
}
private final String head;
private final List<NMPoint> points;
public NMFile(RawNMFile file) {
super(file.getName(), file.meta());
this.head = file.getHead();
points = new ArrayList<>();
for (RawNMPoint point : file.getData()) {
points.add(new NMPoint(point));
}
}
@Override
public String getDescription() {
return "";
}
/**
* @return the head
*/
public String getHead() {
return head;
}
@Override
public Meta getInfo() {
return new MetaBuilder("info").setValue("info", head);
}
/**
* @return the points
*/
@Override
public List<NMPoint> getNMPoints() {
return points;
}
/**
* merge of all point with given Uset
*
* @param U
* @return
*/
public NMPoint getByUset(double U) {
for (NMPoint point : points) {
if (point.getUset() == U) {
return point;
}
}
return null;
}
/**
* merge of all point with given Uread
*
* @param U
* @return
*/
public NMPoint getByUread(double U) {
for (NMPoint point : points) {
if (point.getUread() == U) {
return point;
}
}
return null;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Instant startTime() {
return null;
}
}

View File

@ -0,0 +1,256 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data;
import hep.dataforge.data.DataPoint;
import hep.dataforge.data.MapDataPoint;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import static java.util.Arrays.sort;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author Darksnake
*/
public class NMPoint {
static final String[] dataNames = {"chanel", "count"};
private LocalDateTime absouteTime;
// private MonitorCorrector corrector = null;
// private double deadTime;
private long eventsCount;
private int overflow;
private double pointLength;
// private final MeasurementPoint point;
private final int[] spectrum;
private double uread;
private double uset;
public NMPoint(RawNMPoint point) {
if (point == null) {
throw new IllegalArgumentException();
}
this.pointLength = point.getLength();
this.uset = point.getUset();
this.uread = point.getUread();
this.absouteTime = point.getAbsouteTime();
this.eventsCount = point.getEventsCount();
// this.point = point;
spectrum = calculateSpectrum(point);
}
// public PointSpectrum(RawPoint point, double deadTime) {
// this(point);
// this.deadTime = deadTime;
// }
private int[] calculateSpectrum(RawNMPoint point) {
assert point.getEventsCount() > 0;
int[] result = new int[RawNMPoint.MAX_CHANEL];
Arrays.fill(result, 0);
point.getEvents().stream().forEach((event) -> {
if (event.getChanel() >= RawNMPoint.MAX_CHANEL) {
overflow++;
} else {
result[event.getChanel()]++;
}
});
return result;
}
public DataPoint fastSlice(int... borders) {
assert borders.length > 0;//FIXME replace by condition check
sort(borders);
assert borders[borders.length] < RawNMPoint.MAX_CHANEL;//FIXME replace by condition check
Integer[] slices = new Integer[borders.length + 2];
String[] names = new String[borders.length + 2];
slices[0] = getCountInWindow(0, borders[0]);
names[0] = Integer.toString(borders[0]);
for (int i = 1; i < borders.length; i++) {
slices[i] = getCountInWindow(borders[i - 1], borders[i]);
names[i] = Integer.toString(borders[i]);
}
slices[borders.length + 1] = getCountInWindow(borders[borders.length], RawNMPoint.MAX_CHANEL);
names[borders.length + 1] = Integer.toString(RawNMPoint.MAX_CHANEL);
slices[borders.length + 2] = RawNMPoint.MAX_CHANEL;
names[borders.length + 2] = "TOTAL";
//FIXME fix it!
return new MapDataPoint(names, slices);
}
/**
* @return the absouteTime
*/
public LocalDateTime getAbsouteTime() {
return absouteTime;
}
public int getCountInChanel(int chanel) {
return spectrum[chanel];
}
public int getCountInWindow(int from, int to) {
int res = 0;
for (int i = from; i <= to; i++) {
res += spectrum[i];
}
if (res == Integer.MAX_VALUE) {
throw new RuntimeException("integer overflow in spectrum calculation");
}
return res;
}
public double getCountRate(int from, int to, double deadTime) {
double wind = getCountInWindow(from, to) / getLength();
double res;
if (deadTime > 0) {
double total = getEventsCount();
double time = getLength();
res = wind / (1 - total * deadTime / time);
} else {
res = wind;
}
return res;
}
public double getCountRateErr(int from, int to, double deadTime) {
return Math.sqrt(getCountRate(from, to, deadTime) / getLength());
}
public List<DataPoint> getData() {
List<DataPoint> data = new ArrayList<>();
for (int i = 0; i < RawNMPoint.MAX_CHANEL; i++) {
data.add(new MapDataPoint(dataNames, i, spectrum[i]));
}
return data;
}
/**
* Events count - overflow
*
* @return
*/
public long getEventsCount() {
return eventsCount - getOverflow();
}
public List<DataPoint> getData(int binning, boolean normalize) {
List<DataPoint> data = new ArrayList<>();
double norm;
if (normalize) {
norm = getLength();
} else {
norm = 1d;
}
int i = 0;
while (i < RawNMPoint.MAX_CHANEL - binning) {
int start = i;
double sum = spectrum[start] / norm;
while (i < start + binning) {
sum += spectrum[i] / norm;
i++;
}
data.add(new MapDataPoint(dataNames, start + binning / 2d, sum));
i++;
}
return data;
}
public Map<Double, Double> getMapWithBinning(int binning, boolean normalize) {
Map<Double, Double> res = new LinkedHashMap<>();
double norm;
if (normalize) {
norm = getLength();
} else {
norm = 1d;
}
int i = 0;
while (i < RawNMPoint.MAX_CHANEL - binning) {
int start = i;
double sum = spectrum[start] / norm;
while (i < start + binning) {
sum += spectrum[i] / norm;
i++;
}
res.put(start + binning / 2d, sum);
i++;
}
return res;
}
public Map<Double, Double> getMapWithBinning(NMPoint reference, int binning) {
Map<Double, Double> sp = this.getMapWithBinning(binning, true);
Map<Double, Double> referenceSpectrum = reference.getMapWithBinning(binning, true);
Map<Double, Double> res = new LinkedHashMap<>();
sp.entrySet().stream().map((entry) -> entry.getKey()).forEach((bin) -> {
res.put(bin, Math.max(sp.get(bin) - referenceSpectrum.get(bin), 0));
});
return res;
}
/**
* @return the overflow
*/
public int getOverflow() {
return overflow;
}
/**
* @return the pointLength
*/
public double getLength() {
return pointLength;
}
/**
* @return the uread
*/
public double getUread() {
return uread;
}
/**
* @return the uset
*/
public double getUset() {
return uset;
}
}

View File

@ -0,0 +1,29 @@
/*
* 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.data;
import hep.dataforge.content.Named;
import hep.dataforge.meta.Meta;
import java.time.Instant;
import java.util.List;
/**
*
* @author Alexander Nozik <altavir@gmail.com>
*/
public interface NumassData extends Named{
String getDescription();
Meta getInfo();
List<NMPoint> getNMPoints();
boolean isEmpty();
Instant startTime();
}

View File

@ -0,0 +1,515 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data;
import hep.dataforge.data.BinaryData;
import hep.dataforge.meta.MergeRule;
import hep.dataforge.meta.Meta;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Scanner;
/**
*
* @author Darksnake, based on program by S.V.Zadorozhny, 1996
*/
public class NumassDataReader {
private String name;
private final InputStream stream;
private Meta config;
private double HVdev;
public NumassDataReader(BinaryData data, Meta config) throws IOException {
this(data.getInputStream(), data.meta()
.getString("filename", data.getName()), MergeRule.replace(config, data.meta()));
}
public NumassDataReader(String file, String fname, Meta config) throws FileNotFoundException {
this(new FileInputStream(file), fname, config);
if ((fname == null) || (fname.isEmpty())) {
name = file;
}
}
public NumassDataReader(InputStream is, String fname, Meta config) {
this.stream = new BufferedInputStream(is);
this.name = fname;
this.config = config;
HVdev = config.getDouble("HVdev", 2.468555393226049);
}
public RawNMFile read() throws IOException {
return readFile(name);
}
private int[] readBlock(int length) throws IOException {
int[] res = new int[length];
for (int i = 0; i < res.length; i++) {
res[i] = readByte();
}
return res;
}
private int readByte() throws IOException {
return stream.read();
}
private short readChanel(int hb) throws IOException {
assert hb < 127;
return (short) (readByte() + 256 * hb);
}
private LocalDateTime readDate(String head) throws IOException {
// Должны считать 14 символов
Scanner sc = new Scanner(head);
sc.nextLine();
String dateStr = sc.nextLine().trim();
//DD.MM.YY HH:MM
//12:35:16 19-11-2013
DateTimeFormatter format = DateTimeFormatter.ofPattern("HH:mm:ss dd-MM-yyyy");
LocalDateTime date = LocalDateTime.parse(dateStr, format);
return date;
}
private NMEvent readEvent(int b, double timeDiv) throws IOException {
short chanel;
long time;
int hb = (b & 0x0f);
int lab = (b & 0xf0);
switch (lab) {
case 0x10:
chanel = readChanel(hb);
time = readTime();
break;
case 0x20:
chanel = 0;
time = readTime();
break;
case 0x40:
time = 0;
chanel = readChanel(hb);
break;
case 0x80:
time = 0;
chanel = 0;
break;
default:
throw new IOException("Event head expected");
}
return new NMEvent(chanel, time / timeDiv);
}
private RawNMFile readFile(String name) throws IOException {
RawNMFile file = new RawNMFile(name);
String head = readHead();//2048
file.setHead(head.replaceAll("\u0000", ""));
LocalDateTime filedate = readDate(head);
int lab = readByte();
do {
RawNMPoint point = readPoint(lab, filedate);
//Устанавливаем дату точки
file.putPoint(point);
lab = readByte();
} while (lab != 0xff);
//Check if input file head is numass data file
return file;
}
private String readHead() throws IOException {
byte[] bytes = new byte[2048];
stream.read(bytes);
return new String(bytes);
}
private RawNMPoint readPoint(int head, LocalDateTime filedate) throws IOException {
int[] rx;
int voltage;
short time_out;
double timeDiv = 0;
boolean phoneFlag;
RawNMPoint point = new RawNMPoint();
int lab = head;
//point head
if (lab != 0x0f) {
//Ожидается, что это голова точки
throw new IOException("Point head expected");
}
rx = readBlock(32);
voltage = rx[2] + 256 * rx[3];
voltage = 65536 * voltage + rx[0] + 256 * rx[1];
time_out = (short) (rx[6] + 256 * rx[7]);
phoneFlag = (rx[19] != 0);
switch (time_out) {
case 5:
case 10:
timeDiv = 2e7;
break;
case 15:
case 20:
timeDiv = 1e7;
break;
case 50:
timeDiv = 5e6;
break;
case 100:
timeDiv = 2.5e6;
break;
case 200:
timeDiv = 1.25e6;
break;
default:
throw new IOException("Unknown time divider in input data");
}
if (phoneFlag) {
timeDiv /= 20.0;
time_out *= 20;
}
lab = readByte();
while (lab == 0xBF) {
skip(4);//badHV
lab = readByte();
}
do {
point.putEvent(readEvent(lab, timeDiv));
lab = readByte();
} while (lab != 0xAF);
//point end
skip(37);
int hours = readByte();
int minutes = readByte();
LocalDateTime absoluteTime = filedate.withHour(hours).withMinute(minutes);
//проверяем, не проскочили ли мы полночь
if (absoluteTime.isBefore(filedate)) {
absoluteTime = absoluteTime.plusDays(1);
}
point.setAbsouteTime(absoluteTime);
rx = readBlock(4);
int Uread = rx[2] + 256 * rx[3];
Uread = 65536 * Uread + rx[0] + 256 * rx[1];
skip(21);
point.setLength(time_out);
point.setUread(Uread / 10d / HVdev);
if (config.getBoolean("noUset", false)) {
point.setUset(Uread / 10d / HVdev);
} else {
point.setUset(voltage / 10d);
}
return point;
}
private long readTime() throws IOException {
int[] rx = readBlock(4);
long time = rx[0] + 256 * rx[1] + 65536 * rx[2] + 256 * 65536 * rx[3];
return time;
}
private void skip(int length) throws IOException {
long n = stream.skip(length);
if (n != length) {
stream.skip(length - n);
}
}
}
/*
PROGRAM DAT2PAW;
{$N+}
{$D Copyright (C) 1996 by S.V.Zadorozhny, INR RAS}
Uses Dos, Crt;
CONST
Rec_Len = 32768; { Buffer size }
TYPE
Dim = ARRAY [1..Rec_Len] OF Byte; { Read / Write Buffer }
VAR
DATA : WORD;
TIME : LONGINT;
TD : Double;
i, j, k : WORD;
Voltage, li, CN : LONGINT;
St, St1 : String;
f : File;
txt : Text;
Buf : ^Dim;
Buf_point : Word;
err : INTEGER;
Monitor, Pressure : WORD;
paths : PathStr;
dirs : DirStr;
nams : NameStr;
exts : ExtStr;
name, mask : String;
sr : SearchRec;
rx : Array [1..64] OF Byte;
lab, bt : Byte;
time_out : Word;
hb : Word;
{Gate_L, Gate_H : Word;}
TimDiv : Double;
Phone_Flag, OK : Boolean;
live : word;
(*----------------------------- PROCEDURES ----------------------------------*)
PROCEDURE NextChar;
BEGIN
CASE (live) OF
0 : BEGIN
Write('|');
Inc(live);
END;
1 : BEGIN
Write(#8'/');
Inc(live);
END;
2 : BEGIN
Write(#8'--');
Inc(live);
END;
3 : BEGIN
Write(#8#8'\ ');
Inc(live);
END;
4 : BEGIN
Write(#8#8'|');
live := 1;
END;
END;
END;
PROCEDURE ReadB(VAR bt : BYTE);
VAR fact : INTEGER;
BEGIN
IF Buf_point = 0 THEN
BEGIN
BlockRead(f,Buf^,Rec_Len,fact);
NextChar;
END;
Inc(Buf_point);
bt := Buf^[Buf_point];
IF Buf_point = Rec_Len THEN Buf_point:=0;
END { ReadB };
PROCEDURE SaveTXT;
BEGIN
Writeln(txt, CN, #9, TD:10:5, #9, DATA, #9, time_out, #9, (voltage/10):7:1);
END;
PROCEDURE ReadFile;
BEGIN
Assign(f,name);
{$I-}
Reset(f,1);
{$I+}
IF (IOResult <> 0) THEN
BEGIN
Writeln('Can''t open data file ', name);
Halt(3);
END;
BlockRead(f,Buf^,2048,i); {Skip First Block}
Buf_point := 0;
IF ((Buf^[1] <> Ord('N'))OR(Buf^[2] <> Ord('M'))) THEN
BEGIN
Close(f);
Writeln('File ', name, ' is not a data file !');
Exit;
END;
Write('File : ',name, ' ');
paths := name;
Fsplit(paths, dirs, nams, exts);
Assign(txt, nams + '.paw');
Rewrite(txt);
live := 0;
CN := 0;
REPEAT
ReadB(lab);
hb := lab AND $0F; { High data byte }
lab := lab AND $F0;
CASE (lab) OF
$00 : { New Point }
BEGIN
FOR i:=1 TO 32 DO ReadB(rx[i]);
Voltage := rx[3] + 256 * Word(rx[4]);
Voltage := 65536 * Voltage + rx[1] + 256 * Longint(rx[2]);
time_out := rx[7] + 256 * Word(rx[8]);
{pressure := rx[11] + 256 * Word(rx[12]);}
{Chan := rx[19];}
IF (rx[20] <> 0) THEN Phone_Flag := TRUE ELSE Phone_Flag := FALSE;
CASE (time_out) OF
5, 10 : TimDiv := 20000000.0;
15, 20 : TimDiv := 10000000.0;
50 : TimDiv := 5000000.0;
100 : TimDiv := 2500000.0;
200 : TimDiv := 1250000.0;
END;
IF (Phone_Flag) THEN
BEGIN
TimDiv := TimDiv / 20.0;
time_out := time_out * 20;
END;
END;
$10 : { Event, all present }
BEGIN
FOR i:=1 TO 5 DO ReadB(rx[i]);
TIME := rx[2] + 256 * Longint(rx[3])
+ 65536 * Longint(rx[4])+ 256 * 65536 * Longint(rx[5]);
TD := TIME / TimDiv;
DATA := rx[1] + 256 * hb;
Inc(CN);
SaveTXT;
END;
$20 : { Event, time only }
BEGIN
FOR i:=1 TO 4 DO ReadB(rx[i]);
TIME := rx[1] + 256 * Longint(rx[2])
+ 65536 * Longint(rx[3])+ 256 * 65536 * Longint(rx[4]);
TD := TIME / TimDiv;
DATA := 0;
Inc(CN);
SaveTXT;
END;
$40 : { Event, code only }
BEGIN
ReadB(rx[1]);
DATA := rx[1] + 256 * hb;
TD := 0.0;
Inc(CN);
SaveTXT;
END;
$80 : { Event, nothing }
BEGIN
DATA := 0;
TD := 0.0;
Inc(CN);
SaveTXT;
END;
$B0 : { Bad HV }
BEGIN
FOR i:=1 TO 4 DO ReadB(rx[i]);
END;
$A0 : { End of the point }
BEGIN
FOR i := 1 TO 64 DO ReadB(rx[i]);
END;
END;
UNTIL (lab=$F0);
Close(f);
Close(txt);
Writeln(#8#8' ');
END;
PROCEDURE ReadDataFiles;
BEGIN
mask := ParamStr(1);
FindFirst(mask, anyfile, sr);
WHILE (DosError = 0) DO
BEGIN
name := sr.Name;
ReadFile;
FindNext(sr);
END
END;
(*--------------------------- Main ------------------------------------------*)
BEGIN
ClrScr;
Writeln('TROITSK V-MASS EXPERIMENT DATA FILE -> TEXT FILE CONVERTER');
Writeln('WRITTEN BY S.V.ZADOROZHNY');
Writeln;
IF (ParamCount <> 1) THEN
BEGIN
Writeln('Usage : dat2paw <mask.dat>');
Writeln;
Writeln('--- Press any key to continue ---');
ReadKey;
Halt(1);
END;
New(Buf);
ReadDataFiles;
Writeln;
Writeln('O.K.');
Dispose(Buf);
END. {-- Main --}
*/

View File

@ -0,0 +1,60 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Locale;
import java.util.Scanner;
/**
*
* @author Darksnake
*/
public class NumassPawReader {
public RawNMFile readPaw(InputStream stream, String name){
Locale.setDefault(Locale.US);
BufferedInputStream bs = new BufferedInputStream(stream);
return readPaw(new Scanner(bs), name);
}
public RawNMFile readPaw(String filePath) throws FileNotFoundException{
FileInputStream fs = new FileInputStream(filePath);
return readPaw(fs, filePath);
}
private RawNMFile readPaw(Scanner s, String fileName) {
RawNMFile result = new RawNMFile(fileName);
while (s.hasNext()) {
long eventNum = s.nextLong();
double time = s.nextDouble();
short chanel = s.nextShort();
short timeTotal = s.nextShort();
double U = s.nextDouble();
// NumassEvent event = new NumassEvent(chanel, time);
result.putEvent(U, chanel, time);
}
return result;
}
}

View File

@ -0,0 +1,132 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data;
import hep.dataforge.content.AbstractContent;
import java.io.BufferedOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
* Contains the whole data but requires a lot of memory
* @author Darksnake
*/
public class RawNMFile extends AbstractContent {
// public static String TYPE = ":data:numassdatafile";
private final List<RawNMPoint> points;
private String head;
public void setHead(String head) {
this.head = head;
}
public String getHead() {
return head;
}
public RawNMFile(String fileName) {
super(fileName);
this.points = new ArrayList<>();
}
public void generatePAW(OutputStream stream) {
PrintWriter writer = new PrintWriter(new BufferedOutputStream(stream));
long counter = 0;
for (RawNMPoint point : this.getData()) {
double U = point.getUread();
for (NMEvent event : point.getEvents()) {
counter++;
writer.printf("%d\t%f\t%d\t%.1f\t%.2f%n", counter, event.getTime(), event.getChanel(), point.getLength(), U);
}
}
writer.flush();
}
/**
* merge of all point with given Uset
* @param U
* @return
*/
public RawNMPoint getByUset(double U) {
RawNMPoint res = null;
for (RawNMPoint point : points) {
if (point.getUset() == U) {
if (res == null) {
res = point.clone();
} else {
res = res.merge(point);
}
}
}
return res;
}
/**
* merge of all point with given Uread
* @param U
* @return
*/
public RawNMPoint getByUread(double U) {
RawNMPoint res = null;
for (RawNMPoint point : points) {
if (point.getUread()== U) {
if (res == null) {
res = point.clone();
} else {
res = res.merge(point);
}
}
}
return res;
}
/**
* @return the data
*/
public List<RawNMPoint> getData() {
return points;
}
void putEvent(double U, short chanel, double time) {
for (RawNMPoint point : this.getData()) {
if (U == point.getUread()) {
point.putEvent(new NMEvent(chanel, time));
return;
}
}
RawNMPoint newpoint = new RawNMPoint();
newpoint.putEvent(new NMEvent(chanel, time));
this.putPoint(newpoint);
}
public void putPoint(RawNMPoint point) {
points.add(point);
}
public int size() {
return this.points.size();
}
}

View File

@ -0,0 +1,181 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package inr.numass.data;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* Хранит информацию о спектре точки, но не об отдельных событиях.
*
* @author Darksnake
*/
public class RawNMPoint implements Cloneable {
public static int MAX_CHANEL = 4095;
private LocalDateTime absouteTime;
private final List<NMEvent> events;
private double t;
private double uread;
private double uset;
public RawNMPoint(double U, List<NMEvent> events, double t) {
this.uset = U;
this.uread = U;
this.events = events;
this.t = t;
}
public RawNMPoint(double Uset, double Uread, List<NMEvent> events, double t) {
this.uset = Uset;
this.uread = Uread;
this.events = events;
this.t = t;
}
public RawNMPoint(double uset, double uread, List<NMEvent> events, double t, LocalDateTime absouteTime) {
this.uset = uset;
this.uread = uread;
this.t = t;
this.absouteTime = absouteTime;
this.events = events;
}
RawNMPoint() {
events = new ArrayList<>();
uset = 0;
uread = 0;
t = Double.NaN;
}
@Override
public RawNMPoint clone() {
ArrayList<NMEvent> newevents = new ArrayList<>();
for (NMEvent event : this.getEvents()) {
newevents.add(event.clone());
}
return new RawNMPoint(getUset(), getUread(), newevents, getLength());
}
public LocalDateTime getAbsouteTime() {
return absouteTime;
}
public double getCR() {
return getEventsCount() / getLength();
}
public double getCRError() {
return Math.sqrt(getEventsCount()) / getLength();
}
/**
* @return the events
*/
public List<NMEvent> getEvents() {
return events;
}
public long getEventsCount() {
return events.size();
}
/**
* Measurement time
* @return the tset
*/
public double getLength() {
if (Double.isNaN(t)) {
throw new Error();
}
return t;
}
/**
* @return the Uread
*/
public double getUread() {
if (uread <= 0) {
return getUset();
} else {
return uread;
}
}
/**
* @return the Uset
*/
public double getUset() {
if (uset < 0) {
throw new IllegalStateException();
}
return uset;
}
public RawNMPoint merge(RawNMPoint point) {
RawNMPoint res = this.clone();
for (NMEvent newEvent : point.getEvents()) {
res.putEvent(new NMEvent(newEvent.getChanel(), newEvent.getTime() + this.getLength()));
}
res.t += point.getLength();
res.uread = (this.uread + point.uread) / 2;
return res;
}
void putEvent(NMEvent event) {
events.add(event);
}
public RawNMPoint selectChanels(int from, int to) {
assert to > from;
List<NMEvent> res = new ArrayList<>();
for (NMEvent event : this.getEvents()) {
if ((event.getChanel() >= from) && (event.getChanel() <= to)) {
res.add(event);
}
}
return new RawNMPoint(getUset(), getUread(), res, getLength());
}
void setAbsouteTime(LocalDateTime absouteTime) {
this.absouteTime = absouteTime;
}
/**
* @param tset the tset to set
*/
void setLength(double tset) {
this.t = tset;
}
/**
* @param Uread the Uread to set
*/
void setUread(double Uread) {
assert Uread >= 0;
this.uread = Uread;
}
/**
* @param Uset the Uset to set
*/
void setUset(double Uset) {
this.uset = Uset;
}
}

Some files were not shown because too many files have changed in this diff Show More