Code Examples
A repository of 155 code examples for BeepBeep
PlotSpeed.java
1 package voyager;
2 
3 import plots.BitmapJFrame;
4 import ca.uqac.lif.cep.Connector;
5 import static ca.uqac.lif.cep.Connector.BOTTOM;
6 import static ca.uqac.lif.cep.Connector.INPUT;
7 import static ca.uqac.lif.cep.Connector.OUTPUT;
8 import static ca.uqac.lif.cep.Connector.TOP;
9 import ca.uqac.lif.cep.functions.ApplyFunction;
10 import ca.uqac.lif.cep.functions.Constant;
11 import ca.uqac.lif.cep.functions.FunctionTree;
12 import ca.uqac.lif.cep.functions.StreamVariable;
13 import ca.uqac.lif.cep.io.ReadLines;
14 import ca.uqac.lif.cep.mtnp.DrawPlot;
15 import ca.uqac.lif.cep.mtnp.UpdateTableStream;
16 import ca.uqac.lif.cep.signal.Limit;
17 import ca.uqac.lif.cep.signal.PeakFinderLocalMaximum;
18 import ca.uqac.lif.cep.signal.Smooth;
19 import ca.uqac.lif.cep.signal.Threshold;
20 import ca.uqac.lif.cep.tmf.CountDecimate;
21 import ca.uqac.lif.cep.tmf.Fork;
22 import ca.uqac.lif.cep.tmf.KeepLast;
23 import ca.uqac.lif.cep.tmf.Pump;
24 import ca.uqac.lif.cep.tmf.Splice;
25 import ca.uqac.lif.cep.tmf.Trim;
26 import ca.uqac.lif.cep.util.NthElement;
27 import ca.uqac.lif.cep.util.Numbers;
28 import ca.uqac.lif.cep.util.Strings;
29 import ca.uqac.lif.mtnp.plot.TwoDimensionalPlot.Axis;
30 import ca.uqac.lif.mtnp.plot.gral.Scatterplot;
31 
32 /**
33  * Detect planetary encounters of
34  * <a href="https://en.wikipedia.org/wiki/Voyager_2">Voyager 2</a> by analyzing
35  * its distance from the Earth.
36  * <p>
37  * In this example, we read a processed data feed that provides averaged
38  * hourly readings of various instruments in the spacecraft. We are
39  * interested in the date and the relative distance to Earth, expressed in
40  * astronomical units (AU). From these two data fields, we compute the
41  * average weekly speed (in AU/week), and send the output stream to signal
42  * processors that detect peaks (i.e. abrupt variations in the values of
43  * a numerical signal). This is shown in a plot.
44  * <p>
45  * One can see that the last three peaks correspond precisely to the dates of
46  * Voyager's flybys of Jupiter, Saturn, and Neptune:
47  * <p>
48  * <table>
49  * <tr><td>Planet</td><td>Date</td><td>Days after 77/1/1</td></tr>
50  * <tr><td>Jupiter</td><td>July 9, 1979</td><td>918</td></tr>
51  * <tr><td>Saturn</td><td>August 25, 1981</td><td>1696</td></tr>
52  * <tr><td>Neptune</td><td>August 25, 1989</td><td>4618</td></tr>
53  * </table>
54  * <p>
55  * The flyby of Uranus (Jaunary 24, 1986, or Day 3310) does not produce
56  * a speed variation large enough to be detected through this method.
57  *
58  * <h4>About the data files</h4>
59  * <p>This example requires you to first download some data files from the
60  * Voyager 2 space probe; these files are publicly available on a NASA FTP
61  * site:
62  * <p>
63  * <a href="ftp://spdf.gsfc.nasa.gov/pub/data/voyager/voyager2/merged/">ftp://spdf.gsfc.nasa.gov/pub/data/voyager/voyager2/merged/</a>
64  * <p>
65  * @author Sylvain HallĂ©
66  */
67 public class PlotSpeed
68 {
69  public static void main(String[] args) {
70  ///
71  int start_year = 1977, end_year = 1992;
72 
73  /* The Voyager data is split into multiple CSV files, one per civil
74  * year. Let us create one ReadLines processor for each file. */
75  ReadLines[] readers = new ReadLines[end_year - start_year + 1];
76  for (int y = start_year; y <= end_year; y++) {
77  readers[y - start_year] = new ReadLines(
78  PlotSpeed.class.getResourceAsStream(
79  "data/vy2_" + y + ".asc"));
80  }
81 
82  /* Pass this array of readers to the Splice processors, so that their
83  * contents be used as an uninterrupted stream of events. */
84  Splice spl = new Splice(readers);
85 
86  /* The input files have hourly readings; keep only one reading per week. */
87  CountDecimate cd = new CountDecimate(24 * 7);
88  Connector.connect(spl, cd);
89 
90  /* The 1977 file has no data before week 31 or so (the launch date);
91  * let's ignore these first lines. */
92  Trim ignore_beginning = new Trim(31);
93  Connector.connect(cd, ignore_beginning);
94 
95  /* Split the surviving lines into arrays with the TAB character. */
96  ApplyFunction to_array = new ApplyFunction(
97  new Strings.SplitString("\\s+"));
98  Connector.connect(ignore_beginning, to_array);
99  ///
100 
101  /* Fork this stream of arrays in three. */
102  //!
103  Fork fork = new Fork(3);
104  Connector.connect(to_array, fork);
105 
106  /* From first stream, format date */
107  ApplyFunction format_date = new ApplyFunction(new FunctionTree(
108  FormatDate.instance, new FunctionTree(
109  new NthElement(0), StreamVariable.X),
110  new FunctionTree(new NthElement(1), StreamVariable.X)));
111  Connector.connect(fork, 0, format_date, INPUT);
112 
113  /* From second stream, extract distance */
114  ApplyFunction get_au1 = new ApplyFunction(new FunctionTree(
115  Numbers.numberCast, new FunctionTree(
116  new NthElement(3), StreamVariable.X)));
117  Connector.connect(fork, 1, get_au1, INPUT);
118 
119  /* Delay third stream by one reading, and extract distance */
120  Trim cd_delay = new Trim(1);
121  Connector.connect(fork, 2, cd_delay, INPUT);
122  ApplyFunction get_au2 = new ApplyFunction(new FunctionTree(
123  Numbers.numberCast, new FunctionTree(
124  new NthElement(3), StreamVariable.X)));
125  Connector.connect(cd_delay, get_au2);
126 
127  /* Subtract third and second streams, giving the weekly distance
128  * travelled. */
129  ApplyFunction distance = new ApplyFunction(new FunctionTree(
130  Numbers.maximum, Constant.ZERO, new FunctionTree(
131  Numbers.subtraction,
132  StreamVariable.X, StreamVariable.Y)));
133  Connector.connect(get_au2, OUTPUT, distance, TOP);
134  Connector.connect(get_au1, OUTPUT, distance, BOTTOM);
135 
136  /* Since the weekly distance is very close to the measurement's
137  * precision, smoothen those values by averaging each two successive
138  * points. */
139  Smooth smooth = new Smooth(2);
140  Connector.connect(distance, smooth);
141 
142  Fork f2 = new Fork(2);
143  Connector.connect(smooth, f2);
144  PeakFinderLocalMaximum peak = new PeakFinderLocalMaximum(5);
145  //Passthrough peak = new Passthrough();
146  Connector.connect(f2, BOTTOM, peak, INPUT);
147  Threshold th = new Threshold(0.0125f);
148  Connector.connect(peak, th);
149  Limit li = new Limit(5);
150  Connector.connect(th, li);
151 
152  UpdateTableStream table = new UpdateTableStream("Date",
153  "Speed (AU/week)", "Peak");
154 
155  Connector.connect(format_date, OUTPUT, table, 0);
156  Connector.connect(f2, OUTPUT, table, 1);
157  Connector.connect(li, OUTPUT, table, 2);
158  //!
159 
160  //*
161  Pump pump = new Pump();
162  Connector.connect(table, pump);
163 
164  KeepLast last = new KeepLast(1);
165  Connector.connect(pump, last);
166  Scatterplot plot = new Scatterplot();
167  plot.setCaption(Axis.X, "Days after 1/1/77")
168  .setCaption(Axis.Y, "AU");
169 
170  DrawPlot draw = new DrawPlot(plot);
171  Connector.connect(last, draw);
172 
173  BitmapJFrame window = new BitmapJFrame();
174  Connector.connect(draw, window);
175  window.start();
176  pump.start();
177  //*
178  }
179 }
static final FormatDate instance
The single publicly accessible instance of this function.
Definition: FormatDate.java:32
Receives two arguments: one of a year number, and another with a number of days in the year...
Definition: FormatDate.java:27
Detect planetary encounters of Voyager 2 by analyzing its distance from the Earth.
Definition: PlotSpeed.java:67
Generate tables, charts and plots from event streams.
Receives a byte array as an input, and shows it in a Swing window as a picture.