% Variation log-day analysis + Cohen's f + power simulation, for BOTH metrics:
%   metric = count : behavior = # successes         -> logpower_result.txt
%   metric = rate  : behavior = success / attempts  -> logpower_result_rate.txt
%
% The paper's power code models behavior against LOG training day:
%   behavior ~ stim + log(day) + stim:log(day) + (1|rat).
% Their day is 1-indexed; our data.csv day is 0-indexed, so log(day + 1)
% reproduces their transform (our day 0 = paper "Day 1"). For each metric this
% refits that model, reports the interaction (residual / Satterthwaite / honest
% per-animal random-slope DF) and Cohen's f (partial-eta^2 effect size), then
% runs the Monte-Carlo power sim (per-animal cluster-honest + LME power).
% Run:  matlab -batch "logpowersim"
% (Copy of analysis/matlab/variation_logpower.m; see make_variation_logpower.m.)

here = fileparts(mfilename('fullpath'));
if isempty(here); here = pwd; end
vname = regexprep(here, '.*[/\\]', '');
D = readtable(fullfile(here, 'data.csv'), 'TextType', 'string');

localLogPower(D, 'count', here, vname);
localLogPower(D, 'rate', here, vname);

% ---------------------------------------------------------------- per metric
function localLogPower(D, metric, here, vname)
NS = [3 5 8 12 16 24]; EFFMULS = [1 0.5]; NREP = 120;
FORMULA = 'behavior ~ stim + day + stim:day + (1|rat)';   % 'day' = log(day+1)
if strcmp(metric, 'rate')
    D = D(D.total > 0, :); beh = D.success ./ D.total; mlabel = 'success RATE'; suffix = '_rate';
else
    beh = D.success; mlabel = '# successes (count)'; suffix = '';
end
warnState = warning('off', 'all'); rng(1);
logday = log(D.day + 1);
tbl0 = table(beh, logday, double(D.stim), categorical(D.subject), ...
    'VariableNames', {'behavior', 'day', 'stim', 'rat'});
nStim = numel(unique(D.subject(D.stim == 1)));
nCtrl = numel(unique(D.subject(D.stim == 0)));

bar = repmat('=', 1, 78);
s = sprintf('%s\nLOG-DAY MODEL + COHEN''S f + POWER -- %s   [metric: %s]\n%s\n', bar, vname, mlabel, bar);
s = [s sprintf('model: behavior ~ stim + log(day) + stim:log(day) + (1|rat)   (behavior = %s)\n', mlabel)];
s = [s sprintf('log(day) uses 1-indexed training day (our day 0 = paper "Day 1")\n')];
s = [s sprintf('observed groups: stim n=%d, control n=%d   nrep=%d, alpha=0.05\n', nStim, nCtrl, NREP)];

if nStim < 2 || nCtrl < 2 || numel(unique(tbl0.day)) < 2
    s = [s sprintf('\nInsufficient data for this analysis.\n')];
    localFinish(s, here, suffix); warning(warnState); return
end

full = fitlme(tbl0, FORMULA);
An = anova(full); Asatt = anova(full, 'DFMethod', 'satterthwaite');
ii = strcmp(An.Term, 'day:stim'); is = strcmp(Asatt.Term, 'day:stim');
reduced = fitlme(tbl0, 'behavior ~ stim + day + (1|rat)');
eta2part = max((var(fitted(full)) - var(fitted(reduced))) / var(tbl0.behavior), 0);
cohenf = sqrt(eta2part / (1 - eta2part));

rsP = NaN; rsDf = NaN; rsF = NaN; rsOk = false;
try
    mr = fitlme(tbl0, 'behavior ~ stim + day + stim:day + (day|rat)');
    Ar = anova(mr, 'DFMethod', 'satterthwaite'); ri = strcmp(Ar.Term, 'day:stim');
    rsF = Ar.FStat(ri); rsDf = Ar.DF2(ri); rsP = Ar.pValue(ri); rsOk = true;
catch
end
if cohenf < 0.10; mag = 'small';
elseif cohenf < 0.25; mag = 'small-medium';
elseif cohenf < 0.40; mag = 'medium';
else; mag = 'large'; end

s = [s sprintf('\n--- fitted on real data ---\n')];
s = [s sprintf('stim x log(day) interaction: F(1,%d)=%.3f  p(resid)=%.4g  p(Satt)=%.4g (df=%.0f)\n', ...
    An.DF2(ii), An.FStat(ii), An.pValue(ii), Asatt.pValue(is), Asatt.DF2(is))];
if rsOk
    s = [s sprintf('  honest per-animal random slope (log-day): F(1,%.1f)=%.2f  p=%.4g\n', rsDf, rsF, rsP)];
else
    s = [s sprintf('  honest per-animal random slope (log-day): did not converge\n')];
end
s = [s sprintf('Cohen''s f (interaction, partial eta^2=%.3f) = %.3f  (%s; f: .10 small, .25 medium, .40 large)\n', ...
    eta2part, cohenf, mag)];

cn = full.CoefficientNames; be = full.fixedEffects;
b0 = be(strcmp(cn, '(Intercept)')); bStim = be(strcmp(cn, 'stim'));
bDay = be(strcmp(cn, 'day')); bInt = be(strcmp(cn, 'day:stim'));
psi = covarianceParameters(full); sRat = sqrt(psi{1}); sRes = sqrt(full.MSE);
days = unique(tbl0.day);

s = [s sprintf('\n--- power simulation (log-day ground truth: stim:logday=%+.4g, ratSD=%.4g, resSD=%.4g) ---\n', ...
    bInt, sRat, sRes)];
for eMul = EFFMULS
    bI = bInt * eMul;
    s = [s sprintf('\n true stim:log(day) = %+.4g (%.0f%% of observed)\n', bI, eMul * 100)];
    s = [s sprintf('  %-8s | per-animal power | LME power\n  %s\n', 'N/group', repmat('-', 1, 42))];
    for N = NS
        sigPA = 0; sigL = 0;
        for r = 1:NREP
            tb = localSim(N, days, b0, bStim, bDay, bI, sRat, sRes);
            sigPA = sigPA + (localPAp(tb) < 0.05);
            try
                m = fitlme(tb, FORMULA); Cm = m.Coefficients;
                sigL = sigL + (Cm.pValue(strcmp(Cm.Name, 'day:stim')) < 0.05);
            catch
            end
        end
        star = '';
        if N == nStim || N == nCtrl; star = '  <- observed'; end
        s = [s sprintf('  %-8d | %5.2f            | %5.2f%s\n', N, sigPA / NREP, sigL / NREP, star)];
    end
end
s = [s sprintf('\nRead per-animal as the honest power; LME matches the paper''s power code (optimistic).\n')];
localFinish(s, here, suffix);
warning(warnState);
end

% ---------------------------------------------------------------- helpers
function localFinish(s, here, suffix)
fprintf('%s', s);
fid = fopen(fullfile(here, ['logpower_result' suffix '.txt']), 'w');
fprintf(fid, '%s', s); fclose(fid);
end

function tbl = localSim(N, days, b0, bStim, bDay, bI, sRat, sRes)
nd = numel(days); rows = 2 * N * nd;
rat = strings(rows, 1); day = zeros(rows, 1); stim = zeros(rows, 1); behavior = zeros(rows, 1);
k = 0;
for g = 0:1
    for sIdx = 1:N
        re = sRat * randn;
        rid = sprintf('g%d_r%d', g, sIdx);
        for d = 1:nd
            k = k + 1;
            rat(k) = rid; day(k) = days(d); stim(k) = g;
            behavior(k) = b0 + bStim * g + bDay * days(d) + bI * days(d) * g + re + sRes * randn;
        end
    end
end
tbl = table(categorical(rat), day, stim, behavior, ...
    'VariableNames', {'rat', 'day', 'stim', 'behavior'});
end

function p = localPAp(tbl)
rats = unique(tbl.rat); sl = zeros(numel(rats), 1); gr = zeros(numel(rats), 1);
for i = 1:numel(rats)
    r = tbl.rat == rats(i);
    c = polyfit(tbl.day(r), tbl.behavior(r), 1); sl(i) = c(1);
    gr(i) = tbl.stim(find(r, 1));
end
[~, p] = ttest2(sl(gr == 1), sl(gr == 0), 'Vartype', 'unequal');
end
