Download src/ModelParams.php from danielpetrica/dochia-cycle-model: direct link, hf CLI and curl.
- Browser
- Download file 5.81 kB
-
https://huggingface.co/danielpetrica/dochia-cycle-model/resolve/main/src/ModelParams.php
- Command line
-
hf download hf://danielpetrica/dochia-cycle-model/src/ModelParams.php
-
curl -L -o ModelParams.php https://huggingface.co/danielpetrica/dochia-cycle-model/resolve/main/src/ModelParams.php
5.81 kB
| declare(strict_types=1); | |
| namespace Dochia; | |
| /** | |
| * Model parameters. Mirrors params/*.json so the PHP reference and the Python | |
| * reference use exactly the same numbers. | |
| */ | |
| final class ModelParams | |
| { | |
| public function __construct( | |
| public readonly string $version = 'dochia-v1-literature', | |
| public readonly float $popMean = 29.0, | |
| public readonly float $popBetweenSd = 3.5, | |
| public readonly float $withinSdPrior = 2.0, | |
| public readonly float $priorWeight = 4.0, | |
| public readonly float $minMean = 18.0, | |
| public readonly float $maxMean = 90.0, | |
| public readonly float $minWithinVar = 1.44, | |
| public readonly float $maxWithinVar = 36.0, | |
| public readonly float $lutealMean = 14.13, | |
| public readonly float $lutealSd = 1.41, | |
| public readonly int $fertileWindowDays = 6, | |
| public readonly float $ovulationSdFloor = 0.35, | |
| public readonly float $ovulationGridStep = 0.25, | |
| public readonly float $varianceBlend = 1.0, | |
| public readonly bool $momentMatch = false, | |
| public readonly float $tailProbBase = 0.10, | |
| public readonly float $tailProbMax = 0.40, | |
| public readonly float $tailProbSdGain = 0.06, | |
| public readonly float $tailProbRangeGain = 0.02, | |
| public readonly float $tailProbGapBonus = 0.20, | |
| public readonly float $tailShiftDays = 3.0, | |
| public readonly float $tailSdMultiplier = 2.2, | |
| public readonly float $trendEwma = 0.4, | |
| public readonly float $trendThreshold = 3.0, | |
| public readonly float $trendMaxShift = 3.0, | |
| public readonly float $bodyScale = 1.0, | |
| public readonly float $tailScaleLow = 1.0, | |
| public readonly float $tailScaleHigh = 1.0, | |
| public readonly float $tailAnchorLow = 0.10, | |
| public readonly float $tailAnchorHigh = 0.90, | |
| public readonly string $calibrationMethod = 'none', | |
| public readonly int $minLength = 15, | |
| public readonly int $maxLength = 120, | |
| public readonly int $hazardMaxDay = 120, | |
| public readonly int $abstainGapDays = 90, | |
| public readonly float $abstainRecentSd = 6.0, | |
| public readonly int $abstainMinCycles = 0, | |
| ) { | |
| } | |
| /** @param array<string, mixed> $raw */ | |
| public static function fromArray(array $raw): self | |
| { | |
| $pop = is_array($raw['population'] ?? null) ? $raw['population'] : []; | |
| $luteal = is_array($raw['luteal'] ?? null) ? $raw['luteal'] : []; | |
| $pred = is_array($raw['predictive'] ?? null) ? $raw['predictive'] : []; | |
| $cal = is_array($raw['calibration'] ?? null) ? $raw['calibration'] : []; | |
| $plaus = is_array($raw['plausible'] ?? null) ? $raw['plausible'] : []; | |
| $ov = is_array($raw['ovulation'] ?? null) ? $raw['ovulation'] : []; | |
| $ab = is_array($raw['abstain'] ?? null) ? $raw['abstain'] : []; | |
| $haz = is_array($raw['hazard'] ?? null) ? $raw['hazard'] : []; | |
| return new self( | |
| version: (string) ($raw['version'] ?? 'dochia-v1-literature'), | |
| popMean: (float) ($pop['mean'] ?? 29.0), | |
| popBetweenSd: (float) ($pop['between_sd'] ?? 3.5), | |
| withinSdPrior: (float) ($pop['within_sd_prior'] ?? 2.0), | |
| priorWeight: (float) ($pop['prior_weight'] ?? 4.0), | |
| minMean: (float) ($pop['min_mean'] ?? 18.0), | |
| maxMean: (float) ($pop['max_mean'] ?? 90.0), | |
| minWithinVar: (float) ($pop['min_within_var'] ?? 1.44), | |
| maxWithinVar: (float) ($pop['max_within_var'] ?? 36.0), | |
| lutealMean: (float) ($luteal['mean'] ?? 14.13), | |
| lutealSd: (float) ($luteal['sd'] ?? 1.41), | |
| fertileWindowDays: (int) ($raw['fertile_window_days'] ?? 6), | |
| ovulationSdFloor: (float) ($ov['sd_floor'] ?? 0.35), | |
| ovulationGridStep: (float) ($ov['grid_step'] ?? 0.25), | |
| varianceBlend: (float) ($pred['variance_blend'] ?? 1.0), | |
| momentMatch: (bool) ($pred['moment_match'] ?? false), | |
| tailProbBase: (float) ($pred['tail_prob_base'] ?? 0.10), | |
| tailProbMax: (float) ($pred['tail_prob_max'] ?? 0.40), | |
| tailProbSdGain: (float) ($pred['tail_prob_sd_gain'] ?? 0.06), | |
| tailProbRangeGain: (float) ($pred['tail_prob_range_gain'] ?? 0.02), | |
| tailProbGapBonus: (float) ($pred['tail_prob_gap_bonus'] ?? 0.20), | |
| tailShiftDays: (float) ($pred['tail_shift_days'] ?? 3.0), | |
| tailSdMultiplier: (float) ($pred['tail_sd_multiplier'] ?? 2.2), | |
| trendEwma: (float) ($pred['trend_ewma'] ?? 0.4), | |
| trendThreshold: (float) ($pred['trend_threshold'] ?? 3.0), | |
| trendMaxShift: (float) ($pred['trend_max_shift'] ?? 3.0), | |
| bodyScale: (float) ($cal['body_scale'] ?? 1.0), | |
| tailScaleLow: (float) ($cal['tail_scale_low'] ?? 1.0), | |
| tailScaleHigh: (float) ($cal['tail_scale_high'] ?? 1.0), | |
| tailAnchorLow: (float) ($cal['tail_anchor_low'] ?? 0.10), | |
| tailAnchorHigh: (float) ($cal['tail_anchor_high'] ?? 0.90), | |
| calibrationMethod: (string) ($cal['method'] ?? 'none'), | |
| minLength: (int) ($plaus['min'] ?? 15), | |
| maxLength: (int) ($plaus['max'] ?? 120), | |
| hazardMaxDay: (int) ($haz['max_day'] ?? 120), | |
| abstainGapDays: (int) ($ab['gap_days'] ?? 90), | |
| abstainRecentSd: (float) ($ab['recent_sd'] ?? 6.0), | |
| abstainMinCycles: (int) ($ab['min_cycles'] ?? 0), | |
| ); | |
| } | |
| public static function fromJson(string $path): self | |
| { | |
| $raw = json_decode((string) file_get_contents($path), true, 512, JSON_THROW_ON_ERROR); | |
| if (! is_array($raw)) { | |
| throw new \RuntimeException("Invalid model params JSON: {$path}"); | |
| } | |
| return self::fromArray($raw); | |
| } | |
| } | |