Skip to content

Commit b80accd

Browse files
committed
continued TAO reader
1 parent 6cca815 commit b80accd

File tree

5 files changed

+488
-12
lines changed

5 files changed

+488
-12
lines changed

core/src/main/java/com/bc/fiduceo/reader/insitu/tao/TaoReader.java

Lines changed: 172 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,28 @@
22

33
import com.bc.fiduceo.core.Dimension;
44
import com.bc.fiduceo.core.Interval;
5+
import com.bc.fiduceo.core.NodeType;
56
import com.bc.fiduceo.geometry.Polygon;
67
import com.bc.fiduceo.location.PixelLocator;
78
import com.bc.fiduceo.reader.AcquisitionInfo;
89
import com.bc.fiduceo.reader.Reader;
910
import com.bc.fiduceo.reader.time.TimeLocator;
10-
import com.bc.fiduceo.util.NetCDFUtils;
11+
import com.bc.fiduceo.reader.time.TimeLocator_MillisSince1970;
1112
import com.bc.fiduceo.util.VariableProxy;
13+
import org.esa.snap.core.util.StringUtils;
1214
import ucar.ma2.Array;
1315
import ucar.ma2.ArrayInt;
1416
import ucar.ma2.DataType;
1517
import ucar.ma2.InvalidRangeException;
1618
import ucar.nc2.Attribute;
1719
import ucar.nc2.Variable;
1820

21+
import java.io.BufferedReader;
1922
import java.io.File;
23+
import java.io.FileReader;
2024
import java.io.IOException;
2125
import java.util.ArrayList;
26+
import java.util.Date;
2227
import java.util.List;
2328

2429
import static com.bc.fiduceo.util.NetCDFUtils.*;
@@ -27,19 +32,79 @@ class TaoReader implements Reader {
2732

2833
private final static String REG_EX = "(?:TAO|TRITON)_\\w+_\\w+(-\\w+)??\\d{4}-\\d{2}.txt";
2934

35+
private ArrayList<TaoRecord> records;
36+
private TimeLocator timeLocator;
37+
38+
static TaoRecord parseLine(String line) {
39+
line = line.replaceAll(" +", " "); // ensure that we only have single blanks as separator tb 2023-04-28
40+
final String[] tokens = StringUtils.split(line, new char[]{' '}, true);
41+
42+
final TaoRecord record = new TaoRecord();
43+
record.time = Integer.parseInt(tokens[0]);
44+
record.longitude = Float.parseFloat(tokens[1]);
45+
record.latitude = Float.parseFloat(tokens[2]);
46+
record.SSS = Float.parseFloat(tokens[3]);
47+
record.SST = Float.parseFloat(tokens[4]);
48+
record.AIRT = Float.parseFloat(tokens[5]);
49+
record.RH = Float.parseFloat(tokens[6]);
50+
record.WSPD = Float.parseFloat(tokens[7]);
51+
record.WDIR = Float.parseFloat(tokens[8]);
52+
record.BARO = Float.parseFloat(tokens[9]);
53+
record.RAIN = Float.parseFloat(tokens[10]);
54+
record.Q = Integer.parseInt(tokens[11]);
55+
record.M = tokens[12];
56+
57+
return record;
58+
}
59+
3060
@Override
3161
public void open(File file) throws IOException {
32-
throw new RuntimeException("not implemented");
62+
try (final FileReader fileReader = new FileReader(file)) {
63+
records = new ArrayList<>();
64+
65+
final BufferedReader bufferedReader = new BufferedReader(fileReader);
66+
String line;
67+
while ((line = bufferedReader.readLine()) != null) {
68+
if (line.startsWith("#")) {
69+
// skip comment lines tb 2023-04-28
70+
continue;
71+
}
72+
73+
final TaoRecord record = parseLine(line);
74+
records.add(record);
75+
}
76+
}
3377
}
3478

3579
@Override
3680
public void close() throws IOException {
37-
throw new RuntimeException("not implemented");
81+
if (records != null) {
82+
records.clear();
83+
records = null;
84+
}
85+
timeLocator = null;
3886
}
3987

4088
@Override
4189
public AcquisitionInfo read() throws IOException {
42-
throw new RuntimeException("not implemented");
90+
final AcquisitionInfo acquisitionInfo = new AcquisitionInfo();
91+
int minTime = Integer.MAX_VALUE;
92+
int maxTime = Integer.MIN_VALUE;
93+
for (final TaoRecord record : records) {
94+
if (record.time < minTime) {
95+
minTime = record.time;
96+
}
97+
if (record.time > maxTime) {
98+
maxTime = record.time;
99+
}
100+
}
101+
102+
acquisitionInfo.setSensingStart(new Date(minTime * 1000L));
103+
acquisitionInfo.setSensingStop(new Date(maxTime * 1000L));
104+
105+
acquisitionInfo.setNodeType(NodeType.UNDEFINED);
106+
107+
return acquisitionInfo;
43108
}
44109

45110
@Override
@@ -59,7 +124,10 @@ public PixelLocator getSubScenePixelLocator(Polygon sceneGeometry) throws IOExce
59124

60125
@Override
61126
public TimeLocator getTimeLocator() throws IOException {
62-
throw new RuntimeException("not implemented");
127+
if (timeLocator == null) {
128+
createTimeLocator();
129+
}
130+
return timeLocator;
63131
}
64132

65133
@Override
@@ -91,12 +159,98 @@ public List<Variable> getVariables() throws InvalidRangeException, IOException {
91159
attributes.add(new Attribute(CF_STANDARD_NAME, "longitude"));
92160
variables.add(new VariableProxy("longitude", DataType.FLOAT, attributes));
93161

162+
attributes = new ArrayList<>();
163+
attributes.add(new Attribute(CF_UNITS_NAME, "degree_north"));
164+
attributes.add(new Attribute(CF_STANDARD_NAME, "latitude"));
165+
variables.add(new VariableProxy("latitude", DataType.FLOAT, attributes));
166+
167+
attributes = new ArrayList<>();
168+
attributes.add(new Attribute(CF_UNITS_NAME, "seconds since 1970-01-01"));
169+
attributes.add(new Attribute(CF_STANDARD_NAME, "time"));
170+
variables.add(new VariableProxy("time", DataType.INT, attributes));
171+
172+
attributes = new ArrayList<>();
173+
attributes.add(new Attribute(CF_UNITS_NAME, "psu"));
174+
attributes.add(new Attribute(CF_STANDARD_NAME, "sea_surface_salinity"));
175+
attributes.add(new Attribute(CF_FILL_VALUE_NAME, -9.999));
176+
variables.add(new VariableProxy("SSS", DataType.FLOAT, attributes));
177+
178+
attributes = new ArrayList<>();
179+
attributes.add(new Attribute(CF_UNITS_NAME, "degree_Celsius"));
180+
attributes.add(new Attribute(CF_STANDARD_NAME, "sea_surface_temperature"));
181+
attributes.add(new Attribute(CF_FILL_VALUE_NAME, -9.999));
182+
variables.add(new VariableProxy("SST", DataType.FLOAT, attributes));
183+
184+
attributes = new ArrayList<>();
185+
attributes.add(new Attribute(CF_UNITS_NAME, "degree_Celsius"));
186+
attributes.add(new Attribute(CF_STANDARD_NAME, "air_temperature"));
187+
attributes.add(new Attribute(CF_FILL_VALUE_NAME, -9.99));
188+
variables.add(new VariableProxy("AIRT", DataType.FLOAT, attributes));
189+
190+
attributes = new ArrayList<>();
191+
attributes.add(new Attribute(CF_UNITS_NAME, "percent"));
192+
attributes.add(new Attribute(CF_STANDARD_NAME, "relative_humidity"));
193+
attributes.add(new Attribute(CF_FILL_VALUE_NAME, -9.99));
194+
variables.add(new VariableProxy("RH", DataType.FLOAT, attributes));
195+
196+
attributes = new ArrayList<>();
197+
attributes.add(new Attribute(CF_UNITS_NAME, "m/s"));
198+
attributes.add(new Attribute(CF_STANDARD_NAME, "wind_speed"));
199+
attributes.add(new Attribute(CF_FILL_VALUE_NAME, -99.9));
200+
variables.add(new VariableProxy("WSPD", DataType.FLOAT, attributes));
201+
202+
attributes = new ArrayList<>();
203+
attributes.add(new Attribute(CF_UNITS_NAME, "degree"));
204+
attributes.add(new Attribute(CF_STANDARD_NAME, "wind_to_direction"));
205+
attributes.add(new Attribute(CF_LONG_NAME, "Wind To Direction degree true in Oceanographic Convention"));
206+
attributes.add(new Attribute(CF_FILL_VALUE_NAME, -99.9));
207+
variables.add(new VariableProxy("WDIR", DataType.FLOAT, attributes));
208+
209+
attributes = new ArrayList<>();
210+
attributes.add(new Attribute(CF_UNITS_NAME, "hPa"));
211+
attributes.add(new Attribute(CF_STANDARD_NAME, "air_pressure_at_mean_sea_level"));
212+
attributes.add(new Attribute(CF_FILL_VALUE_NAME, -9.9));
213+
variables.add(new VariableProxy("BARO", DataType.FLOAT, attributes));
214+
215+
attributes = new ArrayList<>();
216+
attributes.add(new Attribute(CF_UNITS_NAME, "mm/hour"));
217+
attributes.add(new Attribute(CF_STANDARD_NAME, "rainfall_rate"));
218+
attributes.add(new Attribute(CF_FILL_VALUE_NAME, -9.99));
219+
variables.add(new VariableProxy("RAIN", DataType.FLOAT, attributes));
220+
221+
attributes = new ArrayList<>();
222+
attributes.add(new Attribute(CF_LONG_NAME, "Data Quality Codes"));
223+
variables.add(new VariableProxy("Q", DataType.INT, attributes));
224+
/*
225+
@todo 1 tb/tb move this to documentation 2023-04-28
226+
Data Quality Codes(Q):
227+
0 = unknown
228+
1 = good data
229+
2 = probably good data
230+
3 = questionable data
231+
4 = bad data
232+
5 = adjusted data
233+
9 = missing data
234+
*/
235+
attributes = new ArrayList<>();
236+
attributes.add(new Attribute(CF_LONG_NAME, "Data Mode Codes"));
237+
variables.add(new VariableProxy("M", DataType.STRING, attributes));
238+
239+
/*
240+
@todo 1 tb/tb move this to documentation 2023-04-28
241+
Data Mode Codes(M):
242+
R = real-time data
243+
P = provisional data
244+
D = delayed mode data
245+
M = mixed real-time and delayed mode data
246+
*/
247+
94248
return variables;
95249
}
96250

97251
@Override
98252
public Dimension getProductSize() throws IOException {
99-
throw new RuntimeException("not implemented");
253+
return new Dimension("product_size", 1, records.size());
100254
}
101255

102256
@Override
@@ -108,4 +262,16 @@ public String getLongitudeVariableName() {
108262
public String getLatitudeVariableName() {
109263
return "latitude";
110264
}
265+
266+
private void createTimeLocator() {
267+
long[] timeArray = new long[records.size()];
268+
269+
int i = 0;
270+
for (final TaoRecord record : records) {
271+
timeArray[i] = record.time * 1000L;
272+
i++;
273+
}
274+
275+
timeLocator = new TimeLocator_MillisSince1970(timeArray);
276+
}
111277
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.bc.fiduceo.reader.insitu.tao;
2+
3+
class TaoRecord {
4+
5+
int time;
6+
float longitude;
7+
float latitude;
8+
float SSS;
9+
float SST;
10+
float AIRT;
11+
float RH;
12+
float WSPD;
13+
float WDIR;
14+
float BARO;
15+
float RAIN;
16+
int Q;
17+
String M;
18+
}

0 commit comments

Comments
 (0)