Esempio n. 1
0
        /// <summary>
        /// Finds patterns of A followed immediately by B (with no other intermediate events), occurring within (strictly less than) a given time duration
        /// </summary>
        /// <typeparam name="TKey">Key type</typeparam>
        /// <typeparam name="TPayload">Payload type</typeparam>
        /// <typeparam name="TResult">Result type</typeparam>
        /// <param name="stream">Input stream</param>
        /// <param name="firstMatch">First element in pattern</param>
        /// <param name="secondMatch">Second element in pattern</param>
        /// <param name="resultSelector">Compose result tuple using matching input events</param>
        /// <param name="withinDuration">Pattern occurs within (strictly less than) given time duration</param>
        /// <returns>Pattern result stream</returns>
        public static IStreamable <TKey, TResult> FollowedByImmediate <TKey, TPayload, TResult>(
            this IStreamable <TKey, TPayload> stream,
            Expression <Func <TPayload, bool> > firstMatch,
            Expression <Func <TPayload, bool> > secondMatch,
            Expression <Func <TPayload, TPayload, TResult> > resultSelector,
            long withinDuration)
        {
            if (withinDuration >= 0)
            {
                // Set match duration
                if (withinDuration < 2)
                {
                    throw new Exception("Duration has to be at least 2 chronons");
                }
                if (withinDuration > StreamEvent.MaxSyncTime)
                {
                    throw new Exception("Duration is too large");
                }
                stream = stream.AlterEventDuration(withinDuration - 1);
            }
            // Clip the stream with itself, to make it a signal stream
            var clippedStream = stream.Multicast(xs => xs.ClipEventDuration(xs));

            // Shift the left side (first match) by one chronon, set right side (second match) to one chronon duration, join to find matches
            var result = clippedStream.Multicast(xs => xs.Where(firstMatch).ShiftEventLifetime(1).Join(xs.Where(secondMatch).AlterEventDuration(1), resultSelector));

            return(result);
        }
Esempio n. 2
0
        /// <summary>
        /// Frequency filter.
        /// </summary>
        /// <param name="source">Input stream</param>
        /// <param name="period">Period of input stream</param>
        /// <param name="window">Window size</param>
        /// <param name="filter">Filter function to select in frequencies</param>
        /// <returns>Signal after frequency filter pass.</returns>
        public static IStreamable <Empty, Signal> BandPassFilter(
            this IStreamable <Empty, Signal> source,
            long period,
            long window,
            double low,
            double high
            )
        {
            var bp = OnlineFilter.CreateBandpass(ImpulseResponse.Finite, period, low, high);

            return(source
                   .Multicast(s => s
                              .ShiftEventLifetime(window)
                              .Join(s
                                    .TumblingWindowLifetime(window, window)
                                    .Aggregate(w => new BatchAggregate <Signal>())
                                    .Select(input => FreqFilter(input, bp))
                                    .SelectMany(e => e),
                                    l => l.ts, r => r.ts,
                                    (l, r) => r
                                    )
                              )
                   .ShiftEventLifetime(-window)
                   );
        }
Esempio n. 3
0
 public static IStreamable <TKey, StructTuple <TPayload, TPayload> > ComputeSignalChangeStream <TKey, TPayload>(this IStreamable <TKey, TPayload> input)
 {
     return
         (input.Multicast(xs => xs.ShiftEventLifetime(vs => vs + 1).Join(xs.AlterEventDuration(1), (l, r) => new StructTuple <TPayload, TPayload> {
         Item1 = l, Item2 = r
     })));
 }
Esempio n. 4
0
 /// <summary>
 /// Resample signal from one frequency to a different one.
 /// </summary>
 /// <param name="source">Input stream</param>
 /// <param name="iperiod">Period of input signal stream</param>
 /// <param name="operiod">Period of output signal stream</param>
 /// <param name="offset">Offset</param>
 /// <returns>Result (output) stream in the new signal frequency</returns>
 public static IStreamable <Empty, Signal> Resample(
     this IStreamable <Empty, Signal> source,
     long iperiod,
     long operiod,
     long offset = 0)
 {
     return(source
            .Multicast(s => s.ClipEventDuration(s))
            .Multicast(s => s
                       .ShiftEventLifetime(1)
                       .Join(s
                             .AlterEventDuration(1),
                             (l, r) => new { st = l.ts, sv = l.val, et = r.ts, ev = r.val }))
            .AlterEventLifetime(t => t - iperiod, iperiod)
            .Chop(offset, operiod)
            .HoppingWindowLifetime(1, operiod)
            .AlterEventDuration(operiod)
            .Select((t, e) => new Signal(t, ((e.ev - e.sv) * (t - e.st) / (e.et - e.st) + e.sv)))
            );
 }
Esempio n. 5
0
        public static void Test()
        {
            IStreamable <Empty, SensorReading> inputStream = CreateStream();
            const int threshold = 42;

            var crossedThreshold = inputStream.Multicast(
                input =>
            {
                // Alter all events 1 sec in the future.
                var alteredForward = input.AlterEventLifetime(s => s + 1, 1);

                // Compare each event that occurs at input with the previous event.
                // Note that, this one works for strictly ordered, strictly (e.g 1 sec) regular streams.
                var filteredInputStream   = input.Where(s => s.Value > threshold);
                var filteredAlteredStream = alteredForward.Where(s => s.Value < threshold);
                return(filteredInputStream.Join(
                           filteredAlteredStream, (evt, prev) => new { evt.Time, Low = prev.Value, High = evt.Value }));
            });

            crossedThreshold.ToStreamEventObservable().ForEachAsync(r => Console.WriteLine(r)).Wait();
        }
Esempio n. 6
0
 /// <summary>
 /// Attach aggregate results back to events
 /// </summary>
 /// <param name="source">Input stream</param>
 /// <param name="sourceSelector">Selector for source stream</param>
 /// <param name="aggregate">Aggregate function</param>
 /// <param name="resultSelector">Result selector</param>
 /// <param name="window">Window size</param>
 /// <param name="period">Period</param>
 /// <param name="offset">Offset</param>
 /// <returns>Signal stream after attaching aggregate result</returns>
 public static IStreamable <TKey, TOutput> AttachAggregate <TKey, TPayload, TInput, TState, TResult, TOutput>(
     this IStreamable <TKey, TPayload> source,
     Func <IStreamable <TKey, TPayload>, IStreamable <TKey, TInput> > sourceSelector,
     Func <Window <TKey, TInput>, IAggregate <TInput, TState, TResult> > aggregate,
     Expression <Func <TPayload, TResult, TOutput> > resultSelector,
     long window,
     long period,
     long offset = 0
     )
 {
     return(source
            .Multicast(s => s
                       .ShiftEventLifetime(offset)
                       .Join(sourceSelector(s)
                             .HoppingWindowLifetime(window, period, offset)
                             .Aggregate(aggregate),
                             resultSelector)
                       .ShiftEventLifetime(-offset)
                       )
            );
 }