function measurement_info = set_measurement_info(M_, dr, options_)

% Builds the measurement_info struct carrying the index vectors describing
% how observed variables map into the restricted state vector and the
% steady-state vector.
%
% INPUTS
% - M_         [struct]   model description
% - dr         [struct]   decision rule (with inv_order_var, restrict_var_list)
% - options_   [struct]   options (uses varobs_id)
%
% OUTPUTS
% - measurement_info       [struct]   with fields
%     .mf0                 positions of state variables in restricted state vector
%     .mf1                 positions of observed variables in restricted state vector
%     .mf2                 positions of observed variables in decision-rule (expanded) state vector
%     .mfys                positions of observables in declaration order (oo_.dr.ys)

% 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/>.

k1 = options_.varobs_id';
if ~isempty(M_.filter_tunes)
    filter_tunes_endo_id = unique([M_.filter_tunes.endo_id]);
    k1 = [k1; filter_tunes_endo_id'];
end
var_obs_index_dr = dr.inv_order_var(k1)';

k2 = union(var_obs_index_dr, (M_.nstatic+1:M_.nstatic+M_.nspred)', 'rows');

[~, measurement_info.mf0] = ismember((M_.nstatic+1:M_.nstatic+M_.nspred)', k2);
[~, measurement_info.mf1] = ismember(var_obs_index_dr, k2);
measurement_info.mf2  = var_obs_index_dr;
measurement_info.mfys = k1;
