function t_scale_load(quiet)
%T_SCALE_LOAD  Tests for code in SCALE_LOAD.

%   MATPOWER
%   Copyright (c) 2008-2016, Power Systems Engineering Research Center (PSERC)
%   by Ray Zimmerman, PSERC Cornell
%
%   This file is part of MATPOWER.
%   Covered by the 3-clause BSD License (see LICENSE file for details).
%   See https://matpower.org for more info.

if nargin < 1
    quiet = 0;
end

n_tests = 846;

t_begin(n_tests, quiet);

%% define named indices into data matrices
[PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
    VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
[GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
    MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
    QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
[PW_LINEAR, POLYNOMIAL, MODEL, STARTUP, SHUTDOWN, NCOST, COST] = idx_cost;

mpc = loadcase('t_auction_case');
mpc.gen(8, GEN_BUS) = 2;    %% multiple d. loads per area, same bus as gen
mpc.gen(8, [QG QMIN QMAX]) = [ 3 0 3 ];
mpc.gencost(7, COST:end) = [-30 -600 -20 -300 -10 -100 0 0];    % 10, 20, 30
mpc.gencost(8, COST:end) = [-30  -60 -20  -30 -10  -10 0 0];    % 1, 2, 3
mpc.gencost(9, COST:end) = [-30 -850 -10 -250  -5  -50 0 0];    % 10, 20, 30
%% split a load in 2 half-size duplicates at same bus ...
mpc.gen(8, [PG PMIN PMAX QG QMIN QMAX]) = mpc.gen(8, [PG PMIN PMAX QG QMIN QMAX]) / 2;
mpc.gencost(8, COST:end) = mpc.gencost(8, COST:end) / 2;
%% ... with one before gens in matrix
mpc.gen = [mpc.gen(8, :); mpc.gen];
mpc.gencost = [mpc.gencost(8, :); mpc.gencost];
gg = find(~isload(mpc.gen));
ld = find( isload(mpc.gen));
for k = 1:3
    a{k} = find(mpc.bus(:, BUS_AREA) == k); %% buses in area k
    tmp = find(ismember(mpc.gen(ld, GEN_BUS), a{k}));
    lda{k} = ld(tmp);                       %% disp loads in area k
end
for k = 1:3
    area(k).fixed.p = sum(mpc.bus(a{k}, PD));
    area(k).fixed.q = sum(mpc.bus(a{k}, QD));
    area(k).disp.p = -sum(mpc.gen(lda{k}, PMIN));
    area(k).disp.qmin = -sum(mpc.gen(lda{k}, QMIN));
    area(k).disp.qmax = -sum(mpc.gen(lda{k}, QMAX));
    area(k).disp.q = area(k).disp.qmin + area(k).disp.qmax;
    area(k).both.p = area(k).fixed.p + area(k).disp.p;
    area(k).both.q = area(k).fixed.q + area(k).disp.q;
end
total.fixed.p = sum(mpc.bus(:, PD));
total.fixed.q = sum(mpc.bus(:, QD));
total.disp.p = -sum(mpc.gen(ld, PMIN));
total.disp.qmin = -sum(mpc.gen(ld, QMIN));
total.disp.qmax = -sum(mpc.gen(ld, QMAX));
total.disp.q = total.disp.qmin + total.disp.qmax;
total.both.p = total.fixed.p + total.disp.p;
total.both.q = total.fixed.q + total.disp.q;
orig_gc = mpc.gencost;

%%-----  single load zone, one scale factor  -----
dmd = 2;
t = 'all fixed loads (PQ) * 2 : ';
bus = scale_load(dmd, mpc.bus);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd*total.fixed.q, 8, [t 'total fixed Q']);
opt = struct('which', 'FIXED');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);

t = 'all fixed loads (P) * 2 : ';
opt = struct('pq', 'P');
bus = scale_load(dmd, mpc.bus, [], [], opt);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
opt = struct('pq', 'P', 'which', 'FIXED');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);

t = 'all loads (PQ) * 2 : ';
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd*total.disp.qmax, 8, [t 'total disp Qmax']);

t = 'all loads/costs (PQ) * 2 : ';
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], [], mpc.gencost);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), 2*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all loads/costs (PQ) * 2 : ';
opt = struct('cost', 1);
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], opt, mpc.gencost);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), 2*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all loads (PQ) * 2 : ';
opt = struct('cost', 0);
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], opt, mpc.gencost);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end),   orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all loads (P) * 2 : ';
opt = struct('pq', 'P');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);

t = 'all loads/costs (P) * 2 : ';
opt = struct('pq', 'P');
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], opt, mpc.gencost);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), 2*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all disp loads (PQ) * 2 : ';
opt = struct('which', 'DISPATCHABLE');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd*total.disp.qmax, 8, [t 'total disp Qmax']);

t = 'all disp loads/costs (PQ) * 2 : ';
opt = struct('which', 'DISPATCHABLE');
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], opt, mpc.gencost);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), 2*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all disp loads (P) * 2 : ';
opt = struct('pq', 'P', 'which', 'DISPATCHABLE');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);

t = 'all disp loads/costs (P) * 2 : ';
opt = struct('pq', 'P', 'which', 'DISPATCHABLE');
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], opt, mpc.gencost);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), 2*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

%%-----  single load zone, one scale quantity  -----
dmd = 200;
t = 'all fixed loads (PQ) => total = 200 : ';
opt = struct('scale', 'QUANTITY');
bus = scale_load(dmd, mpc.bus, [], [], opt);
t_is(sum(bus(:, PD)), dmd, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd/total.fixed.p*total.fixed.q, 8, [t 'total fixed Q']);
opt = struct('scale', 'QUANTITY', 'which', 'FIXED');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
t_is(sum(bus(:, PD)), dmd-total.disp.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), (dmd-total.disp.p)/total.fixed.p*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);

t = 'all fixed loads (P) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P');
bus = scale_load(dmd, mpc.bus, [], [], opt);
t_is(sum(bus(:, PD)), dmd, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
opt = struct('scale', 'QUANTITY', 'pq', 'P', 'which', 'FIXED');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
t_is(sum(bus(:, PD)), dmd-total.disp.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);

t = 'all loads (PQ) => total = 200 : ';
opt = struct('scale', 'QUANTITY');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
t_is(sum(bus(:, PD)), dmd/total.both.p*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd/total.both.p*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd/total.both.p*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd/total.both.p*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd/total.both.p*total.disp.qmax, 8, [t 'total disp Qmax']);

t = 'all loads/costs (PQ) => total = 200 : ';
opt = struct('scale', 'QUANTITY');
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], opt, mpc.gencost);
t_is(sum(bus(:, PD)), dmd/total.both.p*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd/total.both.p*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd/total.both.p*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd/total.both.p*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd/total.both.p*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), dmd/total.both.p*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all loads (P) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
t_is(sum(bus(:, PD)), dmd/total.both.p*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd/total.both.p*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);

t = 'all loads/costs (P) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P');
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], opt, mpc.gencost);
t_is(sum(bus(:, PD)), dmd/total.both.p*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd/total.both.p*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), dmd/total.both.p*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all disp loads (PQ) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'which', 'DISPATCHABLE');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd-total.fixed.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), (dmd-total.fixed.p)/total.disp.p*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), (dmd-total.fixed.p)/total.disp.p*total.disp.qmax, 8, [t 'total disp Qmax']);

t = 'all disp loads/costs (PQ) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'which', 'DISPATCHABLE');
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], opt, mpc.gencost);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd-total.fixed.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), (dmd-total.fixed.p)/total.disp.p*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), (dmd-total.fixed.p)/total.disp.p*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), (dmd-total.fixed.p)/total.disp.p*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all disp loads (P) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P', 'which', 'DISPATCHABLE');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd-total.fixed.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);

t = 'all disp loads/costs (P) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P', 'which', 'DISPATCHABLE');
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], opt, mpc.gencost);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd-total.fixed.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), (dmd-total.fixed.p)/total.disp.p*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

%%-----  3 zones, area scale factors  -----
t = 'area fixed loads (PQ) * [3 2 1] : ';
dmd = [3 2 1];
bus = scale_load(dmd, mpc.bus);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), dmd(k)*area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
end
opt = struct('which', 'FIXED');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), dmd(k)*area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
end

t = 'area fixed loads (P) * [3 2 1] : ';
dmd = [3 2 1];
opt = struct('pq', 'P');
bus = scale_load(dmd, mpc.bus, [], [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
end
opt = struct('pq', 'P', 'which', 'FIXED');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
end

t = 'all area loads (PQ) * [3 2 1] : ';
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), dmd(k)*area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), dmd(k)*area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), dmd(k)*area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
end

t = 'all area loads/costs (PQ) * [3 2 1] : ';
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], [], mpc.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), dmd(k)*area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), dmd(k)*area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), dmd(k)*area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), dmd(k)*orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'all area loads (P) * [3 2 1] : ';
opt = struct('pq', 'P');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
end

t = 'all area loads/costs (P) * [3 2 1] : ';
opt = struct('pq', 'P');
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], opt, mpc.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), dmd(k)*orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'area disp loads (PQ) * [3 2 1] : ';
opt = struct('which', 'DISPATCHABLE');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), dmd(k)*area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), dmd(k)*area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
end

t = 'area disp loads/costs (PQ) * [3 2 1] : ';
opt = struct('which', 'DISPATCHABLE');
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], opt, mpc.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), dmd(k)*area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), dmd(k)*area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), dmd(k)*orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'area disp loads (P) * [3 2 1] : ';
opt = struct('pq', 'P', 'which', 'DISPATCHABLE');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
end

t = 'area disp loads/costs (P) * [3 2 1] : ';
opt = struct('pq', 'P', 'which', 'DISPATCHABLE');
[bus, gen, gencost] = scale_load(dmd, mpc.bus, mpc.gen, [], opt, mpc.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), dmd(k)*orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

%%-----  3 zones, area scale quantities  -----
t = 'area fixed loads (PQ) => total = [100 80 60] : ';
dmd = [100 80 60];
opt = struct('scale', 'QUANTITY');
bus = scale_load(dmd, mpc.bus, [], [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k), 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), dmd(k)/area(k).fixed.p*area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
end
opt = struct('scale', 'QUANTITY', 'which', 'FIXED');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)-area(k).disp.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), (dmd(k)-area(k).disp.p)/area(k).fixed.p*area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
end

t = 'area fixed loads (P) => total = [100 80 60] : ';
dmd = [100 80 60];
opt = struct('scale', 'QUANTITY', 'pq', 'P');
bus = scale_load(dmd, mpc.bus, [], [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k), 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
end
opt = struct('scale', 'QUANTITY', 'pq', 'P', 'which', 'FIXED');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)-area(k).disp.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
end

t = 'all area loads (PQ) => total = [100 80 60] : ';
opt = struct('scale', 'QUANTITY');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)/area(k).both.p*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), dmd(k)/area(k).both.p*area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)/area(k).both.p*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), dmd(k)/area(k).both.p*area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), dmd(k)/area(k).both.p*area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
end

t = 'all area loads (P) => total = [100 80 60] : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)/area(k).both.p*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)/area(k).both.p*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
end

t = 'area disp loads (PQ) => total = [100 80 60] : throws expected exception';
dmd = [100 80 60];
opt = struct('scale', 'QUANTITY', 'which', 'DISPATCHABLE');
err = 0;
try
    [bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
catch
    [msg, id] = lasterr;
    expected = 'scale_load: impossible to make zone 2 load equal 80 by scaling non-existent dispatchable load';
    if ~isempty(strfind(msg, expected))
        err = 1;
    end
end
t_ok(err, t);

t = 'area disp loads (PQ) => total = [100 74.3941 60] : ';
dmd = [100 area(2).fixed.p 60];
opt = struct('scale', 'QUANTITY', 'which', 'DISPATCHABLE');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)-area(k).fixed.p, 8, sprintf('%s area %d disp P', t, k));
    if k == 2
        t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
        t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    else
        t_is(-sum(gen(lda{k}, QMIN)), (dmd(k)-area(k).fixed.p)/area(k).disp.p*area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
        t_is(-sum(gen(lda{k}, QMAX)), (dmd(k)-area(k).fixed.p)/area(k).disp.p*area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    end
end

t = 'area disp loads (P) => total = [100 74.3941 60] : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P', 'which', 'DISPATCHABLE');
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, [], opt);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)-area(k).fixed.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
end

%%-----  explict single load zone  -----
t = 'explicit single load zone';
load_zone = zeros(1, size(mpc.bus, 1));
load_zone([3 4]) = 1;
dmd = 2;
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, load_zone);
Pd = mpc.bus(:, PD);
Pd([3 4]) = dmd * Pd([3 4]);
t_is( bus(:, PD), Pd, 8, t);

%%-----  explict multiple load zone  -----
t = 'explicit multiple load zone';
load_zone = zeros(1, size(mpc.bus, 1));
load_zone([3 4]) = 1;
load_zone([7 8]) = 2;
dmd = [2 0.5];
[bus, gen] = scale_load(dmd, mpc.bus, mpc.gen, load_zone);
Pd = mpc.bus(:, PD);
Pd([3 4]) = dmd(1) * Pd([3 4]);
Pd([7 8]) = dmd(2) * Pd([7 8]);
t_is( bus(:, PD), Pd, 8, t);

%%------------------------------------------------------------------
%% mostly same tests below, but with MPC input/output

%%-----  single load zone, one scale factor  -----
dmd = 2;
t = 'all loads (PQ) * 2 : ';
opt = struct('cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end),   orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all loads/costs (PQ) * 2 : ';
mpc1 = scale_load(dmd, mpc);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), 2*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all loads (P) * 2 : ';
opt = struct('pq', 'P', 'cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end),   orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all loads/costs (P) * 2 : ';
opt = struct('pq', 'P');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), dmd*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), 2*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all disp loads (PQ) * 2 : ';
opt = struct('which', 'DISPATCHABLE', 'cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end),   orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all disp loads/costs (PQ) * 2 : ';
opt = struct('which', 'DISPATCHABLE');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), 2*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all disp loads (P) * 2 : ';
opt = struct('pq', 'P', 'which', 'DISPATCHABLE', 'cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end),   orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all disp loads/costs (P) * 2 : ';
opt = struct('pq', 'P', 'which', 'DISPATCHABLE', 'cost', 1);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), 2*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

%%-----  single load zone, one scale quantity  -----
dmd = 200;
t = 'all fixed loads (PQ) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'which', 'FIXED');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), dmd-total.disp.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), (dmd-total.disp.p)/total.fixed.p*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end),   orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all fixed loads (P) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P', 'which', 'FIXED', 'cost', 1);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), dmd-total.disp.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end),   orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all loads (PQ) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), dmd/total.both.p*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd/total.both.p*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd/total.both.p*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd/total.both.p*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd/total.both.p*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end),   orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all loads/costs (PQ) => total = 200 : ';
opt = struct('scale', 'QUANTITY');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), dmd/total.both.p*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), dmd/total.both.p*total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd/total.both.p*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), dmd/total.both.p*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), dmd/total.both.p*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), dmd/total.both.p*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all loads (P) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P', 'cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), dmd/total.both.p*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd/total.both.p*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end),   orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all loads/costs (P) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), dmd/total.both.p*total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd/total.both.p*total.disp.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), dmd/total.both.p*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all disp loads (PQ) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'which', 'DISPATCHABLE', 'cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd-total.fixed.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), (dmd-total.fixed.p)/total.disp.p*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), (dmd-total.fixed.p)/total.disp.p*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end),   orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all disp loads/costs (PQ) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'which', 'DISPATCHABLE');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd-total.fixed.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), (dmd-total.fixed.p)/total.disp.p*total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), (dmd-total.fixed.p)/total.disp.p*total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), (dmd-total.fixed.p)/total.disp.p*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all disp loads (P) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P', 'which', 'DISPATCHABLE', 'cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd-total.fixed.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end),   orig_gc(ld, COST:end), 8, [t 'gencost loads']);

t = 'all disp loads/costs (P) => total = 200 : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P', 'which', 'DISPATCHABLE');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
t_is(sum(bus(:, PD)), total.fixed.p, 8, [t 'total fixed P']);
t_is(sum(bus(:, QD)), total.fixed.q, 8, [t 'total fixed Q']);
t_is(-sum(gen(ld, PMIN)), dmd-total.fixed.p, 8, [t 'total disp P']);
t_is(-sum(gen(ld, QMIN)), total.disp.qmin, 8, [t 'total disp Qmin']);
t_is(-sum(gen(ld, QMAX)), total.disp.qmax, 8, [t 'total disp Qmax']);
t_is(gencost(gg, COST:end),   orig_gc(gg, COST:end), 8, [t 'gencost gens']);
t_is(gencost(ld, COST:end), (dmd-total.fixed.p)/total.disp.p*orig_gc(ld, COST:end), 8, [t 'gencost loads']);

%%-----  3 zones, area scale factors  -----
t = 'area fixed loads (PQ) * [3 2 1] : ';
dmd = [3 2 1];
opt = struct('which', 'FIXED', 'cost', 1);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), dmd(k)*area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'area fixed loads (P) * [3 2 1] : ';
dmd = [3 2 1];
opt = struct('pq', 'P', 'which', 'FIXED', 'cost', 1);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'all area loads (PQ) * [3 2 1] : ';
opt = struct('cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), dmd(k)*area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), dmd(k)*area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), dmd(k)*area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'all area loads/costs (PQ) * [3 2 1] : ';
mpc1 = scale_load(dmd, mpc);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), dmd(k)*area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), dmd(k)*area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), dmd(k)*area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), dmd(k)*orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'all area loads (P) * [3 2 1] : ';
opt = struct('pq', 'P', 'cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'all area loads/costs (P) * [3 2 1] : ';
opt = struct('pq', 'P');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), dmd(k)*orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'area disp loads (PQ) * [3 2 1] : ';
opt = struct('which', 'DISPATCHABLE', 'cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), dmd(k)*area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), dmd(k)*area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'area disp loads/costs (PQ) * [3 2 1] : ';
opt = struct('which', 'DISPATCHABLE');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), dmd(k)*area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), dmd(k)*area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), dmd(k)*orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'area disp loads (P) * [3 2 1] : ';
opt = struct('pq', 'P', 'which', 'DISPATCHABLE', 'cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'area disp loads/costs (P) * [3 2 1] : ';
opt = struct('pq', 'P', 'which', 'DISPATCHABLE');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), dmd(k)*orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

%%-----  3 zones, area scale quantities  -----
t = 'area fixed loads (PQ) => total = [100 80 60] : ';
dmd = [100 80 60];
opt = struct('scale', 'QUANTITY', 'which', 'FIXED');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)-area(k).disp.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), (dmd(k)-area(k).disp.p)/area(k).fixed.p*area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'area fixed loads (P) => total = [100 80 60] : ';
dmd = [100 80 60];
opt = struct('scale', 'QUANTITY', 'pq', 'P', 'which', 'FIXED', 'cost', 1);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)-area(k).disp.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'all area loads (PQ) => total = [100 80 60] : ';
opt = struct('scale', 'QUANTITY', 'cost', 0);
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)/area(k).both.p*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), dmd(k)/area(k).both.p*area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)/area(k).both.p*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), dmd(k)/area(k).both.p*area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), dmd(k)/area(k).both.p*area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'all area loads/costs (P) => total = [100 80 60] : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), dmd(k)/area(k).both.p*area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)/area(k).both.p*area(k).disp.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    t_is(gencost(lda{k}, COST:end), dmd(k)/area(k).both.p*orig_gc(lda{k}, COST:end), 8, sprintf('%s area %d gencost loads', t, k));
end
t_is(gencost(gg, COST:end), orig_gc(gg, COST:end), 8, sprintf('%s gencost gens', t));

t = 'area disp loads (PQ) => total = [100 80 60] : throws expected exception';
dmd = [100 80 60];
opt = struct('scale', 'QUANTITY', 'which', 'DISPATCHABLE');
err = 0;
try
    mpc1 = scale_load(dmd, mpc, [], opt);
catch
    [msg, id] = lasterr;
    expected = 'scale_load: impossible to make zone 2 load equal 80 by scaling non-existent dispatchable load';
    if ~isempty(strfind(msg, expected))
        err = 1;
    end
end
t_ok(err, t);

t = 'area disp loads (PQ) => total = [100 74.3941 60] : ';
dmd = [100 area(2).fixed.p 60];
opt = struct('scale', 'QUANTITY', 'which', 'DISPATCHABLE');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)-area(k).fixed.p, 8, sprintf('%s area %d disp P', t, k));
    if k == 2
        t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
        t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    else
        t_is(-sum(gen(lda{k}, QMIN)), (dmd(k)-area(k).fixed.p)/area(k).disp.p*area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
        t_is(-sum(gen(lda{k}, QMAX)), (dmd(k)-area(k).fixed.p)/area(k).disp.p*area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
    end
end

t = 'area disp loads (P) => total = [100 74.3941 60] : ';
opt = struct('scale', 'QUANTITY', 'pq', 'P', 'which', 'DISPATCHABLE');
mpc1 = scale_load(dmd, mpc, [], opt);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
for k = 1:length(dmd)
    t_is(sum(bus(a{k}, PD)), area(k).fixed.p, 8, sprintf('%s area %d fixed P', t, k));
    t_is(sum(bus(a{k}, QD)), area(k).fixed.q, 8, sprintf('%s area %d fixed Q', t, k));
    t_is(-sum(gen(lda{k}, PMIN)), dmd(k)-area(k).fixed.p, 8, sprintf('%s area %d disp P', t, k));
    t_is(-sum(gen(lda{k}, QMIN)), area(k).disp.qmin, 8, sprintf('%s area %d disp Qmin', t, k));
    t_is(-sum(gen(lda{k}, QMAX)), area(k).disp.qmax, 8, sprintf('%s area %d disp Qmax', t, k));
end

%%-----  explict single load zone  -----
t = 'explicit single load zone';
load_zone = zeros(1, size(mpc.bus, 1));
load_zone([3 4]) = 1;
dmd = 2;
mpc1 = scale_load(dmd, mpc, load_zone);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
Pd = mpc.bus(:, PD);
Pd([3 4]) = dmd * Pd([3 4]);
t_is( bus(:, PD), Pd, 8, t);

%%-----  explict multiple load zone  -----
t = 'explicit multiple load zone';
load_zone = zeros(1, size(mpc.bus, 1));
load_zone([3 4]) = 1;
load_zone([7 8]) = 2;
dmd = [2 0.5];
mpc1 = scale_load(dmd, mpc, load_zone);
[bus, gen, gencost] = deal(mpc1.bus, mpc1.gen, mpc1.gencost);
Pd = mpc.bus(:, PD);
Pd([3 4]) = dmd(1) * Pd([3 4]);
Pd([7 8]) = dmd(2) * Pd([7 8]);
t_is( bus(:, PD), Pd, 8, t);

t_end;


pointcolor=[rand rand rand];
figure
for count=1:size(AGS,2)
    plot(count,AGS(1,count),'o','MarkerSize',2.5,'MarkerEdgeColor',[pointcolor(1,1) pointcolor(1,2) pointcolor(1,3)],...
        'MarkerFaceColor',[pointcolor(1,1) pointcolor(1,2) pointcolor(1,3)]);axis square;box on;grid on;hold on
end
title('Average Grain Size Vs. MCS')
xlabel('Monte - Carlo Steps')
ylabel('Unit Normalized Average Grain Size')
pause(0.5)

github-repos/MATLAB/Sable-mcbench-benchmarks/mcbench-benchmarks-ba13b2f0296ef49491b95e3f984c7c41fccdb6d8/34784-monte-carlo-simulation-of-two-dimensional-grain-growth-code-version-no-1-basic/Monte Carlo Simulation Q-state Potts model 2D square-lattice - microstructure/PlotAverageGrainSize_2D_QPOTTS.m


function h=m_patch(long,lat,C,varargin)
% M_PATCH Create patches on a map
%    M_PATCH(LONG,LAT,C) is a drop-in replacement for PATCH that uses
%    longitude/latitude coordinates to draw a patch on the current map.
%    See PATCH for more details about the way in which patch colours and
%    properties should be specified.
%
%    Currently you cannot specify C to be other than a string or 1x3 RGB
%    vector.
%
%    See also M_LINE, M_LL2XY

% Rich Pawlowicz (rich@ocgy.ubc.ca) 3/Sep/98
%
% This software is provided "as is" without warranty of any kind. But
% it's mine, so you can't sell it.

%  10/Mar/99 - changed order of calls ('c' not handled correctly in mu_coast otherwise)
% 6/Nov/00 - eliminate returned stuff if ';' neglected (thx to D Byrne)

[m,n]=size(long);

if m==1 && n>1
  h=mu_coast('vector',[long' lat';long(1) lat(1)],'patch',C,'tag','m_patch',varargin{:});
elseif m>1 && n==1
  h=mu_coast('vector',[long lat;long(1) lat(1)],'patch',C,'tag','m_patch',varargin{:});
else
  h=mu_coast('vector',[reshape([long;long(1,:);NaN+ones(1,n)],(m+2)*n,1),...
                     reshape([lat;lat(1,:);NaN+ones(1,n)],(m+2)*n,1)],'patch',C,'tag','m_patch',varargin{:});
end

if nargout==0
 clear h
end


function rgbVector = str2rgb(colorString)
%STR2RGB   Converts a string representation of a color to an RGB triple.
%   X = STR2RGB(STR) converts the string STR into a three-element row
%   vector X (an RGB triple). STR can be one of three string
%   representations of colors that MATLAB uses (see ColorSpec help): a full
%   color name ('yellow'), a single character ('y'), or a string of numbers
%   within the range of 0 and 1 ('[1 1 0]' or '1 1 0').
%
%   If the string STR does not represent a valid string representation of a
%   color, STR2RGB(STR) returns NaN.
%
%   NOTE: STR2RGB does not use eval.
%
%   Examples:
%      str2rgb('yellow')        returns [1 1 0]
%      str2rgb('y')             returns [1 1 0]
%      str2rgb('[1 1 0]')       returns [1 1 0]
%      str2rgb('1 1 0')         returns [1 1 0]
%      str2rgb('[1; 1; 0]')     returns [1 1 0]
%      str2rgb('[0 0.5 0.91]')  returns [0 0.5000 0.9100]
%      str2rgb('purple')        returns NaN
%      str2rgb('[1 2]')         returns NaN

% Author: Ken Eaton
% Last modified: 4/2/08
%--------------------------------------------------------------------------

  if (nargin == 0),
    error('str2rgb:notEnoughInputs','Not enough input arguments.');
  end
  if (~ischar(colorString)),
    error('str2rgb:badArgumentType',...
          'Input argument should be of type char.');
  end
  expression = {'^\s*yellow\s*$','^\s*magenta\s*$','^\s*cyan\s*$',...
                '^\s*red\s*$','^\s*green\s*$','^\s*blue\s*$',...
                '^\s*white\s*$','^\s*black\s*$','^\s*y\s*$','^\s*m\s*$',...
                '^\s*c\s*$','^\s*r\s*$','^\s*g\s*$','^\s*b\s*$',...
                '^\s*w\s*$','^\s*k\s*$','[\[\]\;\,]'};
  replace = {'[1 1 0]','[1 0 1]','[0 1 1]','[1 0 0]','[0 1 0]',...
             '[0 0 1]','[1 1 1]','[0 0 0]','[1 1 0]','[1 0 1]',...
             '[0 1 1]','[1 0 0]','[0 1 0]','[0 0 1]','[1 1 1]',...
             '[0 0 0]',' '};
  rgbVector = sscanf(regexprep(colorString,expression,replace),'%f').';
  if ((numel(rgbVector) ~= 3) || any((rgbVector < 0) | (rgbVector > 1))),
    rgbVector = nan;
  end

end


function [catdim] = checkinput(x)

if ~iscell(x)
  error('input should be a cell-array');
end

siz    = size2(x, [], 'cell');
ndim   = size(siz, 2);

if ndim>2
  error('number of dimensions within a cell > 2 is currently not supported');
end

if length(x)<numel(x)
  error('currently only a 1xN or Nx1 cell-array is supported in the input');
end

same   = false(1,ndim);
for k = 1:ndim
  same(k) = all(siz(1,k)==siz(:,k));
end

if sum(same)==1
  % data need to be concatenated across the other dimension
  catdim = ~same;
elseif sum(same)==0
  % data cannot be concatenated across any of the dimensions
  error('the cells in the input array cannot be concatenated across any of the dimensions in the cells');
elseif sum(same)>1
  % more than one possibility
  catdim = same;
end


function [c, ceq] = ma_OutboundHyperVelVectConstraint(stateLog, eventID, lb, ub, bodyIDApply, celBodyData, maData, constType)
%ma_OutboundHyperVelVectConstraint Summary of this function goes here
%   Detailed explanation goes here
    if(ischar(eventID) && strcmpi(eventID,'final'))
        eventNum = max(stateLog(:,13));
    else
        [~, eventNum] = getEventByID(eventID, maData.script);
    end

    eventLog = stateLog(stateLog(:,13)==eventNum,:);

    bodyEventLog = eventLog(eventLog(:,8)==bodyIDApply,:);
    if(isempty(bodyEventLog))
        finalEntry = eventLog(end,:);
    else
        finalEntry = bodyEventLog(end,:);
    end

    bodyID = finalEntry(8);
    if(bodyID == bodyIDApply || bodyIDApply==-1)
        bodyInfo = getBodyInfoByNumber(bodyID, celBodyData);
        gmu = bodyInfo.gm;
        rVect = finalEntry(2:4)';
        vVect = finalEntry(5:7)';

        [sma, ecc, inc, raan, arg, tru] = getKeplerFromState(rVect,vVect,gmu);
        if(ecc > 1)
            [~, OUnitVector] = computeHyperSVectOVect(sma, ecc, inc, raan, arg, tru, gmu);

            switch constType
                case 'x'
                    vComp = OUnitVector(1);
                case 'y'
                    vComp = OUnitVector(2);
                case 'z'
                    vComp = OUnitVector(3);
                case 'mag'
                    vComp = sqrt(-gmu/sma); %from vis-viva equation; not actually a vector component but wanted to shoe-horn it in here
            end

            if(lb == ub)
                c = [0 0];
                ceq(1) = vComp - ub;
            else
                c(1) = lb - vComp;
                c(2) = vComp - ub;
                ceq = [0]; %#ok<NBRAK>
            end
        else
            c = [0 0];
            ceq = [0]; %#ok<NBRAK>
        end
    else
        c = [0 0];
        ceq = [0]; %#ok<NBRAK>
    end
end


classdef InstanceSegRegLoss < dagnn.Loss
    properties (Transient)
        curSimMat
        weightMat
        mass_
        size_
    end

    methods
        function outputs = forward(obj, inputs, params)
            [h, w, ch, bs] = size(inputs{1});
            sz = [h, w, ch, bs];
            mass = sz(1) * sz(2) + 1;

            obj.size_ = sz;
            obj.mass_ = mass;

            gpuMode = isa(inputs{1}, 'gpuArray');
            if gpuMode
                obj.curSimMat = gpuArray(zeros(sz, 'single'));
                obj.weightMat = gpuArray(zeros(sz, 'single'));
            else
                obj.curSimMat = zeros(sz, 'single');
                obj.weightMat = zeros(sz, 'single');
            end

            for j = 1:sz(4)
                C = inputs{2}(:,:,:,j);
                W = C;
                for ii = 0:4
                    W(W==ii) = sum(C(:)==ii);
                end
                W = W(:)*W(:)';
                W = 1 ./ W;
                W = W ./ sum(W(:));

                C = reshape(C, [sz(1), 1]);
                C = repmat(C, 1, sz(2));
                C = (C==C');
                obj.curSimMat(:,:,:,j) = C;
                obj.weightMat(:,:,:,j) = W;
            end

            outputs{1} = vl_nnloss(inputs{1}, obj.curSimMat, [], ...
                'loss', obj.loss, ...
                'instanceWeights', obj.weightMat) ;% 1./mass
            n = obj.numAveraged ;
            m = n + size(inputs{1},4) ;
            obj.average = (n * obj.average + double(gather(outputs{1}))) / m ;
            obj.numAveraged = m ;
        end

        function [derInputs, derParams] = backward(obj, inputs, params, derOutputs)
            sz = obj.size_;
            mass = obj.mass_;

            gpuMode = isa(inputs{1}, 'gpuArray');
            if gpuMode
                grndLabel = gpuArray(zeros(sz, 'single'));
            else
                grndLabel = zeros(sz, 'single');
            end
            grndLabel = obj.curSimMat;

            derInputs{1} = vl_nnloss(inputs{1}, obj.curSimMat, derOutputs{1}, ...
                'loss', obj.loss, ...
                'instanceWeights', obj.weightMat) ;% 1./mass
            derInputs{2} = [] ;
            derParams = {} ;
        end

        function obj = InstanceSegRegLoss(varargin)
            obj.load(varargin) ;
        end
    end
end


%% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald
%%
%% This file is part of OctSymPy.
%%
%% OctSymPy is free software; you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published
%% by the Free Software Foundation; either version 3 of the License,
%% or (at your option) any later version.
%%
%% This software is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty
%% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
%% the GNU General Public License for more details.
%%
%% You should have received a copy of the GNU General Public
%% License along with this software; see the file COPYING.
%% If not, see <http://www.gnu.org/licenses/>.

%% -*- texinfo -*-
%% @documentencoding UTF-8
%% @deftypemethod  @@sym {} latex (@var{x})
%% @deftypemethodx @@sym {@var{s} =} latex (@var{x})
%% Display or return LaTeX typesetting code for symbolic expression.
%%
%% Example:
%% @example
%% @group
%% syms x
%% latex(sin(x/2))
%%   @print{} \sin@{\left(\frac@{x@}@{2@} \right)@}
%% @end group
%%
%% @group
%% A = [sym(1) 2; sym(3) 4];
%% s = latex(A)
%%   @result{} s = \left[\begin@{matrix@}1 & 2\\3 & 4\end@{matrix@}\right]
%% @end group
%% @end example
%%
%% @seealso{@@sym/disp, @@sym/pretty}
%% @end deftypemethod

function varargout = latex(x)

  if (nargin ~= 1)
    print_usage ();
  end

  cmd = { 'return sp.latex(*_ins),' };

  s = pycall_sympy__ (cmd, x);

  if (nargout == 0)
    disp(s)
  else
    varargout = {s};
  end

end

%!test
%! syms x
%! y = sin(x);
%! assert (strcmp (latex (y), '\sin{\left(x \right)}'))

%!assert (strcmp (latex (exp (sym('x'))), 'e^{x}'))


function RegMISimilarity(handles, metric)
%
% Copyright 2010, Joseph O. Deasy, on behalf of the CERR development team.
%
% This file is part of The Computational Environment for Radiotherapy Research (CERR).
%
% CERR development has been led by:  Aditya Apte, Divya Khullar, James Alaly, and Joseph O. Deasy.
%
% CERR has been financially supported by the US National Institutes of Health under multiple grants.
%
% CERR is distributed under the terms of the Lesser GNU Public License.
%
%     This version of CERR is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
%
% CERR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
% without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% See the GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with CERR.  If not, see <http://www.gnu.org/licenses/>.

global planC stateS;
indexS = planC{end};

    [originF, spacingF, centerF] = getScanOriginSpacing(planC{indexS.scan}(stateS.imageRegistrationBaseDataset));

    [originM, spacingM, centerM] = getScanOriginSpacing(planC{indexS.scan}(stateS.imageRegistrationMovDataset));

    Bins = str2double(get(handles.mattes_bins, 'string'));
    Samples = str2double(get(handles.mattes_samples, 'string'));
    RelaxFactor = str2double(get(handles.mattes_rf, 'string'));
    DefaultPixelValue = str2double(get(handles.mattes_pv, 'string'));
    Iter_MinStep = str2double(get(handles.mattes_minstep, 'string'));
    Iter_MaxStep = str2double(get(handles.mattes_maxstep, 'string'));
    Iter_Num = str2double(get(handles.mattes_inum, 'string'));

    tscale = str2double(get(handles.mattes_tscale, 'string'));
    rscale = str2double(get(handles.mattes_rscale, 'string'));
    scaleFactor = str2double(get(handles.mattes_scalefactor, 'string'));

    output = cell(1, 16);

    FImg = planC{indexS.scan}(stateS.imageRegistrationBaseDataset).scanArray;
    MImg = planC{indexS.scan}(stateS.imageRegistrationMovDataset).scanArray;

    dimF = size(FImg);
    dimM = size(MImg);
    %generate cliped base dataset
    clipBox = uint16(getappdata(stateS.handle.CERRSliceViewer, 'clipBox_baseTrans'));
    if ~isempty(clipBox)
        FImg = FImg(clipBox(2):clipBox(4), clipBox(1):clipBox(3), :);
        originF(1) = originF(1) + spacingF(1)*double(clipBox(1)-1);
        originF(2) = originF(2) + spacingF(2)*double(uint16(dimF(1)-clipBox(4)));
    end
    clipBox = uint16(getappdata(stateS.handle.CERRSliceViewer, 'clipBox_baseSag'));
    if ~isempty(clipBox)
        FImg = FImg(:, :, clipBox(2):clipBox(4));
        originF(3) = originF(3) + spacingF(3)*double(clipBox(2)-1);
    end

    %generate cliped move dataset
    clipBox = uint16(getappdata(stateS.handle.CERRSliceViewer, 'clipBox_movTrans'));
    if ~isempty(clipBox)
        MImg = MImg(clipBox(2):clipBox(4), clipBox(1):clipBox(3), :);
        originM(1) = originM(1) + spacingM(1)*double(clipBox(1)-1);
        originM(2) = originM(2) + spacingM(2)*double(uint16(dimM(1)-clipBox(4)));
    end
    clipBox = uint16(getappdata(stateS.handle.CERRSliceViewer, 'clipBox_movSag'));
    if ~isempty(clipBox)
        MImg = MImg(:, :, clipBox(2):clipBox(4));
        originM(3) = originM(3) + spacingM(3)*double(clipBox(2)-1);
    end

%downsample the input datasets
    dsampled = 0;
    if (get(handles.dsampleCheck,'Value') == get(handles.dsampleCheck,'Max'))

        tic;
        xyScale =  2; zScale = 2;
        spacingF = [spacingF(1)*xyScale spacingF(2)*xyScale spacingF(3)*zScale];
        spacingM = [spacingM(1)*xyScale spacingM(2)*xyScale spacingM(3)*zScale];
        disp('downSampling ...');
%         FImg = imdesample3d(FImg,xyScale,zScale);
%         MImg = imdesample3d(MImg,xyScale,zScale);
%         FImg=GPReduce2D(FImg,1);
%         MImg=GPReduce2(MImg,1);
        FImg = FImg(1:xyScale:end, 1:xyScale:end, 1:zScale:end);
        MImg = MImg(1:xyScale:end, 1:xyScale:end, 1:zScale:end);

        toc;
        dsampled = 1;
    end

    tic;

%flip the source datasets on X for itk coordinate system
    fdim = 1;
    FImg = flipdim(FImg, fdim);
    MImg = flipdim(MImg, fdim);

% transform initializing modes 1:MomentON 0:GeometryOn 2:initail transform On
    initMode = get(handles.InitTrans, 'value');

%prepare the initial transform matrix
    transMB = planC{indexS.scan}(stateS.imageRegistrationBaseDataset).transM;
    transMM = planC{indexS.scan}(stateS.imageRegistrationMovDataset).transM;
    if isempty(transMM), transMM = eye(4); end;
    if isempty(transMB), transMB = eye(4); end;
    transM = inv(transMB) * transMM;

%flip the moving dataset to match the initial transM
    Tf = eye(4);
    flipM = 0;
    if (get(handles.flipX, 'value'))
        MImg = flipdim(MImg, 2);
        Tf = [-1 0 0 2*centerM(1); 0 1 0 0; 0 0 1 0; 0 0 0 1];
        flipM = 2;
    end
    if (get(handles.flipY, 'value'))
        MImg = flipdim(MImg, 1);
        Tf = [1 0 0 0; 0 -1 0 2*centerM(2); 0 0 1 0; 0 0 0 1];
        flipM = 1;
    end
    if (get(handles.flipZ, 'value'))
        MImg = flipdim(MImg, 3);
        Tf = [1 0 0 0; 0 1 0 0; 0 0 -1 2*centerM(3); 0 0 0 1];
        flipM = 3;
    end
    transM = transM * inv(Tf);
    rotM = transM(1:3, 1:3); transV = transM(1:3, 4);
    rotM = rotM';
    transV = -transV;

%call registration method
    switch metric
        case 'mutual information'
            metricIndex = 0;

            try
                try
                [im, Rotation, Offset] = Mattes_MI3D32_2006a(int16(FImg), originF, spacingF, ...
                                         int16(MImg), originM, spacingM, ...
                                         Bins, Samples, RelaxFactor, DefaultPixelValue, ...
                                         Iter_MinStep, Iter_MaxStep, Iter_Num, tscale, rscale, scaleFactor, ...
                                         rotM, transV, initMode);
                catch
                [im, Rotation, Offset] = Mattes_MI3D32_2006b(int16(FImg), originF, spacingF, ...
                                         int16(MImg), originM, spacingM, ...
                                         Bins, Samples, RelaxFactor, DefaultPixelValue, ...
                                         Iter_MinStep, Iter_MaxStep, Iter_Num, tscale, rscale, scaleFactor, ...
                                         rotM, transV, initMode);
                end
            catch
                try
                    [im, Rotation, Offset] = Mattes_MI3D6406b(uint16(FImg), originF, spacingF, ...
                                         int16(MImg), originM, spacingM, ...
                                         Bins, Samples, RelaxFactor, DefaultPixelValue, ...
                                         Iter_MinStep, Iter_MaxStep, Iter_Num, tscale, rscale, scaleFactor, ...
                                         rotM, transV, initMode);
                catch
                    try
                        [im, Rotation, Offset] = Mattes_MI3D6406a(uint16(FImg), originF, spacingF, ...
                                         int16(MImg), originM, spacingM, ...
                                         Bins, Samples, RelaxFactor, DefaultPixelValue, ...
                                         Iter_MinStep, Iter_MaxStep, Iter_Num, tscale, rscale, scaleFactor, ...
                                         rotM, transV, initMode);
                    catch
                        [im, Rotation, Offset] = Mattes_MI3D_debug(uint16(FImg), originF, spacingF, ...
                                         int16(MImg), originM, spacingM, ...
                                         Bins, Samples, RelaxFactor, DefaultPixelValue, ...
                                         Iter_MinStep, Iter_MaxStep, Iter_Num, tscale, rscale, scaleFactor, ...
                                         rotM, transV, initMode);
                    end
                end
            end
        case 'viola well'
            metricIndex = 1;
    end
    im = flipdim(im, fdim);
%??     if (flipM), im = flipdim(im, flipM); end;

    toc;

    output{1} = ['Rotation Angle Z = ' num2str(asin(Rotation(1, 2))*45.0/atan(1.0))];
    output{2} = ['Translation X = ' num2str(Offset(1))];
    output{3} = ['Translation Y = ' num2str(Offset(2))];
    output{4} = ['Translation Z = ' num2str(Offset(3))];

    output{5} = ['Iterations    = ' num2str(Offset(4))];
    output{6} = ['Metric Value (MI) = ' num2str(Offset(5))];

    output{7} = ['Rotation Center X = ' num2str(Offset(6))];
    output{8} = ['Rotation Center Y = ' num2str(Offset(7))];
    output{9} = ['Rotation Center Z = ' num2str(Offset(8))];

    output{10} = ['Scale = ' num2str(Offset(9))];

    output{11} = ['Offset X = ' num2str(Offset(10))];
    output{12} = ['Offset Y = ' num2str(Offset(11))];
    output{13} = ['Offset Z = ' num2str(Offset(12))];

    set(handles.OutputList, 'string', output);

%update the transM;
    scale = Offset(9);
    Tv = [Offset(1) Offset(2) Offset(3)]; %input image is a flip of source along X direction.
    Cv = Offset(6:8);
    Cv(3) = -Cv(3); %CERR z axis is opposite to the ITK.

    rot = reshape(Rotation, 3,3);
    offset = Offset(10:12); %offset related to origin rotation;

%     rot(2,1) = -rot(2,1); rot(1,2) = -rot(1,2);
%     rot(1,3) = -rot(1,3); rot(3,1) = -rot(3,1);
%     rot(2,3) = -rot(2,3); rot(3,2) = -rot(3,2);

%     offset(1) = -offset(1);
%     offset(2) = -offset(2);
%     offset(3) = -offset(3);

    TM = eye(4);
    TM(:,4) = [offset 1];

    RM = eye(4);
    RM(1:3, 1:3) = rot;

    newTransform = inv(TM*RM);
    newTransform =  transMB * newTransform * Tf;

    scanSetM = stateS.imageRegistrationMovDataset;
    scanSetF = stateS.imageRegistrationBaseDataset;
    planC{indexS.(stateS.imageRegistrationMovDatasetType)}(scanSetM).transM = newTransform;

% save the resampled dataset
    if (get(handles.saveCheck, 'value'))
        if (~dsampled)
            planC{indexS.scan}(end+1) = planC{indexS.scan}(scanSetF);
            planC{indexS.scan}(end).scanArray = im;
            planC{indexS.scan}(end).scanUID = createUID('scan');
        else
            %imReg = resample(scanSetF, scanSetM); % need to up-sample im ????
            planC{indexS.scan}(end+1) = planC{indexS.scan}(scanSetF);
            planC{indexS.scan}(end).scanArray = imReg;
            planC{indexS.scan}(end).scanUID = createUID('scan');
        end
        controlFrame('refresh');
    end

    sliceCallBack('refresh');

end


function y = colsum(x)

y = sum(x,2);


function camAlignImageToDTI(dti_ref_filename,high_res_filename,output_filename,pixdim_tosave)
%
%   camAlignImageToDTI(dti_ref_filename,high_res_filename,output_filename,pixdim_tosave)
%
% EXAMPLE:
%           camAlignImageToDTI('b0.nii.gz','mask_t1.nii.gz','xformed_mask.nii.gz');
%
% (c) Stanford VISTA, 2010

% Experiment with xform
ni_src = niftiRead(high_res_filename);
ni_ref = niftiRead(dti_ref_filename);

ref_dim = ni_ref.dim(1:3);
ref_pixdim = ni_ref.pixdim(1:3);

% If no desired pixel size given, choose the source pixel size
if notDefined('pixdim_tosave')
    pixdim_tosave = ni_src.pixdim(1:3);
end

if pixdim_tosave ~= ni_src.pixdim(1:3)
    % Get bounding box to match the world space of the dti reference
    bound_box = mrAnatXformCoords(ni_ref.qto_xyz,[1 1 1;ref_dim]);
    % Must take into account the pixel size difference that slightly shifts the
    % origin and therefore we must shift the bounding box
    % also (see mrAnatResliceSpm)
    bound_box = bound_box + repmat(rem((pixdim_tosave - ref_pixdim)/2,ref_pixdim),2,1);

    % reslice
    [new_data xform] = mrAnatResliceSpm(ni_src.data, ni_src.qto_ijk, bound_box, pixdim_tosave, [0 0 0 0 0 0]);
else
    new_data = ni_src.data;
    xform = ni_src.qto_xyz;
end

% write
dtiWriteNiftiWrapper(new_data, xform, output_filename);

return


function [rtk,sat_,stat]=estpos(rtk,obs,nav,sv,opt)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%estimate reciever position and clock bias
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
global  glc
NX=3+glc.NSYS; MAXITER=10; iter=1;
time=obs(1).time; xr0=[rtk.sol.pos';zeros(glc.NSYS,1)];

while iter<=MAXITER

    % compute residual,measurement model,weight matrix
    [v,H,P,vsat,azel,resp,nv,ns]=rescode(iter,obs,nav,sv,xr0,opt);
    sat_.vsat=vsat;
    sat_.azel=azel;
    sat_.resp=resp;

    if nv<NX, stat=0;return;end

    % least square algrithm
    [dx,Q]=least_square(v,H,P);

    xr0=xr0+dx;
    iter=iter+1;

    if dot(dx,dx)<1e-4
        rtk.sol.time=timeadd(obs(1).time,-xr0(4)/glc.CLIGHT);
        rtk.sol.ns  =ns;
        rtk.sol.ratio=0;
        rtk.sol.pos =xr0(1:3)';
        rtk.sol.vel =zeros(1,3);
        rtk.sol.posP(1)=Q(1,1);rtk.sol.posP(2)=Q(2,2);rtk.sol.posP(3)=Q(3,3);
        rtk.sol.posP(4)=Q(1,2);rtk.sol.posP(5)=Q(2,3);rtk.sol.posP(6)=Q(1,3);
        rtk.sol.dtr(1) =xr0(4)/glc.CLIGHT;
        rtk.sol.dtr(2) =xr0(5)/glc.CLIGHT;
        rtk.sol.dtr(3) =xr0(6)/glc.CLIGHT;
        rtk.sol.dtr(4) =xr0(7)/glc.CLIGHT;
        rtk.sol.dtr(5) =xr0(8)/glc.CLIGHT;

        % validate solution
        stat=valsol(time,v,P,vsat,azel,opt);
        if stat==1
            rtk.sol.stat=glc.SOLQ_SPP; return;
        end
        return;
    end

end

if iter>MAXITER
    stat=0;
    [week,sow]=time2gpst(time);
    fprintf('Warning:GPS week = %d sow = %.3f,SPP iteration divergent!\n',week,sow);
    return;
end

return


% IS_VALID_STRUCT2 - Determine if the input structure is "valid"
%
%     IS_VALID_STRUCT2 determines whether or not the input
%     structure contains additional field data beyond the
%     minimum valid fields checked for by  IS_VALID_STRUCT.
%     Recall that a valid FEM_GRID_STRUCT contains (atleast)
%     the following (NOT EMPTY) fields:
%
%       .name,.e,.x,.y,.z,.bnd
%
%     IS_VALID_STRUCT2 verifies the existence of .A, .B, .A0,
%     and .T which are filled by BELINT, and of .ar filled by
%     EL_AREAS.  These additional FEM fields are needed by
%     OPNML/MATLAB element-finding, basis  and interpotion
%     routines.
%
% CALL: errflag=is_valid_struct2(fem_grid_struct)
%
% Written by : Brian O. Blanton
% Summer 1998
%
function errflag=is_valid_struct2(fem_grid_struct)

errflag=0;

% Make sure input argument is actually a structure
%
if ~isstruct(fem_grid_struct)
   disp('    Argument to IS_VALID_STRUCT2 must be a structure.');return
end

% now, make sure the structure contains the additional fields,
% as above
if ~isfield(fem_grid_struct,'A')
   disp('    "A" field not part of fem_grid_struct; run BELINT');return
elseif ~isfield(fem_grid_struct,'B')
   disp('    "B" field not part of fem_grid_struct; run BELINT');return
elseif ~isfield(fem_grid_struct,'A0')
   disp('    "A0" field not part of fem_grid_struct; run BELINT');return
elseif ~isfield(fem_grid_struct,'T')
   disp('    "T" field not part of fem_grid_struct; run BELINT');return
elseif ~isfield(fem_grid_struct,'ar')
   disp('    "ar" field not part of fem_grid_struct; run ');return
end

% now, make sure these additional fields are NOT EMPTY
%
if isempty(fem_grid_struct.A)
   disp('    "A" field in fem_grid_struct is EMPTY');return
elseif isempty(fem_grid_struct.B)
   disp('    "B" field in fem_grid_struct is EMPTY');return
elseif isempty(fem_grid_struct.A0)
   disp('    "A0" field in fem_grid_struct is EMPTY');return
elseif isempty(fem_grid_struct.T)
   disp('    "T" field in fem_grid_struct is EMPTY');return
elseif isempty(fem_grid_struct.ar)
   disp('    "ar" field in fem_grid_struct is EMPTY');return
end

errflag=1;

%
%        Brian O. Blanton
%        Curr. in Marine Science
%        15-1A Venable Hall
%        CB# 3300
%        Uni. of North Carolina
%        Chapel Hill, NC
%                 27599-3300
%
%        919-962-4466
%        blanton@marine.unc.edu
%
%        Summer 1998


subjectDir = '/biac2/wandell2/data/reading_longitude/templates/child_new/SIRL54warp3';
fileFragment = '*sn*';
[s,subCode] = findSubjects(subjectDir,fileFragment,{'tk040817'});
N = length(s);
tdir = '/silver/scr1/data/templates/child_new';
tname = 'SIRL54';
avgdir = fullfile(tdir,[tname 'warp3']);
template = load(fullfile(avgdir,'average_dt6'));
xformDtToAcpc = template.xformToAcPc;
dtMmPerVox = template.mmPerVox;
avgBrain = template.anat.img;
avgBrain(template.anat.brainMask<0.25) = 0;
avgBrain(template.anat.brainMask<0.5) = avgBrain(template.anat.brainMask<0.5)*.5;
outDir = '/silver/scr1/readingGroupStats/';
if(~exist(outDir,'dir')) mkdir(outDir); end

[behData,colNames] = dtiGetBehavioralData(subCode);
readerType = strmatch('Type of Reader',colNames);
pr = find(behData(:,readerType)==-1);
gr = find(behData(:,readerType)==1);
npr = length(pr);
ngr = length(gr);

dt = load(s{pr(1)});
prDt6 = zeros([size(dt.dt6) npr]);
prDt6(:,:,:,:,1) = dt.dt6;
mnB0 =  double(dt.b0);
for(ii=2:npr)
  disp(['Loading ' s{pr(ii)} '...']);
  dt = load(s{pr(ii)});
  dt.dt6(isnan(dt.dt6)) = 0;
  prDt6(:,:,:,:,ii) = dt.dt6;
  mnB0 = mnB0 + double(dt.b0);
end
grDt6 = zeros([size(dt.dt6) ngr]);
for(ii=1:ngr)
  disp(['Loading ' s{gr(ii)} '...']);
  dt = load(s{gr(ii)});
  dt.dt6(isnan(dt.dt6)) = 0;
  grDt6(:,:,:,:,ii) = dt.dt6;
  mnB0 = mnB0 + double(dt.b0);
end
mnB0 = mnB0./(npr+ngr);
mask = mnB0>250 & all(squeeze(prDt6(:,:,:,1,:)),4)>0 & all(squeeze(grDt6(:,:,:,1,:)),4)>0;
prDt6_ind = dtiImgToInd(prDt6, mask);
clear prDt6;
grDt6_ind = dtiImgToInd(grDt6, mask);
clear grDt6;
% convert to log tensors
[prVec, prVal] = dtiEig(prDt6_ind);
prVal(prVal<0) = 0;
prLogDt6_ind = dtiEigComp(prVec, log(prVal));
[grVec, grVal] = dtiEig(grDt6_ind);
grVal(grVal<0) = 0;
grLogDt6_ind = dtiEigComp(grVec, log(grVal));

showSlices = [20:60];

% Watson test for principal eigenvector difference
[prDir.mean, prDir.stdev, prDir.n, prDir.sbar] = dtiDirMean(squeeze(prVec(:,:,1,:)));
[grDir.mean, grDir.stdev, grDir.n, grDir.sbar] = dtiDirMean(squeeze(grVec(:,:,1,:)));
[T, DISTR, df] = dtiDirTest(prDir.sbar, prDir.n, grDir.sbar, grDir.n);
Timg = dtiIndToImg(T, mask);
fThresh = finv(1-10^-4, df(1), df(2));
fMax = finv(1-10^-12, df(1), df(2));
Timg(Timg>fMax) = fMax;
fMax = max(Timg(:));
figure; imagesc(makeMontage(Timg,showSlices)); axis image; colormap hot; colorbar;
set(gcf,'Name','Dir test'); title(sprintf('fthresh (p<10^-^4) = %0.1f',fThresh));
dtiWriteNiftiWrapper(Timg, xformDtToAcpc, fullfile(outDir,['dir_' DISTR '-test_' num2str(df(1)) ',' num2str(df(2)) 'df.nii.gz']));

% Simple FDR analysis for Watson test
%
fdrVal = 0.10; fdrType = 'original';
T(isnan(T)) = 0;
pvals = 1-fcdf(T, df(1), df(2));
[n_signif,index_signif] = fdr(pvals,fdrVal,fdrType,'mean');
pThreshFDR = max(pvals(index_signif));
% Convert back to an fThreshold
fThreshFDR = finv(1-pThreshFDR, df(1), df(2));
disp(sprintf('f-threshold for FDR (%s method) of %0.3f: %0.2f (%0.3f).\n',...
             fdrType,fdrVal,fThreshFDR,fThreshFDR/fMax));
logPimg = dtiIndToImg(-log10(pvals), mask);
cmap = autumn(256);
maxLogP = 10;
%minLogP = -log10(pThreshFDR);
minLogP = -log10(0.01);
sl = [-20:2:50];

mrAnatOverlayMontage(logPimg, xformDtToAcpc, avgBrain, template.anat.mmPerVox, cmap, [minLogP maxLogP], sl);

% Log-normal tensor tests
%
% Test for eigenvector differences
[prLogDt.mean, prLogDt.stdev, prLogDt.n] = dtiLogTensorMean(prLogDt6_ind);
[grLogDt.mean, grLogDt.stdev, grLogDt.n] = dtiLogTensorMean(grLogDt6_ind);

[T, DISTR, df] = dtiLogTensorTest('vec', prLogDt.mean, prLogDt.stdev, prLogDt.n, grLogDt.mean, grLogDt.stdev, grLogDt.n);

Timg = dtiIndToImg(T, mask);
fThresh = finv(1-10^-4, df(1), df(2));
fMax = finv(1-10^-12, df(1), df(2));
Timg(Timg>fMax) = fMax;
dtiWriteNiftiWrapper(Timg, xformDtToAcpc, fullfile(outDir,['vec_' DISTR '-test_' num2str(df(1)) ',' num2str(df(2)) 'df.nii.gz']));

% Sqrt(F) is the standardized distance between the groups.
%figure; imagesc(makeMontage(sqrt(Timg),[20:55])); axis image; colormap hot; colorbar;
%set(gcf,'Name','Vec Standardized Distance');

% Simple FDR analysis for eigenvector differences
%
fdrVal = 0.05; fdrType = 'original';
T(isnan(T)) = 0;
pvals = 1-fcdf(T, df(1), df(2));
[n_signif,index_signif] = fdr(pvals,fdrVal,fdrType,'mean');
%pThreshFDR = max(pvals(index_signif));
% Convert back to an fThreshold
%fThreshFDR = finv(1-pThreshFDR, df(1), df(2));
%disp(sprintf('f-threshold for FDR (%s method) of %0.3f: %0.2f (%0.3f).\n',...
%             fdrType,fdrVal,fThreshFDR,fThreshFDR/fMax));

logPimg = dtiIndToImg(-log10(pvals), mask);
cmap = autumn(256);
maxLogP = 10;
%minLogP = -log10(pThreshFDR);
minLogP = -log10(0.01);
mrAnatOverlayMontage(logPimg, xformDtToAcpc, avgBrain, template.anat.mmPerVox, cmap, [minLogP maxLogP], sl);

% Test for eigenvalue differences
%
[T, DISTR, df] = dtiLogTensorTest('val', prLogDt.mean, prLogDt.stdev, prLogDt.n, grLogDt.mean, grLogDt.stdev, grLogDt.n);

T(isnan(T)) = 0;
pvals = 1-fcdf(T, df(1), df(2));
[n_signif,index_signif] = fdr(pvals,fdrVal,fdrType,'mean');
pThreshFDR = max(pvals(index_signif));
% Convert back to an fThreshold
fThreshFDR = finv(1-pThreshFDR, df(1), df(2));
disp(sprintf('f-threshold for FDR (%s method) of %0.3f: %0.2f (%0.3f).\n',...
             fdrType,fdrVal,fThreshFDR,fThreshFDR/fMax));
Timg = dtiIndToImg(T, mask);
fMax = finv(1-10^-12, df(1), df(2));
Timg(Timg>fMax) = fMax;
dtiWriteNiftiWrapper(Timg, xformDtToAcpc, fullfile(outDir,['val_' DISTR '-test_' num2str(df(1)) ',' num2str(df(2)) 'df.nii.gz']));
logPimg = dtiIndToImg(-log10(pvals), mask);
cmap = autumn(256);
maxLogP = 10;
minLogP = -log10(pThreshFDR);
%minLogP = -log10(0.001);
mrAnatOverlayMontage(logPimg, xformDtToAcpc, avgBrain, template.anat.mmPerVox, cmap, [minLogP maxLogP], sl);


% Copyright 2019 Jonas Koenemann, Moritz Diehl, University of Freiburg
% Redistribution is permitted under the 3-Clause BSD License terms. Please
% ensure the above copyright notice is visible in any derived work.
%
classdef Matrix < ocl.types.Structure
  %OCLMATRIX Matrix valued structure for variables
  %
  properties
    msize
  end

  methods

    function self = Matrix(size)
      % ocl.types.Matrix(size)
      self.msize = size;
      self.len = prod(size);
    end
    function [N,M] = size(self)
      s = self.msize;
      if nargout>1
        N = s(1);
        M = s(2);
      else
        N = s;
      end
    end
  end
end


function P = adjustPsfSize(P)
%
%      P = adjustPsfSize(P);
%
%  If the size of a PSF is small compared to the dimensions of
%  the image, then our matrix vector multiply functions will be
%  inefficient due to our overlap add and overlap save approach.
%  Therefore, we make the minimum PSF size to be 32.
%
%  Input:  P - psf object
%  Output: P - psf object
%

%  J. Nagy 1/12/02

I = P.image;
center = P.center;

for k = 1:size(I,3)
  for j = 1:size(I,2)
    for i = 1:size(I,1)
      if length(I{i,j,k}) < 32
        I1 = zeros(32*ones(1,length(size(I{i,j,k}))));
        I1(1:size(I{i,j,k},1), 1:size(I{i,j,k},2), 1:size(I{i,j,k},3)) = I{i,j,k};
        I{i,j,k} = I1;
      end
    end
  end
end
P = psf(I, center);


%This function develop by Renoald Tang
%University Teknologi Malaysia, Photogrammetry and Laser scanning group
%for academic purpose
%Email:renoald@live.com
%This function read Off file
function readOFF(file)
[np,nf]=value(file);
fprintf('Number_of_point:%d\n',np);
fprintf('Number_of_face:%d\n',nf);
ext(file,np);

%return number of face and point
function [np,nf]=value(file)
C=0;
fid=fopen(file);
while 1
    tline = fgetl(fid);
    C=C+1;
    if C==2

      num=textscan(tline,'%d %d %d');
        break;
    end
    if ~ischar(tline),   break,   end

end
fclose(fid);
np=num{1,1};
nf=num{1,2};
function ext(file,n)
C=0;
K=0;
fid=fopen(file);
fid1=fopen('point','w');
fid2=fopen('face','w');
while 1
    tline=fgetl(fid);
    C=C+1;
     if ~ischar(tline) , break , end
    if C > 2
       K=K+1;
       if K <=n
           fprintf(fid1,'%s\n',tline);
       else
           fprintf(fid2,'%s\n',tline);
       end

    end

end
fclose(fid);
fclose(fid1);
fclose(fid2);%return and extract face and point value
%disp(K)