package de.randi2.simulation.service; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import org.springframework.stereotype.Service; import de.randi2.model.SubjectProperty; import de.randi2.model.TreatmentArm; import de.randi2.model.Trial; import de.randi2.model.TrialSite; import de.randi2.model.TrialSubject; import de.randi2.model.criteria.AbstractCriterion; import de.randi2.model.criteria.DateCriterion; import de.randi2.model.criteria.DichotomousCriterion; import de.randi2.model.criteria.OrdinalCriterion; import de.randi2.model.criteria.constraints.DateConstraint; import de.randi2.model.criteria.constraints.DichotomousConstraint; import de.randi2.model.criteria.constraints.OrdinalConstraint; import de.randi2.model.randomization.MinimizationConfig; import de.randi2.randomization.Minimization; import de.randi2.simulation.distribution.AbstractDistribution; import de.randi2.simulation.model.DistributionSubjectProperty; import de.randi2.simulation.model.SimulationRawDataEntry; import de.randi2.simulation.model.SimulationResult; import de.randi2.simulation.model.SimulationRun; import de.randi2.unsorted.ConstraintViolatedException; import de.randi2.utility.Pair; @Service("simulationService") public class SimulationServiceImpl implements SimulationService { @Override public SimulationResult simulateTrial(Trial trial, List<DistributionSubjectProperty> properties, AbstractDistribution<TrialSite> distributionTrialSites, int runs, long maxTime, boolean collectRawData) { // copy the trial to avoid side effects Trial copyTrial; try { copyTrial = copyAndPrepareTrial(trial, properties, distributionTrialSites); } catch (ConstraintViolatedException e) { return null; } Map<String, String> strataIdsNames = new HashMap<String, String>(); Pair<List<String>, List<String>> pair = copyTrial.getAllStrataIdsAndNames(); for(int i =0;i< pair.first().size();i++){ strataIdsNames.put(pair.first().get(i), pair.last().get(i)); } // initialize the simulation result SimulationResult simResult = new SimulationResult(new ArrayList<TreatmentArm>(copyTrial.getTreatmentArms()), copyTrial.getRandomizationConfiguration(), strataIdsNames); long startTime; TreatmentArm assignedArm; TrialSubject subject = new TrialSubject(); long endTime = System.currentTimeMillis() + maxTime; // loop over all simulation runs for (int run = 0; run < runs; run++) { if (System.currentTimeMillis() < endTime) { startTime = System.currentTimeMillis(); Trial simTrial = resetTrial(copyTrial); SimulationRun simRun = simResult.getEmptyRun(); // loop over all trial subjects to randomize for (int i = 0; i < simTrial.getPlannedSubjectAmount(); i++) { // generate the subject properties subject = generateTrialSubject(properties, subject); subject.setTrialSite(distributionTrialSites.getNextValue()); // randomize the subject an add it to the treatment arm assignedArm = simTrial.getRandomizationConfiguration() .getAlgorithm().randomize(subject); subject.setArm(assignedArm); subject.setRandNumber(i + "_" + assignedArm.getName()); subject.setCounter(i); subject.setIdentification(subject.getRandNumber()); if(collectRawData){ SimulationRawDataEntry entry = new SimulationRawDataEntry(); entry.setRun(run); entry.setCount(i); entry.setTreatmentArm(assignedArm.getName()); entry.setTrialSite(subject.getTrialSite().getName()); String stratum = ""; if (trial.isStratifyTrialSite()) { stratum = subject.getTrialSite().getId() + "__"; } stratum += subject.getStratum(); entry.setStratum(stratum); simResult.getRawData().add(entry); } String stratum = ""; if (trial.isStratifyTrialSite()) { stratum = subject.getTrialSite().getId() + "__"; } stratum += subject.getStratum(); if(!stratum.equals("")){ Integer count = simRun.getStrataCountsPerArm().get(assignedArm).get(stratum); count++; simRun.getStrataCountsPerArm().get(assignedArm).put(stratum, count); } assignedArm.addSubject(subject); } // set data for this simulation run and add it to the simulation // result List<TreatmentArm> arms = new ArrayList<TreatmentArm>(simTrial.getTreatmentArms()); for (int i = 0; i < simTrial.getTreatmentArms().size(); i++) { simRun.getSubjectsPerArms()[i] = arms.get(i) .getCurrentSubjectsAmount(); } simRun.setTime((System.currentTimeMillis() - startTime)); simResult.addSimulationRun(simRun); } else { break; } } // Analyze the simulation result // simResult.analyze(); return simResult; } /** * TThis method clones the objects and initializes them (id, ...). * * @param trial * @param properties * @param distributionTrialSites * @return */ private static Trial copyAndPrepareTrial(Trial trial, List<DistributionSubjectProperty> properties, AbstractDistribution<TrialSite> distributionTrialSites) throws ConstraintViolatedException{ long id = 0; // copy plain trail data Trial cTrial = new Trial(); cTrial.setId(id++); cTrial.setStratifyTrialSite(trial.isStratifyTrialSite()); cTrial.setStartDate(trial.getStartDate()); cTrial.setEndDate(trial.getEndDate()); // clone and copy the patient properties for (int i = 0; i < distributionTrialSites.getElements().size(); i++) { TrialSite site = distributionTrialSites.getElements().get(i); TrialSite cSite = new TrialSite(); cSite.setName(site.getName()); cSite.setId(id++); distributionTrialSites.getElements().set(i, cSite); cTrial.addParticipatingSite(cSite); } HashSet<TreatmentArm> arms = new HashSet<TreatmentArm>(); for (TreatmentArm arm : trial.getTreatmentArms()) { TreatmentArm cArm = new TreatmentArm(); cArm.setName(arm.getName()); cArm.setPlannedSubjects(arm.getPlannedSubjects()); cArm.setId(id++); cArm.setTrial(cTrial); arms.add(cArm); } cTrial.setTreatmentArms(arms); for (DistributionSubjectProperty dsp : properties) { AbstractCriterion<?, ?> cr = dsp.getCriterion(); if (DateCriterion.class.isInstance(cr)) { DateCriterion ccr = new DateCriterion(); ccr.setName(cr.getName()); ccr.setId(id++); ccr.setInclusionConstraintAbstract(cr.getInclusionConstraint()); for (DateConstraint co : DateCriterion.class.cast(cr) .getStrata()) { DateConstraint cco = new DateConstraint(); cco.setFirstDate(co.getFirstDate()); cco.setSecondDate(co.getSecondDate()); cco.setId(id++); ccr.addStrata(cco); } dsp.setCriterion(ccr); cTrial.addCriterion(ccr); } else if (DichotomousCriterion.class.isInstance(cr)) { DichotomousCriterion ccr = new DichotomousCriterion(); ccr.setName(cr.getName()); ccr.setId(id++); ccr.setInclusionConstraintAbstract(cr.getInclusionConstraint()); ccr .setOption1(DichotomousCriterion.class.cast(cr) .getOption1()); ccr .setOption2(DichotomousCriterion.class.cast(cr) .getOption2()); for (DichotomousConstraint co : DichotomousCriterion.class .cast(cr).getStrata()) { ArrayList<String> values = new ArrayList<String>(); values.add(co.getExpectedValue()); DichotomousConstraint cco; try { cco = new DichotomousConstraint(values); cco.setId(id++); ccr.addStrata(cco); } catch (ConstraintViolatedException e) { } } dsp.setCriterion(ccr); cTrial.addCriterion(ccr); } else if (OrdinalCriterion.class.isInstance(cr)) { OrdinalCriterion ccr = new OrdinalCriterion(); ccr.setName(cr.getName()); ccr.setId(id++); ccr.setInclusionConstraintAbstract(cr.getInclusionConstraint()); ccr.setElements(OrdinalCriterion.class.cast(cr).getElements()); for (OrdinalConstraint co : OrdinalCriterion.class.cast(cr) .getStrata()) { ArrayList<String> values = new ArrayList<String>(co .getExpectedValues()); OrdinalConstraint cco; try { cco = new OrdinalConstraint(values); cco.setId(id++); ccr.addStrata(cco); } catch (ConstraintViolatedException e) { } } dsp.setCriterion(ccr); cTrial.addCriterion(ccr); } } // reset the randomization configuration cTrial.setRandomizationConfiguration(trial .getRandomizationConfiguration()); cTrial.getRandomizationConfiguration().setTrial(cTrial); cTrial.getRandomizationConfiguration().resetAlgorithm(); return cTrial; } // // public long estimateSimulationDuration(Trial trial, // List<DistributionSubjectProperty> properties, // AbstractDistribution<TrialSite> distributionTrialSites, int runs, long // maxTime){ // SimulationResult result = simulateTrial(trial, properties, // distributionTrialSites, 30, maxTime); // long time = 0; // for(int i =10 ; i<30;i++){ // time+= result.getRuns().get(i).getTime(); // } // time = ((time /20)*runs) / 1000000; // return time; // } /** * Reset the passed trial. */ private static Trial resetTrial(Trial trial) { for (TreatmentArm arm : trial.getTreatmentArms()) { arm.getSubjects().clear(); } trial.getRandomizationConfiguration().setTrial(trial); trial.getRandomizationConfiguration().setTempData(null); trial.getRandomizationConfiguration().resetAlgorithmWithNextSeed(); if (MinimizationConfig.class.isInstance(trial .getRandomizationConfiguration())) { ((Minimization) trial.getRandomizationConfiguration() .getAlgorithm()).clear(); } return trial; } /** * Generate a trial subject with the distribution of the subject properties. * * @param properties * The subject properties with the distribution. * @param oldSubject * The old trialSubject object. * @return The reseted and changed trial subject object. */ public static TrialSubject generateTrialSubject( List<DistributionSubjectProperty> properties, TrialSubject oldSubject) { oldSubject.setProperties(null); HashSet<SubjectProperty<?>> tempSet = new HashSet<SubjectProperty<?>>(); for (DistributionSubjectProperty dsp : properties) { SubjectProperty<Serializable> pr = new SubjectProperty<Serializable>( dsp.getCriterion()); try { pr.setValue(dsp.getNextSubjectValue()); } catch (ConstraintViolatedException e) { } tempSet.add(pr); } oldSubject.setProperties(tempSet); return oldSubject; } }