Module:Infobox interval: Difference between revisions
Jump to navigation
Jump to search
Undo revision 184879 by ArrowHead294 (talk). The debug mode is used in several places on the wiki where categories should be disabled Tag: Undo |
m maybe i should discuss this before editing a template lol. Tags: Undo Mobile edit Mobile web edit Advanced mobile edit |
||
| (6 intermediate revisions by 5 users not shown) | |||
| Line 1: | Line 1: | ||
local p = {} | local p = {} | ||
local he = require("Module:Harmonic entropy") | |||
local infobox = require("Module:Infobox") | |||
local rat = require("Module:Rational") | local rat = require("Module:Rational") | ||
local utils = require("Module:Utils") | local utils = require("Module:Utils") | ||
local yesno = require("Module:Yesno") | local yesno = require("Module:Yesno") | ||
| Line 111: | Line 111: | ||
end | end | ||
if rat.is_harmonic(ratio) then | if rat.is_harmonic(ratio) then | ||
num, den = rat.as_pair (ratio) | |||
table.insert(special_properties, "[[harmonic]]") | table.insert(special_properties, "[[harmonic]]") | ||
cats = cats .. "[[Category:Harmonics|" .. string.rep("#", string.len(num)) .. "]]" | cats = cats .. "[[Category:Harmonics|" .. string.rep("#", string.len(num)) .. "]]" | ||
if rat.is_prime(ratio) then | |||
table.insert(special_properties, "[[prime harmonic]]") | |||
cats = cats .. "[[Category:Prime harmonics|" .. string.rep("#", string.len(num)) .. "]]" | |||
end | |||
if rat.is_highly_composite(ratio) then | |||
table.insert(special_properties, "[[highly composite harmonic]]") | |||
cats = cats .. "[[Category:Highly composite harmonics|" .. string.rep("#", string.len(num)) .. "]]" | |||
end | |||
elseif rat.is_harmonic(ratio, true, not small) then | elseif rat.is_harmonic(ratio, true, not small) then | ||
table.insert(special_properties, "[[Harmonic|reduced harmonic]]") | table.insert(special_properties, "[[Harmonic|reduced harmonic]]") | ||
| Line 144: | Line 152: | ||
-- there was a subsequence of 4+ zeros | -- there was a subsequence of 4+ zeros | ||
table.insert(infobox_data, { | table.insert(infobox_data, { | ||
"[[ | "[[Subgroup monzos and vals|Subgroup monzo]]", | ||
rat.as_subgroup_ket(ratio, frame), | rat.as_subgroup_ket(ratio, frame), | ||
}) | }) | ||
| Line 193: | Line 201: | ||
name = name:gsub(",%s+", ",") | name = name:gsub(",%s+", ",") | ||
-- placing line breaks after commas | -- placing line breaks after commas | ||
name = name:gsub(",", ",<br | name = name:gsub(",", ",<br>") | ||
end | end | ||
table.insert(infobox_data, { | table.insert(infobox_data, { | ||
| Line 210: | Line 218: | ||
if value_provided(colour_name) then | if value_provided(colour_name) then | ||
table.insert(infobox_data, { | table.insert(infobox_data, { | ||
"[[ | "[[Kite's color notation|Color name]]", | ||
colour_name, | colour_name, | ||
}) | }) | ||
| Line 250: | Line 258: | ||
table.insert(infobox_data, { | table.insert(infobox_data, { | ||
"Special properties", | "Special properties", | ||
table.concat(special_properties, ",<br | table.concat(special_properties, ",<br>"), | ||
}) | }) | ||
end | end | ||
| Line 257: | Line 265: | ||
if rational and regular then | if rational and regular then | ||
table.insert(infobox_data, { | table.insert(infobox_data, { | ||
"[[Tenney | "[[Tenney norm]] (log<sub>2</sub> ''nd'')", | ||
utils._round(rat.tenney_height(ratio), 6), | utils._round(rat.tenney_height(ratio), 6), | ||
}) | }) | ||
table.insert(infobox_data, { | table.insert(infobox_data, { | ||
"[[Weil | "[[Weil norm]] (log<sub>2</sub> max(''n'', ''d''))", | ||
utils._round(rat.weil_height(ratio), 6), | utils._round(rat.weil_height(ratio), 6), | ||
}) | }) | ||
table.insert(infobox_data, { | table.insert(infobox_data, { | ||
"[[Wilson | "[[Wilson norm]] (sopfr(''nd''))", | ||
utils._round(rat.wilson_height(ratio), 6), | utils._round(rat.wilson_height(ratio), 6), | ||
}) | }) | ||
end | end | ||
if regular then | local harmonic_entropy = frame.args["Harmonic entropy"] | ||
table.insert(infobox_data, { | if regular and value_provided(harmonic_entropy) then | ||
harmonic_entropy_switch = harmonic_entropy:match("^[Yy][Ee][Ss]$") | |||
if harmonic_entropy_switch then | |||
table.insert(infobox_data, { | |||
"[[Harmonic entropy]]<br>(Shannon, <math>\\sqrt{nd}</math>)", | |||
"~" .. utils._round(he.harmonic_entropy(cents), 6) .. " bits", | |||
}) | |||
end | |||
end | end | ||
| Line 306: | Line 318: | ||
local S_expressions = rat.find_S_expression(ratio) | local S_expressions = rat.find_S_expression(ratio) | ||
if #S_expressions > 0 then | if #S_expressions > 0 then | ||
local caption = "[[ | local caption = "[[S-expression]]" | ||
if #S_expressions > 1 then | if #S_expressions > 1 then | ||
caption = caption .. "s" | caption = caption .. "s" | ||
| Line 312: | Line 324: | ||
table.insert(infobox_data, { | table.insert(infobox_data, { | ||
caption, | caption, | ||
table.concat(S_expressions, ",<br | table.concat(S_expressions, ",<br>"), | ||
}) | }) | ||
end | end | ||
| Line 321: | Line 333: | ||
cats = cats .. "[[Category:Pages with internal sound examples]]" | cats = cats .. "[[Category:Pages with internal sound examples]]" | ||
table.insert(infobox_data, { | table.insert(infobox_data, { | ||
"[[File:" .. sound .. "|270px]]<br | "[[File:" .. sound .. "|270px]]<br><span style=\"font-size: 75%;\">[[:File:" .. sound .. "|<nowiki>[sound info]</nowiki>]]</span>", | ||
}) | }) | ||
elseif debug_mode and debug_mode ~= "hide" and regular then | elseif debug_mode and debug_mode ~= "hide" and regular then | ||
Latest revision as of 17:49, 14 September 2025
- This module should not be invoked directly; use its corresponding template instead: Template:Infobox interval.
This module generates an infobox providing information about a given interval.
| Introspection summary for Module:Infobox interval | |||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
| ||||||||||||||||||||||||
No function descriptions were provided. The Lua code may have further information.
local p = {}
local he = require("Module:Harmonic entropy")
local infobox = require("Module:Infobox")
local rat = require("Module:Rational")
local utils = require("Module:Utils")
local yesno = require("Module:Yesno")
-- check whether the input is a non-empty string
local function value_provided(s)
return type(s) == "string" and #s > 0
end
function p.infobox_interval(frame)
local debug_mode = yesno(frame.args["debug"])
local page_name = frame:preprocess("{{PAGENAME}}")
local rational = false
local small = false -- numerator and denominator can be represented as Lua numbers, or irrational
local regular = false -- finite and greater than zero
local ratio = nil
local cents = nil
local ket = nil
local ratio_string = nil
local infobox_data = {}
local cats = ""
-- intervals with relatively small powers
if value_provided(frame.args["Ratio"]) then
ratio = rat.parse(frame.args["Ratio"])
if ratio ~= nil then
rational = true
small = true
regular = not ratio.nan and not ratio.inf and not ratio.zero and ratio.sign > 0
cents = rat.cents(ratio)
ket = rat.as_ket(ratio, frame)
ratio_string = rat.as_ratio(ratio)
end
end
-- intervals with large powers
if ratio == nil and value_provided(frame.args["Ket"]) then
ratio = rat.from_ket(frame.args["Ket"])
if ratio ~= nil then
rational = true
small = false
regular = true
cents = rat.cents(ratio)
ket = rat.as_ket(ratio, frame)
-- display Ratio unless it is page name, in which case it is probably a fallback -- what does this mean?
if frame.args["Ratio"] ~= page_name then
ratio_string = frame.args["Ratio"] or ""
end
end
elseif ratio ~= nil and value_provided(frame.args["Ket"]) then
cats = cats .. "[[Category:Todo:remove explicit ket notation]]"
end
-- irrational intervals
if ratio == nil and value_provided(frame.args["Cents"]) then
cents = tonumber(frame.args["Cents"])
if cents ~= nil then
rational = false
small = true
regular = true
if value_provided(frame.args["Ket"]) then
ket = frame.args["Ket"]
end
-- Ratio is LaTeX unless it is page name, in which case it is probably a fallback -- what does this mean?
if frame.args["Ratio"] ~= page_name then
ratio_string = frame.args["Ratio"] or ""
else
cats = cats .. "[[Category:Todo:add interval ratio]]"
end
end
elseif ratio ~= nil and value_provided(frame.args["Cents"]) then
cats = cats .. "[[Category:Todo:remove explicit cents]]"
end
if not (regular or rational) then
cats = cats .. "[[Category:Todo:initialise interval]]"
end
-- categorize by rationality and prime limit
if regular then
if rational then
local prime_limit = 2
if not rat.eq(ratio, 1) then
prime_limit = rat.max_prime(ratio)
end
cats = cats .. "[[Category:Rational intervals]]" .. "[[Category:" .. prime_limit .. "-limit intervals]]"
else
cats = cats .. "[[Category:Irrational intervals]]"
end
end
local special_properties = {}
if rational then
if small and rat.is_superparticular(ratio) then
if rat.is_square_superparticular(ratio) then
table.insert(special_properties, "[[Square superparticular|square superparticular]]")
else
table.insert(special_properties, "[[Superparticular interval|superparticular]]")
end
cats = cats .. "[[Category:Superparticular ratios]]"
end
if rat.is_reduced(ratio, 2, not small) then
table.insert(special_properties, "[[Octave reduction|reduced]]")
end
if rat.is_harmonic(ratio) then
num, den = rat.as_pair (ratio)
table.insert(special_properties, "[[harmonic]]")
cats = cats .. "[[Category:Harmonics|" .. string.rep("#", string.len(num)) .. "]]"
if rat.is_prime(ratio) then
table.insert(special_properties, "[[prime harmonic]]")
cats = cats .. "[[Category:Prime harmonics|" .. string.rep("#", string.len(num)) .. "]]"
end
if rat.is_highly_composite(ratio) then
table.insert(special_properties, "[[highly composite harmonic]]")
cats = cats .. "[[Category:Highly composite harmonics|" .. string.rep("#", string.len(num)) .. "]]"
end
elseif rat.is_harmonic(ratio, true, not small) then
table.insert(special_properties, "[[Harmonic|reduced harmonic]]")
cats = cats .. "[[Category:Octave-reduced harmonics]]"
elseif rat.is_subharmonic(ratio, true, not small) then
table.insert(special_properties, "[[Subharmonic|reduced subharmonic]]")
cats = cats .. "[[Category:Octave-reduced subharmonics]]"
end
elseif regular then
if cents >= 0 and cents < 1200 then
table.insert(special_properties, "[[Octave reduction|reduced]]")
end
end
if value_provided(ratio_string) then
if rational then
table.insert(infobox_data, {
"Ratio",
ratio_string,
})
else
table.insert(infobox_data, {
"Expression",
"<math>" .. ratio_string .. "</math>",
})
end
end
if regular and rational then
if ket:match("<sup>") then
-- there was a subsequence of 4+ zeros
table.insert(infobox_data, {
"[[Subgroup monzos and vals|Subgroup monzo]]",
rat.as_subgroup_ket(ratio, frame),
})
else
table.insert(infobox_data, {
"Factorization",
rat.factorisation(ratio),
})
table.insert(infobox_data, {
"[[Monzo]]",
ket,
})
end
elseif rational then
table.insert(infobox_data, {
"Factorization",
rat.factorisation(ratio),
})
elseif value_provided(ket) then
-- irrational ket is provided:
table.insert(infobox_data, {
"[[Monzo]]",
frame:expandTemplate({
title = "Monzo",
args = { ket },
}),
})
end
if regular then
table.insert(infobox_data, {
"Size in [[cent]]s",
utils._round(cents, 7) .. "¢",
})
end
local name = frame.args["Name"]
if value_provided(name) then
local caption = "Name"
if name:match(",") then
caption = "Names"
-- removing manual line breaks
local matches
name, matches = name:gsub("<br%s*/?>", "")
if matches > 0 then
cats = cats .. "[[Category:Todo:remove manual line breaks]]"
end
-- removing whitespaces after commas
name = name:gsub(",%s+", ",")
-- placing line breaks after commas
name = name:gsub(",", ",<br>")
end
table.insert(infobox_data, {
caption,
name,
})
else
cats = cats .. "[[Category:Todo:add interval name]]"
table.insert(infobox_data, {
"Name(s)",
"<abbr title=\"missing value for parameter 'Name'\">''missing''</abbr><sup>[[Template:Infobox Interval| ? ]]</sup>",
})
end
local colour_name = frame.args["Color name"]
if value_provided(colour_name) then
table.insert(infobox_data, {
"[[Kite's color notation|Color name]]",
colour_name,
})
elseif regular and rational then
cats = cats .. "[[Category:Todo:add color name]]"
end
local FJS_name = frame.args["FJS name"]
if not value_provided(FJS_name) and rational and regular then
FJS_name = rat.as_FJS(ratio)
elseif value_provided(FJS_name) then
local matches
FJS_name = FJS_name:gsub("%s", "")
FJS_name, matches = FJS_name:gsub("<br%s*/?>", "")
if matches > 0 then
cats = cats .. "[[Category:Todo:remove manual line breaks]]"
end
FJS_name, matches = FJS_name:gsub("<sup>(.*)</sup>", "^{%1}")
if matches > 0 then
cats = cats .. "[[Category:Todo:replace sup and sub with LaTeX]]"
end
FJS_name, matches = FJS_name:gsub("<sub>(.*)</sub>", "_{%1}")
if matches > 0 then
cats = cats .. "[[Category:Todo:replace sup and sub with LaTeX]]"
end
end
if value_provided(FJS_name) then
FJS_name = FJS_name:gsub("^(%w+)", "\\text{%1}")
FJS_name = FJS_name:gsub("(%-%d+)", "{%1}")
if #FJS_name <= 200 then
table.insert(infobox_data, {
"[[Functional Just System|FJS name]]",
"<math>" .. FJS_name .. "</math>",
})
end
end
if #special_properties > 0 then
table.insert(infobox_data, {
"Special properties",
table.concat(special_properties, ",<br>"),
})
end
-- interval complexity
if rational and regular then
table.insert(infobox_data, {
"[[Tenney norm]] (log<sub>2</sub> ''nd'')",
utils._round(rat.tenney_height(ratio), 6),
})
table.insert(infobox_data, {
"[[Weil norm]] (log<sub>2</sub> max(''n'', ''d''))",
utils._round(rat.weil_height(ratio), 6),
})
table.insert(infobox_data, {
"[[Wilson norm]] (sopfr(''nd''))",
utils._round(rat.wilson_height(ratio), 6),
})
end
local harmonic_entropy = frame.args["Harmonic entropy"]
if regular and value_provided(harmonic_entropy) then
harmonic_entropy_switch = harmonic_entropy:match("^[Yy][Ee][Ss]$")
if harmonic_entropy_switch then
table.insert(infobox_data, {
"[[Harmonic entropy]]<br>(Shannon, <math>\\sqrt{nd}</math>)",
"~" .. utils._round(he.harmonic_entropy(cents), 6) .. " bits",
})
end
end
local is_comma = value_provided(frame.args["Comma"])
local comma = nil
if is_comma and regular and cents > 0 then
-- rational powers are not considered commas
if not (rational and rat.is_power(ratio)) then
if cents <= 3.5 then
comma = "[[Unnoticeable comma|unnoticeable]]"
cats = cats .. "[[Category:Unnoticeable commas]]"
elseif cents <= 30 then
comma = "[[Small comma|small]]"
cats = cats .. "[[Category:Small commas]]"
elseif cents <= 100 then
comma = "[[Medium comma|medium]]"
cats = cats .. "[[Category:Medium commas]]"
else
comma = "[[Large comma|large]]"
cats = cats .. "[[Category:Large commas]]"
end
end
end
if comma then
table.insert(infobox_data, {
"[[Comma|Comma size]]",
comma,
})
end
if comma and rational then
local S_expressions = rat.find_S_expression(ratio)
if #S_expressions > 0 then
local caption = "[[S-expression]]"
if #S_expressions > 1 then
caption = caption .. "s"
end
table.insert(infobox_data, {
caption,
table.concat(S_expressions, ",<br>"),
})
end
end
local sound = frame.args["Sound"]
if value_provided(sound) then
cats = cats .. "[[Category:Pages with internal sound examples]]"
table.insert(infobox_data, {
"[[File:" .. sound .. "|270px]]<br><span style=\"font-size: 75%;\">[[:File:" .. sound .. "|<nowiki>[sound info]</nowiki>]]</span>",
})
elseif debug_mode and debug_mode ~= "hide" and regular then
local hz = 2 ^ (math.log(440) / math.log(2) + cents / 1200)
-- is it within hearing range?
if hz >= 20 and hz <= 20000 then
local html_id = "interval_" .. tostring(math.floor(cents))
table.insert(infobox_data, {
"<div style=\"display: flex; justify-content: space-around;\"><div style=\"width: 270px; text-align: center;\">"
.. frame:expandTemplate({
title = "User:Plumtree/Interval Sound",
args = {
Frequency = tostring(hz),
Center = "true",
Label = "Audio demonstration",
Attributes = "id=\"" .. html_id .. "\"",
},
})
.. "<div class=\"sequence-audio-timbre-selector\" data-target=\""
.. html_id
.. "\" data-key=\"interval-audio\" data-default=\"semisine\"></div>"
.. "</div></div>",
})
end
end
if value_provided(frame.args["Calc"]) or (regular and rational) then
local query = frame.args["Calc"] or ""
if not value_provided(query) then
if small then
query = ratio_string
else
query = "|" .. rat.as_ket(ratio, nil, false, true) .. ">"
end
end
query = mw.uri.encode(query)
table.insert(infobox_data, {
"<span style=\"font-size: 75%;\">[https://www.yacavone.net/xen-calc/?q=" .. query .. " Open this interval in ''xen-calc'']</span>",
})
end
local result = infobox.build("<u>Interval information</u>", infobox_data)
if not debug_mode then
result = result .. cats
end
return frame:preprocess(result)
end
return p