Updates for 0.9.3
[debian/openrocket] / src / net / sf / openrocket / file / CSVExport.java
1 package net.sf.openrocket.file;
2
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;
9 import java.util.List;
10
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;
21
22 public class CSVExport {
23
24         /**
25          * Exports the specified flight data branch into a CSV file.
26          * 
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.
38          */
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 {
43                 
44                 if (fields.length != units.length) {
45                         throw new IllegalArgumentException("fields and units lengths must be equal " +
46                                         "(" + fields.length + " vs " + units.length + ")");
47                 }
48                 
49                 
50                 PrintWriter writer = null;
51                 try {
52                         
53                         writer = new PrintWriter(stream);
54                         
55                         // Write the initial comments
56                         if (simulationComments) {
57                                 writeSimulationComments(writer, simulation, branch, fields, commentStarter);
58                         }
59                         
60                         if (simulationComments && fieldComments) {
61                                 writer.println(commentStarter);
62                         }
63                         
64                         if (fieldComments) {
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);
70                                         }
71                                 }
72                                 writer.println();
73                         }
74                         
75                         writeData(writer, branch, fields, units, fieldSeparator, 
76                                         eventComments, commentStarter);
77                         
78                         
79                 } finally {
80                         if (writer != null) {
81                                 try {
82                                         writer.close();
83                                 } catch (Exception e) {
84                                         e.printStackTrace();
85                                 }
86                         }
87                 }
88         }
89
90         private static void writeData(PrintWriter writer, FlightDataBranch branch,
91                         Type[] fields, Unit[] units, String fieldSeparator, boolean eventComments,
92                         String commentStarter) {
93                 
94                 // Number of data points
95                 int n = branch.getLength();
96                 
97                 // Flight events in occurrance order
98                 List<Pair<Double, FlightEvent>> events = branch.getEvents();
99                 Collections.sort(events, new Comparator<Pair<Double, FlightEvent>>() {
100                         @Override
101                         public int compare(Pair<Double, FlightEvent> o1, Pair<Double, FlightEvent> o2) {
102                                 return Double.compare(o1.getU(), o2.getU());
103                         }
104                 });
105                 int eventPosition = 0;
106                 
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));
111                 }
112                 
113                 // Time variable
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);
119                         }
120                         eventPosition = events.size();
121                 }
122                 
123                 
124                 // Loop over all data points
125                 for (int pos=0; pos<n; pos++) {
126                         
127                         // Check for events to store
128                         if (eventComments && time != null) {
129                                 double t = time.get(pos);
130                                 
131                                 while ((eventPosition < events.size()) && 
132                                                 (events.get(eventPosition).getU() <= t)) {
133                                         printEvent(writer, events.get(eventPosition), commentStarter);
134                                         eventPosition++;
135                                 }
136                         }
137                         
138                         // Store CSV line
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);
144                                 }
145                         }
146                         writer.println();
147                         
148                 }
149                 
150                 // Store any remaining events
151                 if (eventComments && time != null) {
152                         while (eventPosition < events.size()) {
153                                 printEvent(writer, events.get(eventPosition), commentStarter);
154                                 eventPosition++;
155                         }
156                 }
157                 
158         }
159
160         
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");
165         }
166
167         private static void writeSimulationComments(PrintWriter writer,
168                         Simulation simulation, FlightDataBranch branch, Type[] fields, 
169                         String commentStarter) {
170                 
171                 String line;
172                 
173                 line = simulation.getName();
174
175                 FlightData data = simulation.getSimulatedData();
176                 
177                 switch (simulation.getStatus()) {
178                 case UPTODATE:
179                         line += " (Up to date)";
180                         break;
181                         
182                 case LOADED:
183                         line += " (Data loaded from a file)";
184                         break;
185                         
186                 case OUTDATED:
187                         line += " (Data is out of date)";
188                         break;
189                         
190                 case EXTERNAL:
191                         line += " (Imported data)";
192                         break;
193                         
194                 case NOT_SIMULATED:
195                         line += " (Not simulated yet)";
196                         break;
197                 }
198                 
199                 writer.println(commentStarter + " " + line);
200                 
201
202                 writer.println(commentStarter + " " + branch.getLength() + " data points written for "
203                                 + fields.length + " variables.");
204                 
205                 
206                 if (data == null) {
207                         writer.println(commentStarter + " No simulation data available.");
208                         return;
209                 }
210                 WarningSet warnings = data.getWarningSet();
211                 
212                 if (!warnings.isEmpty()) {
213                         writer.println(commentStarter + " Simulation warnings:");
214                         for (Warning w: warnings) {
215                                 writer.println(commentStarter + "   " + w.toString());
216                         }
217                 }
218         }
219         
220 }