cmdstanpy 1.2.1__tar.gz → 1.2.3__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. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/MANIFEST.in +0 -2
  2. {cmdstanpy-1.2.1/cmdstanpy.egg-info → cmdstanpy-1.2.3}/PKG-INFO +27 -8
  3. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/__init__.py +2 -1
  4. cmdstanpy-1.2.3/cmdstanpy/_version.py +3 -0
  5. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/cmdstan_args.py +1 -0
  6. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/compilation.py +102 -1
  7. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/install_cmdstan.py +2 -0
  8. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/install_cxx_toolchain.py +4 -0
  9. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/model.py +34 -66
  10. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/stanfit/pathfinder.py +4 -2
  11. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/stanfit/runset.py +10 -10
  12. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/utils/stancsv.py +2 -1
  13. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3/cmdstanpy.egg-info}/PKG-INFO +27 -8
  14. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy.egg-info/SOURCES.txt +0 -4
  15. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy.egg-info/entry_points.txt +0 -1
  16. cmdstanpy-1.2.3/cmdstanpy.egg-info/requires.txt +27 -0
  17. cmdstanpy-1.2.3/pyproject.toml +95 -0
  18. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_optimize.py +5 -4
  19. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_pathfinder.py +39 -0
  20. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_sample.py +14 -9
  21. cmdstanpy-1.2.1/cmdstanpy/_version.py +0 -3
  22. cmdstanpy-1.2.1/cmdstanpy.egg-info/requires.txt +0 -24
  23. cmdstanpy-1.2.1/pyproject.toml +0 -30
  24. cmdstanpy-1.2.1/requirements-optional.txt +0 -1
  25. cmdstanpy-1.2.1/requirements-test.txt +0 -8
  26. cmdstanpy-1.2.1/requirements.txt +0 -4
  27. cmdstanpy-1.2.1/setup.py +0 -90
  28. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/LICENSE.md +0 -0
  29. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/README.md +0 -0
  30. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/progress.py +0 -0
  31. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/py.typed +0 -0
  32. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/stanfit/__init__.py +0 -0
  33. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/stanfit/gq.py +0 -0
  34. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/stanfit/laplace.py +0 -0
  35. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/stanfit/mcmc.py +0 -0
  36. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/stanfit/metadata.py +0 -0
  37. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/stanfit/mle.py +0 -0
  38. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/stanfit/vb.py +0 -0
  39. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/utils/__init__.py +0 -0
  40. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/utils/cmdstan.py +0 -0
  41. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/utils/command.py +0 -0
  42. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/utils/data_munging.py +0 -0
  43. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/utils/filesystem.py +0 -0
  44. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/utils/json.py +0 -0
  45. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy/utils/logging.py +0 -0
  46. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy.egg-info/dependency_links.txt +0 -0
  47. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/cmdstanpy.egg-info/top_level.txt +0 -0
  48. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/setup.cfg +0 -0
  49. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_cmdstan_args.py +0 -0
  50. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_compiler_opts.py +0 -0
  51. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_compliance.py +0 -0
  52. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_cxx_installation.py +0 -0
  53. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_generate_quantities.py +0 -0
  54. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_install_cmdstan.py +0 -0
  55. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_laplace.py +0 -0
  56. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_log_prob.py +0 -0
  57. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_metadata.py +0 -0
  58. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_model.py +0 -0
  59. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_runset.py +0 -0
  60. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_utils.py +0 -0
  61. {cmdstanpy-1.2.1 → cmdstanpy-1.2.3}/test/test_variational.py +0 -0
@@ -1,6 +1,4 @@
1
1
  # This file is used to include extra files in source distributions.
2
- # (Source distributions are generated by running `python setup.py sdist`.)
3
2
 
4
- include requirements*.txt
5
3
  include LICENSE.md
6
4
  include cmdstanpy/py.typed
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cmdstanpy
3
- Version: 1.2.1
3
+ Version: 1.2.3
4
4
  Summary: Python interface to CmdStan
5
- Home-page: https://github.com/stan-dev/cmdstanpy
6
5
  Author: Stan Dev Team
7
- License: UNKNOWN
8
- Platform: UNKNOWN
6
+ License: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/stan-dev/cmdstanpy
8
+ Project-URL: Bug Tracker, https://github.com/stan-dev/cmdstanpy/issues
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: License :: OSI Approved :: BSD License
11
11
  Classifier: Operating System :: OS Independent
@@ -16,10 +16,31 @@ Classifier: Programming Language :: Python
16
16
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
17
17
  Requires-Python: >=3.8
18
18
  Description-Content-Type: text/markdown
19
+ License-File: LICENSE.md
20
+ Requires-Dist: pandas
21
+ Requires-Dist: numpy>=1.21
22
+ Requires-Dist: tqdm
23
+ Requires-Dist: stanio<2.0.0,>=0.4.0
19
24
  Provides-Extra: all
20
- Provides-Extra: tests
25
+ Requires-Dist: xarray; extra == "all"
26
+ Provides-Extra: test
27
+ Requires-Dist: flake8; extra == "test"
28
+ Requires-Dist: pylint; extra == "test"
29
+ Requires-Dist: pytest; extra == "test"
30
+ Requires-Dist: pytest-cov; extra == "test"
31
+ Requires-Dist: pytest-order; extra == "test"
32
+ Requires-Dist: mypy; extra == "test"
33
+ Requires-Dist: xarray; extra == "test"
21
34
  Provides-Extra: docs
22
- License-File: LICENSE.md
35
+ Requires-Dist: sphinx<6,>5; extra == "docs"
36
+ Requires-Dist: pydata-sphinx-theme<0.9; extra == "docs"
37
+ Requires-Dist: nbsphinx; extra == "docs"
38
+ Requires-Dist: ipython; extra == "docs"
39
+ Requires-Dist: ipykernel; extra == "docs"
40
+ Requires-Dist: ipywidgets; extra == "docs"
41
+ Requires-Dist: sphinx-copybutton; extra == "docs"
42
+ Requires-Dist: xarray; extra == "docs"
43
+ Requires-Dist: matplotlib; extra == "docs"
23
44
 
24
45
  # CmdStanPy
25
46
 
@@ -79,5 +100,3 @@ fit = model.sample(chains=4, data=data_file)
79
100
  # summarize the results (wraps CmdStan `bin/stansummary`):
80
101
  fit.summary()
81
102
  ```
82
-
83
-
@@ -22,7 +22,7 @@ atexit.register(_cleanup_tmpdir)
22
22
 
23
23
 
24
24
  from ._version import __version__ # noqa
25
- from .compilation import compile_stan_file
25
+ from .compilation import compile_stan_file, format_stan_file
26
26
  from .install_cmdstan import rebuild_cmdstan
27
27
  from .model import CmdStanModel
28
28
  from .stanfit import (
@@ -50,6 +50,7 @@ __all__ = [
50
50
  'set_make_env',
51
51
  'install_cmdstan',
52
52
  'compile_stan_file',
53
+ 'format_stan_file',
53
54
  'CmdStanMCMC',
54
55
  'CmdStanMLE',
55
56
  'CmdStanGQ',
@@ -0,0 +1,3 @@
1
+ """PyPi Version"""
2
+
3
+ __version__ = '1.2.3'
@@ -930,6 +930,7 @@ class CmdStanArgs:
930
930
  if not (
931
931
  isinstance(self.method_args, SamplerArgs)
932
932
  and self.method_args.num_chains > 1
933
+ or isinstance(self.method_args, PathfinderArgs)
933
934
  ):
934
935
  if not os.path.exists(self.inits):
935
936
  raise ValueError('no such file {}'.format(self.inits))
@@ -9,11 +9,17 @@ import platform
9
9
  import shutil
10
10
  import subprocess
11
11
  from copy import copy
12
+ from datetime import datetime
12
13
  from pathlib import Path
13
14
  from typing import Any, Dict, Iterable, List, Optional, Union
14
15
 
15
16
  from cmdstanpy.utils import get_logger
16
- from cmdstanpy.utils.cmdstan import EXTENSION, cmdstan_path
17
+ from cmdstanpy.utils.cmdstan import (
18
+ EXTENSION,
19
+ cmdstan_path,
20
+ cmdstan_version,
21
+ cmdstan_version_before,
22
+ )
17
23
  from cmdstanpy.utils.command import do_command
18
24
  from cmdstanpy.utils.filesystem import SanitizedOrTmpFilePath
19
25
 
@@ -476,3 +482,98 @@ def compile_stan_file(
476
482
  f"Failed to compile Stan model '{src}'. " f"Console:\n{console}"
477
483
  )
478
484
  return str(exe_target)
485
+
486
+
487
+ def format_stan_file(
488
+ stan_file: Union[str, os.PathLike],
489
+ *,
490
+ overwrite_file: bool = False,
491
+ canonicalize: Union[bool, str, Iterable[str]] = False,
492
+ max_line_length: int = 78,
493
+ backup: bool = True,
494
+ stanc_options: Optional[Dict[str, Any]] = None,
495
+ ) -> None:
496
+ """
497
+ Run stanc's auto-formatter on the model code. Either saves directly
498
+ back to the file or prints for inspection
499
+
500
+ :param stan_file: Path to Stan program file.
501
+ :param overwrite_file: If True, save the updated code to disk, rather
502
+ than printing it. By default False
503
+ :param canonicalize: Whether or not the compiler should 'canonicalize'
504
+ the Stan model, removing things like deprecated syntax. Default is
505
+ False. If True, all canonicalizations are run. If it is a list of
506
+ strings, those options are passed to stanc (new in Stan 2.29)
507
+ :param max_line_length: Set the wrapping point for the formatter. The
508
+ default value is 78, which wraps most lines by the 80th character.
509
+ :param backup: If True, create a stanfile.bak backup before
510
+ writing to the file. Only disable this if you're sure you have other
511
+ copies of the file or are using a version control system like Git.
512
+ :param stanc_options: Additional options to pass to the stanc compiler.
513
+ """
514
+ stan_file = Path(stan_file).resolve()
515
+
516
+ if not stan_file.exists():
517
+ raise ValueError(f'File does not exist: {stan_file}')
518
+
519
+ try:
520
+ cmd = (
521
+ [os.path.join(cmdstan_path(), 'bin', 'stanc' + EXTENSION)]
522
+ # handle include-paths, allow-undefined etc
523
+ + CompilerOptions(stanc_options=stanc_options).compose_stanc(None)
524
+ + [str(stan_file)]
525
+ )
526
+
527
+ if canonicalize:
528
+ if cmdstan_version_before(2, 29):
529
+ if isinstance(canonicalize, bool):
530
+ cmd.append('--print-canonical')
531
+ else:
532
+ raise ValueError(
533
+ "Invalid arguments passed for current CmdStan"
534
+ + " version({})\n".format(
535
+ cmdstan_version() or "Unknown"
536
+ )
537
+ + "--canonicalize requires 2.29 or higher"
538
+ )
539
+ else:
540
+ if isinstance(canonicalize, str):
541
+ cmd.append('--canonicalize=' + canonicalize)
542
+ elif isinstance(canonicalize, Iterable):
543
+ cmd.append('--canonicalize=' + ','.join(canonicalize))
544
+ else:
545
+ cmd.append('--print-canonical')
546
+
547
+ # before 2.29, having both --print-canonical
548
+ # and --auto-format printed twice
549
+ if not (cmdstan_version_before(2, 29) and canonicalize):
550
+ cmd.append('--auto-format')
551
+
552
+ if not cmdstan_version_before(2, 29):
553
+ cmd.append(f'--max-line-length={max_line_length}')
554
+ elif max_line_length != 78:
555
+ raise ValueError(
556
+ "Invalid arguments passed for current CmdStan version"
557
+ + " ({})\n".format(cmdstan_version() or "Unknown")
558
+ + "--max-line-length requires 2.29 or higher"
559
+ )
560
+
561
+ out = subprocess.run(cmd, capture_output=True, text=True, check=True)
562
+ if out.stderr:
563
+ get_logger().warning(out.stderr)
564
+ result = out.stdout
565
+ if overwrite_file:
566
+ if result:
567
+ if backup:
568
+ shutil.copyfile(
569
+ stan_file,
570
+ str(stan_file)
571
+ + '.bak-'
572
+ + datetime.now().strftime("%Y%m%d%H%M%S"),
573
+ )
574
+ stan_file.write_text(result)
575
+ else:
576
+ print(result)
577
+
578
+ except (ValueError, RuntimeError) as e:
579
+ raise RuntimeError("Stanc formatting failed") from e
@@ -523,6 +523,8 @@ def retrieve_version(version: str, progress: bool = True) -> None:
523
523
  first = tar.next()
524
524
  if first is not None:
525
525
  top_dir = first.name
526
+ else:
527
+ top_dir = ''
526
528
  cmdstan_dir = f'cmdstan-{version}'
527
529
  if top_dir != cmdstan_dir:
528
530
  raise CmdStanInstallError(
@@ -235,8 +235,10 @@ def get_toolchain_name() -> str:
235
235
  return ''
236
236
 
237
237
 
238
+ # TODO(2.0): drop 3.5 support
238
239
  def get_url(version: str) -> str:
239
240
  """Return URL for toolchain."""
241
+ url = ''
240
242
  if platform.system() == 'Windows':
241
243
  if version == '4.0':
242
244
  # pylint: disable=line-too-long
@@ -277,6 +279,8 @@ def run_rtools_install(args: Dict[str, Any]) -> None:
277
279
 
278
280
  if 'verbose' in args:
279
281
  verbose = args['verbose']
282
+ else:
283
+ verbose = False
280
284
 
281
285
  install_dir = args['dir']
282
286
  if install_dir is None:
@@ -10,7 +10,6 @@ import tempfile
10
10
  import threading
11
11
  from collections import OrderedDict
12
12
  from concurrent.futures import ThreadPoolExecutor
13
- from datetime import datetime
14
13
  from io import StringIO
15
14
  from multiprocessing import cpu_count
16
15
  from typing import (
@@ -57,9 +56,7 @@ from cmdstanpy.stanfit import (
57
56
  from_csv,
58
57
  )
59
58
  from cmdstanpy.utils import (
60
- EXTENSION,
61
59
  cmdstan_path,
62
- cmdstan_version,
63
60
  cmdstan_version_before,
64
61
  do_command,
65
62
  get_logger,
@@ -320,6 +317,7 @@ class CmdStanModel:
320
317
  return {}
321
318
  return compilation.src_info(str(self.stan_file), self._compiler_options)
322
319
 
320
+ # TODO(2.0) remove
323
321
  def format(
324
322
  self,
325
323
  overwrite_file: bool = False,
@@ -329,6 +327,8 @@ class CmdStanModel:
329
327
  backup: bool = True,
330
328
  ) -> None:
331
329
  """
330
+ Deprecated: Use :func:`cmdstanpy.format_stan_file()` instead.
331
+
332
332
  Run stanc's auto-formatter on the model code. Either saves directly
333
333
  back to the file or prints for inspection
334
334
 
@@ -345,72 +345,24 @@ class CmdStanModel:
345
345
  writing to the file. Only disable this if you're sure you have other
346
346
  copies of the file or are using a version control system like Git.
347
347
  """
348
- if self.stan_file is None or not os.path.isfile(self.stan_file):
349
- raise ValueError("No Stan file found for this module")
350
- try:
351
- cmd = (
352
- [os.path.join(cmdstan_path(), 'bin', 'stanc' + EXTENSION)]
353
- # handle include-paths, allow-undefined etc
354
- + self._compiler_options.compose_stanc(None)
355
- + [str(self.stan_file)]
356
- )
357
348
 
358
- if canonicalize:
359
- if cmdstan_version_before(2, 29):
360
- if isinstance(canonicalize, bool):
361
- cmd.append('--print-canonical')
362
- else:
363
- raise ValueError(
364
- "Invalid arguments passed for current CmdStan"
365
- + " version({})\n".format(
366
- cmdstan_version() or "Unknown"
367
- )
368
- + "--canonicalize requires 2.29 or higher"
369
- )
370
- else:
371
- if isinstance(canonicalize, str):
372
- cmd.append('--canonicalize=' + canonicalize)
373
- elif isinstance(canonicalize, Iterable):
374
- cmd.append('--canonicalize=' + ','.join(canonicalize))
375
- else:
376
- cmd.append('--print-canonical')
377
-
378
- # before 2.29, having both --print-canonical
379
- # and --auto-format printed twice
380
- if not (cmdstan_version_before(2, 29) and canonicalize):
381
- cmd.append('--auto-format')
382
-
383
- if not cmdstan_version_before(2, 29):
384
- cmd.append(f'--max-line-length={max_line_length}')
385
- elif max_line_length != 78:
386
- raise ValueError(
387
- "Invalid arguments passed for current CmdStan version"
388
- + " ({})\n".format(cmdstan_version() or "Unknown")
389
- + "--max-line-length requires 2.29 or higher"
390
- )
349
+ get_logger().warning(
350
+ "CmdStanModel.format() is deprecated and will be "
351
+ "removed in the next major version.\n"
352
+ "Use cmdstanpy.format_stan_file() instead."
353
+ )
391
354
 
392
- out = subprocess.run(
393
- cmd, capture_output=True, text=True, check=True
394
- )
395
- if out.stderr:
396
- get_logger().warning(out.stderr)
397
- result = out.stdout
398
- if overwrite_file:
399
- if result:
400
- if backup:
401
- shutil.copyfile(
402
- self.stan_file,
403
- str(self.stan_file)
404
- + '.bak-'
405
- + datetime.now().strftime("%Y%m%d%H%M%S"),
406
- )
407
- with open(self.stan_file, 'w') as file_handle:
408
- file_handle.write(result)
409
- else:
410
- print(result)
355
+ if self.stan_file is None:
356
+ raise ValueError("No Stan file found for this module")
411
357
 
412
- except (ValueError, RuntimeError) as e:
413
- raise RuntimeError("Stanc formatting failed") from e
358
+ compilation.format_stan_file(
359
+ self.stan_file,
360
+ overwrite_file=overwrite_file,
361
+ max_line_length=max_line_length,
362
+ canonicalize=canonicalize,
363
+ backup=backup,
364
+ stanc_options=self.stanc_options,
365
+ )
414
366
 
415
367
  @property
416
368
  def stanc_options(self) -> Dict[str, Union[bool, int, str]]:
@@ -1635,6 +1587,7 @@ class CmdStanModel:
1635
1587
  refresh: Optional[int] = None,
1636
1588
  time_fmt: str = "%Y%m%d%H%M%S",
1637
1589
  timeout: Optional[float] = None,
1590
+ num_threads: Optional[int] = None,
1638
1591
  ) -> CmdStanPathfinder:
1639
1592
  """
1640
1593
  Run CmdStan's Pathfinder variational inference algorithm.
@@ -1737,6 +1690,10 @@ class CmdStanModel:
1737
1690
  :param timeout: Duration at which Pathfinder times
1738
1691
  out in seconds. Defaults to None.
1739
1692
 
1693
+ :param num_threads: Number of threads to request for parallel execution.
1694
+ A number other than ``1`` requires the model to have been compiled
1695
+ with STAN_THREADS=True.
1696
+
1740
1697
  :return: A :class:`CmdStanPathfinder` object
1741
1698
 
1742
1699
  References
@@ -1763,6 +1720,17 @@ class CmdStanModel:
1763
1720
  "available for CmdStan versions 2.34 and later"
1764
1721
  )
1765
1722
 
1723
+ if num_threads is not None:
1724
+ if (
1725
+ num_threads != 1
1726
+ and exe_info.get('STAN_THREADS', '').lower() != 'true'
1727
+ ):
1728
+ raise ValueError(
1729
+ "Model must be compiled with 'STAN_THREADS=true' to use"
1730
+ " 'num_threads' argument"
1731
+ )
1732
+ os.environ['STAN_NUM_THREADS'] = str(num_threads)
1733
+
1766
1734
  if num_paths == 1:
1767
1735
  if num_single_draws is None:
1768
1736
  num_single_draws = draws
@@ -214,8 +214,10 @@ class CmdStanPathfinder:
214
214
  """
215
215
  return ( # type: ignore
216
216
  self._metadata.cmdstan_config.get("num_paths", 4) > 1
217
- and self._metadata.cmdstan_config.get('psis_resample', 1) == 1
218
- and self._metadata.cmdstan_config.get('calculate_lp', 1) == 1
217
+ and self._metadata.cmdstan_config.get('psis_resample', 1)
218
+ in (1, 'true')
219
+ and self._metadata.cmdstan_config.get('calculate_lp', 1)
220
+ in (1, 'true')
219
221
  )
220
222
 
221
223
  def save_csvfiles(self, dir: Optional[str] = None) -> None:
@@ -61,18 +61,26 @@ class RunSet:
61
61
  self._base_outfile = (
62
62
  f'{args.model_name}-{datetime.now().strftime(time_fmt)}'
63
63
  )
64
- # per-process console messages
64
+ # per-process outputs
65
65
  self._stdout_files = [''] * self._num_procs
66
+ self._profile_files = [''] * self._num_procs # optional
66
67
  if one_process_per_chain:
67
68
  for i in range(chains):
68
69
  self._stdout_files[i] = self.file_path("-stdout.txt", id=i)
70
+ if args.save_profile:
71
+ self._profile_files[i] = self.file_path(
72
+ ".csv", extra="-profile", id=chain_ids[i]
73
+ )
69
74
  else:
70
75
  self._stdout_files[0] = self.file_path("-stdout.txt")
76
+ if args.save_profile:
77
+ self._profile_files[0] = self.file_path(
78
+ ".csv", extra="-profile"
79
+ )
71
80
 
72
81
  # per-chain output files
73
82
  self._csv_files: List[str] = [''] * chains
74
83
  self._diagnostic_files = [''] * chains # optional
75
- self._profile_files = [''] * chains # optional
76
84
 
77
85
  if chains == 1:
78
86
  self._csv_files[0] = self.file_path(".csv")
@@ -80,10 +88,6 @@ class RunSet:
80
88
  self._diagnostic_files[0] = self.file_path(
81
89
  ".csv", extra="-diagnostic"
82
90
  )
83
- if args.save_profile:
84
- self._profile_files[0] = self.file_path(
85
- ".csv", extra="-profile"
86
- )
87
91
  else:
88
92
  for i in range(chains):
89
93
  self._csv_files[i] = self.file_path(".csv", id=chain_ids[i])
@@ -91,10 +95,6 @@ class RunSet:
91
95
  self._diagnostic_files[i] = self.file_path(
92
96
  ".csv", extra="-diagnostic", id=chain_ids[i]
93
97
  )
94
- if args.save_profile:
95
- self._profile_files[i] = self.file_path(
96
- ".csv", extra="-profile", id=chain_ids[i]
97
- )
98
98
 
99
99
  def __repr__(self) -> str:
100
100
  repr = 'RunSet: chains={}, chain_ids={}, num_processes={}'.format(
@@ -52,7 +52,7 @@ def check_sampler_csv(
52
52
  )
53
53
  )
54
54
  if save_warmup:
55
- if not ('save_warmup' in meta and meta['save_warmup'] == 1):
55
+ if not ('save_warmup' in meta and meta['save_warmup'] in (1, 'true')):
56
56
  raise ValueError(
57
57
  'bad Stan CSV file {}, '
58
58
  'config error, expected save_warmup = 1'.format(path)
@@ -116,6 +116,7 @@ def scan_optimize_csv(path: str, save_iters: bool = False) -> Dict[str, Any]:
116
116
  all_iters[i, :] = [float(x) for x in xs]
117
117
  if i == iters - 1:
118
118
  mle: np.ndarray = np.array(xs, dtype=float)
119
+ # pylint: disable=possibly-used-before-assignment
119
120
  dict['mle'] = mle
120
121
  if save_iters:
121
122
  dict['all_iters'] = all_iters
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cmdstanpy
3
- Version: 1.2.1
3
+ Version: 1.2.3
4
4
  Summary: Python interface to CmdStan
5
- Home-page: https://github.com/stan-dev/cmdstanpy
6
5
  Author: Stan Dev Team
7
- License: UNKNOWN
8
- Platform: UNKNOWN
6
+ License: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/stan-dev/cmdstanpy
8
+ Project-URL: Bug Tracker, https://github.com/stan-dev/cmdstanpy/issues
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: License :: OSI Approved :: BSD License
11
11
  Classifier: Operating System :: OS Independent
@@ -16,10 +16,31 @@ Classifier: Programming Language :: Python
16
16
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
17
17
  Requires-Python: >=3.8
18
18
  Description-Content-Type: text/markdown
19
+ License-File: LICENSE.md
20
+ Requires-Dist: pandas
21
+ Requires-Dist: numpy>=1.21
22
+ Requires-Dist: tqdm
23
+ Requires-Dist: stanio<2.0.0,>=0.4.0
19
24
  Provides-Extra: all
20
- Provides-Extra: tests
25
+ Requires-Dist: xarray; extra == "all"
26
+ Provides-Extra: test
27
+ Requires-Dist: flake8; extra == "test"
28
+ Requires-Dist: pylint; extra == "test"
29
+ Requires-Dist: pytest; extra == "test"
30
+ Requires-Dist: pytest-cov; extra == "test"
31
+ Requires-Dist: pytest-order; extra == "test"
32
+ Requires-Dist: mypy; extra == "test"
33
+ Requires-Dist: xarray; extra == "test"
21
34
  Provides-Extra: docs
22
- License-File: LICENSE.md
35
+ Requires-Dist: sphinx<6,>5; extra == "docs"
36
+ Requires-Dist: pydata-sphinx-theme<0.9; extra == "docs"
37
+ Requires-Dist: nbsphinx; extra == "docs"
38
+ Requires-Dist: ipython; extra == "docs"
39
+ Requires-Dist: ipykernel; extra == "docs"
40
+ Requires-Dist: ipywidgets; extra == "docs"
41
+ Requires-Dist: sphinx-copybutton; extra == "docs"
42
+ Requires-Dist: xarray; extra == "docs"
43
+ Requires-Dist: matplotlib; extra == "docs"
23
44
 
24
45
  # CmdStanPy
25
46
 
@@ -79,5 +100,3 @@ fit = model.sample(chains=4, data=data_file)
79
100
  # summarize the results (wraps CmdStan `bin/stansummary`):
80
101
  fit.summary()
81
102
  ```
82
-
83
-
@@ -2,10 +2,6 @@ LICENSE.md
2
2
  MANIFEST.in
3
3
  README.md
4
4
  pyproject.toml
5
- requirements-optional.txt
6
- requirements-test.txt
7
- requirements.txt
8
- setup.py
9
5
  cmdstanpy/__init__.py
10
6
  cmdstanpy/_version.py
11
7
  cmdstanpy/cmdstan_args.py
@@ -1,4 +1,3 @@
1
1
  [console_scripts]
2
2
  install_cmdstan = cmdstanpy.install_cmdstan:__main__
3
3
  install_cxx_toolchain = cmdstanpy.install_cxx_toolchain:__main__
4
-
@@ -0,0 +1,27 @@
1
+ pandas
2
+ numpy>=1.21
3
+ tqdm
4
+ stanio<2.0.0,>=0.4.0
5
+
6
+ [all]
7
+ xarray
8
+
9
+ [docs]
10
+ sphinx<6,>5
11
+ pydata-sphinx-theme<0.9
12
+ nbsphinx
13
+ ipython
14
+ ipykernel
15
+ ipywidgets
16
+ sphinx-copybutton
17
+ xarray
18
+ matplotlib
19
+
20
+ [test]
21
+ flake8
22
+ pylint
23
+ pytest
24
+ pytest-cov
25
+ pytest-order
26
+ mypy
27
+ xarray
@@ -0,0 +1,95 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "cmdstanpy"
7
+ description = "Python interface to CmdStan"
8
+ readme = "README.md"
9
+ license = { text = "BSD-3-Clause" }
10
+ authors = [{ name = "Stan Dev Team" }]
11
+ requires-python = ">=3.8"
12
+ dependencies = ["pandas", "numpy>=1.21", "tqdm", "stanio>=0.4.0,<2.0.0"]
13
+ dynamic = ["version"]
14
+ classifiers = [
15
+ "Programming Language :: Python :: 3",
16
+ "License :: OSI Approved :: BSD License",
17
+ "Operating System :: OS Independent",
18
+ "Development Status :: 5 - Production/Stable",
19
+ "Intended Audience :: Science/Research",
20
+ "Natural Language :: English",
21
+ "Programming Language :: Python",
22
+ "Topic :: Scientific/Engineering :: Information Analysis",
23
+ ]
24
+
25
+ [project.urls]
26
+ "Homepage" = "https://github.com/stan-dev/cmdstanpy"
27
+ "Bug Tracker" = "https://github.com/stan-dev/cmdstanpy/issues"
28
+
29
+ [project.scripts]
30
+ install_cmdstan = "cmdstanpy.install_cmdstan:__main__"
31
+ install_cxx_toolchain = "cmdstanpy.install_cxx_toolchain:__main__"
32
+
33
+ [tool.setuptools.dynamic]
34
+ version = { attr = "cmdstanpy._version.__version__" }
35
+
36
+ [tool.setuptools]
37
+ packages = ["cmdstanpy", "cmdstanpy.stanfit", "cmdstanpy.utils"]
38
+
39
+ [tool.setuptools.package-data]
40
+ "cmdstanpy" = ["py.typed"]
41
+
42
+ [project.optional-dependencies]
43
+ all = ["xarray"]
44
+ test = [
45
+ "flake8",
46
+ "pylint",
47
+ "pytest",
48
+ "pytest-cov",
49
+ "pytest-order",
50
+ "mypy",
51
+ "xarray",
52
+ ]
53
+ docs = [
54
+ "sphinx>5,<6",
55
+ "pydata-sphinx-theme<0.9",
56
+ "nbsphinx",
57
+ "ipython",
58
+ "ipykernel",
59
+ "ipywidgets",
60
+ "sphinx-copybutton",
61
+ "xarray",
62
+ "matplotlib",
63
+ ]
64
+
65
+
66
+ [tool.black]
67
+ line-length = 80
68
+ skip-string-normalization = true
69
+
70
+ [tool.isort]
71
+ multi_line_output = 3
72
+ include_trailing_comma = true
73
+ force_grid_wrap = 0
74
+ use_parentheses = true
75
+ ensure_newline_before_comments = true
76
+ line_length = 80
77
+
78
+ [tool.mypy]
79
+ disallow_untyped_defs = true
80
+ disallow_incomplete_defs = true
81
+ no_implicit_optional = true
82
+ # disallow_any_generics = true # disabled due to issues with numpy
83
+ warn_return_any = true
84
+ # warn_unused_ignores = true # can't be run on CI due to windows having different ctypes
85
+ check_untyped_defs = true
86
+ warn_redundant_casts = true
87
+ strict_equality = true
88
+ disallow_untyped_calls = true
89
+
90
+ [[tool.mypy.overrides]]
91
+ module = ['tqdm.auto', 'pandas']
92
+ ignore_missing_imports = true
93
+
94
+ [tool.coverage.run]
95
+ source = ["cmdstanpy"]
@@ -262,12 +262,13 @@ def test_variables_3d() -> None:
262
262
  )
263
263
  vars_iters = multidim_mle_iters.stan_variables(inc_iterations=True)
264
264
  assert len(vars_iters) == len(multidim_mle_iters.metadata.stan_vars)
265
+ assert 'frac_60' in vars_iters
266
+ n_iter = vars_iters['frac_60'].shape[0]
267
+ assert n_iter > 1
265
268
  assert 'y_rep' in vars_iters
266
- assert vars_iters['y_rep'].shape == (8, 5, 4, 3)
269
+ assert vars_iters['y_rep'].shape == (n_iter, 5, 4, 3)
267
270
  assert 'beta' in vars_iters
268
- assert vars_iters['beta'].shape == (8, 2)
269
- assert 'frac_60' in vars_iters
270
- assert vars_iters['frac_60'].shape == (8,)
271
+ assert vars_iters['beta'].shape == (n_iter, 2)
271
272
 
272
273
 
273
274
  def test_optimize_good() -> None:
@@ -2,6 +2,8 @@
2
2
  Tests for the Pathfinder method.
3
3
  """
4
4
 
5
+ import contextlib
6
+ from io import StringIO
5
7
  from pathlib import Path
6
8
 
7
9
  import numpy as np
@@ -129,6 +131,26 @@ def test_pathfinder_init_sampling():
129
131
  assert fit.draws().shape == (1000, 4, 9)
130
132
 
131
133
 
134
+ def test_inits_for_pathfinder():
135
+ stan = DATAFILES_PATH / 'bernoulli.stan'
136
+ bern_model = cmdstanpy.CmdStanModel(stan_file=stan)
137
+ jdata = str(DATAFILES_PATH / 'bernoulli.data.json')
138
+ bern_model.pathfinder(
139
+ jdata, inits=[{"theta": 0.1}, {"theta": 0.9}], num_paths=2
140
+ )
141
+
142
+ # second path is initialized too large!
143
+ with contextlib.redirect_stdout(StringIO()) as captured:
144
+ bern_model.pathfinder(
145
+ jdata,
146
+ inits=[{"theta": 0.1}, {"theta": 1.1}],
147
+ num_paths=2,
148
+ show_console=True,
149
+ )
150
+
151
+ assert "Bounded variable is 1.1" in captured.getvalue()
152
+
153
+
132
154
  def test_pathfinder_no_psis():
133
155
  stan = DATAFILES_PATH / 'bernoulli.stan'
134
156
  bern_model = cmdstanpy.CmdStanModel(stan_file=stan)
@@ -152,3 +174,20 @@ def test_pathfinder_no_lp_calc():
152
174
  n_lp_nan = np.sum(np.isnan(pathfinder.method_variables()['lp__']))
153
175
  assert n_lp_nan < 4000 # some lp still calculated during pathfinder
154
176
  assert n_lp_nan > 3000 # but most are not
177
+
178
+
179
+ def test_pathfinder_threads():
180
+ stan = DATAFILES_PATH / 'bernoulli.stan'
181
+ bern_model = cmdstanpy.CmdStanModel(stan_file=stan)
182
+ jdata = str(DATAFILES_PATH / 'bernoulli.data.json')
183
+
184
+ bern_model.pathfinder(data=jdata, num_threads=1)
185
+
186
+ with pytest.raises(ValueError, match="STAN_THREADS"):
187
+ bern_model.pathfinder(data=jdata, num_threads=4)
188
+
189
+ bern_model = cmdstanpy.CmdStanModel(
190
+ stan_file=stan, cpp_options={'STAN_THREADS': True}, force_compile=True
191
+ )
192
+ pathfinder = bern_model.pathfinder(data=jdata, num_threads=4)
193
+ assert pathfinder.draws().shape == (1000, 3)
@@ -55,7 +55,7 @@ BERNOULLI_COLS = SAMPLER_STATE + ['theta']
55
55
  )
56
56
  def test_bernoulli_good(stanfile: str):
57
57
  stan = os.path.join(DATAFILES_PATH, stanfile)
58
- bern_model = CmdStanModel(stan_file=stan)
58
+ bern_model = CmdStanModel(stan_file=stan, force_compile=True)
59
59
 
60
60
  jdata = os.path.join(DATAFILES_PATH, 'bernoulli.data.json')
61
61
  bern_fit = bern_model.sample(
@@ -74,6 +74,8 @@ def test_bernoulli_good(stanfile: str):
74
74
 
75
75
  for i in range(bern_fit.runset.chains):
76
76
  csv_file = bern_fit.runset.csv_files[i]
77
+ # NB: This will fail if STAN_THREADS is enabled
78
+ # due to sampling only producing 1 stdout file in that case
77
79
  stdout_file = bern_fit.runset.stdout_files[i]
78
80
  assert os.path.exists(csv_file)
79
81
  assert os.path.exists(stdout_file)
@@ -1746,33 +1748,36 @@ def test_save_latent_dynamics() -> None:
1746
1748
 
1747
1749
  def test_save_profile() -> None:
1748
1750
  stan = os.path.join(DATAFILES_PATH, 'profile_likelihood.stan')
1749
- profile_model = CmdStanModel(stan_file=stan)
1751
+ profile_model = CmdStanModel(
1752
+ stan_file=stan, cpp_options={"STAN_THREADS": '1'}, force_compile=True
1753
+ )
1754
+
1750
1755
  profile_fit = profile_model.sample(
1751
1756
  chains=2,
1752
1757
  parallel_chains=2,
1758
+ force_one_process_per_chain=True,
1753
1759
  seed=12345,
1754
1760
  iter_warmup=100,
1755
1761
  iter_sampling=200,
1756
1762
  save_profile=True,
1757
1763
  )
1758
- for i in range(profile_fit.runset.chains):
1759
- profile_file = profile_fit.runset.profile_files[i]
1764
+ assert len(profile_fit.runset.profile_files) == 2
1765
+ for profile_file in profile_fit.runset.profile_files:
1760
1766
  assert os.path.exists(profile_file)
1761
1767
 
1762
1768
  profile_fit = profile_model.sample(
1763
1769
  chains=2,
1764
1770
  parallel_chains=2,
1771
+ force_one_process_per_chain=False,
1765
1772
  seed=12345,
1773
+ iter_warmup=100,
1766
1774
  iter_sampling=200,
1767
- save_latent_dynamics=True,
1768
1775
  save_profile=True,
1769
1776
  )
1770
1777
 
1771
- for i in range(profile_fit.runset.chains):
1772
- profile_file = profile_fit.runset.profile_files[i]
1778
+ assert len(profile_fit.runset.profile_files) == 1
1779
+ for profile_file in profile_fit.runset.profile_files:
1773
1780
  assert os.path.exists(profile_file)
1774
- diagnostics_file = profile_fit.runset.diagnostic_files[i]
1775
- assert os.path.exists(diagnostics_file)
1776
1781
 
1777
1782
 
1778
1783
  def test_xarray_draws() -> None:
@@ -1,3 +0,0 @@
1
- """PyPi Version"""
2
-
3
- __version__ = '1.2.1'
@@ -1,24 +0,0 @@
1
- pandas
2
- numpy>=1.21
3
- tqdm
4
- stanio~=0.3.0
5
-
6
- [all]
7
- xarray
8
-
9
- [docs]
10
- sphinx
11
- sphinx-gallery
12
- sphinx_rtd_theme
13
- numpydoc
14
- matplotlib
15
-
16
- [tests]
17
- flake8
18
- pylint
19
- pytest
20
- pytest-cov
21
- pytest-order
22
- mypy
23
- tqdm
24
- xarray
@@ -1,30 +0,0 @@
1
- [tool.black]
2
- line-length = 80
3
- skip-string-normalization = true
4
-
5
- [tool.isort]
6
- multi_line_output = 3
7
- include_trailing_comma = true
8
- force_grid_wrap = 0
9
- use_parentheses = true
10
- ensure_newline_before_comments = true
11
- line_length = 80
12
-
13
- [tool.mypy]
14
- disallow_untyped_defs = true
15
- disallow_incomplete_defs = true
16
- no_implicit_optional = true
17
- # disallow_any_generics = true # disabled due to issues with numpy
18
- warn_return_any = true
19
- # warn_unused_ignores = true # can't be run on CI due to windows having different ctypes
20
- check_untyped_defs = true
21
- warn_redundant_casts = true
22
- strict_equality = true
23
- disallow_untyped_calls = true
24
-
25
- [[tool.mypy.overrides]]
26
- module = [
27
- 'tqdm.auto',
28
- 'pandas',
29
- ]
30
- ignore_missing_imports = true
@@ -1 +0,0 @@
1
- xarray
@@ -1,8 +0,0 @@
1
- flake8
2
- pylint
3
- pytest
4
- pytest-cov
5
- pytest-order
6
- mypy
7
- tqdm
8
- xarray
@@ -1,4 +0,0 @@
1
- pandas
2
- numpy>=1.21
3
- tqdm
4
- stanio~=0.3.0
cmdstanpy-1.2.1/setup.py DELETED
@@ -1,90 +0,0 @@
1
- #!/usr/bin/env python
2
-
3
- import os
4
- import re
5
- from typing import List
6
-
7
- import setuptools
8
-
9
- HERE = os.path.dirname(__file__)
10
-
11
-
12
- def readme_contents() -> str:
13
- with open(os.path.join(HERE, 'README.md'), 'r') as fd:
14
- src = fd.read()
15
- return src
16
-
17
-
18
- def requirements() -> List[str]:
19
- with open(os.path.join(HERE, 'requirements.txt'), 'r') as fd:
20
- src = fd.read()
21
- return src.splitlines()
22
-
23
-
24
- def requirements_test() -> List[str]:
25
- with open(os.path.join(HERE, 'requirements-test.txt'), 'r') as fd:
26
- src = fd.read()
27
- return src.splitlines()
28
-
29
-
30
- def requirements_optional() -> List[str]:
31
- with open(os.path.join(HERE, 'requirements-optional.txt'), 'r') as fd:
32
- src = fd.read()
33
- return src.splitlines()
34
-
35
-
36
- def get_version() -> str:
37
- version_file = open(os.path.join('cmdstanpy', '_version.py'))
38
- version_contents = version_file.read()
39
- return re.search("__version__ = '(.*?)'", version_contents).group(1)
40
-
41
-
42
- _classifiers = """
43
- Programming Language :: Python :: 3
44
- License :: OSI Approved :: BSD License
45
- Operating System :: OS Independent
46
- Development Status :: 5 - Production/Stable
47
- Intended Audience :: Science/Research
48
- Natural Language :: English
49
- Programming Language :: Python
50
- Topic :: Scientific/Engineering :: Information Analysis
51
- """
52
-
53
- INSTALL_REQUIRES = requirements()
54
-
55
- EXTRAS_REQUIRE = {
56
- 'all': requirements_optional(),
57
- 'tests': requirements_test(),
58
- 'docs': [
59
- 'sphinx',
60
- 'sphinx-gallery',
61
- 'sphinx_rtd_theme',
62
- 'numpydoc',
63
- 'matplotlib',
64
- ],
65
- }
66
-
67
- setuptools.setup(
68
- name='cmdstanpy',
69
- version=get_version(),
70
- description='Python interface to CmdStan',
71
- long_description=readme_contents(),
72
- long_description_content_type="text/markdown",
73
- author='Stan Dev Team',
74
- url='https://github.com/stan-dev/cmdstanpy',
75
- license_files=['LICENSE.md'],
76
- packages=['cmdstanpy', 'cmdstanpy.stanfit', 'cmdstanpy.utils'],
77
- package_data={
78
- 'cmdstanpy': ['py.typed'],
79
- },
80
- entry_points={
81
- 'console_scripts': [
82
- 'install_cmdstan=cmdstanpy.install_cmdstan:__main__',
83
- 'install_cxx_toolchain=cmdstanpy.install_cxx_toolchain:__main__',
84
- ]
85
- },
86
- install_requires=INSTALL_REQUIRES,
87
- python_requires='>=3.8',
88
- extras_require=EXTRAS_REQUIRE,
89
- classifiers=_classifiers.strip().split('\n'),
90
- )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes