ucar.nc2.NCdump Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of netcdf Show documentation
Show all versions of netcdf Show documentation
The NetCDF-Java Library is a Java interface to NetCDF files,
as well as to many other types of scientific data formats.
The newest version!
/*
* Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package ucar.nc2;
import ucar.ma2.*;
import ucar.nc2.util.CancelTask;
import ucar.nc2.util.URLnaming;
import ucar.nc2.util.Indent;
import ucar.unidata.util.StringUtil2;
import java.io.*;
import java.util.*;
/**
* Print contents of an existing netCDF file of unknown structure, like ncdump.
*
* A difference with ncdump is that the nesting of multidimensional array data is represented by nested brackets,
* so the output is not legal CDL that can be used as input for ncgen. Also, the default is header only (-h)
*
* @author Russ Rew, John Caron
* @deprecated use NCdumpW, to handle Unicode correctly
*/
public class NCdump {
private static boolean debugSelector = false;
private static String usage = "usage: NCdump [-cdl | -ncml] [-c | -vall] [-v varName1;varName2;..] [-v varName(0:1,:,12)]\n";
/**
* Print netcdf "header only" in CDL.
* @param fileName open this file
* @param out print to this stream
* @return true if successful
* @throws IOException on write error
*/
public static boolean printHeader(String fileName, OutputStream out) throws java.io.IOException {
return print( fileName, out, false, false, false, false, null, null);
}
/**
* print NcML representation of this netcdf file, showing coordinate variable data.
* @param fileName open this file
* @param out print to this stream
* @return true if successful
* @throws IOException on write error
*/
public static boolean printNcML(String fileName, OutputStream out) throws java.io.IOException {
return print( fileName, out, false, true, true, false, null, null);
}
/**
* NCdump that parses a command string, using default options.
* Usage:
* NCdump filename [-ncml] [-c | -vall] [-v varName;...]
* @param command command string
* @param out send output here
* @return true if successful
* @throws IOException on write error
*/
public static boolean print(String command, OutputStream out) throws java.io.IOException {
return print( command, out, null);
}
/**
* ncdump that parses a command string.
* Usage:
* NCdump filename [-ncml] [-c | -vall] [-v varName;...]
* @param command command string
* @param out send output here
* @param ct allow task to be cancelled; may be null.
* @return true if successful
* @throws IOException on write error
*/
public static boolean print(String command, OutputStream out, ucar.nc2.util.CancelTask ct) throws java.io.IOException {
// pull out the filename from the command
String filename;
StringTokenizer stoke = new StringTokenizer( command);
if (stoke.hasMoreTokens())
filename = stoke.nextToken();
else {
out.write( usage.getBytes());
return false;
}
NetcdfFile nc = null;
try {
nc = NetcdfFile.open(filename, ct);
// the rest of the command
int pos = command.indexOf(filename);
command = command.substring(pos + filename.length());
return NCdump.print(nc, command, out, ct);
} catch (java.io.FileNotFoundException e) {
String mess = "file not found= "+filename;
out.write( mess.getBytes());
return false;
} finally {
if (nc != null) nc.close();
}
}
/**
* ncdump, parsing command string, file already open.
* @param nc apply command to this file
* @param command : command string
* @param out send output here
* @param ct allow task to be cancelled; may be null.
* @return true if successful
* @throws IOException on write error
*/
public static boolean print(NetcdfFile nc, String command, OutputStream out, ucar.nc2.util.CancelTask ct) throws java.io.IOException {
boolean showAll = false;
boolean showCoords = false;
boolean ncml = false;
boolean strict = false;
String varNames = null;
if (command != null) {
StringTokenizer stoke = new StringTokenizer( command);
while (stoke.hasMoreTokens()) {
String toke = stoke.nextToken();
if (toke.equalsIgnoreCase("-help")) {
out.write( usage.getBytes());
out.write( '\n');
return true;
}
if (toke.equalsIgnoreCase("-vall"))
showAll = true;
if (toke.equalsIgnoreCase("-c"))
showCoords = true;
if (toke.equalsIgnoreCase("-ncml"))
ncml = true;
if (toke.equalsIgnoreCase("-cdl"))
strict = true;
if (toke.equalsIgnoreCase("-v") && stoke.hasMoreTokens())
varNames = stoke.nextToken();
}
}
return NCdump.print( nc, out, showAll, showCoords, ncml, strict, varNames, ct);
}
/**
* ncdump-like print of netcdf file.
* @param fileName NetcdfFile to open
* @param out print to this stream
* @param showAll dump all variable data
* @param showCoords only print header and coordinate variables
* @param ncml print NcML representation (other arguments are ignored)
* @param strict print strict CDL representation
* @param varNames semicolon delimited list of variables whose data should be printed
* @param ct allow task to be cancelled; may be null.
* @return true if successful
* @throws IOException on write error
*/
public static boolean print(String fileName, OutputStream out, boolean showAll, boolean showCoords,
boolean ncml, boolean strict, String varNames, ucar.nc2.util.CancelTask ct) throws java.io.IOException {
NetcdfFile nc = null;
try {
//nc = NetcdfFileCache.acquire(fileName, ct);
nc = NetcdfFile.open(fileName, ct);
return print(nc, out, showAll, showCoords, ncml, strict, varNames, ct);
} catch (java.io.FileNotFoundException e) {
String mess = "file not found= "+fileName;
out.write( mess.getBytes());
return false;
} finally {
//NetcdfFileCache.release(nc);
if (nc != null) nc.close();
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
// heres where the work is done
/**
* ncdump-like print of netcdf file.
* @param nc already opened NetcdfFile
* @param out print to this stream
* @param showAll dump all variable data
* @param showCoords only print header and coordinate variables
* @param ncml print NcML representation (other arguments are ignored)
* @param strict print strict CDL representation
* @param varNames semicolon delimited list of variables whose data should be printed. May have
* Fortran90 like selector: eg varName(1:2,*,2)
* @param ct allow task to be cancelled; may be null.
* @return true if successful
* @throws IOException on write error
*/
public static boolean print(NetcdfFile nc, OutputStream out, boolean showAll, boolean showCoords,
boolean ncml, boolean strict, String varNames, ucar.nc2.util.CancelTask ct) throws java.io.IOException {
PrintWriter pw = new PrintWriter( new OutputStreamWriter(out));
return NCdumpW.print(nc, pw, showAll, showCoords, ncml, strict, varNames, ct);
}
/*
boolean headerOnly = !showAll && (varNames == null);
try {
if (ncml)
writeNcML(nc, out, showCoords, null); // output schema in NcML
else if (headerOnly)
nc.writeCDL(out, strict); // output schema in CDL form (like ncdump)
else {
PrintWriter pw = new PrintWriter( new OutputStreamWriter(out));
nc.toStringStart(pw, strict);
pw.print(" data:\n");
if (showAll) { // dump all data
for (Variable v : nc.getVariables()) {
printArray(v.read(), v.getName(), ps, ct);
if (ct != null && ct.isCancel()) return false;
}
}
else if (showCoords) { // dump coordVars
for (Variable v : nc.getVariables()) {
if (v.isCoordinateVariable())
printArray(v.read(), v.getName(), ps, ct);
if (ct != null && ct.isCancel()) return false;
}
}
if (!showAll && (varNames != null)) { // dump the list of variables
StringTokenizer stoke = new StringTokenizer(varNames,";");
while (stoke.hasMoreTokens()) {
String varSubset = stoke.nextToken(); // variable name and optionally a subset
if (varSubset.indexOf('(') >= 0) { // has a selector
Array data = nc.read(varSubset, false);
printArray(data, varSubset, ps, ct);
} else { // do entire variable
Variable v = nc.findVariable(varSubset);
if (v == null) {
ps.print(" cant find variable: "+varSubset+"\n "+usage);
continue;
}
// dont print coord vars if they are already printed
if (!showCoords || v.isCoordinateVariable())
printArray( v.read(), v.getName(), ps, ct);
}
if (ct != null && ct.isCancel()) return false;
}
}
nc.toStringEnd( ps);
ps.flush();
}
} catch (Exception e) {
e.printStackTrace();
out.write(e.getMessage().getBytes());
return false;
}
return true;
} */
/**
* Parse a section specification String. These have the form:
*
* section specification := selector | selector '.' selector
* selector := varName ['(' dims ')']
* varName := STRING
*
* dims := dim | dim, dims
* dim := ':' | slice | start ':' end | start ':' end ':' stride
* slice := INTEGER
* start := INTEGER
* stride := INTEGER
* end := INTEGER
*
*
* Nonterminals are in lower case, terminals are in upper case, literals are in single quotes.
* Optional components are enclosed between square braces '[' and ']'.
*
* @param ncfile look for variable in here
* @param variableSection the string to parse, eg "record(12).wind(1:20,:,3)"
* @return return CEresult which has the equivilent Variable
* @throws IllegalArgumentException when token is misformed, or variable name doesnt exist in ncfile
* @throws ucar.ma2.InvalidRangeException if section does not match variable shape
*
* @see SectionSpecification
*/
static private CEresult parseVariableSection( NetcdfFile ncfile, String variableSection) throws InvalidRangeException {
StringTokenizer stoke = new StringTokenizer(variableSection, ".");
String selector = stoke.nextToken();
if (selector == null)
throw new IllegalArgumentException("empty sectionSpec = " + variableSection);
// parse each selector, find the inner variable
boolean hasInner = false;
List fullSelection = new ArrayList();
Variable innerV = parseVariableSelector(ncfile, selector, fullSelection);
while (stoke.hasMoreTokens()) {
selector = stoke.nextToken();
innerV = parseVariableSelector(innerV, selector, fullSelection);
hasInner = true;
}
return new CEresult( innerV, fullSelection, hasInner);
}
/** public by accident */
static private class CEresult {
public Variable v; // the variable
public List ranges; // list of ranges for this variable
public boolean hasInner;
CEresult( Variable v, List ranges, boolean hasInner) {
this.v = v;
this.ranges = ranges;
this.hasInner = hasInner;
}
}
// parse variable name and index selector out of the selector String. variable name must be escaped
private static Variable parseVariableSelector( Object parent, String selector, List fullSelection)
throws InvalidRangeException {
String varName, indexSelect = null;
int pos1 = selector.indexOf('(');
if (pos1 < 0) { // no selector
varName = selector;
} else {
varName = selector.substring(0, pos1);
indexSelect = selector.substring(pos1);
}
if (debugSelector)
System.out.println(" parseVariableSection <"+selector+"> = <"+varName+">, <"+indexSelect+">");
Variable v = null;
if (parent instanceof NetcdfFile) {
NetcdfFile ncfile = (NetcdfFile) parent;
v = ncfile.findVariable(varName);
} else if (parent instanceof Structure) {
Structure s = (Structure) parent;
v = s.findVariable(varName); // LOOK
}
if (v == null)
throw new IllegalArgumentException(" cant find variable: "+varName+" in selector="+selector);
// get the selected Ranges, or all, and add to the list
Section section;
if (indexSelect != null) {
section = new Section(indexSelect);
section.setDefaults(v.getShape()); // Check section has no nulls, set from shape array.
} else
section = new Section(v.getShape()); // all
fullSelection.addAll(section.getRanges());
return v;
}
/** Make section specification String from a range list for a Variable.
* @param v for this Variable.
* @param ranges list of Range. Must includes all parent structures. The list be null, meaning use all.
* Individual ranges may be null, meaning all for that dimension.
* @return section specification String.
* @throws InvalidRangeException is specified section doesnt match variable shape
*/
public static String makeSectionString(VariableIF v, List ranges) throws InvalidRangeException {
StringBuilder sb = new StringBuilder();
makeSpec(sb, v, ranges);
return sb.toString();
}
private static List makeSpec(StringBuilder sb, VariableIF v, List orgRanges) throws InvalidRangeException {
if (v.isMemberOfStructure()) {
orgRanges = makeSpec(sb, v.getParentStructure(), orgRanges);
sb.append('.');
}
List ranges = (orgRanges == null) ? v.getRanges() : orgRanges;
sb.append( v.isMemberOfStructure() ? v.getShortName() : v.getFullNameEscaped());
if (!v.isVariableLength() && !v.isScalar()) { // sequences cant be sectioned
sb.append('(');
for (int count=0; count0) sb.append(", ");
sb.append(r.first());
sb.append(':');
sb.append(r.last());
sb.append(':');
sb.append(r.stride());
}
sb.append(')');
}
return (orgRanges == null) ? null : ranges.subList(v.getRank(), ranges.size());
}
/**
* Print all the data of the given Variable.
* @param v variable to print
* @param ct allow task to be cancelled; may be null.
* @return String result
* @throws IOException on write error
*/
static public String printVariableData(VariableIF v, ucar.nc2.util.CancelTask ct) throws IOException {
Array data = v.read();
/* try {
data = v.isMemberOfStructure() ? v.readAllStructures(null, true) : v.read();
}
catch (InvalidRangeException ex) {
return ex.getMessage();
} */
ByteArrayOutputStream bos = new ByteArrayOutputStream();
printArray( data, v.getFullName(), new PrintStream( bos), ct);
return bos.toString();
}
/**
* Print a section of the data of the given Variable.
* @param v variable to print
* @param sectionSpec string specification
* @param ct allow task to be cancelled; may be null.
* @return String result formatted data ouptut
* @throws IOException on write error
* @throws InvalidRangeException is specified section doesnt match variable shape
*/
static public String printVariableDataSection(VariableIF v, String sectionSpec, ucar.nc2.util.CancelTask ct) throws IOException, InvalidRangeException {
Array data = v.read(sectionSpec);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
printArray( data, v.getFullName(), new PrintStream( bos), ct);
return bos.toString();
}
/**
* Print the data array.
* @param array data to print.
* @param name title the output.
* @param out send output here.
* @param ct allow task to be cancelled; may be null.
*/
static public void printArray(Array array, String name, PrintStream out, CancelTask ct) {
printArray( array, name, null, out, new Indent(2), ct);
}
static private void printArray(Array array, String name, String units, PrintStream out, Indent ilev, CancelTask ct) {
if (ct != null && ct.isCancel()) return;
if (name != null) out.print(ilev+name + " =");
ilev.incr();
if (array == null)
throw new IllegalArgumentException("null array");
if ((array instanceof ArrayChar) && (array.getRank() > 0) ) {
printStringArray(out, (ArrayChar) array, ilev, ct);
} else if (array.getElementType() == String.class) {
printStringArray(out, (ArrayObject) array, ilev, ct);
} else if (array.getElementType() == StructureData.class) {
if (array.getSize() == 1)
printStructureData( out, (StructureData) array.getObject( array.getIndex()), ilev, ct);
else
printStructureDataArray( out, array, ilev, ct);
} else {
printArray(array, out, ilev, ct);
}
if (units != null)
out.print(" "+units);
out.print("\n");
ilev.decr();
}
static private void printArray(Array ma, PrintStream out, Indent indent, CancelTask ct) {
if (ct != null && ct.isCancel()) return;
int rank = ma.getRank();
Index ima = ma.getIndex();
// scalar
if (rank == 0) {
out.print( ma.getObject(ima).toString());
return;
}
int [] dims = ma.getShape();
int last = dims[0];
out.print("\n" + indent + "{");
if ((rank == 1) && (ma.getElementType() != StructureData.class)) {
for(int ii = 0; ii < last; ii++) {
out.print( ma.getObject(ima.set(ii)).toString());
if (ii != last-1) out.print(", ");
if (ct != null && ct.isCancel()) return;
}
out.print("}");
return;
}
indent.incr();
for(int ii = 0; ii < last; ii++) {
Array slice = ma.slice(0, ii);
printArray(slice, out, indent, ct);
if(ii != last-1) out.print(",");
if (ct != null && ct.isCancel()) return;
}
indent.decr();
out.print("\n"+indent + "}");
}
static void printStringArray(PrintStream out, ArrayChar ma, Indent indent, ucar.nc2.util.CancelTask ct) {
if (ct != null && ct.isCancel()) return;
int rank = ma.getRank();
if (rank == 1) {
out.print( " \""+ma.getString()+"\"");
return;
}
if (rank == 2) {
boolean first = true;
for (ArrayChar.StringIterator iter = ma.getStringIterator(); iter.hasNext(); ) {
if (!first) out.print(", ");
out.print( "\""+iter.next()+"\"");
first = false;
if (ct != null && ct.isCancel()) return;
}
return;
}
int [] dims = ma.getShape();
int last = dims[0];
out.print("\n" + indent + "{");
indent.incr();
for(int ii = 0; ii < last; ii++) {
ArrayChar slice = (ArrayChar) ma.slice(0, ii);
printStringArray(out, slice, indent, ct);
if(ii != last-1) out.print(",");
if (ct != null && ct.isCancel()) return;
}
indent.decr();
out.print("\n"+indent + "}");
}
static void printStringArray(PrintStream out, ArrayObject ma, Indent indent, ucar.nc2.util.CancelTask ct) {
if (ct != null && ct.isCancel()) return;
int rank = ma.getRank();
Index ima = ma.getIndex();
if (rank == 0) {
out.print( " \""+ma.getObject(ima)+"\"");
return;
}
if (rank == 1) {
boolean first = true;
for (int i=0; i\n");
out.print("\n\n");
else
out.print(" location='"+ StringUtil2.quoteXmlAttribute(URLnaming.canonicalizeWrite(ncfile.getLocation()))+"' >\n\n");
if (ncfile.getId() != null)
out.print(" id='"+ StringUtil2.quoteXmlAttribute(ncfile.getId())+"' >\n");
if (ncfile.getTitle() != null)
out.print(" title='"+ StringUtil2.quoteXmlAttribute(ncfile.getTitle())+"' >\n");
writeNcMLGroup( ncfile, ncfile.getRootGroup(), out, new Indent(2), showCoords);
out.print(" \n");
out.flush();
}
static private void writeNcMLGroup( NetcdfFile ncfile, Group g, PrintStream out, Indent indent, boolean showCoords) throws IOException {
if (g != ncfile.getRootGroup()) {
out.print(indent);
out.print("\n");
}
indent.incr();
List dimList = g.getDimensions();
for (Dimension dim : dimList) {
out.print(indent);
out.print(" \n");
}
if (dimList.size() > 0)
out.print("\n");
List attList = g.getAttributes();
for (Attribute att : attList) {
writeNcMLAtt(att, out, indent);
}
if (attList.size() > 0)
out.print("\n");
for (Variable v : g.getVariables()) {
if (v instanceof Structure) {
writeNcMLStructure((Structure) v, out, indent);
} else {
writeNcMLVariable(v, out, indent, showCoords);
}
}
// nested groups
List groupList = g.getGroups();
for (int i=0; i 0) out.print("\n");
Group nested = (Group) groupList.get(i);
writeNcMLGroup( ncfile, nested, out, indent, showCoords);
}
indent.decr();
if (g != ncfile.getRootGroup()) {
out.print(indent);
out.print(" \n");
}
}
static private void writeNcMLStructure( Structure s, PrintStream out, Indent indent) throws IOException {
out.print(indent);
out.print(" 0) {
writeNcMLDimension( v, out);
}
indent.incr();
boolean closed = false;
// any attributes ?
java.util.List atts = v.getAttributes();
if (atts.size() > 0) {
out.print(" >\n");
closed = true;
for (Attribute att : atts) {
writeNcMLAtt(att, out, indent);
}
}
// print data ?
if ((showCoords && v.isCoordinateVariable())) {
if (!closed) {
out.print(" >\n");
closed = true;
}
writeNcMLValues(v, out, indent);
}
indent.decr();
// close variable element
if (!closed)
out.print(" />\n");
else {
out.print(indent);
out.print("\n");
}
}
// LOOK anon dimensions
static private void writeNcMLDimension( Variable v, PrintStream out) {
out.print(" shape='");
java.util.List dims = v.getDimensions();
for (int j = 0; j < dims.size(); j++) {
Dimension dim = dims.get(j);
if (j != 0)
out.print(" ");
if (dim.isShared())
out.print(StringUtil2.quoteXmlAttribute(dim.getShortName()));
else
out.print(dim.getLength());
}
out.print("'");
}
@SuppressWarnings({"ObjectToString"})
static private void writeNcMLAtt(Attribute att, PrintStream out, Indent indent) {
out.print(indent);
out.print(" \n");
}
static private int totalWidth = 80;
static private void writeNcMLValues(Variable v, PrintStream out, Indent indent) throws IOException {
Array data = v.read();
int width = formatValues(indent+"", out, 0, indent);
IndexIterator ii = data.getIndexIterator();
while (ii.hasNext())
width = formatValues(ii.next()+" ", out, width, indent);
formatValues(" \n", out, width, indent);
}
static private int formatValues(String s, PrintStream out, int width, Indent indent) {
int len = s.length();
if (len + width > totalWidth) {
out.print("\n");
out.print(indent);
width = indent.toString().length();
}
out.print(s);
width += len;
return width;
}
private static char[] org = { '\b', '\f', '\n', '\r', '\t', '\\', '\'', '\"' };
private static String[] replace = {"\\b", "\\f", "\\n", "\\r", "\\t", "\\\\", "\\\'", "\\\""};
/**
* Replace special characters '\t', '\n', '\f', '\r'.
* @param s string to quote
* @return equivilent string replacing special chars
*/
static public String encodeString(String s) {
return StringUtil2.replace(s, org, replace);
}
////////////////////////////////////////////////////////////////////////////////////////////
/**
Main program.
ucar.nc2.NCdump filename [-cdl | -ncml] [-c | -vall] [-v varName1;varName2;..] [-v varName(0:1,:,12)]
where:
* - filename : path of any CDM readable file
*
- cdl or ncml: output format is CDL or NcML
*
- -vall : dump all variable data
*
- -c : dump coordinate variable data
*
- -v varName1;varName2; : dump specified variable(s)
*
- -v varName(0:1,:,12) : dump specified variable section
*
* Default is to dump the header info only.
* @param args arguments
*/
public static void main( String[] args) {
if (args.length == 0) {
System.out.println(usage);
return;
}
StringBuilder sbuff = new StringBuilder();
for (String arg : args) {
sbuff.append(arg);
sbuff.append(" ");
}
try {
NCdump.print(sbuff.toString(), System.out, null);
// NCdump.print(args[0], System.out, false, false, false, false, null, null);
} catch (java.io.IOException ioe) {
ioe.printStackTrace();
}
}
}