/* * nctrim.h Definitions for nctrim.c * * This program trims the record variables to the * record-number range given by the command-line * options, specified either in Matlab-style as * begin:stride:end, or in NetCDF-style as * begin,count,stride. The range specifier must * contain no blanks or other white-space. * * The output file is created in NC_CLOBBER mode. * The input and output files must not have the * same name. * * The base-index is always 0, never 1. * * The range specifier can be defaulted as follows: * * begin < 0 indicates record #0. * stride < 1 indicates stride = 1; * end < 0 indicates the last record. * count < 1 indicates the maximum. * * "begin:end" means "begin:-1:end" * "begin:" means "begin:-1:-1" * "begin,count" means "begin,count,-1" * "begin," means "begin,-1,-1" * "count" means "-1,count,-1" * * All other entities are transfered intact. * * The algorithm does not use ncrecinq/get/put, since * early versions of NetCDF do not have that scheme. * * The ncsetfill() function is not used, since it fails * on some machines. If the value CAN_SETFILL is defined * as a compiler option in the nctrim.make file, then * ncsetfill() will be invoked with NC_NOFILL just before * the output file is switched from define-mode to data-mode. * This may lead to faster execution with files containing * large non-record variables. * * The output filename defaults to the input filename with * the suffix ".out" added. * * Usage is displayed if fewer that two command-line arguments * are provided. * * Copyright (C) 1994 Dr. Charles R. Denham, ZYDECO. * All Rights Reserved. * */ #include #include #include #include "netcdf.h" int main ( int argc, char ** argv, char ** envp ) { long begin = -1; long stride = -1; long end = -1; long count = -1; char srcfilename[MAX_NC_NAME+1]; char dstfilename[MAX_NC_NAME+1]; int srcncid; int srcdimcount; int srcvarcount; int srcattcount; int srcrecdimid; int srcdimid[MAX_NC_DIMS]; long srcdimsize[MAX_NC_DIMS]; char srcdimname[MAX_NC_NAME+1]; int srcvarid[MAX_NC_VARS]; char srcvarname[MAX_NC_NAME+1]; nc_type srcvartype; char srcattname[MAX_NC_NAME+1]; long srcslabstart[MAX_NC_DIMS]; long srcslabcount[MAX_NC_DIMS]; /* Some of the following are not used. */ int dstncid; int dstdimcount; int dstvarcount; int dstattcount; int dstrecdimid; int dstdimid[MAX_NC_DIMS]; long dstdimsize[MAX_NC_DIMS]; char dstdimname[MAX_NC_NAME+1]; int dstvarid[MAX_NC_VARS]; char dstvarname[MAX_NC_NAME+1]; nc_type dstvartype; char dstattname[MAX_NC_NAME+1]; long dstslabstart[MAX_NC_DIMS]; long dstslabcount[MAX_NC_DIMS]; int dimid[MAX_NC_DIMS]; int i; int j; long k; int index; size_t n; size_t memcount = 0; void * datap = NULL; /* Usage. */ if (argc < 3) { printf("\n\tProgram: %s\n\tVersion: %s %s\n", __FILE__, __DATE__, __TIME__); printf("\tAuthor: Charles R. Denham, ZYDECO.\n"); printf("\n\tUsage (Matlab (Base-0)): nctrim begin:stride:end infile outfile"); printf("\n\tUsage (Matlab (Base-0)): nctrim begin:end infile outfile"); printf("\n\tUsage (Matlab (Base-0)): nctrim begin: infile outfile"); printf("\n\tUsage (NetCDF (Base-0)): nctrim begin,count,stride infile outfile"); printf("\n\tUsage (NetCDF (Base-0)): nctrim begin,count infile outfile"); printf("\n\tUsage (NetCDF (Base-0)): nctrim begin, infile outfile"); printf("\n\tUsage (NetCDF (Base-0)): nctrim count infile outfile\n"); printf("\n\t(-1 = logical beginning, end, unit-stride, or maximum-count.)\n"); #ifdef applec #ifdef macintosh printf("\n\tnctrim "); #endif #endif exit (0); } /* Decode the record-range from argv[1]. */ begin = -1; stride = -1; end = -1; count = -1; if (strchr(argv[1], ':')) { /* Matlab style. */ sscanf(argv[1], "%ld:%ld:%ld", & begin, & stride, & end); if (begin < 0) { begin = -1; } if (stride < 1) { stride = -1; } if (end < 0) { end = stride; stride = -1; } } else if (strchr(argv[1], ',')) { /* NetCDF style. */ sscanf(argv[1], "%ld,%ld,%ld", & begin, & count, & stride); if (begin < 0) { begin = -1; } if (count < 0) { count = -1; } if (stride < 1) { stride = 1; } } else { /* Straight count, starting at record #0. */ sscanf(argv[1], "%ld", & count); } #ifdef DEBUG printf("\n\t## begin = %ld; stride = %ld; end = %ld; count = %ld\n", begin, stride, end, count); fflush(stdout); #endif /* Open the input and output netcdf files. */ strcpy(srcfilename, argv[2]); if (argc > 3) { strcpy(dstfilename, argv[3]); } else { strcpy(dstfilename, srcfilename); strcat(dstfilename, ".out"); printf("\n\t## Output filename: %s\n", dstfilename); } if (!strcmp(srcfilename, dstfilename)) { printf("\n\t## Output filename must not be same as input filename.\n"); exit (1); } srcncid = ncopen(srcfilename, NC_NOWRITE); dstncid = nccreate(dstfilename, NC_CLOBBER); #ifdef DEBUG ncopts = NC_VERBOSE; #endif /* Define the output entities and determine needed memory. */ ncinquire(srcncid, & srcdimcount, & srcvarcount, & srcattcount, & srcrecdimid); for (j = 0; j < srcdimcount; j++) { ncdiminq(srcncid, j, srcdimname, & srcdimsize[j]); if (j == srcrecdimid) { srcdimsize[j] = NC_UNLIMITED; } dstdimid[j] = ncdimdef(dstncid, srcdimname, srcdimsize[j]); } memcount = 0; for (i = 0; i < srcvarcount; i++) { ncvarinq(srcncid, i, srcvarname, & srcvartype, & srcdimcount, srcdimid, & srcattcount); n = 1; for (j = 1; j < srcdimcount; j++) { ncdiminq(srcncid, srcdimid[j], srcdimname, & srcdimsize[j]); n *= srcdimsize[j]; } n *= nctypelen(srcvartype); if (memcount < n) { memcount = n; } for (j = 0; j < srcdimcount; j++) { dimid[j] = dstdimid[srcdimid[j]]; } dstvarid[i] = ncvardef(dstncid, srcvarname, srcvartype, srcdimcount, dimid); } /* Allocate memory for data transfers. */ if ((datap = (void *) malloc(memcount)) == NULL) { printf("\n\t## Memory allocation failure: %ld bytes\n", memcount); exit (1); } else { #ifdef DEBUG printf("\n\t## Memory allocated: %d bytes\n", memcount); #endif } /* Transfer all global attributes. */ ncinquire(srcncid, & srcdimcount, & srcvarcount, & srcattcount, & srcrecdimid); for (j = 0; j < srcattcount; j++) { ncattname(srcncid, NC_GLOBAL, j, srcattname); ncattcopy(srcncid, NC_GLOBAL, srcattname, dstncid, NC_GLOBAL); } /* Transfer all variable attributes. */ for (i = 0; i < srcvarcount; i++) { ncvarinq(srcncid, i, srcvarname, & srcvartype, & srcdimcount, srcdimid, & srcattcount); for (j = 0; j < srcattcount; j++) { ncattname(srcncid, i, j, srcattname); ncattcopy(srcncid, i, srcattname, dstncid, dstvarid[i]); } } /* End of define-mode. */ #ifdef CAN_SETFILL ncsetfill(dstncid, NC_NOFILL); #endif ncendef(dstncid); /* Transfer all non-record variables. */ ncinquire(srcncid, & srcdimcount, & srcvarcount, & srcattcount, & srcrecdimid); for (i = 0; i < srcvarcount; i++) { ncvarinq(srcncid, i, srcvarname, & srcvartype, & srcdimcount, srcdimid, & srcattcount); if (srcdimid[0] == srcrecdimid) { continue; } for (j = 0; j < srcdimcount; j++) { ncdiminq(srcncid, srcdimid[j], srcdimname, & srcdimsize[j]); srcslabstart[j] = 0; srcslabcount[j] = srcdimsize[j]; dstslabstart[j] = 0; dstslabcount[j] = srcdimsize[j]; } srcslabcount[0] = 1; dstslabcount[0] = 1; for (k = 0; k < srcdimsize[0]; k++) { if (ncvarget(srcncid, i, srcslabstart, srcslabcount, datap) == -1) { break; } else if (ncvarput(dstncid, dstvarid[i], dstslabstart, dstslabcount, datap) == -1) { break; } srcslabstart[0]++; dstslabstart[0]++; } } /* Transfer all record variables in the range begin:stride:end. */ ncinquire(srcncid, & srcdimcount, & srcvarcount, & srcattcount, & srcrecdimid); for (i = 0; i < srcvarcount; i++) { ncvarinq(srcncid, i, srcvarname, & srcvartype, & srcdimcount, srcdimid, & srcattcount); if (srcdimid[0] != srcrecdimid) { continue; } for (j = 0; j < srcdimcount; j++) { ncdiminq(srcncid, srcdimid[j], srcdimname, & srcdimsize[j]); srcslabstart[j] = 0; srcslabcount[j] = srcdimsize[j]; dstslabstart[j] = 0; dstslabcount[j] = srcdimsize[j]; } srcslabcount[0] = 1; dstslabcount[0] = 1; if (count < 0) { count = srcdimsize[0]; } if (begin < 0) { begin = 0; } if (stride < 1) { stride = 1; } if (end < 0) { end = (begin + (count - 1) * stride); } if (end >= srcdimsize[0]) { end = srcdimsize[0] - 1; } count = (end - begin + stride) / stride; #ifdef DEBUG printf("\t## begin = %ld; stride = %ld; end = %ld; count = %ld\n", begin, stride, end, count); fflush(stdout); #endif for (k = begin; k <= end; k += stride) { srcslabstart[0] = k; if (ncvarget(srcncid, i, srcslabstart, srcslabcount, datap) == -1) { break; } else if (ncvarput(dstncid, dstvarid[i], dstslabstart, dstslabcount, datap) == -1) { break; } dstslabstart[0]++; } } /* Deallocate memory. */ free(datap); /* Close the files. */ ncclose(dstncid); ncclose(srcncid); #ifdef applec #ifdef macintosh printf("\n\tncdump -h %s\n", dstfilename); printf("\tncdump %s\n", dstfilename); printf("\topen nctrim.c\n"); printf("\tnctrim "); #endif #endif }