Java tutorial
/* * Copyright (C) 2012 Tim Vaughan <tgvaughan@gmail.com> * * This program 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 program 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 program. If not, see <http://www.gnu.org/licenses/>. */ package master.outputs; import beast.core.BEASTObject; import beast.core.Input; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import master.Ensemble; import master.EnsembleSpec; import master.EnsembleSummary; import master.EnsembleSummarySpec; import master.model.Moment; import master.model.MomentGroup; import master.model.Population; import master.model.PopulationState; import master.model.PopulationType; import master.model.StateSummary; import master.Trajectory; import master.TrajectorySpec; import master.InheritanceEnsemble; import master.InheritanceEnsembleSpec; import master.InheritanceTrajectory; import com.fasterxml.jackson.databind.ObjectMapper; /** * Class containing static methods for writing trajectory, ensemble * and ensemble summary results to a given PrintStream using a versatile * JSON format. * * @author Tim Vaughan <tgvaughan@gmail.com> */ public class JsonOutput extends BEASTObject implements TrajectoryOutput, EnsembleOutput, EnsembleSummaryOutput, InheritanceTrajectoryOutput, InheritanceEnsembleOutput { public Input<String> fileNameInput = new Input<String>("fileName", "Name of file to write to.", Input.Validate.REQUIRED); PrintStream pstream; /** * Default constructor. */ public JsonOutput() { } @Override public void initAndValidate() { try { pstream = new PrintStream(fileNameInput.get()); } catch (FileNotFoundException e) { throw new RuntimeException("File " + fileNameInput.get() + " not found."); } } /** * Express a given trajectory as a JSON-formatted string and send the * result to a PrintStream. * * @param trajectory Trajectory to dump. */ @Override public void write(Trajectory trajectory) { if (trajectory.getSpec().getVerbosity() > 0) System.out.println("Writing JSON output..."); HashMap<String, Object> outputData = Maps.newHashMap(); TrajectorySpec spec = trajectory.getSpec(); List<PopulationState> sampledStates = trajectory.getSampledStates(); for (PopulationType type : spec.getModel().getPopulationTypes()) { int[] loc = new int[type.getDims().length]; for (int d = 0; d < loc.length; d++) loc[d] = 0; outputData.put(type.getName(), iterateOverLocs(sampledStates, type, loc, 0)); } // Add list of sampling times to output object: outputData.put("t", trajectory.getSampledTimes()); // Add trajectory logP to output object: if (trajectory.getSpec().isTrajLogPRecordingOn()) outputData.put("trajLogP", trajectory.getTrajLogP()); // Record spec parameters to object output: outputData.put("sim", spec); ObjectMapper mapper = new ObjectMapper(); try { pstream.println(mapper.writeValueAsString(outputData)); } catch (IOException ex) { System.err.println(ex); } } /** * Express a given trajectory ensemble as a JSON-formatted string and send * the result to a PrintStream. * * @param ensemble Trajectory ensemble to dump. */ @Override public void write(Ensemble ensemble) { if (ensemble.getSpec().getVerbosity() > 0) System.out.println("Writing JSON output..."); HashMap<String, Object> outputData = Maps.newHashMap(); EnsembleSpec spec = ensemble.getSpec(); List<Object> trajData = Lists.newArrayList(); for (Trajectory trajectory : ensemble.getTrajectories()) { HashMap<String, Object> thisTrajData = Maps.newHashMap(); List<PopulationState> sampledStates = trajectory.getSampledStates(); for (PopulationType type : spec.getModel().getPopulationTypes()) { int[] loc = new int[type.getDims().length]; for (int d = 0; d < loc.length; d++) loc[d] = 0; thisTrajData.put(type.getName(), iterateOverLocs(sampledStates, type, loc, 0)); } // Add list of sampling times to output object: thisTrajData.put("t", trajectory.getSampledTimes()); // Add trajectory logP to output object: if (trajectory.getSpec().isTrajLogPRecordingOn()) thisTrajData.put("trajLogP", trajectory.getTrajLogP()); trajData.add(thisTrajData); } outputData.put("trajectories", trajData); // Record spec parameters to object output: outputData.put("sim", spec); ObjectMapper mapper = new ObjectMapper(); try { pstream.println(mapper.writeValueAsString(outputData)); } catch (IOException ex) { System.err.println(ex); } } /** * Express a given ensemble summary as a JSON-formatted string and send * the result to a PrintStream. * * @param ensembleSummary Ensemble summary to dump. */ @Override public void write(EnsembleSummary ensembleSummary) { if (ensembleSummary.getSpec().getVerbosity() > 0) System.out.println("Writing JSON output..."); HashMap<String, Object> outputData = Maps.newHashMap(); EnsembleSummarySpec spec = ensembleSummary.getSpec(); StateSummary[] stateSummaries = ensembleSummary.getStateSummaries(); // Construct an object containing the summarized // data. Heirarchy is moment->[mean/std]->schema->estimate. for (MomentGroup momentGroup : spec.getMomentGroups()) { Map<String, Object> momentGroupData = Maps.newHashMap(); ArrayList<Object> meanData = Lists.newArrayList(); for (int schema = 0; schema < stateSummaries[0].getGroupMeans().get(momentGroup).length; schema++) { List<Double> schemaData = Lists.newArrayList(); for (StateSummary stateSummary : stateSummaries) schemaData.add(stateSummary.getGroupMeans().get(momentGroup)[schema]); meanData.add(schemaData); } momentGroupData.put("mean", meanData); List<Object> stdData = Lists.newArrayList(); for (int schema = 0; schema < stateSummaries[0].getGroupStds().get(momentGroup).length; schema++) { List<Double> schemaData = Lists.newArrayList(); for (StateSummary stateSummary : stateSummaries) schemaData.add(stateSummary.getGroupStds().get(momentGroup)[schema]); stdData.add(schemaData); } momentGroupData.put("std", stdData); outputData.put(momentGroup.getName(), momentGroupData); } for (Moment moment : spec.getMoments()) { Map<String, Object> momentData = Maps.newHashMap(); List<Object> meanData = Lists.newArrayList(); List<Double> schemaData = Lists.newArrayList(); for (StateSummary stateSummary : stateSummaries) schemaData.add(stateSummary.getMeans().get(moment)); meanData.add(schemaData); momentData.put("mean", meanData); List<Object> stdData = Lists.newArrayList(); schemaData = Lists.newArrayList(); for (StateSummary stateSummary : stateSummaries) schemaData.add(stateSummary.getStds().get(moment)); stdData.add(schemaData); momentData.put("std", stdData); outputData.put(moment.getName(), momentData); } // Add list of sampling times to output object: ArrayList<Double> tData = Lists.newArrayList(); double dT = spec.getSampleDt(); for (int sidx = 0; sidx < stateSummaries.length; sidx++) tData.add(dT * sidx); outputData.put("t", tData); // Record spec parameters to object output: outputData.put("sim", spec); ObjectMapper mapper = new ObjectMapper(); try { pstream.println(mapper.writeValueAsString(outputData)); } catch (IOException ex) { System.err.println(ex); } } /** * Express a given trajectory ensemble as a JSON-formatted string and send * the result to a PrintStream. * * @param iensemble Trajectory ensemble to dump. */ @Override public void write(InheritanceEnsemble iensemble) { HashMap<String, Object> outputData = Maps.newHashMap(); if (iensemble.getSpec().getVerbosity() > 0) System.out.println("Writing JSON output..."); InheritanceEnsembleSpec spec = iensemble.getSpec(); List<Object> trajData = Lists.newArrayList(); for (Trajectory trajectory : iensemble.getTrajectories()) { HashMap<String, Object> thisTrajData = Maps.newHashMap(); List<PopulationState> sampledStates = trajectory.getSampledStates(); for (PopulationType type : spec.getModel().getPopulationTypes()) { int[] loc = new int[type.getDims().length]; for (int d = 0; d < loc.length; d++) loc[d] = 0; thisTrajData.put(type.getName(), iterateOverLocs(sampledStates, type, loc, 0)); } // Add list of sampling times to output object: thisTrajData.put("t", trajectory.getSampledTimes()); // Add trajectory logP to output object: if (trajectory.getSpec().isTrajLogPRecordingOn()) thisTrajData.put("trajLogP", trajectory.getTrajLogP()); trajData.add(thisTrajData); } outputData.put("trajectories", trajData); // Record spec parameters to object output: outputData.put("sim", spec); ObjectMapper mapper = new ObjectMapper(); try { pstream.println(mapper.writeValueAsString(outputData)); } catch (IOException ex) { System.err.println(ex); } } @Override public void write(InheritanceTrajectory inheritanceTrajectory) { write((Trajectory) inheritanceTrajectory); } /** * Private method for iteration over locations. * * @param sampledStates * @param type * @param loc * @param depth * @return */ private Object iterateOverLocs(List<PopulationState> sampledStates, PopulationType type, int[] loc, int depth) { if (depth < type.getDims().length) { List<Object> nestedData = Lists.newArrayList(); for (int i = 0; i < type.getDims()[depth]; i++) { loc[depth] = i; nestedData.add(iterateOverLocs(sampledStates, type, loc, depth + 1)); } return nestedData; } else { List<Object> stateList = Lists.newArrayList(); for (PopulationState state : sampledStates) stateList.add(state.get(new Population(type, loc))); return stateList; } } }