# inhomogenous dephasing function s = theano.shared(math.pow(sparam, 2) / 2) iscan = theano.shared(np.linspace(0, (NEmi - 1), NEmi, dtype=int)) ############################# # Declare theano symbolic input variables x = TT.dscalar("x") # for t xvec = TT.dvector("xvec") # for t y = TT.dscalar("y") # for t1 h1 = TT.dscalar("h1") # for heaviside t2-t1 h2 = TT.dscalar("h2") # for heaviside t3-t2 h3vec = TT.dvector("h3vec") U1 = TT.cmatrix("U1") U2 = TT.cmatrix("U2") U3ten = TT.ctensor3("U3ten") conjU1 = TT.cmatrix("conjU1") conjU2 = TT.cmatrix("conjU2") conjU3ten = TT.ctensor3("conjU3ten") i = TT.ivector("i") ############################# # Theano expression graph # # Explicit calculation of a given point in the 2D time domain response function # # Easier to follow the physics: # #dephasing at each step # deph1 = TT.exp(-g*(t2-y)) # deph2 = TT.exp(-g*(t3-t2)) # deph3 = TT.exp(-g*(x-t3)) # # r1 ket/ket/ket interactions #r1a = (TT.dot(U1,TT.dot(m,TT.dot(p0,conjU1))))*deph1
class multifader(gr.sync_block): # some consts N = 4096 NS = 8 TL = 16 # Tap length of filter NF = TL # number of fading components (equal to n taps for prototype version) step = T.ctensor3("step") l = T.iscalar("l") # length to produce iv = T.cmatrix("iv") # complex input vector stepd = theano.shared(numpy.zeros((NF, NS, N), dtype=numpy.complex64), name="stepd") taps = theano.shared(numpy.ones((TL), dtype=numpy.complex64), name="taps") phase = theano.shared(numpy.asarray([[1 + 0j] * NS] * NF, dtype=numpy.complex64), name="phase") oo = theano.shared(numpy.asarray([[1 + 0j] * N] * NF, dtype=numpy.complex64), name="oo") # theano functions set_step = theano.function(inputs=[step], outputs=[], updates={stepd: step}, name="set_step") rval = theano.function(on_unused_input="warn", inputs=[iv, l], outputs=[ T.signal.conv.conv2d(iv[0:(l + TL - 1)], taps.dimshuffle('x', 0)) ], updates={ phase: phase * stepd[:, :, l - 1] * stepd[:, :, 1], taps: phase[:, 0] }, name="rval") def set_f(self, f): self.f = f # initialize empty step update tensor (Num fading components, num sinusoids per fading compnent, num steps per sine) step_update = numpy.zeros((self.NF, self.NS, self.N), dtype="complex64") # for each fading component for i in range(0, self.NF): # generate random initial frequency components # todo: 100 is hard wired max component doppler freq? make changeable parameter? tones = map(lambda x: random.uniform(1, 100), range(0, self.NS)) # generate phasor step ammount for each component frequency stepval = map(lambda x: numpy.pi * 2.0 * x / self.fs, tones) # update step update tensor sub-matrix step_update[i, :, :] = numpy.vstack( map( lambda x: numpy.exp(1j * numpy.arange( 0, self.N * x, x, dtype=numpy.float32), dtype=numpy.complex64), stepval)) # pass to theano variable self.set_step(step_update) def __init__(self, fs, f, blocksize=1024): gr.sync_block.__init__(self, name="theano_multifader", in_sig=[numpy.complex64], out_sig=[numpy.complex64]) self.fs = fs self.set_f(f) self.set_history(self.TL) self.set_output_multiple(blocksize) self.blocksize = blocksize def work(self, input_items, output_items): out = output_items[0] nout = min(len(output_items[0]), len(input_items[0]) - (self.TL - 1)) nout = self.blocksize o = self.rval(input_items, nout) out[:] = o[0] return nout