edu.uic.apk.IDUbuilder1.java Source code

Java tutorial

Introduction

Here is the source code for edu.uic.apk.IDUbuilder1.java

Source

/*
 * Copyright (c) 2011-2014, Alexander Gutfraind
 *  All rights reserved.
 *  Details in license.txt
 */

package edu.uic.apk;

import edu.uic.apkSynth.DrugUser;
import edu.uic.apkSynth.Gender;
import edu.uic.apkSynth.HCV_state;
import edu.uic.apkSynth.PersonGenerator;

import java.lang.reflect.Method;
//incompatible with 1.6
//import java.nio.charset.Charset;
//import java.nio.file.Files;
//import java.nio.file.Paths;
import java.util.ArrayList;

//import java.util.Calendar;
import org.joda.time.*;

import java.util.HashMap;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;

import cern.jet.random.Poisson;
import repast.simphony.context.Context;
import repast.simphony.engine.environment.RunEnvironment;
import repast.simphony.engine.schedule.IAction;
import repast.simphony.engine.schedule.ISchedule;
import repast.simphony.engine.schedule.ScheduleParameters;
import repast.simphony.essentials.RepastEssentials;
import repast.simphony.parameter.Parameters;
import repast.simphony.random.RandomHelper;
import repast.simphony.space.gis.Geography;
import repast.simphony.space.graph.Network;

/*
 * An agent factory for generating a population of injecting-drug users (IDUs), also called "persons who inject drugs" (PWID)
 * - created as a singleton
 */
public class IDUbuilder1 implements AgentFactory {
    HashMap<String, Object> extra_params;
    HashMap<String, Object> sim_params;

    private Context context;
    private Geography<IDU> geography;
    private Network<IDU> network;
    HashMap<String, ZoneAgent> zip_to_zones;
    Poisson idu_arrivals;

    //Note: we avoid defaults and constants, instead relying on the parameter file
    private static double ab_prob_chronic = Double.NaN;// = 0.80; //when testing antibody-positive
    private static double ab_prob_acute = Double.NaN;//   = 0.05; //when testing antibody-positive
    private static double burn_in_days = Double.NaN;
    private static boolean burn_in_mode = false;
    private static int initial_pwid_count = -1;
    private static double net_inflow = Double.NaN;
    private static double pwid_maturity_threshold = Double.NaN; //usually about 5
    private static double prob_infected_when_arrive = Double.NaN;
    private static double status_report_frequency = -1;

    private Method idu_generator;
    PersonGenerator pg = null;

    public IDUbuilder1(Context context, HashMap<String, Object> sim_params, HashMap<String, Object> extra_params) {
        this.extra_params = extra_params;
        this.sim_params = sim_params;
        this.context = context;
        this.geography = (Geography<IDU>) context.getProjection("Geography");
        this.network = (Network<IDU>) context.getProjection("infection network");
        this.zip_to_zones = (HashMap<String, ZoneAgent>) extra_params.get("zip_to_zones");

        IDU.setStatics(context, network, geography);
        IDU.setHomophilyStrength((Double) sim_params.get("homophily_strength"));//
        IDU.setMeanTieLifetime((Double) sim_params.get("mean_tie_lifetime"));// 
        //IDU.setMeanSero_bias((Double) sim_params.get("mean_sero_bias"));//
        IDU.setAttrition_rate((Double) sim_params.get("attrition_rate"));// 
        IDU.setMean_career_duration((Double) sim_params.get("mean_career_duration"));
        IDU.setProb_cessation((Double) sim_params.get("prob_cessation"));

        try {
            pg = PersonGenerator.make_NEP_generator(sim_params, pwid_maturity_threshold,
                    RandomHelper.nextIntFromTo(0, Integer.MAX_VALUE));
            idu_generator = IDUbuilder1.class.getDeclaredMethod("generate_SynthNEP", HashMap.class);

        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        prob_infected_when_arrive = (Double) sim_params.get("prob_infected_when_arrive");
        status_report_frequency = (Double) sim_params.get("status_report_frequency");

        net_inflow = (Double) sim_params.get("net_inflow");
        assert net_inflow >= 0; //the other case needs to be modeled as attrition or cessation
        initial_pwid_count = Integer.parseInt(sim_params.get("initial_pwid_count").toString());

        ISchedule schedule = repast.simphony.engine.environment.RunEnvironment.getInstance().getCurrentSchedule();
        schedule.schedule(
                ScheduleParameters.createRepeating(burn_in_days + Statistics.getCounterResetTiming() - 0.001, 1.0),
                this, "generate_arriving");
        //remove -0.001 to make sure that the call is made just before the stats counter is reset
    }

    public static double getAb_prob_acute() {
        return ab_prob_acute;
    }

    public static double getAb_prob_chronic() {
        return ab_prob_chronic;
    }

    public static void setStatics(Parameters params) {
        IDUbuilder1.ab_prob_acute = (Double) params.getValue("ab_prob_acute");
        IDUbuilder1.ab_prob_chronic = (Double) params.getValue("ab_prob_chronic");
        IDUbuilder1.pwid_maturity_threshold = (Double) params.getValue("pwid_maturity_threshold");
        assert ab_prob_acute + ab_prob_chronic <= 1.0;
    }

    public static void setBurn_in_period(boolean burn_in_mode, double burn_in_period) {
        IDUbuilder1.burn_in_mode = burn_in_mode;
        IDUbuilder1.burn_in_days = burn_in_period;
    }

    /*
     * 1. receives a raw IDU from a generator
     * 2. checks the IDUs
     * 3. add the IDUs to the simulation
     * prob_infected_when_arrive refers only to immature agents
     */
    public ArrayList<IDU> add_new_IDUs(int count, boolean early_idus_only) {
        ArrayList<IDU> my_IDUs = new ArrayList<IDU>();
        int num_requested_idus = (count >= 0) ? count : idu_arrivals.nextInt();
        GeometryFactory fac = new GeometryFactory();
        HashMap<String, Object> generator_params = new HashMap<String, Object>();
        generator_params.put("early_idus_only", (Boolean) early_idus_only);
        generator_params.put("max_trials", (Integer) 200);

        while (my_IDUs.size() < num_requested_idus) {
            IDU idu = null;
            try {
                idu = (IDU) idu_generator.invoke(this, generator_params);
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
            if (early_idus_only) {
                int days_since_initiated = (int) Math.round(365 * (idu.getAge() - idu.getAgeStarted()));
                idu.setBirthDate(idu.getBirthDate().plusDays(days_since_initiated - 50));
                if (prob_infected_when_arrive < RandomHelper.nextDouble()) { //typically for new IDU
                    idu.setHcvInitialState(HCV_state.susceptible);
                } else {
                    idu.setHcvInitialState(HCV_state.infectiousacute);
                }
            }

            ZoneAgent my_zone = zip_to_zones.get(idu.getPreliminaryZip());
            if (my_zone == null) {
                idu.deactivate();
                continue; //must be off the map? e.g. 60662
            }
            idu.setZone(my_zone);
            if (!idu.self_test_ok(0)) {
                System.out.println("f");
                idu.deactivate();
                continue;
            }

            idu.setEntryDate(APKBuilder.getSimulationDate());
            double elapsed_career_days = 365.0 * (idu.getAge() - idu.getAgeStarted());
            double residual_burnin_days = 0;
            if (burn_in_mode) {
                residual_burnin_days = Math.max(0, burn_in_days - RepastEssentials.GetTickCount());
            }
            if (!idu.activate(residual_burnin_days, elapsed_career_days, status_report_frequency)) {
                context.remove(idu);
                continue;
            }
            my_IDUs.add(idu);
            context.add(idu);
            Statistics.fire_status_change(AgentMessage.activated, idu, "", null);
            System.out.print(".");

            Coordinate possible_agent_coord = new Coordinate(my_zone.getCentroid().getX() + 0.01 * Math.random(),
                    my_zone.getCentroid().getY() + 0.01 * Math.random());
            Point coord = fac.createPoint(possible_agent_coord);
            if (!my_zone.getPolygon().contains(coord)) {
                coord = my_zone.getPolygon().getInteriorPoint();
            }
            geography.move(idu, coord);
        }

        return my_IDUs;
    }

    //immigration + replacement of mortality
    public ArrayList<IDU> generate_arriving() {
        int total_lost = Statistics.daily_losses();
        idu_arrivals = RandomHelper.createPoisson(total_lost + (net_inflow / 365.0));
        int new_count = idu_arrivals.nextInt();
        ArrayList<IDU> pop = add_new_IDUs(new_count, true);
        //System.out.println("T" + RepastEssentials.GetTickCount() + ": Added: " + new_count);

        return pop;

    }

    public ArrayList<IDU> generate_initial() {
        //called just once in the beginning of the simulations
        assert APKBuilder.getDateDifference(APKBuilder.getSimulationDate(),
                APKBuilder.getSimulation_start_date()) < 0.02;

        int count = initial_pwid_count;
        ArrayList<IDU> pop = add_new_IDUs(count, false);

        if (count > 0) {
            int num_infected = 0;
            int num_abpos = 0;
            for (IDU idu : pop) {
                num_infected += idu.isHcvRNA() ? 1 : 0;
                num_abpos += idu.isHcvABpos() ? 1 : 0;
            }
            System.out.println();
            System.out.println("Initial HCV prevalence (RNA+): " + num_infected / (1.0 * count));
            System.out.println("                  (Antibody+): " + num_abpos / (1.0 * count));
        }
        return pop;
    }

    /*
     * calls the NEP generator, converts DrugUser to full IDU object (specific HCV state, name)
     */
    public IDU generate_SynthNEP(HashMap<String, Object> generator_params) throws Exception {
        DrugUser modelDU = null;
        Integer max_trials = 50;
        if (generator_params.containsKey("max_trials")) {
            max_trials = (Integer) generator_params.get("max_trials");
        }
        for (int trial = 0; trial < max_trials; trial++) {
            try {
                modelDU = pg.generate(generator_params);
                assert modelDU != null;
                break;
            } catch (Exception e) {
                System.out.println("x");
                modelDU = null;
            }
        }
        if (modelDU == null) {
            throw new Exception("failed to generate");
        }

        IDU idu = new IDU();
        idu.setAgeStarted(modelDU.getAgeStarted());

        LocalDate b_day = modelDU.getBirthDate();
        LocalDate age_at_survey = modelDU.getSurveyDate();
        LocalDate sim_date = APKBuilder.getSimulationDate();
        b_day = b_day.plusYears(sim_date.getYear() - age_at_survey.getYear());
        b_day = b_day.plusDays(sim_date.getDayOfYear() - age_at_survey.getDayOfYear());
        b_day = b_day.plusDays((int) (0.05 * 365 * (RandomHelper.nextDouble() - 0.5))); //some slight jitter (0.05 of a year)
        idu.setBirthDate(b_day);
        //System.out.println("Age:" + idu.getAge() + "Model age:" + modelDU.getAge());

        idu.setDatabaseLabel(modelDU.getDatabaseLabel());
        idu.setEntryDate(LocalDate.now());
        idu.setDrugGivingDegree(modelDU.getDrugGivingDegree());
        idu.setDrugReceptDegree(modelDU.getDrugReceptDegree());
        idu.setFractionReceptSharing(modelDU.getFractionReceptSharing());
        idu.setGender(modelDU.getGender());
        if (modelDU.getHcvState() == HCV_state.ABPOS) {
            double roll = RandomHelper.nextDouble() - ab_prob_chronic;
            if (roll < 0) {
                idu.setHcvInitialState(HCV_state.chronic);
            } else if (roll - ab_prob_acute < 0) {
                idu.setHcvInitialState(HCV_state.infectiousacute);
            } else {
                idu.setHcvInitialState(HCV_state.recovered);
            }
        } else {
            idu.setHcvInitialState(HCV_state.susceptible);
        }
        idu.setInjectionIntensity(modelDU.getInjectionIntensity());
        if (idu.getName() == null) {
            if (idu.getGender() == Gender.Male) {
                idu.setName(IDU.male_names[RandomHelper.nextIntFromTo(0, IDU.male_names.length - 1)]);
            } else {
                idu.setName(IDU.female_names[RandomHelper.nextIntFromTo(0, IDU.female_names.length - 1)]);
            }
        }
        idu.setPreliminaryZip(modelDU.getPreliminaryZip());
        idu.setRace(modelDU.getRace());
        idu.setSyringe_source(modelDU.getSyringe_source());
        return idu;
    }

    public void remove_IDUs() {
        ArrayList<IDU> removed_agents = new ArrayList<IDU>();
        for (Object obj : context) {
            if (obj instanceof IDU) {
                IDU agent = (IDU) obj;
                removed_agents.add(agent);

            }
        }
        for (IDU agent : removed_agents) {
            agent.deactivate();
        }
    }

    /*
      * used for debugging: constructs IDUs based on each of the NEP synthetic pops
      * - note that this algorithm assumes that the dblabels are sequential
     */
    public void systematic_NEP_synthetic() {
        assert Math.abs((Double) sim_params.get("mean_enrichment_suburbs") - 0.0) < 0.00001;
        assert Math.abs((Double) sim_params.get("mean_enrichment_ChicagoNonNEP") - 0.0) < 0.00001;
        ArrayList<IDU> idu_list = new ArrayList<IDU>();
        GeometryFactory fac = new GeometryFactory();
        HashMap<String, Object> generator_params = new HashMap<String, Object>();
        generator_params.put("max_trials", 1);
        for (Integer db_reference_number = 0; db_reference_number < pg.catalogueSize(); db_reference_number++) {
            IDU idu = null;
            try {
                generator_params.put("db_reference_number", db_reference_number);
                //LOAD the characteristics of the agents
                System.out.print("\n NEP#" + generator_params.get("db_reference_number"));
                idu = (IDU) generate_SynthNEP(generator_params);
                if (idu == null) {
                    continue;
                }
            } catch (Exception e) {
                continue;
            }
            ZoneAgent my_zone = zip_to_zones.get(idu.getPreliminaryZip());
            if (my_zone == null) {
                continue; //must be off the map? e.g. 60662
            }
            idu.setZone(my_zone);
            if (!idu.self_test_ok(1)) {
                continue;
            }
            idu.setEntryDate(APKBuilder.getSimulationDate());
            double elapsed_career_days = 365.0 * (idu.getAge() - idu.getAgeStarted());
            double residual_burnin_days = 0;
            if (burn_in_mode) {
                residual_burnin_days = Math.max(0, burn_in_days - RepastEssentials.GetTickCount());
            }
            if (!idu.activate(residual_burnin_days, elapsed_career_days, status_report_frequency)) {
                continue;
            }

            idu_list.add(idu);
            context.add(idu);
            Statistics.fire_status_change(AgentMessage.activated, idu, "", null);
            System.out.print(".");

            Coordinate possible_agent_coord = new Coordinate(my_zone.getCentroid().getX() + 0.01 * Math.random(),
                    my_zone.getCentroid().getY() + 0.01 * Math.random());
            Point coord = fac.createPoint(possible_agent_coord);
            if (!my_zone.getPolygon().contains(coord)) {
                coord = my_zone.getPolygon().getInteriorPoint();
            }
            geography.move(idu, coord);
        }
        int count = idu_list.size();
        if (count > 0) {
            int num_infected = 0;
            int num_abpos = 0;
            for (IDU idu : idu_list) {
                num_infected += idu.isHcvRNA() ? 1 : 0;
                num_abpos += idu.isHcvABpos() ? 1 : 0;
            }
            System.out.println();
            System.out.println("Initial HCV prevalence (RNA+): " + num_infected / (1.0 * count));
            System.out.println("                  (Antibody+): " + num_abpos / (1.0 * count));
        }

        System.out.println("\nDone. Finished " + idu_list.size() + " agents.");
        return;
    }
}