package de.randi2.jsf.controllerBeans; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.ResourceBundle; import javax.el.ValueExpression; import javax.faces.bean.ManagedBean; import javax.faces.bean.ManagedProperty; import javax.faces.bean.SessionScoped; import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; import javax.faces.model.SelectItem; import lombok.Getter; import lombok.Setter; import com.icesoft.faces.context.Resource; import de.randi2.jsf.backingBeans.AlgorithmConfig; import de.randi2.jsf.backingBeans.Randi2Page; import de.randi2.jsf.backingBeans.SimulationAlgorithm; import de.randi2.jsf.backingBeans.SimulationSubjectProperty; import de.randi2.jsf.wrappers.AlgorithmWrapper; import de.randi2.jsf.wrappers.CriterionWrapper; import de.randi2.jsf.wrappers.DistributedConstraintWrapper; import de.randi2.jsf.wrappers.DistributedCriterionWrapper; import de.randi2.jsf.wrappers.DistributionTrialSiteWrapper; import de.randi2.jsf.wrappers.TrialSiteRatioWrapper; import de.randi2.model.TreatmentArm; import de.randi2.model.Trial; import de.randi2.model.TrialSite; import de.randi2.model.criteria.AbstractCriterion; import de.randi2.model.criteria.constraints.AbstractConstraint; import de.randi2.model.randomization.BiasedCoinRandomizationConfig; import de.randi2.model.randomization.BlockRandomizationConfig; import de.randi2.model.randomization.CompleteRandomizationConfig; import de.randi2.model.randomization.MinimizationConfig; import de.randi2.model.randomization.TruncatedBinomialDesignConfig; import de.randi2.model.randomization.UrnDesignConfig; import de.randi2.simulation.model.DistributionSubjectProperty; import de.randi2.simulation.model.SimulationRawDataEntry; import de.randi2.simulation.model.SimulationResult; import de.randi2.simulation.model.SimulationResultArm; import de.randi2.simulation.model.helper.StrataResultComperatorAST; import de.randi2.simulation.model.helper.StrataResultComperatorATS; import de.randi2.simulation.model.helper.StrataResultComperatorSAT; import de.randi2.simulation.model.helper.StrataResultComperatorSTA; import de.randi2.simulation.model.helper.StrataResultWrapper; import de.randi2.simulation.service.SimulationService; /** * <p> * This class cares about the simulation of trials and contains all the needed * methods to work with this object for the UI. * </p> * * @author ds@randi2.de */ @ManagedBean(name = "simulationHandler") @SessionScoped public class SimulationHandler extends AbstractTrialHandler { private int algorithmWrapperIdSequence = 0; @Getter @Setter private int simulationConfigurationTabIndex = 0; @ManagedProperty(value = "#{trialHandler}") @Getter @Setter private TrialHandler trialHandler; @ManagedProperty(value = "#{simulationService}") @Getter @Setter private SimulationService simulationService; @ManagedProperty(value = "#{simulationAlgorithm}") @Getter @Setter private SimulationAlgorithm simulationAlgorithm; @Getter @Setter private int runs = 1000; @Getter @Setter private long maxTime; @Getter private SimulationResult simResult; @Getter private int countTrialSites; @Setter private boolean criterionChanged = true; public void criterionChanged() { criterionChanged = true; } public boolean isCriterionChanged() { criterionChanged = true; return criterionChanged; } @Getter private List<AlgorithmWrapper> randomisationConfigs = new ArrayList<AlgorithmWrapper>(); @Getter @Setter private List<SimulationResult> simulationResults = new ArrayList<SimulationResult>(); @Getter @Setter private boolean simOnly; @Getter @Setter private boolean seedRandomisationAlgorithmB; @Getter @Setter private long seedRandomisationAlgorithm; @Getter private boolean changeStrataDistribution = false; public void setChangeStrataDistribution(boolean changeStrataDistribution) { createDistributedCriterions(); this.changeStrataDistribution = changeStrataDistribution; } @Getter @Setter private boolean simFromTrialCreationFirst = true; @Getter @Setter private SimulationResultFactorsOrderEnum selectedOrder = SimulationResultFactorsOrderEnum.SAT; public static enum SimulationResultFactorsOrderEnum { SAT("SAT"), STA("STA"), ATS("ATS"), AST("AST"); private String id = null; private SimulationResultFactorsOrderEnum(String id) { this.id = id; } @Override public String toString() { return this.id; } } @Getter @Setter private boolean collectRawData = false; private DistributionTrialSiteWrapper distributedTrialSites; private List<DistributedCriterionWrapper<Serializable, AbstractConstraint<Serializable>>> distributedCriterions; public DistributionTrialSiteWrapper getDistributionTrialSiteWrapper() { if (distributedTrialSites == null || distributedTrialSites.getTrialSitesRatioWrappers().size() != countTrialSites) { List<TrialSiteRatioWrapper> tRatioWrapper = new ArrayList<TrialSiteRatioWrapper>(); for (TrialSite site : currentObject.getParticipatingSites()) { tRatioWrapper.add(new TrialSiteRatioWrapper(site)); } distributedTrialSites = new DistributionTrialSiteWrapper( tRatioWrapper); } return distributedTrialSites; } public void setDistributedCriterions( List<DistributedCriterionWrapper<Serializable, AbstractConstraint<Serializable>>> distributedCriterions) { this.distributedCriterions = distributedCriterions; } public List<DistributedCriterionWrapper<Serializable, AbstractConstraint<Serializable>>> getDistributedCriterions() { if (distributedCriterions == null || distributedCriterions.size() != currentObject.getCriteria() .size()) { distributedCriterions = new ArrayList<DistributedCriterionWrapper<Serializable, AbstractConstraint<Serializable>>>(); // createDistributedCriterions(); } return distributedCriterions; } @SuppressWarnings({ "rawtypes", "unchecked" }) public void createDistributedCriterions(){ distributedCriterions.clear(); for (AbstractCriterion<? extends Serializable, ? extends AbstractConstraint<? extends Serializable>> c : currentObject .getCriteria()) { if (c.getStrata() != null) { List<DistributedConstraintWrapper> strataDistributions = new ArrayList<DistributedConstraintWrapper>(); for (AbstractConstraint<? extends Serializable> con : c .getStrata()) { strataDistributions .add(new DistributedConstraintWrapper(con)); } distributedCriterions.add(new DistributedCriterionWrapper( strataDistributions, new CriterionWrapper<Serializable>( (AbstractCriterion<Serializable, ?>) c, loginHandler.getChosenLocale()))); } } } public Trial getSimTrial() { if (simFromTrialCreationFirst && !simOnly) { currentObject = trialHandler.getCurrentObject(); try { /* Leading Trial Site & Sponsor Investigator */ currentObject.setLeadingSite(trialHandler.getLeadingSite()); if (trialHandler.getSponsorInvestigator() != null) currentObject.setSponsorInvestigator(trialHandler .getSponsorInvestigator().getPerson()); currentObject.setCriteria(configureCriteriaStep4()); simFromTrialCreationFirst = false; } catch (Exception e) { return null; } } else if (currentObject == null && simOnly) { currentObject = new Trial(); cleanTreatmentArms(); } if (simOnly && criterionChanged) { /* SubjectProperties Configuration - done in Step4 */ ValueExpression ve1 = FacesContext .getCurrentInstance() .getApplication() .getExpressionFactory() .createValueExpression( FacesContext.getCurrentInstance().getELContext(), "#{simulationSubjectProperty}", SimulationSubjectProperty.class); SimulationSubjectProperty currentSimulationSubjectProperty = (SimulationSubjectProperty) ve1 .getValue(FacesContext.getCurrentInstance().getELContext()); currentObject .setCriteria(addAllConfiguredCriteria(currentSimulationSubjectProperty .getCriteria())); criterionChanged = false; } return currentObject; } private List<CriterionWrapper<Serializable>> strata; @SuppressWarnings("unchecked") public List<CriterionWrapper<Serializable>> getStrata() { strata = new ArrayList<CriterionWrapper<Serializable>>(); for (AbstractCriterion<? extends Serializable, ? extends AbstractConstraint<? extends Serializable>> c : currentObject .getCriteria()) { strata.add(new CriterionWrapper<Serializable>( (AbstractCriterion<Serializable, ?>) c, loginHandler .getChosenLocale())); } return strata; } /** * Checks if any strata factors are defined. * * @return */ public boolean isStrataFactorsDefined() { for (AbstractCriterion<?, ?> c : currentObject.getCriteria()) { if (c.getStrata() != null) { if (c.getStrata().size() > 0) return true; } } return false; } public String getAlgName() { ResourceBundle bundle = ResourceBundle.getBundle( "de.randi2.jsf.i18n.algorithms", getLoginHandler() .getChosenLocale()); return bundle.getString(currentObject.getRandomizationConfiguration() .getClass().getCanonicalName() + ".name"); } public String getFurtherDetails() { StringBuffer furtherDetails = new StringBuffer(); ResourceBundle bundle = ResourceBundle.getBundle( "de.randi2.jsf.i18n.labels", getLoginHandler() .getChosenLocale()); if (BlockRandomizationConfig.class.isInstance(currentObject .getRandomizationConfiguration())) { BlockRandomizationConfig conf = BlockRandomizationConfig.class .cast(currentObject.getRandomizationConfiguration()); furtherDetails.append("<b>"); furtherDetails.append(bundle .getString("pages.blockR.variableBSize")); furtherDetails.append("</b> "); furtherDetails.append(conf.isVariableBlockSize()); furtherDetails.append("<br//>"); if (conf.isVariableBlockSize()) { furtherDetails.append("<b>"); furtherDetails.append(bundle .getString("pages.blockR.minBlockSize")); furtherDetails.append("</b> "); furtherDetails.append(conf.getMinimum()); furtherDetails.append("<br//>"); furtherDetails.append("<b>"); furtherDetails.append(bundle .getString("pages.blockR.maxBlockSize")); furtherDetails.append("</b> "); furtherDetails.append(conf.getMaximum()); furtherDetails.append("<br//>"); } else { furtherDetails.append("<b>"); furtherDetails.append(bundle .getString("pages.blockR.blockSize")); furtherDetails.append("</b> "); furtherDetails.append(conf.getMinimum()); furtherDetails.append("<br//>"); } } else if (UrnDesignConfig.class.isInstance(currentObject .getRandomizationConfiguration())) { UrnDesignConfig conf = UrnDesignConfig.class.cast(currentObject .getRandomizationConfiguration()); furtherDetails.append("<b>"); furtherDetails.append(bundle.getString("pages.urnR.initialCount")); furtherDetails.append("</b> "); furtherDetails.append(conf.getInitializeCountBalls()); furtherDetails.append("<br//>"); furtherDetails.append("<b>"); furtherDetails.append(bundle.getString("pages.urnR.replacedBalls")); furtherDetails.append("</b> "); furtherDetails.append(conf.getCountReplacedBalls()); furtherDetails.append("<br//>"); } else if (MinimizationConfig.class.isInstance(currentObject .getRandomizationConfiguration())) { MinimizationConfig conf = MinimizationConfig.class .cast(currentObject.getRandomizationConfiguration()); furtherDetails.append("<b>"); furtherDetails .append(bundle.getString("pages.minimization.pvalue")); furtherDetails.append("</b> "); furtherDetails.append(conf.getP()); furtherDetails.append("<br//>"); } else { furtherDetails.append("--"); } return furtherDetails.toString(); } /** * Specifies if the algorithm is stratified or not. * * @return */ public boolean isStratified() { boolean t = isStrataFactorsDefined(); if (t) return t; else return currentObject.isStratifyTrialSite(); } public void simTrial() { simulationResults = null; simResult = null; currentObject.setTreatmentArms(getTreatmentArms()); List<DistributionSubjectProperty> properties = new ArrayList<DistributionSubjectProperty>(); if (distributedCriterions != null) { for (DistributedCriterionWrapper<Serializable, AbstractConstraint<Serializable>> dcw : distributedCriterions) { properties.add(dcw.getDistributionSubjectProperty()); } } if (simOnly) { simulationResults = new ArrayList<SimulationResult>(); for (AlgorithmWrapper alg : randomisationConfigs) { currentObject.setRandomizationConfiguration(alg.getConf()); alg.getConf().setTempData(null); alg.getConf().setTrial(currentObject); if (seedRandomisationAlgorithmB) { alg.getConf().resetAlgorithm(seedRandomisationAlgorithm); } else { alg.getConf().resetAlgorithm(); } SimulationResult result = simulationService.simulateTrial( currentObject, properties, distributedTrialSites.getDistributionTrialSites(), runs, maxTime, collectRawData); result.setAlgorithmDescription(alg.getDescription()); simulationResults.add(result); } } else { SimulationResult result = simulationService.simulateTrial( currentObject, properties, distributedTrialSites.getDistributionTrialSites(), runs, maxTime, collectRawData); simResult = result; Randi2Page rPage = ((Randi2Page) FacesContext .getCurrentInstance() .getApplication() .getELResolver() .getValue(FacesContext.getCurrentInstance().getELContext(), null, "randi2Page")); rPage.simulationResult(null); } simulationConfigurationTabIndex = 0; } public boolean isResultComplete() { return simResult != null; } public boolean isResultsComplete() { return (simulationResults != null && !simulationResults.isEmpty()); } public boolean isSimulationComplete() { return isResultComplete() || isResultsComplete(); } public void addAlgorithm(ActionEvent event) { if (simulationAlgorithm.getSelectedAlgorithmPanelId().equals( AlgorithmConfig.AlgorithmPanelId.COMPLETE_RANDOMIZATION .toString())) { randomisationConfigs.add(new AlgorithmWrapper( new CompleteRandomizationConfig(), this, algorithmWrapperIdSequence++)); } else if (simulationAlgorithm.getSelectedAlgorithmPanelId().equals( AlgorithmConfig.AlgorithmPanelId.BIASEDCOIN_RANDOMIZATION .toString())) { randomisationConfigs.add(new AlgorithmWrapper( new BiasedCoinRandomizationConfig(), this, algorithmWrapperIdSequence++)); } else if (simulationAlgorithm.getSelectedAlgorithmPanelId() .equals(AlgorithmConfig.AlgorithmPanelId.BLOCK_RANDOMIZATION .toString())) { AlgorithmWrapper algWrapper = new AlgorithmWrapper( new BlockRandomizationConfig(), this, algorithmWrapperIdSequence++); algWrapper.getBlockR().setLoginHandler(getLoginHandler()); randomisationConfigs.add(algWrapper); } else if (simulationAlgorithm.getSelectedAlgorithmPanelId().equals( AlgorithmConfig.AlgorithmPanelId.TRUNCATED_RANDOMIZATION .toString())) { randomisationConfigs.add(new AlgorithmWrapper( new TruncatedBinomialDesignConfig(), this, algorithmWrapperIdSequence++)); } else if (simulationAlgorithm.getSelectedAlgorithmPanelId().equals( AlgorithmConfig.AlgorithmPanelId.URN_MODEL.toString())) { randomisationConfigs .add(new AlgorithmWrapper(new UrnDesignConfig(), this, algorithmWrapperIdSequence++)); } else if (simulationAlgorithm.getSelectedAlgorithmPanelId().equals( AlgorithmConfig.AlgorithmPanelId.MINIMIZATION.toString())) { randomisationConfigs.add(new AlgorithmWrapper( new MinimizationConfig(), this, algorithmWrapperIdSequence++)); } renameAlgorithmPossitions(); randomisationConfigs.get(randomisationConfigs.size() - 1).getBlockR() .setPossitionForSimulation(randomisationConfigs.size() - 1); } public void renameAlgorithmPossitions(){ int possition =1; for(AlgorithmWrapper algorithm : randomisationConfigs){ algorithm.setPossition(possition++); } } public void setCountTrialSites(int countTrialSites) { this.countTrialSites = countTrialSites; currentObject.setParticipatingSites(new HashSet<TrialSite>()); for (int i = 0; i < countTrialSites; i++) { TrialSite site = new TrialSite(); site.setName("Trial Site " + (i + 1)); currentObject.addParticipatingSite(site); } } public Resource getExportSimulationResults() { StringBuffer sb = new StringBuffer(); sb.append("<h2>Studie: " + currentObject.getName() + "</h2> \n"); sb.append("<h3>Sites:</h3>\n"); sb.append("<table border=1 width=200px><tr><th>Name</th><th>Ratio</th></tr>"); for (TrialSite site : currentObject.getParticipatingSites()) { sb.append("<tr><td>" + site.getName() + "</td><td>" + 1 + "</td></tr> \n"); } sb.append("</table>"); sb.append("<h3>Treatment Arms:</h3>\n"); sb.append("<table border=1 width=400px><tr><th>Name</th><th>Description</th><th>Ration</th></tr>\n"); for (TreatmentArm arm : currentObject.getTreatmentArms()) { sb.append(" <tr><td> " + arm.getName() + "</td>"); sb.append(" <td> " + arm.getDescription() + "</td>"); sb.append(" <td> " + arm.getPlannedSubjects() + "</td>" + "</tr>\n"); } sb.append("</table"); sb.append("<h3>Simulation runs: </h3>" + runs + " \n"); sb.append("<h3>Algorithms:</h3>\n"); sb.append("<table border=1 width=800px>" + "<tr>" + "<th>Type</th><th>Time in ms</th><th>min Marginal Balance</th> <th>mean Marginal Balance</th> <th>max Marginal Balance</th>" + "</tr>"); for (SimulationResult res : simulationResults) { sb.append(" <tr><td> " + res.getAlgConf().getClass().getSimpleName() + "</td>"); sb.append("<td> " + res.getDuration() + "</td>"); sb.append("<td>" + res.getMarginalBalanceMin() + "</td>"); sb.append("<td>" + res.getMarginalBalanceMean() + "</td>"); sb.append("<td>" + res.getMarginalBalanceMax() + "</td></tr>\n"); } sb.append("</table>"); sb.append("<table>"); sb.append("<table border=0><tr><th><h3>Details Arms</h3></th></tr>\n"); for (SimulationResult res : simulationResults) { sb.append("<tr><th>" + res.getAlgConf().getClass().getSimpleName() + "</th></tr>"); sb.append("<tr><td>"); sb.append("<table border=1 width=800px><tr><th>Arm name</th><th>min</th>" + "<th>min per cent</th><th>max</th><th>max per cent</th><th>mean</th>" + "<th>median</th></tr>"); for (SimulationResultArm simArm : res.getSimResultArms()) { sb.append("<tr><td>" + simArm.getArm().getName() + "</td>"); sb.append("<td>" + simArm.getMin() + "</td>"); sb.append("<td>" + simArm.getMinPercentString() + "</td>"); sb.append("<td>" + simArm.getMax() + "</td>"); sb.append("<td>" + simArm.getMaxPercentString() + "</td>"); sb.append("<td>" + simArm.getMean() + "</td>"); sb.append("<td>" + simArm.getMedian() + "</td></tr>\n"); } sb.append("</table>"); sb.append("</td></tr>"); } sb.append("</table>"); sb.append("<h3>Details Subgroups:</h3>"); sb.append("<table border=1 width=800px><tr><th>Algorithm</th><th>Treatment arm</th><th>Subgroup</th><th>min</th><th>mean</th><th>max</th></tr>\n"); SimulationResultFactorsOrderEnum temp = selectedOrder; selectedOrder = SimulationResultFactorsOrderEnum.ATS; List<StrataResultWrapper> listWrapper = getAllStrataResults(); for (int i = 0; i < listWrapper.size(); i++) { sb.append("<tr>"); // new Algorithm if (i % (listWrapper.size() / simulationResults.size()) == 0) { sb.append("<td rowspan=\" " + (listWrapper.size() / simulationResults.size()) + "\">" + listWrapper.get(i).getAlgorithmName() + "</td>"); } if (i % ((listWrapper.size() / simulationResults.size()) / currentObject .getTreatmentArms().size()) == 0) { sb.append("<td rowspan=\" " + ((listWrapper.size() / simulationResults.size()) / currentObject .getTreatmentArms().size()) + "\">" + listWrapper.get(i).getTreatmentName() + "</td>"); } sb.append("<td>" + listWrapper.get(i).getStrataName() + "</td>"); sb.append("<td>" + listWrapper.get(i).getMinCount() + "</td>"); sb.append("<td>" + listWrapper.get(i).getMean() + "</td>"); sb.append("<td>" + listWrapper.get(i).getMaxCount() + "</td>"); sb.append("</tr>"); } selectedOrder = temp; sb.append("</table>"); return new MyStringResource("simulationResult.html", sb.toString()); } public Resource getExportSimulationRawData() { StringBuffer sb = new StringBuffer(); for (SimulationResult simRes : simulationResults) { sb.append(simRes.getAlgorithmDescription() + ":\n"); for (SimulationRawDataEntry entry : simRes.getRawData()) { sb.append(entry.getRun() + ";"); sb.append(entry.getCount() + ";"); sb.append(entry.getTreatmentArm() + ";"); sb.append(entry.getTrialSite() + ";"); String stratumNameComp = simRes.getStrataIdNames().get( entry.getStratum()); String stratumName = stratumNameComp.substring((stratumNameComp .lastIndexOf("|") + 1)); sb.append(stratumName + "\n"); } sb.append("-------------------------------------------\n"); } return new MyStringResource("rawData.csv", sb.toString()); } public List<StrataResultWrapper> getAllStrataResults() { List<StrataResultWrapper> wrapper = new ArrayList<StrataResultWrapper>(); if (simulationResults != null) { for (SimulationResult simRes : simulationResults) { for (SimulationResultArm simArm : simRes.getSimResultArms()) { wrapper.addAll(simArm.getStrataResults()); } } if (selectedOrder == SimulationResultFactorsOrderEnum.SAT) { Collections.sort(wrapper, new StrataResultComperatorSAT()); } else if (selectedOrder == SimulationResultFactorsOrderEnum.STA) { Collections.sort(wrapper, new StrataResultComperatorSTA()); } else if (selectedOrder == SimulationResultFactorsOrderEnum.ATS) { Collections.sort(wrapper, new StrataResultComperatorATS()); } if (selectedOrder == SimulationResultFactorsOrderEnum.AST) { Collections.sort(wrapper, new StrataResultComperatorAST()); } } return wrapper; } public boolean isSta() { return selectedOrder == SimulationResultFactorsOrderEnum.STA; } public boolean isSat() { return selectedOrder == SimulationResultFactorsOrderEnum.SAT; } public boolean isAts() { return selectedOrder == SimulationResultFactorsOrderEnum.ATS; } public boolean isAst() { return selectedOrder == SimulationResultFactorsOrderEnum.AST; } public SelectItem[] getOrderItems() { SelectItem[] items = new SelectItem[SimulationResultFactorsOrderEnum .values().length]; for (int i = 0; i < SimulationResultFactorsOrderEnum.values().length; i++) { items[i] = new SelectItem( SimulationResultFactorsOrderEnum.values()[i]); } return items; } private class MyStringResource implements Resource, Serializable { private static final long serialVersionUID = 2523708207015651805L; private String resourceName; private String content; private final Date lastModified; @Override public String calculateDigest() { return resourceName; } @Override public Date lastModified() { return lastModified; } @Override public InputStream open() throws IOException { return new ByteArrayInputStream(content.getBytes()); } @Override public void withOptions(Options arg0) throws IOException { } public MyStringResource(String resourceName, String content) { this.resourceName = resourceName; this.content = content; this.lastModified = new Date(); } } }