Skip to content

Commit 03ed6ab

Browse files
committed
dev
1 parent d6870d9 commit 03ed6ab

File tree

1 file changed

+103
-230
lines changed

1 file changed

+103
-230
lines changed

cf/read_write/read.py

Lines changed: 103 additions & 230 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,23 @@ def __new__(
601601

602602
aggregate_options["copy"] = False
603603

604+
# ------------------------------------------------------------
605+
# Parse the 'fmt' keyword parameter
606+
# ------------------------------------------------------------
607+
if fmt:
608+
if isinstance(fmt, str):
609+
fmt = (fmt,)
610+
611+
fmt = set(fmt)
612+
else:
613+
fmt = set(("netCDF", "CDL", "UM"))
614+
615+
# ------------------------------------------------------------
616+
# Parse the 'um' keyword parameter
617+
# ------------------------------------------------------------
618+
if not um:
619+
um = {}
620+
604621
# Count the number of fields (in all files) and the number of
605622
# files
606623
field_counter = -1
@@ -646,49 +663,97 @@ def __new__(
646663

647664
files2 = files3
648665

666+
# How each file was read, as netCDF, or UM, etc.
667+
ftypes = set()
668+
649669
for filename in files2:
650670
if info:
651671
logger.info(f"File: {filename}") # pragma: no cover
652672

653-
# --------------------------------------------------------
673+
# ----------------------------------------------------
654674
# Read the file
655-
# --------------------------------------------------------
656-
ftypes = [None]
657-
file_contents = cls._read_a_file(
658-
filename,
659-
ftypes=ftypes,
660-
external=external,
661-
ignore_read_error=ignore_read_error,
662-
verbose=verbose,
663-
warnings=warnings,
664-
aggregate=aggregate,
665-
aggregate_options=aggregate_options,
666-
fmt=fmt,
667-
um=um,
668-
extra=extra,
669-
height_at_top_of_model=height_at_top_of_model,
670-
dask_chunks=dask_chunks,
671-
store_hdf5_chunks=store_hdf5_chunks,
672-
mask=mask,
673-
unpack=unpack,
674-
warn_valid=warn_valid,
675-
select=select,
676-
domain=domain,
677-
cfa=cfa,
678-
cfa_write=cfa_write,
679-
to_memory=to_memory,
680-
netcdf_backend=netcdf_backend,
681-
storage_options=storage_options,
682-
cache=cache,
683-
squeeze=squeeze,
684-
unsqueeze=unsqueeze,
685-
)
675+
# ----------------------------------------------------
676+
fmts = fmt.copy()
677+
file_format_errors = []
678+
679+
if fmts.intersection(("netCDF", "CDL")):
680+
try:
681+
file_contents = super().__new__(
682+
cls,
683+
filename,
684+
external=external,
685+
extra=extra,
686+
verbose=verbose,
687+
warnings=warnings,
688+
mask=mask,
689+
unpack=unpack,
690+
warn_valid=warn_valid,
691+
domain=domain,
692+
storage_options=storage_options,
693+
netcdf_backend=netcdf_backend,
694+
dask_chunks=dask_chunks,
695+
store_hdf5_chunks=store_hdf5_chunks,
696+
cache=cache,
697+
cfa=cfa,
698+
cfa_write=cfa_write,
699+
to_memory=to_memory,
700+
squeeze=squeeze,
701+
unsqueeze=unsqueeze,
702+
fmt=fmt,
703+
ignore_unknown_format=ignore_read_error,
704+
)
705+
except UnknownFileFormatError as error:
706+
fmts.difference_update(("netCDF", "CDL"))
707+
file_format_errors.append(error)
708+
else:
709+
file_format_errors = ()
710+
if file_contents or not ignore_read_error:
711+
# Zero or more fields/domains were
712+
# successfully read
713+
fmts = set()
714+
ftype = "netCDF"
715+
716+
if fmts.intersection(("UM",)):
717+
try:
718+
file_contents = cls.um.read(
719+
filename,
720+
um_version=um.get("version"),
721+
verbose=verbose,
722+
set_standard_name=False,
723+
height_at_top_of_model=height_at_top_of_model,
724+
fmt=um.get("fmt"),
725+
word_size=um.get("word_size"),
726+
endian=um.get("endian"),
727+
select=select,
728+
squeeze=squeeze,
729+
unsqueeze=unsqueeze,
730+
domain=domain,
731+
)
732+
except UnknownFileFormatError as error:
733+
fmts.difference_update(("UM",))
734+
file_format_errors.append(error)
735+
else:
736+
file_format_errors = ()
737+
if file_contents or not ignore_read_error:
738+
fmts = set()
739+
ftype = "UM"
740+
741+
if file_format_errors:
742+
error = "\n".join(map(str, file_format_errors))
743+
raise UnknownFileFormatError(f"\n{error}")
744+
745+
if domain:
746+
file_contents = DomainList(file_contents)
747+
748+
file_contents = FieldList(file_contents)
749+
750+
ftypes.add(ftype)
686751

687752
# --------------------------------------------------------
688753
# Select matching fields (only from netCDF files at
689754
# this stage - we'll do UM fields later)
690755
# --------------------------------------------------------
691-
if select and ftypes[-1] == "netCDF":
756+
if select and ftype == "netCDF":
692757
file_contents = file_contents.select_by_identity(*select)
693758

694759
# --------------------------------------------------------
@@ -712,6 +777,11 @@ def __new__(
712777
if aggregate and len(out) > 1:
713778
org_len = len(out) # pragma: no cover
714779

780+
if "UM" in ftypes:
781+
# Set defaults specific to UM fields
782+
if "strict_units" not in aggregate_options:
783+
aggregate_options["relaxed_units"] = True
784+
715785
out = cf_aggregate(out, **aggregate_options)
716786

717787
n = len(out) # pragma: no cover
@@ -756,200 +826,3 @@ def __new__(
756826
def _plural(n): # pragma: no cover
757827
"""Return a suffix which reflects a word's plural."""
758828
return "s" if n != 1 else "" # pragma: no cover
759-
760-
@classmethod
761-
@_manage_log_level_via_verbosity
762-
def _read_a_file(
763-
cls,
764-
filename,
765-
ftypes=None,
766-
aggregate=True,
767-
aggregate_options=None,
768-
ignore_read_error=False,
769-
verbose=None,
770-
warnings=False,
771-
external=None,
772-
fmt=None,
773-
um=None,
774-
extra=None,
775-
height_at_top_of_model=None,
776-
mask=True,
777-
unpack=True,
778-
warn_valid=False,
779-
dask_chunks="storage-aligned",
780-
store_hdf5_chunks=True,
781-
select=None,
782-
domain=False,
783-
cfa=None,
784-
cfa_write=None,
785-
to_memory=None,
786-
netcdf_backend=None,
787-
storage_options=None,
788-
cache=True,
789-
squeeze=False,
790-
unsqueeze=False,
791-
):
792-
"""Read the contents of a single file into a field list.
793-
794-
:Parameters:
795-
796-
filename: `str`
797-
See `cf.read` for details.
798-
799-
ftypes: `str` TODOCFA
800-
The file format to interpret the file. Recognised formats are
801-
``'netCDF'``, ``'CDL'``, ``'UM'`` and ``'PP'``.
802-
803-
aggregate_options: `dict`, optional
804-
See `cf.read` for details.
805-
806-
ignore_read_error: `bool`, optional
807-
See `cf.read` for details.
808-
809-
mask: `bool`, optional
810-
See `cf.read` for details.
811-
812-
unpack: `bool`, optional
813-
See `cf.read` for details.
814-
815-
verbose: `int` or `str` or `None`, optional
816-
See `cf.read` for details.
817-
818-
select: optional
819-
For `read. Ignored for a netCDF file.
820-
821-
domain: `bool`, optional
822-
See `cf.read` for details.
823-
824-
cfa: `dict`, optional
825-
See `cf.read` for details.
826-
827-
.. versionadded:: 3.15.0
828-
829-
storage_options: `dict` or `None`, optional
830-
See `cf.read` for details.
831-
832-
.. versionadded:: NEXTVERSION
833-
834-
netcdf_backend: `str` or `None`, optional
835-
See `cf.read` for details.
836-
837-
.. versionadded:: NEXTVERSION
838-
839-
cache: `bool`, optional
840-
See `cf.read` for details.
841-
842-
.. versionadded:: NEXTVERSION
843-
844-
squeeze: `bool`, optional
845-
Whether or not to remove all size 1 axes from field
846-
construct data arrays. See `cf.read` for details.
847-
848-
.. versionadded:: NEXTVERSION
849-
850-
unsqueeze: `bool`, optional
851-
Whether or not to ensure that all size 1 axes are
852-
spanned by field construct data arrays. See
853-
`cf.read` for details.
854-
855-
.. versionadded:: NEXTVERSION
856-
857-
:Returns:
858-
859-
`FieldList` or `DomainList`
860-
The field or domain constructs in the dataset.
861-
862-
"""
863-
if fmt:
864-
if isinstance(fmt, str):
865-
fmt = (fmt,)
866-
867-
fmt = set(fmt)
868-
else:
869-
fmt = set(("netCDF", "CDL", "UM"))
870-
871-
file_format_errors = []
872-
873-
out = None
874-
if fmt.intersection(("netCDF", "CDL")):
875-
try:
876-
out = super().__new__(
877-
cls,
878-
filename,
879-
external=external,
880-
extra=extra,
881-
verbose=verbose,
882-
warnings=warnings,
883-
mask=mask,
884-
unpack=unpack,
885-
warn_valid=warn_valid,
886-
domain=domain,
887-
storage_options=storage_options,
888-
netcdf_backend=netcdf_backend,
889-
dask_chunks=dask_chunks,
890-
store_hdf5_chunks=store_hdf5_chunks,
891-
cache=cache,
892-
cfa=cfa,
893-
cfa_write=cfa_write,
894-
to_memory=to_memory,
895-
squeeze=squeeze,
896-
unsqueeze=unsqueeze,
897-
fmt=fmt,
898-
ignore_unknown_format=ignore_read_error,
899-
)
900-
except UnknownFileFormatError as error:
901-
fmt.difference_update(("netCDF", "CDL"))
902-
if fmt:
903-
file_format_errors.append(error)
904-
else:
905-
raise
906-
else:
907-
if out or not ignore_read_error:
908-
# Zero or more fields/domains were successfully read
909-
fmt = set()
910-
file_format_errors = ()
911-
ftypes.append("netCDF")
912-
913-
if fmt.intersection(("UM",)):
914-
if not um:
915-
um = {}
916-
917-
try:
918-
out = cls.um.read(
919-
filename,
920-
um_version=um.get("version"),
921-
verbose=verbose,
922-
set_standard_name=False,
923-
height_at_top_of_model=height_at_top_of_model,
924-
fmt=um.get("fmt"),
925-
word_size=um.get("word_size"),
926-
endian=um.get("endian"),
927-
select=select,
928-
squeeze=squeeze,
929-
unsqueeze=unsqueeze,
930-
domain=domain,
931-
)
932-
except UnknownFileFormatError as error:
933-
fmt.difference_update(("UM",))
934-
file_format_errors.append(error)
935-
else:
936-
if out or not ignore_read_error:
937-
file_format_errors = ()
938-
ftypes.append("UM")
939-
940-
# UM fields are aggregated intrafile prior to
941-
# interfile aggregation
942-
if aggregate:
943-
# Set defaults specific to UM fields
944-
if "strict_units" not in aggregate_options:
945-
aggregate_options["relaxed_units"] = True
946-
947-
if file_format_errors:
948-
file_format_errors = "\n".join(map(str, file_format_errors))
949-
raise UnknownFileFormatError(f"\n{file_format_errors}")
950-
951-
# Return the fields/domains
952-
if domain:
953-
return DomainList(out)
954-
955-
return FieldList(out)

0 commit comments

Comments
 (0)