Profile
Name: |
Report on Structures v0.03 |
ID: |
16511 |
Created on: |
Wed, 11/17/2010 - 11:21 |
Updated on: |
Wed, 11/17/2010 - 19:21 |
Description: |
detail report on total score or part score for each segment and summary (total points / average) over each loop, helix and sheet |
Best For
Comments
|
| | |
|
Want to try?
Add to Cookbook!
To download recipes to your cookbook, you need to have the game client running.
| |
| | |
| | |
|
-- Report on Structures, by John McLeod
-- detail report on total score or one part score for each segment
-- and summary (total points / average) over each successive structure
-- (loop, helix and sheet) in the puzzle
--
-- v0.01 -- November 15, 2010
-- v0.02 -- November 16, 2010 -- ugly but nearly usable
-- v0.03 -- November 17, 2010 -- lines now double up so report fits in Recipe Window
-- and it now doesn't crash for ligand puzzles;
-- Amino Acid types list added at end of report
-- USER MODIFIES
local select_score_type = 0 -- total score <-- change this to select a part score
-- 1) clashing, 2) packing, 3) hiding, 4) bonding, 5) backbone, 6) sidechain,
-- 7) reference, 8) disulfides, 9) other
-- Funky variable with fragile calculation
-- This will work as long as puzzle ligands are of structure type "M"
-- and occur at the end of the puzzle. If this changes then the following will
-- require manual setting
local puzzle_num_ligands = 0
do -- start constructor for variable puzzle_num_ligands
local seg_no = get_segment_count()
while get_ss(seg_no) == "M" do -- M structures are ligands, and they happen at the end
puzzle_num_ligands = puzzle_num_ligands + 1
seg_no = seg_no - 1
end
end -- end of constructor for variable puzzle_num_ligands
-- TABLES
-- Table attr
local attr = { -- refer to the documentation for "Get segment score part" in the Foldit Wiki
[0] = "total score", -- 0 -- total score
"clashing", -- 1 -- clashing
"packing", -- 2 -- packing
"hiding", -- 3 -- hiding
"bonding", -- 4 -- bonding
"backbone", -- 5 -- backbone
"sidechain", -- 6 -- sidechain
"reference", -- 7 -- reference
"disulfides", -- 8 -- disulfides
"other" -- 9 -- other
}
--[[ table attr: IMPORTANT CLARIFICATION ON "REFERENCE" PART SCORE
beta_helix's comment dated Nov 2, 2010 under this post http://fold.it/portal/node/987935 ...
These [reference] values do not have anything to do with the hydrophobicity of the different
amino acids, they are actually weights that only affect the score when mutating from one
sidechain to another (so they have nothing to do with prediction puzzles).
For example, when you mutate from a smaller sidechain to a big one (such as Tryptophan) you
are going to have a lot more interactions that will be reflected in the score function, so
Trp is penalized with -9.1 Phe, His & Tyr all have similar penalties as well.
These reference weights were set after careful optimizations on a large benchmark
of native proteins.
]]--
-- Table PuzzleStructsTab
local PuzzleStructsTab = {} -- consecutive elements are of the form { start_seg, end_seg, structure_code }
local PuzzleStructs_start_ind = 1
local PuzzleStructs_end_ind = 2
local PuzzleStructs_ss_ind = 3
local PuzzleStructs_num_structs = 0
do -- constructor for PuzzleStructsTab
local puzzle_last_seg = get_segment_count() - puzzle_num_ligands
local current_struct = ''
local current_start_seg = 0
local current_struct_ind = 0
current_struct = get_ss(1)
current_struct_ind = 1
current_start_seg = 1
PuzzleStructsTab[current_struct_ind] = {}
PuzzleStructsTab[current_struct_ind][PuzzleStructs_start_ind] = current_start_seg
PuzzleStructsTab[current_struct_ind][PuzzleStructs_ss_ind] = current_struct
for x=2,puzzle_last_seg do
if get_ss(x) ~= current_struct then
current_struct = get_ss(x)
current_struct_ind = current_struct_ind + 1
current_start_seg = x
PuzzleStructsTab[current_struct_ind] = {}
PuzzleStructsTab[current_struct_ind][PuzzleStructs_start_ind] = current_start_seg
PuzzleStructsTab[current_struct_ind][PuzzleStructs_ss_ind] = current_struct
PuzzleStructsTab[current_struct_ind - 1][PuzzleStructs_end_ind] = x - 1
end
end
PuzzleStructsTab[current_struct_ind][PuzzleStructs_end_ind] = puzzle_last_seg
PuzzleStructs_num_structs = current_struct_ind
end -- constructor for PuzzleStructsTab
-- Table PuzzleStructsKillList
local PuzzleStructsKillList = { } -- structs that print with next structs to conserve lines
do -- constructor for PuzzleStructsKillList
local max_structs_to_print = 45 -- this is the max capacity of the Recipe Output Window
-- reduced by the number of other lines this report prints
local good_list = {} -- structs available to defer printing (not last)
do -- constructor for table good_list
for x=1,(PuzzleStructs_num_structs - 1) do
good_list[x] = true
end
end -- constructor for table good_list
for x=1,(PuzzleStructs_num_structs - max_structs_to_print) do
new_shortest=1
while good_list[new_shortest] == false do
new_shortest = new_shortest + 1
end
for y=new_shortest,(PuzzleStructs_num_structs - 1) do
if (good_list[y] == true) and
(
(
PuzzleStructsTab[y][PuzzleStructs_end_ind] -
PuzzleStructsTab[y][PuzzleStructs_start_ind]
)
<
(
PuzzleStructsTab[new_shortest][PuzzleStructs_end_ind] -
PuzzleStructsTab[new_shortest][PuzzleStructs_start_ind]
)
)
then
new_shortest = y
end
end
good_list[new_shortest] = false
PuzzleStructsKillList[new_shortest] = true
end
end -- constructor for PuzzleStructsKillList
-- Tables UpByLow and LowByUp
local UpByLow = { -- a table of uppercase letters indexed by lowercase letters
['a']='A',['b']='B',['c']='C',['d']='D',['e']='E',
['f']='F',['g']='G',['h']='H',['i']='I',['j']='J',
['k']='K',['l']='L',['m']='M',['n']='N',['o']='O',
['p']='P',['q']='Q',['r']='R',['s']='S',['t']='T',
['u']='U',['v']='V',['w']='W',['x']='X',['y']='Y',
['z']='Z'
}
local LowByUp = { -- a table of lowercase letters indexed by uppercase letters
['A']='a',['B']='b',['C']='c',['D']='d',['E']='e',
['F']='f',['G']='g',['H']='h',['I']='i',['J']='j',
['K']='k',['L']='l',['M']='m',['N']='n',['O']='o',
['P']='p',['Q']='q',['R']='r',['S']='s',['T']='t',
['U']='u',['V']='v',['W']='w',['X']='x',['Y']='y',
['Z']='z'
}
-- Table NATO_Phonetic_Alphabet
local NATO_Phonetic_Alphabet = { -- to give distinctive names to the first 26 structures
'Alfa', 'Bravo', 'Charlie', 'Delta', 'Echo',
'Foxtrot', 'Golf', 'Hotel', 'India', 'Juliet',
'Kilo', 'Lima', 'Mike', 'November', 'Oscar',
'Papa', 'Quebec', 'Romeo', 'Sierra', 'Tango',
'Uniform', 'Victor', 'Whiskey', 'Xray', 'Yankee', 'Zulu'
}
-- Table lua_char
local lua_char = { -- the LUA character set
[0] = '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', '\008', '\009',
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', '\018', '\019',
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', '\028', '\029',
'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', '\038', '\039',
'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', '\048', '\049',
'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', '\058', '\059',
'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', '\068', '\069',
'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', '\078', '\079',
'\080', '\081', '\082', '\083', '\084', '\085', '\086', '\087', '\088', '\089',
'\090', '\091', '\092', '\093', '\094', '\095', '\096', '\097', '\098', '\099',
'\100', '\101', '\102', '\103', '\104', '\105', '\106', '\107', '\108', '\109',
'\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117', '\118', '\119',
'\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127', '\128', '\129',
'\130', '\131', '\132', '\133', '\134', '\135', '\136', '\137', '\138', '\139',
'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', '\148', '\149',
'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', '\158', '\159',
'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', '\168', '\169',
'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', '\178', '\179',
'\180', '\181', '\182', '\183', '\184', '\185', '\186', '\187', '\188', '\189',
'\190', '\191', '\192', '\193', '\194', '\195', '\196', '\197', '\198', '\199',
'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', '\208', '\209',
'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', '\218', '\219',
'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', '\228', '\229',
'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', '\238', '\239',
'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', '\248', '\249',
'\250', '\251', '\252', '\253', '\254', '\255'
}
-- Table AminoAcidTable
local AminoAcidTable = { -- { 'short', 'long' } by lowercase letter code
['a'] = { 'Ala', 'Alanine' },
['b'] = { 'Asx', 'Asparagine or Aspartic acid' }, -- not in Foldit (as of Nov 15, 2010)
['c'] = { 'Cys', 'Cysteine' },
['d'] = { 'Asp', 'Aspartic acid' },
['e'] = { 'Glu', 'Glutamic acid' },
['f'] = { 'Phe', 'Phenylalanine' },
['g'] = { 'Gly', 'Glycine' },
['h'] = { 'His', 'Histidine' },
['i'] = { 'Ile', 'Isoleucine' },
['j'] = { 'Xle', 'Leucine or Isoleucine' }, -- not in Foldit (as of Nov 15, 2010)
['k'] = { 'Lys', 'Lysine' },
['l'] = { 'Leu', 'Leucine' },
['m'] = { 'Met', 'Methionine' },
['n'] = { 'Asn', 'Asparagine' },
['o'] = { 'Pyl', 'Pyrrolysine' }, -- not in Foldit (as of Nov 15, 2010)
['p'] = { 'Pro', 'Proline' },
['q'] = { 'Gln', 'Glutamine' },
['r'] = { 'Arg', 'Arginine' },
['s'] = { 'Ser', 'Serine' },
['t'] = { 'Thr', 'Threonine' },
['u'] = { 'Sec', 'Selenocysteine' }, -- not in Foldit (as of Nov 15, 2010)
['v'] = { 'Val', 'Valine' },
['w'] = { 'Trp', 'Tryptophan' },
['x'] = { 'Xaa', 'Unspecified or unknown amino acid' }, -- not in Foldit (as of Nov 15, 2010)
['y'] = { 'Tyr', 'Tyrosine' },
['z'] = { 'Glx', 'Glutamine or glutamic acid' } -- not in Foldit (as of Nov 15, 2010)
}
local AminoAcidTable_short_ind = 1
local AminoAcidTable_long_ind = 2
-- FUNCTIONS
function Round_to_10ths(num_in_arg) -- returns string num_string, number len
-- Rounds number input to nearest tenth and returns a table with rounded number
-- as a string in the first element and the length of the string as the second
local num_in = 0
local num_out_str = ''
local num_out_len = 0
local whole_part = 0 -- whole number part of num
local frac_part = 0 -- fractional part of num
local dec_part = 0 -- will be 0,1,..., or 9
if num_in_arg == nil then -- no input, return as if zero
return "0.0", 3
else
num_in = num_in_arg + 0
end
-- round up or down to nearest tenth
if (num_in % 0.1) < 0.05 then
num_in = num_in - (num_in % 0.1) -- round down
else
num_in = num_in + (0.1 - (num_in % 0.1)) -- round up
end
if num_in < 0 then
-- flip to absolute value, place minus sign in output string
num_out_str = num_out_str .. '-'
num_out_len = num_out_len + 1
num_in = -num_in
end
num_in = num_in + 0.00001 -- add salt to defend against small arithmetic errors
frac_part = num_in % 1 -- is (about) .0 .1, .2, ... or .9 since we've already rounded
whole_part = num_in - frac_part
num_out_str = num_out_str .. whole_part -- put whole number part in as string
num_out_len = num_out_len + 1 -- always have ones place
-- determine additional places to the left of ones place
local scale = 10
while scale <= whole_part do
num_out_len = num_out_len + 1
scale = scale * 10
end
num_out_str = num_out_str .. '.' -- put in decimal point
num_out_len = num_out_len + 1
dec_part = frac_part * 10
frac_part = dec_part % 1
dec_part = dec_part - frac_part -- remove the salt
num_out_str = num_out_str .. dec_part -- put in tenths digit
num_out_len = num_out_len + 1
return num_out_str, num_out_len
end -- Round_to_10ths
function Desperate_String_Len(string_arg) -- returns length of string_arg
-- mimics function of string.len()
-- until Foldit starts allowing the LUA string library
--
-- requires table lua_char
if string_arg == nil then
return 0
end
local return_val = 0
local compare_str = ''
local search_ind = 0
-- Rebuilds string_arg one bit at a time, counting the number
-- of characters until completion. What's not to love?
while compare_str ~= string_arg do
search_ind = 0
for current_bit=1,8 do
if compare_str .. lua_char[search_ind + 2 ^ (8 - current_bit)] <= string_arg then
search_ind = search_ind + 2 ^ (8 - current_bit)
end
end
compare_str = compare_str .. lua_char[search_ind]
return_val = return_val + 1
end
return return_val
end -- function Desperate_String_Len
function Desperate_Left_Fill(string_arg, field_width, fill_char)
-- NOTE: requires function Desperate_String_Len
--
-- returns string_arg with enough instances of fill_char
-- (assumed to be single character) concatenated to the left
-- so that returned string is field_width wide
--
-- fill_char defaults to a space
local return_string = ''
local char_to_add = ''
local num_chars_to_add = 0
if string_arg == nil then
return ''
elseif field_width == nil then
return string_arg
else
return_string = string_arg
end
if fill_char == nil then
char_to_add = ' ' -- space
else
char_to_add = fill_char
end
num_chars_to_add = field_width - Desperate_String_Len(return_string)
for i=1,num_chars_to_add do
return_string = char_to_add .. return_string
end
return return_string
end -- function Desperate_Left_Fill
function Print_Score_in_1000ths(Prefix)
-- NOTE: requires function Desperate_Left_Fill
--
-- Prints the Foldit score truncated to the nearest thousandth,
-- as displayed in the game in the "Advanced GUI"
-- If provided a Prefix string argument will print ahead of the score
local score_str = ''
if Prefix ~= nil then -- concatenate Prefix ahead of score if one provided
score_str = score_str .. Prefix
end
local negative_score = true -- tells get_score to also return negatives
local score_num = get_score(negative_score) -- present game score
local int_part = 0 -- whole number part of score
local dec_part = 0 -- fractional part of score
local dec_part_thousandths = 0 -- truncated thousandths part of fraction: 0 to 999
if score_num < 0 then
-- flip to absolute value, save minus sign in string
score_str = score_str .. '-'
score_num = -score_num
end
dec_part = score_num % 1
int_part = score_num - dec_part
dec_part_thousandths = (dec_part * 1000) - ((dec_part * 1000) % 1)
score_str = score_str .. int_part -- put whole number part in string
score_str = score_str .. '.' -- put in decimal point
score_str = score_str .. Desperate_Left_Fill(dec_part_thousandths .. '', 3, '0') -- put in decimal places
print(score_str)
end -- function Print_Score_in_1000ths
function Struct_Sequential_Name(seq_no)
-- Returns a distinctive "name" string for the seq_no'th structure.
--
-- input argument seq_no = 1, 2, ..., 26 (numbers) yields one of the
-- twenty-six "letters" of the NATO Phonetic Alphabet. Other values
-- for seq_no are just reflected back as strings.
--
-- requires table NATO_Phonetic_Alphabet
if seq_no == nil then -- no input argument at all
return '???' -- huh?
elseif seq_no == '' then -- input argument is empty string
return '???' -- huh?
else
-- NO ACTION: we've at least got an input arg seq_no
end
if NATO_Phonetic_Alphabet[seq_no] == nil then -- input arg out of range of the table
return seq_no .. '' -- return input argument itself (as string)
else -- input arg is in range of table, return table element
return NATO_Phonetic_Alphabet[seq_no]
end
end -- function Struct_Sequential_Name
function To_Upper(char_in)
-- If string input argument char_in is a single lowercase letter than the equivalent uppercase letter is returned.
-- Otherwise char_in is returned (as a string)
--
-- Requires table UpByLow
local char_in_str = ''
if char_in == nil then -- no input argument at all
return ''
else
char_in_str = char_in .. '' -- force input arg to be string
end
if UpByLow[char_in_str] == nil then -- input arg out of range of the table
return char_in_str -- return input argument itself (as string)
else -- input arg is in range of table, return table element
return UpByLow[char_in_str]
end
end -- function To_Upper
function To_Lower(char_in)
-- If string input argument char_in is a single lowercase letter than the equivalent lowercase letter is returned.
-- Otherwise char_in is returned (as a string)
--
-- Requires table LowByUp
local char_in_str = ''
if char_in == nil then -- no input argument at all
return ''
else
char_in_str = char_in .. '' -- force input arg to be string
end
if LowByUp[char_in_str] == nil then -- input arg out of range of the table
return char_in_str -- return input argument itself (as string)
else -- input arg is in range of table, return table element
return LowByUp[char_in_str]
end
end -- function To_Lower
function Amino_Acid_Name(aa_code, long_name_req)
-- Returns the name of the amino acid, the short 3-letter code by default
--
-- argument aa_code is one-letter string, 1-letter amino acid code
-- if long_name_req is present and boolean true then the long name of the aa is returned
--
-- requires table AminoAcidTable
-- requires function To_Lower
local boolean long_name_req_bool = false
local aa_code_char = ''
if aa_code == nil then -- no input argument at all
return '???' -- huh?
else
aa_code_char = To_Lower(aa_code .. '') -- Foldit uses lowercase aa codes
end
if long_name_req == nil then -- no second argument, default is short name
long_name_req_bool = false
else
long_name_req_bool = (false or long_name_req)
end
if AminoAcidTable[aa_code_char] == nil then -- table has no aa for this code
return '???' -- huh?
elseif long_name_req_bool then
return AminoAcidTable[aa_code_char][AminoAcidTable_long_ind]
else
return AminoAcidTable[aa_code_char][AminoAcidTable_short_ind]
end
end -- function Amino_Acid_Name
-- MAIN
print("begin Report on Structures v0.03")
print("Score Type: ", attr[select_score_type])
-- quick dirty summary for v0.01, v0.02 and v0.03 release
-- needs work obviously
local Struct_Types = { ["L"] = "Loop", ["E"] = "Sheet", ["H"] = "Helix" }
do -- for loop wrapper
-- current_line goes outside loop because it can accumulate
-- so that a large number of structures won't cause the report
-- to have more lines than the script output window can handle
local current_line = ""
for x=1,PuzzleStructs_num_structs do
local score_sum = 0
tot_score_str = ""
ave_score_str = ""
for y=PuzzleStructsTab[x][PuzzleStructs_start_ind],
PuzzleStructsTab[x][PuzzleStructs_end_ind] do
if select_score_type == 0 then -- total score
score_sum = score_sum + get_segment_score(y)
else
score_sum = score_sum + get_segment_score_part(attr[select_score_type], y)
end
end
tot_score_str = Round_to_10ths(score_sum)
ave_score_str = Round_to_10ths(score_sum / ( ( PuzzleStructsTab[x][PuzzleStructs_end_ind] -
PuzzleStructsTab[x][PuzzleStructs_start_ind] ) + 1) )
-- print(Struct_Types[ PuzzleStructsTab[x][PuzzleStructs_ss_ind] ], " ",
-- Struct_Sequential_Name(x), "(",
-- PuzzleStructsTab[x][PuzzleStructs_start_ind], ",",
-- PuzzleStructsTab[x][PuzzleStructs_end_ind], ") -- tot: ",
-- tot_score_str, " ave: ", ave_score_str
-- )
current_line = current_line .. Struct_Types[ PuzzleStructsTab[x][PuzzleStructs_ss_ind] ] .. " " ..
Struct_Sequential_Name(x) .. "(" ..
PuzzleStructsTab[x][PuzzleStructs_start_ind] .. "," ..
PuzzleStructsTab[x][PuzzleStructs_end_ind] .. ") -- [[tot: " ..
tot_score_str .. " ave: " .. ave_score_str .. "]]"
-- Details here
local detail_score_str = ""
for y=PuzzleStructsTab[x][PuzzleStructs_start_ind],PuzzleStructsTab[x][PuzzleStructs_end_ind] do
if select_score_type == 0 then -- total score
detail_score_str = Round_to_10ths(get_segment_score(y))
else -- part score
detail_score_str =
Round_to_10ths(get_segment_score_part(attr[select_score_type], y))
end
current_line = current_line .. ", " .. y .. ")" ..
Amino_Acid_Name(get_aa(y)) .. " " .. detail_score_str
end
if PuzzleStructsKillList[x] == nil then -- OK to print what we've got
print(current_line)
current_line = ""
else -- print with next line to save space
current_line = current_line .. "; "
end
end -- for loop
end -- for loop wrapper
do -- print a line with all the Amino Acid names
local current_line = "Amino Acids list: "
for x=97,121 do -- those are the decimal ASCII values from 'a' to 'y'
current_line = current_line .. Amino_Acid_Name(lua_char[x]) ..
"(" .. To_Upper(lua_char[x]) .. ") " ..
Amino_Acid_Name(lua_char[x], true) .. ", " -- second parm true for long AA name
end
current_line = current_line .. Amino_Acid_Name(lua_char[122]) .. -- 122 is for 'z'
"(" .. To_Upper(lua_char[122]) .. ") " ..
Amino_Acid_Name(lua_char[122], true) -- no comma after last in list
print(current_line)
end -- print a line with all the Amino Acid names
Print_Score_in_1000ths("Current Game Score: ")
print("end Report on Structures v0.03")