Results for
Function Syntax Design Conundrum
As a MATLAB enthusiast, I particularly enjoy Steve Eddins' blog and the cool things he explores. MATLAB's new argument blocks are great, but there's one frustrating limitation that Steve outlined beautifully in his blog post "Function Syntax Design Conundrum": cases where an argument should accept both enumerated values AND other data types.
Steve points out this could be done using the input parser, but I prefer having tab completions and I'm not a fan of maintaining function signature JSON files for all my functions.
Personal Context on Enumerations
To be clear: I honestly don't like enumerations in any way, shape, or form. One reason is how awkward they are. I've long suspected they're simply predefined constructor calls with a set argument, and I think that's all but confirmed here. This explains why I've had to fight the enumeration system when trying to take arguments of many types and normalize them to enumerated members, or have numeric values displayed as enumerated members without being recast to the superclass every operation.
The Discovery
While playing around extensively with metadata for another project, I realized (and I'm entirely unsure why it took so long) that the properties of a metaclass object are just, in many cases, the attributes of the classdef. In this realization, I found a solution to Steve's and my problem.
To be clear: I'm not in love with this solution. I would much prefer a better approach for allowing variable sets of membership validation for arguments. But as it stands, we don't have that, so here's an interesting, if incredibly hacky, solution.
If you call struct() on a metaclass object to view its hidden properties, you'll notice that in addition to the public "Enumeration" property, there's a hidden "Enumerable" property. They're both logicals, which implies they're likely functionally distinct. I was curious about that distinction and hoped to find some functionality by intentionally manipulating these values - and I did, solving the exact problem Steve mentions.
The Problem Statement
We have a function with an argument that should allow "dual" input types: enumerated values (Steve's example uses days of the week, mine uses the "all" option available in various dimension-operating functions) AND integers. We want tab completion for the enumerated values while still accepting the numeric inputs.
A Solution for Tab-Completion Supported Arguments
Rather than spoil Steve's blog post, let me use my own example: implementing a none() function. The definition is simple enough tf = ~any(A, dim); but when we wrap this in another function, we lose the tab-completion that any() provides for the dim argument (which gives you "all"). There's no great way to implement this as a function author currently - at least, that's well documented.
So here's my solution:
%% Example Function Implementation
% This is a simple implementation of the DimensionArgument class for implementing dual type inputs that allow enumerated tab-completion.
function tf = none(A, dim)
    arguments(Input)
        A logical;
        dim DimensionArgument = DimensionArgument(A, true);
    end
    % Simple example (notice the use of uplus to unwrap the hidden property)
    tf = ~any(A, +dim);
end
I like this approach because the additional work required to implement it, once the enumeration class is initialized, is minimal. Here are examples of function calls, note that the behavior parallels that of the MATLAB native-style tab-completion:
%% Test Data
% Simple logical array for testing
A = randi([0, 1], [3, 5], "logical");
%% Example function calls
tf = none(A, "all");     % This is the tab-completion it's 1:1 with MATLABs behavior
tf = none(A, [1, 2]);    % We can still use valid arguments (validated in the constructor)
tf = none(A);            % Showcase of the constructors use as a default argument generator
How It Works
What makes this work is the previously mentioned Enumeration attribute. By setting Enumeration = false while still declaring an enumeration block in the classdef file, we get the suggested members as auto-complete suggestions. As I hinted at, the value of enumerations (if you don't subclass a builtin and define values with the someMember (1) syntax) are simply arguments to constructor calls.
We also get full control over the storage and handling of the class, which means we lose the implicit storage that enumerations normally provide and are responsible for doing so ourselves - but I much prefer this. We can implement internal validation logic to ensure values that aren't in the enumerated set still comply with our constraints, and store the input (whether the enumerated member or alternative type) in an internal property.
As seen in the example class below, this maintains a convenient interface for both the function caller and author the only particuarly verbose portion is the conversion methods... Which if your willing to double down on the uplus unwrapping context can be avoided. What I have personally done is overload the uplus function to return the input (or perform the identity property) this allowss for the uplus to be used universally to unwrap inputs and for those that cant, and dont have a uplus definition, the value itself is just returned:
classdef(Enumeration = false) DimensionArgument % < matlab.mixin.internal.MatrixDisplay
    %DimensionArgument Enumeration class to provide auto-complete on functions needing the dimension type seen in all()
    %      Enumerations are just macros to make constructor calls with a known set of arguments. Declaring the 'all'
    %      enumeration member means this class can be set as the type for an input and the auto-completion for the given
    %      argument will show the enumeration members, allowing tab-completion. Declaring the Enumeration attribute of
    %      the class as false gives us control over the constructor and internal implementation. As such we can use it 
    %      to validate the numeric inputs, in the event the 'all' option was not used, and return an object that will 
    %      then work in place of valid dimension argument options.
    %% Enumeration members
    %      These are the auto-complete options you'd like to make available for the function signature for a given
    %      argument.
    enumeration(Description="Enumerated value for the dimension argument.")
        all
    end
    %% Properties
    %      The internal property allows the constructor's input to be stored; this ensures that the value is store and 
    %      that the output of the constructor has the class type so that the validation passes.
    %      (Constructors must return the an object of the class they're a constructor for)
    properties(Hidden, Description="Storage of the constructor input for later use.")
        Data = [];
    end
    %% Constructor method
    %      By the magic of declaring (Enumeration = false) in our class def arguments we get full control over the
    %      constructor implementation.
    %
    %      The second argument in this specific instance is to enable the argument's default value to be set in the
    %      arguments block itself as opposed to doing so in the function body... I like this better but if you didn't
    %      you could just as easily keep the constructor simple.
    methods
        function obj = DimensionArgument(A, Adim)
            %DimensionArgument Initialize the dimension argument.
            arguments
                % This will be the enumeration member name from auto-completed entries, or the raw user input if not
                % used.
                A = [];
                % A flag that indicates to create the value using different logic, in this case the first non-singleton
                % dimension, because this matches the behavior of functions like, all(), sum() prod(), etc.
                Adim (1, 1) logical = false;
            end
            if(Adim)
                % Allows default initialization from an input to match the aforemention function's behavior
                obj.Data = firstNonscalarDim(A);
            else
                % As a convenience for this style of implementation we can validate the input to ensure that since we're
                % suppose to be an enumeration, the input is valid
                DimensionArgument.mustBeValidMember(A);
                % Store the input in a hidden property since declaring ~Enumeration means we are responsible for storing
                % it.
                obj.Data = A;
            end
        end
    end
    %% Conversion methods
    %      Applies conversion to the data property so that implicit casting of functions works. Unfortunately most of
    %      the MathWorks defined functions use a different system than that employed by the arguments block, which
    %      defers to the class defined converter methods... Which is why uplus (+obj) has been defined to unwrap the
    %      data for ease of use.
    methods
        function obj = uplus(obj)
            obj = obj.Data;
        end
        function str = char(obj)
            str = char(obj.Data);
        end
        function str = cellstr(obj)
            str = cellstr(obj.Data);
        end
        function str = string(obj)
            str = string(obj.Data);
        end
        function A = double(obj)
            A = double(obj.Data);
        end
        function A = int8(obj)
            A = int8(obj.Data);
        end
        function A = int16(obj)
            A = int16(obj.Data);
        end
        function A = int32(obj)
            A = int32(obj.Data);
        end
        function A = int64(obj)
            A = int64(obj.Data);
        end
    end
    %% Validation methods
    %      These utility methods are for input validation
    methods(Static, Access = private)
        function tf = isValidMember(obj)
            %isValidMember Checks that the input is a valid dimension argument.
            tf = (istext(obj) && all(obj == "all", "all")) || (isnumeric(obj) && all(isint(obj) & obj > 0, "all"));
        end
        function mustBeValidMember(obj)
            %mustBeValidMember Validates that the input is a valid dimension argument for the dim/dimVec arguments.
            if(~DimensionArgument.isValidMember(obj))
                exception("JB:DimensionArgument:InvalidInput", "Input must be an integer value or the term 'all'.")
            end
        end
    end
    %% Convenient data display passthrough
    methods
        function disp(obj, name)
            arguments
                obj DimensionArgument
                name string {mustBeScalarOrEmpty} = [];
            end
            % Dispatch internal data's display implementation
            display(obj.Data, char(name));
        end
    end
end
In the event you'd actually play with theres here are the function definitions for some of the utility functions I used in them, including my exception would be a pain so i wont, these cases wont use it any...
% Far from my definition isint() but is consistent with mustBeInteger() for real numbers but will suffice for the example
function tf = isint(A)
    arguments
        A {mustBeNumeric(A)};
    end
    tf = floor(A) == A
end
% Sort of the same but its fine
function dim = firstNonscalarDim(A)
    arguments
        A 
    end
    dim = [find(size(A) > 1, 1), 0];
    dim(1) = dim(1);
end
Hello MATLAB Central, this is my first article.
My name is Yann. And I love MATLAB.
I also love HTTP (i know, weird fetish)
So i started a conversation with ChatGPT about it:
gitclone('https://github.com/yanndebray/HTTP-with-MATLAB');
cd('HTTP-with-MATLAB')
http_with_MATLAB
I'm not sure that this platform is intended to clone repos from github, but i figured I'd paste this shortcut in case you want to try out my live script http_with_MATLAB.m
A lot of what i program lately relies on external web services (either for fetching data, or calling LLMs).
So I wrote a small tutorial of the 7 or so things I feel like I need to remember when making HTTP requests in MATLAB.
Let me know what you think
Hello MATLAB Central community,
My name is Yann. And I love MATLAB. I also love Python ... 🐍 (I know, not the place for that).
I recently decided to go down the rabbit hole of AI. So I started benchmarking deep learning frameworks on basic examples. Here is a recording of my experiment: 
Happy to engage in the debate. What do you think?

I designed and stitched this last week! It uses a total of 20 DMC thread colors, and I frequently stitched with two colors at once to create the gradient.
Did you know that function double with string vector input significantly outperforms str2double with the same input:
x = rand(1,50000);
t = string(x);
tic; str2double(t); toc
tic; I1 = str2double(t); toc
tic; I2 = double(t); toc
isequal(I1,I2)
Recently I needed to parse numbers from text. I automatically tried to use str2double. However, profiling revealed that str2double was the main bottleneck in my code. Than I realized that there is a new note (since R2024a) in the documentation of str2double:
"Calling string and then double is recommended over str2double because it provides greater flexibility and allows vectorization. For additional information, see Alternative Functionality."
Large Language Models (LLMs) with MATLAB was updated again today to support the newly released OpenAI models GPT-5, GPT-5 mini, GPT-5 nano, GPT-5 chat, o3, and o4-mini. When you create an openAIChat object, set the ModelName name-value argument to "gpt-5", "gpt-5-mini", "gpt-5-nano", "gpt-5-chat-latest", "o4-mini", or "o3".
This is version 4.4.0 of this free MATLAB add-on that lets you interact with LLMs on MATLAB. The release notes are at Release v4.4.0: Support for GPT-5, o3, o4-mini · matlab-deep-learning/llms-with-matlab 
Hey cody fellows :-) !
I recently created two problem groups, but as you can see I struggle to set their cover images :
What is weird given : 
- I already did it successfully twice in the past for my previous groups ;
- If you take one problem specifically, Problem 60984. Mesh the icosahedron for instance, you can normally see the icon of the cover image in the top right hand corner, can't you ?
- I always manage to set cover images to my contributions (mostly in the filexchange).
I already tried several image formats, included .png 4/3 ratio, but still the cover images don't set.
Could you please help me to correctly set my cover images ?
Thank you.
Nicolas
Resharing a fun short video explaining what MATLAB is. :)



t = turtle(); % Start a turtle
t.forward(100); % Move forward by 100
t.backward(100); % Move backward by 100
t.left(90); % Turn left by 90 degrees
t.right(90); % Tur right by 90 degrees
t.goto(100, 100); % Move to (100, 100)
t.turnto(90); % Turn to 90 degrees, i.e. north
t.speed(1000); % Set turtle speed as 1000 (default: 500)
t.pen_up(); % Pen up. Turtle leaves no trace.
t.pen_down(); % Pen down. Turtle leaves a trace again.
t.color('b'); % Change line color to 'b'
t.begin_fill(FaceColor, EdgeColor, FaceAlpha); % Start filling
t.end_fill(); % End filling
t.change_icon('person.png'); % Change the icon to 'person.png'
t.clear(); % Clear the Axes
classdef turtle < handle
    properties (GetAccess = public, SetAccess = private)
        x = 0
        y = 0
        q = 0
    end
    properties (SetAccess = public)
        speed (1, 1) double = 500
    end
    properties (GetAccess = private)
        speed_reg = 100
        n_steps = 20
        ax
        l
        ht
        im
        is_pen_up = false
        is_filling = false
        fill_color
        fill_alpha
    end
    methods
        function obj = turtle()
            figure(Name='MATurtle', NumberTitle='off')
            obj.ax = axes(box="on");
            hold on,
            obj.ht = hgtransform();
            icon = flipud(imread('turtle.png'));
            obj.im = imagesc(obj.ht, icon, ...
                XData=[-30, 30], YData=[-30, 30], ...
                AlphaData=(255 - double(rgb2gray(icon)))/255);
            obj.l = plot(obj.x, obj.y, 'k');
            obj.ax.XLim = [-500, 500];
            obj.ax.YLim = [-500, 500];
            obj.ax.DataAspectRatio = [1, 1, 1];
            obj.ax.Toolbar.Visible = 'off';
            disableDefaultInteractivity(obj.ax);
        end
        function home(obj)
            obj.x = 0;
            obj.y = 0;
            obj.ht.Matrix = eye(4);
        end
        function forward(obj, dist)
            obj.step(dist);
        end
        function backward(obj, dist)
            obj.step(-dist)
        end
        function step(obj, delta)
            if numel(delta) == 1
                delta = delta*[cosd(obj.q), sind(obj.q)];
            end
            if obj.is_filling
                obj.fill(delta);
            else
                obj.move(delta);
            end            
        end
        function goto(obj, x, y)
            dx = x - obj.x;
            dy = y - obj.y;
            obj.turnto(rad2deg(atan2(dy, dx)));
            obj.step([dx, dy]);
        end
        function left(obj, q)
            obj.turn(q);
        end
        function right(obj, q)
            obj.turn(-q);
        end
        function turnto(obj, q)
            obj.turn(obj.wrap_angle(q - obj.q, -180));
        end
        function pen_up(obj)
            if obj.is_filling
                warning('not available while filling')
                return
            end
            obj.is_pen_up = true;
        end
        function pen_down(obj, go)
            if obj.is_pen_up
                if nargin == 1
                    obj.l(end+1) = plot(obj.x, obj.y, Color=obj.l(end).Color);
                else
                    obj.l(end+1) = go;
                end
                uistack(obj.ht, 'top')
            end
            obj.is_pen_up = false;
        end
        function color(obj, line_color)
            if obj.is_filling
                warning('not available while filling')
                return
            end
            obj.pen_up();
            obj.pen_down(plot(obj.x, obj.y, Color=line_color));
        end
        function begin_fill(obj, FaceColor, EdgeColor, FaceAlpha)
            arguments
                obj
                FaceColor = [.6, .9, .6];
                EdgeColor = [0 0.4470 0.7410];
                FaceAlpha = 1;
            end
            if obj.is_filling
                warning('already filling')
                return
            end
            obj.fill_color = FaceColor;
            obj.fill_alpha = FaceAlpha;
            obj.pen_up();
            obj.pen_down(patch(obj.x, obj.y, [1, 1, 1], ...
                EdgeColor=EdgeColor, FaceAlpha=0));
            obj.is_filling = true;
        end
        function end_fill(obj)
            if ~obj.is_filling
                warning('not filling now')
                return
            end
            obj.l(end).FaceColor = obj.fill_color;
            obj.l(end).FaceAlpha = obj.fill_alpha;
            obj.is_filling = false;
        end
        function change_icon(obj, filename)
            icon = flipud(imread(filename));
            obj.im.CData = icon;
            obj.im.AlphaData = (255 - double(rgb2gray(icon)))/255;
        end
        function clear(obj)
            obj.x = 0;
            obj.y = 0;
            delete(obj.ax.Children(2:end));
            obj.l = plot(0, 0, 'k');
            obj.ht.Matrix = eye(4);
        end
    end
    methods (Access = private)
        function animated_step(obj, delta, q, initFcn, updateFcn)
            arguments
                obj
                delta
                q
                initFcn = @() []
                updateFcn = @(~, ~) []
            end
            dx = delta(1)/obj.n_steps;
            dy = delta(2)/obj.n_steps;
            dq = q/obj.n_steps;
            pause_duration = norm(delta)/obj.speed/obj.speed_reg;
            initFcn();
            for i = 1:obj.n_steps
                updateFcn(dx, dy);
                obj.ht.Matrix = makehgtform(...
                    translate=[obj.x + dx*i, obj.y + dy*i, 0], ...
                    zrotate=deg2rad(obj.q + dq*i));
                pause(pause_duration)
                drawnow limitrate
            end
            obj.x = obj.x + delta(1);
            obj.y = obj.y + delta(2);
        end
        function obj = turn(obj, q)
            obj.animated_step([0, 0], q);
            obj.q = obj.wrap_angle(obj.q + q, 0);
        end
        function move(obj, delta)
            initFcn = @() [];
            updateFcn = @(dx, dy) [];
            if ~obj.is_pen_up
                initFcn = @() initializeLine();
                updateFcn = @(dx, dy) obj.update_end_point(obj.l(end), dx, dy);
            end
            function initializeLine()
                obj.l(end).XData(end+1) = obj.l(end).XData(end);
                obj.l(end).YData(end+1) = obj.l(end).YData(end);
            end
            obj.animated_step(delta, 0, initFcn, updateFcn);
        end
        function obj = fill(obj, delta)
            initFcn = @() initializePatch();
            updateFcn = @(dx, dy) obj.update_end_point(obj.l(end), dx, dy);
            function initializePatch()
                obj.l(end).Vertices(end+1, :) = obj.l(end).Vertices(end, :);
                obj.l(end).Faces = 1:size(obj.l(end).Vertices, 1);
            end
            obj.animated_step(delta, 0, initFcn, updateFcn);
        end
    end
    methods (Static, Access = private)
        function update_end_point(l, dx, dy)
            l.XData(end) = l.XData(end) + dx;
            l.YData(end) = l.YData(end) + dy;
        end
        function q = wrap_angle(q, min_angle)
            q = mod(q - min_angle, 360) + min_angle;
        end
    end
end
I would like to zoom directly on the selected region when using  on my image created with image or imagesc. First of all, I would recommend using image or imagesc and not imshow for this case, see comparison here: Differences between imshow() and image()? However when zooming Stretch-to-Fill behavior happens and I don't want that. Try range zoom to image generated by this code:
 on my image created with image or imagesc. First of all, I would recommend using image or imagesc and not imshow for this case, see comparison here: Differences between imshow() and image()? However when zooming Stretch-to-Fill behavior happens and I don't want that. Try range zoom to image generated by this code:
 on my image created with image or imagesc. First of all, I would recommend using image or imagesc and not imshow for this case, see comparison here: Differences between imshow() and image()? However when zooming Stretch-to-Fill behavior happens and I don't want that. Try range zoom to image generated by this code:
 on my image created with image or imagesc. First of all, I would recommend using image or imagesc and not imshow for this case, see comparison here: Differences between imshow() and image()? However when zooming Stretch-to-Fill behavior happens and I don't want that. Try range zoom to image generated by this code:fig = uifigure;
ax = uiaxes(fig);
im = imread("peppers.png");
h = imagesc(im,"Parent",ax);
axis(ax,'tight', 'off')
I can fix that with manualy setting data aspect ratio:
daspect(ax,[1 1 1])
However, I need this code to run automatically after zooming. So I create zoom object and ActionPostCallback which is called everytime after I zoom, see zoom - ActionPostCallback. 
z = zoom(ax);
z.ActionPostCallback = @(fig,ax) daspect(ax.Axes,[1 1 1]);
If you need, you can also create ActionPreCallback which is called everytime before I zoom, see zoom - ActionPreCallback.
z.ActionPreCallback = @(fig,ax) daspect(ax.Axes,'auto');
Code written and run in R2025a.
I am thrilled python interoperability now seems to work for me with my APPLE M1 MacBookPro and MATLAB V2025a. The available instructions are still, shall we say, cryptic. Here is a summary of my interaction with GPT 4o to get this to work.
===========================================================
MATLAB R2025a + Python (Astropy) Integration on Apple Silicon (M1/M2/M3 Macs)
===========================================================
Author: D. Carlsmith, documented with ChatGPT
Last updated: July 2025
This guide provides full instructions, gotchas, and workarounds to run Python 3.10 with MATLAB R2025a (Apple Silicon/macOS) using native ARM64 Python and calling modules like Astropy, Numpy, etc. from within MATLAB.
===========================================================
Overview
===========================================================
- MATLAB R2025a on Apple Silicon (M1/M2/M3) runs as "maca64" (native ARM64).
- To call Python from MATLAB, the Python interpreter must match that architecture (ARM64).
- Using Intel Python (x86_64) with native MATLAB WILL NOT WORK.
- The cleanest solution: use Miniforge3 (Conda-forge's lightweight ARM64 distribution).
===========================================================
1. Install Miniforge3 (ARM64-native Conda)
===========================================================
In Terminal, run:
    curl -LO https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-arm64.sh
    bash Miniforge3-MacOSX-arm64.sh
Follow prompts:
- Press ENTER to scroll through license.
- Type "yes" when asked to accept the license.
- Press ENTER to accept the default install location: ~/miniforge3
- When asked:
    Do you wish to update your shell profile to automatically initialize conda? [yes|no]
  Type: yes
===========================================================
2. Restart Terminal and Create a Python Environment for MATLAB
===========================================================
Run the following:
    conda create -n matlab python=3.10 astropy numpy -y
    conda activate matlab
Verify the Python path:
    which python
Expected output:
    /Users/YOURNAME/miniforge3/envs/matlab/bin/python
===========================================================
3. Verify Python + Astropy From Terminal
===========================================================
Run:
    python -c "import astropy; print(astropy.__version__)"
Expected output:
    6.x.x  (or similar)
===========================================================
4. Configure MATLAB to Use This Python
===========================================================
In MATLAB R2025a (Apple Silicon):
    clear classes
    pyenv('Version', '/Users/YOURNAME/miniforge3/envs/matlab/bin/python')
    py.sys.version
You should see the Python version printed (e.g. 3.10.18). No error means it's working.
===========================================================
5. Gotchas and Their Solutions
===========================================================
❌ Error: Python API functions are not available
→ Cause: Wrong architecture or broken .dylib
→ Fix: Use Miniforge ARM64 Python. DO NOT use Intel Anaconda.
❌ Error: Invalid text character (↑ points at __version__)
→ Cause: MATLAB can’t parse double underscores typed or pasted
→ Fix: Use: py.getattr(module, '__version__')
❌ Error: Unrecognized method 'separation' or 'sec'
→ Cause: MATLAB can't reflect dynamic Python methods
→ Fix: Use: py.getattr(obj, 'method')(args)
===========================================================
6. Run Full Verification in MATLAB
===========================================================
Paste this into MATLAB:
    % Set environment
    clear classes
    pyenv('Version', '/Users/YOURNAME/miniforge3/envs/matlab/bin/python');
    % Import modules
    coords = py.importlib.import_module('astropy.coordinates');
    time_mod = py.importlib.import_module('astropy.time');
    table_mod = py.importlib.import_module('astropy.table');
    % Astropy version
    ver = char(py.getattr(py.importlib.import_module('astropy'), '__version__'));
    disp(['Astropy version: ', ver]);
    % SkyCoord angular separation
    c1 = coords.SkyCoord('10h21m00s', '+41d12m00s', pyargs('frame', 'icrs'));
    c2 = coords.SkyCoord('10h22m00s', '+41d15m00s', pyargs('frame', 'icrs'));
    sep_fn = py.getattr(c1, 'separation');
    sep = sep_fn(c2);
    arcsec = double(sep.to('arcsec').value);
    fprintf('Angular separation = %.3f arcsec\n', arcsec);
    % Time difference in seconds
    Time = time_mod.Time;
    t1 = Time('2025-01-01T00:00:00', pyargs('format','isot','scale','utc'));
    t2 = Time('2025-01-02T00:00:00', pyargs('format','isot','scale','utc'));
    dt = py.getattr(t2, '__sub__')(t1);
    seconds = double(py.getattr(dt, 'sec'));
    fprintf('Time difference = %.0f seconds\n', seconds);
    % Astropy table display
    tbl = table_mod.Table(pyargs('names', {'a','b'}, 'dtype', {'int','float'}));
    tbl.add_row({1, 2.5});
    tbl.add_row({2, 3.7});
    disp(tbl);
===========================================================
7. Optional: Automatically Configure Python in startup.m
===========================================================
To avoid calling pyenv() every time, edit your MATLAB startup:
    edit startup.m
Add:
    try
        pyenv('Version', '/Users/YOURNAME/miniforge3/envs/matlab/bin/python');
    catch
        warning("Python already loaded.");
    end
===========================================================
8. Final Notes
===========================================================
- This setup avoids all architecture mismatches.
- It uses a clean, minimal ARM64 Python that integrates seamlessly with MATLAB.
- Do not mix Anaconda (Intel) with Apple Silicon MATLAB.
- Use py.getattr for any Python attribute containing underscores or that MATLAB can't resolve.
You can now run NumPy, Astropy, Pandas, Astroquery, Matplotlib, and more directly from MATLAB.
===========================================================

Hey MATLAB enthusiasts!
I just stumbled upon this hilariously effective GitHub repo for image deformation using Moving Least Squares (MLS)—and it’s pure gold for anyone who loves playing with pixels! 🎨✨
- Real-Time Magic ✨
- Precomputes weights and deformation data upfront, making it blazing fast for interactive edits. Drag control points and watch the image warp like rubber! (2)
- Supports affine, similarity, and rigid deformations—because why settle for one flavor of chaos?
- Single-File Simplicity 🧩
- All packed into one clean MATLAB class (mlsImageWarp.m).
- Endless Fun Use Cases 🤹
- Turn your pet’s photo into a Picasso painting.
- "Fix" your friend’s smile... aggressively.
- Animate static images with silly deformations (1).
Try the Demo!
                    You are not a jedi yet !
                
 
                
                    20%
                
  
            
                    We not grant u the rank of master !
                
 
                
                    0%
                
  
            
                    Ready are u? What knows u of ready?
                
 
                
                    0%
                
  
            
                    May the Force be with you !
                
 
                
                    80%
                
  
            
            5 votes
        
    I saw this on Reddit and thought of the past mini-hack contests. We have a few folks here who can do something similar with MATLAB.

I had an error in the web version Matlab, so I exited and came back in, and this boy was plotted.
It seems like the financial news is always saying the stock market is especially volatile now.  But is it really?  This code will show you the daily variation from the prior day.  You can see that the average daily change from one day to the next is 0.69%.  So any change in the stock market from the prior day less than about 0.7% or 1% is just normal "noise"/typical variation.  You can modify the code to adjust the starting date for the analysis.  Data file (Excel workbook) is attached (hopefully - I attached it twice but it's not showing up yet).

% Program to plot the Dow Jones Industrial Average from 1928 to May 2025, and compute the standard deviation.
% Data available for download at https://finance.yahoo.com/quote/%5EDJI/history?p=%5EDJI
% Just set the Time Period, then find and click the download link, but you ned a paid version of Yahoo.
%
% If you have a subscription for Microsoft Office 365, you can also get historical stock prices.
% Reference: https://support.microsoft.com/en-us/office/stockhistory-function-1ac8b5b3-5f62-4d94-8ab8-7504ec7239a8#:~:text=The%20STOCKHISTORY%20function%20retrieves%20historical,Microsoft%20365%20Business%20Premium%20subscription.
% For example put this in an Excel Cell
% =STOCKHISTORY("^DJI", "1/1/2000", "5/10/2025", 0, 1, 0, 1,2,3,4, 5)
% and it will fill out a table in Excel
%====================================================================================================================
clc;    % Clear the command window.
close all;  % Close all figures (except those of imtool.)
imtool close all;  % Close all imtool figures if you have the Image Processing Toolbox.
clear;  % Erase all existing variables. Or clearvars if you want.
workspace;  % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 14;
filename = 'Dow Jones Industrial Index.xlsx';
data = readtable(filename);
% Date,Close,Open,High,Low,Volume
dates = data.Date;
closing = data.Close;
volume = data.Volume;
% Define start date and stop date
startDate = datetime(2011,1,1)
stopDate = dates(end)
selectedDates = dates > startDate;
% Extract those dates:
dates = dates(selectedDates);
closing = closing(selectedDates);
volume = volume(selectedDates);
% Plot Volume
hFigVolume = figure('Name', 'Daily Volume');
plot(dates, volume, 'b-');
grid on;
xticks(startDate:calendarDuration(5,0,0):stopDate)
title('Dow Jones Industrial Average Volume', 'FontSize', fontSize);
hFig = figure('Name', 'Daily Standard Deviation');
subplot(3, 1, 1);
plot(dates, closing, 'b-');
xticks(startDate:calendarDuration(5,0,0):stopDate)
drawnow;
grid on;
caption = sprintf('Dow Jones Industrial Average from %s through %s', dates(1), dates(end));
title(caption, 'FontSize', fontSize);
% Get the average change from one trading day to the next.
diffs = 100 * abs(closing(2:end) - closing(1:end-1)) ./ closing(1:end-1);
subplot(3, 1, 2);
averageDailyChange = mean(diffs)
% Looks pretty noisy so let's smooth it for a nicer display.
numWeeks = 4;
diffs = sgolayfilt(diffs, 2, 5*numWeeks+1);
plot(dates(2:end), diffs, 'b-');
grid on;
xticks(startDate:calendarDuration(5,0,0):stopDate)
hold on;
line(xlim, [averageDailyChange, averageDailyChange], 'Color', 'r', 'LineWidth', 2);
ylabel('Percentage', 'FontSize', fontSize);
caption = sprintf('Day-to-Day Change Percentage.  Average Daily Change (from prior day) = %.2f%%', averageDailyChange);
title(caption, 'FontSize', fontSize);
drawnow;
% Get the stddev over a 5 trading day window.
sd = stdfilt(closing, ones(5, 1));
% Get it relative to the magnitude.
sd = sd ./ closing * 100;
averageVariation = mean(sd)
numWeeks = 2;
% Looks pretty noisy so let's smooth it for a nicer display.
sd = sgolayfilt(sd, 2, 5*numWeeks+1);
% Plot it.
subplot(3, 1, 3);
plot(dates, sd, 'b-');
grid on;
xticks(startDate:calendarDuration(5,0,0):stopDate)
hold on;
line(xlim, [averageVariation, averageVariation], 'Color', 'r', 'LineWidth', 2);
ylabel('Percentage', 'FontSize', fontSize);
caption = sprintf('Weekly Standard Deviation, Averaged Over %d Weeks (%d trading days).  Mean SD = %.2f', ...
    numWeeks, 5*numWeeks+1, averageVariation);
title(caption, 'FontSize', fontSize);
% Maximize figure window.
g = gcf;
g.WindowState = 'maximized';
I like this problem by James and have solved it in several ways. A solution by Natalie impressed me and introduced me to a new function conv2. However, it occured to me that the numerous test for the problem only cover cases of square matrices. My original solutions, and Natalie's, did niot work on rectangular matrices. I have now produced a solution which works on rectangular matrices. Thanks for this thought provoking problem James.
I wanted to turn a Markdown nested list of text labels:
- A
    - B
        - C
    - D
        - G
        - H
- E
- F
    - Q
into a directed graph, like this:

Here is my blog post with some related tips for doing this, including text I/O, text processing with patterns, and directed graph operations and visualization.
Large Languge model with MATLAB, a free add-on that lets you access LLMs from OpenAI, Azure, amd Ollama (to use local models) on MATLAB, has been updated to support OpenAI GPT-4.1, GPT-4.1 mini, and GPT-4.1 nano. 
According to OpenAI, "These models outperform GPT‑4o and GPT‑4o mini across the board, with major gains in coding and instruction following. They also have larger context windows—supporting up to 1 million tokens of context—and are able to better use that context with improved long-context comprehension."
What would you build with the latest update?














