Module:JI ratios in ED

From Xenharmonic Wiki
Revision as of 20:20, 24 January 2024 by Ganaram inukshuk (talk | contribs) (Bugfix with primes being entered)
Jump to navigation Jump to search
Module documentation[view] [edit] [history] [purge]
This module should not be invoked directly; use its corresponding template instead: Template:JI ratios in ED.
Module:JI ratios in ED is deprecated and has no replacement. Further use of this module is not advised. This module is kept for historical purposes and should not be deleted.
Introspection summary for Module:JI ratios in ED 
Functions provided (4)
Line Function Params
8 find_ratios_in_ed_by_primes (ed, primes, equave, tenney_height, denominator_limit)
107 parse_ed (unparsed)
115 parse_equave (unparsed)
132 ji_ratios_in_ed_frame (invokable) (frame)
Lua modules required (5)
Variable Module Functions used
interval Module:Interval dependency not used
jiraf Module:JI ratio finder find_candidate_ratios_within_subgroup
filter_ratios_by_range
filter_ratios_by_prime_limit
filter_ratios_by_harmonic_class
filter_ratios_by_complement_agnostic_tenney_height
ratios_to_text_with_error
rat Module:Rational new
cents
as_ratio
copy
parse
tip Module:Template input parse parse_numeric_entries
utils Module:Utils dependency not used

No function descriptions were provided. The Lua code may have further information.


local utils = require('Module:Utils')
local interval = require('Module:Interval')
local rat = require('Module:Rational')
local jiraf = require('Module:JI ratio finder')
local tip = require('Module:Template input parse')
local p = {}

function p.find_ratios_in_ed_by_primes(ed, primes, equave, tenney_height, denominator_limit)
	local ed = ed or 7
	local primes = primes or { 2, 3, 7, 11 }
	local equave = equave or rat.new(3, 2)
	local tenney_height = tenney_height or 10
	local denominator_limit = denominator_limit or 99
	
	local equave_in_cents = rat.cents(equave)
	local tolerance = equave_in_cents / ed * 0.4
	
	-- Find candidate ratios; filter later
	local max_prime = primes[#primes]
	local candidate_ratios = jiraf.find_candidate_ratios_within_subgroup(equave_in_cents, denominator_limit, primes)
	
	-- Equave as text
	local equave_as_text = rat.as_ratio(equave) 
	if equave_as_text == "2/1" then
		equave_as_text = "edo"
	elseif equave_as_text == "3/1" then
		equave_as_text = "edt"
	elseif equave_as_text == "3/2" then
		equave_as_text = "edf"
	end
	
	-- Build table headers
	local result = string.format('{| class="wikitable center-all"\n')
	result = result .. string.format('|+ Intervals of %d%s\n', ed, equave_as_text)
	result = result .. string.format('|-\n')
	result = result .. string.format('! rowspan="2" | [[Degree]]\n')
	result = result .. string.format('! rowspan="2" | [[Cent]]s\n')
	result = result .. string.format('! colspan="%d" | Approximated [[JI]] intervals ([[error]] in cents)\n', #primes)
	result = result .. string.format('|-\n')
	
	-- Add table headers for prime limits (technically harmonic classes)
	for i = 1, #primes do
		local current_prime = primes[i]	
		result = result .. string.format('! [[%d-limit]]\n', current_prime)
	end
	result = result .. string.format('|-\n')
	
	-- Build the rows for each edstep, showing ratios by limit
	for i = 1, ed + 1 do
		local edstep = i - 1
		local edstep_in_cents = (edstep / ed) * equave_in_cents
		local filtered_ratios = {}
		
		-- Override ratios for edsteps for the unison and equave
		-- Otherwise, filter ratios by range
		if i == 1 then
			filtered_ratios = { rat.new(1, 1) }
		elseif i == ed + 1 then
			filtered_ratios = { rat.copy(equave) }
		else
			filtered_ratios = jiraf.filter_ratios_by_range(candidate_ratios, edstep_in_cents - tolerance, edstep_in_cents + tolerance)
		end
		
		result = result .. string.format('| %d\n', edstep)
		result = result .. string.format('| %.3f\n', edstep_in_cents)
		
		-- Add ratios according to harmonic class
		for j = 1, #primes do
			local current_prime = primes[j]
			local prime_filtered_ratios = {}
			
			-- The first column filters by prime limit
			-- Successive columns are filered by harmonic class
			if j == 1 then
				prime_filtered_ratios = jiraf.filter_ratios_by_prime_limit(filtered_ratios, current_prime)
			else
				prime_filtered_ratios = jiraf.filter_ratios_by_harmonic_class(filtered_ratios, current_prime)
			end
			
			-- Filter ratios by complement-agnostic tenney height
			prime_filtered_ratios = jiraf.filter_ratios_by_complement_agnostic_tenney_height(prime_filtered_ratios, tenney_height, equave)
			
			-- Add ratios to cells
			local ratios_as_text = jiraf.ratios_to_text_with_error(prime_filtered_ratios, edstep_in_cents, "<br>", true)
			result = result .. string.format('| %s\n', ratios_as_text)
		end
		
		result = result .. string.format('|-\n')
	end
	
	result = result .. string.format('|}\n')
	
	-- Add footnotes
	local subgroup_as_text = ""
	for i = 1, #primes do
		if i ~= #primes then
			subgroup_as_text = subgroup_as_text .. string.format("%d.", primes[i])
		else
			subgroup_as_text = subgroup_as_text .. primes[i]
		end
	end
	result = result .. string.format("Based on treating %d%s as a %s subgroup temperament. Other approaches are possible.\n", ed, equave_as_text, subgroup_as_text)
	
	return result
end

function p.parse_ed(unparsed)
	local unparsed = unparsed or "12edo"
	
	local ed = tonumber(unparsed) or unparsed:match('(%d+)ed')

	return ed
end

function p.parse_equave(unparsed)
	local unparsed = unparsed or "10ed4"
	
	local equave_unparsed = ""
	if string.match(unparsed, "edo") or tonumber(unparsed) ~= nil then
		equave_unparsed = "2/1"
	elseif string.match(unparsed, "edt") then
		equave_unparsed = "3/1"
	elseif string.match(unparsed, "edf") then
		equave_unparsed = "3/2"
	else
		equave_unparsed = unparsed:match('[%d]+ed([%d]+/[%d]+)') or unparsed:match('[%d]+ed([%d]+)')
	end
	
	return rat.parse(equave_unparsed)
end

function p.ji_ratios_in_ed_frame(frame)
	
	local ed = p.parse_ed(frame.args["ED"])
	local equave = p.parse_equave(frame.args["ED"])

	local primes_as_text = "2.3.5.7.11.13"
	if string.len(frame.args["Primes"]) > 0 then
		primes_as_text = frame.args["Primes"]
	end
	local primes = tip.parse_numeric_entries(primes_as_text, '.') or tip.parse_numeric_entries(primes_as_text, ',')
	
	local tenney_height = tonumber(frame.args["Tenney Height"]) or 10
	local denominator_limit = tonumber(frame.args["Denominator Limit"]) or 99
	
	local result = p.find_ratios_in_ed_by_primes(ed, primes, equave, tenney_height, denominator_limit)
	
	return result
	
end

return p