From d3fcc528b09a2fe93ef9c7dc9db7f38ffd41040f Mon Sep 17 00:00:00 2001 From: amas Date: Tue, 6 Jan 2026 13:28:49 -0500 Subject: [PATCH 01/16] Add initial basic ConfigInfo model --- cmdstanpy/stanfit/metadata.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/cmdstanpy/stanfit/metadata.py b/cmdstanpy/stanfit/metadata.py index 34c44c6b..1e88d8d6 100644 --- a/cmdstanpy/stanfit/metadata.py +++ b/cmdstanpy/stanfit/metadata.py @@ -8,7 +8,13 @@ from typing import Any, Iterator, Literal import stanio -from pydantic import BaseModel, field_validator, model_validator +from pydantic import ( + BaseModel, + ConfigDict, + NonNegativeInt, + field_validator, + model_validator, +) from cmdstanpy.utils import stancsv @@ -125,3 +131,15 @@ def validate_inv_metric_shape(self) -> MetricInfo: raise ValueError("Dense inv_metric must be square") return self + + +class ConfigInfo(BaseModel): + """Structured representation of a config JSON file output as part of a + Stan inference run. Only required fields are fully validated.""" + + model_config = ConfigDict(extra="allow") + + stan_major_version: NonNegativeInt + stan_minor_version: NonNegativeInt + stan_patch_version: NonNegativeInt + model_name: str From 81d08ab92eeeef662afebc3ccadfffac27a143af Mon Sep 17 00:00:00 2001 From: amas Date: Fri, 30 Jan 2026 14:28:18 -0500 Subject: [PATCH 02/16] Add flattening and parsing logic for config JSON --- cmdstanpy/stanfit/metadata.py | 116 +++++++++++++++++++++++++++++++--- 1 file changed, 108 insertions(+), 8 deletions(-) diff --git a/cmdstanpy/stanfit/metadata.py b/cmdstanpy/stanfit/metadata.py index 1e88d8d6..afece330 100644 --- a/cmdstanpy/stanfit/metadata.py +++ b/cmdstanpy/stanfit/metadata.py @@ -3,15 +3,16 @@ from __future__ import annotations import copy +import json import math import os -from typing import Any, Iterator, Literal +from typing import Annotated, Any, Iterator, Literal import stanio from pydantic import ( BaseModel, ConfigDict, - NonNegativeInt, + Discriminator, field_validator, model_validator, ) @@ -133,13 +134,112 @@ def validate_inv_metric_shape(self) -> MetricInfo: return self -class ConfigInfo(BaseModel): - """Structured representation of a config JSON file output as part of a - Stan inference run. Only required fields are fully validated.""" +class SampleConfig(BaseModel): + model_config = ConfigDict(extra="allow") + + method: Literal["sample"] = "sample" + algorithm: str + num_samples: int + num_warmup: int + save_warmup: bool = False + thin: int = 1 + max_depth: int | None = None + + +class OptimizeConfig(BaseModel): + model_config = ConfigDict(extra="allow") + + method: Literal["optimize"] = "optimize" + algorithm: str + save_iterations: bool = False + jacobian: bool = False + + +class StanConfig(BaseModel): + """Common representation of a config JSON file output as part of a + Stan inference run. Separate method-specific config classes handle + the variation of output between methods.""" model_config = ConfigDict(extra="allow") - stan_major_version: NonNegativeInt - stan_minor_version: NonNegativeInt - stan_patch_version: NonNegativeInt model_name: str + stan_major_version: str + stan_minor_version: str + stan_patch_version: str + + method_config: Annotated[ + SampleConfig | OptimizeConfig, + Discriminator('method'), + ] + + +def flatten_value_dict(data: dict[str, Any]) -> dict[str, Any]: + """Recursively flatten CmdStan's nested value/subdict structure. + + CmdStan uses a pattern where a field contains: + {"value": "val", "val": {"k1": v1, "k2": v2}} + + This flattens it to the parent level as: + {"field": "val", "k1": v1, "k2": v2} + + The flattening is applied recursively to any nested dicts. + """ + result: dict[str, Any] = {} + + for key, value in data.items(): + if not isinstance(value, dict): + result[key] = value + continue + + # Check if this is a value/subdict pattern + if 'value' in value: + value_name = value['value'] + result[key] = value_name + + # Get the nested dict matching the value name and flatten it + nested = value.get(value_name, {}) + if isinstance(nested, dict): + # Recursively flatten the nested dict first + flattened_nested = flatten_value_dict(nested) + # Merge into result (nested keys go to parent level) + for nested_key, nested_value in flattened_nested.items(): + if nested_key not in result: + result[nested_key] = nested_value + else: + # Regular dict without value pattern - recurse into it + result[key] = flatten_value_dict(value) + + return result + + +def flatten_config(data: dict[str, Any]) -> dict[str, Any]: + """Flatten nested CmdStan config JSON structure. + + CmdStan outputs config JSON with deeply nested structure like: + {"method": {"value": "sample", "sample": {"num_samples": 1000, ...}}} + + This flattens it to: + {"method_config": {"method": "sample", "num_samples": 1000, ...}, ...} + """ + method_data = data.get('method') + if not isinstance(method_data, dict): + return data + + result = {k: v for k, v in data.items() if k != "method"} + method_name = method_data.get('value') + + # Build method_config from the method-specific nested dict + nested_method = method_data.get(method_name, {}) + method_config = flatten_value_dict(nested_method) + method_config['method'] = method_name + + result['method_config'] = method_config + return result + + +def parse_config(json_data: str | bytes) -> StanConfig: + """Parse a CmdStan config JSON string into a StanConfig.""" + + raw = json.loads(json_data) + flat = flatten_config(raw) + return StanConfig.model_validate(flat) # type: ignore From b3b20ebd890e3e33ef7317ca8eaaad253515e890 Mon Sep 17 00:00:00 2001 From: amas Date: Sat, 31 Jan 2026 13:57:48 -0500 Subject: [PATCH 03/16] Update flatten_value_dict to clarify variable naming --- cmdstanpy/stanfit/metadata.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/cmdstanpy/stanfit/metadata.py b/cmdstanpy/stanfit/metadata.py index afece330..a9eeff24 100644 --- a/cmdstanpy/stanfit/metadata.py +++ b/cmdstanpy/stanfit/metadata.py @@ -169,7 +169,7 @@ class StanConfig(BaseModel): method_config: Annotated[ SampleConfig | OptimizeConfig, - Discriminator('method'), + Discriminator("method"), ] @@ -186,28 +186,25 @@ def flatten_value_dict(data: dict[str, Any]) -> dict[str, Any]: """ result: dict[str, Any] = {} - for key, value in data.items(): - if not isinstance(value, dict): - result[key] = value + for key, val in data.items(): + if not isinstance(val, dict): + result[key] = val continue - # Check if this is a value/subdict pattern - if 'value' in value: - value_name = value['value'] + if "value" in val: + value_name = val['value'] result[key] = value_name # Get the nested dict matching the value name and flatten it - nested = value.get(value_name, {}) + nested = val.get(value_name, {}) if isinstance(nested, dict): - # Recursively flatten the nested dict first flattened_nested = flatten_value_dict(nested) - # Merge into result (nested keys go to parent level) - for nested_key, nested_value in flattened_nested.items(): + for nested_key, nested_val in flattened_nested.items(): if nested_key not in result: - result[nested_key] = nested_value + result[nested_key] = nested_val else: # Regular dict without value pattern - recurse into it - result[key] = flatten_value_dict(value) + result[key] = flatten_value_dict(val) return result From a5f8094b585c532a9e1b70b61889bfd6ebe5afb6 Mon Sep 17 00:00:00 2001 From: amas Date: Sat, 31 Jan 2026 14:13:00 -0500 Subject: [PATCH 04/16] Add PathfinderConfig --- cmdstanpy/stanfit/metadata.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cmdstanpy/stanfit/metadata.py b/cmdstanpy/stanfit/metadata.py index a9eeff24..2edba6cb 100644 --- a/cmdstanpy/stanfit/metadata.py +++ b/cmdstanpy/stanfit/metadata.py @@ -155,6 +155,16 @@ class OptimizeConfig(BaseModel): jacobian: bool = False +class PathfinderConfig(BaseModel): + model_config = ConfigDict(extra="allow") + + method: Literal["pathfinder"] = "pathfinder" + num_draws: int = 1000 + num_paths: int = 4 + psis_resample: bool = True + calculate_lp: bool = True + + class StanConfig(BaseModel): """Common representation of a config JSON file output as part of a Stan inference run. Separate method-specific config classes handle @@ -168,7 +178,7 @@ class StanConfig(BaseModel): stan_patch_version: str method_config: Annotated[ - SampleConfig | OptimizeConfig, + SampleConfig | OptimizeConfig | PathfinderConfig, Discriminator("method"), ] From d49c62c8868fbffabeb056ebf8616e9892ef003c Mon Sep 17 00:00:00 2001 From: amas Date: Sat, 31 Jan 2026 14:24:14 -0500 Subject: [PATCH 05/16] Add LaplaceConfig --- cmdstanpy/stanfit/metadata.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cmdstanpy/stanfit/metadata.py b/cmdstanpy/stanfit/metadata.py index 2edba6cb..eab4a587 100644 --- a/cmdstanpy/stanfit/metadata.py +++ b/cmdstanpy/stanfit/metadata.py @@ -165,6 +165,15 @@ class PathfinderConfig(BaseModel): calculate_lp: bool = True +class LaplaceConfig(BaseModel): + model_config = ConfigDict(extra="allow") + + method: Literal["laplace"] = "laplace" + mode: str + draws: int = 1000 + jacobian: bool = True + + class StanConfig(BaseModel): """Common representation of a config JSON file output as part of a Stan inference run. Separate method-specific config classes handle @@ -178,7 +187,7 @@ class StanConfig(BaseModel): stan_patch_version: str method_config: Annotated[ - SampleConfig | OptimizeConfig | PathfinderConfig, + SampleConfig | OptimizeConfig | PathfinderConfig | LaplaceConfig, Discriminator("method"), ] From 503a970d0a1a3c9f50b32293fb7b5863f198708a Mon Sep 17 00:00:00 2001 From: amas Date: Sat, 31 Jan 2026 14:31:02 -0500 Subject: [PATCH 06/16] Add VariationalConfig --- cmdstanpy/stanfit/metadata.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/cmdstanpy/stanfit/metadata.py b/cmdstanpy/stanfit/metadata.py index eab4a587..f2e34d63 100644 --- a/cmdstanpy/stanfit/metadata.py +++ b/cmdstanpy/stanfit/metadata.py @@ -174,6 +174,20 @@ class LaplaceConfig(BaseModel): jacobian: bool = True +class VariationalConfig(BaseModel): + model_config = ConfigDict(extra="allow") + + method: Literal["variational"] = "variational" + algorithm: str + iter: int = 10000 + grad_samples: int = 1 + elbo_samples: int = 100 + eta: float = 1.0 + tol_rel_obj: float = 0.01 + eval_elbo: int = 100 + output_samples: int = 1000 + + class StanConfig(BaseModel): """Common representation of a config JSON file output as part of a Stan inference run. Separate method-specific config classes handle @@ -187,7 +201,11 @@ class StanConfig(BaseModel): stan_patch_version: str method_config: Annotated[ - SampleConfig | OptimizeConfig | PathfinderConfig | LaplaceConfig, + SampleConfig + | OptimizeConfig + | PathfinderConfig + | LaplaceConfig + | VariationalConfig, Discriminator("method"), ] From 08c6d0eb7fec8feb1d8ae03d6f181ec4d8678026 Mon Sep 17 00:00:00 2001 From: amas Date: Sat, 31 Jan 2026 14:43:16 -0500 Subject: [PATCH 07/16] Add GeneratedQuantitiesConfig --- cmdstanpy/stanfit/metadata.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cmdstanpy/stanfit/metadata.py b/cmdstanpy/stanfit/metadata.py index f2e34d63..1dac3b1d 100644 --- a/cmdstanpy/stanfit/metadata.py +++ b/cmdstanpy/stanfit/metadata.py @@ -188,6 +188,14 @@ class VariationalConfig(BaseModel): output_samples: int = 1000 +class GeneratedQuantitiesConfig(BaseModel): + model_config = ConfigDict(extra="allow") + + method: Literal["generate_quantities"] = "generate_quantities" + fitted_params: str + num_chains: int = 1 + + class StanConfig(BaseModel): """Common representation of a config JSON file output as part of a Stan inference run. Separate method-specific config classes handle @@ -205,7 +213,8 @@ class StanConfig(BaseModel): | OptimizeConfig | PathfinderConfig | LaplaceConfig - | VariationalConfig, + | VariationalConfig + | GeneratedQuantitiesConfig, Discriminator("method"), ] From 63ca9a5693a57123056af42fb68c5445cfc8b157 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 07:02:51 +0000 Subject: [PATCH 08/16] Bump actions/cache from 4 to 5 Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/cache dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bb340a8f..5de8657a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -77,7 +77,7 @@ jobs: - name: CmdStan installation cacheing id: cache-cmdstan if: ${{ !startswith(needs.get-cmdstan-version.outputs.version, 'git:') }} - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.cmdstan key: ${{ runner.os }}-cmdstan-${{ needs.get-cmdstan-version.outputs.version }}-${{ hashFiles('**/install_cmdstan.py') }} From 8f62f2e3e3f6ec4a8cd83143806ebf73cff414a0 Mon Sep 17 00:00:00 2001 From: amas Date: Sat, 11 Apr 2026 20:53:52 -0400 Subject: [PATCH 09/16] Add first-pass CmdStanPathfinder rewrite --- cmdstanpy/model.py | 11 +- cmdstanpy/stanfit/__init__.py | 29 +- cmdstanpy/stanfit/gq.py | 31 +- cmdstanpy/stanfit/pathfinder.py | 130 +- test/data/pathfinder/bernoulli-pathfinder.csv | 2033 +++++++++-------- .../bernoulli-pathfinder_config.json | 48 + test/test_metadata.py | 260 ++- 7 files changed, 1440 insertions(+), 1102 deletions(-) create mode 100644 test/data/pathfinder/bernoulli-pathfinder_config.json diff --git a/cmdstanpy/model.py b/cmdstanpy/model.py index ece9fd2e..0a688a18 100644 --- a/cmdstanpy/model.py +++ b/cmdstanpy/model.py @@ -1040,7 +1040,10 @@ def generate_quantities( ), ): fit_object = previous_fit - fit_csv_files = previous_fit.runset.csv_files + if isinstance(previous_fit, CmdStanPathfinder): + fit_csv_files = [previous_fit.csv_file] + else: + fit_csv_files = previous_fit.runset.csv_files elif isinstance(previous_fit, list): if len(previous_fit) < 1: raise ValueError( @@ -1553,7 +1556,11 @@ def pathfinder( ' '.join(runset.cmd(0)), runset.get_err_msgs() ) raise RuntimeError(msg) - return CmdStanPathfinder(runset) + return CmdStanPathfinder.from_files( + csv_file=runset.csv_files[0], + config_file=runset.config_files[0], + stdout_file=runset.stdout_files[0], + ) def log_prob( self, diff --git a/cmdstanpy/stanfit/__init__.py b/cmdstanpy/stanfit/__init__.py index 9f44d842..787d8238 100644 --- a/cmdstanpy/stanfit/__init__.py +++ b/cmdstanpy/stanfit/__init__.py @@ -7,7 +7,6 @@ CmdStanArgs, LaplaceArgs, OptimizeArgs, - PathfinderArgs, SamplerArgs, VariationalArgs, ) @@ -256,21 +255,21 @@ def from_csv( ) return CmdStanLaplace(runset, mode=mode) elif config_dict['method'] == 'pathfinder': - pathfinder_args = PathfinderArgs( - num_draws=config_dict['num_draws'], # type: ignore - num_paths=config_dict['num_paths'], # type: ignore - ) - cmdstan_args = CmdStanArgs( - model_name=model, - model_exe=model, - chain_ids=None, - method_args=pathfinder_args, + if len(csvfiles) != 1: + raise ValueError( + 'Expecting a single Pathfinder Stan CSV file, ' + f'found {len(csvfiles)}' + ) + csv_file = csvfiles[0] + config_file = os.path.splitext(csv_file)[0] + '_config.json' + if not os.path.exists(config_file): + raise ValueError( + 'Pathfinder config file not found at expected path: ' + f'{config_file}' + ) + return CmdStanPathfinder.from_files( + csv_file=csv_file, config_file=config_file ) - runset = RunSet(args=cmdstan_args) - runset._csv_files = csvfiles - for i in range(len(runset._retcodes)): - runset._set_retcode(i, 0) - return CmdStanPathfinder(runset) else: get_logger().warning( 'Unable to process CSV output files from method %s.', diff --git a/cmdstanpy/stanfit/gq.py b/cmdstanpy/stanfit/gq.py index 7046fd61..1937cc32 100644 --- a/cmdstanpy/stanfit/gq.py +++ b/cmdstanpy/stanfit/gq.py @@ -6,15 +6,8 @@ from __future__ import annotations from collections import Counter -from typing import ( - Any, - Generic, - Hashable, - MutableMapping, - NoReturn, - TypeVar, - overload, -) +from collections.abc import Hashable +from typing import Any, Generic, MutableMapping, NoReturn, TypeVar, overload import numpy as np import pandas as pd @@ -239,7 +232,7 @@ def draws( drop_cols: list[int] = [] for dup in dups: drop_cols.extend( - self.previous_fit._metadata.stan_vars[dup].columns() + self.previous_fit.metadata.stan_vars[dup].columns() ) start_idx, _ = self._draws_start(inc_warmup) @@ -333,10 +326,8 @@ def draws_pd( gq_cols.extend( self.column_names[info.start_idx : info.end_idx] ) - elif ( - inc_sample and var in self.previous_fit._metadata.stan_vars - ): - info = self.previous_fit._metadata.stan_vars[var] + elif inc_sample and var in self.previous_fit.metadata.stan_vars: + info = self.previous_fit.metadata.stan_vars[var] mcmc_vars.extend( self.previous_fit.column_names[ info.start_idx : info.end_idx @@ -472,7 +463,7 @@ def draws_xr( for var in vars_list: if var not in self._metadata.stan_vars: if inc_sample and ( - var in self.previous_fit._metadata.stan_vars + var in self.previous_fit.metadata.stan_vars ): mcmc_vars_list.append(var) dup_vars.append(var) @@ -481,7 +472,7 @@ def draws_xr( else: vars_list = list(self._metadata.stan_vars.keys()) if inc_sample: - for var in self.previous_fit._metadata.stan_vars.keys(): + for var in self.previous_fit.metadata.stan_vars.keys(): if var not in vars_list and var not in mcmc_vars_list: mcmc_vars_list.append(var) for var in dup_vars: @@ -490,7 +481,7 @@ def draws_xr( self._assemble_generated_quantities() num_draws = self.previous_fit.num_draws_sampling - sample_config = self.previous_fit._metadata.cmdstan_config + sample_config = self.previous_fit.metadata.cmdstan_config attrs: MutableMapping[Hashable, Any] = { "stan_version": f"{sample_config['stan_version_major']}." f"{sample_config['stan_version_minor']}." @@ -518,7 +509,7 @@ def draws_xr( for var in mcmc_vars_list: build_xarray_data( data, - self.previous_fit._metadata.stan_vars[var], + self.previous_fit.metadata.stan_vars[var], self.previous_fit.draws(inc_warmup=inc_warmup), ) @@ -570,7 +561,7 @@ def stan_variable(self, var: str, **kwargs: bool) -> np.ndarray: CmdStanVB.stan_variable CmdStanLaplace.stan_variable """ - model_var_names = self.previous_fit._metadata.stan_vars.keys() + model_var_names = self.previous_fit.metadata.stan_vars.keys() gq_var_names = self._metadata.stan_vars.keys() if not (var in model_var_names or var in gq_var_names): raise ValueError( @@ -611,7 +602,7 @@ def stan_variables(self, **kwargs: bool) -> dict[str, np.ndarray]: CmdStanLaplace.stan_variables """ result = {} - sample_var_names = self.previous_fit._metadata.stan_vars.keys() + sample_var_names = self.previous_fit.metadata.stan_vars.keys() gq_var_names = self._metadata.stan_vars.keys() for name in gq_var_names: result[name] = self.stan_variable(name, **kwargs) diff --git a/cmdstanpy/stanfit/pathfinder.py b/cmdstanpy/stanfit/pathfinder.py index 60f831cd..bc0339d6 100644 --- a/cmdstanpy/stanfit/pathfinder.py +++ b/cmdstanpy/stanfit/pathfinder.py @@ -2,30 +2,63 @@ Container for the result of running Pathfinder. """ +from __future__ import annotations + +import os +import shutil +from dataclasses import dataclass, field +from pathlib import Path + import numpy as np -from cmdstanpy.cmdstan_args import Method -from cmdstanpy.stanfit.metadata import InferenceMetadata -from cmdstanpy.stanfit.runset import RunSet +from cmdstanpy.stanfit.metadata import ( + InferenceMetadata, + PathfinderConfig, + parse_config, +) from cmdstanpy.utils import stancsv +@dataclass class CmdStanPathfinder: """ Container for outputs from the Pathfinder algorithm. Created by :meth:`CmdStanModel.pathfinder()`. """ - def __init__(self, runset: RunSet): - """Initialize object.""" - if not runset.method == Method.PATHFINDER: + metadata: InferenceMetadata + model_name: str + csv_file: str + config: PathfinderConfig + config_file: str | None = None + stdout_file: str | None = None + _draws: np.ndarray = field(default_factory=lambda: np.array(()), init=False) + + @classmethod + def from_files( + cls, + csv_file: str | os.PathLike, + config_file: str | os.PathLike, + stdout_file: str | os.PathLike | None = None, + ) -> CmdStanPathfinder: + with open(config_file) as f: + stan_config = parse_config(f.read()) + + if not isinstance(stan_config.method_config, PathfinderConfig): + conf_name = type(stan_config.method_config).__name__ raise ValueError( - 'Wrong runset method, expecting Pathfinder runset, ' - 'found method {}'.format(runset.method) + f"Did not find Pathfinder config, instead found: {conf_name}" ) - self.runset = runset - self._draws: np.ndarray = np.array(()) - self._metadata = InferenceMetadata.from_csv(self.runset.csv_files[0]) + + metadata = InferenceMetadata.from_csv(csv_file) + return cls( + metadata=metadata, + csv_file=str(csv_file), + model_name=stan_config.model_name, + config=stan_config.method_config, + config_file=str(config_file), + stdout_file=str(stdout_file) if stdout_file is not None else None, + ) def create_inits( self, seed: int | None = None, chains: int = 4 @@ -49,42 +82,38 @@ def create_inits( draw = self._draws[idxs[0]] return { name: var.extract_reshape(draw) - for name, var in self._metadata.stan_vars.items() + for name, var in self.metadata.stan_vars.items() } else: return [ { name: var.extract_reshape(self._draws[idx]) - for name, var in self._metadata.stan_vars.items() + for name, var in self.metadata.stan_vars.items() } for idx in idxs ] def __repr__(self) -> str: - rep = 'CmdStanPathfinder: model={}{}'.format( - self.runset.model, - self.runset._args.method_args.compose(0, cmd=[]), - ) - rep = '{}\n csv_files:\n\t{}\n output_files:\n\t{}'.format( - rep, - '\n\t'.join(self.runset.csv_files), - '\n\t'.join(self.runset.stdout_files), - ) - return rep + lines = [ + f'CmdStanPathfinder: model={self.model_name}', + f' csv_file:\n\t{self.csv_file}', + ] + if self.config_file is not None: + lines.append(f' config_file:\n\t{self.config_file}') + if self.stdout_file is not None: + lines.append(f' output_file:\n\t{self.stdout_file}') + return '\n'.join(lines) def _assemble_draws(self) -> None: if self._draws.shape != (0,): return - csv_file = self.runset.csv_files[0] try: - *_, draws = stancsv.parse_comments_header_and_draws( - self.runset.csv_files[0] - ) + *_, draws = stancsv.parse_comments_header_and_draws(self.csv_file) self._draws = stancsv.csv_bytes_list_to_numpy(draws) except Exception as exc: raise ValueError( - f"An error occurred when parsing Stan csv {csv_file}" + f"An error occurred when parsing Stan csv {self.csv_file}" ) from exc def stan_variable(self, var: str) -> np.ndarray: @@ -109,7 +138,7 @@ def stan_variable(self, var: str) -> np.ndarray: """ self._assemble_draws() try: - out: np.ndarray = self._metadata.stan_vars[var].extract_reshape( + out: np.ndarray = self.metadata.stan_vars[var].extract_reshape( self._draws ) return out @@ -118,7 +147,7 @@ def stan_variable(self, var: str) -> np.ndarray: raise ValueError( f'Unknown variable name: {var}\n' 'Available variables are ' - + ", ".join(self._metadata.stan_vars.keys()) + + ", ".join(self.metadata.stan_vars.keys()) ) def stan_variables(self) -> dict[str, np.ndarray]: @@ -136,7 +165,7 @@ def stan_variables(self) -> dict[str, np.ndarray]: CmdStanLaplace.stan_variables """ result = {} - for name in self._metadata.stan_vars: + for name in self.metadata.stan_vars: result[name] = self.stan_variable(name) return result @@ -151,7 +180,7 @@ def method_variables(self) -> dict[str, np.ndarray]: self._assemble_draws() return { name: var.extract_reshape(self._draws) - for name, var in self._metadata.method_vars.items() + for name, var in self.metadata.method_vars.items() } def draws(self) -> np.ndarray: @@ -181,15 +210,6 @@ def __getstate__(self) -> dict: self._assemble_draws() return self.__dict__ - @property - def metadata(self) -> InferenceMetadata: - """ - Returns object which contains CmdStan configuration as well as - information about the names and structure of the inference method - and model output variables. - """ - return self._metadata - @property def column_names(self) -> tuple[str, ...]: """ @@ -198,7 +218,7 @@ def column_names(self) -> tuple[str, ...]: and quantities of interest. Corresponds to Stan CSV file header row, with names munged to array notation, e.g. `beta[1]` not `beta.1`. """ - return self._metadata.column_names + return self.metadata.column_names @property def is_resampled(self) -> bool: @@ -207,22 +227,32 @@ def is_resampled(self) -> bool: approximations, False otherwise. """ return ( - self._metadata.cmdstan_config.get("num_paths", 4) > 1 - and self._metadata.cmdstan_config.get('psis_resample', 1) - in (1, 'true') - and self._metadata.cmdstan_config.get('calculate_lp', 1) - in (1, 'true') + self.config.num_paths > 1 + and self.config.psis_resample + and self.config.calculate_lp ) def save_csvfiles(self, dir: str | None = None) -> None: """ - Move output CSV files to specified directory. + Move output CSV file, and any associated config and stdout files, + to the specified directory. Updates the corresponding attributes on + this object to point at the new locations. :param dir: directory path See Also -------- - stanfit.RunSet.save_csvfiles cmdstanpy.from_csv """ - self.runset.save_csvfiles(dir) + dest = Path(dir) if dir is not None else Path.cwd() + dest.mkdir(parents=True, exist_ok=True) + + for attr in ('csv_file', 'config_file', 'stdout_file'): + src = getattr(self, attr) + if src is None: + continue + dst = dest / Path(src).name + if dst.exists(): + raise ValueError(f'File exists, not overwriting: {dst}') + shutil.move(src, dst) + setattr(self, attr, str(dst)) diff --git a/test/data/pathfinder/bernoulli-pathfinder.csv b/test/data/pathfinder/bernoulli-pathfinder.csv index ad5ccff2..d034041e 100644 --- a/test/data/pathfinder/bernoulli-pathfinder.csv +++ b/test/data/pathfinder/bernoulli-pathfinder.csv @@ -1,1039 +1,1044 @@ # stan_version_major = 2 -# stan_version_minor = 32 -# stan_version_patch = 2 +# stan_version_minor = 37 +# stan_version_patch = 0 # model = bernoulli_model -# start_datetime = 2023-08-25 18:20:52 UTC +# start_datetime = 2026-04-12 00:35:48 UTC # method = pathfinder # pathfinder # init_alpha = 0.001 (Default) -# tol_obj = 9.9999999999999998e-13 (Default) +# tol_obj = 1e-12 (Default) # tol_rel_obj = 10000 (Default) # tol_grad = 1e-08 (Default) -# tol_rel_grad = 10000000 (Default) +# tol_rel_grad = 1e+07 (Default) # tol_param = 1e-08 (Default) # history_size = 5 (Default) # num_psis_draws = 1000 (Default) # num_paths = 4 (Default) -# save_single_paths = 0 (Default) +# save_single_paths = false (Default) +# psis_resample = true (Default) +# calculate_lp = true (Default) # max_lbfgs_iters = 1000 (Default) # num_draws = 1000 (Default) # num_elbo_draws = 25 (Default) # id = 1 (Default) # data -# file = /home/brian/Dev/py/cmdstanpy/test/data/bernoulli.data.json +# file = test/data/bernoulli.data.json # init = 2 (Default) # random -# seed = 60096 +# seed = 12345 # output -# file = /tmp/tmpu_8pqsqm/bernoullix1z9yxm4/bernoulli-20230825142052.csv +# file = /tmp/tmpj7vksit8/bernoulli9hb1n4hj/bernoulli-20260411203548.csv # diagnostic_file = (Default) # refresh = 100 (Default) -# sig_figs = -1 (Default) +# sig_figs = 8 (Default) # profile_file = profile.csv (Default) +# save_cmdstan_config = true # num_threads = 1 (Default) -lp_approx__,lp__,theta --0.476551, -6.76206, 0.271327 --1.03168, -7.1987, 0.145419 --2.4285, -8.92516, 0.546197 --1.32207, -7.65466, 0.4371 --1.53739, -7.87901, 0.460369 --1.12454, -7.42633, 0.410357 --0.497944, -6.77806, 0.22023 --0.93635, -7.12896, 0.152721 --1.74264, -7.75439, 0.105291 --0.561756, -6.81822, 0.298664 --1.31969, -7.40828, 0.127362 --1.61855, -7.94818, 0.467076 --0.853618, -7.06293, 0.160499 --0.516076, -6.77093, 0.223904 --1.25333, -7.56654, 0.427208 --0.626345, -6.86948, 0.192008 --0.566813, -6.81689, 0.205629 --1.81711, -7.80861, 0.102414 --0.485188, -6.75037, 0.241505 --1.48451, -7.55049, 0.117398 --1.49785, -7.81761, 0.454244 --0.597054, -6.84943, 0.196709 --0.524347, -6.76562, 0.273927 --0.589162, -6.87127, 0.315193 --0.508892, -6.76518, 0.273615 --0.526366, -6.76768, 0.275313 --1.2809, -7.58501, 0.429321 --0.515714, -6.79968, 0.291537 --1.08516, -7.37888, 0.404289 --0.720885, -6.98905, 0.342663 --1.21042, -7.51517, 0.421205 --0.603394, -6.8608, 0.312244 --0.912615, -7.19824, 0.378964 --1.8676, -7.81361, 0.102155 --0.737547, -6.99206, 0.343271 --0.511134, -6.77588, 0.280252 --0.510004, -6.75108, 0.240313 --0.493452, -6.75001, 0.257941 --0.636148, -6.86832, 0.192268 --0.554036, -6.83687, 0.304983 --0.914616, -7.1106, 0.154789 --0.561853, -6.80424, 0.293389 --0.543132, -6.78486, 0.284908 --1.35137, -7.43078, 0.125683 --0.470003, -6.75434, 0.236132 --0.482583, -6.74804, 0.250683 --0.511373, -6.75251, 0.261965 --0.615103, -6.87287, 0.315632 --1.48451, -7.55049, 0.117398 --0.547459, -6.80618, 0.209068 --0.72476, -6.94711, 0.17715 --1.09627, -7.25885, 0.139717 --0.638048, -6.8846, 0.188752 --0.484429, -6.74986, 0.25763 --0.476269, -6.75965, 0.231266 --0.673947, -6.91074, 0.183582 --1.05347, -7.22239, 0.143114 --0.688123, -6.92693, 0.180622 --0.721566, -6.9443, 0.177619 --1.15416, -7.46034, 0.414585 --0.524232, -6.77841, 0.220062 --0.533364, -6.81676, 0.298138 --0.619038, -6.88407, 0.318644 --5.77772, -10.1268, 0.0384689 --0.543383, -6.79582, 0.212741 --0.595615, -6.83146, 0.201396 --1.52209, -7.57032, 0.116119 --1.11984, -7.41443, 0.408855 --0.48601, -6.77112, 0.277488 --0.500169, -6.76399, 0.22812 --0.564116, -6.84671, 0.308068 --0.93441, -7.21309, 0.381206 --0.59264, -6.82873, 0.202156 --4.27749, -9.21226, 0.0549588 --1.06407, -7.35554, 0.401227 --0.577253, -6.834, 0.304055 --0.535559, -6.80001, 0.291671 --0.983256, -7.16663, 0.148675 --0.483092, -6.74847, 0.246288 --0.937678, -7.22416, 0.382855 --0.48508, -6.75027, 0.241684 --1.5953, -7.95495, 0.467722 --0.788202, -7.00747, 0.167888 --0.911056, -7.19663, 0.378719 --2.8102, -9.26521, 0.568921 --0.463059, -6.74899, 0.255523 --1.7566, -8.14059, 0.484777 --0.598541, -6.85072, 0.196393 --0.985094, -7.2675, 0.389149 --0.616662, -6.86631, 0.19272 --0.868349, -7.14437, 0.370533 --2.75506, -8.45281, 0.0756527 --1.69102, -7.7004, 0.108287 --1.06603, -7.23048, 0.142345 --0.816516, -7.03524, 0.164075 --0.992746, -7.17345, 0.147969 --0.466377, -6.75228, 0.261646 --0.635039, -6.88203, 0.189289 --1.19915, -7.33221, 0.133367 --1.11937, -7.27746, 0.138048 --2.15059, -8.53127, 0.517193 --0.926578, -7.20155, 0.379467 --1.12208, -7.27618, 0.138161 --0.654639, -6.92051, 0.32772 --0.600609, -6.86346, 0.19337 --0.675617, -6.91218, 0.183313 --0.749676, -6.96888, 0.173633 --4.27749, -9.21226, 0.0549588 --0.586314, -6.85174, 0.196142 --1.3103, -7.41547, 0.126821 --0.954169, -7.14257, 0.151229 --0.534988, -6.77649, 0.280587 --0.644452, -6.89911, 0.185817 --1.06961, -7.23511, 0.14191 --0.557442, -6.81384, 0.29707 --1.09875, -7.39395, 0.406239 --0.729041, -6.95776, 0.175402 --0.740701, -7.0225, 0.349236 --0.641459, -6.87311, 0.191207 --0.696773, -6.93031, 0.180025 --0.49457, -6.75891, 0.231863 --0.635866, -6.90126, 0.323048 --0.644235, -6.87561, 0.190662 --0.550628, -6.78976, 0.215093 --3.69897, -8.9643, 0.0608185 --1.01412, -7.1856, 0.146729 --1.48817, -7.565, 0.116459 --1.7993, -7.76635, 0.104646 --0.698811, -6.9602, 0.336649 --0.686703, -6.92169, 0.181562 --3.31541, -8.76493, 0.0661085 --0.524232, -6.77841, 0.220062 --0.6204, -6.85407, 0.195579 --0.664773, -6.90727, 0.184239 --0.561638, -6.80006, 0.211191 --1.5482, -7.87199, 0.459677 --0.502082, -6.75798, 0.232638 --0.668035, -6.90565, 0.184548 --0.720358, -6.97333, 0.33943 --2.31182, -8.76251, 0.534606 --0.540925, -6.79716, 0.290478 --1.31708, -7.43372, 0.125468 --0.51659, -6.75776, 0.267709 --1.54662, -7.91801, 0.464175 --0.534151, -6.78745, 0.216041 --0.483741, -6.74905, 0.244357 --0.579635, -6.84625, 0.197503 --0.762851, -6.99336, 0.169923 --0.504648, -6.76037, 0.230708 --0.662141, -6.9104, 0.325298 --0.579328, -6.81647, 0.205757 --0.518412, -6.77307, 0.22274 --4.3007, -9.39725, 0.0510335 --0.48609, -6.75147, 0.260477 --0.482703, -6.74817, 0.252126 --0.655405, -6.9213, 0.327906 --0.484876, -6.75029, 0.25849 --2.50067, -8.2531, 0.0827528 --0.737547, -6.99206, 0.343271 --0.679143, -6.91521, 0.182749 --1.52767, -7.89565, 0.462001 --0.758427, -7.02826, 0.350331 --0.491842, -6.74844, 0.253629 --0.984875, -7.26927, 0.389401 --1.0793, -7.37456, 0.403727 --0.498706, -6.76372, 0.272576 --0.88251, -7.1672, 0.374166 --0.916666, -7.11215, 0.154611 --1.27527, -7.57901, 0.428637 --0.504361, -6.7607, 0.270251 --0.514673, -6.77936, 0.28213 --0.491842, -6.74844, 0.253629 --1.14149, -7.27974, 0.137847 --7.32737, -10.8822, 0.0290424 --0.482574, -6.74802, 0.250171 --2.82118, -9.45552, 0.58085 --0.55033, -6.78949, 0.215206 --0.546924, -6.8057, 0.209228 --1.85995, -8.24408, 0.493782 --1.44717, -7.76302, 0.448651 --2.97469, -8.59483, 0.0710988 --0.49457, -6.75891, 0.231863 --0.464446, -6.75038, 0.258657 --1.35756, -7.45043, 0.124251 --0.580172, -6.83698, 0.305019 --0.483292, -6.74865, 0.245604 --0.515714, -6.79968, 0.291537 --3.56948, -8.91715, 0.0620196 --0.53011, -6.7715, 0.277715 --0.592377, -6.857, 0.311141 --0.541998, -6.82515, 0.301093 --0.998687, -7.17406, 0.147906 --2.68293, -8.37102, 0.0784552 --1.27952, -7.37961, 0.129563 --0.536132, -6.77767, 0.281226 --0.490585, -6.77551, 0.280042 --0.46224, -6.74805, 0.250978 --1.33761, -7.44117, 0.124923 --0.911113, -7.18772, 0.377355 --0.50848, -6.74959, 0.24304 --0.613657, -6.86373, 0.193307 --0.515405, -6.79279, 0.213895 --0.636148, -6.86832, 0.192268 --1.14179, -7.29545, 0.136474 --1.38065, -7.71021, 0.443101 --2.66315, -8.39248, 0.0777063 --0.644452, -6.89911, 0.185817 --0.51127, -6.78931, 0.215276 --0.567676, -6.83209, 0.303428 --0.581574, -6.82484, 0.300987 --2.01155, -8.41724, 0.508156 --0.536151, -6.77768, 0.281237 --0.486847, -6.75188, 0.23913 --0.53082, -6.79531, 0.289686 --0.789836, -7.00367, 0.168428 --0.665532, -6.91404, 0.326179 --0.760107, -7.03002, 0.350663 --0.808746, -7.02456, 0.165513 --1.0461, -7.20943, 0.144365 --2.63301, -8.27172, 0.0820527 --1.05471, -7.34518, 0.399851 --3.9779, -9.12395, 0.0569619 --0.70141, -6.94479, 0.177537 --0.60206, -6.86465, 0.193098 --2.15609, -8.04921, 0.0910074 --0.604035, -6.84991, 0.196591 --0.53925, -6.77906, 0.219753 --0.932342, -7.20803, 0.380446 --1.28145, -7.5856, 0.429388 --1.00417, -7.1824, 0.147054 --1.98629, -7.86254, 0.0996736 --0.527551, -6.79207, 0.288263 --0.909871, -7.10563, 0.15536 --2.48582, -8.24339, 0.0831209 --1.1631, -7.46005, 0.414549 --0.506979, -6.74812, 0.251783 --7.32737, -10.8822, 0.0290424 --0.720159, -6.95969, 0.175091 --1.68952, -7.66497, 0.110331 --1.66739, -7.69907, 0.108363 --2.97469, -8.59483, 0.0710988 --0.654913, -6.90264, 0.323393 --2.40468, -8.21981, 0.0840255 --2.48615, -8.24361, 0.0831128 --0.515211, -6.75612, 0.234317 --1.45402, -7.52106, 0.119342 --0.503876, -6.78827, 0.286532 --1.53718, -7.58117, 0.115429 --1.12622, -7.26856, 0.138842 --1.56032, -7.57672, 0.115711 --1.33831, -7.65658, 0.437311 --0.676618, -6.92597, 0.329001 --0.860883, -7.14496, 0.370628 --0.483174, -6.74864, 0.254396 --0.977282, -7.15799, 0.14958 --1.52053, -7.86008, 0.458498 --0.659324, -6.94078, 0.332385 --0.718275, -6.98073, 0.340965 --1.0205, -7.30777, 0.394783 --1.7566, -8.14059, 0.484777 --0.751488, -6.97671, 0.17242 --0.608379, -6.86981, 0.191934 --0.491929, -6.74849, 0.246191 --3.28997, -8.72374, 0.0672741 --0.488313, -6.75322, 0.237407 --0.987015, -7.26967, 0.389458 --0.948504, -7.23537, 0.384508 --0.508056, -6.74919, 0.256084 --0.698604, -6.95998, 0.336602 --0.93063, -7.20897, 0.380587 --0.487847, -6.75279, 0.237927 --0.793912, -7.06554, 0.357176 --0.553977, -6.81033, 0.295756 --0.532686, -6.79716, 0.290478 --0.509879, -6.79405, 0.289141 --1.40984, -7.7229, 0.444447 --0.539861, -6.82307, 0.300376 --2.83267, -8.39291, 0.0776913 --2.04207, -7.94632, 0.0956361 --4.3182, -9.31427, 0.0527507 --1.63944, -8.00561, 0.4725 --0.491576, -6.74816, 0.247927 --0.507515, -6.74866, 0.254467 --0.839567, -7.05308, 0.161747 --0.919495, -7.11533, 0.154249 --0.946466, -7.13711, 0.151823 --0.598024, -6.85528, 0.310637 --0.658482, -6.90647, 0.324339 --1.54416, -7.88662, 0.461116 --0.95555, -7.23618, 0.384627 --0.495093, -6.77564, 0.221417 --0.513197, -6.79094, 0.214625 --4.37053, -9.34312, 0.0521459 --1.4869, -7.84764, 0.45726 --0.525514, -6.77958, 0.219507 --0.52013, -6.76086, 0.230337 --1.08516, -7.37888, 0.404289 --3.36444, -10.1208, 0.618855 --0.462555, -6.7482, 0.247675 --2.24011, -8.74832, 0.53357 --0.693746, -6.93868, 0.178573 --1.30376, -7.41061, 0.127186 --0.542003, -6.79824, 0.290937 --0.554032, -6.79295, 0.213833 --0.679828, -6.96126, 0.336877 --1.00615, -7.29134, 0.392508 --0.474323, -6.758, 0.232626 --2.60737, -9.03862, 0.553995 --0.646971, -6.90592, 0.324203 --0.995593, -7.28084, 0.391037 --1.59523, -7.64549, 0.111481 --1.12208, -7.27618, 0.138161 --1.67702, -7.70618, 0.10796 --0.670689, -6.8993, 0.18578 --0.618613, -6.8765, 0.316621 --0.504797, -6.76051, 0.230602 --0.994996, -7.17631, 0.147675 --0.906863, -7.17944, 0.376077 --1.89755, -7.80418, 0.102645 --0.499825, -6.75624, 0.266253 --0.463059, -6.74857, 0.245871 --0.497944, -6.77806, 0.22023 --0.6204, -6.85407, 0.195579 --0.512804, -6.75395, 0.263767 --0.613657, -6.86373, 0.193307 --0.495248, -6.75176, 0.260918 --0.65032, -6.89503, 0.186624 --0.615292, -6.87307, 0.315686 --0.994119, -7.27925, 0.390813 --1.03219, -7.19908, 0.145381 --1.16016, -7.46723, 0.41543 --0.654301, -6.89841, 0.185955 --0.644158, -6.89887, 0.185864 --0.839567, -7.05308, 0.161747 --1.08786, -7.38187, 0.404679 --0.585037, -6.84958, 0.308938 --0.530688, -6.81417, 0.297189 --0.921481, -7.11535, 0.154248 --0.545197, -6.82826, 0.302151 --0.516547, -6.77276, 0.278469 --0.525965, -6.80166, 0.210621 --0.595714, -6.83155, 0.201371 --0.759309, -7.01586, 0.347962 --0.718275, -6.98073, 0.340965 --1.1366, -7.43208, 0.41108 --0.761187, -7.03115, 0.350876 --1.01439, -7.19145, 0.146142 --1.25572, -7.57758, 0.428473 --0.679538, -6.91555, 0.182686 --0.535614, -6.80006, 0.291694 --0.491464, -6.74806, 0.248944 --0.79807, -7.08071, 0.359856 --1.21303, -7.33177, 0.133404 --0.497187, -6.75366, 0.263428 --0.611718, -6.85667, 0.194956 --0.491772, -6.75637, 0.234088 --0.497511, -6.75398, 0.263805 --0.604751, -6.85607, 0.195098 --0.665508, -6.92526, 0.328835 --0.569441, -6.82604, 0.301397 --0.968838, -7.15509, 0.149888 --0.61717, -6.85113, 0.196291 --0.485244, -6.76728, 0.226018 --0.750968, -7.02045, 0.348844 --0.729162, -6.95097, 0.17651 --0.513526, -6.79757, 0.290653 --0.611372, -6.89317, 0.321005 --0.49703, -6.76209, 0.271349 --0.495126, -6.77567, 0.221402 --2.25096, -8.71647, 0.53123 --0.764772, -6.98787, 0.170734 --0.594514, -6.84724, 0.197255 --1.83626, -8.18547, 0.488723 --0.532551, -6.78874, 0.28675 --0.507605, -6.77242, 0.278267 --0.518671, -6.75986, 0.269557 --0.46225, -6.74802, 0.250035 --0.868118, -7.0735, 0.159187 --0.501239, -6.7662, 0.274321 --0.66792, -6.89683, 0.186267 --2.32918, -8.14014, 0.0871861 --0.627899, -6.8857, 0.188522 --0.506739, -6.77157, 0.27776 --1.41469, -7.74162, 0.44642 --2.15357, -7.97102, 0.0944935 --7.32737, -10.8822, 0.0290424 --5.55354, -10.0119, 0.0401856 --1.20438, -7.33987, 0.132737 --0.496515, -6.753, 0.262612 --0.51797, -6.75878, 0.231968 --0.573819, -6.83827, 0.30543 --1.24207, -7.55391, 0.425748 --1.17274, -7.31549, 0.134762 --0.640798, -6.88754, 0.319552 --1.45799, -7.77466, 0.449856 --0.522646, -6.79888, 0.211614 --1.27825, -7.59002, 0.429891 --0.949924, -7.23163, 0.383959 --0.635131, -6.90051, 0.322861 --0.657087, -6.92303, 0.328313 --0.903186, -7.10189, 0.155794 --0.948504, -7.23537, 0.384508 --0.809639, -7.02732, 0.165138 --2.20201, -8.70222, 0.530177 --0.792511, -7.01657, 0.166612 --1.85995, -8.24408, 0.493782 --0.621293, -6.88034, 0.189648 --0.564293, -6.80253, 0.210317 --0.587277, -6.83082, 0.303009 --2.25096, -8.71647, 0.53123 --0.553607, -6.80504, 0.209451 --0.641756, -6.87337, 0.191148 --0.952757, -7.23313, 0.384179 --0.591705, -6.85632, 0.310942 --0.494434, -6.75957, 0.269306 --0.555207, -6.81158, 0.296226 --0.767788, -6.99309, 0.169963 --4.43783, -9.47559, 0.0494739 --1.2903, -7.59502, 0.430458 --0.724092, -6.94652, 0.177248 --4.33534, -9.35797, 0.0518379 --0.519944, -6.76115, 0.270612 --0.501946, -6.78642, 0.285656 --1.07473, -7.36934, 0.403045 --1.78274, -7.76569, 0.104681 --1.35572, -7.45477, 0.123939 --0.498183, -6.75464, 0.264556 --1.39091, -7.45872, 0.123656 --2.27444, -8.0482, 0.0910512 --0.999881, -7.1799, 0.147308 --1.89755, -7.80418, 0.102645 --0.518607, -6.7598, 0.269503 --0.954169, -7.14257, 0.151229 --0.677429, -6.9053, 0.184615 --1.28772, -7.38547, 0.129106 --0.538065, -6.79428, 0.28924 --0.514102, -6.75505, 0.235376 --1.07361, -7.22982, 0.142408 --1.98629, -7.86254, 0.0996736 --0.934812, -7.12647, 0.152997 --1.17589, -7.30483, 0.135667 --0.508743, -6.79296, 0.28866 --1.72671, -7.7259, 0.106855 --1.35325, -7.46175, 0.12344 --0.510451, -6.75151, 0.239653 --0.485259, -6.75067, 0.259163 --1.2459, -7.37805, 0.129684 --0.593782, -6.85787, 0.194671 --0.510004, -6.75108, 0.240313 --0.782098, -7.00483, 0.168263 --0.598118, -6.85537, 0.310666 --0.512671, -6.79049, 0.214801 --0.493605, -6.77841, 0.281623 --0.748394, -6.96777, 0.173808 --1.11486, -7.26022, 0.139593 --1.66119, -7.69449, 0.108624 --0.491438, -6.75606, 0.234376 --1.75994, -7.76703, 0.104609 --0.463688, -6.74963, 0.257129 --0.880292, -7.1571, 0.372569 --1.11486, -7.26022, 0.139593 --1.49377, -7.55731, 0.116955 --2.16434, -8.05495, 0.0907591 --0.720892, -6.95085, 0.17653 --0.933134, -7.2117, 0.380997 --0.637934, -6.8845, 0.188772 --0.735049, -6.96284, 0.174587 --0.894794, -7.16593, 0.373967 --1.63228, -7.96309, 0.468497 --1.30505, -7.39785, 0.128154 --0.543556, -6.79981, 0.291589 --0.819196, -7.09223, 0.361852 --1.23735, -7.54485, 0.424695 --4.43783, -9.47559, 0.0494739 --0.764728, -7.0218, 0.349103 --0.521536, -6.78318, 0.217868 --0.521238, -6.77743, 0.281101 --0.60979, -6.87096, 0.191679 --0.517594, -6.78224, 0.283608 --2.67858, -8.29958, 0.0810207 --0.510071, -6.75121, 0.260061 --0.463853, -6.7492, 0.243961 --1.87409, -7.84974, 0.100314 --0.540443, -6.79998, 0.211218 --1.39091, -7.45872, 0.123656 --0.528726, -6.76908, 0.224953 --0.509511, -6.7506, 0.2411 --0.513784, -6.75493, 0.264883 --1.47638, -7.55606, 0.117036 --1.34536, -7.44143, 0.124904 --1.13461, -7.43379, 0.411293 --0.550773, -6.7899, 0.215038 --1.37239, -7.47653, 0.122395 --0.49409, -6.75063, 0.259107 --3.29022, -8.74966, 0.0665374 --0.522464, -6.78704, 0.285952 --0.749323, -6.96858, 0.173681 --0.987197, -7.27085, 0.389625 --0.482985, -6.74837, 0.246709 --0.533255, -6.81666, 0.2981 --2.21661, -8.0493, 0.0910036 --0.955023, -7.2356, 0.384542 --0.577876, -6.86019, 0.312068 --0.515739, -6.778, 0.220256 --0.494037, -6.75918, 0.268976 --1.27218, -7.37435, 0.129974 --0.927268, -7.20531, 0.380035 --4.38523, -9.44563, 0.0500635 --3.35852, -8.83627, 0.0641505 --0.492148, -6.74869, 0.245435 --0.467602, -6.75346, 0.26319 --2.52031, -8.29762, 0.0810925 --0.673701, -6.90198, 0.185256 --0.497406, -6.75387, 0.263683 --0.471462, -6.75718, 0.267169 --0.53579, -6.79199, 0.28823 --0.763713, -6.98698, 0.170867 --0.498626, -6.75507, 0.265032 --0.713737, -6.96614, 0.337915 --1.11662, -7.27193, 0.13854 --2.67865, -8.29962, 0.0810191 --0.51126, -6.7524, 0.261812 --0.68876, -6.9557, 0.335677 --0.497944, -6.77806, 0.22023 --4.3007, -9.39725, 0.0510335 --0.513563, -6.75471, 0.264638 --0.513489, -6.76973, 0.276627 --0.586105, -6.83407, 0.200682 --1.45131, -7.51909, 0.119474 --0.468008, -6.75265, 0.238101 --0.720358, -6.97333, 0.33943 --0.485087, -6.76715, 0.226099 --1.05253, -7.22339, 0.143019 --0.668628, -6.90616, 0.18445 --0.919495, -7.11533, 0.154249 --0.491526, -6.74813, 0.251834 --1.98189, -7.85966, 0.0998172 --0.47524, -6.76081, 0.270335 --3.2524, -8.77034, 0.0659573 --0.491526, -6.74811, 0.248303 --0.679828, -6.96126, 0.336877 --0.932829, -7.20858, 0.380528 --0.907268, -7.105, 0.155433 --0.66485, -6.89409, 0.186814 --2.22929, -8.69105, 0.529347 --0.485188, -6.75037, 0.241505 --1.49004, -7.52809, 0.118872 --3.28997, -8.72374, 0.0672741 --1.62236, -7.65103, 0.111152 --0.535191, -6.80939, 0.208003 --0.78136, -7.00786, 0.167832 --0.696773, -6.93031, 0.180025 --2.48615, -8.24361, 0.0831128 --2.51515, -8.26254, 0.0823966 --1.17767, -7.4818, 0.417203 --1.80656, -8.19836, 0.489845 --0.559243, -6.81011, 0.207768 --1.01656, -7.18743, 0.146545 --1.43296, -7.51239, 0.119925 --0.87653, -7.08038, 0.158348 --0.536105, -6.77764, 0.281211 --1.34243, -7.44479, 0.124659 --0.698604, -6.95998, 0.336602 --0.599731, -6.84612, 0.197536 --2.8102, -9.26521, 0.568921 --1.92702, -7.88769, 0.0984345 --0.888822, -7.15925, 0.372912 --0.462937, -6.74886, 0.255145 --1.0793, -7.37456, 0.403727 --0.561279, -6.81193, 0.20718 --0.739703, -6.99441, 0.343744 --0.518824, -6.79567, 0.212798 --0.638168, -6.91972, 0.327533 --3.54488, -8.90255, 0.0623976 --0.594279, -6.85892, 0.311701 --0.679075, -6.96051, 0.336715 --0.482687, -6.74811, 0.248353 --0.7967, -7.06419, 0.356934 --0.744694, -7.01389, 0.347581 --0.513598, -6.75457, 0.235885 --1.03212, -7.32036, 0.396506 --2.68293, -8.37102, 0.0784552 --1.03708, -7.2108, 0.144232 --1.03212, -7.32036, 0.396506 --0.500479, -6.76545, 0.27381 --1.10826, -7.4045, 0.407592 --0.483261, -6.74872, 0.254692 --0.497787, -6.76283, 0.271911 --0.511649, -6.75279, 0.262332 --0.698715, -6.92418, 0.181114 --0.527339, -6.76867, 0.275957 --1.63428, -7.65051, 0.111183 --0.483741, -6.74905, 0.244357 --4.27749, -9.21226, 0.0549588 --1.52424, -7.89161, 0.461606 --1.31708, -7.43372, 0.125468 --2.18009, -8.04026, 0.0913965 --2.72572, -9.17077, 0.562799 --4.43783, -9.47559, 0.0494739 --0.74295, -7.00687, 0.346214 --1.66119, -7.69449, 0.108624 --0.512657, -6.75365, 0.236892 --0.465922, -6.7509, 0.24059 --0.579829, -6.86211, 0.312618 --0.503725, -6.76863, 0.275927 --0.714436, -6.9669, 0.338076 --0.603956, -6.86873, 0.314488 --0.518824, -6.79567, 0.212798 --1.3567, -7.66594, 0.438332 --0.490577, -6.7755, 0.280037 --0.464172, -6.75011, 0.258141 --1.05433, -7.22486, 0.142879 --0.86442, -7.06736, 0.159946 --4.49779, -9.4483, 0.0500106 --2.82118, -9.45552, 0.58085 --4.40084, -9.35979, 0.0518004 --3.15312, -9.78286, 0.600215 --1.65214, -7.98466, 0.470536 --0.51773, -6.77245, 0.223074 --1.1922, -7.49082, 0.418293 --0.824186, -7.08734, 0.361008 --1.72671, -7.7259, 0.106855 --0.75653, -6.97485, 0.172706 --0.629168, -6.87195, 0.191462 --0.633933, -6.8761, 0.190555 --0.55033, -6.78949, 0.215206 --0.583585, -6.84047, 0.30613 --3.69897, -8.9643, 0.0608185 --0.648358, -6.90736, 0.324558 --0.507378, -6.74852, 0.253959 --0.621651, -6.87059, 0.191762 --0.466184, -6.75112, 0.240243 --3.67087, -10.3984, 0.633254 --0.629682, -6.87569, 0.3164 --0.518321, -6.75912, 0.231692 --0.708983, -6.97667, 0.340125 --0.49144, -6.74804, 0.249339 --0.823052, -7.03642, 0.163919 --1.30148, -7.62073, 0.433348 --0.793912, -7.06554, 0.357176 --0.554418, -6.8188, 0.298871 --3.55808, -8.91039, 0.0621943 --0.926626, -7.21272, 0.38115 --0.467847, -6.7537, 0.263477 --0.546151, -6.78797, 0.286392 --1.8676, -7.81361, 0.102155 --0.668714, -6.91746, 0.326997 --0.482707, -6.74813, 0.248193 --0.562962, -6.84559, 0.307722 --0.512697, -6.75369, 0.236848 --0.819507, -7.02915, 0.164891 --0.980291, -7.16368, 0.148982 --0.491646, -6.74825, 0.252663 --1.72838, -7.69124, 0.10881 --0.507391, -6.76369, 0.272552 --3.70366, -8.99628, 0.0600206 --0.653194, -6.89747, 0.18614 --0.594279, -6.85892, 0.311701 --0.659713, -6.88949, 0.187742 --1.08396, -7.2489, 0.140627 --0.471622, -6.75571, 0.234721 --0.507449, -6.74859, 0.25423 --0.812757, -7.03232, 0.164465 --1.1636, -7.46057, 0.414613 --1.07894, -7.37199, 0.403392 --1.2631, -7.57327, 0.42798 --0.522429, -6.80617, 0.29415 --0.469929, -6.75571, 0.265709 --0.775816, -7.05808, 0.355836 --0.462632, -6.74854, 0.254027 --0.510451, -6.77326, 0.222644 --0.525965, -6.80166, 0.210621 --0.638168, -6.91972, 0.327533 --0.51202, -6.78994, 0.215021 --0.658737, -6.88862, 0.187921 --0.511134, -6.77588, 0.280252 --0.758553, -6.98549, 0.17109 --0.508227, -6.74936, 0.256513 --0.674024, -6.93417, 0.330891 --0.501889, -6.75827, 0.268175 --0.809358, -7.02507, 0.165444 --1.52053, -7.86008, 0.458498 --1.41552, -7.49944, 0.120807 --1.04239, -7.33158, 0.398026 --1.05253, -7.22339, 0.143019 --1.52863, -7.85083, 0.457579 --1.31047, -7.61654, 0.432879 --0.646971, -6.90592, 0.324203 --0.49144, -6.74804, 0.249339 --0.916047, -7.1108, 0.154766 --1.35572, -7.45477, 0.123939 --0.483783, -6.76899, 0.27616 --0.838751, -7.11293, 0.365367 --0.626504, -6.8596, 0.194265 --0.598541, -6.85072, 0.196393 --1.10702, -7.40183, 0.407251 --3.56948, -8.91715, 0.0620196 --0.547475, -6.80376, 0.293197 --0.959965, -7.24243, 0.38554 --0.493179, -6.77402, 0.222245 --0.622435, -6.86798, 0.314278 --0.508877, -6.74998, 0.242232 --0.932829, -7.20858, 0.380528 --0.855113, -7.1303, 0.368244 --4.38523, -9.44563, 0.0500635 --1.23388, -7.36249, 0.130912 --0.512176, -6.75331, 0.263005 --1.34685, -7.44811, 0.124419 --1.31047, -7.61654, 0.432879 --1.68709, -8.02267, 0.474087 --1.3984, -7.46399, 0.12328 --0.589538, -6.84293, 0.198346 --2.23951, -8.08026, 0.0896753 --0.500005, -6.76384, 0.22822 --1.02073, -7.19054, 0.146232 --0.731705, -6.98569, 0.34198 --0.930609, -7.12448, 0.153219 --0.687322, -6.92626, 0.180742 --1.89535, -8.28444, 0.497207 --0.540269, -6.7965, 0.290197 --1.24478, -7.5649, 0.427019 --0.743087, -6.97782, 0.172251 --0.489786, -6.75505, 0.265014 --0.672115, -6.92138, 0.181619 --2.48582, -8.24339, 0.0831209 --0.794195, -7.0615, 0.356454 --0.495791, -6.7805, 0.282724 --0.519128, -6.7599, 0.231074 --0.515357, -6.75652, 0.266523 --0.707396, -6.93184, 0.179757 --3.25349, -8.77102, 0.0659383 --0.525646, -6.76614, 0.226724 --0.491526, -6.74813, 0.251834 --0.526572, -6.76702, 0.226176 --1.35815, -7.45087, 0.124219 --0.86544, -7.07301, 0.159248 --0.48281, -6.74827, 0.252817 --0.6204, -6.85407, 0.195579 --0.554418, -6.8188, 0.298871 --0.46561, -6.75064, 0.241021 --0.517412, -6.77362, 0.27897 --0.612096, -6.86239, 0.193616 --0.497092, -6.75333, 0.237271 --0.5257, -6.7869, 0.216271 --0.840915, -7.05412, 0.161614 --0.594514, -6.84724, 0.197255 --1.84122, -7.82605, 0.101515 --1.21308, -7.35217, 0.131738 --0.768069, -7.03359, 0.351334 --0.499136, -6.78372, 0.284346 --0.513648, -6.77613, 0.221174 --2.14166, -8.58841, 0.521606 --1.53739, -7.87901, 0.460369 --0.518204, -6.77441, 0.279423 --0.729072, -6.98282, 0.341393 --0.543357, -6.78293, 0.21798 --0.596284, -6.85992, 0.19419 --2.32918, -8.14014, 0.0871861 --0.50707, -6.74821, 0.252455 --0.48508, -6.75027, 0.241684 --0.65662, -6.90037, 0.185569 --1.75844, -8.10041, 0.481188 --1.57514, -7.90114, 0.462537 --0.630616, -6.87826, 0.190091 --0.631733, -6.89008, 0.320212 --1.31926, -7.62592, 0.433926 --3.24212, -8.72042, 0.0673692 --3.04647, -9.65622, 0.592886 --0.544474, -6.81713, 0.205554 --0.513995, -6.7787, 0.281777 --0.483783, -6.76899, 0.27616 --0.926433, -7.11948, 0.15378 --1.51558, -7.54581, 0.117703 --0.492148, -6.74869, 0.245435 --0.565758, -6.84832, 0.308557 --0.646971, -6.90592, 0.324203 --1.1636, -7.46057, 0.414613 --0.741429, -6.9963, 0.344121 --0.522287, -6.78687, 0.285869 --0.688708, -6.94958, 0.33434 --2.5322, -8.25487, 0.0826858 --0.807762, -7.01909, 0.166263 --0.987197, -7.27085, 0.389625 --1.14502, -7.29402, 0.136597 --0.624961, -6.89011, 0.32022 --1.69001, -7.6899, 0.108886 --0.491246, -6.75647, 0.266477 --0.512671, -6.79049, 0.214801 --0.543214, -6.79567, 0.212798 --1.43637, -7.51492, 0.119755 --1.27218, -7.37435, 0.129974 --0.476615, -6.76212, 0.271374 --0.601094, -6.84537, 0.307657 --0.538961, -6.79182, 0.214277 --0.486793, -6.77187, 0.27794 --0.6204, -6.85407, 0.195579 --1.05433, -7.22486, 0.142879 --0.562546, -6.81307, 0.206819 --1.16502, -7.46768, 0.415485 --1.09664, -7.3905, 0.405795 --0.618613, -6.8765, 0.316621 --0.707422, -6.9394, 0.178451 --2.33646, -8.12816, 0.0876762 --0.497599, -6.77776, 0.220371 --2.9931, -8.60661, 0.0707378 --0.824186, -7.08734, 0.361008 --0.48888, -6.77037, 0.224214 --1.09354, -7.38676, 0.405313 --0.493989, -6.75838, 0.232301 --1.4966, -7.57138, 0.116051 --2.20834, -8.08546, 0.0894555 --0.682673, -6.96411, 0.337485 --0.689758, -6.95068, 0.334582 --0.46561, -6.75064, 0.241021 --1.42623, -7.51786, 0.119556 --3.77631, -10.6259, 0.644501 --0.94773, -7.13722, 0.151811 --1.02073, -7.19054, 0.146232 --0.917843, -7.20364, 0.379783 --0.561037, -6.83089, 0.201553 --3.15573, -8.70974, 0.0676761 --0.566382, -6.83079, 0.302998 --0.584803, -6.8505, 0.196446 --1.09083, -7.25446, 0.140118 --1.86575, -7.78312, 0.103751 --0.712181, -6.99373, 0.343608 --0.702106, -6.95352, 0.335203 --0.527966, -6.81153, 0.296207 --0.611076, -6.86152, 0.193819 --0.48888, -6.77037, 0.224214 --0.883681, -7.08622, 0.157644 --2.68615, -8.40763, 0.0771835 --0.508929, -6.75003, 0.242133 --0.484429, -6.74986, 0.25763 --0.693108, -6.93112, 0.179884 --2.25431, -8.7204, 0.53152 --0.903186, -7.10189, 0.155794 --0.578196, -6.82704, 0.202632 --0.648358, -6.90736, 0.324558 --0.553977, -6.81033, 0.295756 --0.622435, -6.86798, 0.314278 --0.636422, -6.86857, 0.192213 --1.38986, -7.45798, 0.123709 --0.735528, -7.01727, 0.348234 --0.553217, -6.79219, 0.21413 --0.4848, -6.75001, 0.242167 --0.859566, -7.06325, 0.160459 --2.33646, -8.12816, 0.0876762 --1.68709, -8.02267, 0.474087 --0.731526, -6.95304, 0.17617 --0.566382, -6.83079, 0.302998 --0.515284, -6.75644, 0.26645 --1.11991, -7.42102, 0.409689 --0.904833, -7.17717, 0.375724 --0.768282, -6.99081, 0.170298 --0.601813, -6.86656, 0.31388 --0.674386, -6.91112, 0.183511 --1.86364, -8.29499, 0.498095 --0.746663, -7.00202, 0.345258 --0.52476, -6.78931, 0.287011 --1.35894, -7.67951, 0.439806 --0.642469, -6.89751, 0.186133 --0.588116, -6.87024, 0.314908 --0.493281, -6.7741, 0.2222 --5.77772, -10.1268, 0.0384689 --1.98399, -8.38571, 0.505599 --0.491444, -6.75607, 0.234371 --1.53164, -7.87255, 0.459733 --0.509143, -6.75024, 0.241738 --0.914221, -7.18769, 0.377351 --1.8072, -7.80142, 0.102788 --0.502568, -6.75894, 0.268767 --1.05556, -7.34612, 0.399976 --1.87754, -7.82045, 0.101802 --0.532395, -6.77384, 0.279092 --2.21086, -8.00772, 0.0928327 --1.30318, -7.41519, 0.126842 --0.484876, -6.75029, 0.25849 --0.495272, -6.75163, 0.23949 --0.509143, -6.75024, 0.241738 --0.593315, -6.84045, 0.198986 --1.26699, -7.5702, 0.427628 --0.571943, -6.83991, 0.199129 --0.49457, -6.75891, 0.231863 --2.66193, -8.39168, 0.0777342 --1.37922, -7.70208, 0.442233 --0.787345, -7.04665, 0.353757 --0.472774, -6.75668, 0.233793 --0.785274, -7.00503, 0.168235 --0.55581, -6.82019, 0.299366 --0.903186, -7.10189, 0.155794 --0.601544, -6.8589, 0.311694 --1.70751, -7.72863, 0.106704 --0.937678, -7.22416, 0.382855 --0.562623, -6.8322, 0.201191 --0.462555, -6.7482, 0.247675 --0.895368, -7.09643, 0.156433 --0.893602, -7.16869, 0.3744 --0.731266, -7.01297, 0.347403 --0.955097, -7.2372, 0.384775 --0.483597, -6.74892, 0.244725 --0.841173, -7.05137, 0.161966 --0.491646, -6.74825, 0.252663 --2.34596, -8.15128, 0.086734 --0.664029, -6.91243, 0.325789 --0.491526, -6.74813, 0.251834 --0.998382, -7.28313, 0.391359 --1.19162, -7.4902, 0.418219 --0.466697, -6.75155, 0.239597 --0.668284, -6.90587, 0.184507 --0.509523, -6.75061, 0.24108 --1.72267, -8.06141, 0.477652 --0.564225, -6.80247, 0.210339 --1.09627, -7.25885, 0.139717 --0.975118, -7.15636, 0.149752 --0.996021, -7.17602, 0.147705 --0.490645, -6.77557, 0.280074 --0.507495, -6.74864, 0.254398 --0.542101, -6.7838, 0.284387 --0.494434, -6.75957, 0.269306 --0.500488, -6.76427, 0.227928 --1.07361, -7.22982, 0.142408 --0.469785, -6.75557, 0.265565 --0.492962, -6.75745, 0.233103 --1.09159, -7.2431, 0.141164 --1.09827, -7.24802, 0.140708 --0.736029, -6.99953, 0.344765 --1.13512, -7.28357, 0.13751 --1.09159, -7.2431, 0.141164 --0.886665, -7.08865, 0.157353 --0.627558, -6.87565, 0.190654 --0.65662, -6.90037, 0.185569 --1.36749, -7.44219, 0.124848 --0.492333, -6.74892, 0.255323 --0.507198, -6.76273, 0.228978 --0.569441, -6.82604, 0.301397 --4.3007, -9.39725, 0.0510335 --2.60737, -9.03862, 0.553995 --0.533379, -6.7735, 0.222517 --0.586765, -6.83028, 0.30283 --1.49377, -7.55731, 0.116955 --0.570682, -6.83511, 0.304415 --1.1114, -7.40554, 0.407725 --0.524171, -6.78554, 0.216847 --2.11067, -7.94339, 0.0957734 --0.543132, -6.78486, 0.284908 --1.0793, -7.37456, 0.403727 --0.612504, -6.84689, 0.197342 --0.555207, -6.81158, 0.296226 --1.2903, -7.59502, 0.430458 --2.7505, -8.34331, 0.0794368 --0.688123, -6.92693, 0.180622 --0.617243, -6.8512, 0.196275 --1.86217, -7.80986, 0.102349 --1.52053, -7.86008, 0.458498 --0.490645, -6.77557, 0.280074 --0.587297, -6.82382, 0.203559 --0.643647, -6.88455, 0.188761 --0.647197, -6.91287, 0.325896 --0.524481, -6.80816, 0.294923 --0.612504, -6.84689, 0.197342 --0.859048, -7.14308, 0.370324 --0.599894, -6.84411, 0.307266 --0.649307, -6.91504, 0.326417 --1.64438, -7.68204, 0.109338 --0.516097, -6.75726, 0.267244 --0.49319, -6.75766, 0.232921 --0.523275, -6.78474, 0.21719 --2.5322, -8.25487, 0.0826858 --2.66193, -8.39168, 0.0777342 --0.544488, -6.78626, 0.285581 --0.507606, -6.74875, 0.254778 --3.37296, -10.0441, 0.614736 --0.463059, -6.74857, 0.245871 --0.992746, -7.17345, 0.147969 --0.850759, -7.12567, 0.367484 --1.11991, -7.42102, 0.409689 --0.509146, -6.77208, 0.22327 --0.591705, -6.85632, 0.310942 --0.584254, -6.84878, 0.308699 --0.634331, -6.88143, 0.189417 --1.41469, -7.74162, 0.44642 --2.32003, -8.11741, 0.0881192 --1.04787, -7.33763, 0.39884 --0.59032, -6.8378, 0.199682 --0.490477, -6.75519, 0.235238 --0.59564, -6.87765, 0.316931 --0.534984, -6.79118, 0.287867 --0.518412, -6.77307, 0.22274 --0.569896, -6.82585, 0.202971 --0.528282, -6.7892, 0.215323 --3.15573, -8.70974, 0.0676761 --0.794913, -7.05499, 0.355278 --0.504239, -6.76058, 0.270153 --1.2414, -7.36823, 0.130456 --0.521371, -6.76205, 0.229463 --0.79807, -7.08071, 0.359856 --2.52657, -8.3018, 0.080939 --0.597499, -6.86218, 0.31264 --0.784977, -6.99948, 0.169031 +# stanc_version = stanc3 v2.37.0 +# stancflags = --filename-in-msg=bernoulli.stan +lp_approx__,lp__,path__,theta +-0.53011422, -6.7643572, 1, 0.22787259 +-1.2434904, -7.3786216, 1, 0.12963963 +-0.51344929, -6.7480341, 1, 0.25062316 +-0.51361354, -6.748198, 1, 0.24765788 +-0.72916307, -6.9788483, 1, 0.34057608 +-0.51580698, -6.7504097, 1, 0.25870416 +-0.57690954, -6.8139559, 1, 0.2971113 +-0.57690954, -6.8139559, 1, 0.2971113 +-1.4648903, -7.5519385, 1, 0.11730339 +-0.86935299, -7.1354121, 1, 0.36908011 +-0.75451965, -7.0068884, 1, 0.34621733 +-0.59567454, -6.8265018, 1, 0.20278586 +-0.57606155, -6.8081515, 1, 0.20840924 +-0.52479256, -6.7595654, 1, 0.26930582 +-0.53471281, -6.7697789, 1, 0.27665868 +-0.72685311, -6.9763007, 1, 0.34004835 +-0.52468536, -6.7594555, 1, 0.26921229 +-0.52468536, -6.7594555, 1, 0.26921229 +-1.332684, -7.4491742, 1, 0.12434209 +-0.63901287, -6.8664976, 1, 0.19267826 +-2.4233653, -8.2450944, 1, 0.083056233 +-0.57877306, -6.8159278, 1, 0.2978347 +-0.64874793, -6.8909131, 1, 0.32042574 +-0.51346801, -6.7480529, 1, 0.25098746 +-0.51631848, -6.7508787, 1, 0.24063141 +-0.51624157, -6.7508028, 1, 0.24075568 +-0.51624157, -6.7508028, 1, 0.24075568 +-0.57554061, -6.8076617, 1, 0.20857151 +-0.732267, -6.9822733, 1, 0.34128139 +-0.732267, -6.9822733, 1, 0.34128139 +-0.60910313, -6.8389711, 1, 0.1993739 +-0.65697452, -6.882879, 1, 0.18911127 +-0.76705444, -6.9812235, 1, 0.17173254 +-1.2438858, -7.5673845, 1, 0.42730441 +-0.64162189, -6.8688837, 1, 0.19214175 +-0.55701363, -6.7901519, 1, 0.21493736 +-1.2880021, -7.6192411, 1, 0.43318155 +-3.7299042, -9.0839971, 1, 0.0578979 +-0.72020598, -6.9689765, 1, 0.33851586 +-0.54333586, -6.7787212, 1, 0.28179117 +-1.9941611, -7.9447447, 1, 0.09570997 +-1.9941611, -7.9447447, 1, 0.09570997 +-0.60447919, -6.8432743, 1, 0.30700753 +-0.51352354, -6.7481083, 1, 0.24835804 +-0.65204401, -6.8783928, 1, 0.19006205 +-0.56127124, -6.7974707, 1, 0.29061121 +-1.5676225, -7.6304039, 1, 0.11238652 +-0.55055607, -6.7862467, 1, 0.28557484 +-1.3980469, -7.5002417, 1, 0.12075215 +-0.76092398, -6.9758295, 1, 0.1725553 +-0.65035304, -6.8926518, 1, 0.32087248 +-0.65555408, -6.8815874, 1, 0.18938311 +-1.2600523, -7.3918004, 1, 0.12861789 +-1.6734974, -7.7100849, 1, 0.10773986 +-0.55069057, -6.7863872, 1, 0.28564192 +-1.0017379, -7.2861678, 1, 0.391785 +-0.58316488, -6.8148176, 1, 0.20626926 +-1.3400604, -7.4549636, 1, 0.12392534 +-0.80576487, -7.0150812, 1, 0.16681842 +-0.61658409, -6.8458868, 1, 0.19759423 +-0.51370921, -6.7482947, 1, 0.25292842 +-0.51370921, -6.7482947, 1, 0.25292842 +-0.51370921, -6.7482947, 1, 0.25292842 +-0.64248393, -6.8696716, 1, 0.19196593 +-0.60525821, -6.8354082, 1, 0.20032054 +-0.573526, -6.8057663, 1, 0.20920645 +-0.65385393, -6.8800405, 1, 0.18971067 +-1.5073359, -7.8793597, 1, 0.46040359 +-0.56439728, -6.7971519, 1, 0.2122463 +-5.8731604, -10.286424, 1, 0.036220511 +-0.52840665, -6.7627008, 1, 0.22900083 +-1.7556965, -7.7711627, 1, 0.10438751 +-0.88810559, -7.1566128, 1, 0.37249262 +-1.0435927, -7.3343145, 1, 0.39839403 +-0.56766254, -6.8002381, 1, 0.21112615 +-0.56766254, -6.8002381, 1, 0.21112615 +-0.89176461, -7.1607558, 1, 0.37314991 +-0.91361565, -7.1855391, 1, 0.37702003 +-0.70449912, -6.9517094, 1, 0.33480783 +-0.70449912, -6.9517094, 1, 0.33480783 +-0.75854337, -6.9737325, 1, 0.17287839 +-0.67985848, -6.9036018, 1, 0.18494225 +-1.2118217, -7.5298041, 1, 0.42293388 +-1.4573789, -7.546155, 1, 0.11768051 +-0.5945442, -6.8326747, 1, 0.30362049 +-0.79796272, -7.0082845, 1, 0.16777245 +-1.4367359, -7.7952443, 1, 0.45196986 +-0.54199587, -6.775814, 1, 0.22132948 +-4.1358736, -9.3260703, 1, 0.052502332 +-4.1358736, -9.3260703, 1, 0.052502332 +-4.1358736, -9.3260703, 1, 0.052502332 +-1.9369465, -8.3974597, 1, 0.50655481 +-1.7468992, -7.7646576, 1, 0.1047365 +-0.54405351, -6.7794677, 1, 0.28218494 +-0.51696672, -6.7515841, 1, 0.26064867 +-0.73853187, -6.9560499, 1, 0.17567866 +-0.65835347, -6.8841323, 1, 0.18884894 +-1.0483696, -7.2204542, 1, 0.1432998 +-2.4112901, -8.236838, 1, 0.083370943 +-0.53267169, -6.766833, 1, 0.22629253 +-2.6778968, -8.4167393, 1, 0.076871586 +-0.56121146, -6.7941353, 1, 0.21337873 +-3.3357834, -10.123235, 1, 0.61898305 +-0.62580579, -6.8661458, 1, 0.31376402 +-0.6811039, -6.904725, 1, 0.18472583 +-0.69641727, -6.9184996, 1, 0.18214299 +-0.78154007, -7.0369131, 1, 0.35195518 +-0.86082501, -7.0626738, 1, 0.1605313 +-2.9247858, -8.5791149, 1, 0.071584449 +-0.51369644, -6.7482806, 1, 0.24716295 +-0.52387455, -6.7586251, 1, 0.26849067 +-0.52108852, -6.7555672, 1, 0.23485803 +-0.59075593, -6.8219159, 1, 0.20411632 +-2.9031539, -8.5650415, 1, 0.072023086 +-1.3895312, -7.4936178, 1, 0.12120712 +-0.57521798, -6.8073583, 1, 0.2086724 +-0.65171257, -6.894125, 1, 0.32124909 +-1.1315792, -7.2885845, 1, 0.13707013 +-0.51364677, -6.7482311, 1, 0.24744778 +-0.67986446, -6.9247462, 1, 0.32871507 +-1.1267549, -7.2846631, 1, 0.13741328 +-1.1267549, -7.2846631, 1, 0.13741328 +-1.1267549, -7.2846631, 1, 0.13741328 +-0.63511471, -6.8761759, 1, 0.31653311 +-1.5348002, -7.6054612, 1, 0.11391059 +-0.81282692, -7.0718525, 1, 0.35829809 +-1.216605, -7.5354042, 1, 0.42359138 +-0.51561152, -6.7502121, 1, 0.25833357 +-0.97888863, -7.2599759, 1, 0.38807443 +-0.88090444, -7.0798751, 1, 0.15840901 +-0.88090444, -7.0798751, 1, 0.15840901 +-1.5301025, -7.6018816, 1, 0.11413219 +-1.0320376, -7.321001, 1, 0.39659256 +-0.72142303, -6.9703168, 1, 0.33879802 +-0.72142303, -6.9703168, 1, 0.33879802 +-0.52605154, -6.7608564, 1, 0.27037426 +-0.52605154, -6.7608564, 1, 0.27037426 +-0.76170372, -7.0148571, 1, 0.34776866 +-0.60299797, -6.8416917, 1, 0.3065134 +-0.51381285, -6.7483965, 1, 0.24658813 +-3.3912972, -8.8759444, 1, 0.063093875 +-0.97960432, -7.1633208, 1, 0.14902035 +-0.63004275, -6.8707076, 1, 0.31503643 +-0.90488775, -7.1003174, 1, 0.15597729 +-0.87933077, -7.1466856, 1, 0.37090511 +-0.5298863, -6.7641363, 1, 0.22801951 +-0.5298863, -6.7641363, 1, 0.22801951 +-1.3838444, -7.4891896, 1, 0.121513 +-2.9573938, -8.6002752, 1, 0.070931563 +-0.81430433, -7.0225047, 1, 0.1657936 +-1.8957738, -7.873754, 1, 0.099118377 +-1.0529482, -7.3451051, 1, 0.39984023 +-0.74732936, -6.9989234, 1, 0.34464468 +-2.0143282, -8.4917023, 1, 0.51409353 +-0.83134972, -7.0926207, 1, 0.36191999 +-0.80472958, -7.0627926, 1, 0.3566848 +-0.64568278, -6.8875949, 1, 0.31956613 +-0.52285239, -6.7572923, 1, 0.2332423 +-0.61342353, -6.8429676, 1, 0.1983365 +-0.72248681, -6.9714885, 1, 0.33904406 +-0.9451492, -7.2214263, 1, 0.38244956 +-0.52921152, -6.7634819, 1, 0.22846094 +-0.95573467, -7.2335044, 1, 0.38423393 +-0.95573467, -7.2335044, 1, 0.38423393 +-0.90138812, -7.171662, 1, 0.3748658 +-1.457036, -7.5458909, 1, 0.11769779 +-1.7356243, -8.1534768, 1, 0.48591607 +-1.3685556, -7.4772649, 1, 0.1223437 +-1.4794683, -7.5631446, 1, 0.11657864 +-0.59794687, -6.828617, 1, 0.20218679 +-0.94253125, -7.2184416, 1, 0.38200539 +-0.94253125, -7.2184416, 1, 0.38200539 +-0.72092371, -6.9404073, 1, 0.17827875 +-0.66921122, -6.9131335, 1, 0.32595982 +-0.96112841, -7.2396646, 1, 0.38513611 +-0.51350684, -6.7480918, 1, 0.25148138 +-0.57914827, -6.816325, 1, 0.29797922 +-0.57914827, -6.816325, 1, 0.29797922 +-1.6622919, -7.7017065, 1, 0.10821337 +-0.62905249, -6.8573667, 1, 0.19479059 +-0.51731166, -6.7518582, 1, 0.23915863 +-1.4310004, -7.5257931, 1, 0.11902542 +-1.0632581, -7.2327231, 1, 0.14213384 +-0.57710247, -6.81416, 1, 0.29718664 +-0.67938488, -6.9031745, 1, 0.18502482 +-1.1944802, -7.3394063, 1, 0.13277525 +-1.2379289, -7.5603956, 1, 0.42649893 +-0.51531777, -6.7498896, 1, 0.24241224 +-0.52221062, -6.7566651, 1, 0.23381019 +-0.5895763, -6.8273886, 1, 0.30185733 +-3.9184128, -9.1973581, 1, 0.055290606 +-3.9184128, -9.1973581, 1, 0.055290606 +-0.88772274, -7.1561794, 1, 0.37242369 +-0.58397834, -6.8214438, 1, 0.29980749 +-0.63815666, -6.865714, 1, 0.19285579 +-0.54271536, -6.778076, 1, 0.28144715 +-0.56743725, -6.8000253, 1, 0.2112022 +-0.52619836, -6.7605544, 1, 0.23056664 +-0.52619836, -6.7605544, 1, 0.23056664 +-0.51397825, -6.7485611, 1, 0.24590963 +-0.51712979, -6.751679, 1, 0.23941234 +-1.7015109, -8.1123283, 1, 0.48225765 +-1.9401713, -7.9058946, 1, 0.097552599 +-1.9401713, -7.9058946, 1, 0.097552599 +-0.89068566, -7.1595339, 1, 0.37295638 +-0.89068566, -7.1595339, 1, 0.37295638 +-1.0042694, -7.2890737, 1, 0.39219148 +-0.53916396, -6.7730934, 1, 0.22272954 +-0.55125071, -6.7846666, 1, 0.21721981 +-0.9209097, -7.1938276, 1, 0.37829172 +-0.57095007, -6.8033398, 1, 0.21003613 +-1.6199319, -7.6699175, 1, 0.11004148 +-1.6199319, -7.6699175, 1, 0.11004148 +-0.51741183, -6.7520356, 1, 0.26130959 +-0.5663097, -6.8027693, 1, 0.29279873 +-1.268175, -7.5959141, 1, 0.43055905 +-0.59798917, -6.8363459, 1, 0.30481489 +-0.7992391, -7.0566563, 1, 0.35557998 +-0.52449297, -6.7588933, 1, 0.23187695 +-0.52504543, -6.7598246, 1, 0.26952478 +-1.1442733, -7.2988867, 1, 0.13617692 +-0.5900474, -6.8212544, 1, 0.20431196 +-1.0704193, -7.2386119, 1, 0.14158143 +-1.2365551, -7.3730921, 1, 0.130073 +-0.72464967, -6.9437241, 1, 0.17771709 +-0.96323771, -7.2420747, 1, 0.38548766 +-0.98435877, -7.1672965, 1, 0.14860561 +-0.5668469, -6.8033349, 1, 0.29302625 +-2.2738784, -8.809344, 1, 0.53799571 +-2.2738784, -8.809344, 1, 0.53799571 +-1.6950696, -8.1045655, 1, 0.4815612 +-0.55622858, -6.7894058, 1, 0.215238 +-0.55622858, -6.7894058, 1, 0.215238 +-1.3843929, -7.4896168, 1, 0.12148343 +-0.52764539, -6.7624932, 1, 0.27165656 +-1.676465, -7.7123017, 1, 0.10761515 +-0.60213617, -6.8407713, 1, 0.30622424 +-2.0067418, -7.9537611, 1, 0.095289886 +-0.81348759, -7.0217954, 1, 0.16589077 +-1.2609468, -7.3925112, 1, 0.12856322 +-0.62395347, -6.8641532, 1, 0.31320112 +-0.83688762, -7.0425203, 2, 0.16311456 +-0.71164002, -6.9329411, 2, 0.1795647 +-2.3912003, -8.2202119, 2, 0.084009803 +-0.5121319, -6.7482338, 2, 0.25258024 +-1.6625218, -7.7004037, 2, 0.1082873 +-2.9065446, -8.5635109, 2, 0.072071006 +-0.54037421, -6.7756307, 2, 0.22142144 +-1.545021, -7.9224679, 2, 0.46460601 +-1.0678069, -7.2363262, 2, 0.14179529 +-0.66773058, -6.8935851, 2, 0.18691409 +-1.0454454, -7.3363375, 2, 0.3986661 +-0.77364943, -7.0289368, 2, 0.35045867 +-0.91089009, -7.1056774, 2, 0.15535497 +-2.1510108, -8.6544858, 2, 0.52661596 +-0.82983285, -7.036442, 2, 0.16391564 +-6.2414336, -10.468602, 2, 0.033834521 +-0.71456966, -6.9637681, 2, 0.33741186 +-1.3758407, -7.482091, 2, 0.12200627 +-0.76495959, -6.9800407, 2, 0.17191194 +-0.95099775, -7.2283122, 2, 0.38346939 +-0.68946992, -6.9363139, 2, 0.33137791 +-0.92217909, -7.1152195, 2, 0.15426199 +-1.1995591, -7.3430297, 2, 0.1324793 +-0.55369947, -6.7883229, 2, 0.21567963 +-2.0037563, -7.9494697, 2, 0.095489481 +-0.51449011, -6.7506046, 2, 0.25905504 +-0.5327035, -6.7682688, 2, 0.22542597 +-0.5327035, -6.7682688, 2, 0.22542597 +-0.85505897, -7.0581291, 2, 0.16110441 +-0.5205241, -6.7567237, 2, 0.26672703 +-0.86509363, -7.06672, 2, 0.1600255 +-0.56280058, -6.7969305, 2, 0.21232811 +-1.1116137, -7.4126509, 2, 0.40862933 +-1.3644413, -7.473217, 2, 0.12262803 +-1.3805817, -7.7272744, 2, 0.44490995 +-0.51595247, -6.7520017, 2, 0.23895977 +-2.549593, -8.3276357, 2, 0.079999448 +-2.549593, -8.3276357, 2, 0.079999448 +-1.0019512, -7.2864513, 2, 0.3918247 +-1.6414528, -8.0377484, 2, 0.47548107 +-0.62110737, -6.8511503, 2, 0.19628682 +-0.68725881, -6.9111561, 2, 0.18350395 +-3.1956687, -8.7487842, 2, 0.066562189 +-3.1956687, -8.7487842, 2, 0.066562189 +-3.1693605, -8.7321264, 2, 0.06703452 +-1.563981, -7.9450895, 2, 0.46678069 +-1.563981, -7.9450895, 2, 0.46678069 +-0.51401234, -6.7500928, 2, 0.24201315 +-0.78204421, -7.038254, 2, 0.3522049 +-0.78204421, -7.038254, 2, 0.3522049 +-0.53575368, -6.7712016, 2, 0.22375111 +-0.51487859, -6.7509461, 2, 0.24052253 +-0.54214463, -6.7773237, 2, 0.22058381 +-0.51641729, -6.7525525, 2, 0.26202291 +-1.9791239, -8.4452342, 2, 0.51040429 +-1.9791239, -8.4452342, 2, 0.51040429 +-1.0235899, -7.1999275, 2, 0.14529796 +-0.56820755, -6.8020231, 2, 0.21049466 +-0.51480847, -6.7509259, 2, 0.25960618 +-0.57792086, -6.8164206, 2, 0.29801393 +-0.57792086, -6.8164206, 2, 0.29801393 +-1.0907933, -7.3885858, 2, 0.405548 +-1.0907933, -7.3885858, 2, 0.405548 +-0.59367048, -6.8258171, 2, 0.20298169 +-1.2150124, -7.3553829, 2, 0.13148005 +-0.57824938, -6.8114424, 2, 0.20733731 +-1.2454699, -7.3796357, 2, 0.12956046 +-1.1652473, -7.4748525, 2, 0.4163599 +-0.74163653, -6.9935339, 2, 0.34356753 +-0.51239043, -6.7484927, 2, 0.25384925 +-0.87270237, -7.0732206, 2, 0.15922145 +-1.638857, -7.682717, 2, 0.10929932 +-1.8526191, -8.2919546, 2, 0.49783972 +-1.3798101, -7.4851773, 2, 0.12179136 +-2.2715744, -8.8018352, 2, 0.53745512 +-0.59125897, -6.8235761, 2, 0.20362949 +-1.1485459, -7.4554515, 2, 0.41398325 +-1.1485459, -7.4554515, 2, 0.41398325 +-3.0423832, -8.6511695, 2, 0.069393069 +-1.0193592, -7.1964284, 2, 0.14564473 +-0.51213028, -6.7482312, 2, 0.24744744 +-0.93920051, -7.2149005, 2, 0.38147674 +-2.2042687, -8.7195224, 2, 0.53145529 +-1.9868565, -8.4546246, 2, 0.51115413 +-0.65524608, -6.8991323, 2, 0.32251614 +-0.69619023, -6.9191556, 2, 0.18202311 +-0.51681493, -6.7528479, 2, 0.23785532 +-2.4746854, -8.2770544, 2, 0.081853613 +-0.83210434, -7.0940835, 2, 0.36217127 +-0.83210434, -7.0940835, 2, 0.36217127 +-0.87171375, -7.0723766, 2, 0.15932525 +-0.51247037, -6.7485728, 2, 0.25416497 +-0.93227285, -7.2070338, 2, 0.38029564 +-1.1578481, -7.3095209, 2, 0.1352673 +-1.7426983, -7.7599097, 2, 0.10499239 +-1.6111372, -7.6619265, 2, 0.11050909 +-2.3772502, -8.2106644, 2, 0.084379798 +-0.5254374, -6.7617417, 2, 0.27107699 +-0.74677331, -6.9992006, 2, 0.3446998 +-1.4757179, -7.5591847, 2, 0.11683385 +-0.77745637, -6.9909793, 2, 0.17027365 +-0.53479286, -6.7713598, 2, 0.27763093 +-0.71884225, -6.968456, 2, 0.33840608 +-0.86950642, -7.1360763, 2, 0.3691883 +-0.63211298, -6.8741824, 2, 0.31599099 +-0.63211298, -6.8741824, 2, 0.31599099 +-1.1118058, -7.2722437, 2, 0.13851187 +-1.3914211, -7.4941944, 2, 0.12116739 +-0.51494967, -6.7510161, 2, 0.24041087 +-0.51673054, -6.7528698, 2, 0.26244108 +-0.57071631, -6.804381, 2, 0.20967773 +-0.82371586, -7.0311632, 2, 0.16462005 +-0.82371586, -7.0311632, 2, 0.16462005 +-0.77837338, -6.9917805, 2, 0.17015545 +-0.77837338, -6.9917805, 2, 0.17015545 +-0.84678037, -7.1105336, 2, 0.36496427 +-0.55974845, -6.797313, 2, 0.29054445 +-1.6326497, -8.0272019, 2, 0.47450696 +-0.76652375, -6.9814118, 2, 0.17170402 +-0.68858431, -6.9123447, 2, 0.18328124 +-0.99265577, -7.2758199, 2, 0.39032924 +-0.99265577, -7.2758199, 2, 0.39032924 +-0.51508193, -6.751202, 2, 0.26005631 +-2.4066119, -8.230743, 2, 0.083604343 +-0.5120777, -6.7481789, 2, 0.24778795 +-0.62027171, -6.8503829, 2, 0.19647503 +-1.3201216, -7.4385647, 2, 0.12511256 +-0.55788772, -6.7922897, 2, 0.21409141 +-0.65705087, -6.9010852, 2, 0.32300507 +-8.6423146, -11.618306, 2, 0.022253545 +-8.6423146, -11.618306, 2, 0.022253545 +-0.75121131, -6.9679639, 2, 0.17377675 +-2.4927158, -8.2892654, 2, 0.08140056 +-2.4927158, -8.2892654, 2, 0.08140056 +-2.4927158, -8.2892654, 2, 0.08140056 +-0.51406797, -6.750179, 2, 0.25826988 +-0.57761446, -6.8160972, 2, 0.29789637 +-0.52473718, -6.761025, 2, 0.27050979 +-0.70714794, -6.9289396, 2, 0.18026671 +-0.70714794, -6.9289396, 2, 0.18026671 +-2.0947941, -8.585935, 2, 0.52141615 +-2.0947941, -8.585935, 2, 0.52141615 +-2.0186852, -7.9601267, 2, 0.094994984 +-0.81682744, -7.0769988, 2, 0.35920526 +-1.0717456, -7.2395535, 2, 0.14149352 +-0.6680823, -6.8939026, 2, 0.18685039 +-0.68603933, -6.9100621, 2, 0.18370978 +-0.68603933, -6.9100621, 2, 0.18370978 +-0.56048512, -6.7980845, 2, 0.29087012 +-0.51191971, -6.7480218, 2, 0.24996755 +-1.3634559, -7.4724492, 2, 0.12268211 +-0.87457757, -7.1417872, 2, 0.37011508 +-0.52230607, -6.7582093, 2, 0.23244661 +-1.4229492, -7.5185983, 2, 0.11950716 +-0.69777801, -6.9453848, 2, 0.33341373 +-0.59882098, -6.8305954, 2, 0.20163433 +-0.59882098, -6.8305954, 2, 0.20163433 +-0.51538169, -6.7514409, 2, 0.23975937 +-0.61491243, -6.8557372, 2, 0.31077247 +-2.0159507, -7.9581761, 2, 0.095085204 +-2.0159507, -7.9581761, 2, 0.095085204 +-1.4513474, -7.811045, 2, 0.45357877 +-1.0542872, -7.2252299, 2, 0.14284349 +-0.51693415, -6.7530761, 2, 0.26270584 +-0.81886432, -7.0269709, 2, 0.16518541 +-0.57646909, -6.8097761, 2, 0.20787618 +-0.51347305, -6.7495606, 2, 0.24310838 +-0.51347305, -6.7495606, 2, 0.24310838 +-0.62933744, -6.8586942, 2, 0.19447737 +-0.51575465, -6.7518074, 2, 0.23922987 +-0.51575465, -6.7518074, 2, 0.23922987 +-3.2116266, -8.7588694, 2, 0.066278313 +-3.2116266, -8.7588694, 2, 0.066278313 +-0.92029314, -7.1934461, 2, 0.37823342 +-0.93644934, -7.2117756, 2, 0.38100867 +-1.6698537, -7.7058719, 2, 0.10797753 +-0.78749926, -7.0443157, 2, 0.35332719 +-0.6679831, -6.893813, 2, 0.18686835 +-0.58592555, -6.8186109, 2, 0.20510381 +-0.51381226, -6.7499214, 2, 0.25775702 +-1.2552644, -7.5798815, 2, 0.4287366 +-0.65146637, -6.8950451, 2, 0.3214834 +-0.65146637, -6.8950451, 2, 0.3214834 +-0.65195183, -6.8955698, 2, 0.32161672 +-0.93764214, -7.1282519, 2, 0.15279896 +-0.58499314, -6.8177415, 2, 0.20536778 +-0.58499314, -6.8177415, 2, 0.20536778 +-1.2714692, -7.5988672, 2, 0.43089294 +-1.00145, -7.1815838, 2, 0.14713668 +-1.0488722, -7.2207775, 2, 0.14326882 +-0.75980992, -6.9755224, 2, 0.17260251 +-0.75980992, -6.9755224, 2, 0.17260251 +-1.3456638, -7.6860777, 2, 0.44051482 +-0.64810868, -6.8914177, 2, 0.32055567 +-1.1455376, -7.45196, 2, 0.4135523 +-0.71530513, -6.9362019, 2, 0.17899931 +-1.0248702, -7.31271, 2, 0.39546084 +-1.5507009, -7.6163189, 2, 0.11324286 +-0.8284414, -7.0352419, 2, 0.16407506 +-1.4767037, -7.5599399, 2, 0.1167851 +-0.52831859, -6.7646957, 2, 0.27327601 +-2.4364945, -9.0040394, 2, 0.55164214 +-2.4364945, -9.0040394, 2, 0.55164214 +-1.2080133, -7.5246559, 2, 0.42232747 +-1.0165206, -7.3031362, 2, 0.39414439 +-2.2877701, -8.1490808, 2, 0.086823014 +-1.5146381, -7.5889178, 2, 0.11494099 +-2.525848, -8.3116444, 2, 0.080579278 +-1.0269718, -7.3151211, 2, 0.39579074 +-1.0269718, -7.3151211, 2, 0.39579074 +-0.52835231, -6.7647303, 2, 0.27330061 +-0.70680068, -6.9552545, 2, 0.33558058 +-2.2168605, -8.0998466, 2, 0.088850008 +-0.90920317, -7.1808859, 2, 0.37630124 +-0.81219486, -7.0211993, 2, 0.16597254 +-2.2988435, -8.1567345, 2, 0.086513905 +-0.65177089, -6.8953743, 2, 0.32156706 +-0.55912663, -6.796662, 2, 0.29026778 +-0.52712612, -6.7634721, 2, 0.27239006 +-0.81882579, -7.0269376, 2, 0.16518992 +-0.51411256, -6.7502239, 2, 0.25835619 +-1.3594025, -7.4692895, 2, 0.12290507 +-1.246497, -7.3804513, 2, 0.12949684 +-0.94141929, -7.1314288, 2, 0.15244736 +-0.57943096, -6.8125476, 2, 0.20698421 +-0.89990088, -7.1703642, 2, 0.3746627 +-0.57010272, -6.8081814, 2, 0.29493228 +-0.78888964, -7.0458615, 2, 0.35361172 +-1.114114, -7.2741199, 2, 0.13834475 +-1.3306442, -7.6683867, 2, 0.4385989 +-0.52502569, -6.7608508, 2, 0.23034253 +-1.4302811, -7.5242568, 2, 0.119128 +-1.4468734, -7.5370389, 2, 0.1182793 +-1.4468734, -7.5370389, 2, 0.1182793 +-0.92033969, -7.1934988, 2, 0.37824149 +-0.62794588, -6.8697051, 2, 0.31475872 +-0.53372351, -6.7702567, 2, 0.27695602 +-1.1778978, -7.3256584, 2, 0.13391014 +-0.55846128, -6.7959657, 2, 0.28996988 +-1.1314517, -7.2881875, 2, 0.13710479 +-0.62711582, -6.8566602, 2, 0.19495815 +-0.54634096, -6.7813281, 2, 0.21869986 +-0.54634096, -6.7813281, 2, 0.21869986 +-0.67713349, -6.9020596, 2, 0.18524089 +-0.53379727, -6.7693213, 2, 0.22481104 +-2.1269162, -8.625092, 2, 0.52439905 +-1.1182176, -7.2774535, 2, 0.13804881 +-0.53712361, -6.7737668, 2, 0.2790526 +-0.76229383, -6.9777026, 2, 0.17226826 +-0.53688342, -6.7735186, 2, 0.27890901 +-2.1383391, -8.0448681, 2, 0.091195872 +-0.52882849, -6.7652192, 2, 0.2736455 +-0.52841847, -6.7641355, 2, 0.22802004 +-0.55861055, -6.7929734, 2, 0.21382558 +-0.52325447, -6.7591314, 2, 0.23168309 +-1.4108488, -7.763059, 2, 0.44865552 +-0.55576593, -6.7902814, 2, 0.21488546 +-2.1427925, -8.0479995, 2, 0.091059835 +-0.59814999, -6.8378576, 2, 0.30529994 +-1.0096059, -7.1883506, 2, 0.14645236 +-0.65948285, -6.8861296, 2, 0.18843376 +-1.107047, -7.2683731, 2, 0.138858 +-1.9009435, -7.8755514, 2, 0.099029793 +-0.95471799, -7.2325455, 2, 0.38409301 +-2.2955358, -8.1544493, 2, 0.086606032 +-0.87632507, -7.0763117, 2, 0.15884274 +-0.58946931, -6.8286387, 2, 0.30227915 +-0.51816782, -6.7546488, 3, 0.26457143 +-0.53252222, -6.7683895, 3, 0.22535456 +-1.7601924, -8.1798392, 3, 0.48823117 +-1.2329409, -7.3695601, 3, 0.13035129 +-0.51211294, -6.7485316, 3, 0.24602261 +-0.51211294, -6.7485316, 3, 0.24602261 +-0.65816077, -6.8851371, 3, 0.18863965 +-0.51600071, -6.7524524, 3, 0.26188801 +-0.51452198, -6.7509583, 3, 0.25966014 +-0.92603695, -7.1185203, 3, 0.15388825 +-0.92603695, -7.1185203, 3, 0.15388825 +-0.97520364, -7.2559176, 3, 0.3874917 +-1.2012904, -7.5166753, 3, 0.42138364 +-1.2012904, -7.5166753, 3, 0.42138364 +-1.2012904, -7.5166753, 3, 0.42138364 +-0.74387665, -6.9961947, 3, 0.34410067 +-0.74387665, -6.9961947, 3, 0.34410067 +-0.81458734, -7.0233793, 3, 0.16567402 +-1.0672731, -7.3614182, 3, 0.40200368 +-1.7365375, -8.1513778, 3, 0.48573079 +-0.51172371, -6.7481455, 3, 0.2480371 +-0.62010844, -6.8504629, 3, 0.19645539 +-0.66148758, -6.906134, 3, 0.32425585 +-0.51186866, -6.7482909, 3, 0.25290753 +-1.8308379, -8.2650019, 3, 0.49556373 +-0.56620084, -6.80438, 3, 0.2934437 +-0.56620084, -6.80438, 3, 0.2934437 +-0.62354408, -6.865249, 3, 0.31351122 +-0.92676837, -7.1191368, 3, 0.15381868 +-0.53691011, -6.7726031, 3, 0.22299024 +-1.8405594, -7.83131, 3, 0.10124648 +-1.1949019, -7.3392051, 3, 0.13279172 +-0.52117046, -6.7577029, 3, 0.26765636 +-0.53918703, -6.7747838, 3, 0.22185068 +-2.501599, -8.2946261, 3, 0.081202773 +-2.501599, -8.2946261, 3, 0.081202773 +-1.627684, -8.0207846, 3, 0.47391225 +-3.6517158, -10.50378, 3, 0.63852179 +-0.59570908, -6.8279565, 3, 0.20237289 +-0.5139184, -6.7503145, 3, 0.24159974 +-0.54193225, -6.7774081, 3, 0.22054276 +-0.88627094, -7.0848524, 3, 0.15780818 +-0.88627094, -7.0848524, 3, 0.15780818 +-1.100441, -7.3996672, 3, 0.40697347 +-0.72690944, -6.97752, 3, 0.34030127 +-0.51560739, -6.7520546, 3, 0.26133655 +-1.0947588, -7.3931059, 3, 0.40613083 +-0.98310737, -7.1663386, 3, 0.14870529 +-1.2349846, -7.3711854, 3, 0.13022309 +-0.78369288, -7.0402488, 3, 0.35257541 +-0.54691181, -6.7842262, 3, 0.28459675 +-0.52151619, -6.7577461, 3, 0.23284367 +-0.52151619, -6.7577461, 3, 0.23284367 +-1.3820168, -7.7286914, 3, 0.44505951 +-0.67527525, -6.9005803, 3, 0.185529 +-1.5605253, -7.9405476, 3, 0.46634571 +-1.1293008, -7.2863825, 3, 0.1372626 +-0.53653258, -6.773471, 3, 0.27888138 +-0.51211273, -6.7485314, 3, 0.24602341 +-0.51211273, -6.7485314, 3, 0.24602341 +-0.52972852, -6.7656987, 3, 0.22700204 +-0.9392963, -7.2150634, 3, 0.3815011 +-1.499272, -7.8676083, 3, 0.45924433 +-0.63288178, -6.862157, 3, 0.19367036 +-0.63288178, -6.862157, 3, 0.19367036 +-0.60442548, -6.8360233, 3, 0.2001556 +-2.8862809, -8.5495553, 3, 0.072509889 +-1.5553432, -7.6195708, 3, 0.11304417 +-0.6301388, -6.8596506, 3, 0.19425307 +-1.8581343, -7.8441004, 3, 0.10059775 +-0.58606322, -6.8253188, 3, 0.30115207 +-0.53577894, -6.7715183, 3, 0.22357707 +-0.574487, -6.8081811, 3, 0.20839946 +-0.56609052, -6.8002993, 3, 0.21110429 +-1.1506305, -7.3036247, 3, 0.13577012 +-0.51324838, -6.7496753, 3, 0.25723389 +-0.51352, -6.7499219, 3, 0.24234735 +-0.92292918, -7.1158997, 3, 0.15418479 +-0.55177001, -6.7867714, 3, 0.21632362 +-0.53740818, -6.7743755, 3, 0.27940186 +-1.3773357, -7.4830701, 3, 0.12193801 +-0.60365026, -6.8439927, 3, 0.30723055 +-0.60365026, -6.8439927, 3, 0.30723055 +-0.511841, -6.7482619, 3, 0.24726701 +-1.5639036, -7.6260463, 3, 0.11265028 +-0.5637516, -6.7980975, 3, 0.21189913 +-0.93476137, -7.2099162, 3, 0.38072948 +-4.0340115, -10.97679, 3, 0.66095406 +-0.53280062, -6.7686573, 3, 0.22519703 +-0.78235091, -7.038759, 3, 0.3522988 +-4.8634033, -9.7340959, 3, 0.044714183 +-1.097349, -7.2604288, 3, 0.13957411 +-0.6037896, -6.8354358, 3, 0.20031313 +-2.2752955, -8.1398851, 3, 0.087196498 +-0.62694595, -6.8688969, 3, 0.31453405 +-1.4672528, -7.8295783, 3, 0.45545107 +-0.60069887, -6.8325782, 3, 0.20108803 +-1.4673945, -7.5525787, 3, 0.11726177 +-0.62969882, -6.8592483, 3, 0.19434728 +-0.53902379, -6.7760459, 3, 0.28034106 +-0.92725878, -7.1195502, 3, 0.15377209 +-0.51235305, -6.748776, 3, 0.25487588 +-1.6790453, -7.7123998, 3, 0.10760964 +-0.80316875, -7.0619083, 3, 0.35652619 +-1.5416196, -7.6091731, 3, 0.11368156 +-0.88387705, -7.1523638, 3, 0.37181534 +-0.5219274, -6.7584745, 3, 0.26835696 +-0.5219274, -6.7584745, 3, 0.26835696 +-0.51588874, -6.7523391, 3, 0.26173355 +-0.69658605, -6.9443038, 3, 0.33317342 +-0.58315273, -6.8162803, 3, 0.20581562 +-0.52285165, -6.7594176, 3, 0.26917993 +-0.57544134, -6.8140999, 3, 0.29716446 +-0.97494852, -7.1595373, 3, 0.14941752 +-1.537259, -7.605865, 3, 0.11388563 +-1.3463369, -7.4589222, 3, 0.12364187 +-2.3955784, -8.2225976, 3, 0.083917708 +-0.79548556, -7.0068167, 3, 0.1679805 +-0.89280199, -7.0904023, 3, 0.15714497 +-0.84603768, -7.0504787, 3, 0.16208139 +-1.0837083, -7.2493021, 3, 0.14059025 +-1.98396, -8.4503533, 3, 0.51081333 +-0.62938973, -6.8715197, 3, 0.31526062 +-1.5278314, -7.5987059, 3, 0.11432942 +-1.0719792, -7.2397121, 3, 0.14147873 +-0.51654388, -6.7528931, 3, 0.23779929 +-0.61408938, -6.8551301, 3, 0.31059392 +-0.51262843, -6.7490523, 3, 0.25570342 +-0.6942265, -6.91758, 3, 0.18231148 +-0.54768728, -6.7850325, 3, 0.28499009 +-0.54768728, -6.7850325, 3, 0.28499009 +-2.7393596, -8.453332, 3, 0.07563536 +-1.4117617, -7.7638383, 3, 0.44873637 +-0.55981088, -6.7943811, 3, 0.21328497 +-1.0435259, -7.3341093, 3, 0.39836642 +-0.97152599, -7.1566808, 3, 0.149719 +-0.97152599, -7.1566808, 3, 0.149719 +-0.97152599, -7.1566808, 3, 0.149719 +-0.53921021, -6.774806, 3, 0.22183934 +-0.55146425, -6.7864813, 3, 0.21644556 +-2.4205048, -8.2396047, 3, 0.083265298 +-2.4205048, -8.2396047, 3, 0.083265298 +-0.85183096, -7.1163192, 3, 0.36593271 +-0.52659414, -6.7626714, 3, 0.22902147 +-0.58973631, -6.8292091, 3, 0.30247059 +-3.1842944, -8.7407039, 3, 0.066790766 +-0.84732133, -7.11126, 3, 0.36508626 +-0.75572846, -7.009275, 3, 0.34668422 +-0.56301147, -6.8010344, 3, 0.29209395 +-0.55650021, -6.7912524, 3, 0.21449906 +-1.9889885, -7.9384591, 3, 0.096004483 +-1.9889885, -7.9384591, 3, 0.096004483 +-0.56614123, -6.8043174, 3, 0.2934188 +-1.5914046, -7.6467967, 3, 0.11140357 +-0.54755207, -6.7848919, 3, 0.28492179 +-2.4105313, -8.2328052, 3, 0.083525271 +-0.66720196, -6.8933065, 3, 0.18697005 +-1.0292561, -7.2045989, 3, 0.14483785 +-0.66613742, -6.8923459, 3, 0.18716348 +-0.94042528, -7.1306304, 3, 0.15253554 +-1.6533089, -8.051469, 3, 0.47674235 +-0.8781862, -7.0779707, 3, 0.15864043 +-1.1536127, -7.3060301, 3, 0.13556453 +-0.55813782, -6.7959317, 3, 0.2899553 +-2.3565872, -8.9049286, 3, 0.54478272 +-1.5372927, -7.6058906, 3, 0.11388405 +-0.54762962, -6.7828382, 3, 0.21802102 +-4.9888497, -9.803503, 3, 0.043529403 +-4.9888497, -9.803503, 3, 0.043529403 +-1.064298, -7.2334202, 3, 0.1420682 +-2.8886686, -9.5597499, 3, 0.58716717 +-0.51959069, -6.7558708, 3, 0.23456079 +-0.65338296, -6.8808096, 3, 0.18954753 +-0.86557025, -7.0672066, 3, 0.15996495 +-2.3219987, -8.1721289, 3, 0.085896937 +-2.3219987, -8.1721289, 3, 0.085896937 +-1.097777, -7.3965906, 3, 0.40657886 +-1.097777, -7.3965906, 3, 0.40657886 +-0.65244668, -6.8963544, 3, 0.32181565 +-0.51950642, -6.7557886, 3, 0.23464065 +-0.56294235, -6.797335, 3, 0.2121788 +-0.52382507, -6.759989, 3, 0.23100196 +-0.52382507, -6.759989, 3, 0.23100196 +-0.51294881, -6.7493741, 3, 0.25653812 +-0.65688832, -6.8839853, 3, 0.18887965 +-0.65688832, -6.8839853, 3, 0.18887965 +-0.87444947, -7.0747857, 3, 0.1590294 +-0.89975773, -7.0963043, 3, 0.15644731 +-0.51229974, -6.7487166, 3, 0.24535954 +-0.80266613, -7.0130522, 3, 0.16710162 +-0.55802934, -6.7926982, 3, 0.2139323 +-0.51307255, -6.7494985, 3, 0.25683388 +-0.51809333, -6.7544091, 3, 0.2360524 +-0.61438333, -6.8452024, 3, 0.19776711 +-1.1060965, -7.4062011, 3, 0.40780868 +-1.8347205, -7.8270544, 3, 0.10146379 +-2.1018609, -8.0186639, 3, 0.092346136 +-0.59228886, -6.8319157, 3, 0.30337057 +-0.62340314, -6.8534847, 3, 0.19571908 +-0.6353865, -6.8644434, 3, 0.19314514 +-1.0310922, -7.3198371, 3, 0.39643413 +-0.53529786, -6.7721964, 3, 0.27813268 +-0.53529786, -6.7721964, 3, 0.27813268 +-2.2361359, -8.7575224, 3, 0.53424211 +-2.197787, -8.0860044, 3, 0.089432255 +-0.73103875, -6.9820592, 3, 0.34123744 +-0.53271667, -6.7695355, 3, 0.276506 +-3.6484273, -9.0285624, 3, 0.059228252 +-0.6979694, -6.9458145, 3, 0.3335091 +-0.51234999, -6.748773, 3, 0.25486593 +-2.2865967, -8.1477025, 3, 0.086878844 +-0.51768686, -6.7541607, 3, 0.26401817 +-0.51856702, -6.7548718, 3, 0.23556278 +-0.61586552, -6.8570287, 3, 0.31115075 +-0.62005632, -6.8615128, 3, 0.31244822 +-0.51357844, -6.7499796, 3, 0.24223303 +-1.1722617, -7.4828912, 3, 0.41733588 +-0.60597683, -6.8374558, 3, 0.19977391 +-0.60597683, -6.8374558, 3, 0.19977391 +-4.5940516, -9.5830407, 3, 0.047426012 +-1.2665411, -7.3962116, 3, 0.12827932 +-0.51748896, -6.7538182, 3, 0.23670491 +-0.69111693, -6.9147977, 3, 0.18282462 +-0.52138878, -6.7576221, 3, 0.23295157 +-1.3686801, -7.7129543, 3, 0.4433925 +-0.56443163, -6.7987379, 3, 0.211666 +-0.63309743, -6.8755025, 3, 0.31635043 +-1.2045978, -7.5205297, 3, 0.42184005 +-0.51208064, -6.7484996, 3, 0.24614906 +-0.51208064, -6.7484996, 3, 0.24614906 +-0.58121836, -6.8144754, 3, 0.20637616 +-0.75073087, -6.9676874, 3, 0.17382017 +-0.76839045, -7.0232807, 3, 0.34938564 +-1.0240276, -7.2002817, 3, 0.14526296 +-0.93260898, -7.1240564, 3, 0.1532663 +-0.93260898, -7.1240564, 3, 0.1532663 +-0.60198071, -6.8337638, 3, 0.20076477 +-0.947726, -7.1367609, 3, 0.15186152 +-0.947726, -7.1367609, 3, 0.15186152 +-0.58657861, -6.8258643, 3, 0.30133881 +-1.4102086, -7.5085519, 3, 0.12018567 +-2.4444259, -9.0126563, 3, 0.55223029 +-5.1686421, -9.9019718, 3, 0.041910687 +-5.1686421, -9.9019718, 3, 0.041910687 +-5.1686421, -9.9019718, 3, 0.041910687 +-0.5258827, -6.7625168, 3, 0.27167451 +-1.2169755, -7.5349633, 3, 0.42353969 +-0.70498577, -6.9534837, 3, 0.33519535 +-0.62689538, -6.8688426, 3, 0.31451894 +-2.4988806, -9.079529, 3, 0.55675134 +-0.51307642, -6.7495024, 3, 0.25684293 +-3.9786774, -10.908369, 3, 0.65782607 +-0.57748748, -6.8162573, 3, 0.29795461 +-0.56383125, -6.7981725, 3, 0.21187174 +-1.3389697, -7.4531658, 3, 0.12405448 +-2.303875, -8.1501497, 4, 0.086779747 +-0.610475, -6.8454007, 4, 0.19771693 +-0.76586865, -6.9831393, 4, 0.17144312 +-0.6254817, -6.8590167, 4, 0.19440163 +-0.51776356, -6.7594856, 4, 0.2692379 +-0.72440981, -6.9470286, 4, 0.17716317 +-0.53667719, -6.7787582, 4, 0.28181079 +-0.53667719, -6.7787582, 4, 0.28181079 +-0.51043387, -6.7520079, 4, 0.23895129 +-0.57548741, -6.8189724, 4, 0.29893251 +-0.59956534, -6.8442502, 4, 0.30731032 +-0.53355015, -6.7755536, 4, 0.2800671 +-2.0037994, -7.9414838, 4, 0.095862588 +-2.0037994, -7.9414838, 4, 0.095862588 +-1.3033393, -7.6325865, 4, 0.4346668 +-1.3033393, -7.6325865, 4, 0.4346668 +-1.3033393, -7.6325865, 4, 0.4346668 +-0.70359954, -6.9555314, 4, 0.33564066 +-0.85861861, -7.0625365, 4, 0.16054854 +-2.3537877, -8.8844949, 4, 0.54334631 +-0.62486579, -6.8710297, 4, 0.31512542 +-0.81350705, -7.0241461, 4, 0.16556936 +-0.64658079, -6.8780313, 4, 0.19013948 +-1.1498333, -7.3017006, 4, 0.13593502 +-0.7801996, -7.03911, 4, 0.35236403 +-0.80164564, -7.0139822, 4, 0.16697165 +-0.52926437, -6.7711722, 4, 0.27751726 +-0.52288891, -6.7646798, 4, 0.27326471 +-0.50639846, -6.748078, 4, 0.24867559 +-0.68790248, -6.9148736, 4, 0.18281056 +-2.0469324, -8.5138623, 4, 0.51583435 +-0.95673201, -7.2356092, 4, 0.38454277 +-1.5643018, -7.9382949, 4, 0.46612966 +-0.54197025, -6.7820772, 4, 0.21836108 +-0.55547367, -6.7981416, 4, 0.2908941 +-0.50833336, -6.7499666, 4, 0.24225865 +-1.0738563, -7.3683405, 4, 0.4029136 +-1.0738563, -7.3683405, 4, 0.4029136 +-0.59655516, -6.8410783, 4, 0.30632086 +-4.0005872, -9.2210515, 4, 0.054764023 +-0.64416312, -6.8758598, 4, 0.19060725 +-0.92067971, -7.1147047, 4, 0.15432048 +-0.69845376, -6.9242032, 4, 0.18110973 +-0.69845376, -6.9242032, 4, 0.18110973 +-0.51047617, -6.7520489, 4, 0.23889516 +-0.68066102, -6.9307495, 4, 0.33010668 +-0.69073896, -6.941622, 4, 0.33257458 +-0.53009993, -6.7708558, 4, 0.2239425 +-0.54509946, -6.7850202, 4, 0.21706737 +-0.50644349, -6.7481252, 4, 0.25180092 +-0.67512159, -6.9247837, 4, 0.32872383 +-3.460479, -10.235565, 4, 0.62490056 +-0.58578155, -6.8228137, 4, 0.2038523 +-3.3121129, -10.053821, 4, 0.61526015 +-0.77229617, -6.9887015, 4, 0.17061099 +-0.59369382, -6.8300771, 4, 0.20177834 +-0.51349528, -6.7551805, 4, 0.26515194 +-0.53223532, -6.7742081, 4, 0.27930617 +-1.0324278, -7.2069288, 4, 0.14460957 +-1.0324278, -7.2069288, 4, 0.14460957 +-0.57713965, -6.8148507, 4, 0.20625893 +-1.6490497, -7.6849166, 4, 0.10917261 +-0.64822447, -6.8959281, 4, 0.32170763 +-0.9631341, -7.2428207, 4, 0.38559632 +-0.73047143, -6.9523343, 4, 0.17628528 +-1.6118483, -7.9944767, 4, 0.47145836 +-0.815175, -7.0776459, 4, 0.35931888 +-1.3843408, -7.7269547, 4, 0.44487619 +-2.8907091, -9.5382294, 4, 0.58587477 +-0.60919317, -6.844234, 4, 0.19801293 +-0.60919317, -6.844234, 4, 0.19801293 +-0.53125899, -6.7732097, 4, 0.27872942 +-2.5600368, -9.134997, 4, 0.56044451 +-0.55212042, -6.7946697, 4, 0.28940997 +-0.65693058, -6.8873067, 4, 0.18819071 +-0.60446318, -6.8399233, 4, 0.19912442 +-0.58824547, -6.8250783, 4, 0.2031941 +-1.0502196, -7.3414239, 4, 0.39934824 +-0.77064521, -7.0286215, 4, 0.35039913 +-0.54334235, -6.7856089, 4, 0.28526878 +-0.53064334, -6.7713717, 4, 0.22365748 +-0.81918938, -7.0820826, 4, 0.36009508 +-0.61124798, -6.846104, 4, 0.19753948 +-1.0677785, -7.2356817, 4, 0.14185572 +-0.51202855, -6.7537062, 4, 0.26348336 +-2.2592646, -8.7700308, 4, 0.53515303 +-2.2592646, -8.7700308, 4, 0.53515303 +-0.50830842, -6.7499819, 4, 0.25788052 +-0.53922745, -6.7794927, 4, 0.21954746 +-3.2702083, -8.7798394, 4, 0.06569303 +-0.68197055, -6.9096151, 4, 0.18379411 +-2.1068741, -8.5860315, 4, 0.52142354 +-0.60127634, -6.8460546, 4, 0.30786639 +-2.0238322, -7.9556396, 4, 0.095202719 +-1.3168615, -7.6483042, 4, 0.43640238 +-0.77714995, -6.9928956, 4, 0.16999135 +-0.53207289, -6.7727277, 4, 0.22292374 +-0.74886174, -7.0047736, 4, 0.34580197 +-0.68664977, -6.9372075, 4, 0.33158043 +-0.68664977, -6.9372075, 4, 0.33158043 +-0.96369423, -7.1504531, 4, 0.1503812 +-0.88535087, -7.1555819, 4, 0.37232859 +-0.59562803, -6.8318488, 4, 0.20128814 +-0.64449239, -6.8919396, 4, 0.32068979 +-0.64449239, -6.8919396, 4, 0.32068979 +-1.0000193, -7.2844715, 4, 0.39154726 +-0.61406352, -6.848664, 4, 0.19689957 +-0.57682742, -6.8145624, 4, 0.20634897 +-0.57682742, -6.8145624, 4, 0.20634897 +-0.75972127, -7.0166508, 4, 0.34811492 +-0.67519234, -6.9035943, 4, 0.1849437 +-0.53387314, -6.7758843, 4, 0.28025137 +-0.84786327, -7.0534208, 4, 0.16170383 +-0.59578587, -6.8319933, 4, 0.20124841 +-1.2508468, -7.3816775, 4, 0.12940132 +-0.50667124, -6.7483516, 4, 0.25321999 +-0.87364491, -7.0752341, 4, 0.15897449 +-0.89814312, -7.0958436, 4, 0.15650148 +-0.89814312, -7.0958436, 4, 0.15650148 +-0.55644886, -6.7956468, 4, 0.21280642 +-0.85890036, -7.126115, 4, 0.36755663 +-0.50704107, -6.748706, 4, 0.24539484 +-2.5743561, -9.1524215, 4, 0.56159429 +-0.95289871, -7.1415114, 4, 0.15134405 +-1.8816724, -7.8544442, 4, 0.10007783 +-0.51999717, -6.7612219, 4, 0.23006571 +-0.51224084, -6.7539194, 4, 0.26373676 +-0.53433597, -6.7763583, 4, 0.28051369 +-2.4493603, -8.2488568, 4, 0.082913376 +-0.51731864, -6.7590359, 4, 0.26885091 +-1.3453494, -7.4553005, 4, 0.12390117 +-1.723994, -7.7400937, 4, 0.10607135 +-0.6969236, -6.9483062, 4, 0.33406021 +-0.6969236, -6.9483062, 4, 0.33406021 +-0.52463898, -6.7656591, 4, 0.22702722 +-2.0838232, -7.9978321, 4, 0.093275989 +-2.0838232, -7.9978321, 4, 0.093275989 +-1.5383495, -7.6023794, 4, 0.11410133 +-0.72729666, -6.9495565, 4, 0.17674315 +-3.0925252, -8.6683298, 4, 0.068884206 +-0.89956313, -7.1714582, 4, 0.37483393 +-0.52804407, -6.7689022, 4, 0.22505392 +-0.52804407, -6.7689022, 4, 0.22505392 +-0.96311287, -7.2427968, 4, 0.38559283 +-0.51001294, -6.7516854, 4, 0.26080035 +-0.53736094, -6.7794597, 4, 0.28218074 +-0.53259849, -6.7745796, 4, 0.27951812 +-1.5240908, -7.8908876, 4, 0.46153504 +-0.53195767, -6.7739241, 4, 0.2791432 +-0.53280034, -6.7734172, 4, 0.22255883 +-0.92933424, -7.2048091, 4, 0.37995995 +-3.7940996, -9.0989456, 4, 0.057545528 +-3.7940996, -9.0989456, 4, 0.057545528 +-0.81551823, -7.0258666, 4, 0.16533522 +-0.81551823, -7.0258666, 4, 0.16533522 +-0.50651655, -6.7481933, 4, 0.24768917 +-0.79016906, -7.0041192, 4, 0.16836481 +-3.9816192, -9.2099162, 4, 0.055010734 +-0.80073982, -7.0132047, 4, 0.16708028 +-0.62115825, -6.8670926, 4, 0.31402996 +-0.52820326, -6.7690536, 4, 0.22496589 +-0.50713246, -6.7488103, 4, 0.25498583 +-0.50634824, -6.7480301, 4, 0.25051065 +-0.50664996, -6.7483237, 4, 0.24693636 +-1.662508, -7.6948659, 4, 0.1086025 +-0.60656565, -6.8418404, 4, 0.19862655 +-0.65289302, -6.8836922, 4, 0.1889409 +-1.3449634, -7.6810155, 4, 0.43996837 +-3.753751, -10.594851, 4, 0.64299242 +-0.69009608, -6.9409277, 4, 0.33241892 +-0.50657759, -6.748253, 4, 0.24731824 +-0.66993483, -6.9192048, 4, 0.32741105 +-0.8856233, -7.1558859, 4, 0.37237699 +-1.3557039, -7.4633003, 4, 0.12332973 +-4.4894074, -9.502626, 4, 0.048948832 +-0.90202381, -7.17421, 4, 0.37526376 +-0.51600852, -6.7577129, 4, 0.26766562 +-0.57515161, -6.8186215, 4, 0.29880711 +-2.5995839, -8.3492157, 4, 0.07922609 +-0.83636196, -7.0436474, 4, 0.16296717 +-0.53573088, -6.7761909, 4, 0.22114136 +-0.53950666, -6.7816631, 4, 0.28331783 +-1.7843578, -8.1993616, 4, 0.48993152 +-0.52913733, -6.7710425, 4, 0.27743842 +-0.7588018, -6.977013, 4, 0.17237378 +-1.6352777, -8.0222096, 4, 0.47404444 +-0.50876097, -6.7503828, 4, 0.24147651 +-0.93792307, -7.2144536, 4, 0.38140989 +-1.248441, -7.3797886, 4, 0.12954853 +-0.56289344, -6.8016505, 4, 0.21062554 +-0.66126057, -6.9098898, 4, 0.32517441 +-0.50750275, -6.7491789, 4, 0.2560452 +-0.50750275, -6.7491789, 4, 0.2560452 +-0.72592977, -6.9797708, 4, 0.34076652 +-0.79967606, -7.0605424, 4, 0.35628081 +-1.2606233, -7.3893462, 4, 0.12880699 +-1.2606233, -7.3893462, 4, 0.12880699 +-1.2606233, -7.3893462, 4, 0.12880699 +-0.51497944, -6.7564014, 4, 0.23405527 +-2.1541937, -8.643089, 4, 0.52575864 +-0.73251101, -6.9541174, 4, 0.17599333 +-1.3217776, -7.4370405, 4, 0.12522399 +-1.6348867, -8.0217464, 4, 0.47400148 +-2.6095867, -8.3558438, 4, 0.078990628 +-1.5683655, -7.9430914, 4, 0.46658943 +-1.5683655, -7.9430914, 4, 0.46658943 +-0.50639121, -6.7480731, 4, 0.25126847 +-0.98854185, -7.2714928, 4, 0.38971657 +-0.51392026, -6.7553802, 4, 0.23504416 +-1.2123987, -7.351398, 4, 0.13180077 +-1.2123987, -7.351398, 4, 0.13180077 +-3.2833216, -10.01856, 4, 0.61334908 +-0.50636266, -6.7480432, 4, 0.24918196 +-0.50829354, -6.7499671, 4, 0.25785041 +-1.4220296, -7.7710319, 4, 0.44948126 +-0.55358209, -6.7929693, 4, 0.21382715 +-1.5716111, -7.6273124, 4, 0.11257354 +-0.94552275, -7.2229958, 4, 0.38268261 +-0.54146502, -6.7836766, 4, 0.28432623 +-1.8087802, -8.2284885, 4, 0.49244665 +-3.7091321, -9.0481203, 4, 0.058754592 +-0.61022967, -6.8555125, 4, 0.31070644 +-0.53967114, -6.7818322, 4, 0.28340357 +-0.53789107, -6.7800038, 4, 0.28246498 +-0.53789107, -6.7800038, 4, 0.28246498 +-1.5314268, -7.5971754, 4, 0.11442468 +-1.741776, -7.7531054, 4, 0.10536087 +-0.85812805, -7.1252562, 4, 0.36741504 +-1.2097263, -7.3492862, 4, 0.13197136 +-0.51468289, -6.7561156, 4, 0.23432544 +-1.4400694, -7.7921654, 4, 0.45165497 +-2.5691948, -8.3290379, 4, 0.079948882 +-2.5691948, -8.3290379, 4, 0.079948882 +-1.7009119, -7.7231582, 4, 0.10700776 +-0.50634533, -6.7480265, 4, 0.24961588 +-0.50634533, -6.7480265, 4, 0.24961588 +-0.82186269, -7.0312882, 4, 0.16460327 # -# Elapsed Time: 0.001000 seconds (Pathfinders) -# 0.001000 seconds (PSIS) -# 0.002000 seconds (Total) +# Elapsed Time: 0.000000 seconds (Pathfinders) +# 0.000000 seconds (PSIS) +# 0.000000 seconds (Total) # diff --git a/test/data/pathfinder/bernoulli-pathfinder_config.json b/test/data/pathfinder/bernoulli-pathfinder_config.json new file mode 100644 index 00000000..c8555515 --- /dev/null +++ b/test/data/pathfinder/bernoulli-pathfinder_config.json @@ -0,0 +1,48 @@ + +{ + "stan_major_version" : "2", + "stan_minor_version" : "37", + "stan_patch_version" : "0", + "model_name" : "bernoulli_model", + "start_datetime" : "2026-04-12 00:35:48 UTC", + "method" : { + "value" : "pathfinder", + "pathfinder" : { + "init_alpha" : 0.001, + "tol_obj" : 1e-12, + "tol_rel_obj" : 10000, + "tol_grad" : 1e-08, + "tol_rel_grad" : 10000000, + "tol_param" : 1e-08, + "history_size" : 5, + "num_psis_draws" : 1000, + "num_paths" : 4, + "save_single_paths" : false, + "psis_resample" : true, + "calculate_lp" : true, + "max_lbfgs_iters" : 1000, + "num_draws" : 1000, + "num_elbo_draws" : 25 + } + }, + "id" : 1, + "data" : { + "file" : "test\/data\/bernoulli.data.json" + }, + "init" : "2", + "random" : { + "seed" : 12345 + }, + "output" : { + "file" : "\/tmp\/tmpj7vksit8\/bernoulli9hb1n4hj\/bernoulli-20260411203548.csv", + "diagnostic_file" : "", + "refresh" : 100, + "sig_figs" : 8, + "profile_file" : "profile.csv", + "save_cmdstan_config" : true + }, + "num_threads" : 1, + "mpi_enabled" : false, + "stanc_version" : "stanc3 v2.37.0", + "stancflags" : "--filename-in-msg=bernoulli.stan" +} diff --git a/test/test_metadata.py b/test/test_metadata.py index e451c762..bf45849f 100644 --- a/test/test_metadata.py +++ b/test/test_metadata.py @@ -5,13 +5,24 @@ import os import tempfile from pathlib import Path +from typing import Any import pytest from pydantic import ValidationError from cmdstanpy.cmdstan_args import CmdStanArgs, SamplerArgs from cmdstanpy.stanfit import InferenceMetadata, RunSet -from cmdstanpy.stanfit.metadata import MetricInfo +from cmdstanpy.stanfit.metadata import ( + GeneratedQuantitiesConfig, + LaplaceConfig, + MetricInfo, + OptimizeConfig, + PathfinderConfig, + SampleConfig, + StanConfig, + VariationalConfig, + parse_config, +) from cmdstanpy.utils import EXTENSION, check_sampler_csv HERE = os.path.dirname(os.path.abspath(__file__)) @@ -22,6 +33,213 @@ BADFILES_PATH = os.path.join(DATAFILES_PATH, 'runset-bad') +def make_config_output( + method_name: str, method_body: dict[str, Any] +) -> dict[str, Any]: + return { + 'stan_major_version': '2', + 'stan_minor_version': '37', + 'stan_patch_version': '0', + 'model_name': 'mu_model', + 'start_datetime': '2026-01-23 22:20:01 UTC', + 'method': { + 'value': method_name, + method_name: method_body, + }, + 'id': 1, + 'data': {'file': ''}, + 'init': '2', + 'random': {'seed': 12345}, + 'output': { + 'file': '/tmp/mu.csv', + 'diagnostic_file': '', + 'refresh': 100, + 'sig_figs': 8, + 'profile_file': 'profile.csv', + 'save_cmdstan_config': True, + }, + 'num_threads': 4, + 'mpi_enabled': False, + 'stanc_version': 'stanc3 v2.37.0', + 'stancflags': '--filename-in-msg=mu.stan', + } + + +CONFIG_OUTPUT_CASES: list[ + tuple[str, dict[str, Any], type[Any], dict[str, Any]] +] = [ + ( + 'sample', + make_config_output( + 'sample', + { + 'num_samples': 1000, + 'num_warmup': 1000, + 'save_warmup': False, + 'thin': 1, + 'adapt': { + 'engaged': True, + 'gamma': 0.05, + 'delta': 0.8, + 'kappa': 0.75, + 't0': 10, + 'init_buffer': 75, + 'term_buffer': 50, + 'window': 25, + 'save_metric': True, + }, + 'algorithm': { + 'value': 'hmc', + 'hmc': { + 'engine': { + 'value': 'nuts', + 'nuts': {'max_depth': 10}, + }, + 'metric': {'value': 'diag_e'}, + 'metric_file': '', + 'stepsize': 1, + 'stepsize_jitter': 0, + }, + }, + 'num_chains': 4, + }, + ), + SampleConfig, + { + 'algorithm': 'hmc', + 'num_samples': 1000, + 'num_warmup': 1000, + 'save_warmup': False, + 'thin': 1, + 'max_depth': 10, + }, + ), + ( + 'optimize', + make_config_output( + 'optimize', + { + 'algorithm': { + 'value': 'lbfgs', + 'lbfgs': { + 'init_alpha': 0.001, + 'tol_obj': 1e-12, + 'tol_rel_obj': 10000, + 'tol_grad': 1e-08, + 'tol_rel_grad': 10000000, + 'tol_param': 1e-08, + 'history_size': 5, + }, + }, + 'jacobian': False, + 'iter': 2000, + 'save_iterations': False, + }, + ), + OptimizeConfig, + { + 'algorithm': 'lbfgs', + 'jacobian': False, + 'save_iterations': False, + }, + ), + ( + 'variational', + make_config_output( + 'variational', + { + 'algorithm': { + 'value': 'meanfield', + 'meanfield': {}, + }, + 'iter': 10000, + 'grad_samples': 1, + 'elbo_samples': 100, + 'eta': 1, + 'adapt': { + 'engaged': True, + 'iter': 50, + }, + 'tol_rel_obj': 0.01, + 'eval_elbo': 100, + 'output_samples': 1000, + }, + ), + VariationalConfig, + { + 'algorithm': 'meanfield', + 'iter': 10000, + 'grad_samples': 1, + 'elbo_samples': 100, + 'eta': 1.0, + }, + ), + ( + 'pathfinder', + make_config_output( + 'pathfinder', + { + 'init_alpha': 0.001, + 'tol_obj': 1e-12, + 'tol_rel_obj': 10000, + 'tol_grad': 1e-08, + 'tol_rel_grad': 10000000, + 'tol_param': 1e-08, + 'history_size': 5, + 'num_psis_draws': 1000, + 'num_paths': 4, + 'save_single_paths': False, + 'psis_resample': True, + 'calculate_lp': True, + 'max_lbfgs_iters': 1000, + 'num_draws': 1000, + 'num_elbo_draws': 25, + }, + ), + PathfinderConfig, + { + 'num_draws': 1000, + 'num_paths': 4, + 'psis_resample': True, + 'calculate_lp': True, + }, + ), + ( + 'laplace', + make_config_output( + 'laplace', + { + 'mode': '/tmp/mu-opt.csv', + 'jacobian': True, + 'draws': 1000, + 'calculate_lp': True, + }, + ), + LaplaceConfig, + { + 'mode': '/tmp/mu-opt.csv', + 'draws': 1000, + 'jacobian': True, + }, + ), + ( + 'generate_quantities', + make_config_output( + 'generate_quantities', + { + 'fitted_params': '/tmp/mu-fit.csv', + 'num_chains': 1, + }, + ), + GeneratedQuantitiesConfig, + { + 'fitted_params': '/tmp/mu-fit.csv', + 'num_chains': 1, + }, + ), +] + + def test_good() -> None: # construct fit using existing sampler output exe = os.path.join(DATAFILES_PATH, 'bernoulli' + EXTENSION) @@ -77,6 +295,46 @@ def test_good() -> None: assert bern_model_vars == metadata.stan_vars.keys() +@pytest.mark.parametrize( + 'method_name, config_json, expected_type, expected_fields', + CONFIG_OUTPUT_CASES, +) +def test_parse_config_outputs( + method_name: str, + config_json: dict[str, Any], + expected_type: type[Any], + expected_fields: dict[str, Any], +) -> None: + parsed = parse_config(json.dumps(config_json)) + + assert isinstance(parsed, StanConfig) + assert parsed.model_name == 'mu_model' + assert parsed.stan_major_version == '2' + assert parsed.stan_minor_version == '37' + assert parsed.stan_patch_version == '0' + assert isinstance(parsed.method_config, expected_type) + assert parsed.method_config.method == method_name + + dumped = parsed.method_config.model_dump() + for key, expected in expected_fields.items(): + assert dumped[key] == expected + + +def test_parse_config_accepts_bytes() -> None: + config_json = make_config_output( + 'generate_quantities', + { + 'fitted_params': '/tmp/mu-fit.csv', + 'num_chains': 1, + }, + ) + + parsed = parse_config(json.dumps(config_json).encode()) + + assert isinstance(parsed.method_config, GeneratedQuantitiesConfig) + assert parsed.method_config.fitted_params == '/tmp/mu-fit.csv' + + class TestMetricInfoValidators: """Test custom validators for MetricInfo model""" From ca13a2eee6f55eddbb6d5cb2fc81cec55fd96fd7 Mon Sep 17 00:00:00 2001 From: amas Date: Wed, 15 Apr 2026 20:50:50 -0400 Subject: [PATCH 10/16] Fixup Path conversion to string --- cmdstanpy/stanfit/__init__.py | 2 +- cmdstanpy/stanfit/pathfinder.py | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cmdstanpy/stanfit/__init__.py b/cmdstanpy/stanfit/__init__.py index 787d8238..6dd3413d 100644 --- a/cmdstanpy/stanfit/__init__.py +++ b/cmdstanpy/stanfit/__init__.py @@ -92,7 +92,7 @@ def from_csv( if os.path.splitext(file)[1] == ".csv": csvfiles.append(os.path.join(path, file)) elif os.path.exists(path): - csvfiles.append(str(path)) + csvfiles.append(os.fspath(path)) else: raise ValueError('Invalid path specification: {}'.format(path)) else: diff --git a/cmdstanpy/stanfit/pathfinder.py b/cmdstanpy/stanfit/pathfinder.py index bc0339d6..49c743f5 100644 --- a/cmdstanpy/stanfit/pathfinder.py +++ b/cmdstanpy/stanfit/pathfinder.py @@ -53,11 +53,13 @@ def from_files( metadata = InferenceMetadata.from_csv(csv_file) return cls( metadata=metadata, - csv_file=str(csv_file), + csv_file=os.fspath(csv_file), model_name=stan_config.model_name, config=stan_config.method_config, - config_file=str(config_file), - stdout_file=str(stdout_file) if stdout_file is not None else None, + config_file=os.fspath(config_file), + stdout_file=( + os.fspath(stdout_file) if stdout_file is not None else None + ), ) def create_inits( @@ -255,4 +257,4 @@ def save_csvfiles(self, dir: str | None = None) -> None: if dst.exists(): raise ValueError(f'File exists, not overwriting: {dst}') shutil.move(src, dst) - setattr(self, attr, str(dst)) + setattr(self, attr, os.fspath(dst)) From c5a42db7458710363489df422f3da01f8ebf3559 Mon Sep 17 00:00:00 2001 From: amas Date: Wed, 15 Apr 2026 21:32:09 -0400 Subject: [PATCH 11/16] Convert StanConfig to Generic for richer typing --- cmdstanpy/stanfit/metadata.py | 37 ++++++++++++++++++++------------- cmdstanpy/stanfit/pathfinder.py | 19 +++++++---------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/cmdstanpy/stanfit/metadata.py b/cmdstanpy/stanfit/metadata.py index 1dac3b1d..051cd2a1 100644 --- a/cmdstanpy/stanfit/metadata.py +++ b/cmdstanpy/stanfit/metadata.py @@ -6,7 +6,7 @@ import json import math import os -from typing import Annotated, Any, Iterator, Literal +from typing import Annotated, Any, Generic, Iterator, Literal import stanio from pydantic import ( @@ -16,6 +16,7 @@ field_validator, model_validator, ) +from typing_extensions import TypeVar from cmdstanpy.utils import stancsv @@ -196,7 +197,20 @@ class GeneratedQuantitiesConfig(BaseModel): num_chains: int = 1 -class StanConfig(BaseModel): +AnyMethodConfig = Annotated[ + SampleConfig + | OptimizeConfig + | PathfinderConfig + | LaplaceConfig + | VariationalConfig + | GeneratedQuantitiesConfig, + Discriminator("method"), +] + +MethodT = TypeVar("MethodT", bound=BaseModel, default=AnyMethodConfig) + + +class StanConfig(BaseModel, Generic[MethodT]): """Common representation of a config JSON file output as part of a Stan inference run. Separate method-specific config classes handle the variation of output between methods.""" @@ -208,15 +222,7 @@ class StanConfig(BaseModel): stan_minor_version: str stan_patch_version: str - method_config: Annotated[ - SampleConfig - | OptimizeConfig - | PathfinderConfig - | LaplaceConfig - | VariationalConfig - | GeneratedQuantitiesConfig, - Discriminator("method"), - ] + method_config: MethodT def flatten_value_dict(data: dict[str, Any]) -> dict[str, Any]: @@ -280,9 +286,12 @@ def flatten_config(data: dict[str, Any]) -> dict[str, Any]: return result -def parse_config(json_data: str | bytes) -> StanConfig: - """Parse a CmdStan config JSON string into a StanConfig.""" +def parse_config( + json_data: str | bytes, method_type: type[MethodT] +) -> StanConfig[MethodT]: + """Parse a CmdStan config JSON string into a StanConfig with the + given method type.""" raw = json.loads(json_data) flat = flatten_config(raw) - return StanConfig.model_validate(flat) # type: ignore + return StanConfig[method_type].model_validate(flat) # type: ignore diff --git a/cmdstanpy/stanfit/pathfinder.py b/cmdstanpy/stanfit/pathfinder.py index 49c743f5..0e02590a 100644 --- a/cmdstanpy/stanfit/pathfinder.py +++ b/cmdstanpy/stanfit/pathfinder.py @@ -14,6 +14,7 @@ from cmdstanpy.stanfit.metadata import ( InferenceMetadata, PathfinderConfig, + StanConfig, parse_config, ) from cmdstanpy.utils import stancsv @@ -29,7 +30,7 @@ class CmdStanPathfinder: metadata: InferenceMetadata model_name: str csv_file: str - config: PathfinderConfig + config: StanConfig[PathfinderConfig] config_file: str | None = None stdout_file: str | None = None _draws: np.ndarray = field(default_factory=lambda: np.array(()), init=False) @@ -42,20 +43,14 @@ def from_files( stdout_file: str | os.PathLike | None = None, ) -> CmdStanPathfinder: with open(config_file) as f: - stan_config = parse_config(f.read()) - - if not isinstance(stan_config.method_config, PathfinderConfig): - conf_name = type(stan_config.method_config).__name__ - raise ValueError( - f"Did not find Pathfinder config, instead found: {conf_name}" - ) + stan_config = parse_config(f.read(), PathfinderConfig) metadata = InferenceMetadata.from_csv(csv_file) return cls( metadata=metadata, csv_file=os.fspath(csv_file), model_name=stan_config.model_name, - config=stan_config.method_config, + config=stan_config, config_file=os.fspath(config_file), stdout_file=( os.fspath(stdout_file) if stdout_file is not None else None @@ -229,9 +224,9 @@ def is_resampled(self) -> bool: approximations, False otherwise. """ return ( - self.config.num_paths > 1 - and self.config.psis_resample - and self.config.calculate_lp + self.config.method_config.num_paths > 1 + and self.config.method_config.psis_resample + and self.config.method_config.calculate_lp ) def save_csvfiles(self, dir: str | None = None) -> None: From 610ad2fcf59b6024ba8444ad43876809a70881ec Mon Sep 17 00:00:00 2001 From: amas Date: Wed, 15 Apr 2026 21:43:18 -0400 Subject: [PATCH 12/16] Minor comment on config_file optionality --- cmdstanpy/stanfit/pathfinder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmdstanpy/stanfit/pathfinder.py b/cmdstanpy/stanfit/pathfinder.py index 0e02590a..fa08f272 100644 --- a/cmdstanpy/stanfit/pathfinder.py +++ b/cmdstanpy/stanfit/pathfinder.py @@ -31,7 +31,7 @@ class CmdStanPathfinder: model_name: str csv_file: str config: StanConfig[PathfinderConfig] - config_file: str | None = None + config_file: str | None = None # None if config object passed directly stdout_file: str | None = None _draws: np.ndarray = field(default_factory=lambda: np.array(()), init=False) From 1e2f272b3e1864bd9891c9c5c0a42308e6c22ad4 Mon Sep 17 00:00:00 2001 From: amas Date: Wed, 15 Apr 2026 22:04:35 -0400 Subject: [PATCH 13/16] Refactor CmdStanLaplace --- cmdstanpy/model.py | 8 +- cmdstanpy/stanfit/__init__.py | 35 +++----- cmdstanpy/stanfit/laplace.py | 156 ++++++++++++++++++++-------------- test/test_laplace.py | 2 +- 4 files changed, 112 insertions(+), 89 deletions(-) diff --git a/cmdstanpy/model.py b/cmdstanpy/model.py index 0a688a18..ecc277ce 100644 --- a/cmdstanpy/model.py +++ b/cmdstanpy/model.py @@ -1040,7 +1040,7 @@ def generate_quantities( ), ): fit_object = previous_fit - if isinstance(previous_fit, CmdStanPathfinder): + if isinstance(previous_fit, (CmdStanPathfinder, CmdStanLaplace)): fit_csv_files = [previous_fit.csv_file] else: fit_csv_files = previous_fit.runset.csv_files @@ -1787,7 +1787,11 @@ def laplace_sample( timeout=timeout, ) runset.raise_for_timeouts() - return CmdStanLaplace(runset, cmdstan_mode) + return CmdStanLaplace.from_files( + csv_file=runset.csv_files[0], + config_file=runset.config_files[0], + stdout_file=runset.stdout_files[0], + ) def _run_cmdstan( self, diff --git a/cmdstanpy/stanfit/__init__.py b/cmdstanpy/stanfit/__init__.py index 6dd3413d..1729aec7 100644 --- a/cmdstanpy/stanfit/__init__.py +++ b/cmdstanpy/stanfit/__init__.py @@ -5,7 +5,6 @@ from cmdstanpy.cmdstan_args import ( CmdStanArgs, - LaplaceArgs, OptimizeArgs, SamplerArgs, VariationalArgs, @@ -233,27 +232,21 @@ def from_csv( runset._set_retcode(i, 0) return CmdStanVB(runset) elif config_dict['method'] == 'laplace': - jacobian = config_dict['jacobian'] == 1 - laplace_args = LaplaceArgs( - mode=config_dict['mode'], # type: ignore - draws=config_dict['draws'], # type: ignore - jacobian=jacobian, - ) - cmdstan_args = CmdStanArgs( - model_name=model, - model_exe=model, - chain_ids=None, - method_args=laplace_args, - ) - runset = RunSet(args=cmdstan_args) - runset._csv_files = csvfiles - for i in range(len(runset._retcodes)): - runset._set_retcode(i, 0) - mode: CmdStanMLE = from_csv( - config_dict['mode'], # type: ignore - method='optimize', + if len(csvfiles) != 1: + raise ValueError( + 'Expecting a single Laplace Stan CSV file, ' + f'found {len(csvfiles)}' + ) + csv_file = csvfiles[0] + config_file = os.path.splitext(csv_file)[0] + '_config.json' + if not os.path.exists(config_file): + raise ValueError( + 'Laplace config file not found at expected path: ' + f'{config_file}' + ) + return CmdStanLaplace.from_files( + csv_file=csv_file, config_file=config_file ) - return CmdStanLaplace(runset, mode=mode) elif config_dict['method'] == 'pathfinder': if len(csvfiles) != 1: raise ValueError( diff --git a/cmdstanpy/stanfit/laplace.py b/cmdstanpy/stanfit/laplace.py index bab78c3f..c1277133 100644 --- a/cmdstanpy/stanfit/laplace.py +++ b/cmdstanpy/stanfit/laplace.py @@ -4,7 +4,12 @@ from __future__ import annotations -from typing import Any, Hashable, MutableMapping +import os +import shutil +from collections.abc import Hashable +from dataclasses import dataclass, field +from pathlib import Path +from typing import Any, MutableMapping import numpy as np import pandas as pd @@ -16,30 +21,60 @@ except ImportError: XARRAY_INSTALLED = False -from cmdstanpy.cmdstan_args import Method from cmdstanpy.utils import stancsv from cmdstanpy.utils.data_munging import build_xarray_data -from .metadata import InferenceMetadata +from .metadata import InferenceMetadata, LaplaceConfig, StanConfig, parse_config from .mle import CmdStanMLE -from .runset import RunSet # TODO list: # - docs and example notebook +@dataclass class CmdStanLaplace: - def __init__(self, runset: RunSet, mode: CmdStanMLE) -> None: - """Initialize object.""" - if not runset.method == Method.LAPLACE: - raise ValueError( - 'Wrong runset method, expecting laplace runset, ' - 'found method {}'.format(runset.method) - ) - self.runset = runset - self._mode = mode - self._draws: np.ndarray = np.array(()) - self._metadata = InferenceMetadata.from_csv(self.runset.csv_files[0]) + """ + Container for outputs from the Laplace approximation. + Created by :meth:`CmdStanModel.laplace_sample`. + """ + + metadata: InferenceMetadata + model_name: str + csv_file: str + config: StanConfig[LaplaceConfig] + mode: CmdStanMLE + config_file: str | None = None # None if config object passed directly + stdout_file: str | None = None + _draws: np.ndarray = field(default_factory=lambda: np.array(()), init=False) + + @classmethod + def from_files( + cls, + csv_file: str | os.PathLike, + config_file: str | os.PathLike, + stdout_file: str | os.PathLike | None = None, + ) -> CmdStanLaplace: + # Local import to avoid circular dependency with stanfit.__init__ + from cmdstanpy.stanfit import from_csv + + with open(config_file) as f: + stan_config = parse_config(f.read(), LaplaceConfig) + + metadata = InferenceMetadata.from_csv(csv_file) + # temporary - should have done CmdStanMLE first + mode = from_csv(stan_config.method_config.mode, method='optimize') + assert isinstance(mode, CmdStanMLE) + return cls( + metadata=metadata, + csv_file=os.fspath(csv_file), + model_name=stan_config.model_name, + config=stan_config, + mode=mode, + config_file=os.fspath(config_file), + stdout_file=( + os.fspath(stdout_file) if stdout_file is not None else None + ), + ) def create_inits( self, seed: int | None = None, chains: int = 4 @@ -63,13 +98,13 @@ def create_inits( draw = self._draws[idxs[0]] return { name: var.extract_reshape(draw) - for name, var in self._metadata.stan_vars.items() + for name, var in self.metadata.stan_vars.items() } else: return [ { name: var.extract_reshape(self._draws[idx]) - for name, var in self._metadata.stan_vars.items() + for name, var in self.metadata.stan_vars.items() } for idx in idxs ] @@ -78,15 +113,12 @@ def _assemble_draws(self) -> None: if self._draws.shape != (0,): return - csv_file = self.runset.csv_files[0] try: - *_, draws = stancsv.parse_comments_header_and_draws( - self.runset.csv_files[0] - ) + *_, draws = stancsv.parse_comments_header_and_draws(self.csv_file) self._draws = stancsv.csv_bytes_list_to_numpy(draws) except Exception as exc: raise ValueError( - f"An error occurred when parsing Stan csv {csv_file}" + f"An error occurred when parsing Stan csv {self.csv_file}" ) from exc def stan_variable(self, var: str) -> np.ndarray: @@ -110,7 +142,7 @@ def stan_variable(self, var: str) -> np.ndarray: """ self._assemble_draws() try: - out: np.ndarray = self._metadata.stan_vars[var].extract_reshape( + out: np.ndarray = self.metadata.stan_vars[var].extract_reshape( self._draws ) return out @@ -119,7 +151,7 @@ def stan_variable(self, var: str) -> np.ndarray: raise ValueError( f'Unknown variable name: {var}\n' 'Available variables are ' - + ", ".join(self._metadata.stan_vars.keys()) + + ", ".join(self.metadata.stan_vars.keys()) ) def stan_variables(self) -> dict[str, np.ndarray]: @@ -140,7 +172,7 @@ def stan_variables(self) -> dict[str, np.ndarray]: CmdStanVB.stan_variables """ result = {} - for name in self._metadata.stan_vars: + for name in self.metadata.stan_vars: result[name] = self.stan_variable(name) return result @@ -155,7 +187,7 @@ def method_variables(self) -> dict[str, np.ndarray]: self._assemble_draws() return { name: var.extract_reshape(self._draws) - for name, var in self._metadata.method_vars.items() + for name, var in self.metadata.method_vars.items() } def draws(self) -> np.ndarray: @@ -181,10 +213,10 @@ def draws_pd( cols = [] if vars is not None: for var in dict.fromkeys(vars_list): - if var in self._metadata.method_vars: + if var in self.metadata.method_vars: cols.append(var) - elif var in self._metadata.stan_vars: - info = self._metadata.stan_vars[var] + elif var in self.metadata.stan_vars: + info = self.metadata.stan_vars[var] cols.extend( self.column_names[info.start_idx : info.end_idx] ) @@ -216,7 +248,7 @@ def draws_xr( ) if vars is None: - vars_list = list(self._metadata.stan_vars.keys()) + vars_list = list(self.metadata.stan_vars.keys()) elif isinstance(vars, str): vars_list = [vars] else: @@ -224,7 +256,7 @@ def draws_xr( self._assemble_draws() - meta = self._metadata.cmdstan_config + meta = self.metadata.cmdstan_config attrs: MutableMapping[Hashable, Any] = { "stan_version": f"{meta['stan_version_major']}." f"{meta['stan_version_minor']}.{meta['stan_version_patch']}", @@ -239,7 +271,7 @@ def draws_xr( for var in vars_list: build_xarray_data( data, - self._metadata.stan_vars[var], + self.metadata.stan_vars[var], self._draws[:, np.newaxis, :], ) return ( @@ -248,38 +280,20 @@ def draws_xr( .squeeze() ) - @property - def mode(self) -> CmdStanMLE: - """ - Return the maximum a posteriori estimate (mode) - as a :class:`CmdStanMLE` object. - """ - return self._mode - - @property - def metadata(self) -> InferenceMetadata: - """ - Returns object which contains CmdStan configuration as well as - information about the names and structure of the inference method - and model output variables. - """ - return self._metadata - def __repr__(self) -> str: - mode = '\n'.join( + mode_repr = '\n'.join( ['\t' + line for line in repr(self.mode).splitlines()] )[1:] - rep = 'CmdStanLaplace: model={} \nmode=({})\n{}'.format( - self.runset.model, - mode, - self.runset._args.method_args.compose(0, cmd=[]), - ) - rep = '{}\n csv_files:\n\t{}\n output_files:\n\t{}'.format( - rep, - '\n\t'.join(self.runset.csv_files), - '\n\t'.join(self.runset.stdout_files), - ) - return rep + lines = [ + f'CmdStanLaplace: model={self.model_name}', + f' mode=({mode_repr})', + f' csv_file:\n\t{self.csv_file}', + ] + if self.config_file is not None: + lines.append(f' config_file:\n\t{self.config_file}') + if self.stdout_file is not None: + lines.append(f' output_file:\n\t{self.stdout_file}') + return '\n'.join(lines) def __getattr__(self, attr: str) -> np.ndarray: """Synonymous with ``fit.stan_variable(attr)""" @@ -307,17 +321,29 @@ def column_names(self) -> tuple[str, ...]: and quantities of interest. Corresponds to Stan CSV file header row, with names munged to array notation, e.g. `beta[1]` not `beta.1`. """ - return self._metadata.column_names + return self.metadata.column_names def save_csvfiles(self, dir: str | None = None) -> None: """ - Move output CSV files to specified directory. + Move output CSV file, and any associated config and stdout files, + to the specified directory. Updates the corresponding attributes on + this object to point at the new locations. :param dir: directory path See Also -------- - stanfit.RunSet.save_csvfiles cmdstanpy.from_csv """ - self.runset.save_csvfiles(dir) + dest = Path(dir) if dir is not None else Path.cwd() + dest.mkdir(parents=True, exist_ok=True) + + for attr in ('csv_file', 'config_file', 'stdout_file'): + src = getattr(self, attr) + if src is None: + continue + dst = dest / Path(src).name + if dst.exists(): + raise ValueError(f'File exists, not overwriting: {dst}') + shutil.move(src, dst) + setattr(self, attr, os.fspath(dst)) diff --git a/test/test_laplace.py b/test/test_laplace.py index 82ce9364..8fc50b56 100644 --- a/test/test_laplace.py +++ b/test/test_laplace.py @@ -33,7 +33,7 @@ def test_laplace_from_csv() -> None: data={}, seed=1234, ) - fit2 = from_csv(fit.runset.csv_files) + fit2 = from_csv([fit.csv_file]) assert isinstance(fit2, cmdstanpy.CmdStanLaplace) assert 'x' in fit2.stan_variables() assert 'y' in fit2.stan_variables() From da04db4fdd4d5c09c211af7eea9904ecb4cc6629 Mon Sep 17 00:00:00 2001 From: amas Date: Wed, 15 Apr 2026 22:30:43 -0400 Subject: [PATCH 14/16] Add default method_type for parse_config --- cmdstanpy/stanfit/metadata.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cmdstanpy/stanfit/metadata.py b/cmdstanpy/stanfit/metadata.py index 051cd2a1..d8a62707 100644 --- a/cmdstanpy/stanfit/metadata.py +++ b/cmdstanpy/stanfit/metadata.py @@ -287,11 +287,16 @@ def flatten_config(data: dict[str, Any]) -> dict[str, Any]: def parse_config( - json_data: str | bytes, method_type: type[MethodT] + json_data: str | bytes, method_type: type[MethodT] | None = None ) -> StanConfig[MethodT]: - """Parse a CmdStan config JSON string into a StanConfig with the - given method type.""" + """Parse a CmdStan config JSON string into a StanConfig. + + When ``method_type`` is omitted the method is auto-detected from the + JSON content using the discriminated union ``AnyMethodConfig``. + """ raw = json.loads(json_data) flat = flatten_config(raw) + if method_type is None: + return StanConfig[AnyMethodConfig].model_validate(flat) # type: ignore return StanConfig[method_type].model_validate(flat) # type: ignore From 8b1a39b30030697dedf0bb799b8e0a27eb35c97f Mon Sep 17 00:00:00 2001 From: amas Date: Sat, 18 Apr 2026 13:47:25 -0400 Subject: [PATCH 15/16] Refactor CmdStanMLE --- cmdstanpy/model.py | 28 ++--- cmdstanpy/stanfit/__init__.py | 65 ++++++----- cmdstanpy/stanfit/gq.py | 10 +- cmdstanpy/stanfit/mle.py | 198 +++++++++++++++++++++------------- test/test_optimize.py | 23 ++-- 5 files changed, 192 insertions(+), 132 deletions(-) diff --git a/cmdstanpy/model.py b/cmdstanpy/model.py index ecc277ce..2e23eeb9 100644 --- a/cmdstanpy/model.py +++ b/cmdstanpy/model.py @@ -22,7 +22,6 @@ CmdStanArgs, GenerateQuantitiesArgs, LaplaceArgs, - Method, OptimizeArgs, PathfinderArgs, SamplerArgs, @@ -434,7 +433,8 @@ def optimize( ) runset.raise_for_timeouts() - if not runset._check_retcodes(): + converged = runset._check_retcodes() + if not converged: msg = "Error during optimization! Command '{}' failed: {}".format( ' '.join(runset.cmd(0)), runset.get_err_msgs() ) @@ -442,8 +442,12 @@ def optimize( get_logger().warning(msg) else: raise RuntimeError(msg) - mle = CmdStanMLE(runset) - return mle + return CmdStanMLE.from_files( + csv_file=runset.csv_files[0], + config_file=runset.config_files[0], + stdout_file=runset.stdout_files[0], + converged=converged, + ) # pylint: disable=too-many-arguments def sample( @@ -1040,7 +1044,9 @@ def generate_quantities( ), ): fit_object = previous_fit - if isinstance(previous_fit, (CmdStanPathfinder, CmdStanLaplace)): + if isinstance( + previous_fit, (CmdStanPathfinder, CmdStanLaplace, CmdStanMLE) + ): fit_csv_files = [previous_fit.csv_file] else: fit_csv_files = previous_fit.runset.csv_files @@ -1075,7 +1081,7 @@ def generate_quantities( elif isinstance(fit_object, CmdStanMLE): chains = 1 chain_ids = [1] - if fit_object._save_iterations: + if fit_object.config.method_config.save_iterations: get_logger().warning( 'MLE contains saved iterations which will be used ' 'to generate additional quantities of interest.' @@ -1746,14 +1752,12 @@ def laplace_sample( else: cmdstan_mode = mode - if cmdstan_mode.runset.method != Method.OPTIMIZE: + if not isinstance(cmdstan_mode, CmdStanMLE): raise ValueError( "Mode must be a CmdStanMLE or a path to an optimize CSV" ) - mode_jacobian = ( - cmdstan_mode.runset._args.method_args.jacobian # type: ignore - ) + mode_jacobian = cmdstan_mode.config.method_config.jacobian if mode_jacobian != jacobian: raise ValueError( "Jacobian argument to optimize and laplace must match!\n" @@ -1761,9 +1765,7 @@ def laplace_sample( f"but optimize was run with jacobian={mode_jacobian}" ) - laplace_args = LaplaceArgs( - cmdstan_mode.runset.csv_files[0], draws, jacobian - ) + laplace_args = LaplaceArgs(cmdstan_mode.csv_file, draws, jacobian) with temp_single_json(data) as _data: args = CmdStanArgs( diff --git a/cmdstanpy/stanfit/__init__.py b/cmdstanpy/stanfit/__init__.py index 1729aec7..d156114d 100644 --- a/cmdstanpy/stanfit/__init__.py +++ b/cmdstanpy/stanfit/__init__.py @@ -3,12 +3,7 @@ import glob import os -from cmdstanpy.cmdstan_args import ( - CmdStanArgs, - OptimizeArgs, - SamplerArgs, - VariationalArgs, -) +from cmdstanpy.cmdstan_args import CmdStanArgs, SamplerArgs, VariationalArgs from cmdstanpy.utils import check_sampler_csv, get_logger, stancsv from .gq import CmdStanGQ, PrevFit @@ -33,7 +28,7 @@ ] -def from_csv( +def from_csv( # pylint: disable=too-many-return-statements path: str | list[str] | os.PathLike | None = None, method: str | None = None, ) -> ( @@ -177,32 +172,52 @@ def from_csv( fit.draws() return fit elif config_dict['method'] == 'optimize': + if len(csvfiles) != 1: + raise ValueError( + 'Expecting a single optimize Stan CSV file, ' + f'found {len(csvfiles)}' + ) + csv_file = csvfiles[0] + config_file = os.path.splitext(csv_file)[0] + '_config.json' + if os.path.exists(config_file): + return CmdStanMLE.from_files( + csv_file=csv_file, config_file=config_file + ) + # Legacy path: no config file, build config from CSV metadata if 'algorithm' not in config_dict: raise ValueError( "Cannot find optimization algorithm in file {}.".format( - csvfiles[0] + csv_file ) ) - algorithm: str = config_dict['algorithm'] # type: ignore - save_iterations = config_dict['save_iterations'] == 1 - jacobian = config_dict.get('jacobian', 0) == 1 + from .metadata import OptimizeConfig, StanConfig - optimize_args = OptimizeArgs( - algorithm=algorithm, - save_iterations=save_iterations, - jacobian=jacobian, + opt_config = OptimizeConfig( + algorithm=config_dict['algorithm'], # type: ignore + save_iterations=config_dict.get('save_iterations', 0) == 1, + jacobian=config_dict.get('jacobian', 0) == 1, ) - cmdstan_args = CmdStanArgs( - model_name=model, - model_exe=model, - chain_ids=None, - method_args=optimize_args, + stan_config = StanConfig[OptimizeConfig].model_validate( + { + 'model_name': config_dict['model'], + 'stan_major_version': str( + config_dict.get('stan_version_major', '') + ), + 'stan_minor_version': str( + config_dict.get('stan_version_minor', '') + ), + 'stan_patch_version': str( + config_dict.get('stan_version_patch', '') + ), + 'method_config': opt_config.model_dump(), + } + ) + return CmdStanMLE( + metadata=InferenceMetadata.from_csv(csv_file), + model_name=stan_config.model_name, + csv_file=csv_file, + config=stan_config, ) - runset = RunSet(args=cmdstan_args) - runset._csv_files = csvfiles - for i in range(len(runset._retcodes)): - runset._set_retcode(i, 0) - return CmdStanMLE(runset) elif config_dict['method'] == 'variational': if 'algorithm' not in config_dict: raise ValueError( diff --git a/cmdstanpy/stanfit/gq.py b/cmdstanpy/stanfit/gq.py index 1937cc32..7cbf09d6 100644 --- a/cmdstanpy/stanfit/gq.py +++ b/cmdstanpy/stanfit/gq.py @@ -209,7 +209,7 @@ def draws( ) elif ( isinstance(self.previous_fit, CmdStanMLE) - and not self.previous_fit._save_iterations + and not self.previous_fit.config.method_config.save_iterations ): get_logger().warning( "MLE doesn't contain draws from pre-convergence iterations," @@ -301,7 +301,7 @@ def draws_pd( ) elif ( isinstance(self.previous_fit, CmdStanMLE) - and not self.previous_fit._save_iterations + and not self.previous_fit.config.method_config.save_iterations ): get_logger().warning( "MLE doesn't contain draws from pre-convergence iterations," @@ -649,7 +649,7 @@ def _draws_start(self, inc_warmup: bool) -> tuple[int, int]: elif isinstance(p_fit, CmdStanMLE): num_draws = 1 - if p_fit._save_iterations: + if p_fit.config.method_config.save_iterations: opt_iters = len(p_fit.optimized_iterations_np) # type: ignore if inc_warmup: num_draws = opt_iters @@ -675,7 +675,7 @@ def _previous_draws(self, inc_warmup: bool) -> np.ndarray: if isinstance(p_fit, CmdStanMCMC): return p_fit.draws(inc_warmup=inc_warmup) elif isinstance(p_fit, CmdStanMLE): - if inc_warmup and p_fit._save_iterations: + if inc_warmup and p_fit.config.method_config.save_iterations: return p_fit.optimized_iterations_np[:, None] # type: ignore return np.atleast_2d( # type: ignore @@ -703,7 +703,7 @@ def _previous_draws_pd( return p_fit.draws_pd(vars or None, inc_warmup=inc_warmup) elif isinstance(p_fit, CmdStanMLE): - if inc_warmup and p_fit._save_iterations: + if inc_warmup and p_fit.config.method_config.save_iterations: return p_fit.optimized_iterations_pd[sel] # type: ignore else: return p_fit.optimized_params_pd[sel] diff --git a/cmdstanpy/stanfit/mle.py b/cmdstanpy/stanfit/mle.py index 03b44799..fb646fd3 100644 --- a/cmdstanpy/stanfit/mle.py +++ b/cmdstanpy/stanfit/mle.py @@ -1,60 +1,86 @@ """Container for the result of running optimization""" +from __future__ import annotations + +import os +import shutil from collections import OrderedDict +from dataclasses import dataclass, field +from pathlib import Path import numpy as np import pandas as pd -from cmdstanpy.cmdstan_args import Method, OptimizeArgs from cmdstanpy.utils import get_logger, stancsv -from .metadata import InferenceMetadata -from .runset import RunSet +from .metadata import ( + InferenceMetadata, + OptimizeConfig, + StanConfig, + parse_config, +) +@dataclass class CmdStanMLE: """ Container for outputs from CmdStan optimization. Created by :meth:`CmdStanModel.optimize`. """ - def __init__(self, runset: RunSet) -> None: - """Initialize object.""" - if not runset.method == Method.OPTIMIZE: - raise ValueError( - 'Wrong runset method, expecting optimize runset, ' - 'found method {}'.format(runset.method) - ) - self.runset = runset - # info from runset to be exposed - self.converged = runset._check_retcodes() - optimize_args = self.runset._args.method_args - assert isinstance( - optimize_args, OptimizeArgs - ) # make the typechecker happy - self._save_iterations: bool = optimize_args.save_iterations - - csv_file = self.runset.csv_files[0] + metadata: InferenceMetadata + model_name: str + csv_file: str + config: StanConfig[OptimizeConfig] + converged: bool = True + config_file: str | None = None # None if config object passed directly + stdout_file: str | None = None + _mle: np.ndarray = field(default_factory=lambda: np.array(()), init=False) + _all_iters: np.ndarray = field( + default_factory=lambda: np.array(()), init=False + ) + + @classmethod + def from_files( + cls, + csv_file: str | os.PathLike, + config_file: str | os.PathLike, + stdout_file: str | os.PathLike | None = None, + converged: bool = True, + ) -> CmdStanMLE: + with open(config_file) as f: + stan_config = parse_config(f.read(), OptimizeConfig) + + metadata = InferenceMetadata.from_csv(csv_file) + return cls( + metadata=metadata, + model_name=stan_config.model_name, + csv_file=os.fspath(csv_file), + config=stan_config, + converged=converged, + config_file=os.fspath(config_file), + stdout_file=( + os.fspath(stdout_file) if stdout_file is not None else None + ), + ) + + def _assemble_draws(self) -> None: + if self._mle.shape != (0,): + return + try: - ( - comment_lines, - header, - draws_lines, - ) = stancsv.parse_comments_header_and_draws( - self.runset.csv_files[0] - ) - self._metadata = InferenceMetadata( - stancsv.construct_config_header_dict(comment_lines, header) + *_, draws_lines = stancsv.parse_comments_header_and_draws( + self.csv_file ) all_draws = stancsv.csv_bytes_list_to_numpy(draws_lines) - except Exception as exc: raise ValueError( - f"An error occurred when parsing Stan csv {csv_file}" + f"An error occurred when parsing Stan csv {self.csv_file}" ) from exc - self._mle: np.ndarray = all_draws[-1] - if self._save_iterations: - self._all_iters: np.ndarray = all_draws + + self._mle = all_draws[-1] + if self.config.method_config.save_iterations: + self._all_iters = all_draws def create_inits( self, seed: int | None = None, chains: int = 4 @@ -79,18 +105,21 @@ def create_inits( return self.stan_variables() def __repr__(self) -> str: - repr = 'CmdStanMLE: model={}{}'.format( - self.runset.model, self.runset._args.method_args.compose(0, cmd=[]) - ) - repr = '{}\n csv_file:\n\t{}\n output_file:\n\t{}'.format( - repr, - '\n\t'.join(self.runset.csv_files), - '\n\t'.join(self.runset.stdout_files), - ) + mc = self.config.method_config + lines = [ + f'CmdStanMLE: model={self.model_name}' + f' method={mc.method} algorithm={mc.algorithm}', + f' csv_file:\n\t{self.csv_file}', + ] + if self.config_file is not None: + lines.append(f' config_file:\n\t{self.config_file}') + if self.stdout_file is not None: + lines.append(f' output_file:\n\t{self.stdout_file}') if not self.converged: - repr = '{}\n Warning: invalid estimate, '.format(repr) - repr = '{} optimization failed to converge.'.format(repr) - return repr + lines.append( + ' Warning: invalid estimate, optimization failed to converge.' + ) + return '\n'.join(lines) def __getattr__(self, attr: str) -> np.ndarray: """Synonymous with ``fit.stan_variable(attr)""" @@ -102,6 +131,23 @@ def __getattr__(self, attr: str) -> np.ndarray: # pylint: disable=raise-missing-from raise AttributeError(*e.args) + def __getstate__(self) -> dict: + # This function returns the mapping of objects to serialize with pickle. + # See https://docs.python.org/3/library/pickle.html#object.__getstate__ + # for details. We call _assemble_draws to ensure estimates have been + # loaded prior to serialization. + self._assemble_draws() + state = self.__dict__.copy() + # StanConfig[OptimizeConfig] is a generic alias with no module-level + # name, so we serialize it as a plain dict for pickle compatibility. + state['config'] = self.config.model_dump() + return state + + def __setstate__(self, state: dict) -> None: + config_dict = state.pop('config') + self.__dict__.update(state) + self.config = StanConfig[OptimizeConfig].model_validate(config_dict) + @property def column_names(self) -> tuple[str, ...]: """ @@ -110,15 +156,6 @@ def column_names(self) -> tuple[str, ...]: """ return self.metadata.column_names - @property - def metadata(self) -> InferenceMetadata: - """ - Returns object which contains CmdStan configuration as well as - information about the names and structure of the inference method - and model output variables. - """ - return self._metadata - @property def optimized_params_np(self) -> np.ndarray: """ @@ -130,6 +167,7 @@ def optimized_params_np(self) -> np.ndarray: get_logger().warning( 'Invalid estimate, optimization failed to converge.' ) + self._assemble_draws() return self._mle @property @@ -140,7 +178,7 @@ def optimized_iterations_np(self) -> np.ndarray | None: the value for `lp__` as well as all Stan program variables. """ - if not self._save_iterations: + if not self.config.method_config.save_iterations: get_logger().warning( 'Intermediate iterations not saved to CSV output file. ' 'Rerun the optimize method with "save_iterations=True".' @@ -150,6 +188,7 @@ def optimized_iterations_np(self) -> np.ndarray | None: get_logger().warning( 'Invalid estimate, optimization failed to converge.' ) + self._assemble_draws() return self._all_iters @property @@ -159,10 +198,11 @@ def optimized_params_pd(self) -> pd.DataFrame: which contains all optimizer outputs, i.e., the value for `lp__` as well as all Stan program variables. """ - if not self.runset._check_retcodes(): + if not self.converged: get_logger().warning( 'Invalid estimate, optimization failed to converge.' ) + self._assemble_draws() return pd.DataFrame([self._mle], columns=self.column_names) @property @@ -173,7 +213,7 @@ def optimized_iterations_pd(self) -> pd.DataFrame | None: the value for `lp__` as well as all Stan program variables. """ - if not self._save_iterations: + if not self.config.method_config.save_iterations: get_logger().warning( 'Intermediate iterations not saved to CSV output file. ' 'Rerun the optimize method with "save_iterations=True".' @@ -183,6 +223,7 @@ def optimized_iterations_pd(self) -> pd.DataFrame | None: get_logger().warning( 'Invalid estimate, optimization failed to converge.' ) + self._assemble_draws() return pd.DataFrame(self._all_iters, columns=self.column_names) @property @@ -191,10 +232,11 @@ def optimized_params_dict(self) -> dict[str, np.float64]: Returns all estimates from the optimizer, including `lp__` as a Python Dict. Only returns estimate from final iteration. """ - if not self.runset._check_retcodes(): + if not self.converged: get_logger().warning( 'Invalid estimate, optimization failed to converge.' ) + self._assemble_draws() return OrderedDict(zip(self.column_names, self._mle)) def stan_variable( @@ -228,36 +270,36 @@ def stan_variable( CmdStanGQ.stan_variable CmdStanLaplace.stan_variable """ - if var not in self._metadata.stan_vars: + if var not in self.metadata.stan_vars: raise ValueError( f'Unknown variable name: {var}\n' - 'Available variables are ' + ", ".join(self._metadata.stan_vars) + 'Available variables are ' + ", ".join(self.metadata.stan_vars) ) - if warn and inc_iterations and not self._save_iterations: + save_iterations = self.config.method_config.save_iterations + if warn and inc_iterations and not save_iterations: get_logger().warning( 'Intermediate iterations not saved to CSV output file. ' 'Rerun the optimize method with "save_iterations=True".' ) - if warn and not self.runset._check_retcodes(): + if warn and not self.converged: get_logger().warning( 'Invalid estimate, optimization failed to converge.' ) - if inc_iterations and self._save_iterations: + self._assemble_draws() + if inc_iterations and save_iterations: data = self._all_iters else: data = self._mle try: - out: np.ndarray = self._metadata.stan_vars[var].extract_reshape( - data - ) + out: np.ndarray = self.metadata.stan_vars[var].extract_reshape(data) return out except KeyError: # pylint: disable=raise-missing-from raise ValueError( f'Unknown variable name: {var}\n' 'Available variables are ' - + ", ".join(self._metadata.stan_vars.keys()) + + ", ".join(self.metadata.stan_vars.keys()) ) def stan_variables( @@ -282,12 +324,12 @@ def stan_variables( CmdStanGQ.stan_variables CmdStanLaplace.stan_variables """ - if not self.runset._check_retcodes(): + if not self.converged: get_logger().warning( 'Invalid estimate, optimization failed to converge.' ) result = {} - for name in self._metadata.stan_vars: + for name in self.metadata.stan_vars: result[name] = self.stan_variable( name, inc_iterations=inc_iterations, warn=False ) @@ -295,13 +337,25 @@ def stan_variables( def save_csvfiles(self, dir: str | None = None) -> None: """ - Move output CSV files to specified directory. + Move output CSV file, and any associated config and stdout files, + to the specified directory. Updates the corresponding attributes on + this object to point at the new locations. :param dir: directory path See Also -------- - stanfit.RunSet.save_csvfiles cmdstanpy.from_csv """ - self.runset.save_csvfiles(dir) + dest = Path(dir) if dir is not None else Path.cwd() + dest.mkdir(parents=True, exist_ok=True) + + for attr in ('csv_file', 'config_file', 'stdout_file'): + src = getattr(self, attr) + if src is None: + continue + dst = dest / Path(src).name + if dst.exists(): + raise ValueError(f'File exists, not overwriting: {dst}') + shutil.move(src, dst) + setattr(self, attr, os.fspath(dst)) diff --git a/test/test_optimize.py b/test/test_optimize.py index 2f255468..4daf56fd 100644 --- a/test/test_optimize.py +++ b/test/test_optimize.py @@ -13,30 +13,19 @@ import numpy as np import pytest -from cmdstanpy.cmdstan_args import CmdStanArgs, OptimizeArgs from cmdstanpy.model import CmdStanModel -from cmdstanpy.stanfit import CmdStanMLE, RunSet, from_csv +from cmdstanpy.stanfit import CmdStanMLE, from_csv HERE = os.path.dirname(os.path.abspath(__file__)) DATAFILES_PATH = os.path.join(HERE, 'data') def test_instantiate() -> None: - stan = os.path.join(DATAFILES_PATH, 'optimize', 'rosenbrock.stan') - model = CmdStanModel(stan_file=stan) - args = OptimizeArgs(algorithm='Newton') - cmdstan_args = CmdStanArgs( - model_name=model.name, - model_exe=model.exe_file, - chain_ids=None, - data={}, - method_args=args, + csvfiles_path = os.path.join( + DATAFILES_PATH, 'optimize', 'rosenbrock_mle.csv' ) - runset = RunSet(args=cmdstan_args, chains=1) - runset._csv_files = [ - os.path.join(DATAFILES_PATH, 'optimize', 'rosenbrock_mle.csv') - ] - mle = CmdStanMLE(runset) + mle = from_csv(path=csvfiles_path) + assert isinstance(mle, CmdStanMLE) assert 'CmdStanMLE: model=rosenbrock' in repr(mle) assert 'method=optimize' in repr(mle) assert mle.column_names == ('lp__', 'x', 'y') @@ -664,7 +653,7 @@ def test_serialization() -> None: history_size=5, ) dumped = pickle.dumps(mle1) - shutil.rmtree(mle1.runset._outdir) + shutil.rmtree(os.path.dirname(mle1.csv_file)) mle2: CmdStanMLE = pickle.loads(dumped) np.testing.assert_array_equal( mle1.optimized_params_np, mle2.optimized_params_np From 34660248f07c7dd9b8c8c44776b8371c9d45a10a Mon Sep 17 00:00:00 2001 From: amas Date: Sat, 18 Apr 2026 14:06:29 -0400 Subject: [PATCH 16/16] Allow passing 'mode' directly to CmdStanLaplace.from_files --- cmdstanpy/model.py | 1 + cmdstanpy/stanfit/laplace.py | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cmdstanpy/model.py b/cmdstanpy/model.py index 2e23eeb9..f3fee26c 100644 --- a/cmdstanpy/model.py +++ b/cmdstanpy/model.py @@ -1793,6 +1793,7 @@ def laplace_sample( csv_file=runset.csv_files[0], config_file=runset.config_files[0], stdout_file=runset.stdout_files[0], + mode=cmdstan_mode, ) def _run_cmdstan( diff --git a/cmdstanpy/stanfit/laplace.py b/cmdstanpy/stanfit/laplace.py index c1277133..7913fc21 100644 --- a/cmdstanpy/stanfit/laplace.py +++ b/cmdstanpy/stanfit/laplace.py @@ -53,6 +53,7 @@ def from_files( csv_file: str | os.PathLike, config_file: str | os.PathLike, stdout_file: str | os.PathLike | None = None, + mode: CmdStanMLE | None = None, ) -> CmdStanLaplace: # Local import to avoid circular dependency with stanfit.__init__ from cmdstanpy.stanfit import from_csv @@ -61,9 +62,15 @@ def from_files( stan_config = parse_config(f.read(), LaplaceConfig) metadata = InferenceMetadata.from_csv(csv_file) - # temporary - should have done CmdStanMLE first - mode = from_csv(stan_config.method_config.mode, method='optimize') - assert isinstance(mode, CmdStanMLE) + if mode is None: + mle = from_csv(stan_config.method_config.mode, method='optimize') + if not isinstance(mle, CmdStanMLE): + raise TypeError( + f'Expected CmdStanMLE from mode file ' + f'{stan_config.method_config.mode!r}, got ' + f'{type(mle).__name__}' + ) + mode = mle return cls( metadata=metadata, csv_file=os.fspath(csv_file),