def setSIM(self, sim): 
     if sim is not None:  
         self.sim=sim
         self.numReplicates=self.sim.numReplicates
         self.n=self.sim.N*2
         self.initTheta=self.sim.theta/(self.sim.L/self.sim.winSize); 
         self.initC0 = np.ones(self.numReplicates,dtype=floatX)*logit(sim.X[0].mean(1).min())
         self.Times=np.tile(sim.getGenerationTimes(),(self.numReplicates,1)).T.astype(np.float32)
         self.replicateIndex=range(self.numReplicates)
     else:
         self.initC0 = np.ones(self.numReplicates,dtype=floatX)
     
     try:
         self.reset()
     except:      
         pass
 def __init__(self,sim, final_momentum=0.9, initial_momentum=0.5,momentum_switchover=5,lr_s=1e-6, lr_nu=1e-2 , lr_Yslack=1e-2, maxIter=1000,initS=0.0,initSviaLineSearch=True):
     self.initSviaLineSearch=initSviaLineSearch
     self.sim=sim
     self.initYslack=0
     self.n=self.sim.N*2
     self.theta=self.sim.theta/(self.sim.L/self.sim.winSize); 
     self.initC0 = np.ones(self.sim.numReplicates,dtype=floatX)*logit(sim.X0.min())
     self.Times=np.tile(sim.getGenerationTimes(),(self.sim.numReplicates,1)).T.astype(np.float32)
     self.momentum_ = T.scalar()
     self.final_momentum=final_momentum; self.initial_momentum=initial_momentum;self.momentum_switchover=momentum_switchover;self.W=3;self.lr_s=lr_s;self.lr_theta=lr_Yslack;self.lr_nu=lr_nu;self.maxIter=maxIter;self.initS=initS
     self.lrS_ = T.scalar();self.lrNu_ = T.scalar();self.lrTheta_ = T.scalar();self.target_ = T.matrix(); self.times_ = T.fmatrix("times"); self.theta_ = T.scalar()
     self.Yslack__=theano.shared(np.asarray(0, dtype = floatX), 'theta');self.n_ = T.scalar("n ")
     self.S__=theano.shared(np.asarray(self.initS, dtype = floatX))
     self.c__=theano.shared(self.initC0, 'c')
     self.weightUpdateS__ = theano.shared(np.asarray(0, dtype = floatX))
     self.weightUpdatec__ = theano.shared(np.zeros(self.sim.numReplicates, dtype = floatX))
     self.weightUpdateYslack__ = theano.shared(np.asarray(0, dtype = floatX))
     self.pred_= Z(sig_(0.5*self.S__*self.times_ + self.c__),self.n_,self.theta_) + self.Yslack__
     self.Feedforward_ = theano.function(inputs=[self.times_,self.n_,self.theta_], outputs=self.pred_)
     self.cost_=0
     for j in range(self.sim.numReplicates):
         self.cost_ += 0.5*((self.target_[:,j] - self.pred_[:,j])**2).sum()
     self.Loss_ = theano.function(inputs=[self.target_,self.pred_], outputs=self.cost_)
     self.gS_,self.gc_, self.gYslack_ = T.grad(self.cost_, [self.S__,self.c__, self.Yslack__])
     
     self.updatesS=[(self.weightUpdateS__,  self.momentum_ * self.weightUpdateS__ - self.lrS_ * self.gS_),(self.S__, self.S__ + self.momentum_ * self.weightUpdateS__ - self.lrS_ * self.gS_)]
     self.updatesc=[(self.weightUpdatec__,  self.momentum_ * self.weightUpdatec__ - self.lrNu_ * self.gc_),(self.c__, self.c__ + self.momentum_ * self.weightUpdatec__ - self.lrNu_ * self.gc_)]
     self.updatesYslack=[(self.weightUpdateYslack__,  self.momentum_ * self.weightUpdateYslack__ - self.lrTheta_ * self.gYslack_),(self.Yslack__, self.Yslack__ + self.momentum_ * self.weightUpdateYslack__ - self.lrTheta_ * self.gYslack_)]
     self.updates=   self.updatesc +self.updatesS + self.updatesYslack
     self.Objective_ = theano.function([ self.target_, self.lrS_, self.lrNu_, self.lrTheta_, self.times_,self.momentum_,self.n_,self.theta_], self.cost_, on_unused_input='warn',updates=self.updates,allow_input_downcast=True)
    def fit(self,winidx,windowIndex=None,filterAfterDrop=True,linesearchTheta=False,YslackLineSearch=False):
        if windowIndex is None:
            y=self.sim.getAverageHAF(self.sim.winIdx[winidx])
        else:
            y=self.sim.getAverageHAF(windowIndex)
        self.times= self.Times
        if filterAfterDrop:
            self.lastGenerationIndex = self.sim.filterTimeSamplesWithHighNegDer(y)
        else:
            self.lastGenerationIndex=(np.ones(self.numReplicates)*self.times.shape[0]).astype(int)-1
        self.y=y.values
        self.reset()
        if YslackLineSearch: self.setInitYslackViaSettingInitObservation()
        self.setInitSviaLineSearch()
        
        start_time=time.time()
        if self.verbose>2:
            print 'y:\n{},times:\n{}\nn:{},\ttheta:{}\tlastGenIDX:{}\tRepIDX:{}'.format(self.y,self.times,self.n,self.Theta__.get_value(),self.lastGenerationIndex,self.replicateIndex)
        self.obj=float(self.Loss_(self.y,self.times,self.n,self.lastGenerationIndex,self.replicateIndex))
        if self.verbose>1:      print 'Before\nIter,\tobj,\ts,\ttheta,\tYslack,\tnu\n','{}\t{:.3f}\t{:.3f}\t{:.3f}\t{:.3f}\t{}'.format(0,self.obj ,float(self.S__.get_value()),float(self.Theta__.get_value()) ,float(self.Yslack__.get_value()),sig(self.c__.get_value()))
        for i in range(self.maxIter):
            self.saveState()
            self.obj=self.Objective_(self.y, self.lr_s, self.lr_nu, self.lr_Yslack, self.lr_theta, self.times, (self.final_momentum , self.initial_momentum)[i<5],self.n, self.lastGenerationIndex,self.replicateIndex)
            if self.verbose>1:  print '{}\t{:.3f}\t{:.3f}\t{:.3f}\t{:.3f}\t{}'.format(i+1,float(self.obj) ,float(self.S__.get_value()),float(self.Theta__.get_value()) ,float(self.Yslack__.get_value()),sig(self.c__.get_value()))
            if self.obj>self.obj__prev:    
                self.undoStep()
                break
        s, nu0, slack,theta= np.asscalar(self.S__.get_value()), sig(self.c__.get_value()),np.asscalar(self.Yslack__.get_value()),np.asscalar(self.Theta__.get_value())
        obj=self.Loss_(self.y,self.times,self.n,self.lastGenerationIndex,self.replicateIndex)
        
        
        obj0=self.getZeroObj()
        negLogLikelihoodRatio=np.log(obj0)-np.log(obj)
        if s<0:
            negLogLikelihoodRatio=0
            s=0
#         if negLogLikelihoodRatio<0: negLogLikelihoodRatio=0
        self.sol=pd.Series({'s':s,'LR':negLogLikelihoodRatio,'Time':time.time()-start_time,'pos':self.sim.winMidPos[winidx],'nu0':nu0,'slack':slack,'obj':float(obj), 'obj0':float(obj0), 'lastTimes': self.lastGenerationIndex, 'y':self.y, 'theta':theta, 'n':self.n, 'winidx':winidx, 'SLR': np.exp(negLogLikelihoodRatio)*s, 'watterson':Estimate.watterson(self.sim.H0.iloc[:,self.sim.winIdx[winidx]]),'method':'HAF'})
        return self.sol