Ejemplo n.º 1
0
def compute_full_ctf(D, Nimg, args):
    freqs = np.arange(-D / 2, D / 2) / (args.Apix * D)
    x0, x1 = np.meshgrid(freqs, freqs)
    freqs = np.stack([x0.ravel(), x1.ravel()], axis=1)
    if args.ctf_pkl:  # todo: refator
        params = pickle.load(open(args.ctf_pkl, 'rb'))
        try:
            assert len(params) == Nimg
        except AssertionError:
            log('Note that the input ctf.pkl contains ' + str(len(params)) +
                ' particles, but that you have only chosen to output the first '
                + str(Nimg) + ' particle')
            params = params[:Nimg]
        ctf = np.array([compute_ctf(freqs, *x[2:], args.b) for x in params])
        ctf = ctf.reshape((Nimg, D, D))
        df1 = np.array([x[2] for x in params])
        df2 = np.array([x[3] for x in params])
        dfa = np.array([x[4] for x in params])
        dfp = np.array([x[8] for x in params])
        df = np.stack([df1, df2, dfa, dfp], axis=1)
    elif args.df_file:
        raise NotImplementedError

#        df = pickle.load(open(args.df_file,'rb'))
#        try:
#            assert len(df) == Nimg
#        except AssertionError:
#            log('Note that the input df.pkl contains '+ str(len(df)) + ' particles, but that you have only chosen to output the first ' + str(Nimg) + ' particle')
#            df = df[:Nimg]
#        ctf = np.array([compute_ctf(freqs, i, i, args.ang, args.kv, args.cs, args.wgh, args.ps, args.b) \
#                for i in df])
#        ctf = ctf.reshape((Nimg, D, D))
#        df = np.stack([df,df], axis=1)
    elif args.sample_df:
        raise NotImplementedError


#
#        df1 = np.random.normal(args.dfu,args.sample_df,Nimg)
#        if args.no_astigmatism:
#            assert args.dfv == args.dfu, "--dfu and --dfv must be the same"
#            df2 = df1
#        else:
#            df2 = np.random.normal(args.dfv,args.sample_df,Nimg)
#        ctf = np.array([compute_ctf(freqs, i, j, args.ang, args.kv, args.cs, args.wgh, args.ps, args.b) \
#                for i, j in zip(df1, df2)])
#        ctf = ctf.reshape((Nimg, D, D))
#        df = np.stack([df1,df2], axis=1)
    else:
        ctf = compute_ctf(freqs, args.dfu, args.dfv, args.ang, args.kv,
                          args.cs, args.wgh, args.ps, args.b)
        ctf = ctf.reshape((D, D))
        df = np.stack([np.ones(Nimg) * args.dfu,
                       np.ones(Nimg) * args.dfv],
                      np.ones(Nimg) * args.ang,
                      np.ones(Nimg) * args.ps,
                      axis=1)
    return ctf, df
Ejemplo n.º 2
0
def train(model,
          lattice,
          optim,
          y,
          rot,
          trans=None,
          ctf_params=None,
          use_amp=False):
    model.train()
    optim.zero_grad()
    B = y.size(0)
    D = lattice.D
    # reconstruct circle of pixels instead of whole image
    mask = lattice.get_circular_mask(D // 2)
    yhat = model(lattice.coords[mask] @ rot).view(B, -1)
    if ctf_params is not None:
        freqs = lattice.freqs2d[mask]
        freqs = freqs.unsqueeze(0).expand(
            B, *freqs.shape) / ctf_params[:, 0].view(B, 1, 1)
        yhat *= ctf.compute_ctf(freqs, *torch.split(ctf_params[:, 1:], 1, 1))
    y = y.view(B, -1)[:, mask]
    if trans is not None:
        y = lattice.translate_ht(y, trans.unsqueeze(1), mask).view(B, -1)
    loss = F.mse_loss(yhat, y)
    if use_amp:
        with amp.scale_loss(loss, optim) as scaled_loss:
            scaled_loss.backward()
    else:
        loss.backward()
    optim.step()
    return loss.item()
Ejemplo n.º 3
0
def run_batch(model, lattice, y, yt, rot, tilt=None, ctf_params=None, yr=None):
    use_tilt = yt is not None
    use_ctf = ctf_params is not None
    B = y.size(0)
    D = lattice.D
    if use_ctf:
        freqs = lattice.freqs2d.unsqueeze(0).expand(
            B, *lattice.freqs2d.shape) / ctf_params[:, 0].view(B, 1, 1)
        c = ctf.compute_ctf(freqs, *torch.split(ctf_params[:, 1:], 1,
                                                1)).view(B, D, D)

    # encode
    if yr is not None:
        input_ = (yr, )
    else:
        input_ = (y, yt) if yt is not None else (y, )
        if use_ctf:
            input_ = (x * c.sign() for x in input_)  # phase flip by the ctf
    z_mu, z_logvar = _unparallelize(model).encode(*input_)
    z = _unparallelize(model).reparameterize(z_mu, z_logvar)

    # decode
    mask = lattice.get_circular_mask(D // 2)  # restrict to circular mask
    y_recon = model(lattice.coords[mask] / lattice.extent / 2 @ rot,
                    z).view(B, -1)
    if use_ctf: y_recon *= c.view(B, -1)[:, mask]

    # decode the tilt series
    if use_tilt:
        y_recon_tilt = model(
            lattice.coords[mask] / lattice.extent / 2 @ tilt @ rot, z)
        if use_ctf: y_recon_tilt *= c.view(B, -1)[:, mask]
    else:
        y_recon_tilt = None
    return z_mu, z_logvar, z, y_recon, y_recon_tilt, mask
Ejemplo n.º 4
0
def eval_z(model, lattice, data, batch_size, device, trans=None, use_tilt=False, ctf_params=None, use_real=False):
    assert not model.training
    z_mu_all = []
    z_logvar_all = []
    data_generator = DataLoader(data, batch_size=batch_size, shuffle=False)
    for minibatch in data_generator:
        ind = minibatch[-1]
        y = minibatch[0].to(device)
        yt = minibatch[1].to(device) if use_tilt else None
        B = len(ind)
        D = lattice.D
        if ctf_params is not None:
            freqs = lattice.freqs2d.unsqueeze(0).expand(B,*lattice.freqs2d.shape)/ctf_params[ind,0].view(B,1,1)
            c = ctf.compute_ctf(freqs, *torch.split(ctf_params[ind,1:], 1, 1)).view(B,D,D)
        if trans is not None:
            y = lattice.translate_ht(y.view(B,-1), trans[ind].unsqueeze(1)).view(B,D,D)
            if yt is not None: yt = lattice.translate_ht(yt.view(B,-1), trans[ind].unsqueeze(1)).view(B,D,D)
        if use_real:
            input_ = (torch.from_numpy(data.particles_real[ind]).to(device),)
        else:
            input_ = (y,yt) if yt is not None else (y,)
        if ctf_params is not None: 
            assert not use_real, "Not implemented"
            input_ = (x*c.sign() for x in input_) # phase flip by the ctf
        z_mu, z_logvar = _unparallelize(model).encode(*input_)
        z_mu_all.append(z_mu.detach().cpu().numpy())
        z_logvar_all.append(z_logvar.detach().cpu().numpy())
    z_mu_all = np.vstack(z_mu_all)
    z_logvar_all = np.vstack(z_logvar_all)
    return z_mu_all, z_logvar_all
Ejemplo n.º 5
0
 def run_model(y):
     '''Helper function'''
     # reconstruct circle of pixels instead of whole image
     mask = lattice.get_circular_mask(D // 2)
     yhat = model(lattice.coords[mask] @ rot).view(B, -1)
     if ctf_params is not None:
         freqs = lattice.freqs2d[mask]
         freqs = freqs.unsqueeze(0).expand(
             B, *freqs.shape) / ctf_params[:, 0].view(B, 1, 1)
         yhat *= ctf.compute_ctf(freqs,
                                 *torch.split(ctf_params[:, 1:], 1, 1))
     y = y.view(B, -1)[:, mask]
     if trans is not None:
         y = lattice.translate_ht(y, trans.unsqueeze(1), mask).view(B, -1)
     return F.mse_loss(yhat, y)
Ejemplo n.º 6
0
def main(args):
    assert args.o.endswith('.mrc')

    t1 = time.time()
    log(args)
    if not os.path.exists(os.path.dirname(args.o)):
        os.makedirs(os.path.dirname(args.o))

    ## set the device
    use_cuda = torch.cuda.is_available()
    device = torch.device('cuda' if use_cuda else 'cpu')
    log('Use cuda {}'.format(use_cuda))
    if use_cuda:
        torch.set_default_tensor_type(torch.cuda.FloatTensor)
    else:
        log('WARNING: No GPUs detected')

    # load the particles
    if args.tilt is None:
        data = dataset.LazyMRCData(args.particles,
                                   norm=(0, 1),
                                   invert_data=args.invert_data,
                                   datadir=args.datadir)
        tilt = None
    else:
        data = dataset.TiltMRCData(args.particles,
                                   args.tilt,
                                   norm=(0, 1),
                                   invert_data=args.invert_data,
                                   datadir=args.datadir)
        tilt = torch.tensor(utils.xrot(args.tilt_deg).astype(np.float32))
    D = data.D
    Nimg = data.N

    lattice = Lattice(D, extent=D // 2)

    posetracker = PoseTracker.load(args.poses, Nimg, D, None, None)

    if args.ctf is not None:
        log('Loading ctf params from {}'.format(args.ctf))
        ctf_params = ctf.load_ctf_for_training(D - 1, args.ctf)
        ctf_params = torch.tensor(ctf_params)
    else:
        ctf_params = None
    Apix = ctf_params[0, 0] if ctf_params is not None else 1

    V = torch.zeros((D, D, D))
    counts = torch.zeros((D, D, D))

    mask = lattice.get_circular_mask(D // 2)

    if args.ind:
        iterator = pickle.load(open(args.ind, 'rb'))
    elif args.first:
        args.first = min(args.first, Nimg)
        iterator = range(args.first)
    else:
        iterator = range(Nimg)

    for ii in iterator:
        if ii % 100 == 0: log('image {}'.format(ii))
        r, t = posetracker.get_pose(ii)
        ff = data.get(ii)
        if tilt is not None:
            ff, ff_tilt = ff  # EW
        ff = torch.tensor(ff)
        ff = ff.view(-1)[mask]
        if ctf_params is not None:
            freqs = lattice.freqs2d / ctf_params[ii, 0]
            c = ctf.compute_ctf(freqs, *ctf_params[ii, 1:]).view(-1)[mask]
            ff *= c.sign()
        if t is not None:
            ff = lattice.translate_ht(ff.view(1, -1), t.view(1, 1, 2),
                                      mask).view(-1)
        ff_coord = lattice.coords[mask] @ r
        add_slice(V, counts, ff_coord, ff, D)

        # tilt series
        if args.tilt is not None:
            ff_tilt = torch.tensor(ff_tilt)
            ff_tilt = ff_tilt.view(-1)[mask]
            if ctf_params is not None:
                ff_tilt *= c.sign()
            if t is not None:
                ff_tilt = lattice.translate_ht(ff_tilt.view(1, -1),
                                               t.view(1, 1, 2), mask).view(-1)
            ff_coord = lattice.coords[mask] @ tilt @ r
            add_slice(V, counts, ff_coord, ff_tilt, D)

    td = time.time() - t1
    log('Backprojected {} images in {}s ({}s per image)'.format(
        len(iterator), td, td / Nimg))
    counts[counts == 0] = 1
    V /= counts
    V = fft.ihtn_center(V[0:-1, 0:-1, 0:-1].cpu().numpy())
    mrc.write(args.o, V.astype('float32'), Apix=Apix)