function init_from_estim_params(o, estim_params_, M_, prior_trunc, Uniform)

% Initializes a dprior object from estim_params_ and M_ structures.
%
% Concatenates prior distribution parameters (shape, mean, std, bounds)
% and parameter names from the seven estimation-parameter blocks, then
% computes hyperparameters and bounds.
%
% INPUTS
% - o              [dprior]    object to initialize (handle, modified in place)
% - estim_params_  [struct]    estimation parameter specification
% - M_             [struct]    model structure (exo_names, endo_names, param_names)
% - prior_trunc    [double]    probability mass to exclude from tails

% Copyright © 2026 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare.  If not, see <https://www.gnu.org/licenses/>.

nvx = size(estim_params_.var_exo, 1);
nvn = size(estim_params_.var_endo, 1);
ncx = size(estim_params_.corrx, 1);
ncn = size(estim_params_.corrn, 1);
nsx = size(estim_params_.skew_exo, 1);
if isfield(estim_params_, 'endo_init_vals') && ~isempty(estim_params_.endo_init_vals)
    nendoinit = size(estim_params_.endo_init_vals, 1);
else
    nendoinit = 0;
end
np = size(estim_params_.param_vals, 1);

pshape = [];
o.p1 = [];
o.p2 = [];
o.p3 = [];
o.p4 = [];
o.name = {};

% Structural shock stderr
if nvx
    pshape = [pshape; estim_params_.var_exo(:,5)];
    o.p1 = [o.p1; estim_params_.var_exo(:,6)];
    o.p2 = [o.p2; estim_params_.var_exo(:,7)];
    o.p3 = [o.p3; estim_params_.var_exo(:,8)];
    o.p4 = [o.p4; estim_params_.var_exo(:,9)];
    for i = 1:nvx
        o.name{end+1,1} = sprintf('stderr %s', M_.exo_names{estim_params_.var_exo(i,1)});
    end
end

% Measurement error stderr
if nvn
    for i = 1:nvn
        o.name{end+1,1} = sprintf('stderr %s', M_.endo_names{estim_params_.var_endo(i,1)});
    end
    pshape = [pshape; estim_params_.var_endo(:,5)];
    o.p1 = [o.p1; estim_params_.var_endo(:,6)];
    o.p2 = [o.p2; estim_params_.var_endo(:,7)];
    o.p3 = [o.p3; estim_params_.var_endo(:,8)];
    o.p4 = [o.p4; estim_params_.var_endo(:,9)];
end

% Structural shock correlations
if ncx
    pshape = [pshape; estim_params_.corrx(:,6)];
    o.p1 = [o.p1; estim_params_.corrx(:,7)];
    o.p2 = [o.p2; estim_params_.corrx(:,8)];
    o.p3 = [o.p3; estim_params_.corrx(:,9)];
    o.p4 = [o.p4; estim_params_.corrx(:,10)];
    for i = 1:ncx
        o.name{end+1,1} = sprintf('corr %s, %s', ...
            M_.exo_names{estim_params_.corrx(i,1)}, ...
            M_.exo_names{estim_params_.corrx(i,2)});
    end
end

% Measurement error correlations
if ncn
    pshape = [pshape; estim_params_.corrn(:,6)];
    o.p1 = [o.p1; estim_params_.corrn(:,7)];
    o.p2 = [o.p2; estim_params_.corrn(:,8)];
    o.p3 = [o.p3; estim_params_.corrn(:,9)];
    o.p4 = [o.p4; estim_params_.corrn(:,10)];
    for i = 1:ncn
        o.name{end+1,1} = sprintf('corr %s, %s', ...
            M_.endo_names{estim_params_.corrn(i,1)}, ...
            M_.endo_names{estim_params_.corrn(i,2)});
    end
end

% Structural shock skewness
if nsx
    pshape = [pshape; estim_params_.skew_exo(:,5)];
    o.p1 = [o.p1; estim_params_.skew_exo(:,6)];
    o.p2 = [o.p2; estim_params_.skew_exo(:,7)];
    o.p3 = [o.p3; estim_params_.skew_exo(:,8)];
    o.p4 = [o.p4; estim_params_.skew_exo(:,9)];
    for i = 1:nsx
        o.name{end+1,1} = sprintf('skew %s', M_.exo_names{estim_params_.skew_exo(i,1)});
    end
end

% Endogenous initial states
if nendoinit
    pshape = [pshape; estim_params_.endo_init_vals(:,5)];
    o.p1 = [o.p1; estim_params_.endo_init_vals(:,6)];
    o.p2 = [o.p2; estim_params_.endo_init_vals(:,7)];
    o.p3 = [o.p3; estim_params_.endo_init_vals(:,8)];
    o.p4 = [o.p4; estim_params_.endo_init_vals(:,9)];
    for i = 1:nendoinit
        o.name{end+1,1} = sprintf('init %s', M_.endo_names{estim_params_.endo_init_vals(i,1)});
    end
end

% Structural parameters
if np
    pshape = [pshape; estim_params_.param_vals(:,5)];
    o.p1 = [o.p1; estim_params_.param_vals(:,6)];
    o.p2 = [o.p2; estim_params_.param_vals(:,7)];
    o.p3 = [o.p3; estim_params_.param_vals(:,8)];
    o.p4 = [o.p4; estim_params_.param_vals(:,9)];
    o.name = [o.name; M_.param_names(estim_params_.param_vals(:,1))];
end

if isempty(pshape)
    return
end

if any(o.p2 == 0)
    error('dprior: point priors (std=0) are not supported. Parameters: %s', ...
        strjoin(o.name(o.p2 == 0), ', '))
end

if nargin >= 5 && Uniform
    pshape = repmat(5, length(pshape), 1);
end

compute_hyperparameters(o, pshape, prior_trunc);
