Icon representing a recipe

Recipe: Bravo Find Terminals With Bands v1.1

created by bravosk8erboy

Profile


Name
Bravo Find Terminals With Bands v1.1
ID
109304
Shared with
Public
Parent
Bravo Find Terminals With Bands
Children
Created on
January 02, 2026 at 06:29 AM UTC
Updated on
January 02, 2026 at 06:29 AM UTC
Description

Best for


Code


-- This is an alternative method to identify terminal segments. works off the idea that you can creat a band on connected atoms. -- correctly identifies seperate proteins, ligands, RNA, and DNA. -- like most things in fold.it this recipe is faster with the window minimized. -- utilizes save.Quicksave(80) for clean up.change this if save slot is need. -- v1.1 -- removed false positives cause from cuts. -- band search more effiecent in a single pass. -- removed false positives from trim. -- Finds terminal segments using bands between atom 3 of segment i and atom 1 of segment i+1 (adjacent segments) -- returns Table or Terminals that is sorted with no duplicates function findTerminalsWithBands() save.Quicksave(80) local segmentCount = structure.GetCount() -- Clear any existing bands to avoid interference band.DeleteAll() -- check and remove false positives from trim. local success, err = pcall(structure.UntrimPose) local trim_total_segments = structure.GetCount() -- get total segments after untrim if trim_total_segments == segmentCount then --print("Pose was NOT trimmed") else print("Pose is trimmed at start of recipe") segmentCount = structure.GetCount() end -- identify false positives from cuts local table_of_cuts = structure.GetCuts() local k = 1 for i = 1, segmentCount - 1 do -- minus 1 so that we don't call a non existant segment with (i+1) if table_of_cuts[k] == i then k = k + 1 -- this is a cut, a false positive for terminals. skip it else -- Create a band between atom 3 of segment i and atom 1 of segment i+1 band.AddBetweenSegments(i, i + 1, 3, 1) end end local bandCount = band.GetCount() -- print(" bandCount: " .. bandCount) local Terminals = {} -- first segment and last segment wont have bands but are always terminals table.insert(Terminals, 1) -- table is sorted for i = 1, bandCount do -- minus 1 so that we don't call a non existant segment with (i+1) -- base before end to keep Terminals table sorted local Base = band.GetResidueBase(i) -- print(Terminals[#Terminals]) -- don't add a duplicate if Terminals[#Terminals] ~= Base then table.insert(Terminals, Base) end table.insert(Terminals, band.GetResidueEnd(i)) end -- first segment and last segment wont have bands but are always terminals -- don't add a duplicate if Terminals[#Terminals] ~= segmentCount then table.insert(Terminals, segmentCount) -- table is sorted end -- Print all Terminal segment indicies in one line, comma-separated print(" Terminals") print(table.concat(Terminals, ", ")) -- remove bands and return user created bands save.Quickload(80) -- return Terminals is sorted with no duplicates return Terminals end function cleanup(err) save.Quickload(80) print(" Error: " .. err) return {} end local Terminals = xpcall(findTerminalsWithBands,cleanup)

Comments


LociOiling Lv 1

Amazing, this recipe works well, and it's quick, even on a large puzzle (392 segments, for example). It's way less complex and more reliable than the stuff in print protein 3.0, which relies on distance measurements. It can also deal with a trimmed pose and open cutpoints.

I was totally baffled by how it works. Stop reading now if you want to savor the magic.

spoiler alert

The lines below give away the secret.

The recipe loops through each segment, attempting to add a band between the segment and the next segment. The band goes from atom 3 of the one segment to atom 1 of the next segment. (The recipe has special handing for the first and last segments, since they are always going to be terminals.)

The recipe in effect does makes this call to create a band between segment 20, atom 3, and segment 21, atom 1:
band.AddBetweenSegments ( 20, 21, 3, 1 )

Due to one of those Foldit quirks, this call is going to fail if 20 and 21 are in the same chain, meaning no band is added. If the two segments are not in same chain, the call is successful, and a band is added.

(You can't use band.AddBetweenSegments to go from segment i to segment i, or from i to i+1 or i-1.)

After banding, the recipe uses band.GetCount to determine how many bands there are, then uses band.GetResidueBase to get the starting segment of the band. The recipe then uses the function band.GetResidueEnd to get the ending segment of the band. The two segments are "terminals", or the ends of their respective chains.

The starting and ending segments are added to a table, which also contains the first and last segment numbers. The result is a list of all the terminals in the puzzle.

Simple and quick, and it doesn't care about protein versus DNA or RNA. The banding approach tricks Foldit into revealing the chain information that's in there somewhere, but isn't explicitly shared with users.

LociOiling Lv 1

This version of the recipe untrims the puzzle, then reports on the terminals.

The same technique also works on a trimmed pose.

When the "untrim" section is commented out, it will correctly report any "buffer" segments in the trimmed pose as being terminals.

Knowing the terminals is useful for recipes trying to avoid the end of chains. For example, remix will never find a remix pose when there's a terminal involved, so attempting to remix at the end of a chain is a waste of time.

As noted in the previous comment, the banding technique is better than the distance measuring technique found in print protein 3.0 and related recipes. Banding will find the buffer segments created by trimming, but distance measurement won't. The buffer segments haven't moved (at least initally), so they'll be at the same distance from the adjacent segments as before the trim.