BDBP
What is the BDBP?
Officially: The Binary Data Base of Profiles
In reality: Birgit's Database of Biblical Proportions
The BDBP is a collection of measurements of atmospheric composition from various satellite-, balloon-, and ground-based measurements. The data base is described in detail in:
Hassler, B., G. E. Bodeker, and M. Dameris (2008), Technical Note: A new global database of trace gases and aerosols from multiple sources of high vertical resolution measurements, Atmospheric Chemistry and Physics, 8, 5403-5421.
Hassler, B., G. E. Bodeker, I. Cionni, and M. Dameris (2009), A vertically resolved, monthly mean, ozone database from 1979 to 2100 for constraining global climate model simulations, International Journal of Remote Sensing, 30(15-16), 4009–4018.
Which version of the BDBP is available?
The current version of the BDBP is version 1.1.0.6. This version is very similar to that described in Hassler et al. (2009) but now also includes the ILAS and ILAS II data. We are currently working on a new version of the database. This will include the AURA MLS data as well as two new grids: one where the vertical coordinate is the altitude above/below the local tropopause, and one where the vertical coordinate is the pressure above/below the local tropopause. If you would like to be made aware of updates to this data base, please email me at greg@bodekerscientific.com and I will add your name to the list of BDBP users.
How do I get the data that is in the BDBP?
The database comprises 3 sets of 90 files each. If you’ve read the paper you will know why there are 3 sets of 90 files. If you haven’t read the paper – go and read the paper. These are on our ftp server here and you will need to use an ftp client such as FileZilla to access the data. To obtain the username and password please contact stefanie@bodekerscientific.com.
At present Bodeker Scientific has no financial support to maintain this database and so if there is any way that you can contribute towards the maintenance of this database, that would be much appreciated. That said, this database is made freely available to any not-for-profit organisation or individual. In return for providing you with this database, all we ask is that you let us know what you plan to do with the database and, if the database is used in a publication, to discussion acknowledgement/co-author options with us.
On the FTP server for this database you will see three different directories, viz.:
EqlatTheta: These are the data files for the data gridded by equivalent latitude and potential temperature.
LatAlt: These are the data files for the data gridded by latitude and altitude.
LatPress: These are the data files for the data gridded by latitude and pressure.
If you have any questions regarding the database, please email me at greg@bodekerscientific.com.
Additionally, Version 1.0 has been archived by NOAA (National Climatic Data Center), and is available here.
How do I add my measurements to the BDBP?
Data can easily be added to the BDBP. To maintain the high vertical resolution of the data base we only accept data at high vertical resolution i.e.~ 1 km or better. We also require that each measurement be provided with a measurement error in percent. If you want to have your data added to the BDBP, please contact us. In general, we will expect a text file listing (in columns separated by spaces):
latitude, longitude, year, month, date, hour, minute, second, altitude, pressure, temperature, measurement ID (see Table 1), value, percentage error
The availability of altitude, pressure, and temperature data will determine which of the three data grids the measurements can be added to.
What code is available for extracting the data from the BDBP?
- Reading the binary data files
- Reading in a measurement set
- Reading in a measurement
Reading the binary data files
There are 3 instances of the BDBP, viz.:
I. Where the data are gridded as a function of geographic latitude, longitude, altitude (in 1 km steps) and time,
II. Where the data are gridded as a function of geographic latitude, longitude, pressure (at levels ~1 km apart) and time,
III. Where the data are gridded as a function of equivalent latitude, potential temperature (8 levels from 300K to 650K) and time.
Each instance of the data base comprises 90 files, each spanning 2o of latitude in the cases of Grids I and II, and 2o of equivalent latitude in the case of Grid III.
To extract the data from each file repeat the following two step sequence until you get to the end of the file.
Read in a 2 byte unsigned integer (0..65535; type word in Pascal). This tells you what level you are at. For Grid I it is the altitude in km. For Grid II it is the pressure where the pressure is given by 1013.25×exp(-i/7) where i is the value read in. For Grid III it is the isentropic level where the index runs from 1 to 8 denoting 300K, 315K, 330K, 350K, 400K, 450K, 550K and 650K respectively.
Read in another 2 byte unsigned integer. This tells you how many measurement sets you will now read in.
Reading in a measurement set
To read in a measurement set from a file (this applies to all files and all 3 grids):
Read in a 1 byte unsigned integer (0..255; type byte in Pascal). This will tell you how many characters are in the identifier string. Call this N.
Read in 10 characters, and concatenate the first N into a string. This string will tell you the source of the set of measurements e.g. 'SAGE1'.
Read in an 8 byte double precision floating point value (type double in Pascal). This will tell you the date and time that the set of measurements was made. The integral part of the value is the number of days that have passed since 30 December 1899. The fractional part of the value is the fraction of a 24 hour day since midnight at the start of the day. For example: 0 corresponds to 30 December 1899 12:00 am, 35065.25 corresponds to 1 January 1996 6:00 am.
Read in a 4 byte single precision floating point value (type single in Pascal). This is the latitude at which the measurement set was made.
Read in a 4 byte single precision floating point value. This is the longitude at which the measurement set was made.
Read in a 4 byte single precision floating point value. This is the equivalent latitude at which the measurement set was made. If an equivalent latitude value could not be calculated for the set of measurements, this value will be -1E10.
Read in a 2 byte unsigned integer. This tells you how many measurements in the current measurement set you will now read in.
Reading in a measurement
To read in a measurement from a file (this applies to all files and all 3 grids):
Read in a 4 byte single precision floating point value. This is the value of the measurement. Look at Table 1 to see what the units are.
Read in a 2 byte unsigned integer. This is the percentage error on the measurement multiplied by 100.
Read in a 1 byte unsigned integer. This tells you what type of measurement it is, i.e. the measurement ID (see Table 1).
Keep going. Stop when you get to the end of the file.
Measurement ID table
Table 1
Delphi code
Here is some Delphi code that implements the recipe outlined above
var
Source:file;
NumMeasurementSets,
NumMeas,
AltIndex,
Error:word;
Test,
MeasType:byte;
Ch:char;
I,J,K:integer;
DateTime:double;
Value,
Latitude,
Longitude,
EquivLat:single;
SourceStr:string;
begin
assignfile(Source,'D:\archive\BDBP_V1\LatAlt\TimeSeries_21.bin');
reset(Source,1);
repeat
blockread(Source,AltIndex,sizeof(word));
blockread(Source,NumMeasurementSets,sizeof(word));
for I:=1 to NumMeasurementSets do
begin
blockread(Source,Test,sizeof(byte));
SourceStr:='';
for J:=1 to 10 do
begin
blockread(Source,Ch,sizeof(char));
if J<=Test then SourceStr:=SourceStr+Ch;
end;
blockread(Source,DateTime,sizeof(TDateTime));
blockread(Source,Latitude,sizeof(single));
blockread(Source,Longitude,sizeof(single));
blockread(Source,Equivlat,sizeof(single));
blockread(Source,NumMeas,sizeof(word));
for K:=1 to NumMeas do
begin
blockread(Source,Value,sizeof(single));
blockread(Source,Error,sizeof(word));
blockread(Source,MeasType,sizeof(byte));
end;
end;
until eof(Source);
closefile(Source);
end.
Here is some Fortran code that implements the recipe outlined above
implicit none
character
& source*10, ! Source of the set of measurements (e.g., 'SAGE1')
& infile*100 ! BDBP file
integer*1 ! (unsigned)
& meastype, ! Type of measurement (i.e., measurement ID)
& numchar ! Number of characters (Source name)
integer*2 ! (unsigned*2)
& altindex, ! Indicator of current level
& numset, ! Number of measurement sets in the file
& nummeas, ! Number of measurements in current set
& errp ! Percentage error on the measurement (x100)
real*4
& value, ! Value of measurement
& lat, ! Latitude at which the measurement set was made
& lon, ! Longitude at which the measurement set was made
& eqlat ! Equivalent latitude at which the measurement set was made
real*8
& datetime ! Date and time since 12 December 1899 12:00am
integer*4
& i,j ! Loop counters
!:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
infile='TimeSeries_01.bin'
open(unit=7,file=trim(infile),form='binary',status='old',
& action='read',convert='LITTLE_ENDIAN',err=990)
do
read(7,end=10) altindex,numset
do i=1,numset
read(7,end=10) numchar,source,datetime,lat,lon,eqlat,nummeas
do j=1,nummeas
read(7,end=10) value,errp,meastype
end do ! end of do-while
end do ! end of do-while
end do
10 continue
close(7)
GOTO 999
990 write(*,'2a') 'Error reading binary data from file: ',infile
stop
999 end
Here is some IDL code that implements the recipe outlined above
pro read_bdbp_file,filename
source = '' ; Source of the set of measurements (e.g., 'SAGE1')
meastype = 0b ; Type of measurement (i.e., measurement ID)
numchar = 0b ; Number of characters (Source name)
altindex = 0U ; Indicator of current level
numset = 0U ; Number of measurement sets in the file
nummeas = 0U ; Number of measurements in current set
errp = 0U ; Percentage error on the measurement (x100)
value = 0.0 ; Value of measurement
lat = 0.0 ; Latitude at which the measurement set was made
lon = 0.0 ; Longitude at which the measurement set was made
eqlat = 0.0 ; Equivalent latitude at which the measurement set was made
datetime = 0.0d ; Date and time since 12 December 1899 12:00am
;open file
openr,unit,filename,ERROR = err,/get_lun,/SWAP_IF_BIG_ENDIAN
if (err ne 0) then begin
print,'Abort: Error opening bdbpfile: ',filename
stop
endif
while (NOT(EOF(unit))) do begin
readu,unit,altindex,numset
for i=1,numset do begin
source = '0123456789' ; reset len(source)=10
readu,unit,numchar,source,datetime,lat,lon,eqlat,nummeas
for j=1,nummeas do begin
readu,unit,value,errp,meastype
endfor
endfor
end
close,unit
end
Here is some C++ code that implements the recipe outlined above
int _tmain()
{
char* Filename;
int I,J,K;
unsigned short NumMeasurementSets;
unsigned short AltIndex;
unsigned short NumMeas;
unsigned short Error;
unsigned char Test;
unsigned char MeasType;
unsigned char Ch;
double DateTime;
float Value;
float Latitude;
float Longitude;
float EquivLat;
string SourceStr;
Filename="D:/archive/BDBP_V1/LatAlt/TimeSeries_21.bin";
ifstream infile;
infile.open(Filename, ios::binary);
if (infile.is_open())
{
do
{ infile.read((char*)&AltIndex,sizeof(unsigned short));
infile.read((char*)&NumMeasurementSets,sizeof(unsigned short));
for (I=1; I<=NumMeasurementSets; I++){
infile.read((char*)&Test,sizeof(Test));
SourceStr="";
for (J=1; J<=10; J++){
infile.read((char*)&Ch,sizeof(unsigned char));
if (J<=int(Test)) {SourceStr.push_back(Ch);}
}
infile.read((char*)&DateTime,sizeof(double));
infile.read((char*)&Latitude,sizeof(float));
infile.read((char*)&Longitude,sizeof(float));
infile.read((char*)&EquivLat,sizeof(float));
infile.read((char*)&NumMeas,sizeof(unsigned short));
for (K=1; K<=NumMeas; K++){
infile.read((char*)&Value,sizeof(float));
infile.read((char*)&Error,sizeof(unsigned short));
infile.read((char*)&MeasType,sizeof(unsigned char));
}
}
} while(!infile.eof());
infile.close();
}
return 0;
}
C++ code
Here is some C++ code that implements the recipe outlined above
int _tmain()
{
char* Filename;
int I,J,K;
unsigned short NumMeasurementSets;
unsigned short AltIndex;
unsigned short NumMeas;
unsigned short Error;
unsigned char Test;
unsigned char MeasType;
unsigned char Ch;
double DateTime;
float Value;
float Latitude;
float Longitude;
float EquivLat;
string SourceStr;
Filename="D:/archive/BDBP_V1/LatAlt/TimeSeries_21.bin";
ifstream infile;
infile.open(Filename, ios::binary);
if (infile.is_open())
{
do
{ infile.read((char*)&AltIndex,sizeof(unsigned short));
infile.read((char*)&NumMeasurementSets,sizeof(unsigned short));
for (I=1; I<=NumMeasurementSets; I++){
infile.read((char*)&Test,sizeof(Test));
SourceStr="";
for (J=1; J<=10; J++){
infile.read((char*)&Ch,sizeof(unsigned char));
if (J<=int(Test)) {SourceStr.push_back(Ch);}
}
infile.read((char*)&DateTime,sizeof(double));
infile.read((char*)&Latitude,sizeof(float));
infile.read((char*)&Longitude,sizeof(float));
infile.read((char*)&EquivLat,sizeof(float));
infile.read((char*)&NumMeas,sizeof(unsigned short));
for (K=1; K<=NumMeas; K++){
infile.read((char*)&Value,sizeof(float));
infile.read((char*)&Error,sizeof(unsigned short));
infile.read((char*)&MeasType,sizeof(unsigned char));
}
}
} while(!infile.eof());
infile.close();
}
return 0;
}