Módulu:Sandbox/Oriciu/CladeN
Esti módulu ta calificáu como alpha. Ta llistu p'aportaciones de terceros, y pue usase'n delles páxines pa ver si causa problemes, pero tendría de vixilase. Afálense les suxerencies de carauterístiques nueves o cambeos nos mecanismos d'entrada y salida. |
This module is designed to be used with the CladeN template to draw phylogenetic trees or cladograms. The new template-module combination extends the feature available with the clade and cladex templates. As it replicates the behaviour of the clade and cladex templates it should be suitable for replacing them.
Additionally, the module as the code for a prototype [Usuariu:Oriciu/sandbox/templates/NewickConverter|NewickConverter] template, which converts Newick strings into clade structure. This is not to be used in wikipedia articles, but is a utility to help construct cladograms for inclusion in articles.
Usage
editar{{#invoke:Sandbox/Oriciu|main|style={{{style}}}}}
Examples
editarSimple examples mimicking the clade template:
- Usuariu:Oriciu/sandbox/templates/Template:Passeroidea
- Usuariu:Oriciu/sandbox/templates/Template:Passerida
Example demonstrating more advanced features of cladeN:
Example demonstrating features available:
Error de Lua na llinia 695: attempt to call local 'p' (a table value).
-- Importao dende https://en.wikipedia.org/w/index.php?title=Module:Sandbox/Jts1882/CladeN
--NOTE: this module contains functions for generating the table structure of the clade tree in two ways:
-- (1) the original method was generated by a number of function calls from the template using {{invoke}}
-- function p.openTable(frame) - creates wikitext code to open the HTML table
-- function p.node(frame) - deals with the first node (|1,|label1) and creates wikitext for top row of the table
-- function p.nodeN(frame) - deals with a sister nodes (|2-17), adding a row each time it is called
-- function p.closeTable() - closes the HTML table
-- (2) the revised method is called by the template with one {{invoke}} instruction; it has three functions:
-- p.main(frame) - opens and closes table, loops through the children of node, main is invoked once and controls the rest, calling ...
-- p.addTaxon(childNumber, nodeLeaf) - the nuts and bolts; code dealing with each child node
-- p.addLabel(childNumber) - adds the label text
local p = {}
function p.toggle(frame)
if 1==2 then return 'some text' end
--local toggleSymbol = 'toggle all'
local toggleSymbol = mw.getCurrentFrame():getParent().args['button'] or ""
local toggleString = '<div class="'
local i=0
while i < 20 do -- limit on number of toggle elements controlled by the trigger button
i = i + 1 -- so we start with 1
local target = mw.getCurrentFrame():getParent().args['id'..tostring(i)]
-- add classes for the three elements of each target: expand symbol, collapse symbol and contents
if target ~= nil then
toggleString = toggleString .. ' mw-customtoggle-myClade' .. target
.. ' mw-customtoggle-collapseSymbol' .. target
.. ' mw-customtoggle-expandSymbol' .. target
end
end
toggleString = toggleString .. '">' .. toggleSymbol .. '</div>'
return toggleString
end
function p.hidden(frame)
local id = mw.getCurrentFrame():getParent().args['id'] or ""
local mode = mw.getCurrentFrame():getParent().args['mode'] or "right"
local expandSymbol = mw.getCurrentFrame():getParent().args['expand-symbol'] or "⊞"
local collapseSymbol = mw.getCurrentFrame():getParent().args['collapse-symbol'] or "⊟"
local initialState = mw.getCurrentFrame():getParent().args['expanded']
-- default is content collapsed
local contentState = " mw-collapsed" -- class to collapse content at start
local collapseSymbolState = " mw-collapsed"
local expandSymbolState = ""
if initialState then
contentState = ""
collapseSymbolState = ""
expandSymbolState = " mw-collapsed"
end
-- collapsible element containing the expand sympol and/or text
local expandSymbolString = '<td style="padding:0 0 0.25em 0;">'
.. '<div class="mw-collapsible' .. expandSymbolState .. '" id="mw-customcollapsible-expandSymbol' .. id .. '">'
.. '<div class="mw-collapsible-content mw-customtoggle-expandSymbol' .. id .. '">'
.. '<span class="mw-customtoggle-myClade' .. id
.. ' mw-customtoggle-collapseSymbol' .. id
.. ' mw-customtoggle-expandSymbol' .. id
.. '" style="font-size:100%;">' .. expandSymbol .. '</span>'
.. '</div></div></td>'
-- collapsible element containing the clade content
local contentString = '<td style="padding:0;">'
.. '<div class="mw-collapsible' .. contentState .. '" id="mw-customcollapsible-myClade' .. id .. '>'
.. '<div class="mw-collapsible-content mw-customtoggle-NOT_ON_CONTENT" >' -- don't toggle on the content
.. '\n' .. p.main(frame) -- important to start wikitext tables on new line
.. '</div></div></td>'
-- collapsible element containing the collapse sympol and/or text
local collapseSymbolString = '<td style="padding:0 0 0.4em 0;">'
.. '<div class="mw-collapsible' .. collapseSymbolState .. '" id="mw-customcollapsible-collapseSymbol' .. id .. '">'
.. '<div class="mw-collapsible-content mw-customtoggle-collapseSymbol' .. id .. '" >'
.. '<span class="mw-customtoggle-expandSymbol' .. id
.. ' mw-customtoggle-myClade' .. id
.. ' mw-customtoggle-collapseSymbol' .. id
.. ' " style="font-size:100%;" >' .. collapseSymbol .. '</span>'
.. '</div></div></td>'
local cladeString = '<table style="border-spacing:0;margin:0;"><tr>'
cladeString = cladeString .. expandSymbolString
if mode == "left" then
cladeString = cladeString .. collapseSymbolString
end
cladeString = cladeString .. contentString
if mode == "right" then
cladeString = cladeString .. collapseSymbolString
end
-- Note: if we want collapse string left and right it needs an extra element with a different id
cladeString = cladeString .. '</tr></table>'
return cladeString
end
--============================== main function (for Method 2) ===========================
-- main function, which will
--[[Main function to generate the table structure of the tree
Usage: {{#invoke:Module:Sandbox/Jts1882/CladeN|main|style={{{STYLE}}} }}
Template: User:Jts1882/sandbox/templates/CladeN
]]
function p.main(frame)
local cladeString = ""
local maxChildren = 20 -- currently 17 in the clade/cladex templates
local childNumber = 0
local lastNode = 0
local nodeCount = 0 -- total leafs plus new clade branches
local leafCount = 0 -- just the terminal leaves
local cladeCount = 0 -- new clade calls (each with a table)
local childCount = 0 -- number of leaves in the clade (can use to set bottom of bracket in addTaxon()
local totalCount = 0
--[[Note: this preprocessing loop gets information about the whole structure (number of nodes, leaves etc)
it makes a redundant calls to the templates through transclusion, but doen't affect the template depths;
it would probably be better to store the transcluded nodes in a table (a job for later)
]]
--[[ disable proprocessing loop
while childNumber < maxChildren do -- preprocessing loop
childNumber = childNumber + 1 -- so we start with 1
local nodeLeaf,data = mw.getCurrentFrame():getParent().args[tostring(childNumber)] or "" -- get data from |N=
if nodeLeaf ~= "" then
childCount = childCount + 1 -- this counts child elements in this clade
for i in string.gmatch(nodeLeaf, "|| rowspan") do -- count number of rows started (transclusion)
nodeCount = nodeCount + 1
end
for i in string.gmatch(nodeLeaf, "{| cellspacing") do -- count number of tables started (transclusion)
cladeCount = cladeCount + 1
end
-- _, cladeCount = string.gsub(nodeLeaf, "{| cellspacing", "")
--_, nodeCount = string.gsub(nodeLeaf, "|| rowspan", "")
--totalCount = totalCount + nodeCount
lastNode = childNumber
-- if data ~= nil then totalCount = totalCount + tonumber(data) else totalCount = totalCount + 1 end
end
--cladeString = cladeString .. '\n' .. ' count= ' .. totalCount
end
]]
nodeCount = nodeCount + childCount --(elements passed down by transduction plus current child elements)
cladeCount = cladeCount + 1 --(elements passed down by transduction plus current clade)
leafCount = nodeCount-cladeCount+1
totalCount =leafCount-- cladeCount --nodeCount
local testing = false
--testing = true -- COMMENT OUT TO GET MODULE RUNNING WITHOUT THE TEST
if testing then
local dataString = p.test(1)
cladeString = cladeString .. dataString
return cladeString
end
local tableStyle = frame.args.style or ""
local tableStyleString = ' style="' .. tableStyle .. '" '
if tableStyle == '{{{style}}}' then tableStyleString = "" end
local captionName =mw.getCurrentFrame():getParent().args['caption'] or ""
local captionStyle = mw.getCurrentFrame():getParent().args['captionstyle'] or ""
-- open table
--cladeString = cladeString .. '{| cellspacing=0 cellpadding=0 border=0 style="' .. tableStyle .. '"'
--cladeString = cladeString .. '{|cellspacing=0 cellpadding=0 ' .. tableStyleString
cladeString = cladeString .. '{| style="border-spacing:0;margin:0;' .. tableStyle .. '"'
--cladeString = cladeString .. '{| cellspacing=0 ' .. tableStyleString -- NOTE: cellpadding supposedly not supported in HTML5
-- add caption
if captionName ~= "" then
cladeString = cladeString .. '\n|+style="' .. captionStyle .. '"|' .. captionName
end
-- global nodeParameters (unnumber, i.e. color, thickness, state) apply to whole node bracket,
-- but can be overrriden by branchParameters (numbered, e.g. color2, thickness2, state2)
nodeColor = mw.getCurrentFrame():getParent().args['color'] or "black"
nodeThickness = tonumber(mw.getCurrentFrame():getParent().args['thickness']) or 1
nodeState = mw.getCurrentFrame():getParent().args['state'] or "solid"
local moreNeeded = true
childNumber = 0
lastNode = 0
--[[get child elements (add more rows for each child of node; each child is two rows)
the function addTaxon is called to add the rows for each child element;
each child add two rows: the first cell of each row contains the label or sublabel (below the line label), respectively;
the second cell spans both rows and contains the leaf name or a new clade structure
a third cell on the top row is sometimes added to contain a group to the right
]]
while childNumber < maxChildren do -- disable moreNeeded
-- while childNumber < 17 and moreNeeded == true do
childNumber = childNumber + 1 -- so we start with 1
local nodeLeaf = mw.getCurrentFrame():getParent().args[tostring(childNumber)] or "" -- get data from |N=
local nodeLabel = mw.getCurrentFrame():getParent().args['label'..tostring(childNumber)] or "" -- get data from |labelN=
local newickString = mw.getCurrentFrame():getParent().args['newick'..tostring(childNumber)] or "" -- get data from |labelN=
if newickString ~= "" then -- if using a newick string instead of a clade structure
if nodeLabel == "" then -- use labelN by default, otherwise use root name from Newick string
nodeLabel = p.getNewickOuterterm(newickString) -- need to use terminal part of newick string for label
end
cladeString = cladeString .. '\n' .. p.addTaxon(childNumber, p.newick(0, newickString), nodeLabel)
lastNode = childNumber
elseif nodeLeaf ~= "" then -- if the node contains a leaf name or clade structue
cladeString = cladeString .. '\n' .. p.addTaxon(childNumber, nodeLeaf, nodeLabel)
lastNode = childNumber
else
moreNeeded = false -- no |N= so don't look for more
-- Note: this changes the behaviour. If there is no |2, it won't look for |3 or |4, which clade does (is this desirable?)
-- this has been disabled to allow consistent behaviour with clade/cladex (it will check to the limit set)
end
end
--[[finish last row by adding cell with no left border
note: the row was started in addTaxon(), but the cell not added as left border yet to be determined;
here the cell is added to the last child node with no left border as it is below the bracket
this will be moved to addTaxon() when the number of the last child is known
]]
local subLabel = mw.getCurrentFrame():getParent().args['sublabel'..tostring(lastNode)] or "" -- request in addLabel
--use subLabel for annotating the clade structues to use structure information (DEBUGGIING ONLY)
--subLabel= '(N=' .. totalCount .. ')'
--cladeString = cladeString .. '\n' .. '| style="border: 0; padding: 0; vertical-align: top;" | <br/> '
cladeString = cladeString .. '\n' .. '|style="border:0;vertical-align:top;text-align:center;"|' .. p.addLabel(lastNode-1,subLabel)
--[[ footer description (add addition row spanning two columns at bottom of table)
this is designed to provide the description below the whole clade structure (mimicking cladogram);
however, it can also be used to add labels and spacing to the whole clade structre
]]
local footerText = mw.getCurrentFrame():getParent().args['footer'] or ""
local footerStyle = mw.getCurrentFrame():getParent().args['footerstyle'] or ""
if footerText ~= "" then
--cladeString = cladeString .. '<tr><td>Test <br/><br/><br/><br/><br/></td></tr>'
cladeString = cladeString .. '\n|-style="' .. footerStyle .. '"\n|colspan="2"|<p>' .. footerText .. '</p>||'
end
-- close table (wikitext to close table)
cladeString = cladeString .. '\n|}'
return cladeString
end
--[[ function to add child elements
adds wikitext for two rows of the table for each child node,
the first cell in each is used for the label and sublabel; the bottom border forms the horizonal branch of the bracket
the second cell is used for the leafname or a transcluded clade structure and spans both rows
note that the first and last child nodes need to be handled differently from the middle elements
the middle elements (|2, |3 ...) use a left border to create the vertical line of the bracket
the first child element doesn't use a left border for the first cell in the top row (as it is above the bracket)
the last child doesn't use a left border for the first cell in the second row (as it is above the bracket)
a complication is that the number of the last child node is not known;
as a result the cells will be added to the row on the next iteration or after the main loop finishes
]]
function p.addTaxon(childNumber, nodeLeaf, nodeLabel)
-- get leaf and labels
--local nodeLeaf = mw.getCurrentFrame():getParent().args[tostring(childNumber)] or "" -- used passed variable to avoid redundancy
--local nodeLabel = mw.getCurrentFrame():getParent().args['label'..tostring(childNumber)] or "" -- request in addLabel
-- get formating parameters for branch (default to global nodeParameters)
-- - the branch parameters have a number, e.g. |colorN, |thicknessN, |stateN
-- - the node parameters have no number, e.g. |color, |thickness, |state
local branchThickness = tonumber(mw.getCurrentFrame():getParent().args['thickness'..tostring(childNumber)]) or nodeThickness
local branchColor = mw.getCurrentFrame():getParent().args['color'..tostring(childNumber)] or nodeColor --"black"
local branchStyle = mw.getCurrentFrame():getParent().args['style'..tostring(childNumber)] or ""
local branchState = mw.getCurrentFrame():getParent().args['state'..tostring(childNumber)] or nodeState -- "solid"
if branchState == 'double' then if branchThickness < 2 then branchThickness = 3 end end -- need thick line for double
-- the left border takes node parameters, the bottom border takes branch parameters
local bottomBorder = tostring(branchThickness) ..'px ' .. branchState .. ' ' .. branchColor
local leftBorder = tostring(nodeThickness) ..'px ' .. nodeState .. ' ' .. nodeColor
-- variables for right hand bar or bracket
--local barColor = ""
local barRight = mw.getCurrentFrame():getParent().args['bar'..tostring(childNumber)] or "0"
local barBottom = mw.getCurrentFrame():getParent().args['barend'..tostring(childNumber)] or "0"
local barTop = mw.getCurrentFrame():getParent().args['barbegin'..tostring(childNumber)] or "0"
local barLabel = mw.getCurrentFrame():getParent().args['barlabel'..tostring(childNumber)] or ""
local groupLabel = mw.getCurrentFrame():getParent().args['grouplabel'..tostring(childNumber)] or ""
local groupLabelStyle = mw.getCurrentFrame():getParent().args['labelstyle'..tostring(childNumber)] or ""
--replace colours with format string; need right bar for all three options
if barRight ~= "0" then barRight = "2px solid " .. barRight end
if barTop ~= "0" then barRight = "2px solid " .. barTop end
if barBottom ~= "0" then barRight = "2px solid " .. barBottom end
if barTop ~= "0" then barTop = "2px solid " .. barTop end
if barBottom ~= "0" then barBottom = "2px solid " .. barBottom end
-- now construct wikitext
local styleString = ''
local cladeString = ''
--[[ first add cell to the spacing row (for 2-17); it completes the previous row
why is this here rather than at the end of each row?
To allow left border (here while extending bracket) or not (end of bracket)
]]
if childNumber ~= 1 then
local subLabel = mw.getCurrentFrame():getParent().args['sublabel'..tostring(childNumber-1)] or "" -- request in addLabel
--styleString = ' style="border-left:' .. leftBorder ..';border-top:0;border-right:0;border-bottom:0;vertical-align:top;text-align:center;"'
styleString = ' style="border:0;border-left:' .. leftBorder ..';vertical-align:top;text-align:center;"'
--cladeString = cladeString .. '| ' .. styleString .. ' | <br/> ' -- for sublabel ' | y<br/> '
cladeString = cladeString .. '|' .. styleString .. '|' .. p.addLabel(childNumber-1,subLabel)
end
-- new row
cladeString = cladeString .. '\n|-'
-- now add cell with label
styleString = ''
if childNumber == 1 then
-- the width gives minimum spacing when all labels are empty (was 1.5em)
--styleString = ' style="width:1em;border-bottom:' .. bottomBorder .. ';border-left:0;border-top:0;border-right:0;padding:0 0.2em;vertical-align:bottom;text-align:center;' .. branchStyle .. '"'
styleString = ' style="width:1em;border:0;padding:0 0.2em;border-bottom:' .. bottomBorder .. ';vertical-align:bottom;text-align:center;' .. branchStyle .. '"'
else -- for 2-17
styleString = ' style="border:0;padding:0 0.2em;border-left:' .. leftBorder .. ';border-bottom:' .. bottomBorder .. ';vertical-align:bottom;text-align:center;' .. branchStyle .. '"'
end
cladeString = cladeString .. '\n|' .. styleString .. '|' .. p.addLabel(childNumber,nodeLabel) -- p.addLabel(nodeLabel)
-- add cell with leaf (which may be a table with transluded content)
--cladeString = cladeString .. '|| rowspan=2 style="border: 0; padding: 0; border-right: ' .. barRight .. ';border-bottom: ' .. barBottom .. ';border-top: ' .. barTop .. ';' .. branchStyle .. ' " | '
styleString = ''
if barRight ~= "0" then
styleString = 'style="border:0;padding:0;border-right:' .. barRight .. ';border-bottom:' .. barBottom .. ';border-top:' .. barTop .. ';' .. branchStyle .. '"'
else
styleString = 'style="border:0;padding:0;' .. branchStyle .. '"'
end
cladeString = cladeString .. '||rowspan=2 ' .. styleString .. '|'
-- note: this is where leading spaces can be added to labels and leaves. This was commented out in the clade template. Most trees seem to have added spaces, to would need to check for existing spaces; however, cladex uses it
-- or could use padding:0 0.2em in cell style as for labels
cladeString = cladeString .. '\n' .. nodeLeaf
-- stuff for right-hand bar-bracket
if barRight ~= "0" then
cladeString = cladeString .. ' ' -- add spaces between leaf text and bar
if barLabel ~= "" then
-- cladeString = cladeString .. '\n| ' .. barLabel end -- experiment for labeling the bar
cladeString = cladeString .. '<td style="vertical-align:middle;">' .. barLabel ..'</td>'
end
end
if groupLabel ~= ""then
--cladeString = cladeString .. ' ' -- add spaces between leaf text and bar (could use padding)
cladeString = cladeString .. '<td style="'.. groupLabelStyle .. '">' .. groupLabel ..'</td>'
end
-- add row (needed because of rowspan=2);
-- note: the cell will be added on the next iteration of addTaxon (with left border) or after the main loop (without left border)
local branchStyleString = 'style="' .. branchStyle .. '" '
if branchStyle == '' then branchStyleString = '' end -- avoid empty style elements
cladeString = cladeString .. '\n|-' .. branchStyleString
-- TODO code to put whole row here instead of completing on next call to addTaxon() or after main loop
return cladeString
end
--[[ adds text for label or sublabel to a cell
]]
function p.addLabel(childNumber,nodeLabel)
--local nodeLabel = mw.getCurrentFrame():getParent().args['label'..tostring(childNumber)] or ""
local firstChars = string.sub(nodeLabel, 1,2) -- get first two characters; will be {{ if no parameter (for Old method?)
--if nodeLabel ~= "{{{label1}}}" then
if firstChars == "{{{" or nodeLabel == "" then
return '<br/>' --' <br/>' -- remove space to reduce post-expand include size (the width=1.5em handles spacing)
else
-- spaces can cause wrapping and can break tree structure, hence use span with nowrap class
--return '<span class="nowrap">' .. nodeLabel .. '</span>'
-- a better method for template expansion size is to replace spaces with nonbreaking spaces
-- however, there is a problem if labels have a styling element (e.g. <span style= ..., <span title= ...)
local stylingElementDetected = false
if string.find(nodeLabel, "span ") ~= nil then stylingElementDetected = true end
if string.find(nodeLabel, " style") ~= nil then stylingElementDetected = true end
if stylingElementDetected == true then
return '<span class="nowrap">' .. nodeLabel .. '</span>'
else
local nowrapString = string.gsub(nodeLabel," ", " ") -- replace spaces with non-breaking space
return nowrapString
end
end
end
--[[=================== Newick string handling function =============================
]]
function p.getNewickOuterterm(newickString)
return string.gsub(newickString, "%b()", "") -- delete parenthetic term
end
function p.newick(count,newickString)
local cladeString = ""
count = count+1
--start table
cladeString = cladeString .. '{| cellspacing=0 cellpadding=0 border=0 '
-- newickString = string.gsub(newickString, ",%s*", ",") -- remove spaces after commas (need to watch this)
local j,k
j,k = string.find(newickString, '%(.*%)') -- find location of outer parenthesised term
local innerTerm = string.sub(newickString, j+1, k-1) -- select content in parenthesis
local outerTerm = string.gsub(newickString, "%b()%s*", "") -- delete parenthetic term [added %s* ?]
--if outerTerm == 'panthera' then outerTerm = "x" end -- how is this set in local variable for inner nodes?
outerTerm = tostring(count)
-- need to remove commas in bracket terms before split, so temporarily replace commas between brackets
local innerTerm2 = string.gsub(innerTerm, "%b()", function (n)
return string.gsub(n, ",%s*", "XXX") -- also strip spaces after commas here
end)
--cladeString = cladeString .. '\n' .. p.addTaxon(1, innerTerm2, "")
local s = strsplit(innerTerm2, ",")
local i=1
while s[i] do
restoredString = string.gsub(s[i],"XXX%s*", ",") -- convert back to commas
--restoredString = s[i]
local outerTerm = string.gsub(restoredString, "%b()", "")
if string.find(restoredString, '%(.*%)') then
--cladeString = cladeString .. '\n' .. p.addTaxon(i, restoredString, "x")
cladeString = cladeString .. '\n' .. p.addTaxon(i, p.newick(count,restoredString), outerTerm)
-- p.addTaxon(2, p.newick(count,newickString2), "root")
else
cladeString = cladeString .. '\n' .. p.addTaxon(i, restoredString, "") --count)
end
i=i+1
end
-- close table
cladeString = cladeString .. '\n' .. '| style="border: 0; padding: 0; vertical-align: top;" | <br/> \n|}'
return cladeString
end
-- emulate a standard split string function
function strsplit(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t={} ; i=1
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
t[i] = str
i = i + 1
end
return t
end
-- Bits from Peter Coxhead's module
-- https://en.wikipedia.org/w/index.php?title=Module:Autotaxobox&action=edit
--[[
Utility function primarily intended for use in checking and debugging.
Returns number of levels in a taxonomic hierarchy, starting from
the supplied taxon as level 1.
Usage: {{#invoke:Autotaxobox|nLevels|TAXON}}
]]
function p.nLevels(frame)
local currTaxon = frame.args[1]
local i = 1
local maxN = 2
local searching = true
while searching and i < maxN do
--local parent = frame:expandTemplate{ title = 'Template:Taxonomy/' .. currTaxon, args = {['machine code'] = 'parent' } }
local parent = frame:expandTemplate{ title = currTaxon, args = {['machine code'] = 'parent' } }
if parent ~= '' then
currTaxon = parent
i = i + 1
else
searching = false
end
end
if searching then return currTaxon --maxN .. '+'
else return i
end
end
--[[
Utility function primarily intended for use in checking and debugging.
Returns a comma separated list of a taxonomic hierarchy, starting from
the supplied taxon.
Usage: {{#invoke:Autotaxobox|listAll|TAXON}}
]]
function p.listAll(frame)
local currTaxon = frame.args[1]
local i = 1
local searching = true
local maxN = 100
local lst = currTaxon
while i < maxN and searching do
local currCall = 'Template:Taxonomy/' .. currTaxon
local parent = frame:expandTemplate{ title = currCall, args = {['machine code'] = 'parent' } }
if parent ~= '' then
currTaxon = parent
lst = lst .. ', ' .. currTaxon
i = i + 1
else
searching = false
end
end
if searching then lst = lst .. '...' end
return lst .. ' (' .. i .. ')'
end
-- =================== experimental Newick to clade parser function =============================
--[[Function of convert Newick strings to clade format
Usage: {{#invoke:Module:Sandbox/Jts1882/CladeN|newickConverter|newickstring={{{NEWICK_STRING}}} }}
]]
function p.newickConverter(frame)
local newickString = frame.args['newickstring']
if newickString == '{{{newickstring}}}' then return newickString end
-- show the Newick string
local cladeString = ''
local levelNumber = 1 -- for depth of iteration
local childNumber = 1 -- number of sister elements on node (always one for root)
-- converted the newick string to the clade structure
cladeString = cladeString .. '{{clade'
cladeString = cladeString .. p.newickParseLevel(newickString, levelNumber, childNumber)
cladeString = cladeString .. '\r}}'
local resultString = ''
local option = mw.getCurrentFrame():getParent().args['option'] or ''
if option == 'tree' then
--show the transcluded clade diagram
resultString = cladeString
else
-- show the Newick string
resultString = '<pre>'..newickString..'</pre>'
-- show the converted clade structure
resultString = resultString .. '<pre>'.. cladeString ..'</pre>'
end
--resultString = frame:expandTemplate{ title = 'clade', frame:preprocess(cladeString) }
return resultString
end
--[[ Parse one level of Newick sting
This function recieves a Newick string, which has two components
1. the right hand term is a clade label: |labelN=labelname
2. the left hand term in parenthesis has common delimited child nodes, each of which can be
i. a taxon name which just needs: |N=leafname
ii. a Newick string which needs further processing through reiteration
]]
function p.newickParseLevel(newickString,levelNumber,childNumber)
local cladeString = ""
local indent = p.getIndent(levelNumber)
--levelNumber=levelNumber+1
local j=0
local k=0
j,k = string.find(newickString, '%(.*%)') -- find location of outer parenthesised term
local innerTerm = string.sub(newickString, j+1, k-1) -- select content in parenthesis
local outerTerm = string.gsub(newickString, "%b()", "") -- delete parenthetic term
cladeString = cladeString .. indent .. '|label'..childNumber..'=' .. outerTerm
cladeString = cladeString .. indent .. '|' .. childNumber..'=' .. '{{clade'
levelNumber=levelNumber+1
indent = p.getIndent(levelNumber)
-- protect commas in inner parentheses from split; temporarily replace commas between parentheses
local innerTerm2 = string.gsub(innerTerm, "%b()", function (n)
return string.gsub(n, ",%s*", "XXX") -- also strip spaces after commas here
end)
local s = strsplit(innerTerm2, ",")
local i=1
while s[i] do
restoredString = string.gsub(s[i],"XXX", ",") -- convert back to commas
local outerTerm = string.gsub(restoredString, "%b()", "")
if string.find(restoredString, '%(.*%)') then
--cladeString = cladeString .. indent .. '|y' .. i .. '=' .. p.newickParseLevel(restoredString,levelNumber+1,i)
cladeString = cladeString .. p.newickParseLevel(restoredString,levelNumber,i)
else
cladeString = cladeString .. indent .. '|' .. i .. '=' .. restoredString --.. '(level=' .. levelNumber .. ')'
end
i=i+1
end
-- end -- end splitting of strings
cladeString = cladeString .. indent .. '}}'
return cladeString
end
function p.getIndent(levelNumber)
local indent = "\r"
local extraIndent = mw.getCurrentFrame():getParent().args['indent'] or 0
while tonumber(extraIndent) > 0 do
indent = indent .. " " -- an extra indent to make aligining compound trees easier
extraIndent = extraIndent - 1
end
while levelNumber > 1 do
indent = indent .. " "
levelNumber = levelNumber-1
end
return indent
end
function p.newickstuff(newickString)
end
------------------------------------------------------------------------------------------
function p.test(dummy)
local dataString = ""
dataString = "NEWCLADE:"
local childNumber =0
local lastNode = 0
while childNumber < 17 do -- disable moreNeeded
childNumber = childNumber + 1 -- so we start with 1
local nodeLeaf = mw.getCurrentFrame():getParent().args[tostring(childNumber)] or "" -- get data from |N=
--local nodeLabel = mw.getCurrentFrame():getParent().args['label'..tostring(childNumber)] or "" -- get data from |labelN=
if nodeLeaf ~= "" then
dataString = dataString .. tostring(childNumber)
local firstChars = string.sub(nodeLeaf, 1,2) -- get first two characters
--if nodeLabel ~= "{{{label1}}}" then
if firstChars == "{{" then
dataString = dataString .. 'XXX' .. nodeLeaf
end
dataString = dataString .. 'LEAF:' .. nodeLeaf
lastNode = childNumber
end
end
local numClades=0
local numBranches=0
-- _, count = string.gsub(dataString, "NEWCLADE", "NEXT")
for i in string.gmatch(dataString, "NEWCLADE") do
numClades = numClades + 1
end
dataString = dataString .. '<br/>(numClades=' .. numClades .. ')'
for i in string.gmatch(dataString, "LEAF") do
numBranches = numBranches + 1
end
dataString = dataString .. '<br/>(numClades=' .. numClades .. ')'
dataString = dataString .. '<br/>(numBranches=' .. numBranches .. ')'
mw:log(numClades)
--return 'numClades=' .. numClades .. '; numBranches=' .. numBranches
return dataString
end
function p.test2(target)
local target ="User:Jts1882/sandbox/templates/Template:Passeroidea"
local result = mw.getCurrentFrame():expandTemplate{ title = target, args = {['style'] = '' } }
return result
end
-- this must be at end
return p
[[Categoría:Páxines con tables frañíes]]