/*************************************************************************** * Copyright (C) 2005 by Nicolas PASCAL * * nicolas.pascal@icare.univ-lille1.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "parasoldata.h" PARASOLData::PARASOLData(const string filename) : PARASOLFileReader(filename) { data_file_descriptor=NULL; data=NULL; // init the format data_file_format=NULL; if (product!=UNDEFINED) data_file_format=new PARASOLDataFormat(product); else { // invalid parametre name bad_product_id e(product); throw e; } read_data_file(filename); } PARASOLData::~PARASOLData() { free_records(); } void PARASOLData::free_records() { delete data_file_descriptor; data_file_descriptor=NULL; delete data; data=NULL; delete data_file_format; data_file_format=NULL; } PARASOLFileRecord * PARASOLData::init_record( const Record & record_code ) { if (record_code==DATA_FILE_DESCRIPTOR) { data_file_descriptor=new DataFileDescriptorRecord(); return data_file_descriptor; } else { cerr<<"In "<<__FILE__<<" at "<<__LINE__<<" : this record code "<(file_format->get_data_file_descriptor_format()); DataFileDescriptorRecord *rec = data_file_descriptor; RecordFormat::iterator entry = rec_format->begin(); if (rec!=NULL) { cout<<"****************** DATA FILE DESCRIPTOR *******************"<name<<" "<rec_nb<name<<" "<rec_len<name<<" "<ref_doc_id<name<<" "<ref_doc_version<name<<" "<soft_version<name<<" "<file_nb<name<<" "<filename<name<<" "<nb_data_rec<name<<" "<one_data_rec_len<name<<" "<data_rec_prefix_len<name<<" "<data_rec_data_len<name<<" "<data_rec_suffix_len<rec_len; } else { cerr<<"In "<<__FILE__<<" at "<<__LINE__<<" : undefined record code "<get_data_file_descriptor_format(); else if (record_code==DATA) return data_file_format->get_data_format(); else { cerr<<"In "<<__FILE__<<" at "<<__LINE__<<" : this record code "<(get_data_file_format()->get_data_format()); EntryFormat var_format = (*rec_format)[entry_index]; unsigned int length=var_format.len; // nb of values to read PARASOLDataType type=var_format.type; size_t size_type=PARASOLLeaderFormat::get_size_of(type); // size in bytes of one value bool endianness = MyTools::get_endianness(); vector v_entry_block = get_entry_block(DATA, entry_index); // --- set the dimensions to read. vector v_sz (rank); // size in bytes along a dimension (record, direction...) vector v_sz_dim (rank); // number of elements along a dimension (record, direction...) vector v_sz_read (rank); // number of elements to read along a dimension (record, direction...) vector v_start (rank); // start read indice along a dimension vector v_end (rank); // end read indice along a dimension int idim0, idim1; // dimensions iterator int nb_val = 1; // number of values to read for (int i = 0 ; i < rank ; ++i) { v_sz [i] = v_entry_block[i].size; v_sz_dim [i] = v_entry_block[i].ntime; v_start [i] = start[i]; v_end [i] = start[i] + edges [i]; v_sz_read [i] = v_end [i] - v_start [i]; nb_val *= edges [i]; } // --- fill the buffer with fill values --- fill_buffer_default(buf, nb_val, type); // --- read the file --- void* val=NULL; int ret = -1; // define value iterator vector i_val(rank); fill (i_val.begin(),i_val.end(), 0); // offset of very first entry from start of record size_t entry_offset = get_entry_offset(DATA, entry_index, i_val); // start of 1st dimension offset size_t offset_root = 0, offset_dim0 = 0, offset_dim1 = 0, offset_val; int ibuf = 0; // go to start of data records offset_root = record_offset + entry_offset; if (rank == 1) { offset_dim0 = offset_root; // save start of dim0 position for (idim0 = v_start[0] ; idim0 < v_end[0] ; ++idim0) { // set the pointer to the buffer's position to fill ibuf = (idim0 - v_start[0]); val = inc_ptr(buf, ibuf, type); // read the entry value in the file offset_val = offset_dim0 + (idim0 * v_sz[0]); fseek(fp, offset_val, SEEK_SET); ret = fread(val, size_type, length, fp); // swap if needed (for little endian machines) if (!endianness) swap_endianess(val, type); } } else if (rank == 2) { offset_dim0 = offset_root; // save start of dim0 position for (idim0 = v_start[0] ; idim0 < v_end[0] ; ++idim0) { offset_dim1 = offset_dim0 + (idim0 * v_sz [0]); // save start of dim1 position for (idim1 = v_start[1] ; idim1 < v_end[1] ; ++idim1) { // set the pointer to the buffer's position to fill ibuf = (idim0 - v_start[0]) * v_sz_read [1] + (idim1 - v_start[1]); val = inc_ptr(buf, ibuf, type); // read the entry value in the file offset_val = offset_dim1 + idim1 * v_sz [1]; fseek(fp, offset_val, SEEK_SET); ret = fread(val, size_type, length, fp); // swap if needed (for little endian machines) if (!endianness) swap_endianess(val, type); } // prepare next iter } } else { g_exception e( __FILE__ , __LINE__ , "Unsupported rank " + MyTools::to_string(rank) ); throw e; } if (!already_opened_file) close_file(); return true; } // bool PARASOLData::read_data( void * buf, const int &entry_index, int * start, int * edges, const int rank ) // { // assert(buf!=NULL); // assert(entry_index>=0); // assert(start!=NULL); // assert(edges!=NULL); // assert(rank>0); // // bool already_opened_file = is_file_loaded(); // if (!already_opened_file) // open_file(); // // int record_offset=get_record_offset(DATA); // // // the format of this entry // RecordFormat *rec_format=const_cast(get_data_file_format()->get_data_format()); // EntryFormat var_format = (*rec_format)[entry_index]; // unsigned int length=var_format.len; // nb of values to read // PARASOLDataType type=var_format.type; // size_t size_type=PARASOLLeaderFormat::get_size_of(type); // size in bytes of one value // int file_offset; // file offset of the value to read // bool endianness = MyTools::get_endianness(); // // // --- set the directions range to be read. No directionnal param : range = 0->1 // int y_start=start[0]; // int x_start=0; // if (rank>1) // x_start=start[1]; // int y_dim=edges[0]; // int x_dim=1; // if (rank>1) // x_dim=edges[1]; // // // --- fill the buffer with fill values --- // int nb_val=x_dim*y_dim; // fill_buffer_default(buf,nb_val,type); // // // --- read the file --- // int data_record_offset=y_start*data_file_descriptor->one_data_rec_len; // offset of the first value to read, relative to the data record start // int i,j,j_line; // int y_end=y_start+y_dim; // int x_end=x_start+x_dim; // void* val=NULL; // int ret = -1; // // define value iterator // vector i_val(rank); // for (j = y_start ; j < y_end ; ++j) { // i_val [0] = j; // j_line = (j - y_start) * x_dim; // for (i = x_start ; i < x_end ; ++i) { // // set the offset of the data // if (rank > 1) // i_val [1] = i; // // file_offset=record_offset+data_record_offset+get_entry_offset(DATA,entry_index,j,i); // file_offset = record_offset + data_record_offset + get_entry_offset(DATA, entry_index, i_val); // // set the pointer to the buffer's position to fill // val=inc_ptr(buf,j_line+(i-x_start),type); // // read the entry value in the file // fseek(fp, file_offset, SEEK_SET); // ret = fread(val, size_type, length, fp); // // swap if needed (for little endian machines) // if (!endianness) // swap_endianess(val,type); // } // data_record_offset+=data_file_descriptor->one_data_rec_len; // } // // if (!already_opened_file) // close_file(); // return true; // } // const int PARASOLData::get_entry_offset(const Record rec, const int entry_idx, const int record_idx, const int direction_index, const int val_index) { // // the offset of the entry from the current record start // EntryFormat format = (*get_record_format(rec))[entry_idx]; // int entry_offset=format.pos-1; // -1 because start position are given from 1 in the DPC (and so on in the format) and in this code offsets are treated from 0 // // // int grp_nb_val=get_entry_group_nb_val(rec,entry_idx); // // int grp_size=get_entry_group_size(rec,entry_idx); // // if (grp_nb_val>1 && direction_index!=-1) { // vector v_entry_block = get_entry_block(rec, entry_idx); // if (! v_entry_block.empty()) { // // the entry is in a group // /* entry_offset+=direction_index*grp_size;*/ // entry_offset += direction_index * v_entry_block[0].size; // } // /* // If the entry is in a group that is repeated many times in a record (directionnal parameters), we need to know the size of this group. // If the entry isn't in a group, the get_entry_group_size method will return 0, and this additional group offset will be ignored // */ // return entry_offset; // } const int PARASOLData::get_nb_data_record() const { return data_file_descriptor->nb_data_rec; } const int PARASOLData::get_sz_data_record() const { return data_file_descriptor->one_data_rec_len; } const int PARASOLData::get_data_entry_index( const string &var_name ) const { int idx=data_file_format->get_entry_index(var_name); if (idx<0) { // invalid parametre name bad_parametre e(var_name); throw e; } return idx; } const int PARASOLData::get_nb_val( const string & var_name, const int edges, const int dir_idx ) const { int var_idx=data_file_format->get_entry_index(var_name); return get_nb_val(var_idx, edges, dir_idx); } const int PARASOLData::get_nb_val( const int & entry_index, const int edges, const int dir_idx ) const { int my_edges = edges; if (my_edges == -1) // read all records my_edges=data_file_descriptor->nb_data_rec; vector v_entry_block = get_entry_block(DATA, entry_index); if (! v_entry_block.empty()) // directionnal entry // read all directions my_edges *= v_entry_block[0].ntime; return my_edges; } vector< EntryBlock > PARASOLData::get_entry_block(const Record rec, const int entry_idx) const { vector< EntryBlock > v_out (0); g_exception e; /***** DATA_FILE_DESCRIPTOR *****/ if (rec == DATA_FILE_DESCRIPTOR) // no blocks repeatition return v_out; /***** DATA RECORD *****/ int ntime = MAX_PARASOL_DIRECTION; int nrec = get_nb_data_record(); int sz_rec = get_sz_data_record(); // records blocks v_out.push_back(EntryBlock(nrec, sz_rec)); switch (product) { case LS_AEROSOL_2 : // no directionnal params case OC_AEROSOL_2 : case OC_SURF_NON_DIR_2 : return v_out; break; case BASIC_1 : if (entry_idx == 6) // DQX : 16 times 2 bytes v_out.push_back (EntryBlock(ntime, 2)); else if (entry_idx >= 11 && entry_idx <= 33) // directionnal sequences entries -> 16 times * 43 bytes v_out.push_back (EntryBlock(ntime, 43)); break; case LS_SURF_DIR_2 : if (entry_idx >= 10 && entry_idx <= 18) // directionnal entries -> 16 times * 17 bytes v_out.push_back (EntryBlock(ntime, 17)); break; case OC_SURF_DIR_2 : if (entry_idx >= 20 && entry_idx <= 27) // directionnal entries -> 16 times * 15 bytes v_out.push_back (EntryBlock(ntime, 15)); break; case RB_2 : if (entry_idx >= 44 && entry_idx <= 53) // directionnal entries -> 16 times * 14 bytes v_out.push_back (EntryBlock(ntime, 14)); break; case RB_3 : case OC_MARINE_3 : case OC_AEROSOL_3 : case LS_DIR_SIGN_3: case LS_ALBEDO_3 : case LS_ATMO_3 : e.set( __FILE__ , __LINE__ , "Method not implemented for L3 products" ); throw e; break; case UNDEFINED : default : e.set( __FILE__ , __LINE__ , "Invalid product ID" ); throw e; break; } return v_out; } // const int PARASOLData::get_entry_group_size( const Record rec, const int entry_idx ) { // assert(entry_idx>=0); // if (rec==DATA_FILE_DESCRIPTOR) return 1; // else if (rec==DATA) { // /************* L1 products *************/ // //----- BASIC_1 -----// // if ( product==BASIC_1 ) { // if (entry_idx<6) // those entries are not in group (ie they are only one time inside a data record) // return 0; // else if ((entry_idx==6)) // dqx // return 2; // else if (entry_idx>6 && entry_idx<11) // return 0; // else if (entry_idx>=11 && entry_idx<=33) // group of sequences entries -> the entire group for one sequence has a size of 43 bytes // return 43; // else if (entry_idx>33) { // shouldn't be the case : the last entry is the 3rd Component Stokes Vector for channel 865P at index 33 // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // /************* L2 products *************/ // //----- LS_SURF_DIR_2 -----// // else if ( product==LS_SURF_DIR_2 ) { // if (entry_idx<10) // those entries are not in group (ie they are only one time inside a data record) // return 0; // else if (entry_idx>=10 && entry_idx<=18) // return 17 ; // size of one directionnal parametres group // else { // shouldn't be the case // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // //----- LS_AEROSOL_2 -----// // else if ( product==LS_AEROSOL_2 ) { // if (entry_idx<=13) // return 0; // no directional param for this product // else { // shouldn't be the case // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // //----- OC_SURF_DIR_2 -----// // else if ( product==OC_SURF_DIR_2 ) { // if (entry_idx<20) // not in group // return 0; // else if (entry_idx>=20 && entry_idx<=27) // return 15; // size of one directionnal parametres group // else { // shouldn't be the case // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // //----- OC_SURF_NON_DIR_2 -----// // else if ( product==OC_SURF_NON_DIR_2 ) { // if (entry_idx<=27) // return 0; // no directional param for this product // else { // shouldn't be the case // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // //----- OC_AEROSOL_2 -----// // else if ( product==OC_AEROSOL_2) { // if (entry_idx<=27) // return 0; // no directional param for this product // else { // shouldn't be the case // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // //----- RB_2 -----// // else if ( product==RB_2 ) { // if (entry_idx<44) // not in group // return 0; // else if (entry_idx>=44 && entry_idx<=53) // return 14; // size of one directionnal parametres group // else { // shouldn't be the case // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // /************ L3 products *************/ // else if ( product==RB_3 || product==OC_MARINE_3 || product==OC_AEROSOL_3 || product==LS_DIR_SIGN_3 || product==LS_ALBEDO_3 || product==LS_ATMO_3) { // cerr<<"In "<<__FILE__<<" at "<<__LINE__<<" : Sorry, method not implemented for L3 products"<=0); // if (rec==DATA_FILE_DESCRIPTOR) return 1; // else if (rec==DATA) { // /************* L1 products *************/ // //----- BASIC_1 -----// // if ( product==BASIC_1 ) { // if (entry_idx<6) // those entries are not in group (ie they are only one time inside a data record) // return 1; // else if (entry_idx==6) // dqx // return MAX_PARASOL_DIRECTION; // else if (entry_idx>6 && entry_idx<11) // those entries are not in group (ie they are only one time inside a data record) // //if (entry_idx<11) // those entries are not in group (ie they are only one time inside a data record) // return 1; // else if (entry_idx>=11 && entry_idx<=33) // group of sequences entries -> the entire group for one sequence has a size of 43 bytes // return MAX_PARASOL_DIRECTION; // else if (entry_idx>33) { // shouldn't be the case : the last entry is the 3rd Component Stokes Vector for channel 865P at index 33 // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // /************* L2 products *************/ // //----- LS_SURF_DIR_2 -----// // else if ( product==LS_SURF_DIR_2 ) { // if (entry_idx<10) // those entries are not in group (ie they are only one time inside a data record) // return 1; // else if (entry_idx>=10 && entry_idx<=18) // return MAX_PARASOL_DIRECTION ; // size of one directionnal parametres group // else { // shouldn't be the case // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // //----- LS_AEROSOL_2 -----// // else if ( product==LS_AEROSOL_2 ) { // if (entry_idx<=13) // return 1; // no directional param for this product // else { // shouldn't be the case // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // //----- OC_SURF_DIR_2 -----// // else if ( product==OC_SURF_DIR_2 ) { // if (entry_idx<20) // not in group // return 1; // else if (entry_idx>=20 && entry_idx<=27) // return MAX_PARASOL_DIRECTION; // size of one directionnal parametres group // else { // shouldn't be the case // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // //----- OC_SURF_NON_DIR_2 -----// // else if ( product==OC_SURF_NON_DIR_2 ) { // if (entry_idx<=27) // return 1; // no directional param for this product // else { // shouldn't be the case // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // //----- OC_AEROSOL_2 -----// // else if ( product==OC_AEROSOL_2) { // if (entry_idx<=27) // return 1; // no directional param for this product // else { // shouldn't be the case // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // //----- RB_2 -----// // else if ( product==RB_2 ) { // if (entry_idx<44) // not in group // return 1; // else if (entry_idx>=44 && entry_idx<=53) // return MAX_PARASOL_DIRECTION; // size of one directionnal parametres group // else { // shouldn't be the case // bad_parametre_idx e(entry_idx); // throw e; // return 0; // } // } // /************ L3 products *************/ // else if ( product==RB_3 || product==OC_MARINE_3 || product==OC_AEROSOL_3 || product==LS_DIR_SIGN_3 || product==LS_ALBEDO_3 || product==LS_ATMO_3) { // cerr<<"In "<<__FILE__<<" at "<<__LINE__<<" : Sorry, method not implemented for L3 products"<