Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Are structure based potentials supported? #10

Open
amin-sagar opened this issue Sep 13, 2023 · 7 comments
Open

Are structure based potentials supported? #10

amin-sagar opened this issue Sep 13, 2023 · 7 comments

Comments

@amin-sagar
Copy link

Hello.
Thanks again for this amazing work.
The sequence based potentials are really useful.
I am wondering if it's also possible to have structure based potentials.
For example, if I want certain residues to be close to each other in the designs, can this be encoded in a structure based potential or bias?
Best,
Amin.

@0merle0
Copy link
Member

0merle0 commented Sep 19, 2023

Hi, this is something that can be possible, if you are familiar with hallucination type approaches for design this is something that could be worth trying here as a potential, if you're interested in setting something like this up, I am happy to chat and explain more!

@amin-sagar
Copy link
Author

Thanks @0merle0
That would be very helpful. I am certainly interested in implementing this.
Please let me know how we can connect.

@0merle0
Copy link
Member

0merle0 commented Sep 26, 2023

Hi sorry for the late reply, if you send me an email with your availability we can set up a time to zoom: [email protected]

@geraseva
Copy link
Contributor

I tried to implement a potential from RFdiffusion. Something like this:

class monomer_ROG(Potential):
    def __init__(self, args, features, potential_scale, DEVICE, min_dist=15):

        super().__init__()

        self.use_features=True

        self.features = features
        self.args = args

        # grad_test is used to retain features in the graph
        if args['sampler']!='grad_test':
            sys.exit('This potential uses grad_test sampler. Please, set --sampler grad_test')

        self.min_dist = min_dist
        self.potential_scale = potential_scale
        self.DEVICE = DEVICE

    def get_gradients(self, features):

        Ca = features['xyz'][:,1] # [L,3]
        centroid = torch.mean(Ca, dim=0, keepdim=True) # [1,3]
        dgram = torch.cdist(Ca[None,...].contiguous(), centroid[None,...].contiguous(), p=2) # [1,L,1,3]
        dgram = torch.maximum(self.min_dist * torch.ones_like(dgram.squeeze(0)), dgram.squeeze(0)) # [L,1,3]
        rad_of_gyration = torch.sqrt( torch.sum(torch.square(dgram)) / Ca.shape[0] ) # [1]
        rad_of_gyration.backward()            

        # Get gradients from msa_masked
        self.gradients = features['msa_masked'][:,0,:22].grad

        # reset gradients
        for key in features:
            try:
                features[key].grad=None
            except AttributeError:
                pass

        return -self.gradients*self.potential_scale

### ADD NEW POTENTIALS INTO LIST DOWN BELOW ###
POTENTIALS = {'aa_bias':AACompositionalBias, 'charge':ChargeBias, 'hydrophobic':HydrophobicBias, 'PSSM':PSSMbias, 
              'monomer_ROG':monomer_ROG}

Anyway, as I have a rather poor understanding of how RoseTTAFoldModel works here, I have some doubts about whether it is right and useful. Is it a good idea to take gradients from msa_masked, perhaps better is from msa_full? Is it a good idea to use elements from features dict, or is it better to run RosettaFold model for seq_out inside the potential?

@geraseva
Copy link
Contributor

Well, it does not work. I was trying to run backward through the RosettaFold model, but it is somehow impossible. Perhaps, a better way is to apply potentials to sequence and structure independently.

@geraseva
Copy link
Contributor

Upd. I managed to run backward through RosettaFold, but I still don't know, whether it is a good idea, to update sequence using structure-based potentials. Hypothetically, it is possible, but practically... Anyway, it is better than when I tried to update structure with sequence-based potentials in RFdiffusion.

@geraseva
Copy link
Contributor

class monomer_ROG(Potential):

    def __init__(self, args, features, potential_scale, DEVICE, model, min_dist=15):

        super().__init__()

        self.features = features
        for key in features:
            try:
                features[key].requires_grad_(False)
            except:
                pass
        self.args = args

        self.min_dist = min_dist
        self.potential_scale = potential_scale
        self.DEVICE = DEVICE
        self.model=model
        self.model.eval()

    def get_gradients(self, seq):

        seq=seq.clone().detach().requires_grad_(True)

        msa_masked=self.features['msa_masked'].clone()
        msa_full=self.features['msa_full'].clone()
        msa_masked[0,0,0,:,:21] = seq
        msa_masked[0,0,0,:,22:43] = seq
        msa_full[0,0,0,:,:21] = seq
        in_seq = torch.argmax(seq, dim=-1)[None,None]

        _, _, xyz, _, _ = self.model(msa_masked[:,0], 
                                     msa_full[:,0], 
                                     in_seq[:,0],
                                     self.features['xyz_prev'], 
                                     self.features['idx_pdb'], 
                                     t1d=self.features['t1d'], 
                                     t2d=self.features['t2d'],
                                     xyz_t=self.features['xyz_t'], 
                                     alpha_t=self.features['alpha_t'],
                                     return_raw=True)

        Ca = xyz[0,:,1,:] # [L,3]
        centroid = torch.mean(Ca, dim=0, keepdim=True) # [1,3]
        dgram = torch.cdist(Ca[None,...].contiguous(), centroid[None,...].contiguous(), p=2) # [1,L,1,3]
        dgram = torch.maximum(self.min_dist * torch.ones_like(dgram.squeeze(0)), dgram.squeeze(0)) # [L,1,3]
        rad_of_gyration = torch.sqrt( torch.sum(torch.square(dgram)) / Ca.shape[0] ) # [1]
        rad_of_gyration.backward()  

        # Get gradients from msa_masked
        self.gradients = seq.grad

        # reset gradient
        seq.grad=None

        return -self.gradients*self.potential_scale

### ADD NEW POTENTIALS INTO LIST DOWN BELOW ###
POTENTIALS = {'aa_bias':AACompositionalBias, 'charge':ChargeBias, 'hydrophobic':HydrophobicBias, 'PSSM':PSSMbias, 
              'monomer_ROG':monomer_ROG}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants