1 package net.sf.openrocket.file;
3 import java.io.IOException;
4 import java.io.OutputStream;
5 import java.io.PrintWriter;
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.Comparator;
11 import net.sf.openrocket.aerodynamics.Warning;
12 import net.sf.openrocket.aerodynamics.WarningSet;
13 import net.sf.openrocket.document.Simulation;
14 import net.sf.openrocket.simulation.FlightData;
15 import net.sf.openrocket.simulation.FlightDataBranch;
16 import net.sf.openrocket.simulation.FlightEvent;
17 import net.sf.openrocket.simulation.FlightDataBranch.Type;
18 import net.sf.openrocket.unit.Unit;
19 import net.sf.openrocket.util.Pair;
20 import net.sf.openrocket.util.TextUtil;
22 public class CSVExport {
25 * Exports the specified flight data branch into a CSV file.
27 * @param stream the stream to write to.
28 * @param simulation the simulation being exported.
29 * @param branch the branch to export.
30 * @param fields the fields to export (in appropriate order).
31 * @param units the units of the fields.
32 * @param fieldSeparator the field separator string.
33 * @param commentStarter the comment starting character(s).
34 * @param simulationComments whether to output general simulation comments.
35 * @param fieldComments whether to output field comments.
36 * @param eventComments whether to output comments for the flight events.
37 * @throws IOException if an I/O exception occurs.
39 public static void exportCSV(OutputStream stream, Simulation simulation,
40 FlightDataBranch branch, FlightDataBranch.Type[] fields, Unit[] units,
41 String fieldSeparator,String commentStarter, boolean simulationComments,
42 boolean fieldComments, boolean eventComments) throws IOException {
44 if (fields.length != units.length) {
45 throw new IllegalArgumentException("fields and units lengths must be equal " +
46 "(" + fields.length + " vs " + units.length + ")");
50 PrintWriter writer = null;
53 writer = new PrintWriter(stream);
55 // Write the initial comments
56 if (simulationComments) {
57 writeSimulationComments(writer, simulation, branch, fields, commentStarter);
60 if (simulationComments && fieldComments) {
61 writer.println(commentStarter);
65 writer.print(commentStarter + " ");
66 for (int i=0; i < fields.length; i++) {
67 writer.print(fields[i].getName() + " (" + units[i].getUnit() + ")");
68 if (i < fields.length-1) {
69 writer.print(fieldSeparator);
75 writeData(writer, branch, fields, units, fieldSeparator,
76 eventComments, commentStarter);
83 } catch (Exception e) {
90 private static void writeData(PrintWriter writer, FlightDataBranch branch,
91 Type[] fields, Unit[] units, String fieldSeparator, boolean eventComments,
92 String commentStarter) {
94 // Number of data points
95 int n = branch.getLength();
97 // Flight events in occurrance order
98 List<Pair<Double, FlightEvent>> events = branch.getEvents();
99 Collections.sort(events, new Comparator<Pair<Double, FlightEvent>>() {
101 public int compare(Pair<Double, FlightEvent> o1, Pair<Double, FlightEvent> o2) {
102 return Double.compare(o1.getU(), o2.getU());
105 int eventPosition = 0;
107 // List of field values
108 List<List<Double>> fieldValues = new ArrayList<List<Double>>();
109 for (Type t: fields) {
110 fieldValues.add(branch.get(t));
114 List<Double> time = branch.get(FlightDataBranch.TYPE_TIME);
115 if (eventComments && time == null) {
116 // If time information is not available, print events at beginning of file
117 for (Pair<Double, FlightEvent> e: events) {
118 printEvent(writer, e, commentStarter);
120 eventPosition = events.size();
124 // Loop over all data points
125 for (int pos=0; pos<n; pos++) {
127 // Check for events to store
128 if (eventComments && time != null) {
129 double t = time.get(pos);
131 while ((eventPosition < events.size()) &&
132 (events.get(eventPosition).getU() <= t)) {
133 printEvent(writer, events.get(eventPosition), commentStarter);
139 for (int i=0; i < fields.length; i++) {
140 double value = fieldValues.get(i).get(pos);
141 writer.print(TextUtil.doubleToString(units[i].toUnit(value)));
142 if (i < fields.length-1) {
143 writer.print(fieldSeparator);
150 // Store any remaining events
151 if (eventComments && time != null) {
152 while (eventPosition < events.size()) {
153 printEvent(writer, events.get(eventPosition), commentStarter);
161 private static void printEvent(PrintWriter writer, Pair<Double, FlightEvent> e,
162 String commentStarter) {
163 writer.println(commentStarter + " Event " + e.getV().getType().name() +
164 " occurred at t=" + TextUtil.doubleToString(e.getU()) + " seconds");
167 private static void writeSimulationComments(PrintWriter writer,
168 Simulation simulation, FlightDataBranch branch, Type[] fields,
169 String commentStarter) {
173 line = simulation.getName();
175 FlightData data = simulation.getSimulatedData();
177 switch (simulation.getStatus()) {
179 line += " (Up to date)";
183 line += " (Data loaded from a file)";
187 line += " (Data is out of date)";
191 line += " (Imported data)";
195 line += " (Not simulated yet)";
199 writer.println(commentStarter + " " + line);
202 writer.println(commentStarter + " " + branch.getLength() + " data points written for "
203 + fields.length + " variables.");
207 writer.println(commentStarter + " No simulation data available.");
210 WarningSet warnings = data.getWarningSet();
212 if (!warnings.isEmpty()) {
213 writer.println(commentStarter + " Simulation warnings:");
214 for (Warning w: warnings) {
215 writer.println(commentStarter + " " + w.toString());