Icon representing a recipe

Recipe: print protein 2.4

created by LociOiling

Profile


Name
print protein 2.4
ID
102243
Shared with
Public
Parent
print protein 2.3
Children
Created on
November 15, 2016 at 19:51 PM UTC
Updated on
November 15, 2016 at 19:51 PM UTC
Description

Updated version of "print protein lua2 V0" by marie_s. Version 2.1 includes rulers. Version 2.2 fixes a bug and adds average subscore per segment. Version 2.3 adds density analysis for Electron Density puzzles and makes the main dialog shorter. Version 2.4 works around a textbox bug for cut-and-paste and fixes the subscore selection logic.

Best for


Code


--[[ print protein info on the protein - Concatenation of recipes, part of recipes or functions by: Tlaloc, spvincent, seagate, John McLeod, Crashguard303, Gary Forbis and authors on wiki Now with code from Timo van der Laan and and more code from spvincent. Borrowed HerobrinesArmy's idea for copy-and-paste on the segment score table, plus option for including atom and rotamer counts. Intended use: 1. Run 2. Open the script log (scriptlog.default.xml) in a text editor. 3. Strip off the start and end lines and save it as a text file with another name. 4. Import that into Excel as a comma-delimited text file. Alternately: 3. Select and copy the lines containing the score detail. 4. Paste into a spreadsheet or other program that accepts CSV (comma-separated values) format. Yet another alternative: 3. Select and copy the "score report" from the new "copy-and-paste" dialog. 4. Paste into the spreadsheet of your choice. version history --------------- print protein lua v0 - 2011/08/15 - marie_s (Marie Suchard) print protein 2.0 - 2015/05/13 - LociOiling + add dialog + use active subscores + restrict scope of most variables + convert amino acid table to keyed format + added kludges specific to puzzle 879 (hope they are never needed) + add adjustable rounding, eliminate existing "no trunc" logic + made tab the default delimiter, with comma or semicolon as alternates + add detailed scoring information + add "modifiable sections" report, make original "mutable" report optional + make "mini contact table" optional + in subscores report, add option for atom and rotamer counts, make hydropathy index optional + add warnings for unknown amino acid or secondary structure codes, subtotal mismatches, suspect ligands + and copy-and-paste dialog for subscores, primary and secondary structure print protein 2.1 - 2016/03/23 - LociOiling + add ruler print protein 2.2 - 2016/04/18 - LociOiling + fix crash in normal ligand case + add mean score to subscore display print protein 2.3 - 2016/10/27 - LociOiling + add density analysis for ED puzzles * density by amino acid * density by aromatic vs. non-aromatic * density by aliphatic vs. non-aliphatic * density by hydrophobic vs. hydrophilic * density deviation, showing whether each segment is above or below mean density for the segment's amino acid type + move less-used parms to second screen to avoid screen overflow print protein 2.4 - 2016/11/15 - LociOiling + move ED items to separate dialog to avoid textbox bug + add "active" flag to active subscores table to fix totally messed up selection logic; ripple change to GetScore ]]-- -- -- globals section -- Recipe = "print protein" Version = "2.4" ReVersion = Recipe .. " " .. Version segCnt = structure.GetCount() segCnt2 = segCnt isLigand = false subScores = {} -- subscore table gTotal = 0 -- grand total all subscores BoxScore = { tSubScores = 0, -- total of active subscores, all segments tSegScores = 0, -- total of segment scores tScoreFilt = 0, -- total score, filters on tScoreFOff = 0, -- total score, filters off tScoreNrgy = 0, -- total energy score tScoreBonus = 0, -- total filter bonus tScoreForm = 0, -- subscores + filter bonus + 8000 tScoreDark = 0, -- total "dark" score } kHydro = false -- include hydropathy index kAtom = false -- include atom count kRotamer = false -- include rotamer count kRound = 3 -- number of digits for rounding kFax = 10 ^ -kRound -- initial rounding factor dtab = true delim = "\t" -- default delimiter is tab character dcomma = false -- allow user to select comma dsemic = false -- allow user to select semicolon kMutDet = false -- detailed mutable report kContact = false -- contact table kDensity = false -- density report jDensity = false -- true if density component present -- -- indexes for helixList, sheetList, structList -- STRCTTYP = 1 --structure type STRCTSTR = 2 --starting segment STRCTEND = 3 --ending segment STRCTUSE = 4 --use flag (boolean) STRCTSCR = 5 --score -- -- indexes for amino acid table -- AASHORT = 1 -- three-letter code AALONG = 2 -- full name AAPOLARITY = 3 -- polarity (text) AAACIDITY = 4 -- acidity (text) AAHYDROPATHY = 5 -- hydropathy index -- -- residues with -- in front (commented) are not in Foldit (as of Nov 15, 2010) -- one-letter amino acid code is the table key -- AminoAcids = { a = { "Ala", "Alanine", "nonpolar", "neutral", 1.8 }, -- b = { "Asx", "Asparagine or Aspartic acid" }, c = { "Cys", "Cysteine", "nonpolar", "neutral", 2.5 }, d = { "Asp", "Aspartate", "polar", "negative", -3.5 }, e = { "Glu", "Glutamate", "polar", "negative", -3.5 }, f = { "Phe", "Phenylalanine", "nonpolar", "neutral", 2.8 }, g = { "Gly", "Glycine", "nonpolar", "neutral", -0.4 }, h = { "His", "Histidine", "polar", "neutral", -3.2 }, i = { "Ile", "Isoleucine", "nonpolar", "neutral", 4.5 }, -- j = { "Xle", "Leucine or Isoleucine" }, k = { "Lys", "Lysine", "polar", "positive", -3.9 }, l = { "Leu", "Leucine", "nonpolar", "neutral", 3.8 }, m = { "Met", "Methionine ", "nonpolar", "neutral", 1.9 }, n = { "Asn", "Asparagine", "polar", "neutral", -3.5 }, -- o = { "Pyl", "Pyrrolysine" }, p = { "Pro", "Proline", "nonpolar", "neutral", -1.6 }, q = { "Gln", "Glutamine", "polar", "neutral", -3.5 }, r = { "Arg", "Arginine", "polar", "positive", -4.5 }, s = { "Ser", "Serine", "polar", "neutral", -0.8 }, t = { "Thr", "Threonine", "polar", "neutral", -0.7 }, -- u = { "Sec", "Selenocysteine" }, v = { "Val", "Valine", "nonpolar", "neutral", 4.2 }, w = { "Trp", "Tryptophan", "nonpolar", "neutral", -0.9 }, x = { "Xaa", "Unspecified/unknown", "", "", 0 }, -- kludge for puzzle 879 y = { "Tyr", "Tyrosine", "polar", "neutral", -1.3 }, -- z = { "Glx", "Glutamine or glutamic acid" } , } -- -- amino acid types -- Aromatic = { f = { "phenylalanine", }, h = { "histidine", }, w = { "tryptophan", }, y = { "tyrosine", }, } Aliphatic = { i = { "isoleucine", }, l = { "leucine", }, v = { "valine", }, } Hydrophobic = { a = { "alanine", }, c = { "cysteine", }, f = { "phenylalanine", }, i = { "isoleucine", }, l = { "leucine", }, m = { "methionine", }, p = { "proline", }, v = { "valine", }, w = { "tryptophan", }, y = { "tyrosine", }, } -- -- end of globals section -- -- -- function print score by spvincent -- function round ( x ) if x == nil then return "nil" end return x - x % kFax end -- -- Segment set and list module -- Notice that most functions assume that the sets are well formed -- (=ordered and no overlaps) -- 02-05-2012 TvdL Free to use for non commercial purposes -- function SegmentListToSet ( list ) -- retirer doublons local result = {} local f = 0 local l = -1 table.sort ( list ) for ii = 1, #list do if list [ ii ] ~= l + 1 and list [ ii ] ~= l then -- note: duplicates are removed if l > 0 then result [ #result + 1 ] = { f, l } end f = list [ ii ] end l = list [ ii ] end if l > 0 then result [ #result + 1 ] = { f, l } end return result end function SegmentSetToList ( set ) -- faire une liste a partir d'une zone local result = {} for ii = 1, #set do for k = set [ ii ] [ 1 ], set [ ii ] [ 2 ] do result [ #result + 1 ] = k end end return result end function SegmentCleanSet ( set ) -- Makes it well formed return SegmentListToSet ( SegmentSetToList ( set ) ) end function SegmentInvertSet ( set, maxseg ) -- Gives back all segments not in the set -- maxseg is added for ligand local result={} if maxseg == nil then maxseg = structure.GetCount () end if #set == 0 then return { { 1, maxseg } } end if set [ 1 ] [ 1 ] ~= 1 then result [ 1 ] = { 1, set [ 1 ] [ 1 ] - 1 } end for i = 2, #set do result [ #result + 1 ] = { set [ i - 1 ] [ 2 ] + 1, set [ i ] [ 1 ] - 1} end if set [ #set ] [ 2 ] ~= maxseg then result [ #result + 1 ] = { set [ #set ] [ 2 ] + 1, maxseg } end return result end function SegmentInList ( s, list ) -- verifier si segment est dans la liste table.sort ( list ) for ii = 1, #list do if list [ ii ] == s then return true elseif list [ ii ] > s then return false end end return false end function SegmentInSet ( set, s ) --verifie si segment est dans la zone for ii = 1, #set do if s >= set [ ii ] [ 1 ] and s <= set [ ii ] [ 2 ] then return true elseif s < set [ ii ] [ 1 ] then return false end end return false end function SegmentJoinList ( list1, list2 ) -- fusionner 2 listes de segments local result = list1 if result == nil then return list2 end for ii = 1, #list2 do result [ #result + 1 ] = list2 [ ii ] end table.sort ( result ) return result end function SegmentJoinSet ( set1, set2 ) --fusionner (ajouter) 2 zones return SegmentListToSet ( SegmentJoinList ( SegmentSetToList ( set1 ), SegmentSetToList ( set2 ) ) ) end function SegmentCommList ( list1, list2 ) -- chercher intersection de 2 listes local result = {} table.sort ( list1 ) table.sort ( list2 ) if #list2 == 0 then return result end local j = 1 for ii = 1, #list1 do while list2 [ j ] < list1 [ ii ] do j = j + 1 if j > #list2 then return result end end if list1 [ ii ] == list2 [ j ] then result [ #result + 1 ] = list1 [ ii ] end end return result end function SegmentCommSet ( set1, set2 ) -- intersection de 2 zones return SegmentListToSet ( SegmentCommList ( SegmentSetToList ( set1 ), SegmentSetToList ( set2 ) ) ) end function SegmentSetMinus ( set1, set2 ) return SegmentCommSet ( set1, SegmentInvertSet ( set2 ) ) end function SegmentPrintSet ( set ) print ( SegmentSetToString ( set ) ) end function SegmentSetToString ( set ) -- pour pouvoir imprimer local line = "" for ii = 1, #set do if ii ~= 1 then line = line .. ", " end line = line .. set [ ii ] [ 1 ] .. "-" .. set [ ii ] [ 2 ] end return line end function SegmentSetInSet ( set, sub ) if sub == nil then return true end -- Checks if sub is a proper subset of set for ii = 1, #sub do if not SegmentRangeInSet ( set, sub [ ii ] ) then return false end end return true end function SegmentRangeInSet ( set, range ) --verifier si zone est dans suite if range == nil or #range == 0 then return true end local bb = range [ 1 ] local ee = range [ 2 ] for ii = 1, #set do if bb >= set [ ii ] [ 1 ] and bb <= set [ ii ] [ 2 ] then return ( ee <= set [ ii ] [ 2 ] ) elseif ee <= set [ ii ] [ 1 ] then return false end end return false end function SegmentSetToBool ( set ) --vrai ou faux pour chaque segment utilisable ou non local result = {} for ii = 1, structure.GetCount () do result [ ii ] = SegmentInSet ( set, ii ) end return result end --- End of Segment Set module -- Module Find Segment Types function FindMutablesList () local result = {} for ii = 1, segCnt2 do if structure.IsMutable ( ii ) then result [ #result + 1 ] = ii end end return result end function FindMutables() return SegmentListToSet ( FindMutablesList () ) end function FindFrozenList () local result = {} for ii = 1, segCnt2 do if freeze.IsFrozen ( ii ) then result [ #result + 1 ] = ii end end return result end function FindFrozen () return SegmentListToSet ( FindFrozenList () ) end function FindLockedList () local result = {} for ii = 1, segCnt2 do if structure.IsLocked ( ii ) then result [ #result + 1 ] = ii end end return result end function FindLocked () return SegmentListToSet ( FindLockedList () ) end function FindZeroScoreList () local result = {} for ii = 1, segCnt do local sub = 0 for jj = 1, #subScores do sub = sub + current.GetSegmentEnergySubscore ( ii, subScores [ jj ] [ 1 ] ) end if sub == 0 then result [ #result + 1 ] = ii end end return result end function FindZeroScore () return SegmentListToSet ( FindZeroScoreList () ) end function FindSelectedList () local result = {} for ii = 1, segCnt do if selection.IsSelected ( ii ) then result [ #result + 1 ] = ii end end return result end function FindSelected() return SegmentListToSet ( FindSelectedList () ) end function FindAAtypeList ( aa ) local result = {} for ii = 1, segCnt2 do if structure.GetSecondaryStructure ( ii ) == aa then result [ #result + 1 ] = ii end end return result end function FindAAtype ( aa ) return SegmentListToSet ( FindAAtypeList ( aa ) ) end function FindAminotype ( at ) --NOTE: only this one gives a list not a set local result={} for ii = 1, segCnt2 do if structure.GetAminoAcid ( ii ) == at then result [ #result + 1 ] = ii end end return result end -- -- end Module Find Segment Types -- -- -- count segments, check for ligand -- function GetSeCount () segCnt = structure.GetCount() -- -- ultra-paranoid method for detecting ligands -- local ligandList = GetStruct ( "M" ) print ( #ligandList .. " ligands" ) if #ligandList > 0 then if #ligandList == 1 then if ligandList [ 1 ] [ STRCTSTR ] == segCnt and ligandList [ 1 ] [ STRCTEND ] == segCnt then print ( "normal ligand, segment " .. segCnt .. ", score = " .. round ( ligandList [ 1 ] [ STRCTSCR ] ) ) segCnt2 = segCnt - 1 if ligandList [ 1 ] [ STRUCTSCR ] ~= 0 then print ( "WARNING: normal ligand with non-zero score" ) end elseif ligandList [ 1 ] [ STRCTEND ] == segCnt then print ( "normal ligand, segments " .. ligandList [ 1 ] [ STRCTSTR ] .. "-" .. ligandList [ 1 ] [ STRCTEND ] .. ", score = " .. round ( ligandList [ 1 ] [ STRCTSCR ] ) ) if ligandList [ 1 ] [ STRUCTSCR ] ~= 0 then print ( "WARNING: suspect multi-segment ligand with non-zero score, segment count not adjusted" ) else segCnt2 = ligandList [ 1 ] [ STRCTSTR ] - 1 end else print ( "WARNING: non-standard ligand, ligand not at end" ) print ( "most ligand-aware recipes will not work correctly" ) print ( "ligand # 1, start = " .. ligandList [ 1 ] [ STRCTSTR ] .. ", end = " .. ligandList [ 1 ] [ STRCTEND ] .. ", score = " .. round ( ligandList [ 1 ] [ STRCTSCR ] ) ) print ( "WARNING: suspect ligand, segment count not adjusted" ) end else print ( "WARNING: non-standard ligands, " .. #ligandList .. " ligand sections" ) print ( "most ligand-aware recipes will not work correctly" ) for jj = 1, #ligandList do print ( "ligand # " .. jj .. ", start = " .. ligandList [ jj ] [ STRCTSTR ] .. ", end = " .. ligandList [ jj ] [ STRCTEND ] .. ", score = " .. round ( ligandList [ jj ] [ STRCTSCR ] ) ) end print ( "WARNING: suspect ligands, segment count not adjusted" ) end end if segCnt2 == segCnt then print ( "segment count = " .. segCnt ) else print ( "original segment count = " .. segCnt ) print ( "adjusted segment count = " .. segCnt2 ) end return ligandList end -- -- build segments table, without any ligand segments -- function tablesegment () local table = { {} } for ii = 1, segCnt2 do table [ ii ] = {} local aac = structure.GetAminoAcid ( ii ) if AminoAcids [ aac ] == nil then -- bizarro kludge code "unk" used -- for segment 134, puzzle 879 print ( "WARNING: unknown amino acid \'" .. aac .. "\' at segment " .. ii .. ", code \'x\' substituted" ) aac = "x" end table [ ii ] [ 1 ] = aac table [ ii ] [ 2 ] = AminoAcids [ aac ] [ AASHORT ] table [ ii ] [ 3 ] = AminoAcids [ aac ] [ AALONG ] table [ ii ] [ 4 ] = AminoAcids [ aac ] [ AAHYDROPATHY ] table [ ii ] [ 5 ] = structure.GetSecondaryStructure ( ii ) if table [ ii ] [ 5 ] ~= "H" and table [ ii ] [ 5 ] ~= "E" and table [ ii ] [ 5 ] ~= "L" and table [ ii ] [ 5 ] ~= "M" then print ( "WARNING: unknown secondary structure code \'" .. table [ ii ] [ 5 ] .. "\' at segment " .. ii ) end end return table end function makeruler ( segments ) local onez = "" local tenz = "" local hunz = "" local numz = 1 for ii = 1, segments do onez = onez .. numz % 10 if ii % 10 == 0 then local ff = ii if ff >= 100 then ff = ff % 100 end tenz = tenz .. ( ff - ( ff % 10 ) ) / 10 if ii >= 100 then local ff = ii if ff >= 1000 then ff = ff % 1000 end hunz = hunz .. ( ff - ( ff % 100 ) ) / 100 else hunz = hunz .. " " end else tenz = tenz .. " " hunz = hunz .. " " end numz = numz + 1 if numz > 10 then numz = 1 end end local ruler = "" if segments >= 100 then ruler = hunz .. "\n" end if segments >= 10 then ruler = tenz .. "\n" end ruler = ruler .. onez return ruler end -- -- tlaloc functions to print sequence of letter -- function BuildSequence ( table ) local seqstring = "" local hydrostring = "" local strucstring = "" for ii = 1, segCnt2 do seqstring = seqstring .. table [ ii ] [ 1 ] if structure.IsHydrophobic ( ii ) then hydrostring = hydrostring .. "i" else hydrostring = hydrostring .. "e" end strucstring = strucstring .. table [ ii ] [ 5 ] end local ruler = makeruler ( segCnt2 ) print ( "sequence with single-letter amino acid codes for searching PDB" ) print ( ruler ) print ( seqstring ) print ( "" ) print ( "sequence with i if hydrophobic" ) print ( ruler ) print ( hydrostring ) print ( "" ) print ( "sequence of structure" ) print ( ruler ) print ( strucstring ) print ( "" ) print ( "--" ) return seqstring, hydrostring, strucstring end -- -- find modifiable sections -- function FindModifiable () -- local flocked = FindLocked () --print ( #flocked .. " locked sections" ) for kk = 1, #flocked do print ( "locked section " .. kk .. ": " .. flocked [ kk ] [ 1 ] .. "-" .. flocked [ kk ] [ 2 ] ) end -- local funlocked = SegmentInvertSet ( flocked ) --print ( #funlocked .. " unlocked sections" ) for kk = 1, #funlocked do print ( "unlocked section " .. kk .. ": " .. funlocked [ kk ] [ 1 ] .. "-" .. funlocked [ kk ] [ 2 ] ) end -- local zeroScore = FindZeroScore () --print ( #zeroScore .. " zero score sections" ) for kk = 1, #zeroScore do print ( "zero score section " .. kk .. ": " .. zeroScore [ kk ] [ 1 ] .. "-" .. zeroScore [ kk ] [ 2 ] ) end -- if #flocked == 1 and #zeroScore > 0 then local LockedNZ = SegmentInvertSet ( zeroScore, flocked [ 1 ] [ 2 ] ) for kk = 1, #LockedNZ do print ( "locked, non-zero score section " .. kk .. ": " .. LockedNZ [ kk ] [ 1 ] .. "-" .. LockedNZ [ kk ] [ 2 ] ) end if flocked [ 1 ] [ 1 ] == 1 then segStart = math.min ( flocked [ 1 ] [ 2 ] + 1, segCnt2 ) end end -- local mutables = FindMutables () --print ( #mutables .. " mutable sections" ) for kk = 1, #mutables do print ( "mutable section " .. kk .. ": " .. mutables [ kk ] [ 1 ] .. "-" .. mutables [ kk ] [ 2 ] ) end -- local lockmut = SegmentCommSet ( flocked, mutables ) --print ( #lockmut .. " locked, mutable sections" ) for kk = 1, #lockmut do print ( "locked, mutable section " .. kk .. ": " .. lockmut [ kk ] [ 1 ] .. "-" .. lockmut [ kk ] [ 2 ] ) end end -- -- find mutable segments -- function FindMutable ( table ) local mutable = {} local mutablestring = '' for ii = 1, segCnt2 do if structure.IsMutable ( ii ) == true then mutable [ #mutable + 1 ] = ii end end print ( #mutable .. " mutables found" ) if #mutable > 0 then print ( "n" .. delim .. "segment" .. delim .. "aacode" .. delim .. "aaname" ) end for ii = 1, #mutable do print ( ii .. delim .. mutable[ii] .. delim .. table [ mutable [ ii ] ] [ 1 ] .. delim .. table [ mutable [ ii ] ] [ 3 ] ) mutablestring = mutablestring .. "'" .. table [ mutable [ ii ] ] [ 1 ] .. "'," end print ( mutablestring ) --- for copy paste on other recipe return mutable end -- -- function FindActiveSubscores adapted from EDRW by Timo van der Laan -- function FindActiveSubscores ( show ) local result = {} local gTotal = 0 -- grand total all subscores local gTotalS = 0 -- grand total all segment subscores local Subs = puzzle.GetPuzzleSubscoreNames () for ii = 1, #Subs do local total = 0 local abstotal = 0 local part for jj = 1, segCnt2 do part = current.GetSegmentEnergySubscore ( jj, Subs [ ii ] ) total = total + part abstotal = abstotal + math.abs ( part ) end if abstotal > 10 then result [ #result + 1 ] = { Subs [ ii ], total, true } gTotal = gTotal + total if show then print ( "active subscore " .. #result .. ": " .. Subs [ ii ] .. ", total = " .. round ( total ) ) end end end for ii = 1, segCnt2 do gTotalS = gTotalS + current.GetSegmentEnergyScore ( ii ) end if show then print ( #result .. " active subscores" ) end if show then print ( "total of all subscores: " .. round ( gTotal ) ) end if show then print ( "total of all segment scores: " .. round ( gTotalS ) ) end if ( round ( gTotal ) ~= round ( gTotalS ) ) then print ( "WARNING: total subscores " .. round ( gTotal ) .. " not equal total segment scores " .. round ( gTotalS ) ) end return result, gTotal, gTotalS end -- -- print segment scores in spreadsheet format -- function SegScores ( table, subScores ) local tReport = "" local headStr = "n" .. delim .. "ID" .. delim .. "SS" .. delim if kHydro then headStr = headStr .. "Hyd" .. delim end if kAtom then headStr = headStr .. "atoms" .. delim end if kRotamer then headStr = headStr .. "rotamers" .. delim end headStr = headStr .. "score" .. delim for ii = 1, #subScores do if subScores [ ii ] [ 3 ] then headStr = headStr .. subScores [ ii ] [ 1 ] .. delim end end print ( "--" ) print ( "\"segment scores\"" ) print ( headStr ) tReport = tReport .. "\"segment scores\"\n" .. headStr .. "\n" local tSegEnergy = 0 for ii = 1, segCnt2 do local segEnergy = current.GetSegmentEnergyScore ( ii ) tSegEnergy = tSegEnergy + segEnergy local segScore = ii .. delim .. table [ ii ] [ 1 ] .. delim .. table [ ii ] [ 5 ] .. delim if kHydro then segScore = segScore .. round ( table [ ii ] [ 4 ] ) .. delim end if kAtom then segScore = segScore .. structure.GetAtomCount ( ii ) .. delim end if kRotamer then segScore = segScore .. rotamer.GetCount ( ii ) .. delim end segScore = segScore .. round ( segEnergy ) .. delim for jj = 1, #subScores do if subScores [ jj ] [ 3 ] then segScore = segScore .. round ( current.GetSegmentEnergySubscore ( ii, subScores [ jj ] [ 1 ] ) ) .. delim end end print ( segScore ) tReport = tReport .. segScore .. "\n" end local footstr = "totals" .. delim .. "" .. delim .. "" .. delim if kHydro then footstr = footstr .. delim -- no totals for hydropathy end if kAtom then footstr = footstr .. delim -- no totals for atoms end if kRotamer then footstr = footstr .. delim -- no totals for rotamers end footstr = footstr .. round ( tSegEnergy ) .. delim for ii = 1, #subScores do if subScores [ ii ] [ 3 ] then footstr = footstr .. round ( subScores [ ii ] [ 2 ] ) .. delim end end print ( footstr ) tReport = tReport .. footstr .. "\n" return tReport end -- -- print density analysis -- function DensityRat ( table ) local tReport = "" local headStr = "\"AA code\"" .. delim .. "\"AA name\"" .. delim .. "\"segment count\"" .. delim .. "\"total density\"" .. delim .. "\"% total density\"" .. delim .. "\"mean density\"" .. delim .. "\"worst density\"" .. delim .. "\"worst density seg\"" .. delim .. "\"best density\"" .. delim .. "\"best density seg\"" .. delim -- -- AA density table - keyed by AA code -- DENCOUNT = 1 DENTOTAL = 2 DENMEAN = 3 DENBEST = 4 DENBESTS = 5 DENWORST = 6 DENWORSTS = 7 -- -- density by amino acid -- local tAA = {} -- -- binary (true/false) tables for density by AA type -- -- -- density of aromatics - true => aromatic -- local tAromatic = {} tAromatic [ true ] = { 0, 0, 0, -999, 0, 999, 0, } tAromatic [ false ] = { 0, 0, 0, -999, 0, 999, 0, } -- -- density of aliphatics - true => alphatic -- local tAliphatic = {} tAliphatic [ true ] = { 0, 0, 0, -999, 0, 999, 0, } tAliphatic [ false ] = { 0, 0, 0, -999, 0, 999, 0, } -- -- density of hydrophobics - true => hydrophobic -- local tHydrophobic = {} tHydrophobic [ true ] = { 0, 0, 0, -999, 0, 999, 0, } tHydrophobic [ false ] = { 0, 0, 0, -999, 0, 999, 0, } local function denUpdate ( tDen, segDensity, segindx ) tDen [ DENCOUNT ] = tDen [ DENCOUNT ] + 1 tDen [ DENTOTAL ] = tDen [ DENTOTAL ] + segDensity if segDensity > tDen [ DENBEST ] then tDen [ DENBEST ] = segDensity tDen [ DENBESTS ] = segindx end if segDensity < tDen [ DENWORST ] then tDen [ DENWORST ] = segDensity tDen [ DENWORSTS ] = segindx end end local tSegDensity = 0 for ii = 1, segCnt2 do local aaCode = table [ ii ] [ 1 ] if tAA [ aaCode ] == nil then tAA [ aaCode ] = { 0, 0, 0, -999, 0, 999, 0, } end -- -- update table of density by amino acid -- local segDensity = current.GetSegmentEnergySubscore ( ii, "Density" ) tSegDensity = tSegDensity + segDensity local aaDen = tAA [ aaCode ] if aaDen ~= nil then denUpdate ( aaDen, segDensity, ii ) else print ( "ERROR: AA density table entry for " .. aaCode .. " is nil" ) end -- -- update table of density by aromatic vs. non-aromatic -- local aromDen = tAromatic [ Aromatic [ aaCode ] ~= nil ] if aromDen ~= nil then denUpdate ( aromDen, segDensity, ii ) else print ( "ERROR: Aromatic density table entry for " .. aaCode .. " is nil" ) end -- -- update table of density by aliphatic vs. non-aliphatic -- local alipDen = tAliphatic [ Aliphatic [ aaCode ] ~= nil ] if alipDen ~= nil then denUpdate ( alipDen, segDensity, ii ) else print ( "ERROR: Aliphatic density table entry for " .. aaCode .. " is nil" ) end -- -- update table of density by hydrophobic vs. non-hydrophobic -- local phobDen = tHydrophobic [ Hydrophobic [ aaCode ] ~= nil ] if phobDen ~= nil then denUpdate ( phobDen, segDensity, ii ) else print ( "ERROR: hydrophobic density table entry for " .. aaCode .. " is nil" ) end end print ( "--" ) print ( "\"density by AA\"" ) print ( headStr ) tReport = tReport .. "\"density by AA\"\n" .. headStr .. "\n" for aac, aaDen in pairs ( tAA ) do if aaDen [ DENCOUNT ] > 0 then aaDen [ DENMEAN ] = aaDen [ DENTOTAL ] / aaDen [ DENCOUNT ] end local denline = aac .. delim .. AminoAcids [ aac ] [ AALONG ] .. delim .. aaDen [ DENCOUNT ] .. delim .. round ( aaDen [ DENTOTAL ] ) .. delim .. round ( ( aaDen [ DENTOTAL ] / tSegDensity ) * 100 ) .. delim .. round ( aaDen [ DENMEAN ] ) .. delim .. round ( aaDen [ DENWORST ] ) .. delim .. aaDen [ DENWORSTS ] .. delim .. round ( aaDen [ DENBEST ] ) .. delim .. aaDen [ DENBESTS ] print ( denline ) tReport = tReport .. denline .. "\n" end local footstr = "totals" .. delim .. segCnt2 .. delim .. round ( tSegDensity ) .. delim .. delim .. round ( tSegDensity / segCnt2 ) print ( footstr ) tReport = tReport .. footstr .. "\n" headStr = "\"aromatic AA\"" .. delim .. "" .. delim .. "\"segment count\"" .. delim .. "\"total density\"" .. delim .. "\"% total density\"" .. delim .. "\"mean density\"" .. delim .. "\"worst density\"" .. delim .. "\"worst density seg\"" .. delim .. "\"best density\"" .. delim .. "\"best density seg\"" .. delim print ( "--" ) print ( "\"density by aromatic vs. non-aromatic\"" ) print ( headStr ) tReport = tReport .. "\"density by aromatic vs. non-aromatic\"\n" .. headStr .. "\n" for aac, aaDen in pairs ( tAromatic ) do if aaDen [ DENCOUNT ] > 0 then aaDen [ DENMEAN ] = aaDen [ DENTOTAL ] / aaDen [ DENCOUNT ] end local denline = tostring ( aac ) .. delim .. "" .. delim .. aaDen [ DENCOUNT ] .. delim .. round ( aaDen [ DENTOTAL ] ) .. delim .. round ( ( aaDen [ DENTOTAL ] / tSegDensity ) * 100 ) .. delim .. round ( aaDen [ DENMEAN ] ) .. delim .. round ( aaDen [ DENWORST ] ) .. delim .. aaDen [ DENWORSTS ] .. delim .. round ( aaDen [ DENBEST ] ) .. delim .. aaDen [ DENBESTS ] print ( denline ) tReport = tReport .. denline .. "\n" end headStr = "\"aliphatic AA\"" .. delim .. "" .. delim .. "\"segment count\"" .. delim .. "\"total density\"" .. delim .. "\"% total density\"" .. delim .. "\"mean density\"" .. delim .. "\"worst density\"" .. delim .. "\"worst density seg\"" .. delim .. "\"best density\"" .. delim .. "\"best density seg\"" .. delim print ( "--" ) print ( "\"density by aliphatic vs. non-aliphatic\"" ) print ( headStr ) tReport = tReport .. "\"density by aliphatic vs. non-aliphatic\"\n" .. headStr .. "\n" for aac, aaDen in pairs ( tAliphatic ) do if aaDen [ DENCOUNT ] > 0 then aaDen [ DENMEAN ] = aaDen [ DENTOTAL ] / aaDen [ DENCOUNT ] end local denline = tostring ( aac ) .. delim .. "" .. delim .. aaDen [ DENCOUNT ] .. delim .. round ( aaDen [ DENTOTAL ] ) .. delim .. round ( ( aaDen [ DENTOTAL ] / tSegDensity ) * 100 ) .. delim .. round ( aaDen [ DENMEAN ] ) .. delim .. round ( aaDen [ DENWORST ] ) .. delim .. aaDen [ DENWORSTS ] .. delim .. round ( aaDen [ DENBEST ] ) .. delim .. aaDen [ DENBESTS ] print ( denline ) tReport = tReport .. denline .. "\n" end headStr = "\"hydrophobic AA\"" .. delim .. "" .. delim .. "\"segment count\"" .. delim .. "\"total density\"" .. delim .. "\"% total density\"" .. delim .. "\"mean density\"" .. delim .. "\"worst density\"" .. delim .. "\"worst density seg\"" .. delim .. "\"best density\"" .. delim .. "\"best density seg\"" .. delim print ( "--" ) print ( "\"density by hydrophobic vs. non-hydrophobic\"" ) print ( headStr ) tReport = tReport .. "\"density by hydrophobic vs. non-hydrophobic\"\n" .. headStr .. "\n" for aac, aaDen in pairs ( tHydrophobic ) do if aaDen [ DENCOUNT ] > 0 then aaDen [ DENMEAN ] = aaDen [ DENTOTAL ] / aaDen [ DENCOUNT ] end local denline = tostring ( aac ) .. delim .. "" .. delim .. aaDen [ DENCOUNT ] .. delim .. round ( aaDen [ DENTOTAL ] ) .. delim .. round ( ( aaDen [ DENTOTAL ] / tSegDensity ) * 100 ) .. delim .. round ( aaDen [ DENMEAN ] ) .. delim .. round ( aaDen [ DENWORST ] ) .. delim .. aaDen [ DENWORSTS ] .. delim .. round ( aaDen [ DENBEST ] ) .. delim .. aaDen [ DENBESTS ] print ( denline ) tReport = tReport .. denline .. "\n" end print ( "--" ) print ( "\"density deviation (above/below mean density by AA)\"" ) local dendeviate = "" for ii = 1, segCnt2 do local aaCode = table [ ii ] [ 1 ] local segDensity = current.GetSegmentEnergySubscore ( ii, "Density" ) local jDenMean = tAA [ aaCode ] [ DENMEAN ] if round ( segDensity ) == round ( jDenMean ) or tAA [ aaCode ] [ DENCOUNT ] == 1 then dendeviate = dendeviate .. "=" elseif segDensity < jDenMean then dendeviate = dendeviate .. "-" else dendeviate = dendeviate .. "+" end end local ruler = makeruler ( segCnt2 ) print ( ruler ) print ( dendeviate ) print ( "" ) return tReport, dendeviate end -- -- GetStruct -- return a list of structures of a specified type -- -- adapted from spvincent's Helix Rebuild -- function GetStruct ( structT ) local within_struct = false local structList = {} local structStart = 0 local structLast = 0 local structScr = 0 local segCnt = structure.GetCount() -- do our own count, lets us check for ligands for ii = 1, segCnt do if ( structure.GetSecondaryStructure ( ii ) == structT ) then if ( within_struct == false ) then -- start of a new struct within_struct = true structStart = ii structScr = 0 end structLast = ii structScr = structScr + current.GetSegmentEnergyScore ( ii ) elseif ( within_struct == true ) then -- end of a struct within_struct = false structList [ #structList + 1 ] = { structT, structStart, structLast, false, structScr } end end if ( within_struct == true ) then structList [ #structList + 1 ] = { structT, structStart, structLast, false, structScr } end return structList end -- -- function to print a little contact table -- function contact ( structs ) local head = delim .. delim local first = true for s = 1, #structs do if structs [ s ] [ STRCTTYP ] == "H" or structs [ s ] [ STRCTTYP ] == "E" then local string = structs [ s ] [ STRCTTYP ] .. delim .. structs [ s ] [ STRCTSTR ] .. delim .. structs [ s ] [ STRCTEND ] for s2 = 1, #structs do if structs [ s2 ] [ STRCTTYP ] == "H" or structs [ s2 ] [ STRCTTYP ] == "E" then if first then head = head .. delim .. structs [ s2 ] [ STRCTTYP ] end local mean = 0 local nb = 0 for i = structs [ s ] [ STRCTSTR ], structs [ s ] [ STRCTEND ] do local min = 999999 for j = structs [ s2 ] [ STRCTSTR ], structs [ s2 ] [ STRCTEND ] do dist = structure.GetDistance ( i, j ) if dist < min then min = dist end end mean = mean + min nb = nb + 1 end mean = mean / nb local c = " " if structure.GetDistance ( structs [ s ] [ STRCTSTR ], structs [ s2 ] [ STRCTEND ] ) < structure.GetDistance ( structs [ s ] [ STRCTSTR ], structs [ s2 ] [ STRCTSTR ] ) then if mean < 5 then c = 'X' elseif mean < 10 then c = 'x' end else if mean < 5 then c = 'O' elseif mean < 10 then c = 'o' end end string = string .. delim .. c end end if first then print ( "--" ) print ( "\"mini contact table\"" ) print ( head ) first = false end print ( string ) end end end function ShowReport ( tReport, seq, struc ) local ask = dialog.CreateDialog ( ReVersion .. " copy-and-paste" ) ask.l15 = dialog.AddLabel ( "Click inside the one of the text boxes, then" ) ask.l16 = dialog.AddLabel ( "use ctrl+a (command+a on Mac) to select all," ) ask.l20 = dialog.AddLabel ( "and control+c or command+c to copy, then" ) ask.l30 = dialog.AddLabel ( "paste into spreadsheet" ) ask.l10 = dialog.AddLabel ( "---- segment subscores report ----" ) ask.rep = dialog.AddTextbox ( "subscores:", tReport ) ask.SEQN = dialog.AddLabel ( "---- primary (sequence) and secondary structure detail ----" ) ask.seq = dialog.AddTextbox ( "AA sequence:", seq ) ask.struc = dialog.AddTextbox ( "secondary:", struc ) ask.OK = dialog.AddButton ( "OK", 1 ) dialog.Show ( ask ) end function ShowDensityReport ( dReport, dendev ) local ask = dialog.CreateDialog ( ReVersion .. " copy-and-paste" ) ask.l15 = dialog.AddLabel ( "Click inside the one of the text boxes, then" ) ask.l16 = dialog.AddLabel ( "use ctrl+a (command+a on Mac) to select all," ) ask.l20 = dialog.AddLabel ( "and control+c or command+c to copy, then" ) ask.l30 = dialog.AddLabel ( "paste into spreadsheet" ) ask.l50 = dialog.AddLabel ( "---- density analysis ----" ) ask.dens = dialog.AddTextbox ( "density:", dReport ) ask.l70 = dialog.AddLabel ( "---- density deviation from mean AA density ----" ) ask.dev = dialog.AddTextbox ( "deviation:", dendev ) ask.OK = dialog.AddButton ( "OK", 1 ) dialog.Show ( ask ) end function GetParms ( scrParts, ligands ) local ask = dialog.CreateDialog ( ReVersion ) local kRet = 0 repeat if segcnt == segcnt2 then ask.segcnt = dialog.AddLabel ( segCnt2 .. " segments" ) else ask.segcnt = dialog.AddLabel ( segCnt .. " segments" ) ask.segcnt2 = dialog.AddLabel ( segCnt2 .. " segments, adjusted for ligands" ) end if #ligands > 0 then ask.ligands = dialog.AddLabel ( #ligands .. " ligand section(s), see scriptlog for details" ) end ask.NRGE = dialog.AddLabel ( "---- score information ----" ) --[[ BoxScore = { tSubScores = 0, -- total of active subscores, all segments tSegScores = 0, -- total of segment scores tScoreFilt = 0, -- total score, filters on tScoreFOff = 0, -- total score, filters off tScoreNrgy = 0, -- total energy score tScoreBonus = 0, -- total filter bonus tScoreForm = 0, -- subscores + filter bonus + 8000 tScoreDark = 0, -- total "dark" score } ]]-- ask.active = dialog.AddLabel ( #scrParts .. " active subscores" ) ask.tSubScores = dialog.AddLabel ( "total of all subscores = " .. round ( BoxScore.tSubScores ) ) ask.tScoreFilt = dialog.AddLabel ( "current score = " .. round ( BoxScore.tScoreFilt ) ) if BoxScore.tScoreBonus ~= 0 then ask.tScoreBonus = dialog.AddLabel ( "filter bonus = " .. round ( BoxScore.tScoreBonus ) ) else ask.tScoreBonus = dialog.AddLabel ( "no filter bonus" ) end ask.tScoreForm = dialog.AddLabel ( "subscores + filter bonus + 8000 = " .. round ( BoxScore.tScoreForm ) ) ask.tScoreDark = dialog.AddLabel ( "\"dark\" points = " .. round ( BoxScore.tScoreDark ) ) ask.DETAIL = dialog.AddLabel ( "---- subscore reporting options ----" ) for ii = 1, #scrParts do ask [ scrParts [ ii ] [ 1 ] ] = dialog.AddCheckbox ( scrParts [ ii ] [ 1 ] .. ": " .. round ( scrParts [ ii ] [ 2 ] ) .. " (" .. round ( scrParts [ ii ] [ 2 ] / segCnt2 ) .. " / seg) ", scrParts [ ii ] [ 3 ] ) end ask.SECT = dialog.AddLabel ( "---- report sections ----" ) ask.kContact = dialog.AddCheckbox ( "mini contact table", kContact ) ask.kMutDet = dialog.AddCheckbox ( "mutable details", kMutDet ) if jDensity then ask.kDensity = dialog.AddCheckbox ( "density analysis", kDensity ) end ask.OK = dialog.AddButton ( "OK", 1 ) ask.more = dialog.AddButton ( "More", 2 ) ask.Cancel = dialog.AddButton ( "Cancel", 0 ) kRet = dialog.Show ( ask ) if kRet > 0 then local aPart = 0 for ii = 1, #scrParts do scrParts [ ii ] [ 3 ] = ask [ scrParts [ ii ] [ 1 ] ].value aPart = aPart + 1 end -- -- select all if nothing selected -- if aPart == 0 then for ii = 1, #scrParts do scrParts [ ii ] [ 3 ] = true end end kContact = ask.kContact.value kMutDet = ask.kMutDet.value if jDensity then kDensity = ask.kDensity.value end if kRet == 2 then GetMoreParms () end end until kRet < 2 if kRet == 1 then return true, scrParts end return false, scrParts end function GetMoreParms ( ) local ask = dialog.CreateDialog ( ReVersion ) ask.DETAIL = dialog.AddLabel ( "---- additional columns ----" ) ask.kHydro = dialog.AddCheckbox ( "hydropathy index", kHydro ) ask.kAtom = dialog.AddCheckbox ( "atom count", kAtom ) ask.kRotamer = dialog.AddCheckbox ( "rotamer count", kRotamer ) ask.FORMAT = dialog.AddLabel ( "---- formatting options ----" ) ask.kRound = dialog.AddSlider ( "decimal places:", kRound, 1, 8, 0 ) ask.ddlm = dialog.AddLabel ( "delimiters (last selected wins)" ) ask.dtab = dialog.AddCheckbox ( "tab", dtab ) ask.dcomma = dialog.AddCheckbox ( "comma", dcomma ) ask.dsemic = dialog.AddCheckbox ( "semicolon", dsemic ) ask.OK = dialog.AddButton ( "OK", 1 ) ask.Cancel = dialog.AddButton ( "Cancel", 0 ) local kRet = dialog.Show ( ask ) if kRet > 0 then kHydro = ask.kHydro.value kAtom = ask.kAtom.value kRotamer = ask.kRotamer.value kRound = ask.kRound.value kFax = 10 ^ -kRound dtab = ask.dtab.value if dtab then delim = "\t" end dcomma = ask.dcomma.value if dcomma then delim = "," end dsemic = ask.dsemic.value if dsemic then delim = ";" end return true end return false end function main () print ( "--" ) print ( ReVersion ) print ( "Puzzle: " .. puzzle.GetName () ) print ( "Track: " .. ui.GetTrackName () ) -- -- count segments and search for ligand -- local ligands = GetSeCount () -- -- determine which subscores are active -- print ( "--" ) print ( "score information" ) --[[ BoxScore = { tSubScores = 0, -- total of active subscores, all segments tSegScores = 0, -- total of segment scores tScoreFilt = 0, -- total score, filters on tScoreFOff = 0, -- total score, filters off tScoreNrgy = 0, -- total energy score tScoreBonus = 0, -- total filter bonus tScoreForm = 0, -- subscores + filter bonus + 8000 tScoreDark = 0, -- total "dark" score } ]]-- subScores, BoxScore.tSubScores, BoxScore.tSegScores = FindActiveSubscores ( true ) -- -- special check for "Density" subscore -- for ii = 1, #subScores do if subScores [ ii ] [ 1 ] == "Density" then jDensity = true -- density present kDensity = true -- select density report by default break end end behavior.SetFiltersDisabled ( false ) BoxScore.tScoreFilt = current.GetEnergyScore () behavior.SetFiltersDisabled ( true ) BoxScore.tScoreFOff = current.GetEnergyScore () BoxScore.tScoreBonus = BoxScore.tScoreFilt - BoxScore.tScoreFOff if fBonus ~= 0 then print ( "current filter bonus = " .. round ( BoxScore.tScoreBonus ) ) end behavior.SetFiltersDisabled ( false ) BoxScore.tScoreForm = BoxScore.tSubScores + BoxScore.tScoreBonus + 8000 print ( "subscores + filter bonus + 8000 = " .. round ( BoxScore.tScoreForm ) ) BoxScore.tScoreDark = BoxScore.tScoreFilt - BoxScore.tScoreForm print ( "current score = " .. round ( BoxScore.tScoreFilt ) ) print ( "\"dark\" points = " .. round ( BoxScore.tScoreDark ) ) print ( "--" ) print ( "sequence information" ) -- -- build table of non-ligand segments -- local segTable = tablesegment () -- -- sequence of letters, hydrophobes, structures -- local seq, hydro, struc = BuildSequence ( segTable ) -- -- find modifiable sections -- print ( "--" ) print ( "modifiable sections" ) FindModifiable () -- -- get details for subscore report -- local go, selScores = GetParms ( subScores, ligands ) if go then -- -- print segment scores -- local tReport = SegScores ( segTable, selScores ) -- -- print density analysis -- local dReport = nil local dendev = nil if jDensity then dReport, dendev = DensityRat ( segTable ) end -- -- detect structures -- local helixList = GetStruct ( "H" ) local sheetList = GetStruct ( "E" ) local structList = {} for ii = 1, #helixList do structList [ #structList + 1 ] = helixList [ ii ] end for ii = 1, #sheetList do structList [ #structList + 1 ] = sheetList [ ii ] end if kContact then -- -- mini contact table -- contact ( structList ) end -- -- find mutable segments and print them -- if kMutDet then print ( "--" ) print ( "mutable segments" ) FindMutable ( segTable ) end -- -- show reports for copy and paste -- ShowReport ( tReport, seq, struc ) if kDensity then ShowDensityReport ( dReport, dendev ) end end -- -- exit via the cleanup function -- cleanup () end function cleanup ( error ) print ( "---" ) -- -- model 100 - print recipe name, puzzle, track, time, score, and gain -- local reason local start, stop, line, msg if error == nil then reason = "complete" else -- -- model 120 - civilized error reporting, -- thanks to Bruno K. and Jean-Bob -- start, stop, line, msg = error:find ( ":(%d+):%s()" ) if msg ~= nil then error = error:sub ( msg, #error ) end if error:find ( "Cancelled" ) ~= nil then reason = "cancelled" else reason = "error" end end print ( ReVersion .. " " .. reason ) print ( "Puzzle: " .. puzzle.GetName () ) print ( "Track: " .. ui.GetTrackName () ) if reason == "error" then print ( "Unexpected error detected" ) print ( "Error line: " .. line ) print ( "Error: \"" .. error .. "\"" ) end end xpcall ( main, cleanup ) --- end of recipe

Comments


LociOiling Lv 1

Version 2.4 adds a separate dialog for copy-and-paste of the density analysis. This dialog only appears when the density analysis option is selected for an Electron Density puzzle. (A textbox bug means you can't have two newline-delimited textboxes in a single dialog. If a certain threshold is reached, one textbox becomes "read-only" and can't be copied.)

Version 2.4 also fixes the subscore selection logic, the limitations of which were exposed by the addition of a "More" dialog in version 2.3. Column selection should now survive a trip to "More", and the selected columns won't be doubled up.