Code
--[[
ligandacious
In puzzle 1446, the ligand at segment 320 can have multiple shapes.
Each shape is a "rotamer". Sidechains can also have multiple rotamers.
Unlike sidechain rotamers, the ligand's rotamers can result in a
completely different shape.
For puzzle 1446, the goal is to find both the best position for the
ligand and the best shape. The protein part of the puzzle is either
locked or held in place with constraints.
This recipe explores the different positions available for a ligand.
The recipe is not specific to puzzle 1446, and should work on any
puzzle with one or more ligands as the highest-numbered segments.
version 1.0 - 2017/11/05 - LociOiling
-- flip through the ligand rotamers
-- shake and wiggle ligand only
-- shake and wiggle all
-- save best positions
-- turn off filters for shake and wiggle
]]--
--
-- globals section
--
Recipe = "ligandacious"
Version = "1.0"
ReVersion = Recipe .. " v" .. Version
STARTSLOT = 1
BESTSLOT = 2
startScore = 0
bestScore = 0
ligandy = false
segCnt = 0
segCnt2 = 0
--
-- end of globals section
--
function round ( x )--cut all afer 3-rd place
return x - x % 0.001
end
--
-- Ident - print identifying information at beginning and end of recipe
--
-- slugline - first line to print - normally recipe name and version
--
function Ident ( slugline )
local function round ( ii )
return ii - ii % 0.001
end
print ( slugline )
print ( "Puzzle: " .. puzzle.GetName () .. " (" .. puzzle.GetPuzzleID () .. ")" )
print ( "Track: " .. ui.GetTrackName () )
gname = user.GetGroupName ()
if gname ~= nil then
gname = " (" .. gname .. ")"
else
gname = ""
end
print ( "User: " .. user.GetPlayerName () .. gname )
local scoretype = scoreboard.GetScoreType ()
local scort = ""
if scoretype == 0 then
scort = "soloist"
elseif scoretype == 1 then
scort = "evolver"
elseif scoretype == 2 then
scort = "all hands"
elseif scoretype == 3 then
scort = "no score"
else
scort = "unknown/error"
end
print ( "Rank: " .. scoreboard.GetRank ( scoretype ) .. " (" .. scort .. ")" )
local sGroup = scoreboard.GetGroupScore ()
if sGroup ~= nil then
print ( "Group rank / score: " .. scoreboard.GetGroupRank () .. " / " .. round ( 10 * ( 800 - sGroup ) ) )
end
end
--
-- inherent vice filter toggling, v 0.1
--
function FilterX ( funcX, ... )
behavior.SetFiltersDisabled ( true )
local ret = funcX ( unpack ( arg ) )
behavior.SetFiltersDisabled ( false )
return ret
end
--
-- end inherent vice filter toggling, v 0.1
--
function BestTest ( currScore )
if currScore > bestScore then
if round ( currScore ) == round ( bestScore ) then
print ( "tiny gain" )
else
print ( "gained another " .. round ( currScore - bestScore ) )
end
bestScore = currScore
save.Quicksave ( BESTSLOT )
end
end
function main ()
Ident ( ReVersion )
save.Quicksave ( STARTSLOT )
save.Quicksave ( BESTSLOT )
startScore = current.GetEnergyScore ()
bestScore = startScore
print ( "starting score = " .. round ( startScore ) )
segCnt = structure.GetCount()
segCnt2 = segCnt
while structure.GetSecondaryStructure ( segCnt2 ) == "M" do
segCnt2 = segCnt2 - 1
end
print ( "initial segment count: " .. segCnt )
if segCnt ~= segCnt2 then
ligandy = true
print ( "ligand found, adjusted segment count: " .. segCnt2 )
end
if ligandy then
for ii = segCnt2 + 1, segCnt do
print ( "----" )
print ( "ligand segment " .. ii )
local rots = rotamer.GetCount ( ii )
print ( "rotamer count = " .. rots )
local llock = structure.IsLocked ( ii )
if llock then
print ( "locked ligand" )
end
if rots > 1 and not llock then
save.Quickload ( STARTSLOT )
for jj = 1, rots do
print ( "--" )
print ( "rotamer " .. jj )
rotamer.SetRotamer ( ii, jj )
local jrots = rotamer.GetCount ( ii )
if rots ~= jrots then
print ( "WARNING: rotamer count changed to " .. jrots )
end
local wScore = current.GetEnergyScore ()
print ( "initial rotamer score = " .. round ( wScore ) )
BestTest ( wScore )
selection.DeselectAll ()
--
-- shake and wiggle just the ligand
--
selection.Select ( ii )
FilterX ( structure.ShakeSidechainsSelected, 1 )
wScore = current.GetEnergyScore ()
print ( "after local shake, score = " .. round ( wScore ) )
BestTest ( wScore )
--
FilterX ( structure.WiggleSelected, 30, false, true )
wScore = current.GetEnergyScore ()
print ( "after wiggle sidechains, score = " .. round ( wScore ) )
BestTest ( wScore )
--
FilterX ( structure.WiggleSelected, 30, true, true )
wScore = current.GetEnergyScore ()
print ( "after wiggle backbone + sidechains, score = " .. round ( wScore ) )
BestTest ( wScore )
--
-- shake and wiggle the whole thing
--
selection.DeselectAll ()
FilterX ( structure.ShakeSidechainsAll, 1 )
wScore = current.GetEnergyScore ()
print ( "after global shake, score = " .. round ( wScore ) )
BestTest ( wScore )
--
FilterX ( structure.WiggleAll, 30, true, true )
wScore = current.GetEnergyScore ()
print ( "after global wiggle backbone + sidechains, score = " .. round ( wScore ) )
BestTest ( wScore )
end
end
end
else
print ( "No ligands found" )
end
cleanup ()
end
function cleanup ( errmsg )
if CLEANUPENTRY ~= nil then
return
end
CLEANUPENTRY = true
print ( "---" )
local reason
local start, stop, line, msg
if errmsg == nil then
reason = "complete"
else
--
-- model 120 - civilized error reporting,
-- thanks to Bruno K. and Jean-Bob
--
start, stop, line, msg = errmsg:find ( ":(%d+):%s()" )
if msg ~= nil then
errmsg = errmsg:sub ( msg, #errmsg )
end
if errmsg:find ( "Cancelled" ) ~= nil then
reason = "cancelled"
else
reason = "error"
end
end
--
-- model 100 - print recipe name, puzzle, track, time, score, and gain
--
Ident ( ReVersion .. " " .. reason )
if reason == "error" then
print ( "Unexpected error detected" )
print ( "Error line: " .. line )
print ( "Error: \"" .. errmsg .. "\"" )
end
--
-- model 130 - reset clash importance, clear selections, restore structures, etc.
--
selection.DeselectAll ()
behavior.SetFiltersDisabled ( false )
if errmsg ~= nil then
save.Quickload ( BESTSLOT )
end
print ( "ending score = " .. round ( current.GetEnergyScore () ) )
end
xpcall ( main, cleanup )