Mostrando las entradas con la etiqueta MATLAB. Mostrar todas las entradas
Mostrando las entradas con la etiqueta MATLAB. Mostrar todas las entradas

lunes, 4 de enero de 2016

Ordenar matrices en MATLAB


El ordenamiento de datos es una tarea muy común dentro del mundo de la informática y en la programación científica. Se ordenan datos para realizar análisis cualitativos, para la visualización gráfica o cualquier otro procedimiento que requiera datos organizados. Los datos se pueden organizar por criterios diversos, pero en esta sección veremos simplemente como ordenarlos de acuerdo a su valor numérico, en orden ascendente o descendente.

Generalmente los algoritmos de ordenamiento forman parte de los cursos básicos de programación y algorítmica, dada su importancia mencionada con anterioridad. Se estudian por lo general métodos tradicionales como: el método de ordenamiento por selección, ordenamiento por inserción y ordenamiento por combinación.

Ahora, enseguida sólo veremos cómo implementar el método de ordenamiento por selección, puesto que resulta muy didáctico y fácil de programar, y como no estamos en disposición de reinventar la rueda,  entonces, para el ordenamiento de las matrices y/o vectores utilizaremos la función sort incluida en el núcleo de MATLAB, y el resto de métodos de ordenamiento tradicionales se propondrán como ejercicios al final de este capítulo.

Así pues, puede revisar el siguiente código:

X=input('Inserte un vector: ');
for i=1:length(X)
   [menor,k]=min(X(i:end));
   X((i-1)+k)=X(i);
   X(i)=menor;
end
disp(X); % Vector ordenado

El programa anterior tiene como punto de entrada un vector introducido por el usuario de forma interactiva y que puede contener valores numéricos cualesquiera. Una vez se ha introducido el vector, se utiliza un bucle for cuyo recorrido está determinado por la longitud del vector, y en cada iteración se busca el elemento de menor valor ubicado en el sub-arreglo $X(i,i+1,...,n-1,n)$ donde i es el i-ésimo elemento dado por el número de iteración actual, y n el último elemento del arreglo, la función min de MATLAB devuelve dos resultados: el valor y la posición del mínimo encontrado, con ello se procede a intercambiar el valor mínimo encontrado con aquel ubicado en la i-ésima posición del arreglo. Y así, cuando se hayan ejecutado tantas iteraciones como elementos tenga el vector, se habrán ordenado en forma ascendente dichos valores. Si por el contrario necesita ordenar un vector en forma descendente, simplemente habrá de sustituir la función min por max, es decir, buscar un valor máximo en lugar del mínimo en cada iteración, o bien, reutilizar el mismo algoritmo y audazmente rotar el vector resultante mediante la función fliplr.

Como se mencionó, en MATLAB todo lo anterior puede reemplazarse utilizando la función sort.
cuya sintaxis más general es:

>> sort(X, dim, mod);

Donde X es la matriz o vector a ordenar, dim es un escalar que puede ser 1 (columnas) o 2 (filas) y que representa la dimensión de referencia sobre la cual se ordenará, y mod es el modo de ordenamiento, que puede ser 'ascend' (menor a mayor) o 'descend' (mayor a menor), por defecto las matrices o vectores se ordenan en forma ascendente. 

Véanse los ejemplos siguientes:

>> X=[10 2 8 17 20 1 4 8 9];
>> sort(X)
ans =
    1     2     4     8     8     9    10    17    20
>> M=randi(10,5)
M =
    3    10     3     2     8
    8     7     2    10     6
    9     4     9     5     5
    1    10     8     3    10
    4     8     4     5     6
>> sort(M,1) % Ordenada por columnas
ans =
    1     4     2     2     5
    3     7     3     3     6
    4     8     4     5     6
    8    10     8     5     8
    9    10     9    10    10
>> sort(M,2) % Ordenada por filas
ans =
    2     3     3     8    10
    2     6     7     8    10
    4     5     5     9     9
    1     3     8    10    10
    4     4     5     6     8

sábado, 19 de diciembre de 2015

Exportar datos de una uitable MATLAB a una tabla en archivo HTML: table2html.


La función table2html que se anexa a continuación permite exportar los datos contenidos en una uitable MATLAB a una tabla contenida en un archivo HTML. La utilidad puede ser en aquellos casos donde se requiera elaborar reportes con datos de salida contenidos en una uitable, evidentemente la opción "Publish" de MATLAB permite elaborar un reporte de cualquier script, pero incluye solamente capturas de los objetos gráficos. Esta función se puede adaptar para que en lugar de devolver un archivo HTML completo, solamente devuelva el código HTML de la tabla e incrustar esto posteriormente en un reporte HTML creado de manera independiente.

function table2html(hTab,filename,opts)
% TABLE2HTML(hTab,filename)
%
%   hTab       - Handle de la uitable a "exportar"
%   filename   - Nombre del archivo de salida (*.html)
%   opts       - Estructura de opciones adicionales (Veáse Opciones)
%
% Exporta una uitable como tabla en un archivo en formato HTML
%
% EJEMPLO:
%
%       f = figure();
%       hTab = uitable(f,'Data',rand(10));
%       table2html(hTab,'miejemplo.html');
%
%
% OPCIONES (OPTS)
%    
%      PageTitle   -  Título de la página web
%      TableTitle  -  Título de la tabla
%      BgColor     -  Color de fondo de la tabla
%      FontName    -  Tipo de fuente utilizada
%      BorderWidth -  Ancho del borde de la tabla
%     
% EJEMPLO CON OPCIONES:
%
%       f = figure();
%       opts.PageTitle = 'Ejemplo';
%       opts.TableTitle = 'Mi tabla';
%       opts.BgColor = '#00FF00';
%       opts.FontName = 'Arial';
%       opts.BorderWidth = '3';
%       hTab = uitable(f,'Data',rand(10));
%       table2html(hTab,'miejemplo.html',opts);
%             
%
%    -------------------------------
%       Ver. 0.0.1  ||  25/10/2014
%           Jorge De Los Santos
%        delossantosmfq@gmail.com
%        http://labdls.blogspot.mx
%              MIT License
%    -------------------------------

if nargin < 1
    % En caso de no especificarse argumentos se "busca" un elemento del
    % tipo uitable y se asigna como archivo de salida a html/utitled.html
    hTab = findobj('type','uitable');
    if ~isempty(hTab)
        filename = 'html/untitled.html';
    else
        error('No existe elemento uitable disponible');
    end
end

if ~strcmp(get(hTab,'type'),'uitable')
    % Verificando que la referencia sea tipo "uitable"
    error('La referencia debe ser de tipo uitable');
end

% ========================== OPCIONES ===================================
fields_opts = {'PageTitle',   'Sin título',;
               'TableTitle',  '<b>Tabla 1</b>';
               'BgColor',     '#F0F0F0';
               'FontName',    'DejaVu Sans Mono';
               'BorderWidth', '2';
               'FontColor',   '#0000F0'};
if nargin == 3 && isstruct(opts)
    for k = 1:size(fields_opts,1)
        if ~isfield(opts,fields_opts{k,1})
            opts = setfield(opts,fields_opts{k,1},fields_opts{k,2});
        end
    end
else
    opts = cell2struct(fields_opts(:,2),fields_opts(:,1),1);
end

% ======================= PROPIEDADES DE LA TABLA ======================

X = get(hTab,'Data');
colnames = get(hTab,'ColumnName');
[nrows, ncols] = size(X);

% ========================= PLANTILLAS ================================

COL_TEMP = '<TD>_col_</TD>';
ROW_TEMP = '<TR>_row_</TR>';
HEADER_TEMP = '<TH bgcolor=#DCDCFF>_header_</TH>';

HTML_TEMP = ['<html><head><title>_pagetitle_</title></head><body><font face="_fontname_">',...
    '<table border=_borderwidth_ bordercolor=#000000 cellspacing=5 cellpadding=5 bgcolor=_bgcolor_>',...
    ' <caption>_tabletitle_</caption> _table_ </table></font> _footnote_ </body></html>'];

FOOT_TEMP = ['<br><br><br><font face="Arial Narrow" color=#C0C0C0 size=2>',...
    'Published by: <cite>table2html</cite></font>'];

% ========================== ENCABEZADOS  =============================
if strcmp(colnames,'numbered')
    colnames = repmat('untitled|',1,ncols);
    remain = colnames;
    colnames = {};
    while 1
        [str,remain]=strtok(remain,'|');
        if isempty(str),break,end;
        colnames=[colnames str];
    end
end
rstr = WriteHeaders(colnames);
WriteTable(rstr);
web(filename,'-browser');

% =====================================================
    function rstr = WriteHeaders(headers)
        rstr = '';
        for k = 1:ncols
            rstr=[rstr,strrep(HEADER_TEMP,'_header_',headers{k})];
        end
    end

    function WriteTable(rstr)
        [path_,~,~] = fileparts(filename);
        if ~isempty(path_)
            if ~isdir(path_)
                mkdir(path_);
            end
        end
       
        fid=fopen(filename,'w');
        for i=1:nrows
            cstr='';
            for j=1:ncols
                if isa(X,'cell')
                    cstr = [cstr,strrep(COL_TEMP,'_col_',num2str(X{i,j})),' '];
                else
                    cstr = [cstr,strrep(COL_TEMP,'_col_',num2str(X(i,j))),' '];
                end
            end
            rstr = [rstr,strrep(ROW_TEMP,'_row_',cstr)];
        end
        WEB_PAGE = strrep(HTML_TEMP,'_table_',rstr);
        WEB_PAGE = regexprep(WEB_PAGE,{'_footnote_','_bgcolor_',...
            '_fontname_','_borderwidth_','_tabletitle_','_pagetitle_','_fontcolor_'},...
            {FOOT_TEMP,opts.BgColor,opts.FontName,opts.BorderWidth,...
            opts.TableTitle,opts.PageTitle,opts.FontColor});
        fprintf(fid,'%s',WEB_PAGE);
        fclose(fid);
    end

end

Para una referencia más completa con algunos ejemplos/test de la función table2html puede revisar el siguiente enlace:

table2html (GitHub)

miércoles, 3 de diciembre de 2014

Intercambiar filas y columnas de una matriz en MATLAB


El hecho de intercambiar filas y columnas de una matriz suele ser un tema muy importante en álgebra lineal. Aquí vamos a explicar con ejemplos cómo lograr esto mediante la indexación de matrices utilizando el operador dos puntos.

Para ejemplificar vamos a utilizar la matriz A, definida por:

$$A=\begin{bmatrix} 1 & 2 & 3 \\ 4 & 5 & 6  \\ 7 & 8 & 9 \end{bmatrix}$$

Creando la matriz en MATLAB:

>> A=[1,2,3;4,5,6;7,8,9]
A =
     1     2     3
     4     5     6
     7     8     9

Intercambiar filas

Suponga que se pide intercambiar las filas 1 y 2, entonces se procedería como sigue:

>> A([1 2],:)=A([2 1],:)
A =
     4     5     6
     1     2     3
     7     8     9

Básicamente le estamos "diciendo" a MATLAB que de la matriz A sustituya todas las columnas de las filas 1 y 2 por las filas 2 y 1, es decir, "invirtiendo" el orden.


Intercambiar columnas

La lógica usada es prácticamente la misma que en el caso anterior, con la única diferencia que el operador dos puntos lo utilizaremos en el índice de las filas. Por ejemplo, de la matriz A original vamos a intercambiar las filas 2 y 3:

>> A(:,[2 3])=A(:,[3 2])
A =
     1     3     2
     4     6     5
     7     9     8


Definiendo funciones propias

Finalmente, si lo anterior le parece un poco confuso, puede utilizar las siguientes funciones: swaprows y swapcols, que intercambian filas y columnas respectivamente:

function X = swaprows(A,m1,m2)
X = A;
X(m1,:) = A(m2,:);
X(m2,:) = A(m1,:);
end

function X = swapcols(A,n1,n2)
X = A;
X(:,n1) = A(:,n2);
X(:,n2) = A(:,n1);
end

La sintaxis para ambas es similar, simplemente necesita pasar como argumento la matriz y las filas y/o columnas a intercambiar de posición. Desde luego las funciones anteriores no están incluidas en MATLAB por defecto, por lo que habrá de colocarlas a su directorio de trabajo o bien añadirlas al PATH de MATLAB.


lunes, 24 de noviembre de 2014

GUIOOD Toolbox, desarrollando GUIs utilizando el paradigma de la POO


GUIOOD Toolbox (Graphical User Interface with Object-Oriented Design) es un conjunto de clases implementadas en MATLAB cuyo objetivo es desarrollar interfaces gráficas de usuario utilizando una sintaxis similar a la de Java, es decir, con el paradigma de la programación orientada a objetos. 

Básicamente, GUIOOD se está desarrollando para funcionar como un wrapper de las GUIs ordinarias en MATLAB. Se pretende que la programación de GUIs sea más rápida y sencilla. Desde luego que habrá de considerarse el hecho de que "debajo" hay una interfaz gráfica ordinaria, por lo cual la cantidad de controles gráficos disponibles serán los mismos, con algunos añadidos utilizando la librería swing de Java.

¿Qué es lo nuevo?

Desde luego, la forma de programar. Todos los elementos gráficos serán objetos de una determinada clase y tendrán métodos para modificar sus atributos. Por ejemplo para crear una ventana el código correspondiente sería algo como esto:

app = Frame('Ventana 1', [300 200]);
app.SetColor('r');

Ha de mencionarse que el nombre de algunos controles gráficos han sido sustituidos por su equivalente en Java, además que muchos métodos guardan similitud con dicho lenguaje y en otros casos con la librería wxPython. La siguiente es una tabla que muestra la equivalencia de notación entre las GUIs MATLAB ordinarias y el GUIOOD Toolbox:



Como puede verse en la tabla, GUIOOD añade algunos controles gráficos no disponibles en MATLAB. El Canvas es un axes "modificado" que se espera utilizar para dibujos 2D como circulos, rectangulos, elipses y otras figuras de geometría simple, en principio. El PasswordField es similar a una entrada de texto editable, con la diferencia que permite "esconder" los caracteres que en el se introducen, es decir, un campo de contraseñas, que se ha extendido del componente JPasswordField de Java. El Spinner de manera similar se ha extendido del componente JSpinner de Java. Y el AboutDialog es un cuadro de diálogo que contiene información acerca de la GUI, la idea y notación se ha tomado del componente del mismo nombre de la librería wxPython. Es muy probable que se añadan otros controles que puedan resultar útiles, desde luego "tomándolos prestados" de Java.

Otra parte interesante de GUIOOD Toolbox es que dispone de manejadores de posiciones o de distribución de componentes (layouts), los cuales ahorran tiempo significativo, dado que no hay necesidad de indicar las posiciones de los objetos gráficos de forma explícita. Los algoritmos de posicionamiento están en fase de desarrollo, siendo funcionales, pero con algunos detalles en cuanto al orden en que habrán de agregarse los componentes. Se dispone de 3 layouts: grid, vertical y horizontal. El primero distribuye los objetos utilizando filas y columnas como referencia, y el vertical y horizontal los distribuyen como se esperaría, dado el nombre.


Utilidades añadidas

GUIOOD permite exportar el contenido de una Table MATLAB a una tabla en HTML, y también a una hoja de cálculo Microsoft Excel.

El contenido de un Axes puede exportarse como imagen PNG, como un PDF, o incrustarla en un archivo HTML.


Estado del proyecto

El proyecto GUIOOD Toolbox comenzó a desarrollarse a principios de Noviembre de 2014, encontrándose ahora en una etapa muy temprana. Existen muchos detalles por agregar, como dar un mayor soporte al manejo de los eventos, un manejo de errores/excepciones un poco más personalizado, refinar los algoritmos de posicionamiento, escribir la documentación, y sobre todo mucho "testeo" del código. 

El plan inicial contempla un desarrollo durante seis meses. Por lo cual, se esperaría que para Mayo de 2015 pueda estar disponible una versión preliminar. ¿Por qué seis meses?, bueno, el calendario incluye muchos días festivos en este lapso.


Un ejemplo preeliminar (funcional)

A continuación se expone un fragmento de código totalmente funcional, y que deja ver más o menos la idea que se sigue y lo que se espera obtener:

function MiniCalc
% MiniCalc / Demo for GUIOOD Toolbox
%
% Author: Jorge De Los Santos
% Version: 0.1.0
% E-mail: delossantosmfq@gmail.com
% License: MIT License

app = Frame('Mini Calculadora',[220 100]);
app.SetLayout('grid',5,3,1); % Set main layout: grid. 5 rows and 3 columns
p1 = Panel();
p2 = Panel();
p3 = Panel();
app.AddMany(p1,p2,p3); % Add many panels to Frame (main app)

% Labels and TextFields
lb1 = Label('# 1');
lb2 = Label('# 2');
num1 = TextField();
num2 = TextField();

p1.AddMany(num1,lb1); % Add controls to Panel p1
p2.AddMany(num2,lb2); % Add controls to Panel p2

% Buttons
bt1 = Button('+');
bt2 = Button('-');
bt3 = Button('*');
bt4 = Button('/');

p3.AddMany(bt1,bt2,bt3,bt4); % Add buttons to panel p3
p3.SetLayout('horizontal',2); % Set layout for p3, horizontal and two controls

bt1.SetCallback(@calcular_fcn); % Set callback for buttons
bt2.SetCallback(@calcular_fcn);
bt3.SetCallback(@calcular_fcn);
bt4.SetCallback(@calcular_fcn);

    function calcular_fcn(~,~,obj)
        a = num1.GetText(); % Get value of "num1" Label
        b = num2.GetText(); % Get value of "num2" Label
        oper = obj.GetText(); % Get the operator of current Button clicked
        MessageBox(['Resultado = ',num2str(eval([a,oper,b]))],'GUIOOD');
    end

end




Si la GUI le parece "rara", no os preocupéis, cuestiones de temas del SO en que se ejecutó esta prueba.



Cualquier comentario o sugerencia  es siempre bienvenida. Y si desea colaborar con el proyecto no dude en contactar a los correos del blog (matlabtyp@gmail.com).