# Path: ripyl/streaming.py
# class SampleChunk(object):
#     ''''Sample stream object
#     
#     This represents a "chunk" of samples contained in a numpy array
#     stored in the samples attribute.
# 
#     '''
#     def __init__(self, samples, start_time, sample_period):
#         self.samples = samples
#         self.start_time = start_time
#         self.sample_period = sample_period
# 
# class StreamError(RuntimeError):
#     '''Custom exception class for edge and sample streams'''
#     pass
# 
# class ChunkExtractor(object):
#     '''Utility class that pulls arbitrarily sized chunks from a sample stream'''
#     def __init__(self, stream):
#         self.stream = stream
#         self.sample_buf = []
#         self.buf_count = 0
#         self.stream_ended = False
#         self.buf_start_time = 0.0
#         self.sample_period = 0.0
# 
#     def next_chunk(self, chunk_size=10000):
#         '''Get a new chunk of samples from the stream
# 
#         chunk_size (int)
#             The number of samples for this chunk.
# 
#         Returns a SampleChunk object. If the stream had fewer than chunk_size samples
#           remaining then the SampleChunk.samples array is sized to hold only those samples.
# 
#         Returns None if the stream has ended.
#         '''
#         if self.stream_ended:
#             return None
# 
#         while True:
#             if self.buf_count < chunk_size: # Need to get another chunk
#                 try:
#                     sc = next(self.stream)
#                     if len(self.sample_buf) == 0:
#                         self.buf_start_time = sc.start_time
#                         self.sample_period = sc.sample_period
#                     self.sample_buf.append(sc.samples)
#                     self.buf_count += len(sc.samples)
# 
#                 except StopIteration:
#                     self.stream_ended = True
# 
#             if self.stream_ended and self.buf_count < chunk_size:
#                 # Not enough samples in buffer for a full sized chunk
#                 chunk_size = self.buf_count
#                 if chunk_size == 0:
#                     break
# 
#             if self.buf_count >= chunk_size:
#                 # We have enough buffered samples to return a new chunk
#                 out_samp = np.empty(chunk_size, dtype=float)
#                 out_count = 0
#                 for b in self.sample_buf:
#                     if out_count + len(b) <= chunk_size:
#                         use_count = len(b)
#                     else:
#                         use_count = chunk_size - out_count
# 
#                     out_samp[out_count:out_count + use_count] = b[:use_count]
#                     out_count += use_count
# 
#                 out_time = self.buf_start_time
# 
#                 if self.buf_count > chunk_size:
#                     # There are unused samples remaining in the buffer
#                     # Place these at the start of the buffer for the next call to next_chunk()
#                     self.sample_buf = [self.sample_buf[-1][use_count:]]
#                     self.buf_count = len(self.sample_buf[0])
#                     self.buf_start_time = self.buf_start_time + self.sample_period * chunk_size
#                 else:
#                     self.sample_buf = []
#                     self.buf_count = 0
# 
#                 return SampleChunk(out_samp, out_time, self.sample_period)
# 
#             if self.stream_ended:
#                 break
# 
#         return None
# 
#     def next_samples(self, sample_count=10000):
#         '''Get a new set of raw samples from the stream
# 
#         sample_count (int)
#             The number of samples for the array.
# 
#         Returns a numpy array of float. If the stream had fewer than sample_count samples
#           remaining then the array is sized to hold only those samples.
# 
#         Returns None if the stream has ended.
#         '''
# 
#         sc = self.next_chunk(sample_count)
#         if sc is not None:
#             return sc.samples
#         else:
#             return None
# 
#     def buffered_chunk(self):
#         '''Get all remaining buffered samples'''
#         return self.next_chunk(self.buf_count)


from ripyl.streaming import SampleChunk, StreamError, ChunkExtractor
import numpy as np
import scipy.signal as signal
        filt = np.zeros((len(sc.samples),), dtype = np.float)
        for j in xrange(len(sc.samples)):
            sample_v = sc.samples[j]
            for _ in xrange(iterations):
                i = (sample_v - vc) / resistance # Capacitor current

                dq = i * dt # Change in charge
                q += dq
                vc = q / capacitance # New capacitor voltage
                #print('$$ i, dq, d, vc', i, dq, q, vc)
            filt[j] = vc
        yield SampleChunk(filt, sc.start_time, sc.sample_period)

        
def sum_streams(stream1, stream2):
    '''Add two sample streams together
    
    The time elements of each stream will not be aligned if they do not match.
    Instead the time values from stream1 are used for the result. The iterator
    terminates when either of the two streams ends.
    
    This is a generator function.
    
    stream1 (iterable of SampleChunk objects)
    stream2 (iterable of SampleChunk objects)
        The two sample streams to have their corresponding values added together.
        
    Yields a sample stream.
    '''


# Path: ripyl/streaming.py
# class SampleChunk(object):
#     ''''Sample stream object
#     
#     This represents a "chunk" of samples contained in a numpy array
#     stored in the samples attribute.
# 
#     '''
#     def __init__(self, samples, start_time, sample_period):
#         self.samples = samples
#         self.start_time = start_time
#         self.sample_period = sample_period
# 
# class StreamError(RuntimeError):
#     '''Custom exception class for edge and sample streams'''
#     pass
# 
# class ChunkExtractor(object):
#     '''Utility class that pulls arbitrarily sized chunks from a sample stream'''
#     def __init__(self, stream):
#         self.stream = stream
#         self.sample_buf = []
#         self.buf_count = 0
#         self.stream_ended = False
#         self.buf_start_time = 0.0
#         self.sample_period = 0.0
# 
#     def next_chunk(self, chunk_size=10000):
#         '''Get a new chunk of samples from the stream
# 
#         chunk_size (int)
#             The number of samples for this chunk.
# 
#         Returns a SampleChunk object. If the stream had fewer than chunk_size samples
#           remaining then the SampleChunk.samples array is sized to hold only those samples.
# 
#         Returns None if the stream has ended.
#         '''
#         if self.stream_ended:
#             return None
# 
#         while True:
#             if self.buf_count < chunk_size: # Need to get another chunk
#                 try:
#                     sc = next(self.stream)
#                     if len(self.sample_buf) == 0:
#                         self.buf_start_time = sc.start_time
#                         self.sample_period = sc.sample_period
#                     self.sample_buf.append(sc.samples)
#                     self.buf_count += len(sc.samples)
# 
#                 except StopIteration:
#                     self.stream_ended = True
# 
#             if self.stream_ended and self.buf_count < chunk_size:
#                 # Not enough samples in buffer for a full sized chunk
#                 chunk_size = self.buf_count
#                 if chunk_size == 0:
#                     break
# 
#             if self.buf_count >= chunk_size:
#                 # We have enough buffered samples to return a new chunk
#                 out_samp = np.empty(chunk_size, dtype=float)
#                 out_count = 0
#                 for b in self.sample_buf:
#                     if out_count + len(b) <= chunk_size:
#                         use_count = len(b)
#                     else:
#                         use_count = chunk_size - out_count
# 
#                     out_samp[out_count:out_count + use_count] = b[:use_count]
#                     out_count += use_count
# 
#                 out_time = self.buf_start_time
# 
#                 if self.buf_count > chunk_size:
#                     # There are unused samples remaining in the buffer
#                     # Place these at the start of the buffer for the next call to next_chunk()
#                     self.sample_buf = [self.sample_buf[-1][use_count:]]
#                     self.buf_count = len(self.sample_buf[0])
#                     self.buf_start_time = self.buf_start_time + self.sample_period * chunk_size
#                 else:
#                     self.sample_buf = []
#                     self.buf_count = 0
# 
#                 return SampleChunk(out_samp, out_time, self.sample_period)
# 
#             if self.stream_ended:
#                 break
# 
#         return None
# 
#     def next_samples(self, sample_count=10000):
#         '''Get a new set of raw samples from the stream
# 
#         sample_count (int)
#             The number of samples for the array.
# 
#         Returns a numpy array of float. If the stream had fewer than sample_count samples
#           remaining then the array is sized to hold only those samples.
# 
#         Returns None if the stream has ended.
#         '''
# 
#         sc = self.next_chunk(sample_count)
#         if sc is not None:
#             return sc.samples
#         else:
#             return None
# 
#     def buffered_chunk(self):
#         '''Get all remaining buffered samples'''
#         return self.next_chunk(self.buf_count)


# Path: ripyl/sigproc.py
from ripyl.streaming import SampleChunk, StreamError, ChunkExtractor
import numpy as np
import scipy.signal as signal

        filt = np.zeros((len(sc.samples),), dtype = np.float)
        for j in xrange(len(sc.samples)):
            sample_v = sc.samples[j]
            for _ in xrange(iterations):
                i = (sample_v - vc) / resistance # Capacitor current

                dq = i * dt # Change in charge
                q += dq
                vc = q / capacitance # New capacitor voltage
                #print('$$ i, dq, d, vc', i, dq, q, vc)
            filt[j] = vc
        yield SampleChunk(filt, sc.start_time, sc.sample_period)

        
def sum_streams(stream1, stream2):
    '''Add two sample streams together
    
    The time elements of each stream will not be aligned if they do not match.
    Instead the time values from stream1 are used for the result. The iterator
    terminates when either of the two streams ends.
    
    This is a generator function.
    
    stream1 (iterable of SampleChunk objects)
    stream2 (iterable of SampleChunk objects)
        The two sample streams to have their corresponding values added together.
        
    Yields a sample stream.
    '''


    ex1 = ChunkExtractor(stream1)