This archive contains answers to questions sent to Unidata support through mid-2025. Note that the archive is no longer being updated. We provide the archive for reference; many of the answers presented here remain technically correct, even if somewhat outdated. For the most up-to-date information on the use of NSF Unidata software and data services, please consult the Software Documentation first.
>From: Unidata User Support <address@hidden> >Organization: Unidata Program Center/UCAR >Keywords: McIDAS-X ADDE netCDF satellite winds Gail (with CC to Russ), I am including the McIDAS application that I wrote that reads CIMSS satellite retrieved winds by ADDE and writes them into a netCDF. As promised, I am including a blow-by-blow on how the application was created. First, I took Gail's minimum list of useful parameters in the winds MD file as the list of things to write to the output netCDF: From: Gail Dengel <address@hidden> Date: Wed, 24 Oct 2001 17:53:00 +0000 Here's the minimum list of useful parameters in the winds MD files I promised (or threatened) to send you: DAY1 HMS1 SATD PROD SID FLAG TYPE LAT LON DIR SPD PW TC CH I turned this into a CDL for the eventual output netCDF (a CDL is the netCDF equivalent of an MD file schema). The CDL I created is: ------ snip --------- satwinds.cdl ------------------------------------------ netcdf satwinds { dimensions: recNum = UNLIMITED ; nameLen = 5 ; variables: // DAY1 and HMS1 double timeObs(recNum) ; timeObs:long_name = "Date/Time of observation" ; timeObs:units = "seconds since 1970-1-1 00:00:00.0" ; timeObs:_FillValue = 1.e+38 ; // SATD char satName(recNum, nameLen) ; satName:long_name = "Satellite ID name" ; // PROD char windProd(recNum, nameLen); windProd:long_name = "Wind vector product (WV or CDFT)" ; // SID int satIdn(recNum) ; satIdn:long_name = "Satellite ID number" ; // FLAG int errFlag(recNum); errFlag:long_name = "Error flag" ; // TYPE char windType(recNum, nameLen) ; windType:long_name = "Satellite ID name" ; // LAT float windLat(recNum) ; windLat:long_name = "Latitude location" ; windLat:units = "degree_N" ; windLat:_FillValue = 1.e+38f ; windLat:valid_range = -90.f, 90.f ; // LON float windLon(recNum) ; windLon:long_name = "Longitude location" ; windLon:units = "degree_E" ; windLon:_FillValue = 1.e+38f ; windLon:valid_range = -180.f, 180.f ; // DIR float windDir(recNum) ; windDir:long_name = "Final wind direction" ; windDir:units = "degree" ; windDir:_FillValue = 1.e+38f ; windDir:valid_range = 0.f, 360.f ; // SPD float windSpeed(recNum) ; windSpeed:long_name = "Final wind speed" ; windSpeed:units = "meter/sec" ; windSpeed:_FillValue = 1.e+38f ; windSpeed:valid_range = -150.f, 150.f ; // PW float windPress(recNum) ; windPress:long_name = "Final height assignment" ; windPress:units = "meter/sec" ; windPress:_FillValue = 1.e+38f ; windPress:valid_range = 0.f, 1050.f; // TC float cloudTemp(recNum) ; cloudTemp:long_name = "Cloud temperature at final height" ; cloudTemp:units = "kelvin" ; cloudTemp:_FillValue = 1.e+38f ; cloudTemp:valid_range = 0.f, 400.f; // CH char hgtAssignMethod(recNum, nameLen) ; hgtAssignMethod:long_name = "Height assignment method" ; // global attributes: :title = "CIMSS SatWinds retrieval" ; } ------ snip --------- satwinds.cdl ------------------------------------------ Next, I used the CDL to generate C source code for the netCDF writer: ncgen -c satwinds.cdl > swnd2cdf.c After that, the job consisted of adding: o #include <string.h> #include <mcidas.h> o documentation (so one can generate a McIDAS .hlp file o additional variable definitions for netCDF code (5 definitions) o McIDAS code that allows a user to specify: SWND2CDF output <keywords> Parameters: output - netCDF file name Keywords: DATaset= ADDE dataset to read DAY= keyword to specify DAY/DAYs to read TIME= keyword to specify range of times to read -- side note: the McIDAS code was the hardest part of this whole exercise! o just before the ncgen generated C code (an nc_close that closes the output netCDF), I added a section that is a mixture of McIDAS ADDE read and parameter convert code and netCDF write code. o at the very end, I announce how many data records were written, and a notice that the program is done I also tried to indicate, by comments in the code, what code was added by me "by hand" and what code was written by ncgen. The only changes I had to make to the ncgen generated code were: o move the declaration 'int stat' up to the top of the program o replace the hardwired output netCDF name in the nc_open call with the variable populated by the Mccmdstr call that allows the user to specify what s/he wants to call the output So, here is the source for the new application: ------ snip --------- swnd2cdf.c -------------------------------------------- /* *? SWND2CDF -- Copy CIMSS satellite wind retrieval values to a netCDF *? SWND2CDF output *? *? Parameter: *? output | netCDF file to write to (def=satwinds.nc) *? *? Keywords: *? DAY= begday endday | DAY range for input (def=current begday) *? TIME= begtim endtim | TIME range for input (def=current begtim) *? TRACE= 0,1 | Send TRACE directive to server (def=0 (no)) *? *? Remarks: *? A small subset of parameters from the wind retrieval files *? are saved to the output netCDF. The parameters copied are: *? *? Parameter Unit Description *? --------- ------- ---------------------------- *? DAY1 ccyyddd winds DAY *? HMS1 hms winds TIME *? SATD text satellite ID *? PROD text product type *? SID I2 satellite ID *? FLAG I2 data error flag *? TYPE text retrieval type *? LAT deg latitude *? LON deg longitude (West positive) *? DIR deg wind direction *? SPD m/s wind speed *? PW mb pressure at retrieved wind level *? TC K temperature at retrieved wind level *? CH text height assignment method *? *? The date and time of the retrieval is saved in the netCDF as *? seconds since 1970-1-1 00:00:00.0 *? *? Example: *? SWND2CDF satwinds.nc DAY=2001306 TIME=12:00 17:30 *? *? ---------- * * History: 20011102 - Written for UW-CIMSS satellite winds team (TCY) */ #include <stdio.h> #include <stdlib.h> #include <strings.h> #include <netcdf.h> #include <mcidas.h> /* McIDAS code added to ncgen .c file */ void check_err(const int stat, const int line, const char *file) { if (stat != NC_NOERR) { (void) fprintf(stderr, "line %d of %s: %s\n", line, file, nc_strerror(stat)); exit(1); } } int main(int argc, char **argv) { /* create satwinds.nc */ /* ** netCDF stuff automatically included by ncgen */ int ncid; /* netCDF id */ /* dimension ids */ int recNum_dim; int nameLen_dim; /* dimension lengths */ size_t recNum_len = NC_UNLIMITED; size_t nameLen_len = 5; /* variable ids */ int timeObs_id; int satName_id; int windProd_id; int satIdn_id; int errFlag_id; int windType_id; int windLat_id; int windLon_id; int windDir_id; int windSpeed_id; int windPress_id; int cloudTemp_id; int hgtAssignMethod_id; /* rank (number of dimensions) for each variable */ # define RANK_timeObs 1 # define RANK_satName 2 # define RANK_windProd 2 # define RANK_satIdn 1 # define RANK_errFlag 1 # define RANK_windType 2 # define RANK_windLat 1 # define RANK_windLon 1 # define RANK_windDir 1 # define RANK_windSpeed 1 # define RANK_windPress 1 # define RANK_cloudTemp 1 # define RANK_hgtAssignMethod 2 /* variable shapes */ int timeObs_dims[RANK_timeObs]; int satName_dims[RANK_satName]; int windProd_dims[RANK_windProd]; int satIdn_dims[RANK_satIdn]; int errFlag_dims[RANK_errFlag]; int windType_dims[RANK_windType]; int windLat_dims[RANK_windLat]; int windLon_dims[RANK_windLon]; int windDir_dims[RANK_windDir]; int windSpeed_dims[RANK_windSpeed]; int windPress_dims[RANK_windPress]; int cloudTemp_dims[RANK_cloudTemp]; int hgtAssignMethod_dims[RANK_hgtAssignMethod]; /* attribute vectors */ double timeObs__FillValue[1]; float windLat__FillValue[1]; float windLat_valid_range[2]; float windLon__FillValue[1]; float windLon_valid_range[2]; float windDir__FillValue[1]; float windDir_valid_range[2]; float windSpeed__FillValue[1]; float windSpeed_valid_range[2]; float windPress__FillValue[1]; float windPress_valid_range[2]; float cloudTemp__FillValue[1]; float cloudTemp_valid_range[2]; /* ** netCDF stuff included by hand */ int stat; size_t start[1]; /* start array for non-text vars */ size_t count[1]; /* count array for non-text vars */ size_t sstart[2]; /* start array for text vars */ size_t scount[2]; /* count array for non-text vars */ /* ** McIDAS stuff included by hand */ int current_day; /* current system day */ int current_hms; /* current system time */ int data_record[20]; /* data record from server */ int beg_day; /* beginning day for copy */ int beg_time; /* beginning hour for copy */ int end_day; /* ending day for copy */ int end_time; /* ending hour for copy */ int ihr, min, sec; /* hour, minute, and second */ int i; /* generic counter */ int gotbytes; /* number of bytes from server */ int nparms; /* number of parameters requested */ int nsorts; /* number of selection clauses */ int rc; /* function return value */ int return_val = 1; /* main() return value */ int trace_val; /* value to set for trace flag */ char cschema[5]; /* schema of MD file*/ char ctextid[33]; /* text ID of MD file */ char creatid[5]; /* creator MD file ID */ char cname[9]; /* name of MD file */ char *p = NULL; /* generic character pointer */ char ctemp[256]; /* working string buffer */ char cpos[5]; /* dataset position */ char *csplit; /* split dataset group descriptor */ char dsname[255]; /* group/descriptor part of dset */ const char *cdfname; /* name of output netCDF */ const char *dset; /* ADDE data set name */ char ctim1[9], ctim2[9]; /* time in HH:MM:SS format */ int header[64]; /* header back from point server */ char *sorts[256] = {0}; /* selection character array */ char *parms[256] = {0}; /* parameters requested */ char *units[256] = {0}; /* units for parameters */ char *forms[256] = {0}; /* formats for parameters */ int scales[20] = {0}; /* scales for parameters */ int day1; /* DAY read from server [ccyyddd] */ int hms1; /* TIME read from server [hms] */ int sid; /* Satellite ID */ int flag; /* data flag */ double dlat; /* Latitude [deg] */ double dlon; /* Longitude [deg] */ int dir; /* Wind direction [deg] */ double dspd; /* Wind speed [m/s] */ int pw; /* Pressure at wind level [mb] */ double dtc; /* Temperature at wind level [K] */ char *satd ={0}; /* Satellite (text) */ char *prod ={0}; /* Product (text) */ char *type ={0}; /* Type (text) */ char *ch ={0}; /* Height assignment method (text)*/ time_t seconds; /* date/time seconds since 1970 */ double dsecs; /* double equivalent of seconds */ float alat; /* real equivalent of dlat */ float alon; /* real equivalent of dlon */ float aspd; /* real equivalent of dspd */ float atc; /* real equivalent of dtc */ /* ** Initialize McIDAS environment */ if ( Mcinit (argc, argv) < 0 ) { fprintf( stderr, "%s\n", Mciniterr () ); return ( return_val ); } /* ** Announce start of program */ Mcprintf( "SWND2CDF: Begin\n" ); /* ** Get the name of the output netCDF. Default to 'satwinds.nc'. */ if ( Mccmdstr( " ", 1, "satwinds.nc", &cdfname ) < 0 ) { return ( return_val ); } /* ** Get the dataset; default is CIMSSP/WNDGOESE.ALL */ if ( Mccmdstr( "DAT.ASET", 1, "CIMSSP/WNDGOESE.ALL", &dset ) < 0 ) { return ( return_val ); } strcpy( dsname, dset ); p = strstr( dsname, "." ); if ( p != (char *)NULL ) { strcpy( cpos, p+1 ); *p = '\0'; } else { strcpy( cpos, "ALL" ); } Mcdprintf( "Data Set Name = '%s' cpos = '%s'\n", dsname, cpos ); rc = M0split( dsname, &csplit ); if ( rc ) { Mceprintf( "ERROR splitting dataset name: %s\n", dsname ); return ( return_val ); } /* ** Get the TRACE flag value */ if ( Mccmdint( "TRA.CE", 1, "", 0, 1, 0, &trace_val ) < 0 ) { return ( return_val ); } (void) sprintf( ctemp, "%s POS=%s BPOS=1 EPOS=9 MAX=1 TRACE=%d VERSION=1", csplit, cpos, trace_val ); Mcdprintf( "selection clause: %s\n", ctemp ); /* ** Get the schema for this dataset. Abort if it is not GWIN. */ rc = M0cxreq( "MDFH", ctemp, 0, 0, &gotbytes ); if ( gotbytes > 256 ) gotbytes = 256; rc = m0cxread_( &gotbytes, (Fint *)header ); if ( rc ) { Mceprintf( "ERROR reading MD file header from server" ); return ( return_val ); } strncpy( cschema, (char *)&header[ 0], 4 ); cschema[4] = '\0'; strncpy( ctextid, (char *)&header[16], 32 ); ctextid[32] = '\0'; strncpy( creatid, (char *)&header[26], 4 ); creatid[4] = '\0'; strncpy( cname, (char *)&header[61], 8 ); cname[8] = '\0'; Mcdprintf( "header[ 0] = '%s'\n", cschema ); for ( i = 1; i < 16; i++ ) { Mcdprintf( "header[%2d] = %8d\n", i, header[i] ); } Mcdprintf( "header[16] = '%s'\n", ctextid ); for ( i = 24; i < 26; i++ ) { Mcdprintf( "header[%2d] = %8d\n", i, header[i] ); } Mcdprintf( "header[26] = '%s'\n", creatid ); for ( i = 27; i < 61; i++ ) { Mcdprintf( "header[%2d] = %8d\n", i, header[i] ); } Mcdprintf( "header[61] = '%s'\n", cname ); Mcdprintf( "header[63] = %8d\n", header[63] ); if ( strcmp( cschema, "GWIN" ) ) { Mceprintf( "ERROR: dataset schema %s is not GWIN\n", cschema ); return ( return_val ); } /* ** Get the current system day and time */ rc = Mcgetdaytime( ¤t_day, ¤t_hms ); /* ** Get the day and time of the first data to copy */ rc = Mccmdiyd( "DAY",1,"Begin day",current_day,1990001,2100001,&beg_day ); if ( rc < 0 ) { return ( return_val ); } rc = Mccmdihr( "TIM.E",1,"Begin time",current_hms,0,235959,&beg_time); if (rc < 0) { return ( return_val ); } ihr = beg_time / 10000; min = (beg_time/100) % 100; sec = beg_time % 100; (void) sprintf( ctim1, "%2d:%02d:%02d", ihr, min, sec ); /* ** Get the day and time of the last data to copy */ rc = Mccmdiyd( "DAY",2,"End day",beg_day,beg_day,2100001,&end_day ); if ( rc < 0 ) { return ( return_val ); } rc = Mccmdihr( "TIM.E",2,"End time",beg_time,0,235959,&end_time ); if ( rc < 0 ) { return ( return_val ); } ihr = end_time / 10000; min = (end_time/100) % 100; sec = end_time % 100; (void) sprintf( ctim2, "%2d:%02d:%02d", ihr, min, sec ); if ( end_day == beg_day && end_time < beg_time ) { Mceprintf( "Ending time %s must be greater than beginning time %s\n", ctim2, ctim1 ); return ( return_val ); } /* ** Build selection arrays */ sorts[0] = strdup( "MAX=ALL" ); sorts[1] = strdup( "POS=ALL" ); sorts[2] = strdup( "PARM=DAY1 HMS1 PROD SID FLAG TYPE LAT LON DIR SPD PW TC CH" ); (void) sprintf( ctemp, "TRACE=%d", trace_val ); sorts[3] = strdup( ctemp ); (void) sprintf( ctemp, "SELECT='DAY1 %d TO %d' 'HMS1 %s TO %s'", beg_day, end_day, ctim1, ctim2 ); sorts[4] = strdup( ctemp ); nsorts = 5; for ( i = 0; i < nsorts; i++ ) { Mcdprintf( "sorts[%1d]: %s\n", i, sorts[i] ); } /* ** Specify parameters to be returned from server */ parms[0] = strdup( "DAY1" ); parms[1] = strdup( "HMS1" ); parms[2] = strdup( "SATD" ); parms[3] = strdup( "PROD" ); parms[4] = strdup( "SID " ); parms[5] = strdup( "FLAG" ); parms[6] = strdup( "TYPE" ); parms[7] = strdup( "LAT " ); parms[8] = strdup( "LON " ); parms[9] = strdup( "DIR " ); parms[10] = strdup( "SPD " ); parms[11] = strdup( "PW " ); parms[12] = strdup( "TC " ); parms[13] = strdup( "CH " ); nparms = 14; for ( i = 0; i < nparms; i++ ) { Mcdprintf( "parms[%1d]: %s\n", i, parms[i] ); } /* ** Initialize POINT data request */ rc = McPtGet( dsname,nsorts,sorts,&nparms,parms,units,forms,scales,0 ); if ( rc < 0 ) { Mceprintf( "ERROR initializing POINT server data request" ); return ( return_val ); } for ( i = 0; i < nparms; i++ ){ Mcdprintf( "%4s units[%2d] = %4s forms[%2d] = %4s scales[%2d] = %d\n", parms[i], i, units[i], i, forms[i], i, scales[i] ); } /* ** Initialize subsystem for future McPtBuf calls */ rc = McPtBufInit( nparms, forms, scales ); if ( rc < 0 ) { Mceprintf( "ERROR initializing POINT server data request" ); return ( return_val ); } /* ** netCDF section created by ncgen. ** ** Create the file, define dimensions, variables, and attributes. */ /* enter define mode */ stat = nc_create(cdfname, NC_CLOBBER, &ncid); check_err(stat,__LINE__,__FILE__); /* define dimensions */ stat = nc_def_dim(ncid, "recNum", recNum_len, &recNum_dim); check_err(stat,__LINE__,__FILE__); stat = nc_def_dim(ncid, "nameLen", nameLen_len, &nameLen_dim); check_err(stat,__LINE__,__FILE__); /* define variables */ timeObs_dims[0] = recNum_dim; stat = nc_def_var(ncid, "timeObs", NC_DOUBLE, RANK_timeObs, timeObs_dims, &timeObs_id); check_err(stat,__LINE__,__FILE__); satName_dims[0] = recNum_dim; satName_dims[1] = nameLen_dim; stat = nc_def_var(ncid, "satName", NC_CHAR, RANK_satName, satName_dims, &satName_id); check_err(stat,__LINE__,__FILE__); windProd_dims[0] = recNum_dim; windProd_dims[1] = nameLen_dim; stat = nc_def_var(ncid, "windProd", NC_CHAR, RANK_windProd, windProd_dims, &windProd_id); check_err(stat,__LINE__,__FILE__); satIdn_dims[0] = recNum_dim; stat = nc_def_var(ncid, "satIdn", NC_INT, RANK_satIdn, satIdn_dims, &satIdn_id); check_err(stat,__LINE__,__FILE__); errFlag_dims[0] = recNum_dim; stat = nc_def_var(ncid, "errFlag", NC_INT, RANK_errFlag, errFlag_dims, &errFlag_id); check_err(stat,__LINE__,__FILE__); windType_dims[0] = recNum_dim; windType_dims[1] = nameLen_dim; stat = nc_def_var(ncid, "windType", NC_CHAR, RANK_windType, windType_dims, &windType_id); check_err(stat,__LINE__,__FILE__); windLat_dims[0] = recNum_dim; stat = nc_def_var(ncid, "windLat", NC_FLOAT, RANK_windLat, windLat_dims, &windLat_id); check_err(stat,__LINE__,__FILE__); windLon_dims[0] = recNum_dim; stat = nc_def_var(ncid, "windLon", NC_FLOAT, RANK_windLon, windLon_dims, &windLon_id); check_err(stat,__LINE__,__FILE__); windDir_dims[0] = recNum_dim; stat = nc_def_var(ncid, "windDir", NC_FLOAT, RANK_windDir, windDir_dims, &windDir_id); check_err(stat,__LINE__,__FILE__); windSpeed_dims[0] = recNum_dim; stat = nc_def_var(ncid, "windSpeed", NC_FLOAT, RANK_windSpeed, windSpeed_dims, &windSpeed_id); check_err(stat,__LINE__,__FILE__); windPress_dims[0] = recNum_dim; stat = nc_def_var(ncid, "windPress", NC_FLOAT, RANK_windPress, windPress_dims, &windPress_id); check_err(stat,__LINE__,__FILE__); cloudTemp_dims[0] = recNum_dim; stat = nc_def_var(ncid, "cloudTemp", NC_FLOAT, RANK_cloudTemp, cloudTemp_dims, &cloudTemp_id); check_err(stat,__LINE__,__FILE__); hgtAssignMethod_dims[0] = recNum_dim; hgtAssignMethod_dims[1] = nameLen_dim; stat = nc_def_var(ncid, "hgtAssignMethod", NC_CHAR, RANK_hgtAssignMethod, hgtAssignMethod_dims, &hgtAssignMethod_id); check_err(stat,__LINE__,__FILE__); /* assign attributes */ stat = nc_put_att_text(ncid, timeObs_id, "long_name", 24, "Date/Time of observation"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, timeObs_id, "units", 33, "seconds since 1970-1-1 00:00:00.0"); check_err(stat,__LINE__,__FILE__); timeObs__FillValue[0] = 1e+38; stat = nc_put_att_double(ncid, timeObs_id, "_FillValue", NC_DOUBLE, 1, timeObs__FillValue); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, satName_id, "long_name", 17, "Satellite ID name"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, windProd_id, "long_name", 32, "Wind vector product (WV or CDFT)"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, satIdn_id, "long_name", 19, "Satellite ID number"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, errFlag_id, "long_name", 10, "Error flag"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, windType_id, "long_name", 17, "Satellite ID name"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, windLat_id, "long_name", 17, "Latitude location"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, windLat_id, "units", 8, "degree_N"); check_err(stat,__LINE__,__FILE__); windLat__FillValue[0] = 9.9999997e+37; stat = nc_put_att_float(ncid, windLat_id, "_FillValue", NC_FLOAT, 1, windLat__FillValue); check_err(stat,__LINE__,__FILE__); windLat_valid_range[0] = -90; windLat_valid_range[1] = 90; stat = nc_put_att_float(ncid, windLat_id, "valid_range", NC_FLOAT, 2, windLat_valid_range); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, windLon_id, "long_name", 18, "Longitude location"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, windLon_id, "units", 8, "degree_E"); check_err(stat,__LINE__,__FILE__); windLon__FillValue[0] = 9.9999997e+37; stat = nc_put_att_float(ncid, windLon_id, "_FillValue", NC_FLOAT, 1, windLon__FillValue); check_err(stat,__LINE__,__FILE__); windLon_valid_range[0] = -180; windLon_valid_range[1] = 180; stat = nc_put_att_float(ncid, windLon_id, "valid_range", NC_FLOAT, 2, windLon_valid_range); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, windDir_id, "long_name", 20, "Final wind direction"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, windDir_id, "units", 6, "degree"); check_err(stat,__LINE__,__FILE__); windDir__FillValue[0] = 9.9999997e+37; stat = nc_put_att_float(ncid, windDir_id, "_FillValue", NC_FLOAT, 1, windDir__FillValue); check_err(stat,__LINE__,__FILE__); windDir_valid_range[0] = 0; windDir_valid_range[1] = 360; stat = nc_put_att_float(ncid, windDir_id, "valid_range", NC_FLOAT, 2, windDir_valid_range); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, windSpeed_id, "long_name", 16, "Final wind speed"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, windSpeed_id, "units", 9, "meter/sec"); check_err(stat,__LINE__,__FILE__); windSpeed__FillValue[0] = 9.9999997e+37; stat = nc_put_att_float(ncid, windSpeed_id, "_FillValue", NC_FLOAT, 1, windSpeed__FillValue); check_err(stat,__LINE__,__FILE__); windSpeed_valid_range[0] = -150; windSpeed_valid_range[1] = 150; stat = nc_put_att_float(ncid, windSpeed_id, "valid_range", NC_FLOAT, 2, windSpeed_valid_range); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, windPress_id, "long_name", 23, "Final height assignment"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, windPress_id, "units", 9, "meter/sec"); check_err(stat,__LINE__,__FILE__); windPress__FillValue[0] = 9.9999997e+37; stat = nc_put_att_float(ncid, windPress_id, "_FillValue", NC_FLOAT, 1, windPress__FillValue); check_err(stat,__LINE__,__FILE__); windPress_valid_range[0] = 0; windPress_valid_range[1] = 1050; stat = nc_put_att_float(ncid, windPress_id, "valid_range", NC_FLOAT, 2, windPress_valid_range); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, cloudTemp_id, "long_name", 33, "Cloud temperature at final height"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, cloudTemp_id, "units", 6, "kelvin"); check_err(stat,__LINE__,__FILE__); cloudTemp__FillValue[0] = 9.9999997e+37; stat = nc_put_att_float(ncid, cloudTemp_id, "_FillValue", NC_FLOAT, 1, cloudTemp__FillValue); check_err(stat,__LINE__,__FILE__); cloudTemp_valid_range[0] = 0; cloudTemp_valid_range[1] = 400; stat = nc_put_att_float(ncid, cloudTemp_id, "valid_range", NC_FLOAT, 2, cloudTemp_valid_range); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, hgtAssignMethod_id, "long_name", 24, "Height assignment method"); check_err(stat,__LINE__,__FILE__); stat = nc_put_att_text(ncid, NC_GLOBAL, "title", 24, "CIMSS SatWinds retrieval"); check_err(stat,__LINE__,__FILE__); /* leave define mode */ stat = nc_enddef (ncid); check_err(stat,__LINE__,__FILE__); /* ** ADDE read and netCDF write code included by hand */ /* ** Read retrieved winds from ADDE Server and write values to file. */ Mcdprintf( " DAY1 HMS1 SATD PROD SID FLAG TYPE LAT LON DIR SPD PW TC CH\n" ); Mcdprintf( " ------ ------ ---- ---- --- ---- ---- ------ ------- --- ----- --- ------ ----\n" ); /* ** For all data types EXCEPT text (strings), we will write one item ** at a time. The index of the write is represented by the array ** start[] and its value is the record number (zero based) of the write. ** The number of writes (one) is represented by the array count[] ** and its value is always 1 (one). ** ** For text (strings) writes, we are also writing one item, but that ** item's length may vary. The CDL for the output netCDF fixes the ** maximum length of the string as 5 (length of 4 plus a NULL byte), ** so one should make sure that the strings really are small enough ** to fit. ** ** For text writes, the index of the write is represented by the array ** sstart[] which is two elements long. The number of writes is ** represented by the array scount[] which is also two elements long. ** ** The first element of sstart[] will vary in the exact same way as ** start[]: it will be the record number of the unlimited dimension. ** The second element of sstart[] will always be 0 (zero) as we ** always write at the beginning. ** ** The first element of the number of writes array, scount[], will ** always be 1, we are always writing one item. The second element ** of scount[] will be the length of the string being written. ** In our case, this would always be a maximum of 4 characters PLUS ** the trailing NULL byte. */ start[0] = 0; count[0] = 1; sstart[0] = 0; sstart[1] = 0; scount[0] = 1; while ( 1 ) { rc = McPtRead( (void *) data_record ); if ( rc < 0 ) { Mceprintf( "ERROR reading point data" ); } if ( rc == 1 ) { break; } /* DAY1 and HMS1 */ rc = McPtBufInt( 0, data_record, &day1 ); rc = McPtBufInt( 1, data_record, &hms1 ); /* Turn DAY [ccyyddd] and time [hhmmss] into seconds since 1970 */ rc = Mcdaytimetosec( day1, hms1, &seconds ); dsecs = (double) seconds; rc = nc_put_vara_double( ncid, timeObs_id, (const size_t *) start, (const size_t *) count, (const double *) &dsecs ); /* SATD */ if ( satd ) free( satd ); rc = McPtBufStr( 2, data_record, &satd ); scount[1] = strlen( satd ) + 1; rc = nc_put_vara_text( ncid, satName_id, (const size_t *) sstart, (const size_t *) scount, (const char *) satd); /* PROD */ if ( prod ) free( prod ); rc = McPtBufStr( 3, data_record, &prod ); scount[1] = strlen( prod ) + 1; rc = nc_put_vara_text( ncid, windProd_id, (const size_t *) sstart, (const size_t *) scount, (const char *) prod); /* SID */ rc = McPtBufInt( 4, data_record, &sid ); rc = nc_put_vara_int( ncid, satIdn_id, (const size_t *) start, (const size_t *) count, (const int *) &sid); /* FLAG */ rc = McPtBufInt( 5, data_record, &flag ); rc = nc_put_vara_int( ncid, errFlag_id, (const size_t *) start, (const size_t *) count, (const int *) &flag); /* TYPE */ if ( type ) free( type ); rc = McPtBufStr( 6, data_record, &type ); scount[1] = strlen( type ) + 1; rc = nc_put_vara_text( ncid, windType_id, (const size_t *) sstart, (const size_t *) scount, (const char *) type); /* LAT */ rc = McPtBufDbl( 7, data_record, &dlat ); alat = (float) dlat; rc = nc_put_vara_float( ncid, windLat_id, (const size_t *) start, (const size_t *) count, (const float *) &alat); /* LON */ rc = McPtBufDbl( 8, data_record, &dlon ); alon = (float) dlon; rc = nc_put_vara_float( ncid, windLon_id, (const size_t *) start, (const size_t *) count, (const float *) &alon); /* DIR */ rc = McPtBufInt( 9, data_record, &dir ); rc = nc_put_vara_int( ncid, windDir_id, (const size_t *) start, (const size_t *) count, (const int *) &dir); /* SPD */ rc = McPtBufDbl( 10, data_record, &dspd ); aspd = (float) dspd; rc = nc_put_vara_float( ncid, windSpeed_id, (const size_t *) start, (const size_t *) count, (const float *) &aspd); /* PW */ rc = McPtBufInt( 11, data_record, &pw ); rc = nc_put_vara_int( ncid, windPress_id, (const size_t *) start, (const size_t *) count, (const int *) &pw); /* TC */ rc = McPtBufDbl( 12, data_record, &dtc ); atc = (float) dtc; rc = nc_put_vara_float( ncid, cloudTemp_id, (const size_t *) start, (const size_t *) count, (const float *) &atc); /* CH */ if ( ch ) free( ch ); rc = McPtBufStr( 13, data_record, &ch ); scount[1] = strlen( ch ) + 1; rc = nc_put_vara_text( ncid, hgtAssignMethod_id, (const size_t *) sstart, (const size_t *) scount, (const char *) ch); start[0] += 1; sstart[0] += 1; Mcdprintf( "%6d %6d %4s %4s %3d %4d %4s %6.2f %7.2f %3d %5.2f %3d %6.2f %4s\n", day1, hms1, satd, prod, sid, flag, type, alat, alon, dir, aspd, pw, atc, ch ); } /* ** Done writing, close the netCDF. */ stat = nc_close(ncid); check_err(stat,__LINE__,__FILE__); /* ** Announce end of program */ Mcprintf( "SWND2CDF: %d data records written to %s\n", start[0], cdfname ); Mcprintf( "SWND2CDF: End\n" ); return 0; } ------ snip --------- satwinds.c -------------------------------------------- This code gets compiled with the following (from Sun Solaris SPARC using SC5.0 C and Fortran compilers): cc -c -I. -I../netcdf/libsrc -I/usr/dt/include -I/usr/openwin/include swnd2cdf.c f77 -o swnd2cdf.k swnd2cdf.o -L. -L../netcdf/libsrc -R/usr/dt/lib -L/usr/dt/lib -R/usr/openwin/lib -L/usr/openwin/lib -R/opt/SUNWspro/lib -L/opt/SUNWspro/lib -lmcidas -lnetcdf -lgen -lsocket -lnsl -lm Please let me know if you have questions. Tom >From address@hidden Mon Nov 5 07:31:32 2001 >Subject: Re: 20011102: satellite winds to netCDF converter Many thanks, Tom! I haven't had time to look this over yet, but we'll have at it some time this week. -- G