import math
import numpy as np
from scipy import interpolate
from .make_model2 import make_model2
from .goveqs_basis2 import goveqs_basis2
from .goveqs_scaleup import goveqs_scaleup
from .ode15s import ode15s
from .goveqs_basissmall import goveqs_basissmall
from .make_smallmodel import make_smallmodel
import collections.abc

#def get_objective(x, prm, ref, sel, agg, gps, gps1, gps2, calfn):
def get_objective(prm, ref, sel, agg, gps, gps1, gps2, calfn): # Signature changed on June 09, 2024, after Carel suggested that we stop passing xs
    
    r = prm['r']
    p = prm['p']
    i = ref['i']
    s = ref['s']
    xi = ref['xi']
  
    #%i0 = ref.i0; s0 = ref.s0; 
    i1 = ref['i1']; s1 = ref['s1']; i2 = ref['i2']; s2 = ref['s2']


    r['cs_1997'] = np.array(r['cs_1997'])
    r['cs_2022'] = np.array(r['cs_2022'])
    r['cs2_2022'] = np.array(r['cs2_2022'])
    r['cs2_1997'] = np.array(r['cs2_1997'])


    # First, check whether the proposed parameter ranges lie within the
    # specified ranges (i.e. implement the uniform priors - can also be done
    # after performing the simulations and alongside the likelihood, but this
    # way saves time, rejecting out-of-range parameters without needing to do
    # the simulations

    #mat = np.array([prm['bounds'][:len(x),1]-x, x-prm['bounds'][:len(x),0]])
    #mat = np.array([prm['bounds'][1,:]-x, x-prm['bounds'][0,:]])
    #The following line was commented out on June 09, 2024 because Carel suggested that we stop passing x to get_objective
    #mat = np.array([np.array(prm['bounds'])[1,range(len(x))]-x, x-np.array(prm['bounds'])[0,range(len(x))]]) #mat = [prm.bounds(2,1:length(x))-x; x-prm.bounds(1,1:length(x))];

    # All values should be positive if x is within the specified ranges

#if np.amin(mat)< 0:
#    
#    out = math.inf*calfn['sgn']
#    # +Inf if using sum of squares, -Inf if using likelihoods
#    aux = None
##     keyboard;
#else:
        
    # Note the use of the subfunction alloc_parameters, to keep things tidy
    # with the allocation of parameters
    #(r, p) = alloc_parameters(x,r,p,xi)
        
    # --- Set up the necessary models -------------------------------------
    #% Equilibrium model - no MDR, no HIV
    p0 = p.copy()
    r0 = r.copy()
        #p0['pu'] = 0
        #p0['rfbeta_mdr'] = 0 ;#p0['rfbeta_hiv'] = 0; #r0['MDR_acqu'] = 0
        #r0['ART_init'] = 0 #p0['MDR_rec'] = np.array([0,0])
        #
    p0['pu'] = 0 
    r0['cs']  = r['cs_1997'] #r0.cs  = r.cs_1997; 
    r0['cs2'] = r['cs2_1997'] #r0.cs2 = r.cs2_1997;
    p0['rfbeta_mdr'] = 0 #p0.rfbeta_mdr = 0; 
    r0['MDR_acqu'] = 0 #r0.MDR_acqu = 0;  
    p0['MDR_rec'] = np.array([0, 0]) #p0.MDR_rec = [0 0]; 
    p0['rfbeta_hiv'] = 0 #p0.rfbeta_hiv = 0; 
    r0['ART_init'] = 0 #r0.ART_init = 0; 
        #
        #Check where make_model2 is defined
    M0 = make_smallmodel(p0, r0, i1, s1, gps1,prm) #M0 = make_model(p0, r0, i, s, gps) #make_model2(p0, r0, i, s, gps)

        #% Introduction of MDR, no ART (1970-1997),
    p1 = p.copy(); r1 = r.copy()#p1 = p; r1 = r;
        #p1['pu'] = 0; r1['ART_init'] = 0; p1['MDR_rec'] = np.array([0, 0]) #p['MDR_rec2015'] #p1.pu = 0; r1.ART_init = 0; p1.MDR_rec = p.MDR_rec2015;
        
    p1['pu'] = 0; r1['cs']  = r['cs_1997']; r1['cs2'] = r['cs2_1997'] #p1.pu = 0; r1.cs  = r.cs_1997; r1.cs2 = r.cs2_1997;
    p1['MDR_rec'] = np.array([0, 0]) #p1.MDR_rec = [0 0];
    p1['rfbeta_hiv'] = 0; r1['ART_init'] = 0#p1.rfbeta_hiv = 0; r1.ART_init = 0;    % I guess HIV should introduce here i.e p1.rfbeta_hiv

    M1a = make_smallmodel(p1, r1, i2, s2, gps2,prm)   
    M1 = make_model2(p1, r1, i, s, gps,prm) #; % To transfer it into full matrix

        #% Start of RNTCP to start of ART  (prm.ART_start(here 2004 for India) (RNTCP scale up 1997 - 2007)
    p2 = p.copy(); r2 = r.copy()
        #r2['ART_init'] = 0; p2['MDR_rec'] = np.array([0, 0]); #%p.MDR_rec2015;  
    p2['pu'] = 0 + (p['pu_2022'] - 0)*((prm['ART_start']-1997)/25)#p2.pu = 0 + (p.pu_2022 - 0)*((prm.ART_start-1997)/25);  % Assuming linear scaleup from 1997 to 2022
    r2['cs']  = r['cs_1997'] + (r['cs_2022'] - r['cs_1997'])*((prm['ART_start']-1997)/25)#r2.cs  = r.cs_1997 + (r.cs_2022 - r.cs_1997)*((prm.ART_start-1997)/25);
    r2['cs2'] = r['cs2_1997'] + (r['cs2_2022'] - r['cs2_1997'])*((prm['ART_start']-1997)/25) #r2.cs2 = r.cs2_1997 + (r.cs2_2022 - r.cs2_1997)*((prm.ART_start-1997)/25); % Assumed to be same from 1997 to 2022
    p2['MDR_rec'] = np.array([0, 0]); r2['ART_init'] = 0 #p2.MDR_rec = [0 0]; r2.ART_init = 0; %p.MDR_rec2015;       
    M2 = make_model2(p2, r2, i, s, gps,prm)
    
        #% Start of ART to start of DST (scaleup 2003 - 2022)
    p3 = p.copy(); r3 = r.copy()
    p3['MDR_rec'] = p['MDR_rec2015']  # %p.MDR_rec2015    
 
    #Guy aligned this to Matlab on 2024-07-25 
    p3['pu'] = 0 + (p['pu_2022'] - 0)*((2015-1997)/25) #p3.pu = 0 + (p.pu_2022 - 0)*((2015-1997)/25);  % Assuming linear scaleup from 1997 to 2022
    r3['cs']  = r['cs_1997'] + (r['cs_2022'] - r['cs_1997'])*((2015-1997)/25)#r3.cs  = r.cs_1997 + (r.cs_2022 - r.cs_1997)*((2015-1997)/25);
    r3['cs2'] = r['cs2_1997'] + (r['cs2_2022'] - r['cs2_1997'])*((2015-1997)/25)#r3.cs2 = r.cs2_1997 + (r.cs2_2022 - r.cs2_1997)*((2015-1997)/25); % Assumed to be same from 1997 to 2022   
    #End #Guy aligned this to Matlab on 2024-07-25
    M3 = make_model2(p3, r3, i, s, gps,prm) #;
      
        #% Scale-up of DST (2015-2022)
    p4 = p.copy(); r4 = r.copy()
    p4['pu'] = p['pu_2022']; r4['cs']  = r['cs_2022']; r4['cs2'] = r['cs2_2022'] #p4.pu = p.pu_2022; r4.cs  = r.cs_2022; r4.cs2 = r.cs2_2022; 
    p4['MDR_rec'] = p['MDR_rec2022'] #p4.MDR_rec = p.MDR_rec2022;#Guy aligned this to Matlab on 2024-07-25
    M4 = make_model2(p4, r4, i, s, gps,prm)
        #%tic
        #% --- Simulate the models

        #% --- Simulate the models
        #% Equilibrium model
        #init = np.zeros((1,i['nx'])); seed = 1e-6 #init = zeros(1,i.nx); seed = 1e-6;
        #init[0,i['U']['h0']['v0']] = (1-seed)
        #init[0,i['I']['h0']['ds']] = seed#init(i.U.h0.v0) = (1-seed); init(i.I.h0.ds) = seed;
        ##geq = @(t,in)goveqs_basis2(t, in, M0, i, prm, sel, agg);
        ##[t0, soln0] = ode15s(geq, [0:2e3], init, odeset('NonNegative',[1:i.nstates]));
        #y0 = list(init[0])
        #(t0, soln0) = ode15s(goveqs_basis2, y0, np.linspace(0, 2e3,100), args=(M0, i, prm, sel, agg))

        #% Equilibrium model from the simplified small model
    init1 = np.zeros((1,i1['nx'])); seed = 1e-6
    init1[0][i1['U']['a1']['h0']['v0']] = prm['N'][0]/np.sum(prm['N']) 
    init1[0][i1['U']['a2']['h0']['v0']] = prm['N'][1]/sum(prm['N']) #init(i1.U.a2.h0.v0) = prm.N(2)/sum(prm.N); 
    init1[0][i1['U']['a3']['h0']['v0']] = prm['N'][2]/sum(prm['N']) #init(i1.U.a3.h0.v0) = prm.N(3)/sum(prm.N); 
    init1[0][i1['U']['a4']['h0']['v0']] = (prm['N'][3]/sum(prm['N']))-seed#init(i1.U.a4.h0.v0) = (prm.N(4)/sum(prm.N))-seed; 
    init1[0][i1['U']['a5']['h0']['v0']] = prm['N'][4]/sum(prm['N'])#init(i1.U.a5.h0.v0) = prm.N(5)/sum(prm.N); 
    init1[0][i1['I']['a4']['h0']['ds']] = seed#init(i1.I.a4.h0.ds) = seed;

    prm['growth'] = 0 #prm.growth = 0;
        #geq = @(t,in) goveqs_basissmall(t, in, r, M0, i1, prm);
        #[t0, soln0] = ode15s(geq, [0:2e3], init, odeset('NonNegative',[1:i1.nstates]));
    y0 = list(init1[0])
    (t0, soln0) = ode15s(goveqs_basissmall, y0, np.linspace(0, 2e3,2000), args=(r,M0, i1, prm))

    #Guy is updating this on 2024-07-25 to align with the code in NGA_final_vaccine
    #inds1 = np.intersect1d(np.intersect1d(s['U'], s['h0']),s['v0']) #inds1 = intersect(intersect(s.U, s.h0),s.v0);
    #inds2 = np.intersect1d(np.intersect1d(np.intersect1d([s['Lf'], s['Ls']], s['h0']), s['ds']),s['v0'])#inds2 = intersect(intersect(intersect([s.Lf, s.Ls], s.h0), s.ds),s.v0);
    #inds3 = np.intersect1d(np.intersect1d(np.concatenate([s['Isc'], s['I'], s['E'], s['Rlo'], s['Rhi'], s['R']]), s['h0']), s['ds']) #inds3 = intersect(intersect([s.Isc, s.I, s.E, s.Rlo, s.Rhi, s.R], s.h0), s.ds);
    #inds4 = np.intersect1d(np.intersect1d(np.intersect1d(np.concatenate([s['Dx'],s['Tx'],s['Tx2']]),s['ds']),s['h0']),s['pr']) #inds4 = intersect(intersect(intersect([s.Dx,s.Tx,s.Tx2],s.ds),s.h0),s.pr);
    #inds0  = np.concatenate([inds1, inds2, inds3,inds4]) #inds0  = [inds1, inds2, inds3,inds4];
    inds1 = np.intersect1d(np.intersect1d(s2['U'], s2['h0']),s2['v0']) #inds1 = intersect(intersect(s.U, s.h0),s.v0);
    inds2 = np.intersect1d(np.intersect1d(np.intersect1d([s2['Lf'], s2['Ls']], s2['h0']), s2['ds']),s2['v0'])#inds2 = intersect(intersect(intersect([s.Lf, s.Ls], s.h0), s.ds),s.v0);
    inds3 = np.intersect1d(np.intersect1d(np.concatenate([s2['Isc'], s2['I'], s2['E'], s2['Rlo'], s2['Rhi'], s2['R']]), s2['h0']), s2['ds']) #inds3 = intersect(intersect([s.Isc, s.I, s.E, s.Rlo, s.Rhi, s.R], s.h0), s.ds);
    inds4 = np.intersect1d(np.intersect1d(np.intersect1d(np.concatenate([s2['Dx'],s2['Tx'],s2['Tx2']]),s2['ds']),s2['h0']),s2['pr']) #inds4 = intersect(intersect(intersect([s.Dx,s.Tx,s.Tx2],s.ds),s.h0),s.pr);
    inds0  = np.concatenate([inds1, inds2, inds3,inds4]) #inds0  = [inds1, inds2, inds3,inds4];


    #% To allocate results from a small model to input vector for a bigger model
    #% model (60 to 115 compartments)
    init_smallmodel =  soln0[-1,:]
    init2 = np.zeros((1,i2['nx'])) #init = np.zeros((1,i['nx'])) #init = zeros(1,i.nx);
    init2[0][inds0] = init_smallmodel #init(inds0) = init_smallmodel;

    
    # % Introduction of MDR  
    prm['growth'] = prm['gth'][0] #prm.growth = prm.gth(1);
    #geq = @(t,in)goveqs_basissmall(t, in, r, M1a, i2, prm) #geq = @(t,in)goveqs_basissmall(t, in, r, M1a, i2, prm);  
    #[t1, soln1] = ode15s(geq, [1970 1997], init2, odeset('NonNegative',[1:i2.nstates])) #[t1, soln1] = ode15s(geq, [1970 1997], init2, odeset('NonNegative',[1:i2.nstates]));
    (t1, soln1) = ode15s(goveqs_basissmall, init2[0], np.linspace(1970, 1997), args=(r,M1a, i2, prm))

    ##End Guy is updating this on 2024-07-25 to align with the code in NGA_final_vaccine
   
    #% To initialise with MDR components
    inds1 = np.intersect1d(np.intersect1d(s['U'], s['h0']),s['v0']) #inds1 = intersect(intersect(s.U, s.h0),s.v0);
    inds2 = np.intersect1d(np.intersect1d([s['Lf'], s['Ls']], s['h0']),s['v0']) #inds2 = intersect(intersect([s.Lf, s.Ls], s.h0),s.v0);
    inds3 = np.intersect1d([s['Isc'], s['I'], s['E'], s['Rlo'], s['Rhi'], s['R']], s['h0'])
    inds4 = np.intersect1d(np.intersect1d([s['Dx'],s['Tx'],s['Tx2']],s['h0']),s['pr'])
    inds_full  = np.concatenate([inds1, inds2, inds3,inds4]) #inds_mdr  = [inds1, inds2, inds3,inds4];
    
    #init1 = init[0][inds_mdr]#init1 = init(inds_mdr);
  
      
    #prm['growth'] = prm['gth'][0] #prm.growth = prm.gth(1);
    #    #geq = @(t,in)goveqs_basissmall(t, in, r, M1a, i2, prm);  
    #    #[t1, soln1] = ode15s(geq, [1970 1997], init1, odeset('NonNegative',[1:i2.nstates]));
    #(t1, soln1) = ode15s(goveqs_basissmall, init1, np.linspace(1970, 1997), args=(r,M1a, i2, prm))

   
        #%     mat = zeros(i.nx,2);  % (Column 1 is i, column 2 is i1)
        #%     mat(:,1) = 1:i.nx;
        #%     mat(inds_mdr,2) = 1:length(inds_mdr);

        #% To allocate results from a small model to input vector for a bigger model
    init_smallmodel2 =  soln1[-1,:] #init_smallmodel2 =  soln1(end,:);
    init = np.zeros((1,i['nx'])) #init = zeros(1,i.nx);
    init[0][inds_full] = init_smallmodel2 #init(inds_mdr) = init_smallmodel2;
    
    #% Introduction of RNTCP % 
    #%init = init_smallmodel2; %soln1(end,:);
    #prm['growth'] = prm['gth'][1] #prm.growth = prm.gth(2);
        #geq = @(t,in) goveqs_scaleup(t, in, r, M1, M2, [1997 prm.ART_start], i, prm, sel, agg);#geq = @(t,in) goveqs_scaleup(t, in, r, M1, M2, [1997 2007], i, prm, sel, agg);
        #[t2, soln2] = ode15s(geq, [1997:prm.ART_start], init, odeset('NonNegative',[1:i.nstates]));
        #(t2, soln2) = ode15s(goveqs_scaleup, init[0], np.linspace(1997, prm['ART_start']), args=(r,M1, M2, [1997, 2007], i, prm, sel, agg))
    #(t2, soln2) = ode15s(goveqs_scaleup, init[0], np.linspace(1997, prm['ART_start']), args=(r,M1, M2, [1997, prm['ART_start']], i, prm, sel, agg))
    #% Before Introduction of RNTCP %
    prm['growth'] = 0 #prm.growth = 0; %prm.gth(2);  %2
    # %geq = @(t,in) goveqs_scaleup(t, in, r, M1, M2, [1997 prm.ART_start], i, prm, sel, agg);
    #geq = @(t,in) goveqs_basis2(t, in, r, M1, i, prm, sel, agg); %1e3
    #[t2a, soln2a] = ode15s(geq, [0:600], init, odeset('NonNegative',[1:i.nstates]));
    (t2a, soln2a) = ode15s(goveqs_basis2, init[0], np.linspace(0, 600), args=(r,M1, i, prm, sel, agg))
    #% Introduction of RNTCP %
    prm['growth'] = prm['gth'][1] #prm.growth = prm.gth(2);  %2
    #geq = @(t,in) goveqs_scaleup(t, in, r, M1, M2, [1997 prm.ART_start], i, prm, sel, agg);
    #%geq = @(t,in) goveqs_basis2(t, in, r, M1, i, prm, sel, agg);
    #[t2, soln2] = ode15s(geq, [1997:1:prm.ART_start], soln2a(end,:), odeset('NonNegative',[1:i.nstates]));
    (t2, soln2) = ode15s(goveqs_scaleup, soln2a[-1,:], np.linspace(1997, prm['ART_start']), args=(r,M1, M2, [1997, prm['ART_start']], i, prm, sel, agg))
    
        #% Introduction of ART (prm.ART_start(here 2004) onwards 2003-2015)
    init = soln2[-1,:] 
    prm['growth'] = prm['gth'][2] #prm.growth = prm.gth(3);
        #geq = @(t,in) goveqs_scaleup(t, in, r, M2, M3, [prm.ART_start 2022], i, prm, sel, agg);
        #geq = @(t,in) goveqs_scaleup(t, in, r, M2, M3, [prm.ART_start 2015], i, prm, sel, agg);#[t3, soln3] = ode15s(geq, [prm.ART_start:2015], init, odeset('NonNegative',[1:i.nstates]));
        #(t3, soln3) = ode15s(goveqs_scaleup, init, np.linspace(prm['ART_start'],2015), args=(r,M2, M3, [prm['ART_start'], 2022], i, prm, sel, agg))
    (t3, soln3) = ode15s(goveqs_scaleup, init, np.linspace(prm['ART_start'],2015), args=(r,M2, M3, [prm['ART_start'], 2015], i, prm, sel, agg))

        #% DST scale-up (Assuming from 2015 to 2022)
    init = soln3[-1,:]; prm['growth'] = prm['gth'][3] #init = soln3(end,:); prm.growth = prm.gth(4);
        #geq = @(t,in) goveqs_scaleup(t, in, r, M3, M4, [2015 2022], i, prm, sel, agg);#[t4, soln4] = ode15s(@(t,in) goveqs_scaleup(t, in,r, M3, M4, [2015 2022], i, prm, sel, agg), [2015 2023], init, odeset('NonNegative',[1:i.nstates]));
    (t4, soln4) = ode15s(goveqs_scaleup, init, np.linspace(2015,2023), args=(r,M3, M4, [2015, 2022], i, prm, sel, agg))

        #%keyboard;
    allt   = np.concatenate([t2, t3[1:], t4[1:]]) #allt   = [t2; t3(2:end); t4(2:end)]; #% ;   % 1997:2023
    allsol = np.concatenate([soln2, soln3[1:,:],soln4[1:,:]]) #allsol = [soln2; soln3(2:end,:);soln4(2:end,:)];
        
    proj_t = np.array(range(1997,2024))
    soln = np.zeros((len(proj_t),i['nx']))
    for jj in range(i['nx']):
        temp_fn_sol = interpolate.interp1d(allt, allsol[:,jj],fill_value="extrapolate") 
        soln[:,jj] = [temp_fn_sol(t) for t in proj_t]

        #soln = interp1(allt, allsol, 1997:2023) #soln = interp1(allt, allsol, 1997:2023);
        #dsol   = diff(soln,[],1);
        #sfin  = soln(end,:);
    dsol = np.diff(soln, 1, axis=0)
    sfin = soln[-1,]

        #%  toc
        #%  keyboard;
    #This line was added on 2024-10-23
    pop = np.sum(soln[0:(np.shape(soln)[0]-1),0:(i['nstates']-1)],1) # %1997:2022 (1:end -> 1997:2023) #pop = sum(soln(1:end-1,1:i.nstates),2);  %1997:2022 (1:end -> 1997:2023)

        #% --- Get the objectives ----------------------------------------------
    inc2000      = dsol[len(pop)-23,i['aux']['inc'][0]]/pop[len(pop)-23]*1e5 #  inc2000      = sum(dsol(end-22,i.aux.inc(1)))*1e5  
    if isinstance(inc2000, (collections.abc.Sequence, np.ndarray)):
        inc2000 = sum(inc2000) 

    inc2022  = dsol[-1,i['aux']['inc'][0]]/pop[-1]*1e5 #inc2022  = sum(dsol(end,i.aux.inc(1)))*1e5;
    if isinstance(inc2022, (collections.abc.Sequence, np.ndarray)):
        inc2022 = sum(inc2022)
    inc_h1   = dsol[-1,i['aux']['inc'][1]]/pop[-1]*1e5 #inc_h1   = dsol(end,i.aux.inc(2))*1e5;     %([2,3])
    mdr2015  = dsol[-8,i['aux']['inc'][2]]/pop[-8]*1e5 #mdr2015  = dsol(end-7,i.aux.inc(3))*1e5; %end--> 2022
    mdr2022  = dsol[-1,i['aux']['inc'][2]]/pop[-1]*1e5 #mdr2022  = dsol(end,i.aux.inc(3))*1e5;

    noti_cu      =  sum(np.sum(dsol[(len(proj_t)-23):len(proj_t),i['aux']['noti']]/pop[(len(proj_t)-23):len(proj_t)][:,None]*1e5,1)) #noti_cu      =  sum(sum(dsol(end-22:end,i.aux.noti)*1e5,2));  %cumulative notification from 2000 to 2022
    #noti_cu      =  sum(sum((dsol(end-22:end,i.aux.noti)./pop(end-22:end))*1e5,2));

    noti2022     = sum(dsol[-1,i['aux']['noti']]/pop[-1])*1e5 #noti     = sum(dsol(end,i.aux.noti))*1e5;
    ART_covg = sum(sfin[s['hart']]/np.sum(sfin[[s['h1'],s['hart']]])) #ART_covg = sum(sfin(s.hart)/sum(sfin([s.h1,s.hart])));
    HIV_prev = np.sum(sfin[[s['h1'], s['hart']]])/np.sum(sfin[0:(i['nstates']-1)]) #HIV_prev = sum(sfin([s.h1, s.hart]))/sum(sfin(1:i.nstates));
        
    mort_H02000  = dsol[len(proj_t)-23,i['aux']['mort'][0]]/pop[-23]*1e5 #mort_H02000  = dsol(end-22,i.aux.mort(1))*1e5;

    mort_H02022  = dsol[-1,i['aux']['mort'][0]]/pop[-1]*1e5 #mort_H0  = dsol(end,i.aux.mort(1))*1e5;
    mort_H12022  = dsol[-1,i['aux']['mort'][1]]/pop[-1]*1e5 #mort_H1  = dsol(end,i.aux.mort(2))*1e5;
    mdriniTX = dsol[-1,i['aux']['noti2']]/pop[-1]*1e5 #mdriniTX = dsol(end,i.aux.noti2)*1e5;  % MDR treatment initiation 2019
    sym_sim =  sum(sfin[s['I']])/sum(sfin[s['prevalent']]) #sym_sim =  sum(sfin(s.I))/sum(sfin(s.prevalent)); 
    inc2015  = dsol[-8,i['aux']['inc'][0]]/pop[-8]*1e5 #inc2015  = sum(dsol(end-7,i.aux.inc(1)))*1e5;
    if isinstance(inc2015, (collections.abc.Sequence, np.ndarray)):
        inc2015 = sum(inc2015)
    
    aux = {}
    if inc2022 < 1 : #if inc2022 < 1
        out = math.inf*calfn['sgn']
        aux = {}
    else:
            #out = calfn['fn'](inc2015, inc2022, inc_h1, noti, ART_covg, HIV_prev, mort_H0, mort_H1, mdr2015, mdr2022, mdriniTX, sym_sim) #out = calfn.fn(inc2015, inc2022, inc_h1, noti, ART_covg, HIV_prev, mort_H0, mort_H1, mdr2015, mdr2022, mdriniTX, sym_sim);
            #out = calfn.fn(sym_sim,inc2000, inc2022, mort_H02000,mort_H02022,noti_cu, noti2022, mdr2015, mdr2022, mdriniTX,HIV_prev,inc_h1,ART_covg,mort_H12022)
        out = calfn['fn'](sym_sim,inc2000, inc2022, mort_H02000,mort_H02022,noti_cu, noti2022, mdr2015, mdr2022, mdriniTX,HIV_prev,inc_h1,ART_covg,mort_H12022) #out = calfn.fn(inc2015, inc2022, inc_h1, noti, ART_covg, HIV_prev, mort_H0, mort_H1, mdr2015, mdr2022, mdriniTX, sym_sim);
        #%         keyboard;
        
    if out.imag>0 : #if imag(out)>0
        out = math.inf*calfn['sgn'] #out = Inf*calfn.sgn;
        aux = []   
    else:
        #% --- Get additional outputs and package --------------------------
        aux['soln']     = soln# %[soln, t] #aux.soln     = soln; %[soln, t];         % 2003:2023
        aux['allsol']   = np.concatenate([soln2, soln3[1:,:], soln4[1:,:]]) #aux.allsol   = [soln2; soln3(2:end,:); soln4(2:end,:)];  % 1997:2023
        aux['inc2022']  = inc2022 #aux.inc2022  = inc2022;
        aux['inc2015'] = inc2015 #aux.inc2015 = inc2015;
        aux['inc2000'] = inc2000 #aux.inc2015 = inc2015;

        aux['inc_h1']   = inc_h1 #aux.inc_h1   = inc_h1;
        aux['noti']     = noti2022 #aux.noti     = noti;
        aux['noti_cu']  = noti_cu #aux.noti_cu  = noti_cu;
        aux['ART_covg'] = ART_covg#aux.ART_covg = ART_covg;
        aux['HIV_prev'] = HIV_prev #aux.HIV_prev = HIV_prev;
        aux['mort_H02000']  = mort_H02000 #aux['mort_H0']  = mort_H0 #aux.mort_H0  = mort_H0;
        aux['mort_H02022']  = mort_H02022 #aux.mort_H02022  = mort_H02022;
        aux['mort_H1']  = mort_H12022#aux['mort_H1']  = mort_H1#aux.mort_H1  = mort_H1;
        aux['mdr2015']  = mdr2015 #aux.mdr2015  = mdr2015;
        aux['mdr2022']  = mdr2022#aux.mdr2022  = mdr2022;
        aux['mdriniTX'] = mdriniTX #aux.mdriniTX = mdriniTX;
        aux['sym']      = sym_sim #aux.sym      = sym_sim;
        aux['M1']       = M1 #aux.M1       = M1;
    #end
        
    return (out, aux)