diff --git a/numass-core/src/main/java/inr/numass/data/api/MetaBlock.java b/numass-core/src/main/java/inr/numass/data/api/MetaBlock.java new file mode 100644 index 00000000..1c809246 --- /dev/null +++ b/numass-core/src/main/java/inr/numass/data/api/MetaBlock.java @@ -0,0 +1,46 @@ +package inr.numass.data.api; + +import java.time.Duration; +import java.time.Instant; +import java.util.*; +import java.util.stream.Stream; + +/** + * A block constructed from a set of other blocks. Internal blocks are not necessary subsequent. Blocks are automatically sorted. + * Created by darksnake on 16.07.2017. + */ +public class MetaBlock implements NumassBlock { + private SortedSet blocks = new TreeSet<>(Comparator.comparing(NumassBlock::getStartTime)); + + public MetaBlock(NumassBlock... blocks) { + this.blocks.addAll(Arrays.asList(blocks)); + } + + public MetaBlock(Collection blocks) { + this.blocks.addAll(blocks); + } + + @Override + public Instant getStartTime() { + return blocks.first().getStartTime(); + } + + @Override + public Duration getLength() { + return Duration.ofNanos(blocks.stream().mapToLong(block -> block.getLength().toNanos()).sum()); + } + + @Override + public Stream getEvents() { + return blocks.stream() + .sorted(Comparator.comparing(NumassBlock::getStartTime)) + .flatMap(NumassBlock::getEvents); + } + + @Override + public Stream getFrames() { + return blocks.stream() + .sorted(Comparator.comparing(NumassBlock::getStartTime)) + .flatMap(NumassBlock::getFrames); + } +} diff --git a/numass-core/src/main/java/inr/numass/data/api/NumassBlock.java b/numass-core/src/main/java/inr/numass/data/api/NumassBlock.java new file mode 100644 index 00000000..eafc97d6 --- /dev/null +++ b/numass-core/src/main/java/inr/numass/data/api/NumassBlock.java @@ -0,0 +1,36 @@ +package inr.numass.data.api; + +import java.time.Duration; +import java.time.Instant; +import java.util.stream.Stream; + +/** + * A single continuous measurement block. The block can contain both isolated events and signal frames + *

+ * Created by darksnake on 06-Jul-17. + */ +public interface NumassBlock { + /** + * The absolute start time of the block + * @return + */ + Instant getStartTime(); + + /** + * The length of the block + * @return + */ + Duration getLength(); + + /** + * Stream of isolated events. Could be empty + * @return + */ + Stream getEvents(); + + /** + * Stream of frames. Could be empty + * @return + */ + Stream getFrames(); +} diff --git a/numass-core/src/main/java/inr/numass/data/api/NumassPoint.java b/numass-core/src/main/java/inr/numass/data/api/NumassPoint.java new file mode 100644 index 00000000..c9129a00 --- /dev/null +++ b/numass-core/src/main/java/inr/numass/data/api/NumassPoint.java @@ -0,0 +1,94 @@ +package inr.numass.data.api; + +import hep.dataforge.meta.Metoid; +import hep.dataforge.values.Value; + +import java.time.Duration; +import java.time.Instant; +import java.util.stream.Stream; + +/** + * Created by darksnake on 06-Jul-17. + */ +public interface NumassPoint extends Metoid, NumassBlock { + + String START_TIME_KEY = "start"; + String LENGTH_KEY = "length"; + String HV_KEY = "voltage"; + String INDEX_KEY = "index"; + + + Stream getBlocks(); + + /** + * Get the voltage setting for the point + * + * @return + */ + default double getVoltage() { + return getMeta().getDouble(HV_KEY, 0); + } + + /** + * Get the index for this point in the set + * @return + */ + default int getIndex() { + return getMeta().getInt(INDEX_KEY, -1); + } + + /** + * Get the first block if it exists. Throw runtime exception otherwise. + * + * @return + */ + default NumassBlock getFirstBlock() { + return getBlocks().findFirst().orElseThrow(() -> new RuntimeException("The point is empty")); + } + + /** + * Get the starting time from meta or from first block + * + * @return + */ + @Override + default Instant getStartTime() { + return getMeta().optValue(START_TIME_KEY).map(Value::timeValue).orElseGet(() -> getFirstBlock().getStartTime()); + } + + /** + * Get the length key of meta or calculate length as a sum of block lengths. The latter could be a bit slow + * + * @return + */ + @Override + default Duration getLength() { + return Duration.ofNanos( + getMeta().optValue(LENGTH_KEY).map(Value::longValue) + .orElseGet(() -> getBlocks().mapToLong(it -> it.getLength().toNanos()).sum()) + ); + } + + /** + * Get all events it all blocks as a single sequence + *

+ * Some performance analysis of different stream concatenation approaches is given here: https://www.techempower.com/blog/2016/10/19/efficient-multiple-stream-concatenation-in-java/ + *

+ * + * @return + */ + @Override + default Stream getEvents() { + return getBlocks().flatMap(NumassBlock::getEvents); + } + + /** + * Get all frames in all blocks as a single sequence + * + * @return + */ + @Override + default Stream getFrames() { + return getBlocks().flatMap(NumassBlock::getFrames); + } +} diff --git a/numass-core/src/main/java/inr/numass/data/api/NumassSet.java b/numass-core/src/main/java/inr/numass/data/api/NumassSet.java new file mode 100644 index 00000000..49771ec4 --- /dev/null +++ b/numass-core/src/main/java/inr/numass/data/api/NumassSet.java @@ -0,0 +1,101 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package inr.numass.data.api; + +import hep.dataforge.meta.Metoid; +import hep.dataforge.names.Named; +import hep.dataforge.providers.Provider; +import hep.dataforge.providers.Provides; +import hep.dataforge.providers.ProvidesNames; +import hep.dataforge.tables.Table; +import hep.dataforge.values.Value; +import org.jetbrains.annotations.NotNull; + +import java.time.Instant; +import java.util.Iterator; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * A single set of numass points previously called file. + * + * @author Alexander Nozik + */ +public interface NumassSet extends Named, Metoid, Iterable, Provider { + String DESCRIPTION_KEY = "info"; + String NUMASS_POINT_PROVIDER_KEY = "point"; + + Stream getPoints(); + +// default String getDescription() { +// return getMeta().getString(DESCRIPTION_KEY, ""); +// } + + @NotNull + @Override + default Iterator iterator() { + return getPoints().iterator(); + } + + /** + * Get the first point if it exists. Throw runtime exception otherwise. + * + * @return + */ + default NumassPoint getFirstPoint() { + return getPoints().findFirst().orElseThrow(() -> new RuntimeException("The set is empty")); + } + + /** + * Get the starting time from meta or from first point + * + * @return + */ + default Instant getStartTime() { + return getMeta().optValue(NumassPoint.START_TIME_KEY).map(Value::timeValue).orElseGet(() -> getFirstPoint().getStartTime()); + } + + /** + * Find first point with given voltage + * + * @param voltage + * @return + */ + default Optional optPoint(double voltage) { + return getPoints().filter(it -> it.getVoltage() == voltage).findFirst(); + } + + /** + * List all points with given voltage + * + * @param voltage + * @return + */ + default List getPoints(double voltage) { + return getPoints().filter(it -> it.getVoltage() == voltage).collect(Collectors.toList()); + } + + @Provides(NUMASS_POINT_PROVIDER_KEY) + default Optional optPoint(String voltage) { + return optPoint(Double.parseDouble(voltage)); + } + + @Override + default String defaultTarget() { + return NUMASS_POINT_PROVIDER_KEY; + } + + @ProvidesNames(NUMASS_POINT_PROVIDER_KEY) + default Stream listPoints() { + return getPoints().map(it -> Double.toString(it.getVoltage())); + } + + default Optional getHvData() { + return Optional.empty(); + } +} diff --git a/numass-core/src/main/java/inr/numass/data/api/SignalProcessor.java b/numass-core/src/main/java/inr/numass/data/api/SignalProcessor.java new file mode 100644 index 00000000..8f2d212c --- /dev/null +++ b/numass-core/src/main/java/inr/numass/data/api/SignalProcessor.java @@ -0,0 +1,11 @@ +package inr.numass.data.api; + +import java.util.stream.Stream; + +/** + * An ancestor to numass frame analyzers + * Created by darksnake on 07.07.2017. + */ +public interface SignalProcessor { + Stream analyze(NumassFrame frame); +} diff --git a/numass-core/src/main/java/inr/numass/data/api/SimpleBlock.java b/numass-core/src/main/java/inr/numass/data/api/SimpleBlock.java new file mode 100644 index 00000000..a38ec952 --- /dev/null +++ b/numass-core/src/main/java/inr/numass/data/api/SimpleBlock.java @@ -0,0 +1,43 @@ +package inr.numass.data.api; + +import java.io.Serializable; +import java.time.Duration; +import java.time.Instant; +import java.util.List; +import java.util.stream.Stream; + +/** + * A simple in-memory implementation of block of events. No frames are allowed + * Created by darksnake on 08.07.2017. + */ +public class SimpleBlock implements NumassBlock, Serializable { + private final Instant startTime; + private final Duration length; + private final List events; + + public SimpleBlock(Instant startTime, Duration length, List events) { + this.startTime = startTime; + this.length = length; + this.events = events; + } + + @Override + public Instant getStartTime() { + return startTime; + } + + @Override + public Duration getLength() { + return length; + } + + @Override + public Stream getEvents() { + return events.stream(); + } + + @Override + public Stream getFrames() { + return Stream.empty(); + } +} diff --git a/numass-core/src/main/java/inr/numass/data/api/SimpleNumassPoint.java b/numass-core/src/main/java/inr/numass/data/api/SimpleNumassPoint.java new file mode 100644 index 00000000..3a6b52ec --- /dev/null +++ b/numass-core/src/main/java/inr/numass/data/api/SimpleNumassPoint.java @@ -0,0 +1,41 @@ +package inr.numass.data.api; + +import hep.dataforge.meta.Meta; +import hep.dataforge.meta.MetaBuilder; +import hep.dataforge.meta.MetaHolder; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Stream; + +/** + * A simple static implementation of NumassPoint + * Created by darksnake on 08.07.2017. + */ +public class SimpleNumassPoint extends MetaHolder implements NumassPoint { + private final List blocks; + + /** + * Input blocks must be sorted + * @param voltage + * @param blocks + */ + public SimpleNumassPoint(double voltage, Collection blocks) { + super(new MetaBuilder("point").setValue(HV_KEY, voltage)); + this.blocks = new ArrayList<>(blocks); + this.blocks.sort(Comparator.comparing(NumassBlock::getStartTime)); + } + + public SimpleNumassPoint(Meta meta, Collection blocks) { + super(meta); + this.blocks = new ArrayList<>(blocks); + this.blocks.sort(Comparator.comparing(NumassBlock::getStartTime)); + } + + @Override + public Stream getBlocks() { + return blocks.stream(); + } +}