From 0ce0bf6d09faf903e67a56c2220c342200847ff1 Mon Sep 17 00:00:00 2001 From: SharonGoliath Date: Mon, 31 Oct 2022 12:01:52 -0700 Subject: [PATCH] CADC-11894 - introduce CFHT handling for metadata from HDF5 files. (#160) *introduce CFHT handling for metadata from HDF5 files --- caom2/caom2/diff.py | 2 +- .../tests/data/diff-expected-CAOM-2.3.xml | 4 +- caom2utils/caom2utils/caom2blueprint.py | 73 +++++++---- caom2utils/caom2utils/data_util.py | 3 +- .../dao_c122_2016_007777.xml | 2 +- .../dao_c122_2016_007830.xml | 2 +- .../dao_c122_2016_007939.xml | 2 +- .../dao_c122_2016_007942.xml | 2 +- .../20220201T200117/20220201T200117.xml | 14 +-- .../data/taos_h5file/def/attrs.blueprint | 51 ++++++++ .../tests/data/taos_h5file/def/def.h5 | Bin 0 -> 32784 bytes .../tests/data/taos_h5file/def/def.module | 62 ++++++++++ .../tests/data/taos_h5file/def/def.py | 62 ++++++++++ .../tests/data/taos_h5file/def/def.xml | 114 ++++++++++++++++++ .../caom2utils/tests/test_collections.py | 6 +- .../caom2utils/tests/test_fits2caom2.py | 5 +- caom2utils/setup.cfg | 4 +- 17 files changed, 366 insertions(+), 42 deletions(-) create mode 100644 caom2utils/caom2utils/tests/data/taos_h5file/def/attrs.blueprint create mode 100644 caom2utils/caom2utils/tests/data/taos_h5file/def/def.h5 create mode 100644 caom2utils/caom2utils/tests/data/taos_h5file/def/def.module create mode 100644 caom2utils/caom2utils/tests/data/taos_h5file/def/def.py create mode 100644 caom2utils/caom2utils/tests/data/taos_h5file/def/def.xml diff --git a/caom2/caom2/diff.py b/caom2/caom2/diff.py index 62581210..72cd01af 100644 --- a/caom2/caom2/diff.py +++ b/caom2/caom2/diff.py @@ -413,7 +413,7 @@ def _not_equal(rhs, lhs): else: # if only using python 3.5+, use math.isclose, instead of this # description of math.isclose from the python documentation - result = abs(rhs-lhs) <= max(1e-10 * max(abs(rhs), abs(lhs)), 1e-9) + result = abs(rhs-lhs) <= max(1e-12 * max(abs(rhs), abs(lhs)), 1e-11) else: result = rhs == lhs return not result diff --git a/caom2/caom2/tests/data/diff-expected-CAOM-2.3.xml b/caom2/caom2/tests/data/diff-expected-CAOM-2.3.xml index 046d468a..19d65158 100644 --- a/caom2/caom2/tests/data/diff-expected-CAOM-2.3.xml +++ b/caom2/caom2/tests/data/diff-expected-CAOM-2.3.xml @@ -119,11 +119,11 @@ 58979.5015625 - 58979.5017365 + 58979.50173611111 58979.5015625 - 58979.5017365 + 58979.50173611111 diff --git a/caom2utils/caom2utils/caom2blueprint.py b/caom2utils/caom2utils/caom2blueprint.py index 79cb4ba5..2a151f0a 100755 --- a/caom2utils/caom2utils/caom2blueprint.py +++ b/caom2utils/caom2utils/caom2blueprint.py @@ -71,7 +71,6 @@ from logging.handlers import TimedRotatingFileHandler import math -import numpy from astropy.wcs import Wcsprm, WCS from astropy.io import fits from astropy.time import Time @@ -1835,6 +1834,19 @@ def configure_time_axis(self, axis, override=True): self._time_axis_configed = True + def set(self, caom2_element, value, extension=0): + """ + Sets the value associated with an element in the CAOM2 model. Value + cannot be a tuple. + :param caom2_element: name CAOM2 element (as in + ObsBlueprint.CAOM2_ELEMEMTS) + :param value: new value of the CAOM2 element + :param extension: extension number (used only for Chunk elements) + """ + if hasattr(value, 'decode'): + value = value.decode('utf-8') + super().set(caom2_element, value, extension) + def _guess_axis_info(self): self._guess_axis_info_from_plan() @@ -2071,7 +2083,7 @@ def _to_enum_type(self, value, to_enum_type): if value is None: raise ValueError( f'Must set a value of {to_enum_type.__name__} for ' - f'{self._uri}.') + f'{self.uri}.') elif isinstance(value, to_enum_type): return value else: @@ -3668,18 +3680,15 @@ class Hdf5Parser(ContentParser): """ def __init__( - self, obs_blueprint, uri, local_f_name, find_roots_here='sitedata' + self, obs_blueprint, uri, h5_file, find_roots_here='sitedata' ): """ :param obs_blueprint: Hdf5ObsBlueprint instance :param uri: which artifact augmentation is based on - :param local_f_name: str file name on disk + :param h5_file: h5py file handle :param find_roots_here: str location where Chunk metadata starts """ - # h5py is an extra in this package since most collections do not - # require it - import h5py - self._file = h5py.File(local_f_name) + self._file = h5_file # where N Chunk metadata starts self._find_roots_here = find_roots_here # the length of the array is the number of Parts in an HDF5 file, @@ -3698,7 +3707,7 @@ def apply_blueprint_from_file(self): # h5py is an extra in this package since most collections do not # require it import h5py - individual, multi = self._extract_path_names_from_blueprint() + individual, multi, attributes = self._extract_path_names_from_blueprint() def _extract_from_item(name, object): """ @@ -3765,28 +3774,45 @@ def _extract_from_item(name, object): for jj in individual.get(temp): self._blueprint.set(jj, object[d_name], 0) - self._file.visititems(_extract_from_item) + if len(individual) == 0 and len(multi) == 0: + self._extract_from_attrs(attributes) + else: + self._file.visititems(_extract_from_item) self.logger.debug('Done apply_blueprint_from_file') + def _extract_from_attrs(self, attributes): + # I don't currently see any way to have more than one Part, if relying on + # attrs for metadata + part_index = 0 + # v == list of blueprint keys + for k, v in attributes.items(): + if k in self._file.attrs: + value = self._file.attrs[k] + for entry in v: + self._blueprint.set(entry, value, part_index) + def _extract_path_names_from_blueprint(self): """ - :return: individual - a dictionary of lists, keys are unique path - names for finding metadata once per file. Values are - _CAOM2_ELEMENT strings. - multiple - a dictionary of lists, keys are unique path names for - finding metadata N times per file. Values are _CAOM2_ELEMENT - strings. + :return: individual - a dictionary of lists, keys are unique path names for finding metadata once per file. + Values are _CAOM2_ELEMENT strings. + multiple - a dictionary of lists, keys are unique path names for finding metadata N times per file. Values + are _CAOM2_ELEMENT strings. + attributes - a dictionary of lists, keys reference expected content from the h5py.File().attrs data + structure and its keys. """ individual = defaultdict(list) multi = defaultdict(list) + attributes = defaultdict(list) for key, value in self._blueprint._plan.items(): if ObsBlueprint.needs_lookup(value): for ii in value[0]: if ii.startswith('//'): individual[ii].append(key) - else: + elif ii.startswith('/'): multi[ii].append(key) - return individual, multi + else: + attributes[ii].append(key) + return individual, multi, attributes def apply_blueprint(self): self.logger.debug('Begin apply_blueprint') @@ -4239,8 +4265,6 @@ def _sanitize(self, value): return None elif not str(value): return None # empty string - elif isinstance(value, numpy.bytes_): - return value.decode('utf-8') else: return value @@ -4562,7 +4586,8 @@ def _finish_chunk_time(self, chunk): if not math.isnan(self._wcs.wcs.xposure): chunk.time.exposure = self._wcs.wcs.xposure chunk.time.timesys = self._wcs.wcs.timesys - chunk.time.trefpos = self._wcs.wcs.trefpos + if self._wcs.wcs.trefpos is not None and self._wcs.wcs.trefpos != '': + chunk.time.trefpos = self._wcs.wcs.trefpos # convert from the numpy array length 2 of self._wcs.wcs.mjdref # to a single value # TODO chunk.time.mjdref = self._wcs.to_header().get('MJDREF') @@ -4906,7 +4931,11 @@ def _augment(obs, product_id, uri, blueprint, subject, dumpconfig=False, elif '.h5' in local: logging.debug( f'Using an Hdf5Parser for local file {local}') - parser = Hdf5Parser(blueprint, uri, local) + # h5py is an extra in this package since most collections do + # not require it + import h5py + temp = h5py.File(local) + parser = Hdf5Parser(blueprint, uri, temp) else: # explicitly ignore headers for txt and image files logging.debug(f'Using a BlueprintParser for {local}') diff --git a/caom2utils/caom2utils/data_util.py b/caom2utils/caom2utils/data_util.py index aa80da6b..b73a862a 100644 --- a/caom2utils/caom2utils/data_util.py +++ b/caom2utils/caom2utils/data_util.py @@ -226,7 +226,8 @@ def info(self, uri): id=uri, size=temp.get('size'), file_type=temp.get('type'), - md5sum=temp.get('md5sum').replace('md5:', '') + md5sum=temp.get('md5sum').replace('md5:', ''), + encoding=temp.get('encoding'), ) except exceptions.NotFoundException: self._logger.info(f'cadcinfo:: {uri} not found') diff --git a/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007777/dao_c122_2016_007777.xml b/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007777/dao_c122_2016_007777.xml index f2736fd6..a1759979 100644 --- a/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007777/dao_c122_2016_007777.xml +++ b/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007777/dao_c122_2016_007777.xml @@ -20,7 +20,7 @@ DAO 1.2-m - -2331226.78834 + -2331226.7883358444 -3532798.9829 4755607.32183 diff --git a/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007830/dao_c122_2016_007830.xml b/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007830/dao_c122_2016_007830.xml index 945b61d6..a48babf3 100644 --- a/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007830/dao_c122_2016_007830.xml +++ b/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007830/dao_c122_2016_007830.xml @@ -20,7 +20,7 @@ DAO 1.2-m - -2331226.78834 + -2331226.7883358444 -3532798.9829 4755607.32183 diff --git a/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007939/dao_c122_2016_007939.xml b/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007939/dao_c122_2016_007939.xml index 0b0a1152..7544e18a 100644 --- a/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007939/dao_c122_2016_007939.xml +++ b/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007939/dao_c122_2016_007939.xml @@ -19,7 +19,7 @@ DAO 1.2-m - -2331226.78834 + -2331226.7883358444 -3532798.9829 4755607.32183 diff --git a/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007942/dao_c122_2016_007942.xml b/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007942/dao_c122_2016_007942.xml index 8de706e7..dafb284c 100644 --- a/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007942/dao_c122_2016_007942.xml +++ b/caom2utils/caom2utils/tests/data/dao/dao_c122_2016_007942/dao_c122_2016_007942.xml @@ -19,7 +19,7 @@ DAO 1.2-m - -2331226.78834 + -2331226.7883358444 -3532798.9829 4755607.32183 diff --git a/caom2utils/caom2utils/tests/data/taos_h5file/20220201T200117/20220201T200117.xml b/caom2utils/caom2utils/tests/data/taos_h5file/20220201T200117/20220201T200117.xml index bb179533..c1cb7bed 100644 --- a/caom2utils/caom2utils/tests/data/taos_h5file/20220201T200117/20220201T200117.xml +++ b/caom2utils/caom2utils/tests/data/taos_h5file/20220201T200117/20220201T200117.xml @@ -66,9 +66,9 @@ 0.36083190511928515 - -3.056099929280465e-06 - 5.26221921634137e-09 - -8.906590162255861e-09 + -3.055789796926023e-06 + 5.17684229864217e-09 + -8.84247710317511e-09 -3.0546760780702482e-06 @@ -128,10 +128,10 @@ 0.3608318611649132 - -3.056099929280465e-06 - 5.26221921634137e-09 - -8.906590162255861e-09 - -3.0546760780702482e-06 + -3.056038798826708e-06 + 5.311589798573419e-09 + -8.530093204777965e-09 + -3.054771726598754e-06 2000.0 diff --git a/caom2utils/caom2utils/tests/data/taos_h5file/def/attrs.blueprint b/caom2utils/caom2utils/tests/data/taos_h5file/def/attrs.blueprint new file mode 100644 index 00000000..6089b467 --- /dev/null +++ b/caom2utils/caom2utils/tests/data/taos_h5file/def/attrs.blueprint @@ -0,0 +1,51 @@ +Observation.algorithm.name = ['PROGRAM'] +Observation.metaRelease = 2018-05-21T02:07:22.0 +Observation.type = OBJECT +Observation.target.name = ['object_name'] +Plane.calibrationLevel = 2 +Plane.dataProductType = timeseries + +Chunk.position.axis.function.dimension.naxis1 = ['NAXIS1'] +Chunk.position.axis.function.dimension.naxis2 = ['NAXIS2'] +Chunk.position.axis.function.refCoord.coord1.pix = ['CRPIX1'] +Chunk.position.axis.function.refCoord.coord1.val = ['CRVAL1'] +Chunk.position.axis.function.refCoord.coord2.pix = ['CRPIX2'] +Chunk.position.axis.function.refCoord.coord2.val = ['CRVAL2'] +Chunk.position.axis.axis1.ctype = ['CTYPE1'] +Chunk.position.axis.axis1.cunit = ['CUNIT1'] +Chunk.position.axis.axis2.ctype = ['CTYPE2'] +Chunk.position.axis.axis2.cunit = ['CUNIT2'] +Chunk.position.axis.function.cd11 = ['PC1_1'] +Chunk.position.axis.function.cd12 = ['PC1_2'] +Chunk.position.axis.function.cd21 = ['PC2_1'] +Chunk.position.axis.function.cd22 = ['PC2_2'] +Chunk.position.equinox = ['EQUINOX'] +Chunk.position.axis.error1.syser = None +Chunk.position.axis.error1.rnder= None +Chunk.position.axis.error2.syser = None +Chunk.position.axis.error2.rnder = None +Chunk.position.coordsys = None + +Chunk.energyAxis = 4 +Chunk.energy.bandpassName = ['filter_name'] +Chunk.energy.resolvingPower = _get_energy_resolving_power() +Chunk.energy.specsys = TOPOCENT +Chunk.energy.axis.function.naxis = 1 +Chunk.energy.axis.axis.ctype = WAVE +Chunk.energy.axis.axis.cunit = nm +Chunk.energy.axis.function.delta = ['exposure_time'] +Chunk.energy.axis.function.refCoord.pix = 0.5 +Chunk.energy.axis.function.refCoord.val = _get_fwhm() + +Chunk.timeAxis = 3 +Chunk.time.axis.axis.ctype = TIME +Chunk.time.axis.axis.cunit = s +Chunk.time.axis.function.naxis = 1 +Chunk.time.axis.function.delta = ['exposure_time'] +Chunk.time.axis.function.refCoord.pix = 0.5 +Chunk.time.axis.function.refCoord.val = _get_datetime() +Chunk.time.axis.error.rnder = None +Chunk.time.axis.error.syser = None +Chunk.time.exposure = _get_exposure() +Chunk.time.timesys = MJD +Chunk.time.mjdref = None diff --git a/caom2utils/caom2utils/tests/data/taos_h5file/def/def.h5 b/caom2utils/caom2utils/tests/data/taos_h5file/def/def.h5 new file mode 100644 index 0000000000000000000000000000000000000000..937a2aea1260acff615176376c5a329324da85be GIT binary patch literal 32784 zcmeHwcU%+Qvv;syELgCM1q*fvAgJi-4n$OxfKu%gDS|X12sZ4BH4(em5xZhn?245= zXYF7YyJD9FJHBT(yH9*jZhU^f-@Whsys!I5zS-S#W@qNi%qg>FM$c~DO)Au@AmKKt zR8mG#mH#XLd>6K=6Ld$!eet}%@W)8NWC1sp()}@#43}`{>IlcH3iQoO>keEjqeCwb zXJ_u8NMA(V*+0MkziXhUvtu7l2mJ&^NCiA6*qN})+Zy+uFDxGXH&C=!(SWNC(-EsA zvF866NyRd-v$2={YppWE&a>-w*N+b55o5EUjK|5e!4za|97w7@K^PH99@6o`qLEB_tpHu ze{p?M|2MARw@TE;Ax(Od`tW!Cd-d<*Os-$o$cT?jT=diFT-S=C{wr~{bcgu!zobL> z_$PEY)BTB#x0?%R4~FRQ<{|LI{r@GM-{9v*I$S8$(?ry(TpOZl{A%w^S{9hx9POl0_ z&)(btLwe@02VbteQzrw$`2O?K|1qT3Oq6w6k{56{sSV z6Xo)BYsViE%z=#FbXy60+E{b!_OY{(DQv85{JMt)M+DjZ_}`BZEWYojtK#S0!^YYw zJUY;-JMl)HcoAW7O8$b?gzJKUR>g@F-~TU&4hssgHx=mokIG|f^_M)=|6}slT5J6;T%ar3`H$D<17WPLV`=zn#@0o}Yi*ktugc^~ALe{q=O~seC=MepOOE z?l`yoRL|Ydvv>cJ>*;E7^?LGujmSy>x6VaoBYxsq7k9$Yx(q*#6nNm)B7Q~B%SGYL zU*tFF@#A@c9tZk$9%CJU9^Lq%>hG-+n?v#XedIQN+{%Zc`o`A5Ce2FKKK85nq&W=M zU$x=1R8@Mz(Vy$v{?_&5rKL^M%Kf_j?_7WLBKK0&ifWN{av
sh+>zCIrAJvE+C?&lzgp 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 Aa{vGU literal 0 HcmV?d00001 diff --git a/caom2utils/caom2utils/tests/data/taos_h5file/def/def.module b/caom2utils/caom2utils/tests/data/taos_h5file/def/def.module new file mode 100644 index 00000000..2bf6d8ef --- /dev/null +++ b/caom2utils/caom2utils/tests/data/taos_h5file/def/def.module @@ -0,0 +1,62 @@ +from astropy.time import Time +from datetime import datetime + + +def _get_datetime(base): + b = base.get('base').attrs + result = None + d = b.get('OBS_DATE') + t = b.get('OBS_TIME') + if d is not None and t is not None: + dt = f'{d} {t}' + result = Time(datetime.strptime(dt, '%Y-%m-%d %H:%M:%S.%f')) + result.format = 'mjd' + result = result.value + return result + + +def _get_energy_resolving_power(base): + b = base.get('base').attrs + result = None + # Laurie Rousseau-Nepton - 11-08-22 + # Resolving Power could be given at the central wavelength of the filter. + # The formula is R = 1/lambda[nm]* (2*(STEP[nm]*(NAXIS3-zpd_index))/1.2067 + step = b.get('STEP') + zpd_index = b.get('zpd_index') + naxis_3 = b.get('step_nb') + filter_max = b.get('filter_nm_max') + filter_min = b.get('filter_nm_min') + wl = None + if filter_max is not None and filter_min is not None: + wl = (filter_min + filter_max) / 2 + if ( + step is not None + and zpd_index is not None + and naxis_3 is not None + and wl is not None + ): + result = 1 / wl * 2 * (step * (naxis_3 - zpd_index)) / 1.2067 + return result + + +def _get_exposure(base): + b = base.get('base').attrs + # Laurie Rousseau-Nepton - 11-08-22 + # Int. Time could be the total (multiplied by the cube spectral dimension + # f.attrs.get(‘NAXIS3’) + result = None + exposure = b.get('exposure_time') + naxis_3 = b.get('step_nb') + if exposure is not None and naxis_3 is not None: + result = exposure * naxis_3 + return result + + +def _get_fwhm(base): + b = base.get('base').attrs + minimum = b.get('filter_nm_min') + maximum = b.get('filter_nm_max') + result = None + if minimum is not None and maximum is not None: + result = (maximum - minimum) / 2 + return result diff --git a/caom2utils/caom2utils/tests/data/taos_h5file/def/def.py b/caom2utils/caom2utils/tests/data/taos_h5file/def/def.py new file mode 100644 index 00000000..2bf6d8ef --- /dev/null +++ b/caom2utils/caom2utils/tests/data/taos_h5file/def/def.py @@ -0,0 +1,62 @@ +from astropy.time import Time +from datetime import datetime + + +def _get_datetime(base): + b = base.get('base').attrs + result = None + d = b.get('OBS_DATE') + t = b.get('OBS_TIME') + if d is not None and t is not None: + dt = f'{d} {t}' + result = Time(datetime.strptime(dt, '%Y-%m-%d %H:%M:%S.%f')) + result.format = 'mjd' + result = result.value + return result + + +def _get_energy_resolving_power(base): + b = base.get('base').attrs + result = None + # Laurie Rousseau-Nepton - 11-08-22 + # Resolving Power could be given at the central wavelength of the filter. + # The formula is R = 1/lambda[nm]* (2*(STEP[nm]*(NAXIS3-zpd_index))/1.2067 + step = b.get('STEP') + zpd_index = b.get('zpd_index') + naxis_3 = b.get('step_nb') + filter_max = b.get('filter_nm_max') + filter_min = b.get('filter_nm_min') + wl = None + if filter_max is not None and filter_min is not None: + wl = (filter_min + filter_max) / 2 + if ( + step is not None + and zpd_index is not None + and naxis_3 is not None + and wl is not None + ): + result = 1 / wl * 2 * (step * (naxis_3 - zpd_index)) / 1.2067 + return result + + +def _get_exposure(base): + b = base.get('base').attrs + # Laurie Rousseau-Nepton - 11-08-22 + # Int. Time could be the total (multiplied by the cube spectral dimension + # f.attrs.get(‘NAXIS3’) + result = None + exposure = b.get('exposure_time') + naxis_3 = b.get('step_nb') + if exposure is not None and naxis_3 is not None: + result = exposure * naxis_3 + return result + + +def _get_fwhm(base): + b = base.get('base').attrs + minimum = b.get('filter_nm_min') + maximum = b.get('filter_nm_max') + result = None + if minimum is not None and maximum is not None: + result = (maximum - minimum) / 2 + return result diff --git a/caom2utils/caom2utils/tests/data/taos_h5file/def/def.xml b/caom2utils/caom2utils/tests/data/taos_h5file/def/def.xml new file mode 100644 index 00000000..e2ca5eaf --- /dev/null +++ b/caom2utils/caom2utils/tests/data/taos_h5file/def/def.xml @@ -0,0 +1,114 @@ + + + def + def + 2018-05-21T02:07:22.0 + + ORB + + OBJECT + science + + M101_Field4 + + + + def + timeseries + 2 + + + cadc:def/def.h5 + science + data + application/x-hdf5 + 32784 + md5:5a28f24e62324c1a12ff76a46c59bc54 + + + 0 + + + 1 + 2 + 4 + 3 + + + + RA---TAN-SIP + deg + + + DEC--TAN-SIP + deg + + + + 2048 + 2064 + + + + 1073.5 + 210.97094060537 + + + 1031.5 + 54.268513730755 + + + -8.7769937953286e-05 + -6.8586770533601e-07 + -6.8634246910166e-07 + 8.7709224842659e-05 + + + 2000.0 + + + + + WAVE + nm + + + 1 + 0.0 + + 0.5 + 18.649999999999977 + + + + TOPOCENT + SN3 + 4926.487818556442 + + + + + TIME + s + + + 1 + 0.0 + + 0.5 + 59694.3770853125 + + + + MJD + 11198.6 + + + + + + + + + + diff --git a/caom2utils/caom2utils/tests/test_collections.py b/caom2utils/caom2utils/tests/test_collections.py index 59964286..802c9c06 100644 --- a/caom2utils/caom2utils/tests/test_collections.py +++ b/caom2utils/caom2utils/tests/test_collections.py @@ -232,8 +232,10 @@ def _get_cardinality(directory): return '--lineage catalog/vos://cadc.nrc.ca!vospace/CAOMworkshop/' \ 'Examples/DAO/dao_c122_2016_012725.fits' elif 'taos_' in directory: - return '--lineage star04239531/' \ - 'cadc:TAOSII/taos2_20220201T201317Z_star04239531.h5' + if 'def' in directory: + return '--lineage def/cadc:def/def.h5' + else: + return '--lineage star04239531/cadc:TAOSII/taos2_20220201T201317Z_star04239531.h5' else: return '' diff --git a/caom2utils/caom2utils/tests/test_fits2caom2.py b/caom2utils/caom2utils/tests/test_fits2caom2.py index 1c0b3e0c..d71d9841 100755 --- a/caom2utils/caom2utils/tests/test_fits2caom2.py +++ b/caom2utils/caom2utils/tests/test_fits2caom2.py @@ -188,7 +188,10 @@ def test_hdf5_wcs_parser_set_wcs(): test_observable_bp, test_custom_bp, ]: - test_subject = Hdf5Parser(bp, test_uri, test_fqn) + # limit the cases where h5py needs to be installed + import h5py + temp = h5py.File(test_fqn) + test_subject = Hdf5Parser(bp, test_uri, temp) assert test_subject is not None, 'expect a result' test_subject.augment_artifact(test_artifact) if bp == test_position_bp: diff --git a/caom2utils/setup.cfg b/caom2utils/setup.cfg index 4b70fefe..462b5417 100644 --- a/caom2utils/setup.cfg +++ b/caom2utils/setup.cfg @@ -33,7 +33,7 @@ url = https://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2 edit_on_github = False github_project = opencadc/caom2tools # version should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) -version = 1.6.5 +version = 1.6.6 [options] install_requires = @@ -55,4 +55,4 @@ test = [entry_points] fits2caom2 = caom2utils.legacy:main_app -caom2gen = caom2utils.fits2caom2:caom2gen +caom2gen = caom2utils.caom2blueprint:caom2gen