Skip to content

Commit b65e609

Browse files
committed
dev
1 parent 5fed753 commit b65e609

File tree

6 files changed

+77
-13
lines changed

6 files changed

+77
-13
lines changed

cf/data/array/umarray.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
load_stash2standard_name,
99
parse_indices,
1010
)
11-
from ...umread_lib.umfile import File
11+
from ...umread_lib.umfile import File, Rec
1212
from .abstract import Array
1313
from .mixin import FileArrayMixin
1414

@@ -272,14 +272,12 @@ def _get_rec(self, f, header_offset):
272272
The record container.
273273
274274
"""
275-
# TODOCFA: This method doesn't require data_offset and disk_length,
276-
# so plays nicely with CFA. Is it fast enough that we can
277-
# use this method always?
275+
return Rec.from_file_and_offsets(f, header_offset)
278276
for v in f.vars:
279277
for r in v.recs:
280278
if r.hdr_offset == header_offset:
279+
print (r.__dict__)
281280
return r
282-
283281
def _set_units(self, int_hdr):
284282
"""The units and calendar properties.
285283
@@ -683,4 +681,5 @@ def open(self):
683681
byte_ordering=self.get_byte_ordering(),
684682
word_size=self.get_word_size(),
685683
fmt=self.get_fmt(),
684+
parse=False,
686685
)

cf/umread_lib/c-lib/bits/type_dep_protos.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ int get_var_gridcode(const INTEGER *int_hdr);
1212
int get_var_packing(const INTEGER *int_hdr);
1313
REAL get_var_real_fill_value(const REAL *int_hdr);
1414

15+
/* int my_get_extra_data_length(const INTEGER *int_hdr);
16+
int my_get_num_data_words(const INTEGER *int_hdr);
17+
int my_get_ff_disk_length(const INTEGER *int_hdr); */
18+
19+
20+
1521
/* read.c */
1622

1723
size_t read_words(int fd,

cf/umread_lib/c-lib/type-dep/interpret_header.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,4 @@ REAL get_var_real_fill_value(const REAL *real_hdr)
139139
{
140140
return real_hdr[INDEX_BMDI];
141141
}
142+

cf/umread_lib/c-lib/umfile.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ int get_type_and_num_words(int word_size,
1818
default:
1919
return -1;
2020
}
21+
2122
}
2223

2324
int get_extra_data_offset_and_length(int word_size,
@@ -163,3 +164,10 @@ int read_record_data(int fd,
163164
/* invalid word size falls through to error return */
164165
ERRBLKI;
165166
}
167+
168+
169+
/* Get the word address of the current file position. */
170+
int file_pos(int fd)
171+
{
172+
return lseek(fd, 0, SEEK_CUR);
173+
}

cf/umread_lib/cInterface.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ def c_rec_to_py_rec(self, c_rec_p):
377377
header_offset = c_rec.header_offset
378378
data_offset = c_rec.data_offset
379379
disk_length = c_rec.disk_length
380+
380381
return umfile.Rec(
381382
int_hdr, real_hdr, header_offset, data_offset, disk_length
382383
)

cf/umread_lib/umfile.py

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ class UMFileException(Exception):
1111
pass
1212

1313

14+
LBLREC = 14
15+
LBROW = 17
16+
LBNPT = 18
17+
LBEXT = 19
18+
LBPACK = 20
19+
LBEGIN = 28
20+
LBNREC = 29
21+
22+
1423
class File:
1524
"""A class for a UM file that gives a view of the file including
1625
sets of PP records combined into variables."""
@@ -34,7 +43,7 @@ def __init__(
3443
'little_endian' or 'big_endian'
3544
3645
word_size: `int`, optional
37-
4 or 8
46+
The size in bytes of one word. Either ``4`` or ``8``.
3847
3948
fmt: `str`, optional
4049
'FF' or 'PP'
@@ -280,8 +289,13 @@ def __init__(
280289
if file:
281290
self.file = file
282291

292+
# import cf; pp = cf.umread_lib.umfile.File('/home/david/test2.pp', fmt='PP', byte_ordering= 'little_endian' , word_size=4, parse=False)
293+
# cf.umread_lib.umfile.Rec.from_file_and_offsets(pp, 4, 268, 46640)
294+
283295
@classmethod
284-
def from_file_and_offsets(cls, file, hdr_offset, data_offset, disk_length):
296+
def from_file_and_offsets(
297+
cls, file, hdr_offset, data_offset=None, disk_length=None
298+
):
285299
"""Instantiate a `Rec` object from the `File` object and the
286300
header and data offsets.
287301
@@ -295,24 +309,59 @@ def from_file_and_offsets(cls, file, hdr_offset, data_offset, disk_length):
295309
into variables.
296310
297311
hdr_offset: `int`
298-
The start word in the file of the header.
312+
The file start address of the header, in bytes.
299313
300-
data_offset: `int`
301-
The start word in the file of the data.
314+
data_offset: `int`, optional
315+
The file start address of the data, in bytes. If
316+
`None`, the default, then the data offset will be
317+
calculated from the integer header.
302318
303319
disk_length: `int`
304-
The length in words of the data in the file.
320+
The length in bytes of the data in the file. If
321+
`None`, the default, then the disk length will be
322+
calculated from the integer header.
305323
306324
:Returns:
307325
308326
`Rec`
309327
310328
"""
311329
c = file._c_interface
330+
word_size = file.word_size
312331
int_hdr, real_hdr = c.read_header(
313-
file.fd, hdr_offset, file.byte_ordering, file.word_size
332+
file.fd, hdr_offset, file.byte_ordering, word_size
314333
)
315-
334+
PP = file.fmt == "PP"
335+
print (c.lib.arse)
336+
if data_offset is None:
337+
# Calculate the data offset from the integer header
338+
if PP:
339+
# We only support 64-word headers, so the data starts
340+
# 66 words after the header, i.e. 64 words of the
341+
# header plus two block control words.
342+
data_offset = hdr_offset + 66 * word_size
343+
else:
344+
# Fields file
345+
data_offset = int_hdr[LBEGIN] * word_size
346+
347+
if disk_length is None:
348+
# Calculate the disk length from the integer header
349+
lbpack = int_hdr[LBPACK]
350+
lbnrec = int_hdr[LBNREC]
351+
lblrec = int_hdr[LBLREC]
352+
353+
if not lbpack:
354+
disk_length = (lblrec - int_hdr[LBEXT]) * word_size
355+
elif lbpack != 0 and lblrec * word_size:
356+
disk_length = lblrec * word_size
357+
elif lbpack % 10 == 2:
358+
lbnpt = int_hdr[LBNPT]
359+
lbrow = int_hdr[LBROW]
360+
if lbnpt > 0 and lbrow > 0:
361+
disk_length = lbnpt * lbrow * 4
362+
else:
363+
disk_length = (lblrec - int_hdr[LBEXT]) * 4
364+
316365
return cls(
317366
int_hdr, real_hdr, hdr_offset, data_offset, disk_length, file=file
318367
)

0 commit comments

Comments
 (0)