miércoles, enero 29, 2014

Licencia de la extensión extSDF

No hay comentarios.:
La extensión extSDF fue desarrollada y se distribuye bajo los términos de la licencia GPL versión 2, compatible con las licencias de cada uno de los componentes empleados en su desarrollo.
El API 4.2 de UNIDATA y el API SLF4J para la generación de logs, se distribuyen con una licencia MIT compatible con la licencia GPL.
El API empleado para la generación de los videos en formato QuickTime Movie (MOV) se distribuye bajo la licencia Creative Commons Attribution 3.0, compatible con la licencia GPL.
Leer más »

Probar extSDF utilizando los binarios

No hay comentarios.:
Para probar la extensión desarrollada no es necesario tener que configurar todo el IDE de desarrollo. Esta puede ser probada directamente desde los binarios.
Para probar la extensión descargamos y descompactamos el gvSIG 1.12 portable desde la dirección URL:
https://downloads.gvsig.org/download/gvsig-desktop/other-dists/gvSIG_1.12-portable/gvSIG-1.12-build1417-lin-x86-portable.tgz
Descargamos los binarios de la extensión extSDF desde la dirección URL:

https://docs.google.com/uc?authuser=0&id=0B_guBlaZtRQ9MWhaaEJ3YnFhejQ&export=download
El archivo descargado uclv.gvsig.extsdf.tar.gz lo descompactamos y movemos la carpeta uclv.gvsig.extsdf hacia la carpeta de las extensiones del gvSIG portable:
<RUTA_GVSIG_PORTABLE>/bin/gvSIG/extensiones
quedando la nueva ruta:
<RUTA_GVSIG_PORTABLE>/bin/gvSIG/extensiones/uclv.gvsig.extsdf
Una vez movida la carpeta de la extensión ya podemos ejecutar el gvSIG portable para probar la extensión. Para esto ejecutamos el script:
<RUTA_GVSIG_PORTABLE>/bin/gvSIG.sh
La extensión puede ser probada con los datos de prueba  en la dirección URL:
http://lsi.ugr.es/~romel/cru_ts3.21.1901.1910.tmp.dat.nc.gz
Leer más »

Concluye el desarrollo de la extensión

No hay comentarios.:
La etapa de desarrollo de la extensión extSDf para dar soporte al formato de archivo NetCDF en el gvSIG 1.12 finalizó exitosamente, lográndose los resultados y objetivos planteados.
Para el desarrollo de la extensión se tomó como base el sistema empleado por las capas Raster del gvSIG, por lo que no fue necesario la reimplementación del mecanismo de representación gráfica de la capa. Para integrar el nuevo formato de datos a los formatos de datos en el gvSIG como capas Raster, se creó una fuente de datos encargada de manipular la información desde un archivo NetCDF (uclv.gvsig.extsdf.raster.NetCDFRasterDataset). La fuente de datos es la encargada de mediar entre la información proveniente del archivo NetCDF y la información solicitada por la capa raster (FlyrRasterSE) para su representación gráfica. En la fuente de datos se realiza el manejo de las operaciones de zoom, desplazamiento y rotación de la capa (getWindowRaster), representando en cada momento un fragmento de los datos del archivo NetCDF.
Asociada a la fuente de datos se implementó un controlador para el archivo NetCDF (uclv.gvsig.extsdf.NetCDFController), el cual es empleado en toda la extensión para interactuar directamente con la información contenida en el archivo. Su mayor uso se hace en la fuente de datos para leer la información en dependencia del tipo de dato, aunque también es empleado en el resto de los elementos que componen la extensión. El controlador se encarga de manejar el sistema de coordenadas que se está representando gráficamente, así como los ejes de coordenadas y las variables asociadas al sistema de coordenadas. En caso de que la variable a representar contenga una dimensión de tiempo, el controlador se encarga de cargar en memoria sólo los datos para un sólo instante de tiempo y así disminuir el consumo de memoria de la extensión.
Vinculado a la capa Raster y a la información manejada en el archivo NetCDF se creó un panel de configuración que permiten modificar algunos parámetros de la representación gráfica. En el panel de configuración NetCDF (uclv.gvsig.extsdf.properties.panels.NetCDFPanel) se puede seleccionar el sistema de coordenadas a representar, así como opciones de formato de fecha y hora. En caso de que el sistema de coordenadas representado contenga una variable que represente tiempo, permite seleccionar que instante de tiempo se representará en la gráfica. Una de las características de la extensión, es que permite generar animaciones a partir de archivos NetCDF cuyo sistema de coordenadas representado contiene una variable de tiempo. Esta característica debe ser activada a través del panel de configuración del archivo NetCDF.
Todas las propiedades que se configuran de una capa Raster (estadísticas de la capa, paleta de colores, histograma, transformaciones, etc.) en el gvSIG se almacenan en una archivo XML con extensión RMF. La configuración de la capa asociada a un archivo NetCDF (uclv.gvsig.extsdf.NetCDFConfiguration) también es almacenada en ese archivo XML a través de un serializador (uclv.gvsig.extsdf.raster.NetCDFConfigurationSerializer) que se encarga de escribir y leer la información desde el archivo XML. Esta información se guarda desde el panel de configuración NetCDF y se lee cuando la fuente de datos accede a la información del archivo NetCDF.
Para generar la animación de los datos contenidos en el archivo NetCDF en el transcurso de una dimensión de tiempo se implementó una extensión (uclv.gvsig.extsdf.timeslider.TimeSliderExtension) que incluye una ventana de control de la animación, así como paneles para la configuración de la animación. En la configuración de la animación se permite seleccionar un intervalo de tiempo en el cual se desea realizar la animación, así como el modo de animación (sencillo, repetitivo, alternando la dirección) y el retardo de la animación. El parámetro de retardo de la animación debe ser seleccionado a gusto en dependencia de las prestaciones de la computadora donde ejecuta el gvSIG, pues si usamos un valor de retardo muy corto en una computadora de bajas prestaciones esto provocará que ocurran "flashes" o pantallas en blanco entre las capas animadas. La ventana de animación permite exportar una animación o fragmento de la animación a un formato de video QuickTime Movie (MOV).
La extensión fue probada sobre el gvSIG 1.12 portable con datos reales de temperaturas pertenecientes al British Atmospheric Data Centre, RAL, provistos por la Unidad de Investigaciones Climáticas de la Universidad del Este de Anglia en Reino Unido. Para obtener más información sobre los datos empleados para la validación consultar http://badc.nerc.ac.uk/data/cru/.
A continuación se muestran un video de la extensión en funcionamiento:
En el Laboratorio de Computación Gráfica del Centro de Estudios de Informática se continuará la implementación de nuevos controladores para el soporte de nuevos formatos de datos como es el formato HDF, así como algoritmos de conversión entre los  formatos de datos empleados en el laboratorio.
Leer más »

Usando el API 4.2 para NetCDF de UNIDATA

No hay comentarios.:
Al comenzar el desarrollo del proyecto, se había decidido emplear la biblioteca de HDF-Java 2.9, la cual tiene soporte para archivos HDF4, HDF5 y NetCDF. Luego de realizado un estudio sobre el API de HDF-Java se detectó que internamente esta biblioteca emplea el API para el formato NetCDF que provee UNIDATA. La versión 2.9 de HDF-Java emplea la versión 4.0 del API de NetCDF. Esta versión ya se encuentra en desuso, y ya no se encuentra disponible en los servidores de UNIDATA.
Se decidió no emplear la biblioteca HDF-Java para el desarrollo del proyecto, y en lugar de esta emplear el API para archivos NetCDF en su versión 4.2, del cual se cuenta con el código fuente y la documentación del API en la dirección URL:
ftp://ftp.unidata.ucar.edu/pub/netcdf-java/v4.2/
Se descargó el archivo mínimo del API de NetCDF desde la URL:
ftp://ftp.unidata.ucar.edu/pub/netcdf-java/v4.2/netcdf-4.2.jar
Fue necesario descargar el API de SLF4J para Logs desde la URL:
http://www.slf4j.org/dist/slf4j-1.7.5.tar.gz
Del cual se empleó la biblioteca:
slf4j-api-1.7.5.jar

Usando el API 4.2 de UNIDATA

El API 4.2 de UNIDATA brinda una serie de ventajas sobre el API 4.0 empleado por la biblioteca HDF-Java 2.9. En esta nueva versión del API se incorpora el concepto de sistemas de coordenadas mediante la clase CoordinateSystem. Un sistema de coordenadas no es más que una abstracción compuesta por un conjunto de ejes de coordenadas o dimensiones (CoordinateAxis) y se encuentra asociado a una o más variables de datos. Esta nueva abstracción permite la identificación automática de los diferentes ejes de coordenadas que pueden incidir en la representación gráfica de la información del archivo NetCDF (latitud, longitud, tiempo, altura,...).
Para obtener todos los sistemas de coordenadas asociados a un archivo NetCDF, podemos ejecutar el siguiente fragmento de código:
// Abre el archivo NetCDF
NetcdfFile file = NetcdfFile.open(filename);
NetcdfDataset fileDataSet = new NetcdfDataset(file);

// Inicializa las estructuras para almacenar los ejes coordenados
datas = new ArrayList<CoordinateSystem>();

// Obtiene todos los sistemas de coordenadas
List<CoordinateSystem> coordSystems = fileDataSet.getCoordinateSystems();
Para acceder a los ejes de coordenadas o dimensiones que componen el sistema de coordenadas se emplean los métodos en función del eje de coordenadas que queremos obtener:

  • getCoordinateAxes(): Devuelve una lista con todos los ejes de coordenadas.
  • getAzimuthAxis(): Sistema de coordenadas polares
  • getElevationAxis(): Sistema de coordenadas polares
  • getHeightAxis(): Sistema de coordenadas verticales
  • getLatAxis(): Devuelve el eje de coordenadas asociado a la latitud en un sistema geográfico
  • getLonAxis(): Devuelve el eje de coordenadas asociado a la longitud en un sistema geográfico
  • getPressureAxis(): Sistema de coordenadas verticales
  • getRadialAxis(): Sistema de coordenadas polares
  • getTaxis(): Devuelve el eje de coordenadas asociado a una variable de tiempo
  • getXaxis(): Transformación de los ejes de coordenadas de latitud
  • getYaxis(): Transformación de los ejes de coordenadas de longitud
  • getZaxis(): Transformación de los ejes de coordenadas verticales
En la extensión solo emplearemos los ejes de coordenadas de latitud, longitud y tiempo, así como sus transformaciones X e Y en caso de existir. Para obtener más información puede consultar el modelo de  datos.
Para determinar si una variable de datos está asociada a un sistema de coordenadas, o sea, si se puede acceder a los datos de la variable utilizando las dimensiones que componen el sistema de coordenadas, ejecutamos el siguiente fragmento de código:
CoordinateSystem system = ...

// Obtenemos todas las variables del archivo NetCDF
List<Variable> vars = file.getVariables();

// Recorre todas las variables para encontrar las asociadas al sistema de coordenadas
for (Variable var : vars) {
  // Verifica si la variable está asociada al sistema de coordenadas                
  if (system.isCoordinateSystemFor(var)) {
    ...
  }
}

Leer más »

miércoles, enero 22, 2014

Agregar una nueva entrada en el menú contextual de la Tabla de Contenido (TOC) y en la barra de herramienta genérica que muestre las propiedades del NetCDF

No hay comentarios.:
Por: Daynier Cardoso Roques
El formato de dato NetCDF es un formato de dato científico en el cual se puede almacenar gran cantidad de información. Los archivos de este tipo contienen algunas propiedades que es importante mostrar y configurar con el fin de lograr una correcta visualización. Algunas de estas propiedades son:
  • Sistemas de Coordenadas, por ejemplo Longitud y Latitud
  • Variable Medida, por ejemplo Temperatura, Presión, Nubosidad, etc.
  • X_Dimensión
  • Y_Dimensión
Y en caso de ser un NetCDF 3D o 4D puede tener:
  • Tiempo
  • Altura

Añadiendo la nueva entrada


Para crear una nueva entrada en la Tabla de Contenido (TOC) es necesario crear una clase que herede de la clase abstracta AbstractTocContextMenuAction e implemente la interfaz IGenericToolBarMenuItem lo que permite añadir la nueva entrada en el TOC y en la Barra de Herramienta Genérica. Luego en la nueva clase creada añadimos los siguientes import:
import javax.swing.Icon;
import org.gvsig.fmap.raster.layers.FLyrRasterSE;
import org.gvsig.gui.beans.panelGroup.PanelGroupManager;
import org.gvsig.gui.beans.panelGroup.tabbedPanel.TabbedPanel;
import org.gvsig.raster.gui.IGenericToolBarMenuItem;
import org.gvsig.raster.util.RasterToolsUtil;
import uclv.gvsig.extsdf.raster.NetCDFRasterDataset;
import com.iver.andami.PluginServices;
import com.iver.andami.ui.mdiManager.WindowInfo;
import com.iver.cit.gvsig.fmap.layers.FLayer;
import com.iver.cit.gvsig.panelGroup.PanelGroupDialog;
import com.iver.cit.gvsig.panelGroup.loaders.PanelGroupLoaderFromExtensionPoint;
import com.iver.cit.gvsig.project.documents.view.toc.AbstractTocContextMenuAction;
import com.iver.cit.gvsig.project.documents.view.toc.ITocItem;

La cual deberá implementar los siguientes métodos:

  • boolean isVisisble(TocItem item, FLayer[] selectedItems): Método que será invocado para verificar si el ítem del menú debe ser visible o no. Este método devuelve true si la capa activa es construida a partir de un archivo NetCDF en otro caso devolverá false.

public boolean isVisible(ITocItem item, FLayer[] selectedItems) {
  if ((selectedItems == null) || (selectedItems.length != 1))
    return false;
  FLayer lyr = selectedItems[0];
  if (lyr instanceof FLyrRasterSE) {
    FLyrRasterSE fr = (FLyrRasterSE) lyr;
    return fr.getDataSource().getDataset(0)[0] instanceof NetCDFRasterDataset;          
  }
  return false;
}
  • boolean isEnabled(ITocItem item, FLayer[] selectedItems): Método que será invocado para verificar si el ítem del menú debe estar habilitado o no. Este método devuelve true si la capa activa es construida a partir de un archivo NetCDF en otro caso devolverá false.

public boolean isEnabled(ITocItem item, FLayer[] selectedItems) {
  if ((selectedItems == null) || (selectedItems.length != 1))
    return false;
  FLayer lyr = selectedItems[0];
  if (lyr instanceof FLyrRasterSE) {
    FLyrRasterSE fr = (FLyrRasterSE) lyr;
    return fr.getDataSource().getDataset(0)[0] instanceof NetCDFRasterDataset;          
  }
  return false;
}

  • void execute(ITocItem item, FLayer[] selectedItems): Este método es el encargado de gestionar la apertura de la ventana que mostrará los paneles de propiedades del NetCDF.

public void execute(ITocItem item, FLayer[] selectedItems) {
  ...
  FLayer lyr = getNodeLayer(item);
  ...
  enableEvents = false;
  PanelGroupManager manager = PanelGroupManager.getManager();
  manager.registerPanelGroup(TabbedPanel.class);
  manager.setDefaultType(TabbedPanel.class);
  TabbedPanel panelGroup = (TabbedPanel)manager.getPanelGroup(lyr);
  PanelGroupLoaderFromExtensionPoint loader = new PanelGroupLoaderFromExtensionPoint("NetCDFPropertiesDialog");
  properties = new PanelGroupDialog(lyr.getName(), PluginServices.getText(this,"NetCDF_properties"), 550, 450, (byte) (WindowInfo.MODELESSDIALOG | WindowInfo.RESIZABLE | WindowInfo.MAXIMIZABLE), panelGroup);
  properties.loadPanels(loader);
  enableEvents = true;
  RasterToolsUtil.addWindow(properties);
  ...
}

  • Icon getIcon(): Devuelve el icono del ítem del menú.
  • String getText(): Devuelve el texto que se debe ver en el menú.
  • String getGroup(): Devuelve el nombre del grupo al que pertenece el ítem de menú.
  • String getGroupOrder(): Devuelve el orden del grupo.
  • String getOrder(): Devuelve orden del ítem.

Es importante tener en cuenta que los paneles de propiedades que serán mostrados en la ventana deben registrarse en un nuevo punto de extensión para que los paneles puedan ser cargados luego dentro del método execute().
// Obtiene todos los puntos de extensión del gvSIG
ExtensionPoints extensionPoints = ExtensionPointsSingleton.getInstance();

// Creación del punto de extensión para registrar paneles en el cuadro de propiedades.
if (!extensionPoints.containsKey("NetCDFPropertiesDialog")) {
extensionPoints.put(new ExtensionPoint("NetCDFPropertiesDialog",
"NetCDF Properties registrable panels (register instances of javax.swing.JPanel)"));
}

// Añadimos el panel al cuadro de propiedades.
extensionPoints.add("NetCDFPropertiesDialog", "NetCDF",NetCDFPanel.class);

// Añadimos las entradas del menú del toc de raster
extensionPoints.add("View_TocActions", "NetCDFProperties",PropertiesNetCDFRasterTocMenuEntry.getSingleton());

// Añadimos la entrada en la Barra de Herramienta Genérica
org.gvsig.raster.util.extensionPoints.ExtensionPoint point = org.gvsig.raster.util.extensionPoints.ExtensionPoint.getExtensionPoint("GenericToolBarMenu");
point.register("NetCDFProperties",PropertiesNetCDFRasterTocMenuEntry.getSingleton());

Todos los paneles de propiedades deben implementar la clase abstracta AbstractPanel que contiene los métodos abstracto accept(), apply(), cancel(), los cuales definirán el comportamiento de dichos botones cuando se haga clic sobre ellos. Además los paneles tendrán que implementar el método setReference(Object ref) a través del cual reciben todos los objetos relacionados con dichos paneles como es el caso de el objeto Flayer.
Leer más »

domingo, enero 19, 2014

Metodología para la adición de nuevas extensiones a gvSIG

No hay comentarios.:
Por: Alexis Fajardo Moya


Las extensiones son la vía en la que los complementos extienden a Andami. Toda clase que implemente a la interfaz com.iver.andami.plugins.IExtension es una extensión, aunque esta clase no debe ser implementada directamente, para ello se provee la clase abstracta que la implementa com.iver.andami.plugins.Extension y de la cual deben heredar las extensiones que se deseen añadir.
Durante la inicialización, Andami instancia a cada una de las extensiones definidas. Las extensiones son capaces de agregar controles (herramientas, barras de herramientas y menús) a la interfaz de usuario; cuando se ejecuta un click en alguno de estos controles o alguno de ellos es modificado, se invoca al método execute() de la extensión asociada. Las extensiones pueden controlar también si los controles definidos están habilitados o no, y cuando son visibles o no.
Aun cuando se implemente esta interfaz para añadir una nueva extensión, es necesario definirla con un constructor vacío porque esta será invocada para crear una instancia de la extensión durante la inicialización.
Aquellos complementos bien instalados se crearán una instancia por cada extensión del complemento.
Cada vez que se cambia el foco de la venta activa y cada vez que se ejecuta el método execute(), Andami chequea los métodos isEnabled() e isVisible() de cada extensión, para decidir cuál de ellas deben estar habilitadas y visibles.
El método execute() será llamado desde el hilo de la interfaz de usuario (GUI), por tanto la GUI será bloqueada durante la ejecución del código implementado en el método; por tanto la ejecución debe ser rápida. En caso de que se inicie un proceso extenso desde execute(), un nuevo hilo debe ser inicializado.
Normalmente las extensiones no deben implementar directamente a la interfaz IExtension, sino heredar de la clase abstracta Extension.
A continuación se muestran los métodos que componen a la interfaz IExtension y su explicación:
  • void initialize(): Método donde se implementa el código de la inicialización de la extensión
  • void postInitialize(): Método donde se implementa la post inicialización de la extensión. Este código se ejecuta por Andami después de inicializar todas las extensiones.
  • void Terminate(): Método que se ejecuta al terminar la ejecución de Andami.
  • void Execute(String actionCommand): Este método se ejecuta al presionar el click del mouse sobre alguno de los controles definidos por la extensión (menús, herramientas, etc.). El parámetro actionCommand es útil para diferenciar los eventos generados por los controles añadidos por la misma extensión.
  • boolean isEnabled(): Método que se invoca para chequear si es habilitada o no la extensión y sus controles asociados. Los controles deshabilitados se muestran en color gris claro.
  • boolean isVisible(): Método que se invoca para chequear la visibilidad de la extensión y sus controles asociados.
  • IExtensionStatus getStatus(),
  • IExtensionStatus getStatus(IExtension extension): Devuelve el estado de la extensión, que será consultada para chequear si la extensión posee algún dato sin salvar a alguna tarea asociada ejecutándose de fondo.
Una vez implementadas todas las clases extensiones que se desean añadir en el complemento, es necesario definir en el archivo “./config/config.xml” los parámetros de cada una de las extensiones. En el tag <extensions> del archivo xml de configuración del complemento se definen las propiedades de cada una de las extensiones del complemento teniendo en cuenta el siguiente prototipo:
<extension
class-name=”Nombre de la clase que implementa una extension. Ejemplo: uclv.extsdf.NetCDFRasterAnimationExtension
description=”Descripción de la extensión
active=”true o false, que define si la extensión se activa o no
priority=”Valor numérico que define la prioridad de la extensión en la carga inicial”>
<menu <!--Define un menú en la GUI-->
text=”Texto del menú, los niveles se definen mediante ‘/’. Las extensiones que poseen la misma ruta son agrupados en el mismo menú en la GUI.
key=””
mnemonic=”Método nemotécnico
tooltip=”Texto breve que explica la funcionalidad del menú. Se muestra al pasar el puntero del mouse sobre el menú.
action-command=”cadena de texto que se pasa al método execute() de la clase que implementa una extensión.”
icon=”Icono del menú”>
</menu>
<tool-bar <!--Define una barra de herramienta en la GUI-->
name="Nombre de la barra de herramienta. Este mismo valor puede ser empleado en la declaración de otras extensiones para agrupar todos los controles del complemento en una misma barra de herramientas."
position="valor numérico que define la posición de esta barra de herramienta en la barra de herramienta general de gvSIG">
<action-tool <!--define una herramienta de la barra de herramienta-->
icon="imagen del botón de la barra de herramienta"
tooltip="Texto breve que explica la funcionalidad de la herramienta. Se muestra al pasar el puntero del mouse sobre el icono de la herramienta."
action-command="Cadena de texto que se pasa al método execute() de la clase que implementa una extensión"
position="Valor numérico que define la posición de la herramienta en la barra de herramienta."/>
</tool-bar>
</extension>
Todas las funcionalidades que se deseen añadir en el complemento como extensiones de gvSIG pueden seguir tres estrategias:
  • Implementar cada funcionalidad como una extensión (cada funcionalidad implementa a la clase abstracta Extension) y luego se añade la especificación de cada una de las extensiones en el archivo de configuración del complemento,
  • Implementar todas las funcionalidades en una única extensión y diferenciarlas mediante el parámetro action-command, o
  • La combinación de las dos anteriores.
Resulta válido aclarar que los controles que se implementan para una extensión poseen el mismo action-command.

Leer más »

sábado, enero 11, 2014

Leer archivos NetCDF desde Java

No hay comentarios.:
El formato NetCDF ( del inglés Network Common Data Format) fue creado por UNIDATA. Es un formato binario orientado a arreglos (arrays) de datos, que facilita la manipulación de datos espaciales a través de varias dimensiones de forma eficiente. El formato incluye la información necesaria para determinar las dimensiones y variables almacenadas, así como sus valores, tipos de datos y atributos adicionales que son agregados en el momento de creación del archivo. Es un formato portable que puede ser manipulado desde varios lenguajes de programación con las bibliotecas NetCDF (C/C++, Fortran, Java, Perl, Python, etc.). En nuestro caso veremos como manipular este formato de archivos empleando las bibliotecas HDF-Java.
Para más información acerca del formato NetCDF se puede consultar: The NetCDF Users' Guide.

Leer archivos NetCDF desde Java

Antes de comenzar a trabajar con los archivos NetCDF añadimos a nuestro proyecto las bibliotecas HDF-Java como se explicó en la entrada anterior. En la clase donde vamos a trabajar con los archivos NetCDF es necesario agregar los siguientes import:

import java.util.List;
import ucar.ma2.Array;
import ucar.ma2.DataType;
import ucar.ma2.Index;
import ucar.ma2.Range;
import ucar.nc2.Attribute;
import ucar.nc2.Dimension;
import ucar.nc2.Group;
import ucar.nc2.Variable;
import ucar.nc2.NetcdfFile;
Para abrir un archivo NetCDF empleamos la clase NetcdfFile de la siguiente forma:
NetcdfFile ncdf  = NetcdfFile.open("/home/millo/Documents/NetCDF/netCDFTest.nc");
Una vez abierto el archivo NetCDF podemos acceder a toda la información que contiene el archivo. Para acceder a los atributos generales declarados cuando se creó el archivo NetCDF ejecutamos el siguiente fragmento de código:

List<Attribute> attrs = ncdf.getGlobalAttributes();
System.out.println("Total de atributos "+attrs.size());
for (Attribute attr: attrs){
  System.out.print("  Nombre: " + attr.getName() + " (Tipo: " + attr.getDataType().name() + ", Valor: ");

  if(attr.getDataType()==DataType.DOUBLE)
    System.out.println(attr.getNumericValue()+")"
);
  else
    System.out.println(attr.getStringValue()+")"
);
}
Los datos dentro de un archivo NetCDF pueden estar divididos por grupos. Los elementos que conforman al archivo NetCDF pueden ser accedidos directamente desde el objeto NetcdfFile o a través del objeto de tipo Group que representa a cada grupo. Para acceder a los grupos de un archivo NetCDF podemos ejecutar el siguiente fragmento de código:
List<Group> groups=ncdf.getRootGroup().getGroups();
System.out.println("Total de grupos: "+groups.size());
for(Group group : groups){
  System.out.println("  Nombre: " + group.getNameAndAttributes());
}
Para el trabajo con el formato NetCDF trabajaremos accediendo los elementos del formato directamente desde el objeto NetcdfFile, ya que en caso de ser necesario manipular los grupos de datos, cada uno de los elementos del archivo permite determinar el grupo al cual pertenece.
Las dimensiones y variables de un archivo NetCDF son dos elementos que están estrechamente relacionados. Todas las variables de una sola dimensión les corresponde un objeto de tipo Dimension, mientras que a las variables multidimensionales no. El objeto Dimension permite obtener el rango de las dimensiones que componen una variable. Para obtener todas las dimensiones de un archivo NetCDF ejecutamos el siguiente fragmento de código:
List<Dimension> dims =ncdf.getDimensions();
System.out.println("Total de dimensiones: "+dims.size());
for (Dimension dim : dims){
  System.out.println("  Nombre: " + dim.getName() + " ( Tamaño: " + dim.getLength()+")");
}
Los datos del archivo NetCDF se obtienen a través de los objetos de tipo Variable. Estos objetos a su ver tienen un conjunto de atributos y propiedades, entres las que se encuentran las dimensiones de la variables. Una variable unidimensional responde a un sólo objeto Dimension, mientras que una variable multidimensional responde a tantos objetos Dimension como dimensiones tenga. Las variables también tienen asociada una forma o shape, determinada por el tamaño de cada una de las dimensiones a las que responde la variable. Para obtener todas las variables de un archivo NetCDF ejecutamos el siguiente fragmento de código:
List<Variable> vars = ncdf.getVariables();
System.out.println("Total de variables "+vars.size());
for( Variable var: vars){
  System.out.print("  Nombre: " + var.getName() + " (Tipo: " + var.getDataType().name() + ", Dimensiones: " + var.getDimensionsString() + ", Tamaño:");
  int [] size = var.getShape();
  for(int i=0; i<size.length;++i){
    System.out.print(" " +size[i]);
  }
  System.out.println(")");
}
De igual forma que consultamos los atributos generales del archivo NetCDF podemos consultar los atributos de las variables ejecutando el siguiente fragmento de código:
Variable var = ...; // Obtenemos una variable
List<Attribute> attrs = var.getAttributes();
System.out.println("Total de atributos "+attrs.size());
for (Attribute attr: attrs){
  System.out.print("  Nombre: " + attr.getName() + " (Tipo: " + attr.getDataType().name() + ", Valor: ");
  if(attr.getDataType()==DataType.DOUBLE)
    System.out.println(attr.getNumericValue()+")");
  else
    System.out.println(attr.getStringValue()+")");
}
Cuando accedemos a los datos del archivo del formato NetCDF es necesario tener en cuenta las dimensiones que tiene la variable a la cual queremos acceder, pues por lo general, las variables con datos geográficos son de grandes dimensiones, y esto puede provocar la excepción OutOfMemory en Java. Una variante para corregir este imprevisto, es asignarle más memoria a la máquina virtual de Java, pero aún puede seguir ocurriendo la misma excepción. La otra forma más práctica de resolver este problema es no cargar en memoria toda la información de la variable, o sea, cargar la información de forma parcial. Cargar de forma parcial la información puede provocar en nuestra aplicación un pequeño retraso por las lecturas sucesivas desde el archivo, pero por lo general este retraso es poco notable, siendo mucho más notable la diferencia del consumo de memoria de la máquina virtual de Java.
Para acceder a un subconjunto de los datos de una variable, empleamos los objetos Range, los cuales permiten definir el rango de valores que se desea leer para cada dimensión de la variable. Por ejemplo, supongamos que tenemos un archivo NetCDF con una variable "tmn". Esta variable "tmn" de tipo real, está responde a tres dimensiones: "tiempo", "latitud" y "longitud", con tamaños 120, 360 y 720 respectivamente. Esto le daría a la variable "tmn" una forma tridimensional de 120x360x720, lo cual equivale a 31104000 valores reales que se deben almacenar en memoria (este valor puede resultar un poco pequeño comparado con el tamaño de otros archivos NetCDF). Si tratamos de leer todos los valores de esta variable en una PC con 1GB de RAM con los valores por defecto de la máquina virtual de Java, nos produce la excepción OutOfMemory. Sin embargo, si leemos estos valores para cada instante de la dimensión "tiempo", lo cual correspondería a 259200 (360x720) valores reales, la aplicación funcionaría correctamente incluso en PC con menos de 1GB de RAM. Tomando como base la definición de la variable "tmn", el siguiente fragmento de código lee los datos del archivo NetCDF para cada instante de la dimensión "tiempo", y luego accede a cada uno de los valores para procesarlos:
Variable tmn = ...; //Obtenemos la variable tmn
// Toma los rangos de las variables, de solo lectura
List<Range> ranges = tmn.getRanges();
// Crea una estructura con los rangos leidos
ArrayList<Range> newRanges = new ArrayList<Range>();
newRanges.add(ranges.get(0));
newRanges.add(ranges.get(1));
newRanges.add(ranges.get(2));
// Recorre todos los instantes de tiempo
for (int tm = 0; tm < 120; ++tm) {
  // Actualiza el rango de tiempo
  newRanges.set(0, new Range(tm, tm));
  // Lee los datos para cada instante de tiempo
  Array arr = tmn.read(newRanges);
  // Toma el índice del arreglo de datos
  Index idx = arr.getIndex();
  // Recorre todas las longitudes
  for(int lat = 0; lat < 360; ++lat) {
    for (int lon = 0; lon < 720; ++lon) {
      idx.set(0, lat, lon); // tiempo, latitud, longitud
      double val = arr.getDouble(idx);
      // PROCESAMOS EL VALOR LEIDO
    }
  }
}

De igual forma se pueden modificar otros o varios de los rangos para acceder a subconjuntos de datos más pequeños. Una vez que hemos finalizado el trabajo con el archivo NetCDF es necesario cerrarlo ejecutando el siguiente fragmento de código:
ncdf.close();
Leer más »