sdgym 0.15.2.dev0__tar.gz → 0.16.1.dev0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. {sdgym-0.15.2.dev0/sdgym.egg-info → sdgym-0.16.1.dev0}/PKG-INFO +3 -3
  2. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/pyproject.toml +3 -3
  3. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/__init__.py +1 -1
  4. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_benchmark/credentials_utils.py +1 -1
  5. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/benchmark.py +12 -0
  6. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/result_explorer/result_explorer.py +28 -1
  7. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/result_explorer/result_handler.py +22 -0
  8. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/result_writer.py +18 -0
  9. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0/sdgym.egg-info}/PKG-INFO +3 -3
  10. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym.egg-info/requires.txt +2 -2
  11. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/LICENSE +0 -0
  12. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/README.md +0 -0
  13. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_benchmark/__init__.py +0 -0
  14. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_benchmark/benchmark.py +0 -0
  15. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_benchmark_launcher/__init__.py +0 -0
  16. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_benchmark_launcher/_instance_manager.py +0 -0
  17. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_benchmark_launcher/_storage_manager.py +0 -0
  18. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_benchmark_launcher/_validation.py +0 -0
  19. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_benchmark_launcher/benchmark_base.yaml +0 -0
  20. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_benchmark_launcher/benchmark_config.py +0 -0
  21. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_benchmark_launcher/benchmark_launcher.py +0 -0
  22. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_benchmark_launcher/script.py +0 -0
  23. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_benchmark_launcher/utils.py +0 -0
  24. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/_dataset_utils.py +0 -0
  25. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/cli/__init__.py +0 -0
  26. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/cli/__main__.py +0 -0
  27. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/cli/collect.py +0 -0
  28. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/cli/summary.py +0 -0
  29. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/cli/utils.py +0 -0
  30. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/dataset_explorer.py +0 -0
  31. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/datasets.py +0 -0
  32. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/errors.py +0 -0
  33. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/metrics.py +0 -0
  34. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/progress.py +0 -0
  35. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/result_explorer/__init__.py +0 -0
  36. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/run_benchmark/__init__.py +0 -0
  37. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/run_benchmark/run_benchmark.py +0 -0
  38. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/run_benchmark/upload_benchmark_results.py +0 -0
  39. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/run_benchmark/utils.py +0 -0
  40. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/s3.py +0 -0
  41. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizer_descriptions.yaml +0 -0
  42. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizers/__init__.py +0 -0
  43. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizers/base.py +0 -0
  44. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizers/clavaddpm.py +0 -0
  45. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizers/column.py +0 -0
  46. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizers/data_designer.py +0 -0
  47. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizers/generate.py +0 -0
  48. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizers/identity.py +0 -0
  49. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizers/realtabformer.py +0 -0
  50. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizers/sdv.py +0 -0
  51. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizers/tabddpm.py +0 -0
  52. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizers/uniform.py +0 -0
  53. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/synthesizers/utils.py +0 -0
  54. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym/utils.py +0 -0
  55. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym.egg-info/SOURCES.txt +0 -0
  56. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym.egg-info/dependency_links.txt +0 -0
  57. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym.egg-info/entry_points.txt +0 -0
  58. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/sdgym.egg-info/top_level.txt +0 -0
  59. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/setup.cfg +0 -0
  60. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/tests/test_scripts.py +0 -0
  61. {sdgym-0.15.2.dev0 → sdgym-0.16.1.dev0}/tests/test_tasks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sdgym
3
- Version: 0.15.2.dev0
3
+ Version: 0.16.1.dev0
4
4
  Summary: Benchmark tabular synthetic data generators using a variety of datasets
5
5
  Author-email: "DataCebo, Inc." <info@sdv.dev>
6
6
  License-Expression: BUSL-1.1
@@ -63,8 +63,8 @@ Requires-Dist: torch>=2.6.0; python_version >= "3.13" and python_version < "3.14
63
63
  Requires-Dist: torch>=2.9.0; python_version >= "3.14"
64
64
  Requires-Dist: tqdm>=4.66.3
65
65
  Requires-Dist: XlsxWriter>=1.2.8
66
- Requires-Dist: rdt>=1.18.2; python_version < "3.14"
67
- Requires-Dist: rdt>=1.20.0; python_version >= "3.14"
66
+ Requires-Dist: rdt<2,>=1.18.2; python_version < "3.14"
67
+ Requires-Dist: rdt<2,>=1.20.0; python_version >= "3.14"
68
68
  Requires-Dist: sdmetrics>=0.29.0
69
69
  Requires-Dist: sdv<2,>=1.37.0
70
70
  Provides-Extra: dask
@@ -61,8 +61,8 @@ dependencies = [
61
61
  "torch>=2.9.0;python_version>='3.14'",
62
62
  'tqdm>=4.66.3',
63
63
  'XlsxWriter>=1.2.8',
64
- "rdt>=1.18.2;python_version<'3.14'",
65
- "rdt>=1.20.0;python_version>='3.14'",
64
+ "rdt>=1.18.2,<2;python_version<'3.14'",
65
+ "rdt>=1.20.0,<2;python_version>='3.14'",
66
66
  "sdmetrics>=0.29.0",
67
67
  "sdv>=1.37.0,<2",
68
68
  ]
@@ -177,7 +177,7 @@ namespaces = false
177
177
  version = {attr = 'sdgym.__version__'}
178
178
 
179
179
  [tool.bumpversion]
180
- current_version = "0.15.2.dev0"
180
+ current_version = "0.16.1.dev0"
181
181
  parse = '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.(?P<release>[a-z]+)(?P<candidate>\d+))?'
182
182
  serialize = [
183
183
  '{major}.{minor}.{patch}.{release}{candidate}',
@@ -8,7 +8,7 @@ __author__ = 'DataCebo, Inc.'
8
8
  __copyright__ = 'Copyright (c) 2022 DataCebo, Inc.'
9
9
  __email__ = 'info@sdv.dev'
10
10
  __license__ = 'BSL-1.1'
11
- __version__ = '0.15.2.dev0'
11
+ __version__ = '0.16.1.dev0'
12
12
 
13
13
  import logging
14
14
 
@@ -13,5 +13,5 @@ def sdv_install_cmd(credentials):
13
13
  pip install sdv-installer
14
14
 
15
15
  python -c "from sdv_installer.installation.installer import install_packages; \\
16
- install_packages(username='{username}', license_key='{license_key}')"
16
+ install_packages(username='{username}', license_key='{license_key}', version='0.53')"
17
17
  """)
@@ -268,6 +268,9 @@ def _setup_output_destination_aws(
268
268
  f's3://{bucket_name}/{synth_folder}/'
269
269
  f'{final_synth_name}_synthetic_data.{synthetic_data_extension}'
270
270
  ),
271
+ 'quality_report': (
272
+ f's3://{bucket_name}/{synth_folder}/{final_synth_name}_quality_report.pkl'
273
+ ),
271
274
  'benchmark_result': (
272
275
  f's3://{bucket_name}/{synth_folder}/{final_synth_name}_benchmark_result.csv'
273
276
  ),
@@ -335,6 +338,7 @@ def _setup_output_destination(
335
338
  'synthetic_data': str(
336
339
  synth_folder / f'{final_synth_name}_synthetic_data.{synthetic_data_extension}'
337
340
  ),
341
+ 'quality_report': str(synth_folder / f'{final_synth_name}_quality_report.pkl'),
338
342
  'benchmark_result': str(synth_folder / f'{final_synth_name}_benchmark_result.csv'),
339
343
  'metainfo': str(top_folder / f'metainfo{suffix}.yaml'),
340
344
  'results': str(top_folder / f'results{suffix}.csv'),
@@ -569,6 +573,8 @@ def _compute_scores(
569
573
  compute_privacy_score,
570
574
  modality,
571
575
  dataset_name,
576
+ synthesizer_path=None,
577
+ result_writer=None,
572
578
  ):
573
579
  metrics = metrics or []
574
580
  if modality == 'single_table':
@@ -633,6 +639,8 @@ def _compute_scores(
633
639
  quality_report.generate(real_data, synthetic_data, sdmetrics_metadata, verbose=False)
634
640
  output['quality_score_time'] = calculate_score_time(start)
635
641
  output['quality_score'] = quality_report.get_score()
642
+ if synthesizer_path is not None and result_writer is not None:
643
+ result_writer.write_report(quality_report, synthesizer_path['quality_report'])
636
644
 
637
645
  if compute_privacy_score:
638
646
  start = get_utc_now()
@@ -724,6 +732,8 @@ def _score(
724
732
  compute_privacy_score,
725
733
  modality,
726
734
  dataset_name,
735
+ synthesizer_path,
736
+ result_writer,
727
737
  )
728
738
 
729
739
  output['timeout'] = False # There was no timeout
@@ -1293,6 +1303,7 @@ def benchmark_single_table(
1293
1303
  <synthesizer_name>/
1294
1304
  synthesizer.pkl
1295
1305
  synthetic_data.csv
1306
+ quality_report.pkl
1296
1307
  show_progress (bool):
1297
1308
  Whether to use tqdm to keep track of the progress. Defaults to ``False``.
1298
1309
 
@@ -1704,6 +1715,7 @@ def benchmark_multi_table(
1704
1715
  <synthesizer_name>/
1705
1716
  synthesizer.pkl
1706
1717
  synthetic_data.csv
1718
+ quality_report.pkl
1707
1719
  show_progress (bool):
1708
1720
  Whether to use tqdm to keep track of the progress. Defaults to ``False``.
1709
1721
 
@@ -96,7 +96,7 @@ class ResultsExplorer:
96
96
  return self._handler.list()
97
97
 
98
98
  def _get_file_path(self, results_folder_name, dataset_name, synthesizer_name, file_type):
99
- """Validate access to the synthesizer or synthetic data file."""
99
+ """Validate access to the synthesizer, synthetic data or quality report file."""
100
100
  end_filename = f'{synthesizer_name}'
101
101
  if file_type == 'synthetic_data':
102
102
  # Multi-table synthetic data is zipped (multiple CSVs), single table is CSV
@@ -106,6 +106,8 @@ class ResultsExplorer:
106
106
  end_filename += '_synthetic_data.csv'
107
107
  elif file_type == 'synthesizer':
108
108
  end_filename += '.pkl'
109
+ elif file_type == 'quality_report':
110
+ end_filename += '_quality_report.pkl'
109
111
 
110
112
  date = '_'.join(results_folder_name.split('_')[-3:])
111
113
  path_parts = [results_folder_name, f'{dataset_name}_{date}', synthesizer_name]
@@ -154,6 +156,31 @@ class ResultsExplorer:
154
156
  )
155
157
  return self._handler.load_synthetic_data(file_path)
156
158
 
159
+ def load_quality_report(self, dataset_name, synthesizer_name, results_folder_name=None):
160
+ """Load the quality report for a given dataset and synthesizer.
161
+
162
+ Args:
163
+ dataset_name (str):
164
+ The name of the dataset.
165
+ synthesizer_name (str):
166
+ The name of the synthesizer.
167
+ results_folder_name (str, optional):
168
+ The name of the results folder to load from. If not provided,
169
+ the latest run will be used. Defaults to None.
170
+
171
+ Returns:
172
+ sdmetrics.reports.QualityReport:
173
+ The quality report computed during the benchmark.
174
+ """
175
+ results_folder_name = results_folder_name or self._get_latest_run()
176
+ file_path = self._get_file_path(
177
+ results_folder_name=results_folder_name,
178
+ dataset_name=dataset_name,
179
+ synthesizer_name=synthesizer_name,
180
+ file_type='quality_report',
181
+ )
182
+ return self._handler.load_quality_report(file_path)
183
+
157
184
  def load_real_data(self, dataset_name):
158
185
  """Load the real data for a given dataset.
159
186
 
@@ -3,6 +3,7 @@
3
3
  import io
4
4
  import operator
5
5
  import os
6
+ import tempfile
6
7
  import warnings
7
8
  from abc import ABC, abstractmethod
8
9
  from datetime import datetime
@@ -11,6 +12,7 @@ import cloudpickle
11
12
  import pandas as pd
12
13
  import yaml
13
14
  from botocore.exceptions import ClientError
15
+ from sdmetrics.reports.base_report import BaseReport
14
16
 
15
17
  from sdgym._dataset_utils import _read_zipped_data
16
18
  from sdgym.benchmark import TIMEOUT, _add_adjusted_scores
@@ -58,6 +60,11 @@ class ResultsHandler(ABC):
58
60
  """Load synthetic data from a file."""
59
61
  pass
60
62
 
63
+ @abstractmethod
64
+ def load_quality_report(self, file_path):
65
+ """Load a quality report from a file."""
66
+ pass
67
+
61
68
  @abstractmethod
62
69
  def _load_yaml_file(self, folder_name, file_name):
63
70
  """Load a YAML file from the results folder."""
@@ -412,6 +419,10 @@ class LocalResultsHandler(ResultsHandler):
412
419
 
413
420
  return pd.read_csv(full_path)
414
421
 
422
+ def load_quality_report(self, file_path):
423
+ """Load a quality report from a pickle file."""
424
+ return BaseReport.load(os.path.join(self.base_path, file_path))
425
+
415
426
  def _get_results_files(self, results_folder_name, prefix, suffix):
416
427
  return [
417
428
  f
@@ -529,6 +540,17 @@ class S3ResultsHandler(ResultsHandler):
529
540
 
530
541
  return pd.read_csv(io.BytesIO(body))
531
542
 
543
+ def load_quality_report(self, file_path):
544
+ """Load a quality report from S3."""
545
+ key = f'{self.prefix}{file_path}'
546
+ response = self.s3_client.get_object(Bucket=self.bucket_name, Key=key)
547
+ with tempfile.TemporaryDirectory() as temp_dir:
548
+ temp_path = os.path.join(temp_dir, 'report.pkl')
549
+ with open(temp_path, 'wb') as temp_file:
550
+ temp_file.write(response['Body'].read())
551
+
552
+ return BaseReport.load(temp_path)
553
+
532
554
  def _get_results_files(self, results_folder_name, prefix, suffix):
533
555
  s3_prefix = f'{self.prefix}{results_folder_name}/'
534
556
  paginator = self.s3_client.get_paginator('list_objects_v2')
@@ -1,6 +1,7 @@
1
1
  """Results writer for SDGym benchmark."""
2
2
 
3
3
  import io
4
+ import tempfile
4
5
  import zipfile
5
6
  from abc import ABC, abstractmethod
6
7
  from pathlib import Path
@@ -33,6 +34,11 @@ class ResultsWriter(ABC):
33
34
  """Write data to a YAML file."""
34
35
  pass
35
36
 
37
+ @abstractmethod
38
+ def write_report(self, report, file_path):
39
+ """Write an SDMetrics report to a pickle file."""
40
+ pass
41
+
36
42
 
37
43
  class LocalResultsWriter:
38
44
  """Local results writer for saving results to the local filesystem."""
@@ -95,6 +101,10 @@ class LocalResultsWriter:
95
101
  with open(file_path, 'wb') as f:
96
102
  cloudpickle.dump(obj, f)
97
103
 
104
+ def write_report(self, report, file_path):
105
+ """Write an SDMetrics report to a pickle file."""
106
+ report.save(file_path)
107
+
98
108
  def write_yaml(self, data, file_path, append=False):
99
109
  """Write data to a YAML file."""
100
110
  file_path = Path(file_path)
@@ -141,6 +151,14 @@ class S3ResultsWriter(ResultsWriter):
141
151
  buffer.seek(0)
142
152
  self.s3_client.put_object(Body=buffer.read(), Bucket=bucket, Key=key)
143
153
 
154
+ def write_report(self, report, file_path):
155
+ """Write an SDMetrics report to S3 as a pickle file."""
156
+ bucket, key = parse_s3_path(file_path)
157
+ with tempfile.TemporaryDirectory() as temp_dir:
158
+ temp_path = Path(temp_dir) / 'report.pkl'
159
+ report.save(temp_path)
160
+ self.s3_client.put_object(Body=temp_path.read_bytes(), Bucket=bucket, Key=key)
161
+
144
162
  def write_yaml(self, data, file_path, append=False):
145
163
  """Write data to a YAML file in S3."""
146
164
  bucket, key = parse_s3_path(file_path)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sdgym
3
- Version: 0.15.2.dev0
3
+ Version: 0.16.1.dev0
4
4
  Summary: Benchmark tabular synthetic data generators using a variety of datasets
5
5
  Author-email: "DataCebo, Inc." <info@sdv.dev>
6
6
  License-Expression: BUSL-1.1
@@ -63,8 +63,8 @@ Requires-Dist: torch>=2.6.0; python_version >= "3.13" and python_version < "3.14
63
63
  Requires-Dist: torch>=2.9.0; python_version >= "3.14"
64
64
  Requires-Dist: tqdm>=4.66.3
65
65
  Requires-Dist: XlsxWriter>=1.2.8
66
- Requires-Dist: rdt>=1.18.2; python_version < "3.14"
67
- Requires-Dist: rdt>=1.20.0; python_version >= "3.14"
66
+ Requires-Dist: rdt<2,>=1.18.2; python_version < "3.14"
67
+ Requires-Dist: rdt<2,>=1.20.0; python_version >= "3.14"
68
68
  Requires-Dist: sdmetrics>=0.29.0
69
69
  Requires-Dist: sdv<2,>=1.37.0
70
70
  Provides-Extra: dask
@@ -24,7 +24,7 @@ torch>=1.13.0
24
24
 
25
25
  [:python_version < "3.14"]
26
26
  cloudpickle>=2.1.0
27
- rdt>=1.18.2
27
+ rdt<2,>=1.18.2
28
28
 
29
29
  [:python_version >= "3.10" and python_version < "3.11"]
30
30
  scikit-learn>=1.1.0
@@ -59,7 +59,7 @@ pandas<3,>=2.3.3
59
59
  scikit-learn>=1.8.0
60
60
  scipy>=1.16.1
61
61
  torch>=2.9.0
62
- rdt>=1.20.0
62
+ rdt<2,>=1.20.0
63
63
 
64
64
  [all]
65
65
  sdgym[dask,dev,test]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes