Profile
- Name
- Contact Cement 2.02
- ID
- 49437
- Shared with
- Public
- Parent
- None
- Children
- Created on
- June 20, 2014 at 05:51 AM UTC
- Updated on
- June 20, 2014 at 05:51 AM UTC
- Description
Checks for contacts with non-zero heat. Displays fun facts about any such contacts found. Bands any contacts above a user-specifed heat cutoff. Band strength weithed by heat.
Best for
Code
--[[
Contact Cement
Original Author: LociOiling
Version 1.0 May 5, 2014
This recipe checks the contact heat for each pair of segments.
The recipe reports the number of contacts with non-zero heat, and displays
the minimum, maximum, mean, and median contact heat.
The recipe can band contacts with a heat value at or above a specified minimum.
The minimum is initially set to the mean heat.
The bands are created with default strength and length.
Version 2.0 by Bruno Kestemont 04/06/2014 (ideas = lincher)
Added weighting of band strength relative to heat, and zone, as suggested by lincher
Versions 2.01 07/06/2014, 2.02 20/06/2014 debugged
Band strength = 0 at cut off heat or fc of heat
Option to select the number of (best) bands.
]]--
--
-- globals section
--
Recipe = "Contact Cement"
Version = "2.02"
ReVersion = Recipe .. " v" .. Version
bndcut = 0
heatmap = {}
tHeat = 0
minHeat = 0.5
maxHeat = 0.9
meanHeat = 0.7
mediHeat = 0.7
strengthFactor=1.5 -- new 04/06/2014 -- from 0.5 to 10
bndNb2keep=0
RELATIVE=true -- bands strength is fc of distance between threshold and max heat (false: simple fc. of heat from 0 to max)
segCnt = structure.GetCount()
segCnt2 = segCnt
while structure.GetSecondaryStructure ( segCnt2 ) == "M" do segCnt2 = segCnt2 - 1 end
segStart=1
segEnd=segCnt2
--
-- end of globals section
--
function r4 ( i )
return i - i % 0.0001
end
function SortByHeat ( tab )
local ii
local jj
for ii = 1, #tab - 1 do
for jj = ii + 1, #tab do
local h1 = tab [ ii ] [ 3 ]
local h2 = tab [ jj ] [ 3 ]
if h2 > h1 then
tab [ ii ], tab [ jj ] = tab [ jj ], tab [ ii ]
end
end
end
return tab
end
function GetOnlyContacts()
tHeat=0
heatmap = {}
local ii
local jj
for ii = segStart, segEnd - 1 do -- 04/06/2004
for jj = ii + 1, segEnd do -- 04/06/2004
if ( ii ~= jj ) then
local heat = contactmap.GetHeat ( ii, jj )
if ( heat > 0 ) then
local heatpnt = { ii, jj, heat }
heatmap [ #heatmap + 1 ] = heatpnt
tHeat = tHeat + heat
end
end
end
end
end
function GetContacts( )
local ii
local jj
GetOnlyContacts()
print ( #heatmap .. " contacts with non-zero heat found" )
if ( #heatmap > 0 ) then
if( #heatmap > 100 ) then -- no sorting to save time -- EXPERIMENTAL
print("Too many contacts. Please be restrictive in options")
if GetParamsSmall() then
GetOnlyContacts() -- reset of (smaler) contact map
end
else
print("Sorting, please wait ...")
SortByHeat ( heatmap )
end
if (#heatmap < 20 or ii==1 or ii== #heatmap) then
print ( "seg1,seg2,heat" )
end
minHeat = 9999999
maxHeat = 0
for ii = 1, #heatmap do
if (#heatmap < 20 or ii==1 or ii== #heatmap) then
print ( heatmap [ ii ] [ 1 ]
.. "," ..
heatmap [ ii ] [ 2 ]
.. "," ..
heatmap [ ii ] [ 3 ] )
end
if heatmap [ ii ] [ 3 ] > maxHeat then maxHeat = heatmap [ ii ] [ 3 ] end
if heatmap [ ii ] [ 3 ] < minHeat then minHeat = heatmap [ ii ] [ 3 ] end
end
print ( "minimum contact heat = " .. r4 ( minHeat ) )
print ( "maximum contact heat = " .. r4 ( maxHeat ) )
meanHeat = tHeat / #heatmap
print ( "mean contact heat = " .. r4 ( meanHeat ) )
ii = math.floor ( #heatmap / 2 )
mediHeat = heatmap [ ii ] [ 3 ]
if #heatmap % 2 == 0 then -- even number of entries
ii = ii + 1
mediHeat = ( mediHeat + heatmap [ ii ] [ 3 ] )/2 -- corrected BK 04/06/2014
end
print ( "median contact heat = " .. r4 ( mediHeat ) )
end
end
function BandContacts ()
local ii
local bndCnt = 0
local bandstrength=1-- new 04/06/2014 strength fc of heat
local heatrange=maxHeat-bndcut-- new 04/06/2014 strength fc of heat
if heatrange == 0 then heatrange=maxHeat end -- fixed bug 07/06/2014
local bandnum=0
for ii = 1, bndNb2keep do -- 07/06/2014 takes the x best bands
if heatmap [ ii ] [ 3 ] >= bndcut then
if RELATIVE then
bandstrength= ((heatmap [ ii ] [ 3 ]-bndcut)/heatrange)*strengthFactor or strengthFactor-- new 04/06/2014 strength fc of heat (or 1)
--NB: strength is fc. of relative heat from threshold to max (not absolute)
else
bandstrength= ((heatmap [ ii ] [ 3 ])/maxHeat)*strengthFactor or strengthFactor-- new 04/06/2014 strength fc of heat (or 1)
--NB: strength is fc. of absolute heat
end
bandnum=band.AddBetweenSegments ( heatmap [ ii ] [ 1 ], heatmap [ ii ] [ 2 ] )
--print("band n "..bandnum.." / "..#heatmap)
if bandnum > 0 then -- else bug some bands are not created
band.SetStrength(bandnum,bandstrength) -- new 04/06/2014 strength fc of heat
end
bndCnt = bndCnt + 1
else
break
end
end
print ( "contact heat cutoff = " .. bndcut )
print ( bndCnt .. " contacts banded" )
end
function GetParams()
local dlg = dialog.CreateDialog( ReVersion )
if #heatmap == 0 then
dlg.l0 = dialog.AddLabel ( "No contacts found." )
dlg.l1 = dialog.AddLabel ( "This recipe is for puzzles with a contact map." )
dlg.cancel = dialog.AddButton ( "Cancel", 0 )
dialog.Show ( dlg )
return false
else
dlg.l0 = dialog.AddLabel ( #heatmap .. " contacts with non-zero heat found" )
dlg.l1 = dialog.AddLabel ( "minimum contact heat = " .. r4 ( minHeat ) )
dlg.l2 = dialog.AddLabel ( "maximum contact heat = " .. r4 ( maxHeat ) )
dlg.l3 = dialog.AddLabel ( "mean contact heat = " .. r4 ( meanHeat ) )
dlg.l4 = dialog.AddLabel ( "median contact heat = " .. r4 ( mediHeat ) )
if not meanHeat==maxHeat then
dlg.l5 = dialog.AddLabel ( "Select minimum heat to band" )-- 07/06/2014 (otherways bug)
dlg.bndpct = dialog.AddSlider ( "Heat cutoff" , meanHeat, minHeat, maxHeat, 3 )
dlg.RELATIVE = dialog.AddCheckbox("cutoff band strength = 0", RELATIVE)
dlg.l6 = dialog.AddLabel ( "unchecked: cutoff band strength fc of heat")
end
if bndNb2keep==0 then
if #heatmap >bndNb2keep then bndNb2keep= #heatmap end
if #heatmap >100 then bndNb2keep= 100 end
end
dlg.bndNb2keep=dialog.AddSlider ( "Band best:" , bndNb2keep, 1, #heatmap, 0 ) -- 07/06/2014
dlg.strengthFactor = dialog.AddSlider ( "Max band strength" , strengthFactor, 0.5, 10, 2 ) -- 04/06/2014
dlg.segStart=dialog.AddTextbox("From seg ", segStart) -- 04/06/2014
dlg.segEnd=dialog.AddTextbox("To seg ", segEnd) -- 04/06/2014
dlg.ok = dialog.AddButton ( "OK", 1 )
dlg.cancel = dialog.AddButton ( "Cancel", 0 )
if dialog.Show ( dlg ) > 0 then
if not meanHeat==maxHeat then
bndcut = dlg.bndpct.value
bndNb2keep = dlg.bndNb2keep.value -- 07/06/2014
RELATIVE=dlg.RELATIVE.value -- 07/06/2014
end
strengthFactor = dlg.strengthFactor.value
segStart = dlg.segStart.value
segEnd = dlg.segEnd.value
return true
else
print( "dialog cancelled" )
end
end
return false
end
function GetParamsSmall()
local dlg = dialog.CreateDialog( ReVersion )
if #heatmap == 0 then
dlg.l0 = dialog.AddLabel ( "No contacts found." )
dlg.l1 = dialog.AddLabel ( "This recipe is for puzzles with a contact map." )
dlg.cancel = dialog.AddButton ( "Cancel", 0 )
dialog.Show ( dlg )
return false
else
dlg.l0 = dialog.AddLabel ( #heatmap .. " contacts with non-zero heat found" )
--dlg.l1 = dialog.AddLabel ( "minimum contact heat = " .. r4 ( minHeat ) )
--dlg.l2 = dialog.AddLabel ( "maximum contact heat = " .. r4 ( maxHeat ) )
--dlg.l3 = dialog.AddLabel ( "mean contact heat = " .. r4 ( meanHeat ) )
--dlg.l4 = dialog.AddLabel ( "median contact heat = " .. r4 ( mediHeat ) )
--dlg.l5 = dialog.AddLabel ( "Select minimum heat to band" )
--dlg.bndpct = dialog.AddSlider ( "Heat cutoff" , meanHeat, minHeat, maxHeat, 3 )
--dlg.strengthFactor = dialog.AddSlider ( "Max band strength" , strengthFactor, 0.5, 10, 2 ) -- 04/06/2014
if #heatmap >bndNb2keep then bndNb2keep= #heatmap end
if #heatmap >100 then bndNb2keep= 100 end
dlg.bndNb2keep=dialog.AddSlider ( "Band best:" , bndNb2keep, 1, #heatmap, 0 ) -- 07/06/2014
dlg.segStart=dialog.AddTextbox("From seg ", segStart) -- 04/06/2014
dlg.segEnd=dialog.AddTextbox("To seg ", segEnd) -- 04/06/2014
dlg.ok = dialog.AddButton ( "OK", 1 )
dlg.cancel = dialog.AddButton ( "Cancel", 0 )
if dialog.Show ( dlg ) > 0 then
--bndcut = dlg.bndpct.value
--strengthFactor = dlg.strengthFactor.value
segStart = dlg.segStart.value
segEnd = dlg.segEnd.value
bndNb2keep = dlg.bndNb2keep.value -- 07/06/2014
return true
else
print( "dialog cancelled" )
end
end
return false
end
function cleanup ( error )
print ( error )
end
function main()
print ( ReVersion )
GetContacts ()
if GetParams() then
BandContacts ()
end
end
xpcall ( main, cleanup )