#include #include #include #include #include #include #include #include #define slag 0.23 /* lag between the acquisition of the wind and scalar data, in seconds*/ #define samplerate 10.0 /* samples per second */ #define boom 0 /* boom angle for the sonic anemometer */ #define nch 6 /* number of channels */ /* ************************************************************ raw_flux_grass.C The program processes RAW data files and despikes the data. It produces *.flx, *.nrt and *.err files that can be processed in the normal manner with programs that merge met, soil and flux data. The input raw data are not adjusted for lags between velocity and scalar variables. So we call the subroutine lag_adjust. 2/15/2001 Dennis Baldocchi Ecosystem Science Division Department of Environmental Science, Policy and Management 151 Hilgard Hall University of California, Berkeley Berkeley, CA 94720 baldocchi@nature.berkeley.edu Vaira Grassland debug notes 1/6/2001 new file names 12/4/2000 too much v data was despiked at night when var v was small and atmospheric stratification was stable. Need to up the threshold Also debug running variances. There were errors in the calcs ************************************************************ */ /* declare subroutine names */ void filename(); void indata(); /* reads the 2 byte binary integer files from *.raw */ void lag_adjust(); /* adjust the raw data for the lag in the data */ void despike(); /* removes spikes from the data stream */ void reynolds_ave(); /* computes flux statistics using Reynolds averaging */ void output(); /* outputs the data */ void zero(); /* zero the arrays */ /* declare structures */ struct output { /* output variables */ long int endtime, sample; int end_day, end_hour, end_hourmin, end_minute; float ww,uu,vv,uw,uv,wv; float vari[nch],x_bar[nch],wx[nch],ux[nch],vx[nch],wxr[nch]; float theta,eta,u_bar,w_bar,v_bar; float uur,vvr,wwr,uwr,wvr,u_star; float skew[nch],kurt[nch]; float wdir; long int spkcnt[nch]; float spkave[nch]; } out; struct input { /* input variables */ short int intdata[nch]; float fltdata[19000][nch], newdata[19000]; } in; struct filename { /* structure for filenames */ char flxbuff[39], nrtbuff[39], errbuff[39], spkbuff[39]; }name; /* declare global variables */ int handle, handle1, day, fcheck; long int daytime; float timeconst; char fname[39], tname[8]; /* File pointers */ FILE *fptr1, *fptr3, *fptr4, *fptr5, *fptr6, *fptr7, *fptr9; main () { int hourmin, hour, minute, oldday; int j,i; fcheck=0; oldday=190; /* open list of raw filenames This file is created from the most recent raw files. It is in ascii form as: d:\vaira\raw\g3101100.raw d:\vaira\raw\g3101130.raw etc...... file296.raw * file310.raw * file324.raw * file338.raw * file361.raw * */ fptr1=fopen("c:\\vaira_2000\\raw\\file361.raw","rt"); /* INPUT DATA FROM DISK, Read consequtive files to construct hour average */ handle1=fileno(fptr1); /* while file.raw is open */ while(! feof(fptr1)) { /* read RAW file */ fscanf(fptr1,"%s",fname); /* strip the string to find the daytime */ j=0; for(i=19;i<=25; i++) { tname[j]=fname[i]; j++; } daytime=atoi(tname); day=daytime/10000; hour=daytime-(daytime/10000)*10000; hour=(hour/100); printf("%2s\n",tname); daytime=atoi(tname); hourmin=daytime-(daytime/10000)*10000; hour=(hourmin/100); minute=hourmin-hour*100; /* compute end time */ out.end_day=day; out.end_hour=hour; if (minute < 30) out.end_minute=30; else out.end_minute=0; if(out.end_minute==0) out.end_hour+=1; if(out.end_hour >=24) {out.end_day += 1; out.end_hour=0; out.end_minute=0; } out.end_hourmin=out.end_hour*100+out.end_minute; out.endtime=out.end_day*10000+out.end_hourmin; /* create new file if hourmin is 0030 */ if(out.end_hour==0 && out.end_minute == 30) fcheck = 0; /* new day and new file */ /* create new file if newday but some other hour, as if there was an interruption between days */ if (out.end_day > oldday && out.end_hourmin > 30) fcheck = 0; oldday=out.end_day; filename(); /* read data from raw files Remember element 0 is channel 1, etc */ indata(); /* adjust the time series for the lag between scalars and velocity measurements */ lag_adjust(); /* examine data files and remove spikes */ timeconst=600.; despike(); /* compute turbulent statistics and flux covariances with Reynolds averaging */ reynolds_ave(); /* write to output files */ output(); zero(); /* end of file.raw loop */ } /* END OF MAIN */ } void filename() { int i; char fileflx[35], filenrt[35], fileerr[35], filespk[35]; char daybuff[4]; itoa(day,daybuff,10); /* define flux file name as vryr_day.flx, x is system or expt number */ strcpy(fileflx,"c:\\vaira_2000\\flux\\vr00_"); strcat(fileflx,daybuff); memmove(name.flxbuff,fileflx,29); strcat(name.flxbuff, ".flx_dspk"); printf("%s %s \n",fileflx, name.flxbuff); /* define flux file name as vryr_day.nrt */ strcpy(filenrt,"c:\\vaira_2000\\flux\\vr00_"); strcat(filenrt,daybuff); memmove(name.nrtbuff,filenrt,29); strcat(name.nrtbuff,".nrt_dspk"); printf("%s %s\n",filenrt,name.nrtbuff); /* define flux file name as vryr_day.err */ strcpy(fileerr,"c:\\vaira_2000\\flux\\vr00_"); strcat(fileerr,daybuff); memmove(name.errbuff,fileerr,29); strcat(name.errbuff,".err_dspk"); printf("%s %s\n",fileerr,name.errbuff); /* define file name for quantifying spikes as vryr_day.spk */ strcpy(filespk,"c:\\vaira_2000\\flux\\vr00_"); strcat(filespk,daybuff); memmove(name.spkbuff,filespk,29); strcat(name.spkbuff,".spk"); printf("%s %s\n",filespk,name.spkbuff); /* output data */ i = access(name.flxbuff,0); /* check if file exists */ if(i < 0) fcheck = 0; /* set set flag for newfile */ if(fcheck==0) { if((fptr4=fopen(name.flxbuff,"w"))==NULL) printf("can't open flxbuff\n"); if((fptr5=fopen(name.nrtbuff,"w"))==NULL) printf("can't open nrtbuff\n"); if((fptr6=fopen(name.errbuff,"w"))==NULL) printf("can't open errbuff\n"); if((fptr7=fopen(name.spkbuff,"w"))==NULL) printf("can't open spkbuff\n"); fclose(fptr4); fclose(fptr5); fclose(fptr6); fclose(fptr7); fcheck=1; } return; } void indata() { int j; long int freebyte, ii; ii=0; if((fptr9=fopen(fname,"rb")) != NULL) handle=fileno(fptr9); freebyte=filelength(handle); while (! feof(fptr9)) { fread(in.intdata,2,nch,fptr9); /* convert wind velocity from cm/s to m/s */ for(j=0; j< 3;j++) in.fltdata[ii][j]=(float)in.intdata[j]/100.; /* convert integer data from millivolts to floating point volts */ in.fltdata[ii][3]=(float)in.intdata[3]/100.; in.fltdata[ii][4]=(float)in.intdata[4]/1000.; in.fltdata[ii][5]=(float)in.intdata[5]/1000.; /* w,u and v are channels 0, 1 and 2, respectively. T, Q, CO2 are channels 3, 4, 5 */ ii++; } fclose(fptr9); out.sample=ii; return; /* end of indata */ } void lag_adjust() { /* adjust the raw data set for the lag between the sonic anemometer and LICOR LI-7500 data, which is 0.23 seconds */ /* it may be suitable to re-write the code and use pointers to shift the arrays */ int i,j,lag; lag=slag*samplerate; for(j=4;j< nch;j++) { for(i=1;i<=out.sample;i++) { if(i+lag 9.8) { out.spkcnt[j]++; out.spkave[j] +=in.fltdata[i][j]; in.fltdata[i][j]=runfill[j]; iflag[j]=1; } if (iflag[j] != 1) { delx=in.fltdata[i][j]-runmean[j]; fl_delx=fabs(delx); // is the fluctuation > six times the std dev? if (fl_delx/runstd[j] > 6) {out.spkcnt[j]++; out.spkave[j] +=in.fltdata[i][j]; in.fltdata[i][j]=runfill[j]; iflag[j]=1;} } } /* end of loop j = 0 to 2 */ /* looking for sonic temperature spikes, with wet sensors getting bad data or when u,v,w are bad too. Originally I was not rejecting enough T data and computed a lot of bad H's. Changed threshold from 6 to 4. */ if (j==3) { if(fabs(in.fltdata[i][j]) > fabs(runmean[j]+4.*runstd[j])) { out.spkcnt[j]++; out.spkave[j] +=in.fltdata[i][j]; in.fltdata[i][j]=runfill[j]; iflag[j]=1; } } /* check if q and c are dropping bits (as the LI7500 was observed to have been doing) or spiking out of the 5 volt range */ if(j>3) { if(in.fltdata[i][j] < 0.1 || in.fltdata[i][j] > 4.98) { out.spkcnt[j]++; out.spkave[j] +=in.fltdata[i][j]; in.fltdata[i][j]=runfill[j]; iflag[j]=1; } if(fabs(in.fltdata[i][j]) > fabs(runmean[j]+6.*runstd[j])) { out.spkcnt[j]++; out.spkave[j] +=in.fltdata[i][j]; in.fltdata[i][j]=runfill[j]; iflag[j]=1; } } /* update running means, variances and standard deviations for data without spike */ if (iflag[j]==1) cnt[j]--; if (iflag[j]==0) { runmean[j] = runmean[j]*alpha + in.fltdata[i][j]*onealpha; delx=in.fltdata[i][j] - runmean[j]; sumvar[j] += delx*delx; runvar[j] = sumvar[j]/cnt[j]; runstd[j]=pow(runvar[j],0.5); runfill[j]=runfill[j]*alpha_fill+in.fltdata[i][j]*(1.-alpha_fill); } } /* next i */ } /* next j */ /* evaluate mean values of the spikes */ for (j=0; j 360.) out.wdir -= 360.0; if(out.wdir < 0.0) out.wdir += 360.0; out.u_bar = out.x_bar[1]*ct*ce + out.x_bar[2]*ct*se + out.x_bar[0]*st; out.v_bar = out.x_bar[2]*ce - out.x_bar[1]*se; out.w_bar = out.x_bar[0]*ct - out.x_bar[1]*st*ce - out.x_bar[2]*st*se; out.uur = out.uu*ct2*ce2 + 2*out.uv*ct2*ce*se + 2*out.uw*ct*ce*st + out.vv*ct2*se2 + 2*out.wv*ct*se*st + out.ww*st2; out.vvr = out.vv*ce2 + out.uu*se2 - 2*out.uv*ce*se; out.wwr = out.ww*ct2 + out.uu*st2*ce2 + out.vv*st2*se2 - 2*out.uw*ct*st*ce - 2*out.wv*ct*st*se + 2*out.uv*st2*ce*se; out.uwr = out.uw*ce*(ct2-st2) + out.wv*se*(ct2-st2) + out.ww*st*ct - out.uu*st*ct*ce2 - out.vv*st*ct*se2 - 2*out.uv*st*ct*se*ce; out.wvr = 0; if (out.uwr < 0) out.u_star = sqrt(-out.uwr); else out.u_star = 9999; for (i = 3; i < nch; i++) out.wxr[i] = out.wx[i]*ct - out.ux[i]*st*ce - out.vx[i]*st*se; return; /* end of Reynolds_ave */ } void output() { int i; /* write 'flx' file */ fptr4 = fopen(name.flxbuff,"a"); fprintf(fptr4,"%3d %02d%02d %4.0f ", out.end_day,out.end_hour, out.end_minute,out.wdir); fprintf(fptr4,"%4.2f %4.3e ",out.u_bar,out.uwr); for(i = 3; i < nch; i++) fprintf(fptr4,"%5.3f ", out.x_bar[i]); fprintf(fptr4,"%4.3e %4.3e %4.3e",out.uur,out.vvr,out.wwr); for(i = 3; i < nch; i++) fprintf(fptr4," %4.3e",out.vari[i]); for (i = 3; i < nch; i++) fprintf(fptr4," %4.3e",out.wxr[i]); fprintf(fptr4," %u\n",out.sample); fclose(fptr4); /* write unrotated file */ fptr5 = fopen(name.nrtbuff,"a"); fprintf(fptr5,"%3d %02d%02d %4.0f ",out.end_day,out.end_hour, out.end_minute,out.wdir); fprintf(fptr5,"%5.3f %5.3f %5.3f ",out.x_bar[0], out.x_bar[1],out.x_bar[2]); fprintf(fptr5," %4.3e %4.3e %4.3e %4.3e %4.3e %4.3e ", out.ww,out.uu,out.vv,out.uw,out.uv,out.wv); for (i = 3; i < nch; i++) fprintf(fptr5," %4.3e %4.3e %4.3e %4.3e ",out.wx[i],out.ux[i], out.vx[i],out.vari[i]); fprintf(fptr5," %d\n",out.sample); fclose(fptr5); /* write 'err' file */ fptr6 = fopen(name.errbuff,"a"); fprintf(fptr6,"%3d %02d%02d %4.0f ",out.end_day,out.end_hour, out.end_minute,out.wdir); for (i = 0; i < nch; i++) fprintf(fptr6," %4.3e ",out.skew[i]); for (i = 0; i < nch; i++) fprintf(fptr6," %4.3e ",out.kurt[i]); fprintf(fptr6," %4.0f %4.0f ", out.theta,out.eta); fprintf(fptr6," %d\n",out.sample); fclose(fptr6); /* write 'spk file */ fptr7=fopen(name.spkbuff,"a"); fprintf(fptr6,"%3d %02d%02d ",out.end_day,out.end_hour, out.end_minute); for (i = 0; i < nch; i++) fprintf(fptr7," %d ",out.spkcnt[i]); for (i = 0; i < nch; i++) fprintf(fptr7," %f ",out.spkave[i]); fprintf(fptr7," \n"); fclose(fptr7); return; /* end of output */ } void zero() { return; }