Using tasks in numass viewer
This commit is contained in:
parent
c8ad2a51bc
commit
cbfbe27958
@ -89,7 +89,7 @@ public class PrepareDataAction extends OneToOneAction<NMFile, DataSet> {
|
|||||||
double cr = point.getCountRate(a, b, deadTime);
|
double cr = point.getCountRate(a, b, deadTime);
|
||||||
double crErr = point.getCountRateErr(a, b, deadTime);
|
double crErr = point.getCountRateErr(a, b, deadTime);
|
||||||
|
|
||||||
Instant timestamp = point.getAbsouteTime().toInstant(ZoneOffset.UTC);
|
Instant timestamp = point.getStartTime();
|
||||||
|
|
||||||
dataList.add(new MapDataPoint(parnames, new Object[]{Uset, Uread, time, total, wind, corr, cr, crErr, timestamp}));
|
dataList.add(new MapDataPoint(parnames, new Object[]{Uset, Uread, time, total, wind, corr, cr, crErr, timestamp}));
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
|
import static java.lang.String.format;
|
||||||
|
import static java.lang.String.format;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -13,244 +13,248 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package inr.numass.data;
|
package inr.numass.data;
|
||||||
|
|
||||||
import hep.dataforge.data.DataPoint;
|
import hep.dataforge.data.DataPoint;
|
||||||
import hep.dataforge.data.MapDataPoint;
|
import hep.dataforge.data.MapDataPoint;
|
||||||
import java.time.LocalDateTime;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import static java.util.Arrays.sort;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.List;
|
||||||
import java.util.List;
|
import java.util.Map;
|
||||||
import java.util.Map;
|
import static java.util.Arrays.sort;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Darksnake
|
* @author Darksnake
|
||||||
*/
|
*/
|
||||||
public class NMPoint {
|
public class NMPoint {
|
||||||
|
|
||||||
static final String[] dataNames = {"chanel", "count"};
|
static final String[] dataNames = {"chanel", "count"};
|
||||||
private LocalDateTime absouteTime;
|
private Instant startTime;
|
||||||
|
|
||||||
// private MonitorCorrector corrector = null;
|
// private MonitorCorrector corrector = null;
|
||||||
// private double deadTime;
|
// private double deadTime;
|
||||||
private long eventsCount;
|
private long eventsCount;
|
||||||
|
|
||||||
private int overflow;
|
private int overflow;
|
||||||
|
|
||||||
private double pointLength;
|
private double pointLength;
|
||||||
// private final MeasurementPoint point;
|
// private final MeasurementPoint point;
|
||||||
private final int[] spectrum;
|
private final int[] spectrum;
|
||||||
private double uread;
|
private double uread;
|
||||||
private double uset;
|
private double uset;
|
||||||
|
|
||||||
public NMPoint(RawNMPoint point) {
|
public NMPoint(RawNMPoint point) {
|
||||||
if (point == null) {
|
if (point == null) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pointLength = point.getLength();
|
this.pointLength = point.getLength();
|
||||||
this.uset = point.getUset();
|
this.uset = point.getUset();
|
||||||
this.uread = point.getUread();
|
this.uread = point.getUread();
|
||||||
this.absouteTime = point.getAbsouteTime();
|
this.startTime = point.getStartTime();
|
||||||
this.eventsCount = point.getEventsCount();
|
this.eventsCount = point.getEventsCount();
|
||||||
// this.point = point;
|
// this.point = point;
|
||||||
spectrum = calculateSpectrum(point);
|
spectrum = calculateSpectrum(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public PointSpectrum(RawPoint point, double deadTime) {
|
// public PointSpectrum(RawPoint point, double deadTime) {
|
||||||
// this(point);
|
// this(point);
|
||||||
// this.deadTime = deadTime;
|
// this.deadTime = deadTime;
|
||||||
// }
|
// }
|
||||||
private int[] calculateSpectrum(RawNMPoint point) {
|
private int[] calculateSpectrum(RawNMPoint point) {
|
||||||
assert point.getEventsCount() > 0;
|
assert point.getEventsCount() > 0;
|
||||||
|
|
||||||
int[] result = new int[RawNMPoint.MAX_CHANEL];
|
int[] result = new int[RawNMPoint.MAX_CHANEL];
|
||||||
Arrays.fill(result, 0);
|
Arrays.fill(result, 0);
|
||||||
point.getEvents().stream().forEach((event) -> {
|
point.getEvents().stream().forEach((event) -> {
|
||||||
if (event.getChanel() >= RawNMPoint.MAX_CHANEL) {
|
if (event.getChanel() >= RawNMPoint.MAX_CHANEL) {
|
||||||
overflow++;
|
overflow++;
|
||||||
} else {
|
} else {
|
||||||
result[event.getChanel()]++;
|
result[event.getChanel()]++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataPoint fastSlice(int... borders) {
|
public DataPoint fastSlice(int... borders) {
|
||||||
assert borders.length > 0;//FIXME replace by condition check
|
assert borders.length > 0;//FIXME replace by condition check
|
||||||
sort(borders);
|
sort(borders);
|
||||||
assert borders[borders.length] < RawNMPoint.MAX_CHANEL;//FIXME replace by condition check
|
assert borders[borders.length] < RawNMPoint.MAX_CHANEL;//FIXME replace by condition check
|
||||||
|
|
||||||
Integer[] slices = new Integer[borders.length + 2];
|
Integer[] slices = new Integer[borders.length + 2];
|
||||||
String[] names = new String[borders.length + 2];
|
String[] names = new String[borders.length + 2];
|
||||||
|
|
||||||
slices[0] = getCountInWindow(0, borders[0]);
|
slices[0] = getCountInWindow(0, borders[0]);
|
||||||
names[0] = Integer.toString(borders[0]);
|
names[0] = Integer.toString(borders[0]);
|
||||||
for (int i = 1; i < borders.length; i++) {
|
for (int i = 1; i < borders.length; i++) {
|
||||||
slices[i] = getCountInWindow(borders[i - 1], borders[i]);
|
slices[i] = getCountInWindow(borders[i - 1], borders[i]);
|
||||||
names[i] = Integer.toString(borders[i]);
|
names[i] = Integer.toString(borders[i]);
|
||||||
}
|
}
|
||||||
slices[borders.length + 1] = getCountInWindow(borders[borders.length], RawNMPoint.MAX_CHANEL);
|
slices[borders.length + 1] = getCountInWindow(borders[borders.length], RawNMPoint.MAX_CHANEL);
|
||||||
names[borders.length + 1] = Integer.toString(RawNMPoint.MAX_CHANEL);
|
names[borders.length + 1] = Integer.toString(RawNMPoint.MAX_CHANEL);
|
||||||
|
|
||||||
slices[borders.length + 2] = RawNMPoint.MAX_CHANEL;
|
slices[borders.length + 2] = RawNMPoint.MAX_CHANEL;
|
||||||
names[borders.length + 2] = "TOTAL";
|
names[borders.length + 2] = "TOTAL";
|
||||||
|
|
||||||
//FIXME fix it!
|
//FIXME fix it!
|
||||||
return new MapDataPoint(names, slices);
|
return new MapDataPoint(names, slices);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the absouteTime
|
* @return the absouteTime
|
||||||
*/
|
*/
|
||||||
public LocalDateTime getAbsouteTime() {
|
public Instant getStartTime() {
|
||||||
return absouteTime;
|
if (startTime == null) {
|
||||||
}
|
return Instant.EPOCH;
|
||||||
|
} else {
|
||||||
public int getCountInChanel(int chanel) {
|
return startTime;
|
||||||
return spectrum[chanel];
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCountInWindow(int from, int to) {
|
public int getCountInChanel(int chanel) {
|
||||||
int res = 0;
|
return spectrum[chanel];
|
||||||
for (int i = from; i <= to; i++) {
|
}
|
||||||
res += spectrum[i];
|
|
||||||
}
|
public int getCountInWindow(int from, int to) {
|
||||||
if (res == Integer.MAX_VALUE) {
|
int res = 0;
|
||||||
throw new RuntimeException("integer overflow in spectrum calculation");
|
for (int i = from; i <= to; i++) {
|
||||||
}
|
res += spectrum[i];
|
||||||
return res;
|
}
|
||||||
}
|
if (res == Integer.MAX_VALUE) {
|
||||||
|
throw new RuntimeException("integer overflow in spectrum calculation");
|
||||||
public double getCountRate(int from, int to, double deadTime) {
|
}
|
||||||
double wind = getCountInWindow(from, to) / getLength();
|
return res;
|
||||||
double res;
|
}
|
||||||
if (deadTime > 0) {
|
|
||||||
double total = getEventsCount();
|
public double getCountRate(int from, int to, double deadTime) {
|
||||||
double time = getLength();
|
double wind = getCountInWindow(from, to) / getLength();
|
||||||
res = wind / (1 - total * deadTime / time);
|
double res;
|
||||||
} else {
|
if (deadTime > 0) {
|
||||||
res = wind;
|
double total = getEventsCount();
|
||||||
}
|
double time = getLength();
|
||||||
return res;
|
res = wind / (1 - total * deadTime / time);
|
||||||
}
|
} else {
|
||||||
|
res = wind;
|
||||||
public double getCountRateErr(int from, int to, double deadTime) {
|
}
|
||||||
return Math.sqrt(getCountRate(from, to, deadTime) / getLength());
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DataPoint> getData() {
|
public double getCountRateErr(int from, int to, double deadTime) {
|
||||||
List<DataPoint> data = new ArrayList<>();
|
return Math.sqrt(getCountRate(from, to, deadTime) / getLength());
|
||||||
for (int i = 0; i < RawNMPoint.MAX_CHANEL; i++) {
|
}
|
||||||
data.add(new MapDataPoint(dataNames, i, spectrum[i]));
|
|
||||||
|
public List<DataPoint> getData() {
|
||||||
}
|
List<DataPoint> data = new ArrayList<>();
|
||||||
return data;
|
for (int i = 0; i < RawNMPoint.MAX_CHANEL; i++) {
|
||||||
}
|
data.add(new MapDataPoint(dataNames, i, spectrum[i]));
|
||||||
|
|
||||||
/**
|
}
|
||||||
* Events count - overflow
|
return data;
|
||||||
*
|
}
|
||||||
* @return
|
|
||||||
*/
|
/**
|
||||||
public long getEventsCount() {
|
* Events count - overflow
|
||||||
return eventsCount - getOverflow();
|
*
|
||||||
}
|
* @return
|
||||||
|
*/
|
||||||
public List<DataPoint> getData(int binning, boolean normalize) {
|
public long getEventsCount() {
|
||||||
List<DataPoint> data = new ArrayList<>();
|
return eventsCount - getOverflow();
|
||||||
|
}
|
||||||
double norm;
|
|
||||||
if (normalize) {
|
public List<DataPoint> getData(int binning, boolean normalize) {
|
||||||
norm = getLength();
|
List<DataPoint> data = new ArrayList<>();
|
||||||
} else {
|
|
||||||
norm = 1d;
|
double norm;
|
||||||
}
|
if (normalize) {
|
||||||
|
norm = getLength();
|
||||||
int i = 0;
|
} else {
|
||||||
|
norm = 1d;
|
||||||
while (i < RawNMPoint.MAX_CHANEL - binning) {
|
}
|
||||||
int start = i;
|
|
||||||
double sum = spectrum[start] / norm;
|
int i = 0;
|
||||||
while (i < start + binning) {
|
|
||||||
sum += spectrum[i] / norm;
|
while (i < RawNMPoint.MAX_CHANEL - binning) {
|
||||||
i++;
|
int start = i;
|
||||||
}
|
double sum = spectrum[start] / norm;
|
||||||
data.add(new MapDataPoint(dataNames, start + binning / 2d, sum));
|
while (i < start + binning) {
|
||||||
i++;
|
sum += spectrum[i] / norm;
|
||||||
}
|
i++;
|
||||||
return data;
|
}
|
||||||
}
|
data.add(new MapDataPoint(dataNames, start + binning / 2d, sum));
|
||||||
|
i++;
|
||||||
public Map<Double, Double> getMapWithBinning(int binning, boolean normalize) {
|
}
|
||||||
Map<Double, Double> res = new LinkedHashMap<>();
|
return data;
|
||||||
|
}
|
||||||
double norm;
|
|
||||||
if (normalize) {
|
public Map<Double, Double> getMapWithBinning(int binning, boolean normalize) {
|
||||||
norm = getLength();
|
Map<Double, Double> res = new LinkedHashMap<>();
|
||||||
} else {
|
|
||||||
norm = 1d;
|
double norm;
|
||||||
}
|
if (normalize) {
|
||||||
|
norm = getLength();
|
||||||
int i = 0;
|
} else {
|
||||||
|
norm = 1d;
|
||||||
while (i < RawNMPoint.MAX_CHANEL - binning) {
|
}
|
||||||
int start = i;
|
|
||||||
double sum = spectrum[start] / norm;
|
int i = 0;
|
||||||
while (i < start + binning) {
|
|
||||||
sum += spectrum[i] / norm;
|
while (i < RawNMPoint.MAX_CHANEL - binning) {
|
||||||
i++;
|
int start = i;
|
||||||
}
|
double sum = spectrum[start] / norm;
|
||||||
res.put(start + binning / 2d, sum);
|
while (i < start + binning) {
|
||||||
i++;
|
sum += spectrum[i] / norm;
|
||||||
}
|
i++;
|
||||||
return res;
|
}
|
||||||
|
res.put(start + binning / 2d, sum);
|
||||||
}
|
i++;
|
||||||
|
}
|
||||||
public Map<Double, Double> getMapWithBinning(NMPoint reference, int binning) {
|
return res;
|
||||||
Map<Double, Double> sp = this.getMapWithBinning(binning, true);
|
|
||||||
Map<Double, Double> referenceSpectrum = reference.getMapWithBinning(binning, true);
|
}
|
||||||
|
|
||||||
Map<Double, Double> res = new LinkedHashMap<>();
|
public Map<Double, Double> getMapWithBinning(NMPoint reference, int binning) {
|
||||||
|
Map<Double, Double> sp = this.getMapWithBinning(binning, true);
|
||||||
sp.entrySet().stream().map((entry) -> entry.getKey()).forEach((bin) -> {
|
Map<Double, Double> referenceSpectrum = reference.getMapWithBinning(binning, true);
|
||||||
res.put(bin, Math.max(sp.get(bin) - referenceSpectrum.get(bin), 0));
|
|
||||||
});
|
Map<Double, Double> res = new LinkedHashMap<>();
|
||||||
|
|
||||||
return res;
|
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 overflow
|
||||||
|
*/
|
||||||
/**
|
public int getOverflow() {
|
||||||
* @return the pointLength
|
return overflow;
|
||||||
*/
|
}
|
||||||
public double getLength() {
|
|
||||||
return pointLength;
|
/**
|
||||||
}
|
* @return the pointLength
|
||||||
|
*/
|
||||||
/**
|
public double getLength() {
|
||||||
* @return the uread
|
return pointLength;
|
||||||
*/
|
}
|
||||||
public double getUread() {
|
|
||||||
return uread;
|
/**
|
||||||
}
|
* @return the uread
|
||||||
|
*/
|
||||||
/**
|
public double getUread() {
|
||||||
* @return the uset
|
return uread;
|
||||||
*/
|
}
|
||||||
public double getUset() {
|
|
||||||
return uset;
|
/**
|
||||||
}
|
* @return the uset
|
||||||
|
*/
|
||||||
}
|
public double getUset() {
|
||||||
|
return uset;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -24,6 +24,7 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
@ -227,7 +228,7 @@ public class NumassDataReader {
|
|||||||
absoluteTime = absoluteTime.plusDays(1);
|
absoluteTime = absoluteTime.plusDays(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
point.setAbsouteTime(absoluteTime);
|
point.setStartTime(absoluteTime.toInstant(ZoneOffset.UTC));
|
||||||
|
|
||||||
rx = readBlock(4);
|
rx = readBlock(4);
|
||||||
int Uread = rx[2] + 256 * rx[3];
|
int Uread = rx[2] + 256 * rx[3];
|
||||||
|
@ -13,169 +13,170 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package inr.numass.data;
|
package inr.numass.data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Хранит информацию о спектре точки, но не об отдельных событиях.
|
* Хранит информацию о спектре точки, но не об отдельных событиях.
|
||||||
*
|
*
|
||||||
* @author Darksnake
|
* @author Darksnake
|
||||||
*/
|
*/
|
||||||
public class RawNMPoint implements Cloneable {
|
public class RawNMPoint implements Cloneable {
|
||||||
|
|
||||||
public static int MAX_CHANEL = 4095;
|
public static int MAX_CHANEL = 4095;
|
||||||
private LocalDateTime absouteTime;
|
private Instant startTime;
|
||||||
private final List<NMEvent> events;
|
private final List<NMEvent> events;
|
||||||
private double t;
|
private double length;
|
||||||
private double uread;
|
private double uread;
|
||||||
|
|
||||||
private double uset;
|
private double uset;
|
||||||
|
|
||||||
public RawNMPoint(double U, List<NMEvent> events, double t) {
|
public RawNMPoint(double U, List<NMEvent> events, double t) {
|
||||||
this.uset = U;
|
this.uset = U;
|
||||||
this.uread = U;
|
this.uread = U;
|
||||||
this.events = events;
|
this.events = events;
|
||||||
this.t = t;
|
this.length = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RawNMPoint(double Uset, double Uread, List<NMEvent> events, double t) {
|
public RawNMPoint(double Uset, double Uread, List<NMEvent> events, double t) {
|
||||||
this.uset = Uset;
|
this.uset = Uset;
|
||||||
this.uread = Uread;
|
this.uread = Uread;
|
||||||
this.events = events;
|
this.events = events;
|
||||||
this.t = t;
|
this.length = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RawNMPoint(double uset, double uread, List<NMEvent> events, double t, LocalDateTime absouteTime) {
|
public RawNMPoint(double uset, double uread, List<NMEvent> events, double t, Instant absouteTime) {
|
||||||
this.uset = uset;
|
this.uset = uset;
|
||||||
this.uread = uread;
|
this.uread = uread;
|
||||||
this.t = t;
|
this.length = t;
|
||||||
this.absouteTime = absouteTime;
|
this.startTime = absouteTime;
|
||||||
this.events = events;
|
this.events = events;
|
||||||
}
|
}
|
||||||
|
|
||||||
RawNMPoint() {
|
RawNMPoint() {
|
||||||
events = new ArrayList<>();
|
events = new ArrayList<>();
|
||||||
uset = 0;
|
uset = 0;
|
||||||
uread = 0;
|
uread = 0;
|
||||||
t = Double.NaN;
|
length = Double.NaN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RawNMPoint clone() {
|
public RawNMPoint clone() {
|
||||||
ArrayList<NMEvent> newevents = new ArrayList<>();
|
ArrayList<NMEvent> newevents = new ArrayList<>();
|
||||||
for (NMEvent event : this.getEvents()) {
|
for (NMEvent event : this.getEvents()) {
|
||||||
newevents.add(event.clone());
|
newevents.add(event.clone());
|
||||||
}
|
}
|
||||||
return new RawNMPoint(getUset(), getUread(), newevents, getLength());
|
return new RawNMPoint(getUset(), getUread(), newevents, getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalDateTime getAbsouteTime() {
|
public Instant getStartTime() {
|
||||||
return absouteTime;
|
return startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getCR() {
|
public double getCR() {
|
||||||
return getEventsCount() / getLength();
|
return getEventsCount() / getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getCRError() {
|
public double getCRError() {
|
||||||
return Math.sqrt(getEventsCount()) / getLength();
|
return Math.sqrt(getEventsCount()) / getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the events
|
* @return the events
|
||||||
*/
|
*/
|
||||||
public List<NMEvent> getEvents() {
|
public List<NMEvent> getEvents() {
|
||||||
return events;
|
return events;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getEventsCount() {
|
public long getEventsCount() {
|
||||||
return events.size();
|
return events.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Measurement time
|
* Measurement time
|
||||||
* @return the tset
|
* @return the tset
|
||||||
*/
|
*/
|
||||||
public double getLength() {
|
public double getLength() {
|
||||||
if (Double.isNaN(t)) {
|
if (Double.isNaN(length)) {
|
||||||
throw new Error();
|
throw new Error();
|
||||||
}
|
}
|
||||||
return t;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the Uread
|
* @return the Uread
|
||||||
*/
|
*/
|
||||||
public double getUread() {
|
public double getUread() {
|
||||||
if (uread <= 0) {
|
if (uread <= 0) {
|
||||||
return getUset();
|
return getUset();
|
||||||
} else {
|
} else {
|
||||||
return uread;
|
return uread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the Uset
|
* @return the Uset
|
||||||
*/
|
*/
|
||||||
public double getUset() {
|
public double getUset() {
|
||||||
if (uset < 0) {
|
if (uset < 0) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
return uset;
|
return uset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RawNMPoint merge(RawNMPoint point) {
|
public RawNMPoint merge(RawNMPoint point) {
|
||||||
RawNMPoint res = this.clone();
|
RawNMPoint res = this.clone();
|
||||||
for (NMEvent newEvent : point.getEvents()) {
|
for (NMEvent newEvent : point.getEvents()) {
|
||||||
res.putEvent(new NMEvent(newEvent.getChanel(), newEvent.getTime() + this.getLength()));
|
res.putEvent(new NMEvent(newEvent.getChanel(), newEvent.getTime() + this.getLength()));
|
||||||
}
|
}
|
||||||
res.t += point.getLength();
|
res.length += point.getLength();
|
||||||
res.uread = (this.uread + point.uread) / 2;
|
res.uread = (this.uread + point.uread) / 2;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void putEvent(NMEvent event) {
|
void putEvent(NMEvent event) {
|
||||||
events.add(event);
|
events.add(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RawNMPoint selectChanels(int from, int to) {
|
public RawNMPoint selectChanels(int from, int to) {
|
||||||
assert to > from;
|
assert to > from;
|
||||||
|
|
||||||
List<NMEvent> res = new ArrayList<>();
|
List<NMEvent> res = new ArrayList<>();
|
||||||
for (NMEvent event : this.getEvents()) {
|
for (NMEvent event : this.getEvents()) {
|
||||||
if ((event.getChanel() >= from) && (event.getChanel() <= to)) {
|
if ((event.getChanel() >= from) && (event.getChanel() <= to)) {
|
||||||
res.add(event);
|
res.add(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new RawNMPoint(getUset(), getUread(), res, getLength());
|
return new RawNMPoint(getUset(), getUread(), res, getLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAbsouteTime(LocalDateTime absouteTime) {
|
void setStartTime(Instant absouteTime) {
|
||||||
this.absouteTime = absouteTime;
|
this.startTime = absouteTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param tset the tset to set
|
* @param tset the tset to set
|
||||||
*/
|
*/
|
||||||
void setLength(double tset) {
|
void setLength(double tset) {
|
||||||
this.t = tset;
|
this.length = tset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Uread the Uread to set
|
* @param Uread the Uread to set
|
||||||
*/
|
*/
|
||||||
void setUread(double Uread) {
|
void setUread(double Uread) {
|
||||||
assert Uread >= 0;
|
assert Uread >= 0;
|
||||||
this.uread = Uread;
|
this.uread = Uread;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Uset the Uset to set
|
* @param Uset the Uset to set
|
||||||
*/
|
*/
|
||||||
void setUset(double Uset) {
|
void setUset(double Uset) {
|
||||||
this.uset = Uset;
|
this.uset = Uset;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
@ -13,100 +13,94 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package inr.numass.data;
|
package inr.numass.data;
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta;
|
import hep.dataforge.data.DataAdapter;
|
||||||
import hep.dataforge.data.DataPoint;
|
import hep.dataforge.meta.Meta;
|
||||||
import hep.dataforge.data.MapDataPoint;
|
import hep.dataforge.data.DataPoint;
|
||||||
import hep.dataforge.data.XYDataAdapter;
|
import hep.dataforge.data.MapDataPoint;
|
||||||
import hep.dataforge.exceptions.DataFormatException;
|
import hep.dataforge.data.XYDataAdapter;
|
||||||
import hep.dataforge.exceptions.NameNotFoundException;
|
import hep.dataforge.exceptions.DataFormatException;
|
||||||
import hep.dataforge.names.Names;
|
import hep.dataforge.exceptions.NameNotFoundException;
|
||||||
import hep.dataforge.values.Value;
|
import hep.dataforge.meta.MetaBuilder;
|
||||||
|
import hep.dataforge.values.Value;
|
||||||
/**
|
|
||||||
*
|
/**
|
||||||
* @author Darksnake
|
*
|
||||||
*/
|
* @author Darksnake
|
||||||
public class SpectrumDataAdapter extends XYDataAdapter {
|
*/
|
||||||
|
public class SpectrumDataAdapter extends XYDataAdapter {
|
||||||
private static final String ANNOTATION_TIMENAME = "timeName";
|
|
||||||
|
private static final String POINT_LENGTH_NAME = "time";
|
||||||
private String timeName = "time";
|
|
||||||
|
public SpectrumDataAdapter() {
|
||||||
public SpectrumDataAdapter() {
|
}
|
||||||
}
|
|
||||||
|
public SpectrumDataAdapter(Meta meta) {
|
||||||
public SpectrumDataAdapter(Meta aliasAnnotation) {
|
super(meta);
|
||||||
super(aliasAnnotation);
|
}
|
||||||
this.timeName = aliasAnnotation.getString(ANNOTATION_TIMENAME, "X");
|
|
||||||
}
|
public SpectrumDataAdapter(String xName, String yName, String yErrName, String measurementTime) {
|
||||||
|
super(new MetaBuilder(DataAdapter.DATA_ADAPTER_ANNOTATION_NAME)
|
||||||
public SpectrumDataAdapter(String xName, String yName, String yErrName, String timeTime) {
|
.setValue(X_NAME, xName)
|
||||||
super(xName, yName, yErrName);
|
.setValue(Y_NAME, yName)
|
||||||
this.timeName = timeTime;
|
.setValue(Y_ERR_NAME, yErrName)
|
||||||
}
|
.setValue(POINT_LENGTH_NAME, measurementTime)
|
||||||
|
.build()
|
||||||
public SpectrumDataAdapter(String xName, String yName, String timeTime) {
|
);
|
||||||
super(xName, yName);
|
}
|
||||||
this.timeName = timeTime;
|
|
||||||
}
|
public SpectrumDataAdapter(String xName, String yName, String measurementTime) {
|
||||||
|
super(new MetaBuilder(DataAdapter.DATA_ADAPTER_ANNOTATION_NAME)
|
||||||
public double getTime(DataPoint point) {
|
.setValue(X_NAME, xName)
|
||||||
if (point.names().contains(timeName)) {
|
.setValue(Y_NAME, yName)
|
||||||
return point.getDouble(timeName);
|
.setValue(POINT_LENGTH_NAME, measurementTime)
|
||||||
} else {
|
.build()
|
||||||
return 1d;
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public double getTime(DataPoint point) {
|
||||||
public DataPoint buildSpectrumDataPoint(double x, long count, double t) {
|
return this.getFrom(point, POINT_LENGTH_NAME, 1d).doubleValue();
|
||||||
return new MapDataPoint(new String[]{xName,yName,timeName}, x,count,t);
|
}
|
||||||
}
|
|
||||||
|
public DataPoint buildSpectrumDataPoint(double x, long count, double t) {
|
||||||
public DataPoint buildSpectrumDataPoint(double x, long count, double countErr, double t) {
|
return new MapDataPoint(new String[]{getValueName(X_NAME), getValueName(Y_NAME),
|
||||||
return new MapDataPoint(new String[]{xName,yName,yErrName,timeName}, x,count,countErr,t);
|
getValueName(POINT_LENGTH_NAME)},
|
||||||
}
|
x, count, t);
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public Meta buildAnnotation() {
|
public DataPoint buildSpectrumDataPoint(double x, long count, double countErr, double t) {
|
||||||
Meta res = super.buildAnnotation();
|
return new MapDataPoint(new String[]{getValueName(X_NAME), getValueName(Y_NAME),
|
||||||
res.getBuilder().putValue(ANNOTATION_TIMENAME, timeName);
|
getValueName(Y_ERR_NAME), getValueName(POINT_LENGTH_NAME)},
|
||||||
return res;
|
x, count, countErr, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Names getNames() {
|
public boolean providesYError(DataPoint point) {
|
||||||
return Names.of(xName,yName);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean providesYError(DataPoint point) {
|
public Value getYerr(DataPoint point) throws NameNotFoundException {
|
||||||
return true;
|
if (providesYError(point)) {
|
||||||
}
|
return Value.of(super.getYerr(point).doubleValue() / getTime(point));
|
||||||
|
} else {
|
||||||
|
double y = super.getY(point).doubleValue();
|
||||||
|
if (y <= 0) {
|
||||||
@Override
|
throw new DataFormatException();
|
||||||
public Value getYerr(DataPoint point) throws NameNotFoundException {
|
} else {
|
||||||
if (point.names().contains(yErrName)) {
|
return Value.of(Math.sqrt(y) / getTime(point));
|
||||||
return Value.of(super.getYerr(point).doubleValue()/getTime(point));
|
}
|
||||||
} else{
|
}
|
||||||
double y = super.getY(point).doubleValue();
|
}
|
||||||
if(y<=0) throw new DataFormatException();
|
|
||||||
else {
|
public long getCount(DataPoint point) {
|
||||||
return Value.of(Math.sqrt(y)/getTime(point));
|
return super.getY(point).numberValue().longValue();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
@Override
|
||||||
|
public Value getY(DataPoint point) {
|
||||||
public long getCount(DataPoint point){
|
return Value.of(super.getY(point).doubleValue() / getTime(point));
|
||||||
return point.getValue(yName).numberValue().longValue();
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public Value getY(DataPoint point) {
|
|
||||||
return Value.of(super.getY(point).doubleValue() / getTime(point));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -27,6 +27,7 @@ import java.util.Iterator;
|
|||||||
import org.apache.commons.math3.random.JDKRandomGenerator;
|
import org.apache.commons.math3.random.JDKRandomGenerator;
|
||||||
import org.apache.commons.math3.random.RandomDataGenerator;
|
import org.apache.commons.math3.random.RandomDataGenerator;
|
||||||
import org.apache.commons.math3.random.RandomGenerator;
|
import org.apache.commons.math3.random.RandomGenerator;
|
||||||
|
import static java.lang.Double.isNaN;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Генератор наборов данных для спектров. На входе требуется набор данных,
|
* Генератор наборов данных для спектров. На входе требуется набор данных,
|
||||||
@ -64,7 +65,7 @@ public class SpectrumGenerator implements Generator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListDataSet generateData(Iterable<DataPoint> config) {
|
public ListDataSet generateData(Iterable<DataPoint> config) {
|
||||||
ListDataSet res = adapter.buildEmptyDataSet("");
|
ListDataSet res = new ListDataSet(adapter.getFormat());
|
||||||
for (Iterator<DataPoint> it = config.iterator(); it.hasNext();) {
|
for (Iterator<DataPoint> it = config.iterator(); it.hasNext();) {
|
||||||
res.add(this.generateDataPoint(it.next()));
|
res.add(this.generateDataPoint(it.next()));
|
||||||
}
|
}
|
||||||
|
@ -13,71 +13,71 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package inr.numass.debunch;
|
package inr.numass.debunch;
|
||||||
|
|
||||||
import inr.numass.data.NMEvent;
|
import inr.numass.data.NMEvent;
|
||||||
import inr.numass.data.RawNMPoint;
|
import inr.numass.data.RawNMPoint;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Darksnake
|
* @author Darksnake
|
||||||
*/
|
*/
|
||||||
public class DebunchReportImpl implements DebunchReport {
|
public class DebunchReportImpl implements DebunchReport {
|
||||||
|
|
||||||
private final List<Frame> bunches;
|
private final List<Frame> bunches;
|
||||||
private final RawNMPoint pointAfter;
|
private final RawNMPoint pointAfter;
|
||||||
private final RawNMPoint pointBefore;
|
private final RawNMPoint pointBefore;
|
||||||
|
|
||||||
public DebunchReportImpl(RawNMPoint pointBefore, RawNMPoint pointAfter, List<Frame> bunches) {
|
public DebunchReportImpl(RawNMPoint pointBefore, RawNMPoint pointAfter, List<Frame> bunches) {
|
||||||
this.pointBefore = pointBefore;
|
this.pointBefore = pointBefore;
|
||||||
this.pointAfter = pointAfter;
|
this.pointAfter = pointAfter;
|
||||||
this.bunches = bunches;
|
this.bunches = bunches;
|
||||||
}
|
}
|
||||||
|
|
||||||
DebunchReportImpl(RawNMPoint pointBefore, DebunchData debunchData) {
|
DebunchReportImpl(RawNMPoint pointBefore, DebunchData debunchData) {
|
||||||
this.pointBefore = pointBefore;
|
this.pointBefore = pointBefore;
|
||||||
pointAfter = new RawNMPoint(pointBefore.getUset(),pointBefore.getUread(),
|
pointAfter = new RawNMPoint(pointBefore.getUset(),pointBefore.getUread(),
|
||||||
debunchData.getDebunchedEvents(), debunchData.getDebunchedLength(),pointBefore.getAbsouteTime());
|
debunchData.getDebunchedEvents(), debunchData.getDebunchedLength(),pointBefore.getStartTime());
|
||||||
this.bunches = debunchData.getBunches();
|
this.bunches = debunchData.getBunches();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double eventsFiltred() {
|
public double eventsFiltred() {
|
||||||
return 1-(double)getPoint().getEventsCount()/getInitialPoint().getEventsCount();
|
return 1-(double)getPoint().getEventsCount()/getInitialPoint().getEventsCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<NMEvent> getBunchEvents() {
|
public List<NMEvent> getBunchEvents() {
|
||||||
List<NMEvent> res = new ArrayList<>();
|
List<NMEvent> res = new ArrayList<>();
|
||||||
for (Frame interval : getBunches()) {
|
for (Frame interval : getBunches()) {
|
||||||
res.addAll(interval.getEvents());
|
res.addAll(interval.getEvents());
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Frame> getBunches() {
|
public List<Frame> getBunches() {
|
||||||
return bunches;
|
return bunches;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RawNMPoint getInitialPoint() {
|
public RawNMPoint getInitialPoint() {
|
||||||
return pointBefore;
|
return pointBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RawNMPoint getPoint() {
|
public RawNMPoint getPoint() {
|
||||||
return pointAfter;
|
return pointAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double timeFiltred() {
|
public double timeFiltred() {
|
||||||
return 1-getPoint().getLength()/getInitialPoint().getLength();
|
return 1-getPoint().getLength()/getInitialPoint().getLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,171 +13,174 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package inr.numass.generators;
|
package inr.numass.generators;
|
||||||
|
|
||||||
import inr.numass.data.NMEvent;
|
import inr.numass.data.NMEvent;
|
||||||
import inr.numass.data.RawNMPoint;
|
import inr.numass.data.RawNMPoint;
|
||||||
import static java.lang.Math.max;
|
import static java.lang.Math.max;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import static java.lang.Math.max;
|
||||||
/**
|
import static java.lang.Math.max;
|
||||||
*
|
import static java.lang.Math.max;
|
||||||
* @author Darksnake
|
|
||||||
*/
|
/**
|
||||||
public final class EventChainGenerator {
|
*
|
||||||
|
* @author Darksnake
|
||||||
private final static double us = 1e-6;
|
*/
|
||||||
|
public final class EventChainGenerator {
|
||||||
private double blockStartTime = 0;
|
|
||||||
|
private final static double us = 1e-6;
|
||||||
private final List<NMEvent> generatedChain = new ArrayList<>();
|
|
||||||
private final EventGenerator generator;
|
private double blockStartTime = 0;
|
||||||
private final double length;
|
|
||||||
private final List<NMEvent> pileupChain = new ArrayList<>();
|
private final List<NMEvent> generatedChain = new ArrayList<>();
|
||||||
|
private final EventGenerator generator;
|
||||||
private final List<NMEvent> registredChain = new ArrayList<>();
|
private final double length;
|
||||||
|
private final List<NMEvent> pileupChain = new ArrayList<>();
|
||||||
public EventChainGenerator(double cr, double length) {
|
|
||||||
generator = new EventGenerator(cr);
|
private final List<NMEvent> registredChain = new ArrayList<>();
|
||||||
this.length = length;
|
|
||||||
|
public EventChainGenerator(double cr, double length) {
|
||||||
run();
|
generator = new EventGenerator(cr);
|
||||||
}
|
this.length = length;
|
||||||
|
|
||||||
public EventChainGenerator(double cr, double length, RawNMPoint source, int minChanel, int maxChanel) {
|
run();
|
||||||
generator = new EventGenerator(cr);
|
}
|
||||||
this.generator.loadFromPoint(source, minChanel, maxChanel);
|
|
||||||
this.length = length;
|
public EventChainGenerator(double cr, double length, RawNMPoint source, int minChanel, int maxChanel) {
|
||||||
|
generator = new EventGenerator(cr);
|
||||||
run();
|
this.generator.loadFromPoint(source, minChanel, maxChanel);
|
||||||
}
|
this.length = length;
|
||||||
|
|
||||||
public EventChainGenerator(double cr, double length, Map<Double,Double> spectrum, int minChanel, int maxChanel) {
|
run();
|
||||||
generator = new EventGenerator(cr);
|
}
|
||||||
this.generator.loadFromSpectrum(spectrum, minChanel, maxChanel);
|
|
||||||
this.length = length;
|
public EventChainGenerator(double cr, double length, Map<Double,Double> spectrum, int minChanel, int maxChanel) {
|
||||||
|
generator = new EventGenerator(cr);
|
||||||
run();
|
this.generator.loadFromSpectrum(spectrum, minChanel, maxChanel);
|
||||||
}
|
this.length = length;
|
||||||
|
|
||||||
/**
|
run();
|
||||||
* Амлпитуда второго сигнала в зависимости от амплитуд наложенных сигналов и
|
}
|
||||||
* задержки
|
|
||||||
*
|
/**
|
||||||
* @param delay
|
* Амлпитуда второго сигнала в зависимости от амплитуд наложенных сигналов и
|
||||||
* @return
|
* задержки
|
||||||
*/
|
*
|
||||||
private short getNewChanel(double delay, short prevChanel, short newChanel) {
|
* @param delay
|
||||||
assert delay > 0;
|
* @return
|
||||||
//эмпирическая формула для канала
|
*/
|
||||||
double x = delay / us;
|
private short getNewChanel(double delay, short prevChanel, short newChanel) {
|
||||||
double coef = max(0, 0.99078 + 0.05098 * x - 0.45775 * x * x + 0.10962 * x * x * x);
|
assert delay > 0;
|
||||||
|
//эмпирическая формула для канала
|
||||||
return (short) (prevChanel + coef * newChanel);
|
double x = delay / us;
|
||||||
}
|
double coef = max(0, 0.99078 + 0.05098 * x - 0.45775 * x * x + 0.10962 * x * x * x);
|
||||||
|
|
||||||
public RawNMPoint getPileUp() {
|
return (short) (prevChanel + coef * newChanel);
|
||||||
return new RawNMPoint(2, pileupChain, length);
|
}
|
||||||
}
|
|
||||||
|
public RawNMPoint getPileUp() {
|
||||||
public RawNMPoint getPointAsGenerated() {
|
return new RawNMPoint(2, pileupChain, length);
|
||||||
return new RawNMPoint(0, generatedChain, length);
|
}
|
||||||
}
|
|
||||||
|
public RawNMPoint getPointAsGenerated() {
|
||||||
public RawNMPoint getPointAsRegistred() {
|
return new RawNMPoint(0, generatedChain, length);
|
||||||
return new RawNMPoint(1, registredChain, length);
|
}
|
||||||
}
|
|
||||||
|
public RawNMPoint getPointAsRegistred() {
|
||||||
/**
|
return new RawNMPoint(1, registredChain, length);
|
||||||
* Имеется второй сигнал
|
}
|
||||||
*
|
|
||||||
* @param delay
|
/**
|
||||||
* @return
|
* Имеется второй сигнал
|
||||||
*/
|
*
|
||||||
private boolean hasNew(double delay) {
|
* @param delay
|
||||||
if (delay > 2.65 * us) {
|
* @return
|
||||||
return false;
|
*/
|
||||||
} else if (delay < 2.35 * us) {
|
private boolean hasNew(double delay) {
|
||||||
return true;
|
if (delay > 2.65 * us) {
|
||||||
} else {
|
return false;
|
||||||
return heads((2.65 * us - delay) / 0.3 / us);
|
} else if (delay < 2.35 * us) {
|
||||||
}
|
return true;
|
||||||
}
|
} else {
|
||||||
|
return heads((2.65 * us - delay) / 0.3 / us);
|
||||||
private boolean heads(double prob) {
|
}
|
||||||
double r = generator.nextUniform();
|
}
|
||||||
return r < prob;
|
|
||||||
}
|
private boolean heads(double prob) {
|
||||||
|
double r = generator.nextUniform();
|
||||||
NMEvent nextEvent(NMEvent prev) {
|
return r < prob;
|
||||||
if (prev == null) {
|
}
|
||||||
return generator.nextEvent(new NMEvent((short)0, 0));
|
|
||||||
}
|
NMEvent nextEvent(NMEvent prev) {
|
||||||
|
if (prev == null) {
|
||||||
NMEvent event = generator.nextEvent(prev);
|
return generator.nextEvent(new NMEvent((short)0, 0));
|
||||||
generatedChain.add(event);
|
}
|
||||||
double delay = event.getTime() - blockStartTime;
|
|
||||||
if (notDT(delay)) {
|
NMEvent event = generator.nextEvent(prev);
|
||||||
//Если система сбора данных успела переварить предыдущие события
|
generatedChain.add(event);
|
||||||
registredChain.add(event);
|
double delay = event.getTime() - blockStartTime;
|
||||||
blockStartTime = event.getTime();
|
if (notDT(delay)) {
|
||||||
return event;
|
//Если система сбора данных успела переварить предыдущие события
|
||||||
} else {
|
registredChain.add(event);
|
||||||
if ((!prevSurvived(delay)) && (!registredChain.isEmpty())) {
|
blockStartTime = event.getTime();
|
||||||
//если первое событие не выжило, а ушло в наложения
|
return event;
|
||||||
registredChain.remove(registredChain.size() - 1);
|
} else {
|
||||||
}
|
if ((!prevSurvived(delay)) && (!registredChain.isEmpty())) {
|
||||||
if (hasNew(delay)) {
|
//если первое событие не выжило, а ушло в наложения
|
||||||
// Если есть событие с увеличенной амлитудой
|
registredChain.remove(registredChain.size() - 1);
|
||||||
NMEvent pileup = new NMEvent(getNewChanel(delay, prev.getChanel(), event.getChanel()), event.getTime());
|
}
|
||||||
registredChain.add(pileup);
|
if (hasNew(delay)) {
|
||||||
pileupChain.add(pileup);
|
// Если есть событие с увеличенной амлитудой
|
||||||
}
|
NMEvent pileup = new NMEvent(getNewChanel(delay, prev.getChanel(), event.getChanel()), event.getTime());
|
||||||
//возвращаем предыдущее событие, чтобы отсчитывать мертвое время от него
|
registredChain.add(pileup);
|
||||||
return prev;
|
pileupChain.add(pileup);
|
||||||
}
|
}
|
||||||
}
|
//возвращаем предыдущее событие, чтобы отсчитывать мертвое время от него
|
||||||
|
return prev;
|
||||||
/**
|
}
|
||||||
* Не попал в мертвое время и наложения
|
}
|
||||||
*
|
|
||||||
* @param delay
|
/**
|
||||||
* @return
|
* Не попал в мертвое время и наложения
|
||||||
*/
|
*
|
||||||
private boolean notDT(double delay) {
|
* @param delay
|
||||||
if (delay > 7.0 * us) {
|
* @return
|
||||||
return true;
|
*/
|
||||||
} else if (delay < 6.5 * us) {
|
private boolean notDT(double delay) {
|
||||||
return false;
|
if (delay > 7.0 * us) {
|
||||||
} else {
|
return true;
|
||||||
return heads((delay - 6.5 * us) / 0.5 / us);
|
} else if (delay < 6.5 * us) {
|
||||||
}
|
return false;
|
||||||
}
|
} else {
|
||||||
|
return heads((delay - 6.5 * us) / 0.5 / us);
|
||||||
/**
|
}
|
||||||
* Выжило предыдушее событие
|
}
|
||||||
*
|
|
||||||
* @param delay
|
/**
|
||||||
* @return
|
* Выжило предыдушее событие
|
||||||
*/
|
*
|
||||||
private boolean prevSurvived(double delay) {
|
* @param delay
|
||||||
if (delay > 2.65 * us) {
|
* @return
|
||||||
return true;
|
*/
|
||||||
} else if (delay < 2.35 * us) {
|
private boolean prevSurvived(double delay) {
|
||||||
return false;
|
if (delay > 2.65 * us) {
|
||||||
} else {
|
return true;
|
||||||
return heads((delay - 2.35 * us) / 0.3 / us);
|
} else if (delay < 2.35 * us) {
|
||||||
}
|
return false;
|
||||||
}
|
} else {
|
||||||
|
return heads((delay - 2.35 * us) / 0.3 / us);
|
||||||
private void run() {
|
}
|
||||||
NMEvent next = null;
|
}
|
||||||
|
|
||||||
do {
|
private void run() {
|
||||||
next = nextEvent(next);
|
NMEvent next = null;
|
||||||
} while (next.getTime() < length);
|
|
||||||
}
|
do {
|
||||||
|
next = nextEvent(next);
|
||||||
}
|
} while (next.getTime() < length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -13,174 +13,174 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package inr.numass.utils;
|
package inr.numass.utils;
|
||||||
|
|
||||||
import hep.dataforge.context.GlobalContext;
|
import hep.dataforge.context.GlobalContext;
|
||||||
import hep.dataforge.data.DataPoint;
|
import hep.dataforge.data.DataPoint;
|
||||||
import hep.dataforge.data.ListDataSet;
|
import hep.dataforge.data.ListDataSet;
|
||||||
import hep.dataforge.data.MapDataPoint;
|
import hep.dataforge.data.MapDataPoint;
|
||||||
import inr.numass.data.SpectrumDataAdapter;
|
import inr.numass.data.SpectrumDataAdapter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import static java.util.Locale.setDefault;
|
import java.util.Scanner;
|
||||||
import java.util.Scanner;
|
import static java.util.Locale.setDefault;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Darksnake
|
* @author Darksnake
|
||||||
*/
|
*/
|
||||||
public class OldDataReader {
|
public class OldDataReader {
|
||||||
|
|
||||||
public static ListDataSet readConfig(String path) throws FileNotFoundException {
|
public static ListDataSet readConfig(String path) throws FileNotFoundException {
|
||||||
String[] list = {"X","time","ushift"};
|
String[] list = {"X","time","ushift"};
|
||||||
ListDataSet res = new ListDataSet(list);
|
ListDataSet res = new ListDataSet(list);
|
||||||
File file = GlobalContext.instance().io().getFile(path);
|
File file = GlobalContext.instance().io().getFile(path);
|
||||||
Scanner sc = new Scanner(file);
|
Scanner sc = new Scanner(file);
|
||||||
sc.nextLine();
|
sc.nextLine();
|
||||||
|
|
||||||
while(sc.hasNextLine()){
|
while(sc.hasNextLine()){
|
||||||
String line = sc.nextLine();
|
String line = sc.nextLine();
|
||||||
Scanner lineScan = new Scanner(line);
|
Scanner lineScan = new Scanner(line);
|
||||||
int time = lineScan.nextInt();
|
int time = lineScan.nextInt();
|
||||||
double u = lineScan.nextDouble();
|
double u = lineScan.nextDouble();
|
||||||
double ushift = 0;
|
double ushift = 0;
|
||||||
if(lineScan.hasNextDouble()){
|
if(lineScan.hasNextDouble()){
|
||||||
ushift = lineScan.nextDouble();
|
ushift = lineScan.nextDouble();
|
||||||
}
|
}
|
||||||
DataPoint point = new MapDataPoint(list, u,time,ushift);
|
DataPoint point = new MapDataPoint(list, u,time,ushift);
|
||||||
res.add(point);
|
res.add(point);
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ListDataSet readData(String path, double Elow) {
|
public static ListDataSet readData(String path, double Elow) {
|
||||||
SpectrumDataAdapter factory = new SpectrumDataAdapter();
|
SpectrumDataAdapter factory = new SpectrumDataAdapter();
|
||||||
ListDataSet res = factory.buildEmptyDataSet("");
|
ListDataSet res = new ListDataSet(factory.getFormat());
|
||||||
File file = GlobalContext.instance().io().getFile(path);
|
File file = GlobalContext.instance().io().getFile(path);
|
||||||
double x;
|
double x;
|
||||||
int count;
|
int count;
|
||||||
int time;
|
int time;
|
||||||
|
|
||||||
setDefault(Locale.ENGLISH);
|
setDefault(Locale.ENGLISH);
|
||||||
|
|
||||||
Scanner sc;
|
Scanner sc;
|
||||||
try {
|
try {
|
||||||
sc = new Scanner(file);
|
sc = new Scanner(file);
|
||||||
} catch (FileNotFoundException ex) {
|
} catch (FileNotFoundException ex) {
|
||||||
throw new RuntimeException(ex.getMessage());
|
throw new RuntimeException(ex.getMessage());
|
||||||
}
|
}
|
||||||
double dummy;
|
double dummy;
|
||||||
// sc.skip("\\D*");
|
// sc.skip("\\D*");
|
||||||
while (!sc.hasNextDouble()) {
|
while (!sc.hasNextDouble()) {
|
||||||
sc.nextLine();
|
sc.nextLine();
|
||||||
}
|
}
|
||||||
while (sc.hasNextDouble() | sc.hasNextInt()) {
|
while (sc.hasNextDouble() | sc.hasNextInt()) {
|
||||||
/*Надо сделать, чтобы считывало весь файл*/
|
/*Надо сделать, чтобы считывало весь файл*/
|
||||||
x = sc.nextDouble();
|
x = sc.nextDouble();
|
||||||
|
|
||||||
dummy = sc.nextInt();
|
dummy = sc.nextInt();
|
||||||
|
|
||||||
time = sc.nextInt();
|
time = sc.nextInt();
|
||||||
|
|
||||||
dummy = sc.nextInt();
|
dummy = sc.nextInt();
|
||||||
dummy = sc.nextInt();
|
dummy = sc.nextInt();
|
||||||
dummy = sc.nextInt();
|
dummy = sc.nextInt();
|
||||||
dummy = sc.nextInt();
|
dummy = sc.nextInt();
|
||||||
dummy = sc.nextInt();
|
dummy = sc.nextInt();
|
||||||
dummy = sc.nextInt();
|
dummy = sc.nextInt();
|
||||||
|
|
||||||
count = sc.nextInt();
|
count = sc.nextInt();
|
||||||
// count = (int) (count / (1 - 2.8E-6 / time * count));
|
// count = (int) (count / (1 - 2.8E-6 / time * count));
|
||||||
|
|
||||||
dummy = sc.nextInt();
|
dummy = sc.nextInt();
|
||||||
dummy = sc.nextDouble();
|
dummy = sc.nextDouble();
|
||||||
dummy = sc.nextDouble();
|
dummy = sc.nextDouble();
|
||||||
dummy = sc.nextDouble();
|
dummy = sc.nextDouble();
|
||||||
DataPoint point = factory.buildSpectrumDataPoint(x, count, time);
|
DataPoint point = factory.buildSpectrumDataPoint(x, count, time);
|
||||||
if (x >= Elow) {
|
if (x >= Elow) {
|
||||||
res.add(point);
|
res.add(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ListDataSet readDataAsGun(String path, double Elow) {
|
public static ListDataSet readDataAsGun(String path, double Elow) {
|
||||||
SpectrumDataAdapter factory = new SpectrumDataAdapter();
|
SpectrumDataAdapter factory = new SpectrumDataAdapter();
|
||||||
ListDataSet res = factory.buildEmptyDataSet("");
|
ListDataSet res = new ListDataSet(factory.getFormat());
|
||||||
File file = GlobalContext.instance().io().getFile(path);
|
File file = GlobalContext.instance().io().getFile(path);
|
||||||
double x;
|
double x;
|
||||||
long count;
|
long count;
|
||||||
int time;
|
int time;
|
||||||
|
|
||||||
setDefault(Locale.ENGLISH);
|
setDefault(Locale.ENGLISH);
|
||||||
|
|
||||||
Scanner sc;
|
Scanner sc;
|
||||||
try {
|
try {
|
||||||
sc = new Scanner(file);
|
sc = new Scanner(file);
|
||||||
} catch (FileNotFoundException ex) {
|
} catch (FileNotFoundException ex) {
|
||||||
throw new RuntimeException(ex.getMessage());
|
throw new RuntimeException(ex.getMessage());
|
||||||
}
|
}
|
||||||
double dummy;
|
double dummy;
|
||||||
sc.nextLine();
|
sc.nextLine();
|
||||||
while (sc.hasNext()) {
|
while (sc.hasNext()) {
|
||||||
x = sc.nextDouble();
|
x = sc.nextDouble();
|
||||||
time = sc.nextInt();
|
time = sc.nextInt();
|
||||||
dummy = sc.nextInt();
|
dummy = sc.nextInt();
|
||||||
count = sc.nextLong();
|
count = sc.nextLong();
|
||||||
dummy = sc.nextDouble();
|
dummy = sc.nextDouble();
|
||||||
dummy = sc.nextDouble();
|
dummy = sc.nextDouble();
|
||||||
DataPoint point = factory.buildSpectrumDataPoint(x, count, time);
|
DataPoint point = factory.buildSpectrumDataPoint(x, count, time);
|
||||||
if (x > Elow) {
|
if (x > Elow) {
|
||||||
res.add(point);
|
res.add(point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ListDataSet readSpectrumData(String path){
|
public static ListDataSet readSpectrumData(String path){
|
||||||
SpectrumDataAdapter factory = new SpectrumDataAdapter();
|
SpectrumDataAdapter factory = new SpectrumDataAdapter();
|
||||||
ListDataSet res = factory.buildEmptyDataSet("");
|
ListDataSet res = new ListDataSet(factory.getFormat());
|
||||||
File file = GlobalContext.instance().io().getFile(path);
|
File file = GlobalContext.instance().io().getFile(path);
|
||||||
double x;
|
double x;
|
||||||
double count;
|
double count;
|
||||||
double time;
|
double time;
|
||||||
|
|
||||||
double cr;
|
double cr;
|
||||||
double crErr;
|
double crErr;
|
||||||
|
|
||||||
setDefault(Locale.ENGLISH);
|
setDefault(Locale.ENGLISH);
|
||||||
|
|
||||||
Scanner sc;
|
Scanner sc;
|
||||||
try {
|
try {
|
||||||
sc = new Scanner(file);
|
sc = new Scanner(file);
|
||||||
} catch (FileNotFoundException ex) {
|
} catch (FileNotFoundException ex) {
|
||||||
throw new RuntimeException(ex.getMessage());
|
throw new RuntimeException(ex.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sc.hasNext()) {
|
while (sc.hasNext()) {
|
||||||
String line = sc.nextLine();
|
String line = sc.nextLine();
|
||||||
if (!line.startsWith("*")) {
|
if (!line.startsWith("*")) {
|
||||||
Scanner lsc = new Scanner(line);
|
Scanner lsc = new Scanner(line);
|
||||||
if (lsc.hasNextDouble() || lsc.hasNextInt()) {
|
if (lsc.hasNextDouble() || lsc.hasNextInt()) {
|
||||||
|
|
||||||
x = lsc.nextDouble();
|
x = lsc.nextDouble();
|
||||||
lsc.next();
|
lsc.next();
|
||||||
time = lsc.nextDouble();
|
time = lsc.nextDouble();
|
||||||
lsc.next();
|
lsc.next();
|
||||||
lsc.next();
|
lsc.next();
|
||||||
count = lsc.nextDouble();
|
count = lsc.nextDouble();
|
||||||
cr = lsc.nextDouble();
|
cr = lsc.nextDouble();
|
||||||
crErr = lsc.nextDouble();
|
crErr = lsc.nextDouble();
|
||||||
DataPoint point = factory.buildSpectrumDataPoint(x, (long)(cr*time), crErr*time, time);
|
DataPoint point = factory.buildSpectrumDataPoint(x, (long)(cr*time), crErr*time, time);
|
||||||
// SpectrumDataPoint point = new SpectrumDataPoint(x, (long) count, time);
|
// SpectrumDataPoint point = new SpectrumDataPoint(x, (long) count, time);
|
||||||
|
|
||||||
res.add(point);
|
res.add(point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ import static java.lang.Math.sqrt;
|
|||||||
import org.apache.commons.math3.analysis.UnivariateFunction;
|
import org.apache.commons.math3.analysis.UnivariateFunction;
|
||||||
import static java.lang.Math.abs;
|
import static java.lang.Math.abs;
|
||||||
import static java.lang.Math.abs;
|
import static java.lang.Math.abs;
|
||||||
|
import static java.lang.Math.abs;
|
||||||
|
import static java.lang.Math.abs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -19,7 +19,7 @@ import hep.dataforge.description.ActionDescriptor;
|
|||||||
import hep.dataforge.description.DescriptorUtils;
|
import hep.dataforge.description.DescriptorUtils;
|
||||||
import hep.dataforge.exceptions.NameNotFoundException;
|
import hep.dataforge.exceptions.NameNotFoundException;
|
||||||
import hep.dataforge.fx.LogOutputPane;
|
import hep.dataforge.fx.LogOutputPane;
|
||||||
import hep.dataforge.fx.MetaEditorComponent;
|
import hep.dataforge.fx.MetaEditor;
|
||||||
import hep.dataforge.fx.MetaTreeItem;
|
import hep.dataforge.fx.MetaTreeItem;
|
||||||
import hep.dataforge.io.IOManager;
|
import hep.dataforge.io.IOManager;
|
||||||
import hep.dataforge.io.MetaFileReader;
|
import hep.dataforge.io.MetaFileReader;
|
||||||
@ -67,8 +67,8 @@ public class NumassWorkbenchController implements Initializable, StagePaneHolder
|
|||||||
Context parentContext;
|
Context parentContext;
|
||||||
MetaFactory<Context> contextFactory;
|
MetaFactory<Context> contextFactory;
|
||||||
|
|
||||||
List<MetaEditorComponent> actionEditors = new ArrayList<>();
|
List<MetaEditor> actionEditors = new ArrayList<>();
|
||||||
MetaEditorComponent dataEditor;
|
MetaEditor dataEditor;
|
||||||
Context context;
|
Context context;
|
||||||
|
|
||||||
Configuration dataConfig;
|
Configuration dataConfig;
|
||||||
@ -187,7 +187,7 @@ public class NumassWorkbenchController implements Initializable, StagePaneHolder
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
MetaEditorComponent contextEditor = MetaEditorComponent.build(contextValues, null);
|
MetaEditor contextEditor = MetaEditor.build(contextValues, null);
|
||||||
|
|
||||||
contextEditor.geTable().setShowRoot(false);
|
contextEditor.geTable().setShowRoot(false);
|
||||||
contextPane.setContent(contextEditor);
|
contextPane.setContent(contextEditor);
|
||||||
@ -203,7 +203,7 @@ public class NumassWorkbenchController implements Initializable, StagePaneHolder
|
|||||||
} else {
|
} else {
|
||||||
dataConfig = new Configuration("data");
|
dataConfig = new Configuration("data");
|
||||||
}
|
}
|
||||||
dataEditor = MetaEditorComponent.build(dataConfig,
|
dataEditor = MetaEditor.build(dataConfig,
|
||||||
DescriptorUtils.buildDescriptor(
|
DescriptorUtils.buildDescriptor(
|
||||||
DescriptorUtils.findAnnotatedElement("method::hep.dataforge.data.DataManager.read")
|
DescriptorUtils.findAnnotatedElement("method::hep.dataforge.data.DataManager.read")
|
||||||
));
|
));
|
||||||
@ -219,7 +219,7 @@ public class NumassWorkbenchController implements Initializable, StagePaneHolder
|
|||||||
actionsConfig.setNode("action", actions);
|
actionsConfig.setNode("action", actions);
|
||||||
|
|
||||||
for (Configuration action : actions) {
|
for (Configuration action : actions) {
|
||||||
MetaEditorComponent actionEditor = new MetaEditorComponent();
|
MetaEditor actionEditor = new MetaEditor();
|
||||||
|
|
||||||
MetaTreeItem rootItem = new MetaTreeItem(action, getDescriptorForAction(action.getString("type")));
|
MetaTreeItem rootItem = new MetaTreeItem(action, getDescriptorForAction(action.getString("type")));
|
||||||
//Freezing actions names
|
//Freezing actions names
|
||||||
|
@ -34,10 +34,14 @@ import java.net.URL;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -172,13 +176,26 @@ public class NumassDataLoader extends AbstractLoader implements BinaryLoader<Env
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LocalDateTime startTime = envelope.meta().get
|
// LocalDateTime startTime = envelope.meta().get
|
||||||
RawNMPoint raw = new RawNMPoint(envelope.meta().getDouble("external_meta.HV1_value", 0),
|
double u = envelope.meta().getDouble("external_meta.HV1_value", 0);
|
||||||
|
RawNMPoint raw = new RawNMPoint(u, u,
|
||||||
events,
|
events,
|
||||||
envelope.meta().getValue("external_meta.acquisition_time").doubleValue());
|
envelope.meta().getValue("external_meta.acquisition_time").doubleValue(),
|
||||||
|
readTime(envelope.meta()));
|
||||||
|
|
||||||
return transformation.apply(raw);
|
return transformation.apply(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Instant readTime(Meta meta) {
|
||||||
|
if (meta.hasValue("date") && meta.hasValue("start_time")) {
|
||||||
|
LocalDate date = LocalDate.parse(meta.getString("date"), DateTimeFormatter.ofPattern("uuuu.MM.dd"));
|
||||||
|
LocalTime time = LocalTime.parse(meta.getString("start_time"));
|
||||||
|
LocalDateTime dateTime = LocalDateTime.of(date, time);
|
||||||
|
return dateTime.toInstant(ZoneOffset.UTC);
|
||||||
|
} else {
|
||||||
|
return Instant.EPOCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read numass point without transformation
|
* Read numass point without transformation
|
||||||
*
|
*
|
||||||
@ -244,7 +261,7 @@ public class NumassDataLoader extends AbstractLoader implements BinaryLoader<Env
|
|||||||
this.getPoints().stream().forEachOrdered((point) -> {
|
this.getPoints().stream().forEachOrdered((point) -> {
|
||||||
res.add(readPoint(point));
|
res.add(readPoint(point));
|
||||||
});
|
});
|
||||||
// res.sort((NMPoint o1, NMPoint o2) -> o1.getAbsouteTime().compareTo(o2.getAbsouteTime()));
|
// res.sort((NMPoint o1, NMPoint o2) -> o1.getStartTime().compareTo(o2.getStartTime()));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,13 +304,17 @@ public class NumassDataLoader extends AbstractLoader implements BinaryLoader<Env
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Instant startTime() {
|
public Instant startTime() {
|
||||||
//TODO read meta
|
|
||||||
return null;
|
return null;
|
||||||
|
// List<NMPoint> points = getNMPoints();
|
||||||
|
// if(!points.isEmpty()){
|
||||||
|
// return points.get(0).getStartTime();
|
||||||
|
// } else {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
//TODO read from annotation
|
return meta().getString("description", "").replace("\\n", "\n");
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,12 +85,12 @@ public class NumassStorage extends FileStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NumassStorage buildRemoteNumassRoot(String uri) throws StorageException {
|
public static NumassStorage buildNumassRoot(String uri, boolean readOnly, boolean monitor) throws StorageException {
|
||||||
try {
|
try {
|
||||||
Meta meta = new MetaBuilder("storage")
|
Meta meta = new MetaBuilder("storage")
|
||||||
.setValue("type", "file.numass")
|
.setValue("type", "file.numass")
|
||||||
.setValue("readOnly", true)
|
.setValue("readOnly", readOnly)
|
||||||
.setValue("monitor", false);
|
.setValue("monitor", monitor);
|
||||||
return new NumassStorage(VFSUtils.getRemoteFile(uri), meta);
|
return new NumassStorage(VFSUtils.getRemoteFile(uri), meta);
|
||||||
} catch (FileSystemException ex) {
|
} catch (FileSystemException ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
|
@ -5,7 +5,7 @@ if (!hasProperty('mainClass')) {
|
|||||||
}
|
}
|
||||||
mainClassName = mainClass
|
mainClassName = mainClass
|
||||||
|
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
|
|
||||||
description = "The viewer for numass data"
|
description = "The viewer for numass data"
|
||||||
|
|
||||||
|
@ -5,11 +5,12 @@
|
|||||||
*/
|
*/
|
||||||
package inr.numass.viewer;
|
package inr.numass.viewer;
|
||||||
|
|
||||||
|
import javafx.concurrent.Task;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexander Nozik <altavir@gmail.com>
|
* @author Alexander Nozik <altavir@gmail.com>
|
||||||
*/
|
*/
|
||||||
public interface ProgressUpdateCallback {
|
public interface FXTaskManager {
|
||||||
void setProgressText(String text);
|
void postTask(Task task);
|
||||||
void setProgress(double progress);
|
|
||||||
}
|
}
|
@ -24,10 +24,13 @@ import java.io.File;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
|
import javafx.concurrent.Task;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
@ -48,6 +51,7 @@ import javafx.scene.control.TreeTableView;
|
|||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import javafx.stage.DirectoryChooser;
|
import javafx.stage.DirectoryChooser;
|
||||||
|
import javafx.util.Duration;
|
||||||
import javafx.util.Pair;
|
import javafx.util.Pair;
|
||||||
import org.controlsfx.control.StatusBar;
|
import org.controlsfx.control.StatusBar;
|
||||||
|
|
||||||
@ -56,7 +60,7 @@ import org.controlsfx.control.StatusBar;
|
|||||||
*
|
*
|
||||||
* @author Alexander Nozik
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
public class MainViewerController implements Initializable, ProgressUpdateCallback {
|
public class MainViewerController implements Initializable, FXTaskManager {
|
||||||
|
|
||||||
public static MainViewerController build(NumassStorage root) {
|
public static MainViewerController build(NumassStorage root) {
|
||||||
MainViewerController res = new MainViewerController();
|
MainViewerController res = new MainViewerController();
|
||||||
@ -111,14 +115,14 @@ public class MainViewerController implements Initializable, ProgressUpdateCallba
|
|||||||
// TabPaneDetacher.create().makeTabsDetachable(tabPane);
|
// TabPaneDetacher.create().makeTabsDetachable(tabPane);
|
||||||
ConsoleDude.hookStdStreams(consoleArea);
|
ConsoleDude.hookStdStreams(consoleArea);
|
||||||
|
|
||||||
SplitPaneDividerSlider slider = new SplitPaneDividerSlider(consoleSplit, 0, SplitPaneDividerSlider.Direction.DOWN);
|
SplitPaneDividerSlider slider = new SplitPaneDividerSlider(consoleSplit, 0,
|
||||||
|
SplitPaneDividerSlider.Direction.DOWN, Duration.seconds(1));
|
||||||
|
|
||||||
consoleButton.selectedProperty().addListener((ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) -> {
|
slider.aimContentVisibleProperty().bindBidirectional(consoleButton.selectedProperty());
|
||||||
slider.setAimContentVisible(t1);
|
|
||||||
});
|
consoleButton.setSelected(false);
|
||||||
slider.setAimContentVisible(false);
|
|
||||||
|
|
||||||
loadRemoteButton.setDisable(true);
|
loadRemoteButton.setDisable(true);
|
||||||
|
mspController.setCallback(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@ -131,39 +135,72 @@ public class MainViewerController implements Initializable, ProgressUpdateCallba
|
|||||||
final File rootDir = chooser.showDialog(((Node) event.getTarget()).getScene().getWindow());
|
final File rootDir = chooser.showDialog(((Node) event.getTarget()).getScene().getWindow());
|
||||||
|
|
||||||
if (rootDir != null) {
|
if (rootDir != null) {
|
||||||
storagePathLabel.setText("Storage: " + rootDir.getAbsolutePath());
|
Task dirLoadTask = new DirectoryLoadTask(rootDir.toURI().toString());
|
||||||
setProgress(-1);
|
postTask(dirLoadTask);
|
||||||
setProgressText("Building numass storage tree...");
|
Viewer.runTask(dirLoadTask);
|
||||||
new Thread(() -> {
|
}
|
||||||
try {
|
|
||||||
|
|
||||||
NumassStorage root = NumassStorage.buildLocalNumassRoot(rootDir, true);
|
}
|
||||||
setRootStorage(root);
|
|
||||||
|
|
||||||
} catch (StorageException ex) {
|
private class DirectoryLoadTask extends Task<Void> {
|
||||||
setProgress(0);
|
|
||||||
setProgressText("Failed to load local storage");
|
private final String uri;
|
||||||
Logger.getLogger(MainViewerController.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
}
|
public DirectoryLoadTask(String uri) {
|
||||||
}, "loader thread").start();
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void call() throws Exception {
|
||||||
|
updateTitle("Load storage ("+uri+")");
|
||||||
|
updateProgress(-1, 1);
|
||||||
|
updateMessage("Building numass storage tree...");
|
||||||
|
try {
|
||||||
|
NumassStorage root = NumassStorage.buildNumassRoot(uri, true, false);
|
||||||
|
setRootStorage(root);
|
||||||
|
Platform.runLater(() -> storagePathLabel.setText("Storage: " + uri));
|
||||||
|
} catch (StorageException ex) {
|
||||||
|
updateProgress(0, 1);
|
||||||
|
updateMessage("Failed to load storage " + uri);
|
||||||
|
Logger.getLogger(MainViewerController.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setProgress(double progress) {
|
@SuppressWarnings("unchecked")
|
||||||
Platform.runLater(() -> statusBar.setProgress(progress));
|
public void postTask(Task task) {
|
||||||
//statusBar.setProgress(progress);
|
task.setOnRunning((e) -> {
|
||||||
}
|
statusBar.setText(task.getTitle() + ": " + task.getMessage());
|
||||||
|
statusBar.setProgress(task.getProgress());
|
||||||
|
});
|
||||||
|
|
||||||
|
task.messageProperty().addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
|
||||||
|
statusBar.setText(task.getTitle() + ": " +newValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
task.progressProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
|
||||||
|
statusBar.setProgress(newValue.doubleValue());
|
||||||
|
});
|
||||||
|
|
||||||
@Override
|
task.setOnSucceeded((e) -> {
|
||||||
public void setProgressText(String text) {
|
statusBar.setText(task.getTitle() + ": Complete");
|
||||||
Platform.runLater(() -> statusBar.setText(text));
|
statusBar.setProgress(0);
|
||||||
//statusBar.setText(text);
|
});
|
||||||
|
|
||||||
|
task.setOnFailed((e) -> {
|
||||||
|
statusBar.setText(task.getTitle() + ": Failed");
|
||||||
|
statusBar.setProgress(0);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRootStorage(NumassStorage root) {
|
public void setRootStorage(NumassStorage root) {
|
||||||
fillNumassStorageData(root);
|
Task fillTask = new StorageDataFillTask(root);
|
||||||
|
postTask(fillTask);
|
||||||
|
Viewer.runTask(fillTask);
|
||||||
|
|
||||||
if (mspController != null) {
|
if (mspController != null) {
|
||||||
mspController.setCallback(this);
|
mspController.setCallback(this);
|
||||||
mspController.fillMspData(root);
|
mspController.fillMspData(root);
|
||||||
@ -176,28 +213,46 @@ public class MainViewerController implements Initializable, ProgressUpdateCallba
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillNumassStorageData(NumassStorage rootStorage) {
|
private class StorageDataFillTask extends Task<Void> {
|
||||||
if (rootStorage != null) {
|
|
||||||
setProgress(-1);
|
|
||||||
setProgressText("Loading numass storage tree...");
|
|
||||||
|
|
||||||
|
private final NumassStorage root;
|
||||||
|
|
||||||
|
public StorageDataFillTask(NumassStorage root) {
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void call() throws Exception {
|
||||||
|
updateTitle("Fill data to UI ("+root.getName()+")");
|
||||||
|
this.updateProgress(-1, 1);
|
||||||
|
this.updateMessage("Loading numass storage tree...");
|
||||||
|
|
||||||
|
Task treeBuilderTask = new NumassLoaderTreeBuilder(numassLoaderDataTree, root, (NumassData loader) -> {
|
||||||
|
NumassLoaderViewComponent component = new NumassLoaderViewComponent();
|
||||||
|
component.loadData(loader);
|
||||||
|
component.setCallback(MainViewerController.this);
|
||||||
|
numassLoaderViewContainer.getChildren().clear();
|
||||||
|
numassLoaderViewContainer.getChildren().add(component);
|
||||||
|
AnchorPane.setTopAnchor(component, 0.0);
|
||||||
|
AnchorPane.setRightAnchor(component, 0.0);
|
||||||
|
AnchorPane.setLeftAnchor(component, 0.0);
|
||||||
|
AnchorPane.setBottomAnchor(component, 0.0);
|
||||||
|
numassLoaderViewContainer.requestLayout();
|
||||||
|
});
|
||||||
|
postTask(treeBuilderTask);
|
||||||
|
Viewer.runTask(treeBuilderTask);
|
||||||
try {
|
try {
|
||||||
new NumassLoaderTreeBuilder(MainViewerController.this).fillTree(numassLoaderDataTree, rootStorage, (NumassData loader) -> {
|
treeBuilderTask.get();
|
||||||
NumassLoaderViewComponent component = NumassLoaderViewComponent.build(loader);
|
this.updateProgress(0, 1);
|
||||||
numassLoaderViewContainer.getChildren().clear();
|
this.updateMessage("Numass storage tree loaded.");
|
||||||
numassLoaderViewContainer.getChildren().add(component);
|
this.succeeded();
|
||||||
AnchorPane.setTopAnchor(component, 0.0);
|
} catch (InterruptedException | ExecutionException ex) {
|
||||||
AnchorPane.setRightAnchor(component, 0.0);
|
this.failed();
|
||||||
AnchorPane.setLeftAnchor(component, 0.0);
|
|
||||||
AnchorPane.setBottomAnchor(component, 0.0);
|
|
||||||
numassLoaderViewContainer.requestLayout();
|
|
||||||
});
|
|
||||||
setProgress(0);
|
|
||||||
setProgressText("Loaded");
|
|
||||||
} catch (StorageException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@ -230,7 +285,7 @@ public class MainViewerController implements Initializable, ProgressUpdateCallba
|
|||||||
dialog.getDialogPane().setContent(grid);
|
dialog.getDialogPane().setContent(grid);
|
||||||
|
|
||||||
// Request focus on the username field by default.
|
// Request focus on the username field by default.
|
||||||
Platform.runLater(() -> storageText.requestFocus());
|
storageText.requestFocus();
|
||||||
|
|
||||||
// Convert the result to a username-password-pair when the login button is clicked.
|
// Convert the result to a username-password-pair when the login button is clicked.
|
||||||
dialog.setResultConverter(dialogButton -> {
|
dialog.setResultConverter(dialogButton -> {
|
||||||
@ -243,21 +298,9 @@ public class MainViewerController implements Initializable, ProgressUpdateCallba
|
|||||||
Optional<Pair<String, String>> result = dialog.showAndWait();
|
Optional<Pair<String, String>> result = dialog.showAndWait();
|
||||||
|
|
||||||
if (result.isPresent()) {
|
if (result.isPresent()) {
|
||||||
storagePathLabel.setText("Storage: remote/" + result.get().getValue());
|
Task dirLoadTask = new DirectoryLoadTask(result.get().getKey() + "/data/" + result.get().getValue());
|
||||||
|
postTask(dirLoadTask);
|
||||||
setProgress(-1);
|
Viewer.runTask(dirLoadTask);
|
||||||
setProgressText("Building numass storage tree...");
|
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
|
||||||
NumassStorage root = NumassStorage.buildRemoteNumassRoot(result.get().getKey() + "/data/" + result.get().getValue());
|
|
||||||
setRootStorage(root);
|
|
||||||
} catch (StorageException ex) {
|
|
||||||
setProgress(0);
|
|
||||||
setProgressText("Failed to load remote storage");
|
|
||||||
Logger.getLogger(MainViewerController.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
}, "loader thread").start();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ package inr.numass.viewer;
|
|||||||
*/
|
*/
|
||||||
import hep.dataforge.data.DataPoint;
|
import hep.dataforge.data.DataPoint;
|
||||||
import hep.dataforge.data.MapDataPoint;
|
import hep.dataforge.data.MapDataPoint;
|
||||||
import hep.dataforge.exceptions.StorageException;
|
|
||||||
import hep.dataforge.storage.api.PointLoader;
|
import hep.dataforge.storage.api.PointLoader;
|
||||||
import hep.dataforge.storage.api.Storage;
|
import hep.dataforge.storage.api.Storage;
|
||||||
import hep.dataforge.values.Value;
|
import hep.dataforge.values.Value;
|
||||||
@ -35,6 +34,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
|
import javafx.concurrent.Task;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
@ -58,7 +58,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
*/
|
*/
|
||||||
public class MspViewController implements Initializable {
|
public class MspViewController implements Initializable {
|
||||||
|
|
||||||
private ProgressUpdateCallback callback;
|
private FXTaskManager callback;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private AnchorPane mspPlotPane;
|
private AnchorPane mspPlotPane;
|
||||||
@ -119,86 +119,105 @@ public class MspViewController implements Initializable {
|
|||||||
|
|
||||||
public void fillMspData(Storage rootStorage) {
|
public void fillMspData(Storage rootStorage) {
|
||||||
if (rootStorage != null) {
|
if (rootStorage != null) {
|
||||||
try {
|
MspDataFillTask fillTask = new MspDataFillTask(rootStorage);
|
||||||
List<DataPoint> mspData = getMspData(rootStorage);
|
if(callback!= null){
|
||||||
Map<String, XYSeries> series = new HashMap<>();
|
callback.postTask(fillTask);
|
||||||
|
}
|
||||||
|
Viewer.runTask(fillTask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (DataPoint point : mspData) {
|
private class MspDataFillTask extends Task<Void> {
|
||||||
for (String name : point.names()) {
|
|
||||||
if (!name.equals("timestamp")) {
|
private final Storage storage;
|
||||||
if (!series.containsKey(name)) {
|
|
||||||
series.put(name, new XYSeries(name));
|
public MspDataFillTask(Storage storage) {
|
||||||
}
|
this.storage = storage;
|
||||||
long time = point.getValue("timestamp").timeValue().toEpochMilli();
|
}
|
||||||
double value = point.getDouble(name);
|
|
||||||
if (value > 0) {
|
@Override
|
||||||
series.get(name).add(time, value);
|
protected Void call() throws Exception {
|
||||||
}
|
updateTitle("Fill msp data ("+storage.getName()+")");
|
||||||
|
MspDataLoadTask loadTask = new MspDataLoadTask(storage);
|
||||||
|
if(callback!= null){
|
||||||
|
callback.postTask(loadTask);
|
||||||
|
}
|
||||||
|
Viewer.runTask(loadTask);
|
||||||
|
List<DataPoint> mspData = loadTask.get();
|
||||||
|
Map<String, XYSeries> series = new HashMap<>();
|
||||||
|
|
||||||
|
for (DataPoint point : mspData) {
|
||||||
|
for (String name : point.names()) {
|
||||||
|
if (!name.equals("timestamp")) {
|
||||||
|
if (!series.containsKey(name)) {
|
||||||
|
series.put(name, new XYSeries(name));
|
||||||
|
}
|
||||||
|
long time = point.getValue("timestamp").timeValue().toEpochMilli();
|
||||||
|
double value = point.getDouble(name);
|
||||||
|
if (value > 0) {
|
||||||
|
series.get(name).add(time, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
XYSeriesCollection mspSeriesCollection = new XYSeriesCollection();
|
|
||||||
List<String> names = new ArrayList<>(series.keySet());
|
|
||||||
names.sort((String o1, String o2) -> {
|
|
||||||
try {
|
|
||||||
return Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
|
|
||||||
} catch (Exception ex) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
for (String name : names) {
|
|
||||||
mspSeriesCollection.addSeries(series.get(name));
|
|
||||||
}
|
|
||||||
updateMspPane(mspSeriesCollection);
|
|
||||||
} catch (StorageException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
}
|
||||||
}
|
XYSeriesCollection mspSeriesCollection = new XYSeriesCollection();
|
||||||
}
|
List<String> names = new ArrayList<>(series.keySet());
|
||||||
|
names.sort((String o1, String o2) -> {
|
||||||
private List<DataPoint> getMspData(Storage storage) throws StorageException {
|
try {
|
||||||
List<DataPoint> mspData = new ArrayList<>();
|
return Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
|
||||||
DataPoint last = null;
|
|
||||||
for (String loaderName : storage.loaders().keySet()) {
|
|
||||||
if (loaderName.startsWith("msp")) {
|
|
||||||
try (PointLoader mspLoader = (PointLoader) storage.getLoader(loaderName)) {
|
|
||||||
mspLoader.open();
|
|
||||||
updateProgress("Loading mass spectrometer data from " + mspLoader.getName());
|
|
||||||
updateProgress(-1);
|
|
||||||
for (DataPoint dp : mspLoader.asDataSet()) {
|
|
||||||
mspData.add(dp);
|
|
||||||
last = dp;
|
|
||||||
}
|
|
||||||
if (last != null) {
|
|
||||||
mspData.add(terminatorPoint(last));
|
|
||||||
}
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
LoggerFactory.getLogger(getClass()).error("Can't read msp loader data", ex);
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for (String name : names) {
|
||||||
|
mspSeriesCollection.addSeries(series.get(name));
|
||||||
|
}
|
||||||
|
updateMspPane(mspSeriesCollection);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MspDataLoadTask extends Task<List<DataPoint>> {
|
||||||
|
|
||||||
|
private final Storage storage;
|
||||||
|
|
||||||
|
public MspDataLoadTask(Storage storage) {
|
||||||
|
this.storage = storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<DataPoint> call() throws Exception {
|
||||||
|
updateTitle("Load msp data ("+storage.getName()+")");
|
||||||
|
List<DataPoint> mspData = new ArrayList<>();
|
||||||
|
DataPoint last = null;
|
||||||
|
for (String loaderName : storage.loaders().keySet()) {
|
||||||
|
if (loaderName.startsWith("msp")) {
|
||||||
|
try (PointLoader mspLoader = (PointLoader) storage.getLoader(loaderName)) {
|
||||||
|
mspLoader.open();
|
||||||
|
updateMessage("Loading mass spectrometer data from " + mspLoader.getName());
|
||||||
|
updateProgress(-1, 1);
|
||||||
|
for (DataPoint dp : mspLoader.asDataSet()) {
|
||||||
|
mspData.add(dp);
|
||||||
|
last = dp;
|
||||||
|
}
|
||||||
|
if (last != null) {
|
||||||
|
mspData.add(terminatorPoint(last));
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LoggerFactory.getLogger(getClass()).error("Can't read msp loader data", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// for (String shelfName : storage.shelves().keySet()) {
|
|
||||||
// mspData.addAll(getMspData(storage.getShelf(shelfName)));
|
|
||||||
// }
|
|
||||||
|
|
||||||
updateProgress("Loading msp data finished");
|
updateMessage("Loading msp data finished");
|
||||||
updateProgress(0);
|
updateProgress(0, 1);
|
||||||
return mspData;
|
return mspData;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateProgress(String progress) {
|
public void setCallback(FXTaskManager callback) {
|
||||||
if (callback != null) {
|
|
||||||
callback.setProgressText(progress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateProgress(double progress) {
|
|
||||||
if (callback != null) {
|
|
||||||
callback.setProgress(progress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCallback(ProgressUpdateCallback callback) {
|
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import java.util.List;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.concurrent.Task;
|
||||||
import javafx.scene.control.TreeItem;
|
import javafx.scene.control.TreeItem;
|
||||||
import javafx.scene.control.TreeTableColumn;
|
import javafx.scene.control.TreeTableColumn;
|
||||||
import javafx.scene.control.TreeTableView;
|
import javafx.scene.control.TreeTableView;
|
||||||
@ -35,19 +36,23 @@ import javafx.scene.input.MouseEvent;
|
|||||||
*
|
*
|
||||||
* @author darksnake
|
* @author darksnake
|
||||||
*/
|
*/
|
||||||
public class NumassLoaderTreeBuilder implements ProgressUpdateCallback {
|
public class NumassLoaderTreeBuilder extends Task<Void> {
|
||||||
|
|
||||||
ProgressUpdateCallback callback;
|
private final TreeTableView<TreeItemValue> numassLoaderDataTree;
|
||||||
|
private final NumassStorage rootStorage;
|
||||||
|
private final Consumer<NumassData> numassViewBuilder;
|
||||||
|
|
||||||
public NumassLoaderTreeBuilder(ProgressUpdateCallback callback) {
|
public NumassLoaderTreeBuilder(TreeTableView<TreeItemValue> numassLoaderDataTree, NumassStorage rootStorage, Consumer<NumassData> numassViewBuilder) {
|
||||||
this.callback = callback;
|
this.numassLoaderDataTree = numassLoaderDataTree;
|
||||||
|
this.rootStorage = rootStorage;
|
||||||
|
this.numassViewBuilder = numassViewBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NumassLoaderTreeBuilder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void fillTree(TreeTableView<TreeItemValue> numassLoaderDataTree, NumassStorage rootStorage, Consumer<NumassData> numassViewBuilder) throws StorageException {
|
@Override
|
||||||
|
protected Void call() throws Exception {
|
||||||
|
updateTitle("Load numass data ("+rootStorage.getName()+")");
|
||||||
TreeItem<TreeItemValue> root = buildNode(rootStorage, numassViewBuilder);
|
TreeItem<TreeItemValue> root = buildNode(rootStorage, numassViewBuilder);
|
||||||
root.setExpanded(true);
|
root.setExpanded(true);
|
||||||
|
|
||||||
@ -81,6 +86,7 @@ public class NumassLoaderTreeBuilder implements ProgressUpdateCallback {
|
|||||||
numassLoaderTimeColumn.setVisible(false);
|
numassLoaderTimeColumn.setVisible(false);
|
||||||
nummassLoaderDescriptionColumn.setVisible(false);
|
nummassLoaderDescriptionColumn.setVisible(false);
|
||||||
});
|
});
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TreeItem<TreeItemValue> buildNode(NumassStorage storage, Consumer<NumassData> numassViewBuilder) throws StorageException {
|
private TreeItem<TreeItemValue> buildNode(NumassStorage storage, Consumer<NumassData> numassViewBuilder) throws StorageException {
|
||||||
@ -99,12 +105,12 @@ public class NumassLoaderTreeBuilder implements ProgressUpdateCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setProgressText("Building storage " + storage.getName());
|
updateMessage("Building storage " + storage.getName());
|
||||||
|
|
||||||
double counter = 0;
|
double counter = 0;
|
||||||
for (Loader loader : storage.loaders().values()) {
|
for (Loader loader : storage.loaders().values()) {
|
||||||
setProgressText("Building numass data loader " + loader.getName());
|
updateMessage("Building numass data loader " + loader.getName());
|
||||||
setProgress(counter / storage.loaders().size());
|
updateProgress(counter, storage.loaders().size());
|
||||||
|
|
||||||
if (loader instanceof NumassData) {
|
if (loader instanceof NumassData) {
|
||||||
NumassData numassLoader = (NumassData) loader;
|
NumassData numassLoader = (NumassData) loader;
|
||||||
@ -126,8 +132,8 @@ public class NumassLoaderTreeBuilder implements ProgressUpdateCallback {
|
|||||||
//adding legacy data files
|
//adding legacy data files
|
||||||
counter = 0;
|
counter = 0;
|
||||||
for (NumassData legacyDat : storage.legacyFiles()) {
|
for (NumassData legacyDat : storage.legacyFiles()) {
|
||||||
setProgressText("Loading numass DAT file " + legacyDat.getName());
|
updateMessage("Loading numass DAT file " + legacyDat.getName());
|
||||||
setProgress(counter / storage.loaders().size());
|
updateProgress(counter, storage.loaders().size());
|
||||||
TreeItem<TreeItemValue> numassLoaderTreeItem = new TreeItem<>(buildValue(legacyDat));
|
TreeItem<TreeItemValue> numassLoaderTreeItem = new TreeItem<>(buildValue(legacyDat));
|
||||||
list.add(numassLoaderTreeItem);
|
list.add(numassLoaderTreeItem);
|
||||||
counter++;
|
counter++;
|
||||||
@ -197,7 +203,7 @@ public class NumassLoaderTreeBuilder implements ProgressUpdateCallback {
|
|||||||
@Override
|
@Override
|
||||||
public String getTime() {
|
public String getTime() {
|
||||||
Instant startTime = loader.startTime();
|
Instant startTime = loader.startTime();
|
||||||
if (startTime == null) {
|
if (startTime == null || startTime.equals(Instant.EPOCH)) {
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
return loader.startTime().toString();
|
return loader.startTime().toString();
|
||||||
@ -211,20 +217,6 @@ public class NumassLoaderTreeBuilder implements ProgressUpdateCallback {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setProgress(double progress) {
|
|
||||||
if (callback != null) {
|
|
||||||
callback.setProgress(progress);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setProgressText(String text) {
|
|
||||||
if (callback != null) {
|
|
||||||
callback.setProgressText(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface TreeItemValue {
|
public interface TreeItemValue {
|
||||||
|
|
||||||
public String getName();
|
public String getName();
|
||||||
|
@ -22,6 +22,7 @@ package inr.numass.viewer;
|
|||||||
*/
|
*/
|
||||||
import hep.dataforge.data.DataPoint;
|
import hep.dataforge.data.DataPoint;
|
||||||
import hep.dataforge.data.DataSet;
|
import hep.dataforge.data.DataSet;
|
||||||
|
import hep.dataforge.data.ListDataSet;
|
||||||
import hep.dataforge.data.MapDataPoint;
|
import hep.dataforge.data.MapDataPoint;
|
||||||
import hep.dataforge.io.ColumnedDataWriter;
|
import hep.dataforge.io.ColumnedDataWriter;
|
||||||
import hep.dataforge.meta.Meta;
|
import hep.dataforge.meta.Meta;
|
||||||
@ -41,11 +42,16 @@ import java.net.URL;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import javafx.application.Platform;
|
||||||
import javafx.beans.property.BooleanProperty;
|
import javafx.beans.property.BooleanProperty;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.beans.value.ObservableValue;
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.concurrent.Task;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
@ -63,6 +69,8 @@ import javafx.stage.FileChooser;
|
|||||||
import javafx.util.converter.NumberStringConverter;
|
import javafx.util.converter.NumberStringConverter;
|
||||||
import org.controlsfx.control.CheckListView;
|
import org.controlsfx.control.CheckListView;
|
||||||
import org.controlsfx.control.RangeSlider;
|
import org.controlsfx.control.RangeSlider;
|
||||||
|
import org.controlsfx.validation.ValidationSupport;
|
||||||
|
import org.controlsfx.validation.Validator;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@ -73,21 +81,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
*/
|
*/
|
||||||
public class NumassLoaderViewComponent extends AnchorPane implements Initializable {
|
public class NumassLoaderViewComponent extends AnchorPane implements Initializable {
|
||||||
|
|
||||||
public static NumassLoaderViewComponent build(NumassData numassLoader) {
|
private FXTaskManager callback;
|
||||||
NumassLoaderViewComponent component = new NumassLoaderViewComponent();
|
|
||||||
FXMLLoader loader = new FXMLLoader(component.getClass().getResource("/fxml/NumassLoaderView.fxml"));
|
|
||||||
|
|
||||||
loader.setRoot(component);
|
|
||||||
loader.setController(component);
|
|
||||||
|
|
||||||
try {
|
|
||||||
loader.load();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
component.setData(numassLoader);
|
|
||||||
return component;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger logger = LoggerFactory.getLogger(NumassLoaderViewComponent.class);
|
Logger logger = LoggerFactory.getLogger(NumassLoaderViewComponent.class);
|
||||||
private NumassData data;
|
private NumassData data;
|
||||||
@ -120,15 +114,29 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
|
|||||||
private CheckBox detectorNormalizeSwitch;
|
private CheckBox detectorNormalizeSwitch;
|
||||||
@FXML
|
@FXML
|
||||||
private Button detectorDataExportButton;
|
private Button detectorDataExportButton;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TextField lowChannelField;
|
private TextField lowChannelField;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TextField upChannelField;
|
private TextField upChannelField;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private RangeSlider channelSlider;
|
private RangeSlider channelSlider;
|
||||||
|
@FXML
|
||||||
|
private Button spectrumExportButton;
|
||||||
|
@FXML
|
||||||
|
private TextField dTimeField;
|
||||||
|
|
||||||
|
public NumassLoaderViewComponent() {
|
||||||
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/NumassLoaderView.fxml"));
|
||||||
|
|
||||||
|
loader.setRoot(this);
|
||||||
|
loader.setController(this);
|
||||||
|
|
||||||
|
try {
|
||||||
|
loader.load();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the controller class.
|
* Initializes the controller class.
|
||||||
@ -138,9 +146,8 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL url, ResourceBundle rb) {
|
public void initialize(URL url, ResourceBundle rb) {
|
||||||
// TODO
|
detectorBinningSelector.setItems(FXCollections.observableArrayList(1, 2, 5, 10, 20, 50));
|
||||||
detectorBinningSelector.setItems(FXCollections.observableArrayList(1, 2, 5, 10, 20));
|
detectorBinningSelector.getSelectionModel().select(4);
|
||||||
detectorBinningSelector.getSelectionModel().selectLast();
|
|
||||||
detectorNormalizeSwitch.setSelected(true);
|
detectorNormalizeSwitch.setSelected(true);
|
||||||
|
|
||||||
detectorPointListView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
detectorPointListView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
|
||||||
@ -148,36 +155,83 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
|
|||||||
lowChannelField.textProperty().bindBidirectional(channelSlider.lowValueProperty(), new NumberStringConverter());
|
lowChannelField.textProperty().bindBidirectional(channelSlider.lowValueProperty(), new NumberStringConverter());
|
||||||
upChannelField.textProperty().bindBidirectional(channelSlider.highValueProperty(), new NumberStringConverter());
|
upChannelField.textProperty().bindBidirectional(channelSlider.highValueProperty(), new NumberStringConverter());
|
||||||
|
|
||||||
channelSlider.setLowValue(300);
|
channelSlider.setHighValue(1900d);
|
||||||
channelSlider.setHighValue(1900);
|
channelSlider.setLowValue(300d);
|
||||||
|
|
||||||
ChangeListener<? super Number> rangeChangeListener = (ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
|
ChangeListener<? super Number> rangeChangeListener = (ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
|
||||||
updateSpectrumPane();
|
updateSpectrumPane(points);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dTimeField.textProperty().addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
|
||||||
|
updateSpectrumPane(points);
|
||||||
|
});
|
||||||
|
|
||||||
channelSlider.lowValueProperty().addListener(rangeChangeListener);
|
channelSlider.lowValueProperty().addListener(rangeChangeListener);
|
||||||
channelSlider.highValueProperty().addListener(rangeChangeListener);
|
channelSlider.highValueProperty().addListener(rangeChangeListener);
|
||||||
|
|
||||||
|
ValidationSupport validationSupport = new ValidationSupport();
|
||||||
|
Predicate<String> isNumber = (String t) -> {
|
||||||
|
try {
|
||||||
|
Double.parseDouble(t);
|
||||||
|
return true;
|
||||||
|
} catch (NumberFormatException | NullPointerException ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
validationSupport.registerValidator(dTimeField, Validator.createPredicateValidator(isNumber, "Must be number"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public NumassData getData() {
|
public NumassData getData() {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setData(NumassData data) {
|
public void setCallback(FXTaskManager callback) {
|
||||||
|
this.callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadData(NumassData data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
points = data.getNMPoints();
|
LoadPointsTask task = new LoadPointsTask(data);
|
||||||
//setup detector data
|
if (callback != null) {
|
||||||
setupDetectorPane(points);
|
callback.postTask(task);
|
||||||
//setup spectrum plot
|
}
|
||||||
updateSpectrumPane();
|
Viewer.runTask(task);
|
||||||
|
try {
|
||||||
setupInfo(data);
|
this.points = task.get();
|
||||||
|
} catch (InterruptedException |ExecutionException ex) {
|
||||||
detectorTab.getTabPane().getSelectionModel().select(detectorTab);
|
logger.error("Can't load spectrum data points", ex);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.error("The data model is null");
|
logger.error("The data model is null");
|
||||||
}
|
}
|
||||||
|
detectorTab.getTabPane().getSelectionModel().select(detectorTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LoadPointsTask extends Task<List<NMPoint>> {
|
||||||
|
|
||||||
|
private final NumassData loader;
|
||||||
|
|
||||||
|
public LoadPointsTask(NumassData loader) {
|
||||||
|
this.loader = loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<NMPoint> call() throws Exception {
|
||||||
|
updateTitle("Load numass data (" + loader.getName() + ")");
|
||||||
|
List<NMPoint> points = loader.getNMPoints();
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
//setup detector data
|
||||||
|
setupDetectorPane(points);
|
||||||
|
//setup spectrum plot
|
||||||
|
updateSpectrumPane(points);
|
||||||
|
|
||||||
|
setupInfo(data);
|
||||||
|
});
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -192,11 +246,11 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
|
|||||||
detectorBinningSelector.getSelectionModel().selectedItemProperty()
|
detectorBinningSelector.getSelectionModel().selectedItemProperty()
|
||||||
.addListener((ObservableValue<? extends Integer> observable, Integer oldValue, Integer newValue) -> {
|
.addListener((ObservableValue<? extends Integer> observable, Integer oldValue, Integer newValue) -> {
|
||||||
boolean norm = detectorNormalizeSwitch.isSelected();
|
boolean norm = detectorNormalizeSwitch.isSelected();
|
||||||
updateDetectorPane(fillDetectorData(points, newValue, norm));
|
updateDetectorPane(fillDetectorData(NumassLoaderViewComponent.this.points, newValue, norm));
|
||||||
});
|
});
|
||||||
detectorNormalizeSwitch.selectedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
|
detectorNormalizeSwitch.selectedProperty().addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
|
||||||
int bin = detectorBinningSelector.getValue();
|
int bin = detectorBinningSelector.getValue();
|
||||||
updateDetectorPane(fillDetectorData(points, bin, newValue));
|
updateDetectorPane(fillDetectorData(NumassLoaderViewComponent.this.points, bin, newValue));
|
||||||
});
|
});
|
||||||
detectorDataExportButton.setDisable(false);
|
detectorDataExportButton.setDisable(false);
|
||||||
}
|
}
|
||||||
@ -204,10 +258,10 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
|
|||||||
private void setupInfo(NumassData loader) {
|
private void setupInfo(NumassData loader) {
|
||||||
Meta info = loader.getInfo();
|
Meta info = loader.getInfo();
|
||||||
infoTextBox.setText(new JSONMetaWriter().writeString(info, null).
|
infoTextBox.setText(new JSONMetaWriter().writeString(info, null).
|
||||||
replace("\\r", "\r").replace("\\n", "\n"));
|
replace("\\r", "\r\t").replace("\\n", "\n\t"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSpectrumPane() {
|
private void updateSpectrumPane(List<NMPoint> points) {
|
||||||
if (spectrumPlotFrame == null) {
|
if (spectrumPlotFrame == null) {
|
||||||
Meta plotMeta = new MetaBuilder("plot")
|
Meta plotMeta = new MetaBuilder("plot")
|
||||||
.setValue("xAxis.axisTitle", "U")
|
.setValue("xAxis.axisTitle", "U")
|
||||||
@ -230,73 +284,66 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
|
|||||||
spectrumData.clear();
|
spectrumData.clear();
|
||||||
} else {
|
} else {
|
||||||
spectrumData.fillData(points.stream()
|
spectrumData.fillData(points.stream()
|
||||||
.<DataPoint>map((NMPoint point) -> getSpectrumPoint(point, lowChannel, highChannel))
|
.<DataPoint>map((NMPoint point) -> getSpectrumPoint(point, lowChannel, highChannel, getDTime()))
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataPoint getSpectrumPoint(NMPoint point, int lowChannel, int highChannel) {
|
private double getDTime() {
|
||||||
double u = point.getUread();
|
try {
|
||||||
double count = point.getCountInWindow(lowChannel, highChannel);
|
return Double.parseDouble(dTimeField.getText()) * 1e-6;
|
||||||
double time = point.getLength();
|
} catch (NumberFormatException ex) {
|
||||||
double err = Math.sqrt(count);
|
return 0;
|
||||||
return new MapDataPoint(new String[]{"x", "y", "yErr"}, u, count / time, err / time);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataPoint getSpectrumPoint(NMPoint point, int lowChannel, int upChannel, double dTime) {
|
||||||
|
double u = point.getUread();
|
||||||
|
return new MapDataPoint(new String[]{"x", "y", "yErr"}, u,
|
||||||
|
point.getCountRate(lowChannel, upChannel, dTime),
|
||||||
|
point.getCountRateErr(lowChannel, upChannel, dTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
// private void setupSpectrumPane(List<NMPoint> points, int lowChannel, int upChannel) {
|
|
||||||
// updateSpectrumData(fillSpectrumData(points, (point) -> point.getCountInWindow(lowChannel, upChannel)));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// private void updateSpectrumData(XYIntervalSeriesCollection data) {
|
|
||||||
// spectrumPlotPane.getChildren().clear();
|
|
||||||
// NumberAxis xAxis = new NumberAxis("HV");
|
|
||||||
// NumberAxis yAxis = new NumberAxis("count rate");
|
|
||||||
//
|
|
||||||
// xAxis.setAutoRangeIncludesZero(false);
|
|
||||||
// yAxis.setAutoRangeIncludesZero(false);
|
|
||||||
//
|
|
||||||
// XYPlot plot = new XYPlot(data, xAxis, yAxis, new XYErrorRenderer());
|
|
||||||
// JFreeChart spectrumPlot = new JFreeChart("spectrum", plot);
|
|
||||||
// displayPlot(spectrumPlotPane, spectrumPlot);
|
|
||||||
// }
|
|
||||||
/**
|
/**
|
||||||
* update detector pane with new data
|
* update detector pane with new data
|
||||||
*/
|
*/
|
||||||
private void updateDetectorPane(List<XYPlottable> detectorData) {
|
private void updateDetectorPane(List<XYPlottable> detectorData) {
|
||||||
if (detectorData == null) {
|
Platform.runLater(() -> {
|
||||||
throw new IllegalArgumentException("Detector data not defined");
|
if (detectorData == null) {
|
||||||
}
|
throw new IllegalArgumentException("Detector data not defined");
|
||||||
|
}
|
||||||
|
|
||||||
detectorPointListView.getItems().clear();//removing all checkboxes
|
detectorPointListView.getItems().clear();//removing all checkboxes
|
||||||
detectorPlotPane.getChildren().clear();//removing plot
|
detectorPlotPane.getChildren().clear();//removing plot
|
||||||
|
|
||||||
Meta frameMeta = new MetaBuilder("frame")
|
Meta frameMeta = new MetaBuilder("frame")
|
||||||
.setValue("frameTitle", "Detector response plot")
|
.setValue("frameTitle", "Detector response plot")
|
||||||
.setNode(new MetaBuilder("xAxis")
|
.setNode(new MetaBuilder("xAxis")
|
||||||
.setValue("axisTitle", "ADC")
|
.setValue("axisTitle", "ADC")
|
||||||
.setValue("axisUnits", "channels")
|
.setValue("axisUnits", "channels")
|
||||||
.build())
|
.build())
|
||||||
.setNode(new MetaBuilder("yAxis")
|
.setNode(new MetaBuilder("yAxis")
|
||||||
.setValue("axisTitle", "count rate")
|
.setValue("axisTitle", "count rate")
|
||||||
.setValue("axisUnits", "Hz")
|
.setValue("axisUnits", "Hz")
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
detectorPlotFrame = new JFreeChartFrame("detectorSignal", frameMeta, detectorPlotPane);
|
detectorPlotFrame = new JFreeChartFrame("detectorSignal", frameMeta, detectorPlotPane);
|
||||||
|
|
||||||
for (XYPlottable pl : detectorData) {
|
for (XYPlottable pl : detectorData) {
|
||||||
detectorPlotFrame.add(pl);
|
detectorPlotFrame.add(pl);
|
||||||
detectorPointListView.getItems().add(pl.getName());
|
detectorPointListView.getItems().add(pl.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (String plotName : detectorPointListView.getItems()) {
|
for (String plotName : detectorPointListView.getItems()) {
|
||||||
BooleanProperty checked = detectorPointListView.getItemBooleanProperty(plotName);
|
BooleanProperty checked = detectorPointListView.getItemBooleanProperty(plotName);
|
||||||
checked.set(true);
|
checked.set(true);
|
||||||
|
|
||||||
checked.addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
|
checked.addListener((ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) -> {
|
||||||
detectorPlotFrame.get(plotName).getConfig().setValue("visible", newValue);
|
detectorPlotFrame.get(plotName).getConfig().setValue("visible", newValue);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<XYPlottable> fillDetectorData(List<NMPoint> points, int binning, boolean normalize) {
|
private List<XYPlottable> fillDetectorData(List<NMPoint> points, int binning, boolean normalize) {
|
||||||
@ -317,27 +364,6 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
|
|||||||
return plottables;
|
return plottables;
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Fill spectrum with custom window calculator
|
|
||||||
// *
|
|
||||||
// * @param points
|
|
||||||
// * @param lowerBoundCalculator
|
|
||||||
// * @param upperBoundCalculator
|
|
||||||
// * @return
|
|
||||||
// */
|
|
||||||
// private XYIntervalSeriesCollection fillSpectrumData(List<NMPoint> points, Function<NMPoint, Number> calculator) {
|
|
||||||
// XYIntervalSeriesCollection collection = new XYIntervalSeriesCollection();
|
|
||||||
// XYIntervalSeries ser = new XYIntervalSeries("spectrum");
|
|
||||||
// for (NMPoint point : points) {
|
|
||||||
// double u = point.getUread();
|
|
||||||
// double count = calculator.apply(point).doubleValue();
|
|
||||||
// double time = point.getLength();
|
|
||||||
// double err = Math.sqrt(count);
|
|
||||||
// ser.add(u, u, u, count / time, (count - err) / time, (count + err) / time);
|
|
||||||
// }
|
|
||||||
// collection.addSeries(ser);
|
|
||||||
// return collection;
|
|
||||||
// }
|
|
||||||
@FXML
|
@FXML
|
||||||
private void checkAllAction(ActionEvent event) {
|
private void checkAllAction(ActionEvent event) {
|
||||||
detectorPointListView.getCheckModel().checkAll();
|
detectorPointListView.getCheckModel().checkAll();
|
||||||
@ -362,6 +388,49 @@ public class NumassLoaderViewComponent extends AnchorPane implements Initializab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void onSpectrumExportClick(ActionEvent event) {
|
||||||
|
if (points != null && !points.isEmpty()) {
|
||||||
|
FileChooser fileChooser = new FileChooser();
|
||||||
|
fileChooser.setTitle("Choose text export destination");
|
||||||
|
fileChooser.setInitialFileName(data.getName() + "_spectrum.out");
|
||||||
|
File destination = fileChooser.showSaveDialog(spectrumPlotPane.getScene().getWindow());
|
||||||
|
if (destination != null) {
|
||||||
|
String[] names = new String[]{"Uset", "Uread", "Length", "Total", "Window", "CR", "CRerr", "Timestamp"};
|
||||||
|
int loChannel = (int) channelSlider.getLowValue();
|
||||||
|
int upChannel = (int) channelSlider.getHighValue();
|
||||||
|
double dTime = getDTime();
|
||||||
|
ListDataSet spectrumDataSet = new ListDataSet(names);
|
||||||
|
|
||||||
|
for (NMPoint point : points) {
|
||||||
|
spectrumDataSet.add(new MapDataPoint(names, new Object[]{
|
||||||
|
point.getUset(),
|
||||||
|
point.getUread(),
|
||||||
|
point.getLength(),
|
||||||
|
point.getEventsCount(),
|
||||||
|
point.getCountInWindow(loChannel, upChannel),
|
||||||
|
point.getCountRate(loChannel, upChannel, dTime),
|
||||||
|
point.getCountRateErr(loChannel, upChannel, dTime),
|
||||||
|
point.getStartTime()
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String comment = String.format("Numass data viewer spectrum data export for %s%n"
|
||||||
|
+ "Window: (%d, %d)%n"
|
||||||
|
+ "Dead time per event: %g%n",
|
||||||
|
data.getName(), loChannel, upChannel, dTime);
|
||||||
|
|
||||||
|
ColumnedDataWriter
|
||||||
|
.writeDataSet(destination, spectrumDataSet, comment, false);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
LoggerFactory.getLogger(getClass()).error("Destination file not found", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onExportButtonClick(ActionEvent event) {
|
private void onExportButtonClick(ActionEvent event) {
|
||||||
FileChooser fileChooser = new FileChooser();
|
FileChooser fileChooser = new FileChooser();
|
||||||
fileChooser.setTitle("Choose text export destination");
|
fileChooser.setTitle("Choose text export destination");
|
||||||
|
@ -13,54 +13,55 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package inr.numass.viewer;
|
package inr.numass.viewer;
|
||||||
|
|
||||||
import hep.dataforge.storage.commons.StoragePlugin;
|
import hep.dataforge.storage.commons.StoragePlugin;
|
||||||
import inr.numass.storage.NumassDataLoader;
|
import inr.numass.storage.NumassDataLoader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author darksnake
|
* @author darksnake
|
||||||
*/
|
*/
|
||||||
public class TestDirectoryViewer extends Application {
|
public class TestDirectoryViewer extends Application {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage primaryStage) throws IOException {
|
public void start(Stage primaryStage) throws IOException {
|
||||||
new StoragePlugin().startGlobal();
|
new StoragePlugin().startGlobal();
|
||||||
|
|
||||||
NumassDataLoader reader = NumassDataLoader.fromLocalDir(null, new File("C:\\Users\\darksnake\\Dropbox\\PlayGround\\data-test\\20150703143643_1\\"));
|
NumassDataLoader reader = NumassDataLoader.fromLocalDir(null, new File("C:\\Users\\darksnake\\Dropbox\\PlayGround\\data-test\\20150703143643_1\\"));
|
||||||
// NumassLoader reader = NumassLoader.fromZip(null, new File("C:\\Users\\darksnake\\Dropbox\\PlayGround\\data-test\\20150703143643_1.zip"));
|
// NumassLoader reader = NumassLoader.fromZip(null, new File("C:\\Users\\darksnake\\Dropbox\\PlayGround\\data-test\\20150703143643_1.zip"));
|
||||||
|
|
||||||
NumassLoaderViewComponent comp = NumassLoaderViewComponent.build(reader);
|
NumassLoaderViewComponent comp = new NumassLoaderViewComponent();
|
||||||
// FXMLLoader fxml = new FXMLLoader(getClass().getResource("/fxml/DirectoryViewer.fxml"));
|
comp.loadData(reader);
|
||||||
//
|
// FXMLLoader fxml = new FXMLLoader(getClass().getResource("/fxml/DirectoryViewer.fxml"));
|
||||||
// Parent parent = fxml.load();
|
//
|
||||||
//
|
// Parent parent = fxml.load();
|
||||||
// NumassLoaderViewController controller = fxml.getController();
|
//
|
||||||
//
|
// NumassLoaderViewController controller = fxml.getController();
|
||||||
// controller.setModel(reader);
|
//
|
||||||
|
// controller.setModel(reader);
|
||||||
Scene scene = new Scene(comp, 800, 600);
|
|
||||||
|
Scene scene = new Scene(comp, 800, 600);
|
||||||
primaryStage.setTitle("Detector Visualisation test");
|
|
||||||
primaryStage.setScene(scene);
|
primaryStage.setTitle("Detector Visualisation test");
|
||||||
primaryStage.setMinHeight(600);
|
primaryStage.setScene(scene);
|
||||||
primaryStage.setMinWidth(800);
|
primaryStage.setMinHeight(600);
|
||||||
// primaryStage.setResizable(false);
|
primaryStage.setMinWidth(800);
|
||||||
|
// primaryStage.setResizable(false);
|
||||||
primaryStage.show();
|
|
||||||
}
|
primaryStage.show();
|
||||||
|
}
|
||||||
/**
|
|
||||||
* @param args the command line arguments
|
/**
|
||||||
*/
|
* @param args the command line arguments
|
||||||
public static void main(String[] args) {
|
*/
|
||||||
launch(args);
|
public static void main(String[] args) {
|
||||||
}
|
launch(args);
|
||||||
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@ import hep.dataforge.exceptions.StorageException;
|
|||||||
import hep.dataforge.storage.commons.StoragePlugin;
|
import hep.dataforge.storage.commons.StoragePlugin;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
|
import javafx.concurrent.Task;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Parent;
|
import javafx.scene.Parent;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
@ -34,7 +35,6 @@ public class Viewer extends Application {
|
|||||||
public void start(Stage primaryStage) throws StorageException, IOException {
|
public void start(Stage primaryStage) throws StorageException, IOException {
|
||||||
new StoragePlugin().startGlobal();
|
new StoragePlugin().startGlobal();
|
||||||
|
|
||||||
|
|
||||||
FXMLLoader fxml = new FXMLLoader(getClass().getResource("/fxml/MainView.fxml"));
|
FXMLLoader fxml = new FXMLLoader(getClass().getResource("/fxml/MainView.fxml"));
|
||||||
|
|
||||||
Parent parent = fxml.load();
|
Parent parent = fxml.load();
|
||||||
@ -52,8 +52,12 @@ public class Viewer extends Application {
|
|||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void runTask(Task task) {
|
||||||
|
Thread th = new Thread(task);
|
||||||
|
th.setDaemon(true);
|
||||||
|
th.start();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param args the command line arguments
|
* @param args the command line arguments
|
||||||
*/
|
*/
|
||||||
|
@ -16,6 +16,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
<?import org.controlsfx.control.textfield.*?>
|
||||||
<?import org.controlsfx.control.*?>
|
<?import org.controlsfx.control.*?>
|
||||||
<?import javafx.geometry.*?>
|
<?import javafx.geometry.*?>
|
||||||
<?import java.lang.*?>
|
<?import java.lang.*?>
|
||||||
@ -24,9 +25,9 @@ limitations under the License.
|
|||||||
<?import javafx.scene.control.*?>
|
<?import javafx.scene.control.*?>
|
||||||
<?import javafx.scene.layout.*?>
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
<fx:root id="AnchorPane" prefHeight="400.0" prefWidth="600.0" type="AnchorPane" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
|
<fx:root id="AnchorPane" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" type="AnchorPane" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<children>
|
<children>
|
||||||
<TabPane layoutX="200.0" layoutY="100.0" prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
<TabPane layoutX="200.0" layoutY="100.0" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
<tabs>
|
<tabs>
|
||||||
<Tab text="Info">
|
<Tab text="Info">
|
||||||
<content>
|
<content>
|
||||||
@ -41,15 +42,10 @@ limitations under the License.
|
|||||||
<content>
|
<content>
|
||||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
||||||
<children>
|
<children>
|
||||||
<BorderPane layoutX="200.0" layoutY="86.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
<SplitPane dividerPositions="0.5" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
<center>
|
<items>
|
||||||
<AnchorPane fx:id="detectorPlotPane" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER" />
|
<AnchorPane fx:id="detectorPlotPane" minHeight="300.0" minWidth="300.0" prefHeight="200.0" prefWidth="200.0" />
|
||||||
</center>
|
<VBox fx:id="detectorOptionsPane" maxWidth="250.0" prefWidth="200.0" spacing="2.0" style="-fx-border-color: blue;">
|
||||||
<right>
|
|
||||||
<VBox fx:id="detectorOptionsPane" minWidth="-Infinity" prefWidth="200.0" spacing="2.0" style="-fx-border-color: blue;" BorderPane.alignment="CENTER">
|
|
||||||
<BorderPane.margin>
|
|
||||||
<Insets />
|
|
||||||
</BorderPane.margin>
|
|
||||||
<children>
|
<children>
|
||||||
<Label text="Channels per bin">
|
<Label text="Channels per bin">
|
||||||
<VBox.margin>
|
<VBox.margin>
|
||||||
@ -78,8 +74,8 @@ limitations under the License.
|
|||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
|
<Insets bottom="2.0" left="2.0" right="2.0" top="2.0" />
|
||||||
</padding></VBox>
|
</padding></VBox>
|
||||||
</right>
|
</items>
|
||||||
</BorderPane>
|
</SplitPane>
|
||||||
</children>
|
</children>
|
||||||
</AnchorPane>
|
</AnchorPane>
|
||||||
</content>
|
</content>
|
||||||
@ -91,7 +87,7 @@ limitations under the License.
|
|||||||
</Tab>
|
</Tab>
|
||||||
<Tab fx:id="spectrumTab" text="Spectrum">
|
<Tab fx:id="spectrumTab" text="Spectrum">
|
||||||
<content>
|
<content>
|
||||||
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
|
<AnchorPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0">
|
||||||
<children>
|
<children>
|
||||||
<BorderPane prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
<BorderPane prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
<center>
|
<center>
|
||||||
@ -100,9 +96,32 @@ limitations under the License.
|
|||||||
<top>
|
<top>
|
||||||
<ToolBar prefHeight="40.0" prefWidth="200.0" BorderPane.alignment="CENTER">
|
<ToolBar prefHeight="40.0" prefWidth="200.0" BorderPane.alignment="CENTER">
|
||||||
<items>
|
<items>
|
||||||
<TextField fx:id="lowChannelField" prefWidth="60.0" />
|
<VBox>
|
||||||
<RangeSlider fx:id="channelSlider" accessibleRole="SLIDER" highValue="1900.0" lowValue="300.0" majorTickUnit="500.0" max="4000.0" minorTickCount="5" prefHeight="38.0" prefWidth="336.0" showTickLabels="true" showTickMarks="true" />
|
<children>
|
||||||
<TextField fx:id="upChannelField" prefWidth="60.0" />
|
<Label text="Lo channel" />
|
||||||
|
<TextField fx:id="lowChannelField" prefWidth="60.0" />
|
||||||
|
</children>
|
||||||
|
</VBox>
|
||||||
|
<RangeSlider fx:id="channelSlider" accessibleRole="SLIDER" highValue="1900.0" lowValue="300.0" majorTickUnit="500.0" max="4000.0" minorTickCount="5" prefHeight="38.0" prefWidth="276.0" showTickLabels="true" showTickMarks="true">
|
||||||
|
<padding>
|
||||||
|
<Insets left="10.0" right="10.0" />
|
||||||
|
</padding></RangeSlider>
|
||||||
|
<VBox>
|
||||||
|
<children>
|
||||||
|
<Label text="Up channel" />
|
||||||
|
<TextField fx:id="upChannelField" prefWidth="60.0" />
|
||||||
|
</children>
|
||||||
|
</VBox>
|
||||||
|
<Separator orientation="VERTICAL" />
|
||||||
|
<VBox>
|
||||||
|
<children>
|
||||||
|
<Label text="Dead time (us)" />
|
||||||
|
<TextField fx:id="dTimeField" prefHeight="25.0" prefWidth="0.0" text="7.2" />
|
||||||
|
</children>
|
||||||
|
</VBox>
|
||||||
|
<Separator orientation="VERTICAL" />
|
||||||
|
<Pane minWidth="0.0" HBox.hgrow="ALWAYS" />
|
||||||
|
<Button fx:id="spectrumExportButton" mnemonicParsing="false" onAction="#onSpectrumExportClick" text="Export" />
|
||||||
</items>
|
</items>
|
||||||
</ToolBar>
|
</ToolBar>
|
||||||
</top>
|
</top>
|
||||||
|
Loading…
Reference in New Issue
Block a user