SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS 3. CÓDIGO 3.1 INTRODUCCIÓN Continuando con nuestra subida desde el nivel más bajo hasta el más alto, hemos llegadoal capítulo dedicado al código, el paso previo al nivel de usuario. En este capítulo desgranaremos todos los desarrollos que se han realizado para dar a la aplicación el aspecto global y la funcionalidad de la que goza. 3.2 ESTRUCTURA GENERAL Como se ha comentado en capítulos anteriores, esta aplicación está desarrollada íntegramente en Java, siendo el entorno de desarrollo elegido Netbeans. Se ha creado un proyecto nuevo con Netbeans para alojar el código de la aplicación, siendo el nombre de este proyecto TDSApplet. El desarrollo de la aplicación está basado en dos tipos de código fundamentales: • • Librerías o clases externas: Son clases que han sido desarrolladas por terceros y que están disponibles (bajo diversos tipos de licencia) para su utilización. El código fuente puede estar o no disponible y no tienen por qué ser editables. Clases propias: Son clases que han sido desarrolladas expresamente para esta aplicación por el autor de la misma, el código fuente está disponible y es editable. Visualizando las categorías de nuestro IDE, podemos diferenciar claramente estos dos tipos de clases, ya que cada uno está agrupado bajo un epígrafe diferente, estando las clases propias agrupadas bajo Source Packages y las librerías bajo Libraries: 27 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS 3.3 LIBRERÍAS Las librerías que se han utilizado para el desarrollo de esta aplicación son las siguientes: • • • • • JDK 1.7 JGraphX ApacheMath JFreeChart JTransforms Cada una de estas librerías tiene un cometido diferente dentro de la ejecución de la aplicación. En los subapartados siguientes nos detendremos en cada una de ellas para analizarlas con mayor profundidad. 3.3.1 JDK 1.7 Este es el Application Programming Interface (API) de Java versión 1.7. y está incluido dentro del JDK con el que hemos realizado la compilación de la aplicación. El API de Java contiene una gran variedad de clases y utilidades diferentes que con cada versión nueva aumentan más y más: 28 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS está completamente desarrollado en Java y constituye la base sobre la cual desarrollar cualquier aplicación en Java. Las clases del API de Java que se han utilizado en este desarrollo están englobadas en 5 paquetes diferentes: • • • • • AWT: Es el Abstract Window Toolkit, AWT (Herramientas de Ventanas Abstractas). Soporta la programación de Graphical User Interface, GUI (Interfaz Gráfica de Usuario). Las características más importantes de AWT son: - Es un conjunto de componentes de interfaz de usuario nativo en Java. - Tiene un modelo de gestión de eventos robusto. - Contiene herramientas gráficas y de imágenes, incluyendo clases de formas, colores y fuentes. - Implementa gestores de ventanas que permiten que las ventanas no dependan de un tamaño de ventana particular o de una determinada resolución de pantalla. Incluye clases de transferencia de datos para el copiado y pegado a través del portapapeles nativo de la plataforma. Io: Implementa entradas y salidas de flujos de datos, serialización y sistema de archivos. Net: Proporciona clases para implementar aplicaciones de red. Util: Contiene colecciones de elementos útiles como gestores de eventos, colección de utilidades tradicionales, gestores de fecha y hora, utilidades de internacionalización y otra miscelánea de utilidades (generador de números aleatorios, arrays de bits, etc.) Swing:Implementa un conjunto de componentes para la construcción de GUIs y para el añadido de funcionalidades gráficas e interactividad mejoradas a aplicaciones de Java. Los componentes de Swing están implementados completamente en Java. Estos componentes permiten a los GUIs mostrar la misma apariencia en todas las plataformas o tomar la apariencia propia de cada plataforma por separado (como Windows, Solaris o Linux). Los elementos utilizados de cada uno de estos conjuntos son los siguientes: • • • • java.awt.BorderLayout: Proporciona un contenedor para el cambio de tamaño y organización de sus componentes en cinco regiones (norte, sur, este, oeste y centro). java.awt.Color: La clase Color se utiliza para encapsular los colores en el espacio por defecto RGB (Red, Green, Blue) o en espacios arbitrarios identificados por ColorSpace. java.awt.Desktop: La clase Desktop permite a una aplicación Java lanzar aplicaciones registradas en el escritorio nativo para manejar una URI o archivo. java.awt.Dimension: La clase Dimension encapsula la altura y anchura de un objeto (en precisión Integer) en un solo objeto. 29 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS • • • • • • • • • • • • • • • • • • java.awt.event.MouseAdapter: La clase MouseAdapter implementa un adaptador abstracto para la recepción de eventos de ratón. Esta clase se puede editar a conveniencia para crear listeners de objetos. java.awt.event.MouseEvent: La clase MouseEvent implementa un listener que indica que una acción de ratón se ha producido en un componente. java.awt.geom.Ellipse2D: La clase Ellipse2D implementa una elipse que está definida por un rectángulo y enmarcada en él. java.io.IOException: Indica que una excepción de algún tipo de entrada/salida se ha producido. java.net.URI: Representa una referencia de un Uniform Resource Identifier (URI). java.util.logging.Level: La clase Level define un conjunto de niveles de registro estándar que pueden ser utilizados para controlar el registro de salida. java.util.logging.Logger: El objeto Logger se utiliza para registrar los mensajes de un sistema o componente específico de la aplicación. java.util.Map: El objeto Map es un objeto que mapea elementos en valores. java.util.regex.Matcher: La clase Matcher implementa un motor que realiza operaciones de búsqueda y coincidencia en una cadena de caracteres mediante la interpretación de un patrón Pattern. java.util.regex.Pattern: El objeto Pattern es una representación compilada de una expresión regular. java.util.Vector: La clase Vector implementa un conjunto ampliable de objetos. javax.swing.JFrame: La clase JFrame es una versión extendida de java.awt.Frame que añade soporte para la arquitectura de componentes Swing. javax.swing.JPanel: La clase JPanel implementa un contenedor ligero genérico. javax.swing.JTable: La clase JTable se utiliza para visualizar y editar tablas de dos dimensiones. javax.swing.SwingUtilities: La clase SwingUtilities implementa un conjunto de métodos de utilidad para Swing. javax.swing.table.DefaultTableModel: La clase DefaultTableModel es una implementación de TableModel que utiliza un vector de vectores para almacenar los valores de los objetos de las celdas. javax.swing.tree.DefaultMutableTreeNode: la clase DefaultMutableTreeNode es un nodo de propósito general en una estructura de datos de árbol. javax.swing.tree.TreePath: La clase TreePath representa una matriz de objetos que identifican unívocamente la ruta de acceso a un nodo en un árbol. 30 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS 3.3.2 JGraphX JGraphX es una librería de visualización de diagramas de Java Swing licenciada bajo la licencia NewBSD (New Berkeley Software Distribution). Esta licencia tiene menos restricciones en comparación con otras como la GPL estando muy cercana al dominio público. La licencia BSD al contrario que la GPL permite el uso del código fuente en software no libre. A pesar de que los paquetes usan el nombre de “mxGraph”, la librería no se llama mxGraph ya que mxGraph es la librería de graficado de JavaScript que sólo está disponible a través de compra y no es de código libre. Originalmente la librería fue nombrada JGraph a secas hasta la versión 1.5. En la versión 1.6 se decidió cambiar el nombre a JGraphX para reflejar que el código base de la API fue reescrito desde cero. JGraphX proporciona funcionalidades para la visualización e interacción con grafos (no gráficos). Algunos ejemplos de aplicaciones que pueden ser escritos con esta librería son editores de flujos de trabajo, cuadros de organizaciones, herramientas de modelado de procesos de negocios, visualizador de circuitos electrónicos, visualizador de redes de telecomunicaciones, etc. es decir, una multitud de aplicaciones en las que esté presente el concepto de grafo. JGraphX también incluye soporte para XML, importación y exportación de grafos, maquetación, etc. Esta librería puede ser encontrada en la siguiente dirección web http://www.jgraph.com y constituye, junto con el JDK 1.7 de Java, la base de nuestra aplicación. Es con esta librería con la que se implementa el grafo (aristas, bloques funcionales y conectividad entre ellos) del Panel de Operaciones. Este grafo es el que permite mover el flujo de información de un bloque a otro y realizar el cálculo de las distintas operaciones. Los elementos de esta librería utilizados en la confección del código de nuestra aplicación son los siguientes: • • • com.mxgraph.analysis.mxAnalysisGraph: La clase mxAnalysisGraph implementa un conjunto de métodos útiles para analizar la estructura y propiedades del grafo. com.mxgraph.model.mxCell: La clase mxCell representa un elemento del modelo del grafo (celda). Los vértices, aristas y grupos de ellos son modelados como mxCell. com.mxgraph.model.mxGeometry: La clase mxGeometry representa la geometría de una celda. Para vértices la geometría consta de localización en los ejes X e Y así como de anchura y altura. Para aristas, la geometría define los terminales origen y destino. 31 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS • • • • • • • • com.mxgraph.swing.mxGraphComponent: Esta clase lanza los siguientes eventos: START_EDITING, LABEL_CHANGED, ADD_OVERLAY, BEFORE_PAINT. com.mxgraph.util.mxConstants: Esta clase contiene todas las constantes globales del grafo. com.mxgraph.util.mxEvent: Esta clase implementa los eventos del grafo. com.mxgraph.util.mxEventObject: La clase mxEventObject constituye la base para objetos que lanzan eventos con nombre. com.mxgraph.util.mxEventSource.mxIEventListener: Esta clase define los requisitos para un objeto que escucha una fuente de eventos. com.mxgraph.util.mxPoint: La clase mxPoint implementa un punto bidimensional con coordinadas de precisión Double. com.mxgraph.view.mxEdgeStyle: La clase mxEdgeStyle proporciona varios estilos de aristas que se utilizarán como valores para mxConstants.STYLE_EDGE en el estilo de las celdas. De manera alternativa, las constantes mxConstants.EDGESTYLE_* pueden ser utilizadas para hacer referencia a un estilo de arista a través del registro mxStyleRegistry. com.mxgraph.view.mxGraph: La clase mxGraph implementa un objeto que permite crear grafos a partir de un modelo de grafos y una hoja de estilos. Es la clase base a partir de la cual se construye el grafo de nuestra aplicación. 3.3.3 ApacheMath La Apache Commons Mathematics Library es una librería ligera de componentes matemáticos y estadísticos autocontenidos que abordan los problemas matemáticos más comunes que no están disponibles en las librerías nativas de Java. Sus principios están basados en: • • • • • Las aplicaciones al mundo real determinan las prioridades de su desarrollo. El desarrollo de la librería hace hincapié en el desarrollo de pequeños componentes de fácil integración en lugar del desarrollo de grandes componentes con complejas dependencias entre ellos. Todos los algoritmos están completamente documentados y siguen, generalmente, las pautas de edición aceptadas comúnmente. En situaciones donde existen multitud de algoritmos estándar, se utiliza un patrón estratégico para soportar múltiples implementaciones. Dependencias limitadas. No existen dependencias externas más allá de los propios componentes Commons y las librerías nativas 32 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS de Java (requiere al menos Java 3 para la versión 1.2 de la librería y Java 5 para la versión 2.0). Esta librería es distribuida bajo la Apache License 2.0, que es una licencia de software libre creada por la Apache Software Foundation (ASF). La licencia Apache (con versiones 1.0, 1.1 y 2.0) requiere la conservación del aviso de copyright y el disclaimer, pero no es una licencia copyleft, ya que no requiere la redistribución del código fuente cuando se distribuyen versiones modificadas. El uso principal que se le ha dado a esta librería es el de soportar los cálculos del más bajo nivel para números complejos. La única clase que se ha utilizado en este desarrollo de esta librería ha sido la siguiente: • org.apache.commons.math3.complex.Complex: La clase Complex soporta la representación de un número complejo, es decir, un número que tiene parte real y parte imaginaria. Las implementaciones de las operaciones aritméticas manejan valores NaN e Infinito de acuerdo con la aritmética de valores Double. 3.3.4 JFreeChart El proyecto JFreeChart fue fundado hace catorce años, en el año 2000 por David Gilbert. JFreeChart es la más ampliamente utilizada librería de graficado para Java, con más de 2.1 millones de descargas hasta la fecha. El proyecto continúa su desarrollo a día de hoy gracias a la gestión del propio David Gilbert y la contribución de una diversa comunidad de desarrolladores. JFreeChart es una librería gratuita desarrollada íntegramente en Java y que facilita a los desarrolladores la implementación de gráficos profesionales y de calidad en sus desarrollos. Las características más importantes de JFreeChart incluyen: • • • Una API consistente y bien documentada que soporta un amplio abanico de gráficos diferentes. Un diseño flexible que lo hace fácilmente extensible orientado tanto a aplicaciones en el lado del servidor como del cliente. Soporta una variada gama de tipos de salidas diferentes, incluyendo componentes Swing, archivos de imagen (incluyendo PNG y JPEG) e incluso archivos en formato vectorial (incluyendo PDF, EPS y SVG). 33 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS JFreeChart es de código abierto, más concretamente, es software libre. Se distribuye bajo los términos de la licencia GNU LGPL (GNU Lesser General Public Licence), la cual permite su uso en aplicaciones propietarias. Algunos ejemplos de lo que esta librería es capaz de ofrecer se muestran en las siguientes figuras: 34 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS Esta librería constituye el corazón de la representación gráfica de la salida de los cálculos realizados por nuestro desarrollo. Las clases de esta librería utilizada en el desarrollo de esta aplicación han sido las siguientes: • • • • • • org.jfree.chart.axis.NumberAxis: La clase NumberAxis implementa un eje para la visualización de datos numéricos. Si el eje está configurado para determinar automáticamente su rango para mostrar los datos, se puede asegurar que el cero está incluido dentro del rango configurando autoRangeIncludesZero a true. Esta clase tiene un mecanismo para seleccionar automáticamente la unidad de división apropiada dependiendo del rango del eje. org.jfree.chart.ChartFactory: La clase ChartFactory incluye una colección de métodos para crear diferentes gráficos estándar de JFreeChart (diagramas de Gantt, tartas, de barras, de área, etc.). org.jfree.chart.ChartFrame: Esta clase implementa un marco para mostrar por pantalla el gráfico. org.jfree.chart.ChartPanel: La clase ChartPanel implementa un componente Swing para mostrar un objeto JFreeChart. org.jfree.chart.JFreeChart: La clase JFreeChart es una clase para el graficado implementada utilizando la API Java 2D. La versión actual soporta diagramas de barras, gráficos lineales, diagramas de tarta y representaciones XY (incluyendo series temporales). JFreeChart coordina varios objetos para realizar la representación, incluyendo objetos de títulos, dibujado y un conjunto de datos. org.jfree.chart.plot.PlotOrientation: Esta clase es utilizada para determinar la orientación del gráfico 2D (horizontal o vertical). 35 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS • • • • • org.jfree.chart.plot.XYPlot: Esta es una clase general para graficar datos en formato de pares (x, y). Esta clase puede utilizar datos de cualquier clase que implemente la interfaz XYDataset. Esta clase hace uso deun XYItemRenderer para dibujar cada punto en el gráfico. Por medio del uso de diferentes renderers se pueden producir diferentes tipos de gráficos. org.jfree.chart.renderer.xy.XYLineAndShapeRenderer: Esta clase implementa un renderer que conecta puntos de datos con líneas o dibuja la forma de cada punto. Este renderer está diseñado para ser utilizado con la clase XYPlot. org.jfree.data.Range: Esta clase representa un rango inmutable de valores. org.jfree.data.xy.XYSeries: Esta clase representa una serie de cero o más elementos de datos en formato (x, y). Por defecto, los elementos en la serie se clasifican en orden ascendente de X y se permite duplicar valores de X. Tanto el ordenado como la duplicación por defecto se pueden modificar en el constructor. Los valores de Y pueden ser Null para representar valores que faltan. org.jfree.data.xy.XYSeriesCollection: Esta clase representa una colección de objetos XYSeries que pueden ser utilizados como un conjunto de datos. 3.3.5 JTransforms JTransforms constituye la primera librería FFT multiprocesador y de código abierto escrita 100% en Java. Actualmente tiene disponibles los siguientes tipos de transformaciones: • • • • Discrete Discrete Discrete Discrete Fourier Transform (DFT) Cosine Transform (DCT) Sine Transform (DST) Hartley Transform (DHT) El código de esta librería viene derivado del General Purpose FFT Package escrito por Takuya Ooura y del Java FFTPack escrito por Baoshe Zang. Algunos de los proyectos que hacen uso de la librería JTransforms son: • • • • Music Reader: Un software que hace fácil la lectura de la música. Spectro-Edit: Un software para la visualización del audio en un gráfico tiempo-frecuencia. YAPRNN: Un software para el reconocimiento de patrones en redes neuronales. ExpertEyes: Un software de código abierto para aplicaciones de seguimiento de ojos. Las características fundamentales de esta librería son las siguientes: 36 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS • • • • • • • Rápida implementación de DFT, DCT, DST y DHT. Transformaciones en 1, 2 y 3 dimensiones. Tamaño de datos arbitrario. Precisión normal y doble. Variaciones unidimensional y multidimensional de transformaciones 2D y 3D. Multiprocesado automático si existe más de una CPU. FFTs optimizadas para datos reales (un 40% más rápida que con datos complejos). Esta librería está distribuida bajo los términos de la licencia MPL/LGPL/GPL. El uso principal que se le ha dado en nuestro desarrollo ha sido el de calcular la FFT y la FFT inversa. Por tanto, la única clase utilizada en nuestro código ha sido la siguiente: • 3.4 edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D: Calcula la DFT unidimensional con datos de precisión Double reales y/o complejos. El tamaño de los datos puede ser arbitrario, si bien está optimizado para potencias de 2. CLASES PROPIAS Las clases propias están agrupadas en diferentes paquetes dependiendo de la funcionalidad de cada una. La estructura de las mismas es la siguiente: Como se puede comprobar en la figura anterior, las clases están agrupadas en 5 paquetes, siendo la funcionalidad de cada agrupación la siguiente: • us.tds.algebra: En este paquete están agrupadas todas las clases encargadas del cálculo a bajo nivel de las secuencias y las 37 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS • • • • distintas operaciones entre ellas. En este paquete están incluidas las clases Sequence y SequenceGraphOperations. us.tds.applet: En este paquete están agrupadas las clases principales de la aplicación, las que se encargan de coordinar todas las clases y mostrar la información al usuario de manera amigable. En este paquete está incluida la clase AppletGUI_v1_00. En el caso de la aplicación autoejecutable, estaría incluida también la clase ApplicationLauncher. us.tds.chart: En este paquete están agrupadas las clases encargadas de imprimir por pantalla las gráficas de las diferentes secuencias. En este paquete está incluida la clase SequenceChart. us.tds.graph: En este paquete están agrupadas las clases encargadas de trabajar con el grafo mostrado en el Panel de Operaciones. En este paquete está incluida la clase TDSGraph. us.tds.utils: En este paquete están agrupadas las clases que, si bien no son imprescindibles, sí que son útiles para realizar determinadas funciones de importancia menor dentro de la aplicación. En este paquete están incluidas las clases EditableTableModel, NotEditableTableModel y TDSJTable. 3.4.1 Sequence En esta clase se implementan las herramientas básicas para tratar con secuencias, desde su almacenamiento y modificación hasta el cálculo de operaciones básicas con secuencias. Esta clase tiene tres constructores diferentes: • • • Sequence(int minTime, int maxTime, String type, Complex param1, Complex param2, Complex param3, Complex param4) : Construye un objeto Sequence con las características determinadas por sus argumentos, tiempo mínimo, tiempo máximo, tipo de secuencia y determinados parámetros en función del tipo de secuencia. Sequence(int size) : Construye un objeto Sequence con valores ceros del tamaño descrito en el argumento. Sequence() : Construye un objeto sequence con un único valor cero en la posición cero temporal. Las instancias de esta clase son dos: • time: Es un vector de enteros donde se almacena el valor temporal de cada muestra, es decir, el valor de n. Esta instancia es privada. 38 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS • • value: Es un vector de complejos donde se almacenan los valores que toma la secuencia, es decir el valor de x(n). Esta instancia también es privada. sequenceType: Es una variable tipo cadena de texto donde se almacena el tipo de secuencia que es, si temporal o de frecuencia. Esta instancia también es privada. Al ser las tres instancias anteriores privadas, la única manera de acceder a sus valores es a través de los métodos proporcionados en esta clase. Además de los métodos encargados de transformar las dos instancias de esta clase, existen otros métodos encargados de realizar operaciones con secuencias como sumar, multiplicar, calcular la FFT, etc. Los métodos que componen esta clase se presentan a continuación. Modificador y tipo Método Sequence Sequence boolean boolean Sequence Sequence void Sequence Sequence Sequence double[] Sequence Sequence Sequence Sequence double double double double int double double double double int int org.apache.commons.mat h3.complex.Complex Sequence Sequence add(Sequence sequence1) antisymmetricConjugatePart() checkSequenceOverflow() checkString(java.lang.String valuesString) circularTimeInvert(int N) circularTimeTranslate(int time_translation, int N) clearSequence() conjugate() convolve(Sequence sequence1) convolveCircular(Sequence sequence1, int N) getComplexArrayFromSequenceForFFT(int N) getFFT(int points, boolean pointsAuto) getFFT(int points, int N) getInverseFFT(int points, boolean pointsAuto) getInverseFFT(int points, int N) getMaxImaginaryValue() getMaxModuleValue() getMaxPhaseValue() getMaxRealValue() getMaxTime() getMinImaginaryValue() getMinModuleValue() getMinPhaseValue() getMinRealValue() getMinTime() getNearestPowerOf2(int input) getNumericValueOfSingleString(java.lang.String values String) getPolarSequence() getSequenceFromComplexArrayForFFT(double[] array) Sequence getSequenceFromString(java.lang.String valuesString) 39 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS Modificador y tipo java.lang.String int java.lang.String org.apache.commons.mat h3.complex.Complex org.apache.commons.mat h3.complex.Complex double boolean boolean boolean Sequence Sequence Sequence void boolean void void void void void Sequence Sequence Sequence Método getSequenceType() getSize() getStringFromSequence() getSummation() getValueAt(int time_data) idealLPFilterSequence(double x, double wc) isFrequencySequenceType() isSequenceTypeSet() isTimeSequenceType() multiplicateByNumber(org.apache.commons.math3.co mplex.Complex factor) multiplicateBySequence(Sequence sequence1) power(org.apache.commons.math3.complex.Complex power) printSequence() sequenceIsEmpty() setCopyOf(Sequence sequence1) setSameSequenceTypeAs(Sequence sequence) setSequenceTypeAsFrequency() setSequenceTypeAsTime() setValueAt(org.apache.commons.math3.complex.Com plex value_data, int time_data) symmetricConjugatePart() timeInvert() timeTranslate(int time_translation) Por lo demás, poco más se puede añadir de esta clase que, constituye el álgebra básica con el que se realizan los cálculos con secuencias. Claro está, con esta clase tan sólo se podría construir un programa simple de cálculo por línea de comando. Para realizar cálculos mediante interfaz gráfica habría que construir otros objetos a más alto nivel con los que trabajar. Es por ello por lo que se crea la siguiente clase. 3.4.2 SequenceGraphOperations Esta clase, como su propio nombre indica, está pensada para integrar las operaciones con secuencias en el entorno de trabajo gráfico de nuestra aplicación. La clase SequenceGraphOperations implementa el núcleo de los bloques funcionales del grafo de la aplicación, integrando las operaciones de dicho bloque funcional, el número de entradas/salidas, los valores de las secuencias de entrada/salida y los propios atributos de dichos bloques funcionales. Los constructores de esta clase son dos: 40 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS • • SequenceGraphOperations(): Este constructor crea un objeto vacío, por lo que para darle forma, habrá que introducir los cambios a través de los múltiples métodos de esta clase. SequenceGraphOperations(String type, String typeNode, int inputsNumber, int outputsNumber): Este constructor crea un objeto del tipo y número de entradas/salidas indicado en los argumentos. El argumento type hace referencia al tipo de bloque funcional (Sink, Source, Intermediate), mientras que el argumento typeNode hace referencia al tipo de operación que implementa. Dependiendo del tipo de operación tendrá asociados unos atributos u otros y un tipo de operación interna u otra. Por su parte, las instancias de esta clase son las siguientes: • • • • attributes: Es un vector de vectores con dos columnas, la primera para indicar el atributo y la segunda para indicar el valor del atributo. Cada atributo tiene una etiqueta única en la primera columna que resulta identificativa. inputs: Es un vector de secuencias (Sequence). En este vector se guardan las secuencias de entrada al bloque funcional. outputs: Es un vector de secuencias (Sequence). En este vector se guardan los resultados de realizar los cálculos propios del bloque funcional. internalSequence: Es una secuencia (Sequence). En esta variable se guardan las secuencias características de un bloque funcional que no puedan actuar como entradas o salidas del mismo, es decir, que sean inherentes al propio bloque funcional, por ejemplo, para un filtro, en esta variable se guardaría la respuesta impulsional del filtro. Una vez descritos los constructores e instancias, daremos paso a la descripción de los métodos de esta clase. Modificador y tipo Sequence boolean boolean java.lang.String boolean boolean boolean boolean boolean boolean boolean boolean boolean org.apache.commons.math Método calculate() checkOverflow() checkSequenceTypeMismatch() getAttribute(java.lang.String type) getAttributeAutoPointsFFT() getAttributeAutoXImaginary() getAttributeAutoXModule() getAttributeAutoXPhase() getAttributeAutoXReal() getAttributeAutoYImaginary() getAttributeAutoYModule() getAttributeAutoYPhase() getAttributeAutoYReal() getAttributeComplexConstant(int number) 41 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS Modificador y tipo 3.complex.Complex int java.awt.Color double java.lang.String java.lang.String java.awt.Color double double double double double double double double double double double double double double double double java.awt.Color java.lang.String java.lang.String java.awt.Color java.awt.Color java.lang.String java.lang.String java.awt.Color int java.awt.Color double java.lang.String java.lang.String java.awt.Color boolean java.lang.String java.lang.String java.lang.String java.lang.String Sequence Sequence int int Sequence void void int void Método getAttributeDelay() getAttributeImaginaryBackgroundColor() getAttributeImaginaryConstant(int number) getAttributeImaginaryLabelX() getAttributeImaginaryLabelY() getAttributeImaginaryLineColor() getAttributeMaxXImaginary() getAttributeMaxXModule() getAttributeMaxXPhase() getAttributeMaxXReal() getAttributeMaxYImaginary() getAttributeMaxYModule() getAttributeMaxYPhase() getAttributeMaxYReal() getAttributeMinXImaginary() getAttributeMinXModule() getAttributeMinXPhase() getAttributeMinXReal() getAttributeMinYImaginary() getAttributeMinYModule() getAttributeMinYPhase() getAttributeMinYReal() getAttributeModuleBackgroundColor() getAttributeModuleLabelX() getAttributeModuleLabelY() getAttributeModuleLineColor() getAttributePhaseBackgroundColor() getAttributePhaseLabelX() getAttributePhaseLabelY() getAttributePhaseLineColor() getAttributePointsFFT() getAttributeRealBackgroundColor() getAttributeRealConstant(int number) getAttributeRealLabelX() getAttributeRealLabelY() getAttributeRealLineColor() getAttributeSequenceCustomized() getAttributeSequenceType() getAttributeType() getAttributeTypeNode() getAttributeValue() getInput(int input) getInternalSequence() getNumberOfInputs() getNumberOfOutputs() getOutput(int output) initializeToZero() printAttributes() searchAttribute(java.lang.String type) setAttribute(java.lang.String type, java.lang.String value) 42 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS Modificador y tipo void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void void Método setAttributeAutoPointsFFT(boolean state) setAttributeAutoXImaginary(boolean state) setAttributeAutoXModule(boolean state) setAttributeAutoXPhase(boolean state) setAttributeAutoXReal(boolean state) setAttributeAutoYImaginary(boolean state) setAttributeAutoYModule(boolean state) setAttributeAutoYPhase(boolean state) setAttributeAutoYReal(boolean state) setAttributeComplexConstant(org.apache.commons.ma th3.complex.Complex complexConstant, int number) setAttributeComplexConstant(double realConstant, double imaginaryConstant, int number) setAttributeDelay(int delay) setAttributeImaginaryBackgroundColor(java.awt.Color color) setAttributeImaginaryConstant(double imaginaryConst ant, int number) setAttributeImaginaryLabelX(java.lang.String label) setAttributeImaginaryLabelY(java.lang.String label) setAttributeImaginaryLineColor(java.awt.Color color) setAttributeMaxXImaginary(double value) setAttributeMaxXModule(double value) setAttributeMaxXPhase(double value) setAttributeMaxXReal(double value) setAttributeMaxYImaginary(double value) setAttributeMaxYModule(double value) setAttributeMaxYPhase(double value) setAttributeMaxYReal(double value) setAttributeMinXImaginary(double value) setAttributeMinXModule(double value) setAttributeMinXPhase(double value) setAttributeMinXReal(double value) setAttributeMinYImaginary(double value) setAttributeMinYModule(double value) setAttributeMinYPhase(double value) setAttributeMinYReal(double value) setAttributeModuleBackgroundColor(java.awt.Color col or) setAttributeModuleLabelX(java.lang.String label) setAttributeModuleLabelY(java.lang.String label) setAttributeModuleLineColor(java.awt.Color color) setAttributePhaseBackgroundColor(java.awt.Color color ) setAttributePhaseLabelX(java.lang.String label) setAttributePhaseLabelY(java.lang.String label) setAttributePhaseLineColor(java.awt.Color color) setAttributePointsFFT(int value) setAttributeRealBackgroundColor(java.awt.Color color) setAttributeRealConstant(double realConstant, int number) 43 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS Modificador y tipo void void void void void Método setAttributeRealLabelX(java.lang.String label) setAttributeRealLabelY(java.lang.String label) setAttributeRealLineColor(java.awt.Color color) setAttributeSequenceCustomized(boolean customized) setAttributeSequenceType(java.lang.String sequenceT ype) setAttributeType(java.lang.String type) setAttributeTypeNode(java.lang.String typeNode) setAttributeValue(java.lang.String value) setInput(int input, Sequence sequence) setInternalSequence(Sequence sequence) setOutput(int output, Sequence sequence) void void void int void int Como se puede comprobar, existen muchos métodos del tipo setAttribute y getAttribute. Estos métodos se utilizan para modificar el vector attributes de una manera segura y controlada, no permitiendo al usuario que realice modificaciones indeseadas o que puedan provocar error. Por otro lado, además de estos métodos, los principales son los siguientes: • • • setInput/setOutput/setInternalSequence: Estos métodos establecen el valor de la secuencia de entrada/salida/interna. getInput/getOutput/getInternalSequence: Estos métodos devuelven el valor de la secuencia de entrada/salida/interna. calculate: Este método es el núcleo principal de la clase ya que es el que realiza el cálculo asociado al bloque funcional con las entradas y lo inserta en el vector de salidas. El ciclo de funcionamiento a nivel interno de esta clase sería el siguiente: 1. 2. 3. 4. 5. Crear el objeto Establecer los atributos fundamentales Establecer secuencias de entrada Realizar el cálculo interno Obtener secuencias de salida 3.4.3 SequenceChart El cometido principal de esta clase es el de servir como soporte a las operaciones de representación de gráficas a través de la librería JFreeChart. Es una clase de segundo nivel, de soporte a otras clases que trabajan directamente con la clase principal. Su constructor es único, SequenceChart(), y crea el objeto sin más. No están definidas instancias para esta clase, ya que como hemos explicado anteriormente, tan sólo sirve de interfaz de cara a la librería JFreeChart. 44 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS Esta clase ofrece una interfaz amigable a la hora de realizar las representaciones de gráficas. Tanto es así que están definidos tan sólo cuatro métodos: Modificador y tipo org.jfree.chart.JFreeChart org.jfree.chart.JFreeChart org.jfree.chart.JFreeChart org.jfree.chart.JFreeChart Método createImaginaryChart(java.lang.String imaginary_title, java.lang.String imaginary_x_axis_label, java.lang.String imaginary_y_axis_label, Sequence seq uence, java.awt.Color lineColor, java.awt.Color backgroundColor, boolean autoX, boolean autoY, double minX, double maxX, double minY, double maxY) createModuleChart(java.lang.String module_title, java.lang.String module_x_axis_label, java.lang.String module_y_axis_label, Sequence seque nce, java.awt.Color lineColor, java.awt.Color backgroundColor, boolean autoX, boolean autoY, double minX, double maxX, double minY, double maxY) createPhaseChart(java.lang.String phase_title, java.lang.String phase_x_axis_label, java.lang.String phase_y_axis_label, Sequence sequen ce, java.awt.Color lineColor, java.awt.Color backgroundColor, boolean autoX, boolean autoY, double minX, double maxX, double minY, double maxY) createRealChart(java.lang.String real_title, java.lang.String real_x_axis_label, java.lang.String real_y_axis_label, Sequence sequence , java.awt.Color lineColor, java.awt.Color backgroundColor, boolean autoX, boolean autoY, double minX, double maxX, double minY, double maxY) Estos cuatro métodos devuelven un objeto tipo JFreeChart ya construido, tan sólo para ser insertado en un ChartFrame. Los argumentos que se le pasan a cada uno de estos cuatro métodos son todos similares: título del gráfico, etiqueta de ejes X e Y, la secuencia, el color de líneas y de fondo, los valores máximos y mínimos de ejes entre los cuales representar y si estos valores pueden ser calculados automáticamente o no. Cabe reseñar, como nota curiosa, que en la librería JFreeChart no existe ningún gráfico del tipo secuencia utilizado en esta aplicación. Para realizar esta representación se ha tenido que utilizar un pequeño truco; se ha utilizado un gráfico tipo XY con dos series de datos, por un lado una serie con representación gráfica en formato punto y sin línea y otras tantas series como puntos existiesen con representación gráfica en formato de línea con el objetivo de hacer el “cuerpo” de cada punto. Los valores de la serie de puntos no han tenido que ser modificados, ya que por cada par (x,y) se generaba un punto aislado; sin embargo, para 45 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS conseguir representar las líneas verticales sin conexión entre todas ellas, se han creado tantas series como puntos existiesen, siendo dos los valores de cada una de estas series, (x,y) y (0,y). Una vez superpuestas todas las series en la gráfica y coloreándolas con el mismo color, da la sensación de que el gráfico es de tipo secuencia, como se puede observar en la siguiente figura. 3.4.4 TDSGraph Es en esta clase donde reside, por así decirlo, el cerebro de la aplicación. No es la clase principal de la aplicación, ya que ese papel le corresponde a la clase AppletGUI_v1_00, pero sí que es la clase más importante. Esta clase extiende a mxGraph, que es la clase generadora de grafos de la librería JGraphX y, por tanto, hereda de la clase padre todos los constructores, instancias y métodos. Además de todo esto, también se han definido nuevas instancias y métodos a esta clase para enlazarla con el cálculo de secuencias y bloques funcionales desarrollado en las clases anteriormente descritas. Las instancias definidas son las siguientes: • • • • • style: En este objeto de tipo Map se guardan los atributos del estilo de representación gráfica de las aristas del grafo. parent: En este objeto se guarda el objeto Padre del grafo, es decir, la celda de la cual cuelgan todos los elementos del grafo como aristas y vértices. PORT_DIAMETER y PORT_RADIUS: Son dos constantes que determinan el tamaño de los puertos de los bloques funcionales. vertexVector: En este vector se guardan todos los vértices que componen el grafo. edgesToPortsMatrix: En este vector de vectores se guardan los orígenes y destinos de todas las aristas del grafo, teniendo como elemento origen y destino el puerto al que están conectadas las aristas. La primera columna identifica al origen y la segunda al destino 46 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS • • • • • • edgesToVertexMatrix: Este vector de vectores tiene la misma filosofía que el anterior, guarda los vértices origen y destino de todas las aristas del grafo. Además incluye también el número de salida y de entrada al que están conectadas estas aristas dentro de cada uno de los bloques funcionales. El formato es columna 0, origen, columna 1, destino, columna 2, número de salida, columna 3, número de entrada. operationsMatrix: En este vector de vectores se guarda la información relativa a cada uno de los bloques funcionales añadidos al grafo. La estructura de la información guardada es, por orden de columnas, Cell (la identificación del vértice del bloque funcional), SequenceGraphOperations (el objeto de operación asociado al bloque funcional), TypeNode (Source, Sink, Intermediate), TypeOperation (Multiplication, Convolution,etc). sourcePathMatrix: En este vector de vectores se guarda la información relativa a caminos encontrados desde los vértices fuente hasta los vértices sumidero o hasta encontrar un lazo. En las filas se guardan cada uno de los caminos, mientras que en las columnas se guarda la identificación del vértice en formato numérico (según la matriz de adyacencia). sinkPathMatrix: Este vector de vectores tiene la misma función que el anterior solo que el recorrido de los caminos es el inverso, desde los nodos sumidero hasta los nodos fuente o hasta encontrar un lazo. La estructura de la información dentro de la instancia es la misma. adjacenceMatrix: En este array bidimensional se guarda la información relativa a la matriz de adyacencias del grafo a nivel de vértice (no a nivel de puerto). Las filas denotan el vértice origen, mientras que las columnas denotan los vértices destino. Si el elemento es cero, significa que no hay conectividad entre origen y destino. Si el elemento es mayor que cero, hay tantas aristas entre el vértice origen y destino como indique el elemento. iterationsNumber: En este entero se guarda el número de iteraciones a realizar en el momento del cálculo en caso de existir lazos en el grafo. Por su parte, los métodos definidos en esta clase son los siguientes: Modificador y tipo java.lang.String java.lang.String void java.lang.String int void void boolean Método analyseGraph() analysis() calculateOperations() checkOperations() countTypeOfVertex(java.lang.String type) deleteCell(com.mxgraph.model.mxCell selectedCell) deleteLineInOperationsMatrix(com.mxgraph.model.mx Cell vertex) errorOfOperationConnectionsNumber() 47 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS Modificador y tipo boolean boolean boolean boolean void java.lang.String SequenceGraphOperations java.lang.String java.lang.String void void int int int int int Sequence void void java.lang.String void void void com.mxgraph.model.mxCel l void void boolean boolean boolean boolean boolean int boolean boolean boolean void void Método errorOfOperationsNotConnectedToSink() errorOfOperationsNotConnectedToSource() errorOfSinkConnectionsNumber() errorOfSourceConnectionsNumber() getAdjacenceMatrix() getCellAttribute(com.mxgraph.model.mxCell cell, java.lang.String attribute) getCellSequenceGraphOperation(com.mxgraph.model. mxCell cell) getCellType(com.mxgraph.model.mxCell cell) getCellTypeNode(com.mxgraph.model.mxCell cell) getEdgesToPortsMatrix() getEdgesToVertexMatrix() getInputNumberFromEdgesToVertexMatrix(com.mxgra ph.model.mxCell source, com.mxgraph.model.mxCell terminal, int lastInputNumber) getInputPortNumber(com.mxgraph.model.mxCell cell) getIterationsNumber() getOutputNumberFromEdgesToVertexMatrix(com.mxgr aph.model.mxCell source, com.mxgraph.model.mxCell terminal, int lastOutputNumber) getOutputPortNumber(com.mxgraph.model.mxCell cell ) getOutputSequence(com.mxgraph.model.mxCell cell) getSinkPathMatrix() getSourcePathMatrix() getToolTipForCell(java.lang.Object cell) getVertexVector() initGraph() initializeOperationsToZero() insertBox(java.lang.String name, int inputs, int outputs, int x, int y) insertLineInOperationsMatrix(com.mxgraph.model.mx Cell vertex,SequenceGraphOperations sequenceGraph Operation) insertOperation(java.lang.String type, int xPosition, int yPosition) isCellEditable(java.lang.Object cell) isCellFoldable(java.lang.Object cell, boolean collapse) isDeletableTheCell(com.mxgraph.model.mxCell cell) isDoubleRepeatedElementInPath(int element, java.util.Vector path) isEdgeCorrect(com.mxgraph.model.mxCell cell) isInEdgesToPortsMatrix(com.mxgraph.model.mxCell ce ll, java.lang.String type) isOnlyPlotCompare(com.mxgraph.model.mxCell cell) isPlot(com.mxgraph.model.mxCell cell) isRepeatedElementInPath(int element, java.util.Vector path) printAdjacenceMatrix() printCells(java.lang.String label, 48 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS Modificador y tipo void void void void void void int void void void void void void void void boolean boolean boolean boolean void Método java.lang.Object[] cells) printEdgesToPortsMatrix() printEdgesToVertexMatrix() printSinkPathMatrix() printSourcePathMatrix() printVertexVector() refreshGraph() searchVertexInOperationsMatrix(com.mxgraph.model. mxCell vertex) setCellAttribute(com.mxgraph.model.mxCell cell, java.lang.String attribute, java.lang.String attributeValue) setOutputSequence(com.mxgraph.model.mxCell cell, S equence sequence) showCartesianPlot(com.mxgraph.model.mxCell cell) showImaginaryPlot(com.mxgraph.model.mxCell cell) showModulePlot(com.mxgraph.model.mxCell cell) showPhasePlot(com.mxgraph.model.mxCell cell) showPolarPlot(com.mxgraph.model.mxCell cell) showRealPlot(com.mxgraph.model.mxCell cell) sinkContainsBadLoop() sinkContainsLoop() sourceContainsBadLoop() sourceContainsLoop() updateData() Esta lista de métodos como tal, puede darnos poca información del funcionamiento de la aplicación, ya que es información totalmente inconexa la que podemos deducir del nombre de los métodos. Así pues, procederemos a explicar con un poco más de detenimiento el funcionamiento de esta clase. Cuando se añade un bloque funcional al grafo del Panel de Operaciones, se desencadena una llamada al método insertOperation que, por un lado realiza el dibujo del vértice con sus puertos de entrada y salida predeterminados según el tipo de operación y, por otro, crea el objeto SequenceGraphOperations asociado al tipo de operación del bloque funcional. Toda esta información se añade a la instancia operationsMatrix. En caso de que el bloque funcional sea eliminado, se hace una llamada a deleteCell que elimina esa entrada de la operationsMatrix y del grafo del Panel de Operaciones. Cuando, en el proceso de ejecución normal de la aplicación, se quiere visualizar un resultado por pantalla, bien a través de los Show Plots, o bien a través del Print Numeric Values, se hace una llamada al método analysis que realiza la función de cálculo en cuatro pasos: 1. Actualiza los datos (llamada a updateData). 2. Analiza el grafo (llamada a analyseGraph). 49 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS 3. Si no hay error, calcula el resultado de las operaciones (llamada a calculateOperations). 4. Comprueba si no hay errores de desbordamiento en las operaciones (llamada a checkOperations). Analicemos ahora más detenidamente qué hace cada uno de estos cuatro métodos llamados. 3.4.4.1 updateData Este método realiza la actualización de las instancias del grafo asociadas a la morfología del mismo. Es decir, recoge los datos del estado actual del grafo para poder analizarlo con detenimiento. Las instancias que se actualizan son las siguientes: • • • • • edgesToPortsMatrix, a través del método getEdgesToPortsMatrix. edgesToVertexMatrix, a través del método getEdgesToVertexMatrix. adjacenceMatrix, a través del método getAdjacenceMatrix. sourcePathMatrix, a través del método getSourcePathMatrix, que realiza la búsqueda de caminos por el método de búsqueda en anchura (BFS). sinkPathMatrix, a través del método getSinkPathMatrix, que realiza la búsqueda de caminos por el método de búsqueda en anchura (BFS). 3.4.4.2 analyseGraph Una vez actualizados los datos morfológicos del grafo, llega la hora de analizarlos. El método analyseGraph se encarga de esta función. Este método comprueba que todos los bloques funcionales estén conectados, que no haya puertos sin conectar, que existan al menos una fuente y un sumidero de información e incluso que los lazos que existan, tengan un retraso incluido y que este sea distinto de cero. En caso de encontrar error, este método devolverá una cadena de caracteres con los errores encontrados. 50 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS 3.4.4.3 calculateOperations En caso de no haber encontrado error a la hora de analizar el grafo, se realizará el cálculo de las operaciones contenidas en él. Es por ello por lo que se realiza la llamada al método calculateOperations. Este método sigue una pauta muy simple y es colocar todas las secuencias de salida de los bloques operacionales en los puertos de entrada indicados por la matriz de adyacencias y realizar el cálculo de cada bloque funcional. Este paso se repite tantas veces como indique el número de iteraciones. El número de iteraciones depende del tipo de grafo. Si tenemos un grafo sin lazos, el número de iteraciones se calcula teniendo en cuenta el camino más largo entre una fuente y un sumidero. Si en el grafo se encuentra algún lazo, el número de iteraciones es el predeterminado por la instancia iterationsNumber de la clase. 3.4.4.4 checkOperations Por último, una vez realizados todos los cálculos, llega el momento de comprobar si ha habido desbordamiento en las operaciones. Este método comprueba que ningún resultado de las operaciones contiene elementos que son infinitos o NaN. En caso de encontrar error devuelve una cadena de caracteres con el error encontrado. 3.4.5 EditableTableModel y NotEditableTableModel Ambas clases son clases de segundo nivel, es decir, que sirven de soporte a otra clase de primer nivel, como es la TDSJTable, que trata directamente con la clase principal. Estas dos clases han sido creadas con el único objetivo de permitir convertir una tabla de datos en editable y no editable de la manera más rápida posible. Ambas clases extienden a la clase DefaultTableModel, que es la clase base de Java para la construcción de tablas de datos. Estas clases, al ser extensiones, no tienen definidos constructores (ya que utilizan el propio de la clase padre). Tan sólo tienen dos métodos (además de los propios del padre) que se superponen a los de la clase padre: 51 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS Modificador y tipo java.lang.Class boolean Método getColumnClass(int col) isCellEditable(int row, int column) El método getColumnClass devuelve las clases según el formato predeterminado para nuestras tablas de datos, es decir, la primera columna es de tipo Integer, mientras que el resto son de tipo Double. Por su parte, el método isCellEditable devuelve siempre verdadero o siempre falso, dependiendo de si la clase es EditableTableModel o NotEditableTableModel respectivamente. Es mediante este artificio que se consigue una tabla de datos editable o no editable. 3.4.6 TDSJTable La clase TDSJTable extiende a la clase JTable de Java. Esta clase se ha creado con el objetivo de conseguir añadir, eliminar y extraer datos de manera rápida de las tablas de datos utilizadas en la aplicación además de poder hacerlas editables y no editables con total facilidad. Esta clase, aunque hereda los constructores, métodos e instancias de la clase padre, JTable, tiene definidos varios métodos más: Modificador y tipo static void static void static void static static static static void boolean void void static void Método add2SequencesToTable(Sequence sequence1, Sequenc e sequence2, javax.swing.JTable table) addSequenceToTable(Sequence sequence, javax.swing.JTable table) addTableToSequence(Sequence sequence, javax.swing.JTable table) cleanTable(javax.swing.JTable table) errorTableValues(javax.swing.JTable table) setTableEditable(javax.swing.JTable table) setTableLimits(javax.swing.JTable table, int minSet, int maxSet) setTableNotEditable(javax.swing.JTable table) Como se puede observar, los métodos son autodescriptivos, por lo que no nos extenderemos más en la explicación y remitiremos al lector interesado a la documentación de la aplicación (javadoc) para ampliar la información. 52 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS 3.4.7 AppletGUI_v1_02 y ApplicationLauncher Estas son las clases principales del applet y la aplicación. Para el primero, sólo es necesaria la clase AppletGUI_v1_02, para la aplicación, además de la clase anterior, es necesaria la clase ApplicationLauncher. El objeto de la clase ApplicationLauncher es el de crear un JFrame dentro del lazo main que sirva de soporte para que la clase AppletGUI_v1_00 se ejecute dentro de él. Por su parte, la clase AppletGUI_v1_02 es la clase principal donde reside toda la lógica de la aplicación. Es decir, se encarga de aglutinar todas las partes funcionales en las que se divide el código y ofrecer al usuario una interfaz amigable. La programación de esta clase está basada en eventos. Quiere ello decir que la aplicación salta de un estado a otro a través de los distintos eventos provocados por el usuario como consecuencia de su interacción con la aplicación, es decir, no sigue un proceso lineal de ejecución, sino que es el usuario, en su libre albedrío, el que decide cómo se ejecuta la aplicación. En esta clase también está contenido el formulario de la aplicación, que es la “cara visible” de todo el código programado. Como se puede observar en la siguiente figura, existen dos grandes grupos, por un lado el grupo JApplet, que constituye la ventana principal donde se ejecuta el applet en el navegador y, por otro lado, Other Components, que constituyen todas las ventanas y cuadros de diálogos presentes en la ventana emergente de la aplicación una vez esta se ejecuta. 53 SOFTWARE PARA CÁLCULO Y APRENDIZAJE DE SEÑALES DISCRETAS 54