From 8c5d48c16faf7d1960aa737b85b7cde00a5c7d35 Mon Sep 17 00:00:00 2001 From: Colm Talbot Date: Thu, 17 Apr 2025 15:53:52 -0500 Subject: [PATCH 1/8] MAINT: remove unsupported roq json weight file format --- bilby/gw/likelihood/roq.py | 148 ++++++++++++------------------------- test/gw/likelihood_test.py | 14 +--- 2 files changed, 51 insertions(+), 111 deletions(-) diff --git a/bilby/gw/likelihood/roq.py b/bilby/gw/likelihood/roq.py index 8f13a7ae3..000d358af 100644 --- a/bilby/gw/likelihood/roq.py +++ b/bilby/gw/likelihood/roq.py @@ -1,10 +1,7 @@ -import json - import numpy as np from .base import GravitationalWaveTransient -from ...core.utils import BilbyJsonEncoder, decode_bilby_json from ...core.utils import ( logger, create_frequency_series, speed_of_light, radius_of_earth ) @@ -992,84 +989,55 @@ def _set_weights_quadratic_multiband(self, quadratic_matrix, basis_idxs): def save_weights(self, filename, format='hdf5'): """ - Save ROQ weights into a single file. format should be npz, or hdf5. - For weights from multiple bases, hdf5 is only the possible option. - Support for json format is deprecated as of :code:`v2.1` and will be - removed in :code:`v2.2`, another method should be used by default. + Save ROQ weights into a single file. + Support for json format was removed in :code:`v2.5`, only hdf5 is supported. Parameters ========== filename : str The name of the file to save the weights to. - format : str - The format to save the data to, this should be one of - :code:`"hdf5"`, :code:`"npz"`, default=:code:`"hdf5"`. + format : str (deprecated) + This argument has no effect after removing support for json weight files. """ - if format not in ['json', 'npz', 'hdf5']: + if format != 'hdf5': raise IOError(f"Format {format} not recognized.") - if format == "json": - import warnings - - warnings.warn( - "json format for ROQ weights is deprecated, use hdf5 instead.", - DeprecationWarning - ) if format not in filename: filename += "." + format logger.info(f"Saving ROQ weights to {filename}") - if format == 'json' or format == 'npz': - if self.number_of_bases_linear > 1 or self.number_of_bases_quadratic > 1: - raise ValueError(f'Format {format} not compatible with multiple bases') - weights = dict() - weights['time_samples'] = self.weights['time_samples'] + import h5py + with h5py.File(filename, 'w') as f: + f.create_dataset('time_samples', + data=self.weights['time_samples']) for basis_type in ['linear', 'quadratic']: + key = f'prior_range_{basis_type}' + if key in self.weights: + grp = f.create_group(key) + for param_name in self.weights[key]: + grp.create_dataset( + param_name, data=self.weights[key][param_name]) + key = f'frequency_nodes_{basis_type}' + if key in self.weights: + grp = f.create_group(key) + for i in range(len(self.weights[key])): + grp.create_dataset( + str(i), data=self.weights[key][i]) for ifo in self.interferometers: - key = f'{ifo.name}_{basis_type}' - weights[key] = self.weights[key][0] - if format == 'json': - with open(filename, 'w') as file: - json.dump(weights, file, indent=2, cls=BilbyJsonEncoder) - else: - np.savez(filename, **weights) - else: - import h5py - with h5py.File(filename, 'w') as f: - f.create_dataset('time_samples', - data=self.weights['time_samples']) - for basis_type in ['linear', 'quadratic']: - key = f'prior_range_{basis_type}' - if key in self.weights: - grp = f.create_group(key) - for param_name in self.weights[key]: - grp.create_dataset( - param_name, data=self.weights[key][param_name]) - key = f'frequency_nodes_{basis_type}' - if key in self.weights: - grp = f.create_group(key) - for i in range(len(self.weights[key])): - grp.create_dataset( - str(i), data=self.weights[key][i]) - for ifo in self.interferometers: - key = f"{ifo.name}_{basis_type}" - grp = f.create_group(key) - for i in range(len(self.weights[key])): - grp.create_dataset( - str(i), data=self.weights[key][i]) + key = f"{ifo.name}_{basis_type}" + grp = f.create_group(key) + for i in range(len(self.weights[key])): + grp.create_dataset( + str(i), data=self.weights[key][i]) def load_weights(self, filename, format=None): """ - Load ROQ weights. format should be json, npz, or hdf5. - json or npz file is assumed to contain weights from a single basis. - Support for json format is deprecated as of :code:`v2.1` and will be - removed in :code:`v2.2`, another method should be used by default. + Load ROQ weights. Support for json format was removed in :code:`v2.2`. Parameters ========== filename : str The name of the file to save the weights to. - format : str - The format to save the data to, this should be one of - :code:`"hdf5"`, :code:`"npz"`, default=:code:`"hdf5"`. + format : str (deprecated) + This argument is no longer used after removing json support. Returns ======= @@ -1078,49 +1046,29 @@ def load_weights(self, filename, format=None): """ if format is None: format = filename.split(".")[-1] - if format not in ["json", "npz", "hdf5"]: + if format != "hdf5": raise IOError(f"Format {format} not recognized.") - if format == "json": - import warnings - - warnings.warn( - "json format for ROQ weights is deprecated, use hdf5 instead.", - DeprecationWarning - ) logger.info(f"Loading ROQ weights from {filename}") - if format == "json" or format == "npz": - # Old file format assumed to contain only a single basis - if format == "json": - with open(filename, 'r') as file: - weights = json.load(file, object_hook=decode_bilby_json) - else: - # Wrap in dict to load data into memory - weights = dict(np.load(filename)) + weights = dict() + import h5py + with h5py.File(filename, 'r') as f: + weights['time_samples'] = f['time_samples'][()] for basis_type in ['linear', 'quadratic']: + key = f'prior_range_{basis_type}' + if key in f: + idxs_in_prior_range, selected_prior_ranges = \ + self._select_prior_ranges(f[key]) + weights[key] = selected_prior_ranges + else: + idxs_in_prior_range = [0] + key = f'frequency_nodes_{basis_type}' + if key in f: + weights[key] = [f[key][str(i)][()] + for i in idxs_in_prior_range] for ifo in self.interferometers: - key = f'{ifo.name}_{basis_type}' - weights[key] = [weights[key]] - else: - weights = dict() - import h5py - with h5py.File(filename, 'r') as f: - weights['time_samples'] = f['time_samples'][()] - for basis_type in ['linear', 'quadratic']: - key = f'prior_range_{basis_type}' - if key in f: - idxs_in_prior_range, selected_prior_ranges = \ - self._select_prior_ranges(f[key]) - weights[key] = selected_prior_ranges - else: - idxs_in_prior_range = [0] - key = f'frequency_nodes_{basis_type}' - if key in f: - weights[key] = [f[key][str(i)][()] - for i in idxs_in_prior_range] - for ifo in self.interferometers: - key = f"{ifo.name}_{basis_type}" - weights[key] = [f[key][str(i)][()] - for i in idxs_in_prior_range] + key = f"{ifo.name}_{basis_type}" + weights[key] = [f[key][str(i)][()] + for i in idxs_in_prior_range] return weights def _get_time_resolution(self): diff --git a/test/gw/likelihood_test.py b/test/gw/likelihood_test.py index 84298e1d9..3e98887d7 100644 --- a/test/gw/likelihood_test.py +++ b/test/gw/likelihood_test.py @@ -1088,18 +1088,10 @@ def test_in_multiple_bases(self, multiband): ) self.check_weights_are_same(likelihood, likelihood_from_weights) - @parameterized.expand(product(['npz', 'json'], [False, True])) - def test_out_multiple_bases_inconsistent_format(self, format, multiband): - "npz or json format is not compatible with multiple bases" - likelihood = self.create_likelihood_multiple_bases(multiband) - with self.assertRaises(ValueError): - likelihood.save_weights('weights', format=format) - def tearDown(self): - for format in ['npz', 'json', 'hdf5']: - filename = f'weights.{format}' - if os.path.exists(filename): - os.remove(filename) + filename = f'weights.hdf5' + if os.path.exists(filename): + os.remove(filename) @staticmethod def check_weights_are_same(l1, l2): From 42094d00d8142d2b496531c892356ffca336153c Mon Sep 17 00:00:00 2001 From: Colm Talbot Date: Mon, 21 Apr 2025 15:04:22 -0500 Subject: [PATCH 2/8] BUG: CI fixes --- bilby/gw/likelihood/roq.py | 3 +-- test/gw/likelihood_test.py | 32 +++++++++++++++++--------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/bilby/gw/likelihood/roq.py b/bilby/gw/likelihood/roq.py index 000d358af..c8020b16d 100644 --- a/bilby/gw/likelihood/roq.py +++ b/bilby/gw/likelihood/roq.py @@ -1006,8 +1006,7 @@ def save_weights(self, filename, format='hdf5'): logger.info(f"Saving ROQ weights to {filename}") import h5py with h5py.File(filename, 'w') as f: - f.create_dataset('time_samples', - data=self.weights['time_samples']) + f.create_dataset('time_samples', data=self.weights['time_samples']) for basis_type in ['linear', 'quadratic']: key = f'prior_range_{basis_type}' if key in self.weights: diff --git a/test/gw/likelihood_test.py b/test/gw/likelihood_test.py index 3e98887d7..3b1729a7e 100644 --- a/test/gw/likelihood_test.py +++ b/test/gw/likelihood_test.py @@ -1046,18 +1046,22 @@ def test_from_npy(self, from_array): @pytest.mark.requires_roqs class TestInOutROQWeights(unittest.TestCase): - @parameterized.expand(['npz', 'hdf5']) - def test_out_single_basis(self, format): + def test_out_single_basis(self): likelihood = self.create_likelihood_single_basis() - filename = f'weights.{format}' - likelihood.save_weights(filename, format=format) + filename = 'weights.hdf5' + likelihood.save_weights(filename, format='hdf5') self.assertTrue(os.path.exists(filename)) - @parameterized.expand(['npz', 'hdf5']) - def test_in_single_basis(self, format): + def test_saving_wrong_format_fails(self): likelihood = self.create_likelihood_single_basis() - filename = f'weights.{format}' - likelihood.save_weights(filename, format=format) + filename = 'weights.npz' + with self.assertRaises(IOError): + likelihood.save_weights(filename, format='npz') + + def test_in_single_basis(self): + likelihood = self.create_likelihood_single_basis() + filename = 'weights.hdf5' + likelihood.save_weights(filename, format='hdf5') likelihood_from_weights = bilby.gw.likelihood.ROQGravitationalWaveTransient( interferometers=likelihood.interferometers, priors=likelihood.priors, @@ -1068,18 +1072,16 @@ def test_in_single_basis(self, format): @parameterized.expand([(False, ), (True, )]) def test_out_multiple_bases(self, multiband): - format = 'hdf5' - filename = f'weights.{format}' + filename = 'weights.hdf5' likelihood = self.create_likelihood_multiple_bases(multiband) - likelihood.save_weights(filename, format=format) + likelihood.save_weights(filename, format='hdf5') self.assertTrue(os.path.exists(filename)) @parameterized.expand([(False, ), (True, )]) def test_in_multiple_bases(self, multiband): - format = 'hdf5' - filename = f'weights.{format}' + filename = 'weights.hdf5' likelihood = self.create_likelihood_multiple_bases(multiband) - likelihood.save_weights(filename, format=format) + likelihood.save_weights(filename, format='hdf5') likelihood_from_weights = bilby.gw.likelihood.ROQGravitationalWaveTransient( interferometers=likelihood.interferometers, priors=likelihood.priors, @@ -1089,7 +1091,7 @@ def test_in_multiple_bases(self, multiband): self.check_weights_are_same(likelihood, likelihood_from_weights) def tearDown(self): - filename = f'weights.hdf5' + filename = 'weights.hdf5' if os.path.exists(filename): os.remove(filename) From 4bddab18e513250c397e84a684ec7db95dd20b6a Mon Sep 17 00:00:00 2001 From: Colm Talbot Date: Thu, 12 Jun 2025 13:40:17 -0500 Subject: [PATCH 3/8] DEP: restore npz weight format --- bilby/gw/likelihood/roq.py | 119 ++++++++++++++++++++++--------------- test/gw/likelihood_test.py | 14 ++++- 2 files changed, 82 insertions(+), 51 deletions(-) diff --git a/bilby/gw/likelihood/roq.py b/bilby/gw/likelihood/roq.py index c8020b16d..08f073231 100644 --- a/bilby/gw/likelihood/roq.py +++ b/bilby/gw/likelihood/roq.py @@ -990,53 +990,64 @@ def _set_weights_quadratic_multiband(self, quadratic_matrix, basis_idxs): def save_weights(self, filename, format='hdf5'): """ Save ROQ weights into a single file. - Support for json format was removed in :code:`v2.5`, only hdf5 is supported. + Support for json format was removed in :code:`v2.6`, only hdf5 and npz are supported. Parameters ========== filename : str The name of the file to save the weights to. - format : str (deprecated) - This argument has no effect after removing support for json weight files. + format : str + The format to save the weight in, should be in :code:`hdf5, npz`. """ - if format != 'hdf5': + if format not in ['hdf5', 'npz']: raise IOError(f"Format {format} not recognized.") if format not in filename: filename += "." + format logger.info(f"Saving ROQ weights to {filename}") - import h5py - with h5py.File(filename, 'w') as f: - f.create_dataset('time_samples', data=self.weights['time_samples']) + if format == 'npz': + if self.number_of_bases_linear > 1 or self.number_of_bases_quadratic > 1: + raise ValueError(f'Format {format} not compatible with multiple bases') + weights = dict() + weights['time_samples'] = self.weights['time_samples'] for basis_type in ['linear', 'quadratic']: - key = f'prior_range_{basis_type}' - if key in self.weights: - grp = f.create_group(key) - for param_name in self.weights[key]: - grp.create_dataset( - param_name, data=self.weights[key][param_name]) - key = f'frequency_nodes_{basis_type}' - if key in self.weights: - grp = f.create_group(key) - for i in range(len(self.weights[key])): - grp.create_dataset( - str(i), data=self.weights[key][i]) for ifo in self.interferometers: - key = f"{ifo.name}_{basis_type}" - grp = f.create_group(key) - for i in range(len(self.weights[key])): - grp.create_dataset( - str(i), data=self.weights[key][i]) - + key = f'{ifo.name}_{basis_type}' + weights[key] = self.weights[key][0] + np.savez(filename, **weights) + else: + import h5py + with h5py.File(filename, 'w') as f: + f.create_dataset('time_samples', + data=self.weights['time_samples']) + for basis_type in ['linear', 'quadratic']: + key = f'prior_range_{basis_type}' + if key in self.weights: + grp = f.create_group(key) + for param_name in self.weights[key]: + grp.create_dataset( + param_name, data=self.weights[key][param_name]) + key = f'frequency_nodes_{basis_type}' + if key in self.weights: + grp = f.create_group(key) + for i in range(len(self.weights[key])): + grp.create_dataset( + str(i), data=self.weights[key][i]) + for ifo in self.interferometers: + key = f"{ifo.name}_{basis_type}" + grp = f.create_group(key) + for i in range(len(self.weights[key])): + grp.create_dataset( + str(i), data=self.weights[key][i]) def load_weights(self, filename, format=None): """ - Load ROQ weights. Support for json format was removed in :code:`v2.2`. + Load ROQ weights. Support for json format was removed in :code:`v2.6`. Parameters ========== filename : str The name of the file to save the weights to. - format : str (deprecated) - This argument is no longer used after removing json support. + format : str + The format of the weight file, should be in :code:`hdf5, npz`. Returns ======= @@ -1045,29 +1056,41 @@ def load_weights(self, filename, format=None): """ if format is None: format = filename.split(".")[-1] - if format != "hdf5": - raise IOError(f"Format {format} not recognized.") + if format == "json": + import warnings + + warnings.warn( + "json format for ROQ weights is deprecated, use hdf5 instead.", + DeprecationWarning + ) logger.info(f"Loading ROQ weights from {filename}") - weights = dict() - import h5py - with h5py.File(filename, 'r') as f: - weights['time_samples'] = f['time_samples'][()] + if format == "npz": + weights = dict(np.load(filename)) for basis_type in ['linear', 'quadratic']: - key = f'prior_range_{basis_type}' - if key in f: - idxs_in_prior_range, selected_prior_ranges = \ - self._select_prior_ranges(f[key]) - weights[key] = selected_prior_ranges - else: - idxs_in_prior_range = [0] - key = f'frequency_nodes_{basis_type}' - if key in f: - weights[key] = [f[key][str(i)][()] - for i in idxs_in_prior_range] for ifo in self.interferometers: - key = f"{ifo.name}_{basis_type}" - weights[key] = [f[key][str(i)][()] - for i in idxs_in_prior_range] + key = f'{ifo.name}_{basis_type}' + weights[key] = [weights[key]] + else: + weights = dict() + import h5py + with h5py.File(filename, 'r') as f: + weights['time_samples'] = f['time_samples'][()] + for basis_type in ['linear', 'quadratic']: + key = f'prior_range_{basis_type}' + if key in f: + idxs_in_prior_range, selected_prior_ranges = \ + self._select_prior_ranges(f[key]) + weights[key] = selected_prior_ranges + else: + idxs_in_prior_range = [0] + key = f'frequency_nodes_{basis_type}' + if key in f: + weights[key] = [f[key][str(i)][()] + for i in idxs_in_prior_range] + for ifo in self.interferometers: + key = f"{ifo.name}_{basis_type}" + weights[key] = [f[key][str(i)][()] + for i in idxs_in_prior_range] return weights def _get_time_resolution(self): diff --git a/test/gw/likelihood_test.py b/test/gw/likelihood_test.py index 3b1729a7e..d4fb65de9 100644 --- a/test/gw/likelihood_test.py +++ b/test/gw/likelihood_test.py @@ -1090,10 +1090,18 @@ def test_in_multiple_bases(self, multiband): ) self.check_weights_are_same(likelihood, likelihood_from_weights) + @parameterized.expand([(False, ), (True, )]) + def test_out_multiple_bases_inconsistent_format(self, multiband): + "npz format is not compatible with multiple bases" + likelihood = self.create_likelihood_multiple_bases(multiband) + with self.assertRaises(ValueError): + likelihood.save_weights('weights', format="npz") + def tearDown(self): - filename = 'weights.hdf5' - if os.path.exists(filename): - os.remove(filename) + for format in ['npz', 'hdf5']: + filename = f'weights.{format}' + if os.path.exists(filename): + os.remove(filename) @staticmethod def check_weights_are_same(l1, l2): From 4567d6070d83b1041ec792f7a6bc25b01fa1729a Mon Sep 17 00:00:00 2001 From: Colm Talbot Date: Thu, 12 Jun 2025 13:42:56 -0500 Subject: [PATCH 4/8] TYPO: add missing line --- bilby/gw/likelihood/roq.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bilby/gw/likelihood/roq.py b/bilby/gw/likelihood/roq.py index 08f073231..6782d62fe 100644 --- a/bilby/gw/likelihood/roq.py +++ b/bilby/gw/likelihood/roq.py @@ -1038,6 +1038,7 @@ def save_weights(self, filename, format='hdf5'): for i in range(len(self.weights[key])): grp.create_dataset( str(i), data=self.weights[key][i]) + def load_weights(self, filename, format=None): """ Load ROQ weights. Support for json format was removed in :code:`v2.6`. From eb23bcd2cfb441c0d1eba587efe7a49ec6d2d908 Mon Sep 17 00:00:00 2001 From: Colm Talbot Date: Tue, 24 Jun 2025 09:16:18 -0500 Subject: [PATCH 5/8] TST: fix broken test --- test/gw/likelihood_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/gw/likelihood_test.py b/test/gw/likelihood_test.py index d4fb65de9..f8e6e1d60 100644 --- a/test/gw/likelihood_test.py +++ b/test/gw/likelihood_test.py @@ -1054,9 +1054,9 @@ def test_out_single_basis(self): def test_saving_wrong_format_fails(self): likelihood = self.create_likelihood_single_basis() - filename = 'weights.npz' + filename = 'weights.json' with self.assertRaises(IOError): - likelihood.save_weights(filename, format='npz') + likelihood.save_weights(filename, format='json') def test_in_single_basis(self): likelihood = self.create_likelihood_single_basis() From c95758a61087464e225a0e71b82721ef4f796e95 Mon Sep 17 00:00:00 2001 From: Colm Talbot Date: Thu, 18 Sep 2025 10:24:35 -0400 Subject: [PATCH 6/8] Revert some changes raised in review --- bilby/gw/likelihood/roq.py | 3 +++ test/gw/likelihood_test.py | 14 ++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/bilby/gw/likelihood/roq.py b/bilby/gw/likelihood/roq.py index 6782d62fe..2b5708ca0 100644 --- a/bilby/gw/likelihood/roq.py +++ b/bilby/gw/likelihood/roq.py @@ -1064,6 +1064,9 @@ def load_weights(self, filename, format=None): "json format for ROQ weights is deprecated, use hdf5 instead.", DeprecationWarning ) + elif format not in ["npz", "hdf5"]: + raise IOError(f"Format {format} not recognized.") + logger.info(f"Loading ROQ weights from {filename}") if format == "npz": weights = dict(np.load(filename)) diff --git a/test/gw/likelihood_test.py b/test/gw/likelihood_test.py index f8e6e1d60..76a74c708 100644 --- a/test/gw/likelihood_test.py +++ b/test/gw/likelihood_test.py @@ -1046,10 +1046,11 @@ def test_from_npy(self, from_array): @pytest.mark.requires_roqs class TestInOutROQWeights(unittest.TestCase): - def test_out_single_basis(self): + @parameterized.expand(['npz', 'hdf5']) + def test_out_single_basis(self, format): likelihood = self.create_likelihood_single_basis() - filename = 'weights.hdf5' - likelihood.save_weights(filename, format='hdf5') + filename = f'weights.{format}' + likelihood.save_weights(filename, format=format) self.assertTrue(os.path.exists(filename)) def test_saving_wrong_format_fails(self): @@ -1058,10 +1059,11 @@ def test_saving_wrong_format_fails(self): with self.assertRaises(IOError): likelihood.save_weights(filename, format='json') - def test_in_single_basis(self): + @parameterized.expand(['npz', 'hdf5']) + def test_in_single_basis(self, format): likelihood = self.create_likelihood_single_basis() - filename = 'weights.hdf5' - likelihood.save_weights(filename, format='hdf5') + filename = f'weights.{format}' + likelihood.save_weights(filename, format=format) likelihood_from_weights = bilby.gw.likelihood.ROQGravitationalWaveTransient( interferometers=likelihood.interferometers, priors=likelihood.priors, From b27430f023a9d618eac366991091f0e70caec959 Mon Sep 17 00:00:00 2001 From: Colm Talbot Date: Mon, 29 Sep 2025 07:25:11 -0400 Subject: [PATCH 7/8] Update removal version in docs Co-authored-by: Michael J. Williams --- bilby/gw/likelihood/roq.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bilby/gw/likelihood/roq.py b/bilby/gw/likelihood/roq.py index 2b5708ca0..1fad97373 100644 --- a/bilby/gw/likelihood/roq.py +++ b/bilby/gw/likelihood/roq.py @@ -990,7 +990,7 @@ def _set_weights_quadratic_multiband(self, quadratic_matrix, basis_idxs): def save_weights(self, filename, format='hdf5'): """ Save ROQ weights into a single file. - Support for json format was removed in :code:`v2.6`, only hdf5 and npz are supported. + Support for json format was removed in :code:`v2.7`, only hdf5 and npz are supported. Parameters ========== From 04b9ab1208ec8c2afb5f9b19f2b2b6814226178c Mon Sep 17 00:00:00 2001 From: Colm Talbot Date: Thu, 2 Oct 2025 07:22:49 -0400 Subject: [PATCH 8/8] DOC: fix json roq weight removal version --- bilby/gw/likelihood/roq.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bilby/gw/likelihood/roq.py b/bilby/gw/likelihood/roq.py index 1fad97373..493ee66c5 100644 --- a/bilby/gw/likelihood/roq.py +++ b/bilby/gw/likelihood/roq.py @@ -1041,7 +1041,7 @@ def save_weights(self, filename, format='hdf5'): def load_weights(self, filename, format=None): """ - Load ROQ weights. Support for json format was removed in :code:`v2.6`. + Load ROQ weights. Support for json format was removed in :code:`v2.7`. Parameters ==========