Fixed tests. Moved unsupported modules out of project

This commit is contained in:
Alexander Nozik 2016-05-29 19:44:02 +03:00
parent 57a9e9b465
commit 3cbc3e9aee
25 changed files with 5 additions and 2357 deletions

View File

@ -1,17 +0,0 @@
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

@ -1,85 +0,0 @@
/*
* 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.StorageManager;
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 StorageManager().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

@ -1,418 +0,0 @@
/*
* 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.context.Context;
import hep.dataforge.control.collectors.RegularPointCollector;
import hep.dataforge.control.measurements.DataDevice;
import hep.dataforge.control.ports.PortHandler;
import hep.dataforge.control.ports.TcpPortHandler;
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.names.Named;
import hep.dataforge.storage.api.PointLoader;
import hep.dataforge.storage.api.Storage;
import hep.dataforge.storage.commons.LoaderFactory;
import hep.dataforge.tables.TableTableFormatBuilder;
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
TableTableFormatBuilder TableFormatBuilder = new TableTableFormatBuilder()
.addTime("timestamp");
List<String> names = new ArrayList<>();
for (PKT8Channel channel : this.channels.values()) {
TableFormatBuilder.addNumber(channel.getName());
names.add(channel.getName());
}
this.pointLoader = LoaderFactory.buildPointLoder(storage, "cryotemp_" + suffix, "", "timestamp", TableFormatBuilder.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

@ -1,276 +0,0 @@
/*
* 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.measurements.MeasurementDevice;
import hep.dataforge.control.measurements.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).display(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

@ -1,87 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package inr.numass.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

@ -1,14 +0,0 @@
<?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

@ -1,46 +0,0 @@
<?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

@ -1,6 +0,0 @@
description = "Numass add-on for proportional counters"
dependencies{
compile project(':numass-main')
}

View File

@ -1,46 +0,0 @@
<?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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>inr.numass</groupId>
<artifactId>numass-prop</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>numass-main</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>

View File

@ -1,165 +0,0 @@
/*
* 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.prop;
import hep.dataforge.functions.AbstractParametricFunction;
import hep.dataforge.functions.ParametricFunction;
import hep.dataforge.maths.NamedDoubleSet;
import hep.dataforge.maths.integration.UnivariateIntegrator;
import hep.dataforge.names.AbstractNamedSet;
import static hep.dataforge.names.NamedUtils.combineNamesWithEquals;
import inr.numass.NumassContext;
import inr.numass.models.RangedNamedSetSpectrum;
import inr.numass.models.Transmission;
import static java.lang.Double.isNaN;
import java.util.Arrays;
import org.apache.commons.math3.analysis.UnivariateFunction;
/**
*
* @author Darksnake
*/
public abstract class AbstractTransmission extends AbstractNamedSet implements Transmission {
protected final UnivariateIntegrator integrator = NumassContext.defaultIntegrator;
// private final UnivariateIntegrator integrator = new SimpsonIntegrator(1e-2, Double.MAX_VALUE, 3, 64);
public AbstractTransmission(String[] list) {
super(list);
}
@Override
public ParametricFunction getConvolutedSpectrum(final RangedNamedSetSpectrum bare) {
return new AbstractParametricFunction(combineNamesWithEquals(this.namesAsArray(), bare.namesAsArray())) {
// int maxEval = GlobalContext.getPreferences().getInt("INTEGR_POINTS", 1000);
@Override
public double derivValue(String parName, double out, NamedDoubleSet set) {
return integrate(getDerivProduct(parName, bare, set, out), getBorders(set, out));
}
@Override
public boolean providesDeriv(String name) {
return this.names().contains(name) || bare.providesDeriv(name);
}
@Override
public double value(double out, NamedDoubleSet set) {
return integrate(getProduct(bare, set, out), getBorders(set, out));
}
};
}
/**
* Provides borders for integration. the number of borders must be >= 2
* @param pars
* @param out
* @return
*/
protected abstract double[] getBorders(NamedDoubleSet pars, double out);
/**
* Интегрирует функцию по кускам. Переданный масив должен содержать не
* меньше двух значений
*
* @param func
* @param borders
* @return
*/
protected double integrate(UnivariateFunction func, double[] borders) {
if (borders.length < 2) {
throw new IllegalArgumentException();
}
double res = 0;
Arrays.sort(borders);
for (int i = 0; i < borders.length - 1; i++) {
if (borders[i + 1] > borders[i]) {
res += integrator.integrate(func, borders[i], borders[i + 1]);
}
}
return res;
}
UnivariateFunction getDerivProduct(final String name, final ParametricFunction bare, final NamedDoubleSet pars, final double out) {
return (double in) -> {
double res1;
double res2;
res1 = bare.derivValue(name, in, pars) * getValue(pars, in, out);
res2 = bare.value(in, pars) * getDeriv(name, pars, in, out);
return res1 + res2;
};
}
UnivariateFunction getProduct(final ParametricFunction bare, final NamedDoubleSet pars, final double out) {
return (double in) -> {
double res = bare.value(in, pars) * getValue(pars, in, out);
assert !isNaN(res);
return res;
};
}
public ParametricFunction getResponseFunction(final double in) {
return new AbstractParametricFunction(AbstractTransmission.this.names()) {
@Override
public double derivValue(String parName, double out, NamedDoubleSet set) {
return AbstractTransmission.this.getDeriv(parName, set, in, out);
}
@Override
public boolean providesDeriv(String name) {
return AbstractTransmission.this.providesDeriv(name);
}
@Override
public double value(double out, NamedDoubleSet set) {
return AbstractTransmission.this.getValue(set, in, out);
}
};
}
/**
* Функция отклика с дополнительным параметром. Никаких производных по этому
* параметру, разумеется нет.
*
* @param positionParameterName
* @return
*/
public ParametricFunction getResponseFunction(String positionParameterName) {
return new AbstractParametricFunction(AbstractTransmission.this.names()) {
@Override
public double derivValue(String parName, double out, NamedDoubleSet set) {
return AbstractTransmission.this.getDeriv(parName, set, set.getValue(positionParameterName), out);
}
@Override
public boolean providesDeriv(String name) {
return AbstractTransmission.this.providesDeriv(name) && !name.equals(positionParameterName);
}
@Override
public double value(double out, NamedDoubleSet set) {
return AbstractTransmission.this.getValue(set, set.getValue(positionParameterName), out);
}
};
}
}

View File

@ -1,62 +0,0 @@
/*
* 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.prop;
import hep.dataforge.maths.NamedDoubleSet;
import org.apache.commons.math3.special.Erf;
/**
* Нормированаая функция подложки разрешающей функции пропорционального счетчика
* @author Darksnake
*/
public class BaseFunction extends AbstractTransmission{
public BaseFunction() {
super(new String[0]);
}
@Override
protected double[] getBorders(NamedDoubleSet pars, double out) {
double[] res = new double[2];
res[0] = 0;
res[1] = out;
return res;
}
@Override
public double getValue(NamedDoubleSet set, double input, double output) {
// if(output >0 && input>0 && input > output){
// return 1/input;
// } else {
// return 0;
// }
double w = set.getValue("w")*Math.sqrt(input);
return 1/input * Erf.erfc((output-input)/w)/2d;
}
@Override
public double getDeriv(String name, NamedDoubleSet set, double input, double output) {
return 0;
}
@Override
public boolean providesDeriv(String name) {
return true;
}
}

View File

@ -1,32 +0,0 @@
/*
* 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.prop;
import hep.dataforge.datafitter.MINUITPlugin;
/**
*
*/
public class Main {
public static void main(String[] args) throws Exception {
PropContext context = new PropContext();
context.loadPlugin(new MINUITPlugin());
inr.numass.Main.run(context, args);
}
}

View File

@ -1,39 +0,0 @@
/*
* 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.prop;
import hep.dataforge.tables.DataPoint;
import hep.dataforge.tables.XYAdapter;
import hep.dataforge.exceptions.NameNotFoundException;
import hep.dataforge.values.Value;
/**
* Simple adapter for Poisson-distributed y values.
*
* @author Darksnake
*/
public class PoissonAdapter extends XYAdapter {
public PoissonAdapter(String xName, String yName) {
super(xName, yName);
}
@Override
public Value getYerr(DataPoint point) throws NameNotFoundException {
return Value.of(Math.sqrt(getY(point).doubleValue()));
}
}

View File

@ -1,53 +0,0 @@
/*
* 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.prop;
import hep.dataforge.actions.ActionManager;
import hep.dataforge.datafitter.FitPlugin;
import hep.dataforge.datafitter.models.XYModel;
import hep.dataforge.functions.ParametricFunction;
import inr.numass.NumassContext;
import inr.numass.models.NBkgSpectrum;
import inr.numass.prop.ar.FitJNAData;
import inr.numass.prop.ar.MergeJNADataAction;
import inr.numass.prop.ar.ReadJNADataAction;
/**
*
* @author Darksnake
*/
public class PropContext extends NumassContext {
public PropContext() {
super();
ActionManager actions = ActionManager.buildFrom(this);
actions.registerAction(ReadJNADataAction.class);
actions.registerAction(FitJNAData.class);
actions.registerAction(MergeJNADataAction.class);
super.provide("hep.dataforge:fitting",FitPlugin.class).getFitManager().getModelManager()
.addModel("prop-response", (context, an) -> {
PropResolution trans = new PropResolution(new BaseFunction());
ParametricFunction response = trans.getResponseFunction("pos");
NBkgSpectrum spectrum = new NBkgSpectrum(response);
XYModel model = new XYModel("prop-response", spectrum, new PoissonAdapter(null, null));
return model;
});
}
}

View File

@ -1,143 +0,0 @@
/*
* 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.prop;
import hep.dataforge.exceptions.NotDefinedException;
import hep.dataforge.maths.NamedDoubleSet;
import hep.dataforge.names.NamedUtils;
import inr.numass.models.Transmission;
import static java.lang.Math.abs;
import static java.lang.Math.exp;
import static java.lang.Math.sqrt;
/**
*
* @author Darksnake
*/
public class PropResolution extends AbstractTransmission {
private static final String[] list = {"w", "dw", "base"};
private final double cutoff = 6d;
private final Transmission base;
public PropResolution(Transmission base) {
super(NamedUtils.combineNamesWithEquals(list, base.names().asArray()));
this.base = base;
}
/**
* @return the base
*/
public Transmission getBase() {
return base;
}
// private double getPos(NamedDoubleSet pars) {
// return pars.getValue("pos");
// }
private double getW(NamedDoubleSet pars, double Ebeta) {
return pars.getValue("w")*Math.sqrt(Ebeta);
}
private double getdW(NamedDoubleSet pars) {
if (pars.names().contains("dw")) {
return pars.getValue("dw");
} else {
return 0;
}
}
private double getBase(NamedDoubleSet pars) {
if (pars.names().contains("base")) {
return pars.getValue("base");
} else {
return 0;
}
}
@Override
public boolean providesDeriv(String name) {
return false;
}
/**
*
* @param Ebeta - начальная энергия электрона, полученная в результате
* бета-распада
* @param Ef - конечная энергия электрона, как она зарегистрирована прибором
* @param pars - параметры
* @return - вероятность получить такую конечную энергию при такой начальной
*/
@Override
public double getValue(NamedDoubleSet pars, double Ebeta, double Ef) {
double res = 0;
double baseValue = getBase().getValue(pars, Ebeta, Ef);
double w = getW(pars, Ebeta);
if (abs(Ef - Ebeta) <= cutoff * w) {
double aux;
if (Ef > Ebeta) {
aux = (Ef - Ebeta) / (w*(1+getdW(pars)));
} else {
aux = (Ef - Ebeta) / (w*(1-getdW(pars)));
}
res = exp(-aux * aux / 2) / w / sqrt(2 * Math.PI);
}
return res * (1 - getBase(pars)) + getBase(pars)*baseValue;
}
@Override
public double getDeriv(String name, NamedDoubleSet pars, double Ebeta, double Ef) {
double w = getW(pars, Ebeta);
if (abs(Ef - Ebeta) > cutoff * w) {
return 0;
}
double res;
switch (name) {
case "pos":
res = this.getValue(pars, Ebeta, Ef) * (Ef - Ebeta) / w / w * (1 - getBase(pars));
break;
case "w":
res = this.getValue(pars, Ebeta, Ef) * ((Ef - Ebeta) * (Ef - Ebeta) / w / w / w - 1 / w) * (1 - getBase(pars));
break;
case "dw":
throw new NotDefinedException();
// case "base":
// return 1 / getPos(pars) - this.value(E, pars) * (E - getPos(pars)) / getW(pars) / getW(pars);
case "base":
return getBase().getValue(pars, Ebeta, Ef) - getValue(pars, Ebeta, Ef);
default:
res = 0;
}
return res;
}
@Override
protected double[] getBorders(NamedDoubleSet pars, double out) {
double[] res = new double[3];
res[0] = 0;
res[1] = Math.max(out - cutoff*getW(pars, out),0);
res[2] = out + cutoff*getW(pars, out);
return res;
}
}

View File

@ -1,93 +0,0 @@
/*
* 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.prop;
import hep.dataforge.context.GlobalContext;
import static hep.dataforge.context.GlobalContext.out;
import hep.dataforge.datafitter.FitManager;
import hep.dataforge.datafitter.FitState;
import hep.dataforge.datafitter.ParamSet;
import hep.dataforge.datafitter.models.HistogramGenerator;
import hep.dataforge.datafitter.models.HistogramModel;
import hep.dataforge.functions.ParametricFunction;
import hep.dataforge.maths.MatrixOperations;
import hep.dataforge.maths.RandomUtils;
import hep.dataforge.tables.DataPoint;
import hep.dataforge.tables.Table;
import inr.numass.models.BetaSpectrum;
import inr.numass.models.NBkgSpectrum;
import java.io.FileNotFoundException;
/**
* Hello world!
*
*/
public class PropTest {
public static void main(String[] args) throws FileNotFoundException {
FitManager fm = new FitManager();
RandomUtils.setSeed(138);
GlobalContext.instance().putValue(MatrixOperations.MATRIX_SINGULARITY_THRESHOLD, 1e-80);
BetaSpectrum bareBeta = new BetaSpectrum();
PropResolution trans = new PropResolution(new BaseFunction());
ParametricFunction convolutedBeta = trans.getConvolutedSpectrum(bareBeta);
NBkgSpectrum spectrum = new NBkgSpectrum(convolutedBeta);
// XYModel model = new XYModel("tritium", spectrum);
HistogramModel model = new HistogramModel("tritium-prop", spectrum);
ParamSet allPars = new ParamSet(model.namesAsArray());
allPars.setPar("N", 1e8, 1e3, 0d, Double.POSITIVE_INFINITY)
.setPar("bkg", 1, 1e-4)
.setPar("E0", 18575d, 5)
.setPar("mnu2", 0d, 1d)
.setPar("msterile2", 6.4e7, 1e2)
.setPar("U2", 0, 1e-3)
.setPar("w", 5.5, 5e-3)
.setPar("dw", 1e-2, 1e-3)
.setPar("base", 0.05, 0.1);
// NamedSpectrum response = trans.getResponseFunction(2700d);
//
// pm.plotFunction(FunctionUtils.getSpectrumFunction(response, allPars), 100, 4000, 400);
// pm.plotFunction(FunctionUtils.getSpectrumFunction(spectrum, allPars), 100, 19000, 400);
//pm.plotFunction(trans.getProduct(bareBeta, allPars, 9000d), 1000d, 19000d, 400);
// pm.plotFunction(FunctionUtils.fix1stArgument(trans.getBivariateFunction(allPars), 14000d), 1000, 18000, 400);
HistogramGenerator generator = new HistogramGenerator(null, model, allPars);
Table data = generator.generateUniformHistogram(1000d, 18500d, 350);
long count = 0;
for (DataPoint dp : data) {
count += dp.getValue("count").longValue();
}
out().printf("The total number of events is %g%n", (double) count);
// allPars.setParValue("base", 1e-3);
// allPars.setParValue("w", 5.470);
allPars.setParValue("dw", 2e-2);
FitState state = new FitState(data, model, allPars);
FitState res = fm.runDefaultTask(state, "U2", "E0", "N");
res.print(out());
// log.print(out());
}
}

View File

@ -1,61 +0,0 @@
/*
* 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.prop;
import hep.dataforge.exceptions.NotDefinedException;
import hep.dataforge.functions.AbstractParametricFunction;
import hep.dataforge.maths.NamedDoubleSet;
/**
*
* @author Darksnake
*/
public class SplitNormalSpectrum extends AbstractParametricFunction {
private static final String[] list = {"amp", "pos", "sigma", "dsigma"};
public SplitNormalSpectrum() {
super(list);
}
@Override
public double derivValue(String parName, double x, NamedDoubleSet set) {
throw new NotDefinedException();
}
@Override
public boolean providesDeriv(String name) {
return false;
}
@Override
public double value(double x, NamedDoubleSet set) {
double amp = set.getValue("amp");
double pos = set.getValue("pos");
double sigma = set.getValue("sigma");
double dsigma = set.getValue("dsigma");
double t;
if (x <= pos) {
t = (x - pos) / (sigma - dsigma * sigma);
} else {
t = (x - pos) / (sigma + dsigma * sigma);
}
return amp / Math.sqrt(2 * Math.PI) / sigma * Math.exp(-t * t / 2);
}
}

View File

@ -1,133 +0,0 @@
/*
* 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.prop.ar;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.context.Context;
import hep.dataforge.tables.DataPoint;
import hep.dataforge.tables.ListTable;
import hep.dataforge.tables.MapPoint;
import hep.dataforge.datafitter.FitManager;
import hep.dataforge.datafitter.FitPlugin;
import hep.dataforge.datafitter.FitState;
import hep.dataforge.datafitter.ParamSet;
import hep.dataforge.datafitter.models.Model;
import hep.dataforge.datafitter.models.XYModel;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.description.ValueDef;
import hep.dataforge.io.ColumnedDataWriter;
import hep.dataforge.io.log.Log;
import hep.dataforge.io.log.Logable;
import hep.dataforge.meta.Meta;
import inr.numass.prop.PoissonAdapter;
import inr.numass.prop.SplitNormalSpectrum;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import hep.dataforge.tables.Table;
/**
*
* @author Darksnake
*/
@TypedActionDef(name = "fitJNA", inputType = JNAEpisode.class, outputType = Table.class, description = "Fit JNA data by apropriate model")
@ValueDef(name = "saveResult", type = "BOOLEAN", def = "true", info = "Save the results of action to a file")
@ValueDef(name = "suffix", def = "", info = "Suffix for saved file")
@ValueDef(name = "loFitChanel", type = "NUMBER", def = "600", info = "Lo chanel to filter data for fit")
@ValueDef(name = "upFitChanel", type = "NUMBER", def = "1100", info = "Up chanel to filter data for fit")
public class FitJNAData extends OneToOneAction<JNAEpisode, Table> {
private final FitManager fm;
public FitJNAData(Context context, Meta annotation) {
super(context, annotation);
if (context.provides("hep.dataforge:fitting")) {
this.fm = context.provide("hep.dataforge:fitting", FitPlugin.class).getFitManager();
} else {
this.fm = new FitManager(context);
}
}
@Override
protected Table execute(Logable log, Meta meta, JNAEpisode input){
List<DataPoint> res = new ArrayList<>(input.size());
Model model = buildModel();
for (JNASpectrum spectrum : input) {
Log fitLog = new Log("fit", log);
FitState state = fit(fitLog, spectrum, model);
ParamSet pars = state.getParameters();
double pos = pars.getValue("pos");
double posErr = pars.getError("pos");
double amp = pars.getValue("amp");
double ampErr = pars.getError("amp");
double sigma = pars.getValue("sigma");
double sigmaErr = pars.getError("sigma");
double dsigma = pars.getValue("dsigma");
double dsigmaErr = pars.getError("dsigma");
double chi2 = state.getChi2() / (state.getDataSize() - 4);
MapPoint point = new MapPoint(
new String[]{"name", "time", "pos", "posErr", "amp", "ampErr", "sigma", "sigmaErr", "dsigma", "dsigmaErr", "chi2"},
new Object[]{spectrum.getName(), spectrum.startTime(), pos, posErr, amp, ampErr, sigma, sigmaErr, dsigma, dsigmaErr, chi2});
if (spectrum.hasTemperature()) {
point = point.join(spectrum.getTemperatures());
}
res.add(point);
}
Table data = new ListTable(input.getName(), input.meta(), res);
if (meta.getBoolean("saveResult")) {
String suffix = meta.getString("suffix");
OutputStream out = getContext().io().out(getName(), input.getName() + suffix);
ColumnedDataWriter.writeDataSet(out, data, "***RESULT***");
}
return data;
}
public FitState fit(Logable log, JNASpectrum spectrum, Model model) {
Meta reader = readMeta(spectrum.meta());
double lowerChanel = reader.getDouble("loFitChanel");
double upperChanel = reader.getDouble("upFitChanel");
Table data = spectrum.asDataSet().filter("chanel", lowerChanel, upperChanel);
ParamSet params = new ParamSet()
.setPar("amp", 2e5, 1e3)
.setPar("pos", 800d, 1d)
.setPar("sigma", 100d, 1d)
.setPar("dsigma", 0d, 1e-1);
params.updateFrom(ParamSet.fromAnnotation(meta()));//Updating parameters forma action meta
params.updateFrom(ParamSet.fromAnnotation(spectrum.meta()));//Updating parameters from content meta
FitState state = new FitState(data, model, params);
// return fm.runDefaultTask(state, log);
return fm.runTask(state, "MINUIT", "fit", log);
}
private Model buildModel() {
return new XYModel("split-normal", new SplitNormalSpectrum(), new PoissonAdapter("chanel", "count"));
}
}

View File

@ -1,55 +0,0 @@
/*
* 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.prop.ar;
import hep.dataforge.names.NamedMetaHolder;
import hep.dataforge.meta.Meta;
import java.util.Iterator;
import java.util.List;
/**
* An episode of JNA measurements
*
* @author Darksnake
*/
public class JNAEpisode extends NamedMetaHolder implements Iterable<JNASpectrum> {
private final List<JNASpectrum> spectra;
public JNAEpisode(String name, List<JNASpectrum> spectra) {
super(name);
this.spectra = spectra;
}
public JNAEpisode(String name, Meta annotation, List<JNASpectrum> spectra) {
super(name, annotation);
this.spectra = spectra;
}
@Override
public Iterator<JNASpectrum> iterator() {
return spectra.iterator();
}
public JNASpectrum get(int i) {
return spectra.get(i);
}
public int size() {
return spectra.size();
}
}

View File

@ -1,140 +0,0 @@
/*
* 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.prop.ar;
import hep.dataforge.names.NamedMetaHolder;
import hep.dataforge.tables.DataPoint;
import hep.dataforge.tables.ListTable;
import hep.dataforge.tables.MapPoint;
import hep.dataforge.description.NodeDef;
import hep.dataforge.description.ValueDef;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import hep.dataforge.tables.Table;
/**
*
* @author Darksnake
*/
@NodeDef(name = "temperature", info = "The temperature measurements data for this spectrum.")
@ValueDef(name = "relativeStartTime", type = "NUMBER", info = "Start time in days relative to some starting point.")
@ValueDef(name = "relativeStopTime", type = "NUMBER", info = "Stop time in days relative to some starting point.")
public class JNASpectrum extends NamedMetaHolder {
public static String[] names = {"chanel", "count"};
private LinkedHashMap<Double, Long> spectrum;
public JNASpectrum(String name, Meta annotation, Map<Double, Long> spectrum) {
super(name, annotation);
this.spectrum = new LinkedHashMap<>(spectrum);
}
public JNASpectrum(String name, Meta annotation, double[] x, long[] y) {
super(name, annotation);
if (x.length != y.length) {
throw new IllegalArgumentException();
}
this.spectrum = new LinkedHashMap<>(x.length);
for (int i = 0; i < x.length; i++) {
spectrum.put(x[i], y[i]);
}
}
public Table asDataSet() {
List<DataPoint> points = new ArrayList<>();
for (Map.Entry<Double, Long> point : spectrum.entrySet()) {
points.add(new MapPoint(names, point.getKey(), point.getValue()));
}
return new ListTable(getName(), meta(), points);
}
public Map<Double, Long> asMap() {
return Collections.unmodifiableMap(spectrum);
}
public double startTime() {
return meta().getDouble("relativeStartTime");
}
public double stopTime() {
return meta().getDouble("relativeStopTime");
}
public double length(){
return stopTime() - startTime();
}
public boolean hasTemperature() {
return this.meta().hasNode("temperature");
}
public DataPoint getTemperatures() {
if (!hasTemperature()) {
throw new IllegalStateException("temperature are not present");
} else {
// double T1 = getDouble("temperature.T1",0);
// double T2 = getDouble("temperature.T2",0);
// double T3 = getDouble("temperature.T3",0);
// double T4 = getDouble("temperature.T4",0);
// double T5 = getDouble("temperature.T5",0);
// double T6 = getDouble("temperature.T6",0);
MapPoint res = new MapPoint();
Meta temps = meta().getNode("temperature");
for (String name : temps.getValueNames()) {
res.putValue(name, temps.getValue(name));
}
return res;
}
}
public JNASpectrum mergeWith(String name, JNASpectrum sp){
LinkedHashMap<Double, Long> points = new LinkedHashMap<>();
for (Map.Entry<Double, Long> entry : this.spectrum.entrySet()) {
points.put(entry.getKey(), entry.getValue() + sp.spectrum.get(entry.getKey()));
}
MetaBuilder temperatures = new MetaBuilder("temperature");
if(this.hasTemperature() && sp.hasTemperature()){
DataPoint temps1 = this.getTemperatures();
DataPoint temps2 = sp.getTemperatures();
for(String tName: temps1.namesAsArray()){
temperatures.putValue(tName, (temps1.getDouble(tName)*this.length() + temps2.getDouble(tName)*sp.length())/(this.length() + sp.length()));
}
}
MetaBuilder an = new MetaBuilder("")
.putValue("relativeStartTime", Math.min(this.startTime(), sp.startTime()))
.putValue("relativeStopTime", Math.max(this.stopTime(), sp.stopTime()));
if(!temperatures.isEmpty()){
an.putNode(temperatures);
}
return new JNASpectrum(name, an.build(), points);
}
}

View File

@ -1,71 +0,0 @@
/*
* 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.prop.ar;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.context.Context;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.description.ValueDef;
import hep.dataforge.io.log.Logable;
import hep.dataforge.meta.Meta;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
*
* @author darksnake
*/
@TypedActionDef(name = "mergeJNA",inputType = JNAEpisode.class, outputType = JNAEpisode.class, description = "Couple some spectra together")
@ValueDef(name = "coupling", def = "2", type = "NUMBER", info = "If not 1, than spectra are coupled and merged together with given group size")
public class MergeJNADataAction extends OneToOneAction<JNAEpisode, JNAEpisode> {
public MergeJNADataAction(Context context, Meta annotation) {
super(context, annotation);
}
@Override
protected JNAEpisode execute(Logable log, Meta meta, JNAEpisode input){
List<JNASpectrum> res = new ArrayList<>();
int coupling = meta.getInt("coupling");
int counter = 0;
for (Iterator<JNASpectrum> iterator = input.iterator(); iterator.hasNext();) {
List<JNASpectrum> mergeList = new ArrayList<>();
for (int i = 0; i < coupling; i++) {
if (iterator.hasNext()) {
mergeList.add(iterator.next());
} else {
res.addAll(mergeList);
mergeList.clear();
}
}
if (!mergeList.isEmpty()) {
JNASpectrum spectrum = mergeList.get(0);
for (int i = 1; i < mergeList.size(); i++) {
spectrum = spectrum.mergeWith("merge_"+Integer.toString(counter), mergeList.get(i));
}
res.add(spectrum);
counter++;
}
}
return new JNAEpisode(input.getName(), input.meta(), res);
}
}

View File

@ -1,169 +0,0 @@
/*
* 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.prop.ar;
import hep.dataforge.actions.OneToOneAction;
import hep.dataforge.context.Context;
import hep.dataforge.tables.DataPoint;
import hep.dataforge.tables.FileData;
import hep.dataforge.description.TypedActionDef;
import hep.dataforge.description.ValueDef;
import hep.dataforge.exceptions.ContentException;
import hep.dataforge.io.ColumnedDataReader;
import hep.dataforge.io.IOUtils;
import hep.dataforge.io.log.Logable;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import hep.dataforge.tables.Table;
/**
*
* @author Darksnake
*/
@TypedActionDef(
name = "readJNA",
description = "Read data in the format provided by JNA",
inputType = FileData.class,
outputType = JNAEpisode.class
)
@ValueDef(name = "numBins", def = "820", type = "NUMBER", info = "Number of bins in the histogram")
@ValueDef(name = "loChanel", def = "0", type = "NUMBER", info = "Lower chanel")
@ValueDef(name = "upChanel", def = "4100", type = "NUMBER", info = "Upper chanel")
@ValueDef(name = "bkgChanel", def = "30", type = "NUMBER", info = "All chanels lower than the background are excluded from analisys")
@ValueDef(name = "temperatureFile", info = "The location of temperature data file")
@ValueDef(name = "timeFile", info = "The location of time data file")
public class ReadJNADataAction extends OneToOneAction<FileData, JNAEpisode> {
public ReadJNADataAction(Context context, Meta annotation) {
super(context, annotation);
}
@Override
protected JNAEpisode execute(Logable log, Meta reader, FileData input){
try {
InputStream stream = new BufferedInputStream(new FileInputStream(input.getInputFile()));
String timeFileName = reader.getString("timeFile", input.getInputFile().getName().replace("ar37", "tar37"));
File timeFile = IOUtils.getFile(input.getInputFile(), timeFileName);
Scanner timeScanner = new Scanner(timeFile);
String tempFileName = reader.getString("temperatureFile", "");
Table tempData = null;
if (!tempFileName.isEmpty()) {
String[] format = {"time", "T2", "T4", "T5", "T6"};
File tempFile = IOUtils.getFile(input.getInputFile(), tempFileName);
ColumnedDataReader fileReader = new ColumnedDataReader(tempFile, format);
tempData = fileReader.toDataSet(tempFileName);
}
List<JNASpectrum> spectra = new ArrayList<>();
int counter = 1;
while (timeScanner.hasNext()) {
log.log("reading spectrum number {}", counter);
double time = timeScanner.nextDouble();
Meta annotation = prepareAnnotation(input.meta(), time, time + 1d / 24d, tempData);
String spName = input.getName() + "_" + counter;
spectra.add(readSingleSpectrum(spName, annotation, stream));
counter++;
}
JNAEpisode res = new JNAEpisode(input.getName(), spectra);
//TODO configure list
return res;
} catch (FileNotFoundException ex) {
throw new ContentException("Can't open file " + input.getName());
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
private Meta prepareAnnotation(Meta parent, double startTime, double stopTime, Table tempData) {
MetaBuilder meta = parent.getBuilder();
meta.putValue("relativeStartTime", startTime);
meta.putValue("relativeStopTime", stopTime);
if (tempData != null) {
MetaBuilder tempBuilder = new MetaBuilder("temperature");
double t2 = 0;
double t4 = 0;
double t5 = 0;
double t6 = 0;
int counter = 0;
for (DataPoint dp : tempData) {
double time = dp.getDouble("time");
if (time >= startTime && time <= stopTime) {
counter++;
t2 += dp.getDouble("T2");
t4 += dp.getDouble("T4");
t5 += dp.getDouble("T5");
t6 += dp.getDouble("T6");
}
}
t2 /= counter;
t4 /= counter;
t5 /= counter;
t6 /= counter;
//TODO добавить ошибки температуры?
tempBuilder.putValue("T2", t2);
tempBuilder.putValue("T4", t4);
tempBuilder.putValue("T5", t5);
tempBuilder.putValue("T6", t6);
meta.putNode(tempBuilder);
}
return meta.build();
}
private JNASpectrum readSingleSpectrum(String name, Meta annotation, InputStream stream) throws IOException {
int numBins = getInt("numBins");
int loChanel = getInt("loChanel");
int upChanel = getInt("upChanel");
double binSize = ((double) (upChanel - loChanel)) / numBins;
Map<Double, Long> spectrum = new LinkedHashMap<>(numBins);
byte[] buffer = new byte[4];
for (int i = 0; i < numBins + 1; i++) {
Double binCenter = i * binSize + binSize / 2;
stream.read(buffer);
long count = (buffer[0] & 0xFF) | (buffer[1] & 0xFF) << 8 | (buffer[2] & 0xFF) << 16 | (buffer[3] & 0xFF) << 24;
if (binCenter > getDouble("bkgChanel")) {
spectrum.put(binCenter, count);
}
}
return new JNASpectrum(name, annotation, spectrum);
}
}

View File

@ -1,56 +0,0 @@
/*
* 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.prop;
import hep.dataforge.context.GlobalContext;
import hep.dataforge.tables.FileData;
import hep.dataforge.datafitter.MINUITPlugin;
import hep.dataforge.io.ColumnedDataWriter;
import hep.dataforge.meta.MetaBuilder;
import inr.numass.prop.ar.FitJNAData;
import inr.numass.prop.ar.JNAEpisode;
import inr.numass.prop.ar.ReadJNADataAction;
import java.io.File;
import java.io.FileNotFoundException;
import hep.dataforge.tables.Table;
/**
*
* @author Darksnake
*/
public class TestFit {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws FileNotFoundException, InterruptedException {
GlobalContext.instance().loadPlugin(new MINUITPlugin());
File sourceDir = new File("c:\\Users\\Darksnake\\Dropbox\\jna_data");
FileData file = new FileData(new File(sourceDir, "ar37e2.dat"));
file.setMeta(new MetaBuilder("meta")
.putValue("timeFile", "tar37e2.dat")
.putValue("temperatureFile", "e2temp.txt")
);
JNAEpisode spectra = new ReadJNADataAction(GlobalContext.instance(), null).runOne(file);
Table data = new FitJNAData(GlobalContext.instance(), null).runOne(spectra);
ColumnedDataWriter.writeDataSet(System.out, data, "***RESULT***");
}
}

View File

@ -1,88 +0,0 @@
/*
* 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.prop;
import hep.dataforge.context.GlobalContext;
import hep.dataforge.tables.FileData;
import hep.dataforge.tables.XYAdapter;
import hep.dataforge.meta.Meta;
import hep.dataforge.meta.MetaBuilder;
import hep.dataforge.plots.PlotFrame;
import hep.dataforge.plots.data.PlottableData;
import hep.dataforge.plots.fx.FXPlotUtils;
import inr.numass.prop.ar.JNAEpisode;
import inr.numass.prop.ar.JNASpectrum;
import inr.numass.prop.ar.ReadJNADataAction;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Map;
/**
*
* @author darksnake
*/
public class TestReader {
/**
* @param args the command line arguments
* @throws java.io.FileNotFoundException
* @throws java.lang.InterruptedException
*/
public static void main(String[] args) throws FileNotFoundException, InterruptedException {
// new MINUITModule().load();
FileData file = new FileData(new File("c:\\Users\\Darksnake\\Dropbox\\jna_data\\ar37e2.dat"));
file.setMeta(new MetaBuilder("meta")
.putValue("timeFile", "c:\\Users\\Darksnake\\Dropbox\\jna_data\\tar37e2.dat")
.putValue("temperatureFile", "c:\\Users\\Darksnake\\Dropbox\\jna_data\\e2temp.txt")
);
JNAEpisode spectra = new ReadJNADataAction(GlobalContext.instance(), null).runOne(file);
JNASpectrum sp = spectra.get(4);
System.out.println();
for (Map.Entry<Double, Long> entry : sp.asMap().entrySet()) {
System.out.printf("%g\t%d%n", entry.getKey(), entry.getValue());
}
PlotFrame frame = FXPlotUtils.displayJFreeChart("JNA test", null);
frame.add(PlottableData.plot(sp.asDataSet(), new XYAdapter("chanel", "count")));
Meta temps = sp.meta().getNode("temperature");
System.out.printf("%n%nThe average temperatures are:%n T2 = %f;%n T4 = %f;%n T5 = %f;%n T6 = %f;%n",
temps.getDouble("T2"),
temps.getDouble("T4"),
temps.getDouble("T5"),
temps.getDouble("T6"));
// double lowerChanel = 600;
// double upperChanel = 1100;
// Table data = sp.asDataSet().filter("chanel", lowerChanel, upperChanel);
// ParamSet params = new ParamSet()
// .setPar("amp", 2e5, 1e3)
// .setPar("pos", 800d, 1d)
// .setPar("sigma", 100d, 1d)
// .setPar("dsigma", 0d, 1e-1);
//
// Model model = new XYModel("split-normal", new SplitNormalSpectrum(), new PoissonAdapter("chanel", "count"));
// FitState state = new FitState(data, model, params);
// state = new FitManager(GlobalContext.instance()).runDefaultTask(state);
// state.print(new PrintWriter(System.out));
}
}

View File

@ -10,11 +10,14 @@ version = "0.3.4"
description = "The viewer for numass data"
configurations {
compile.exclude module: 'groovy-all'
compile.exclude module: 'groovy'
compile.exclude module: 'fontawesomefx'
compile.exclude module: 'commons-math3'
compile.exclude module: 'httpclient'
compile.exclude module: 'httpcore'
compile.exclude module: 'shichimifx'
compile.exclude module: 'commons-math3'
compile.exclude module: 'dataforge-fitting'
compile.exclude module: 'dataforge-minuit'
}
dependencies {