Managing custom classes, mat-files, and namespaces
    27 vues (au cours des 30 derniers jours)
  
       Afficher commentaires plus anciens
    
Say I have a (simple) custom class, defined with a classdef. Let's say it's defined in my_class.m
I then generate a bunch of objects of the class, and save the results to a matfile: my_data.mat.
I then want to reorganize my code, either by:
- renaming my class (but otherwise keeping the definition the same). Now I have my_class_ver1.m as the classdef.
- introducing namespaces. Here, I've moved the file, my_class.m, into a namespace directory, i.e.,: +ver1/my_class.m
Is there any way to provide a class (re)mapping when loading the existing my_data.mat file? As it stands, Matlab just loads the file as an int a uint32 array. For #2, just importing the namespace (import ver1.* or import ver1.my_class) does not work. 
0 commentaires
Réponse acceptée
  Steven Lord
    
      
 le 1 Août 2024
        For at least the first of those scenarios, class aliasing may be of use. That documentation page has a section "Renaming a Namespace" that may also address the second of your scenarios.
3 commentaires
  Steven Lord
    
      
 le 1 Août 2024
				
      Modifié(e) : Steven Lord
    
      
 le 1 Août 2024
  
			That page states "MATLAB recognizes both FirstName and SecondName as the same class as long as SecondName.m and the associated alias resources folder are in the same folder on the MATLAB path." so I believe you can move the resources directory elsewhere as long as you move SecondName.m alongside it.
[Removed something I'd written about FirstName.m after rereading the page, as it says "In fact, you must remove the original definition from the path so that MATLAB finds the newer alias instead of the older definition."]
Plus de réponses (1)
  Shubham
      
 le 1 Août 2024
        Hi John,
When you rename a class or move it into a namespace, MATLAB does not automatically recognize the new class definition when loading old .mat files containing objects of the original class. However, you can use MATLAB's matfile and loadobj functionalities to handle this situation.
Scenario 1: Renaming the Class
- Define the new class with a loadobj method: Create a loadobj method in your new class definition to handle the conversion from the old class to the new class.
% my_class_ver1.m
classdef my_class_ver1
    properties
        % Define your properties here
    end
    methods
        function obj = my_class_ver1()
            % Constructor code
        end
    end
    methods (Static)
        function obj = loadobj(a)
            if isa(a, 'my_class')
                % Convert from my_class to my_class_ver1
                obj = my_class_ver1();
                % Copy properties from a to obj as needed
            else
                obj = a;
            end
        end
    end
end
        2. Load the .mat file: When you load the .mat file, MATLAB will call the loadobj method to convert the objects.
data = load('my_data.mat');
% Access your objects from the data struct
Scenario 2: Introducing Namespaces
- Define the new class within the namespace with a loadobj method: Create a loadobj method in your new class definition within the namespace to handle the conversion.
% +ver1/my_class.m
classdef my_class
    properties
        % Define your properties here
    end
    methods
        function obj = my_class()
            % Constructor code
        end
    end
    methods (Static)
        function obj = loadobj(a)
            if isa(a, 'my_class')
                % Convert from my_class to ver1.my_class
                obj = ver1.my_class();
                % Copy properties from a to obj as needed
            else
                obj = a;
            end
        end
    end
end
        2. Load the .mat file: Similar to the first scenario, MATLAB will call the loadobj method to convert the objects when you load the file.
data = load('my_data.mat');
% Access your objects from the data struct
Important Points to consider:
- Ensure that the properties and methods of the new class match those of the old class to facilitate smooth conversion.
- You might need to manually copy the properties from the old object to the new object within the loadobj method.
- This approach requires you to have access to the old class definition during the transition period. If the old class definition is not available, you will need to manually handle the conversion.
3 commentaires
  Shubham
      
 le 1 Août 2024
				John,
You're right, the loadobj method of the new class won't be called directly if the .mat file contains objects of the old class, and MATLAB will look for the old class definition.
I think your approach is right that you can temporarily add the legacy class definitions to the path when loading and converting your data. 
An Idea for writing a code would look like this:
function new_data = load_and_convert(filename, legacy_path, new_class_map)
    % Temporarily add the legacy class definitions to the path
    old_path = addpath(legacy_path);
    % Load the data
    legacy_data = load(filename);
    % Convert the data
    new_data = structfun(@(obj) convert_legacy_object(obj, new_class_map), legacy_data, 'UniformOutput', false);
    % Restore the original path
    path(old_path);
end
function new_obj = convert_legacy_object(obj, new_class_map)
    % Check if the object is an instance of a legacy class
    old_class_name = class(obj);
    if isfield(new_class_map, old_class_name)
        new_class_name = new_class_map.(old_class_name);
        new_obj = feval(new_class_name); % Create an instance of the new class
        % Copy properties from the old object to the new object
        % Note: This assumes the properties have the same names and types
        props = properties(obj);
        for i = 1:numel(props)
            new_obj.(props{i}) = obj.(props{i});
        end
    else
        % If the object is not a legacy class, return it unchanged
        new_obj = obj;
    end
end
You can use it like this:
First, define the mapping of legacy class to new class:
new_class_map = struct();
new_class_map.my_class = 'my_class_ver1';
% Add more mappings as needed
Then, call the load_and_convert function:
legacy_path = '/path/to/legacy/classdefs';
filename = 'my_data.mat';
new_data = load_and_convert(filename, legacy_path, new_class_map);
This should let you load and convert legacy data without needing to keep the old class definitions permanently on the path. It handles multiple legacy classes with minimal changes. It might work in your case.
Voir également
Catégories
				En savoir plus sur Workspace Variables and MAT Files dans Help Center et File Exchange
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!


