/*************************************************************************** * 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 "parasolfiledata.h" const double PARASOLFileData::lat2time_coef=3840./233.; const int PARASOLFileData::nb_parasol_direction = 16; const double PARASOLFileData::satellite_altitude = 705.e3; const double PARASOLFileData::pix_sz_nadir = 6e3; // 6 km const double PARASOLFileData::pix_obs_nadir_angle = atan2(PARASOLFileData::pix_sz_nadir / 2., PARASOLFileData::satellite_altitude); const double PARASOLFileData::max_sat_nadir_angle = radians (75.); const double PARASOLFileData::pix_sz_max = PARASOLFileData::satellite_altitude * (tan (PARASOLFileData::max_sat_nadir_angle) - tan (PARASOLFileData::max_sat_nadir_angle - PARASOLFileData::pix_obs_nadir_angle)); const int PARASOLFileData::nb_acq_seq_max = 130; const int PARASOLFileData::nb_acq_img_max = 9; PARASOLFileData::PARASOLFileData(const string& name, const string& mode): FileData(name,mode), SatelliteFileData(name,mode) { init(); } void PARASOLFileData::init() { instrument=-1; level=-1; processing_line=UNDEFINED; product=' '; orbit_cycle_nb=-1; orbit_nb=-1; reprocessing_nb=' '; grid_factor=-1; leader=NULL; line_data=NULL; col_data=NULL; software_version_number = ""; // extract the product infos from the file name string short_filename = get_tail(get_name()); parse_filename(short_filename); // init grid paramtres set_grid_factor(); sz_cell = (double)(grid_factor) / 18.; sz_grid [0] = 3240 / grid_factor; sz_grid [1] = 6480 / grid_factor; // init the leader file reader string filename_skeleton=get_directory(get_name())+get_radix(); // remove ending "L" or "D" character if ((*filename_skeleton.rbegin())=='L' || (*filename_skeleton.rbegin())=='D') filename_skeleton=filename_skeleton.substr(0,filename_skeleton.size()-1); leader = new PARASOLLeader(filename_skeleton+"L"); data = new PARASOLData(filename_skeleton+"D"); if (leader!=NULL) { leader->open_file(); //-- read the software version number leader->read_record(LEADER_FILE_DESCRIPTOR); software_version_number = leader->leader_file_descriptor->soft_version; //-- read the spatio-temporal parameters leader->read_record(SPATIO_TEMPORAL_CHARACTERISTICS); // init the time coverage date->set_date_str(leader->spatio_temp_char->first_acq_date,"%Y%m%d%H%M%S"); Date end_date; end_date.set_date_str(leader->spatio_temp_char->last_acq_date,"%Y%m%d%H%M%S"); time_coverage=end_date.get_TAI93_time()-date->get_TAI93_time(); // init the spatial coverage // unsigned short line_minmax[2]; // float lat_minmax[2]; // int grid_idx[2]; // grid_idx[1]=0; // dummy col number // set the min latitude using the min line index int irow = MyTools::string2int(leader->spatio_temp_char->line_nb_southern_pix); lat_min = get_grid_lat(irow); // line_minmax[0]= // grid_idx[0]=line_minmax[0]; // min line // grid_to_geolocation(grid_idx, lat_minmax); // lat_min=lat_minmax[0]; // set the max latitude using the max line index irow = MyTools::string2int(leader->spatio_temp_char->line_nb_northern_pix); lat_max = get_grid_lat(irow); // grid_idx[0]=line_minmax[1]; // max line // grid_to_geolocation(grid_idx,lat_minmax); // lat_max=lat_minmax[1]; // init the scaling factors leader->read_record(LEADER_FILE_DESCRIPTOR); // leader->print_leader_file_descriptor(); leader->read_record(SCALING_FACTORS); // leader->print_scaling_factors(); // leader->read_record(SPATIO_TEMPORAL_CHARACTERISTICS); // leader->print_spatio_temp_char(); // leader->read_record(TECHNOLOGICAL_PARAMETERS); // leader->print_techno_param(); leader->close_file(); } // geolocation buffers line_data = NULL; col_data = NULL; // viewing directions buffers v_alt_view = NULL; v_saa = NULL; v_vza = NULL; v_raa = NULL; v_ni = NULL; v_sn = NULL; v_x_sat = NULL; v_y_sat = NULL; v_z_sat = NULL; } PARASOLFileData::~PARASOLFileData() { delete leader, leader = NULL; delete data, data = NULL; free_geolocation_data(); } bool PARASOLFileData::check_filename( const string& short_filename ) const { string parasol_filename(short_filename); bool check_instrument=( parasol_filename[0]=='P' && (parasol_filename[1]=='1' || parasol_filename[1]=='2' || parasol_filename[1]=='3') ); bool check_level=check_instrument && ( parasol_filename[2]=='L' && (parasol_filename[3]=='1' || parasol_filename[3]=='2') ); if (parasol_filename[3]=='3') cerr<<"In "<<__FILE__<<" at "<<__LINE__<<" : Sorry but level 3 PARASOL files can't be read yet. The PARASOLFileData class must be completed"<<endl; bool check_processing_line=check_level && ( parasol_filename[4]=='T' && (parasol_filename[5]=='B' || parasol_filename[5]=='L' || parasol_filename[5]=='O' || parasol_filename[5]=='R') ); bool check_product=check_processing_line && ( parasol_filename[6]=='G' && (parasol_filename[7]=='A' || parasol_filename[7]=='B' || parasol_filename[7]=='C' || parasol_filename[7]=='1') ) ; bool check_orbit=check_product; if (parasol_filename[3]!='3') { // attributes specific to level 1 and 2 files string s_orbit_cycle_nb = parasol_filename.substr(8,3); string s_orbit_nb = parasol_filename.substr(11,3); string s_reprocessing_nb = parasol_filename.substr(14,1); char s_reprocessing_nb_char = s_reprocessing_nb[0]; check_orbit=check_orbit && MyTools::is_int(s_orbit_cycle_nb) && MyTools::is_int(s_orbit_nb); check_orbit=check_orbit && (s_reprocessing_nb_char>='A' && s_reprocessing_nb_char<='Z'); } else { // TODO level 3 attributes must be implemented here } bool all_checked = check_orbit && ( parasol_filename[15]=='L' || parasol_filename[15]=='D' ); if ( !all_checked ) { invalid_filename e(__FILE__,__LINE__,parasol_filename,"PARASOL"); throw e; } return all_checked; } void PARASOLFileData::parse_filename( const string& short_filename ) { check_filename(short_filename); // throw a parse_PARASOL_filename_error if the filename doesn't matches the pattern try { string parasol_filename(short_filename); instrument = MyTools::char2int(parasol_filename[1]); level=MyTools::char2int(parasol_filename[3]); char processing_line_code=parasol_filename[5]; if (processing_line_code == 'B') processing_line=BASIC; else if (processing_line_code == 'L') processing_line=LAND_SURFACE; else if (processing_line_code == 'O') processing_line=OCEAN_COLOR; else if (processing_line_code == 'R') processing_line=RADIATION_BUDGET; else processing_line=UNDEFINED; product=parasol_filename[7]; if (level!=3) { // attributes specific to level 1 and 2 files string s_orbit_cycle_nb = parasol_filename.substr(8,3); orbit_cycle_nb=MyTools::string2int(s_orbit_cycle_nb); string s_orbit_nb = parasol_filename.substr(11,3); orbit_nb=MyTools::string2int(s_orbit_nb); reprocessing_nb=parasol_filename[14]; } else { // TODO level 3 attributes must be implemented here } } catch (invalid_filename e) { cerr<<e.what()<<endl; throw; } } const string PARASOLFileData::get_processing_line_string( ) const { if (processing_line == BASIC) return "basic"; else if (processing_line == LAND_SURFACE) return "land surface"; else if (processing_line == OCEAN_COLOR) return "ocean color"; else if (processing_line == RADIATION_BUDGET) return "radiation budget"; else return "undefined"; } const char PARASOLFileData::get_processing_line_char( ) const { if (processing_line == BASIC) return 'B'; else if (processing_line == LAND_SURFACE) return 'L'; else if (processing_line == OCEAN_COLOR) return 'O'; else if (processing_line == RADIATION_BUDGET) return 'R'; else return ' '; } const string PARASOLFileData::get_radix() { string ret="P"+MyTools::to_string(instrument)+ "L"+MyTools::to_string(level)+ "T"+get_processing_line_char()+ "G"+product+ MyTools::int2string(orbit_cycle_nb,3)+MyTools::int2string(orbit_nb,3)+ reprocessing_nb; return ret; } const double PARASOLFileData::get_grid_lat(const int irow) const { if (irow <= 0 || irow > sz_grid [0]) { g_exception e(__FILE__,__LINE__, "Invalid row indice " + MyTools::to_string(irow)); throw e; } return 90. - ((double)(irow) - .5) * sz_cell; } const int PARASOLFileData::get_nrow() const { return sz_grid [0]; } const int PARASOLFileData::get_ncol(const int irow) const { if (irow == -1) return sz_grid [0]; int ni = (int)(round (sz_grid [0] * sin (radians((irow - 0.5) * sz_cell)))); return 2 * ni; } const int PARASOLFileData::get_ncol(const double lat) const { int ni = (int)(round(sz_grid [0] * cos(radians(lat)))); return 2 * ni; } void PARASOLFileData::geolocation_to_grid(const float lat, const float lon, int & irow, int & icol) { check_geolocation(lat, lon); irow = (int)(round((1. / sz_cell) * (90. - lat) + 0.5)); int ni = get_ncol (irow) / 2; icol = (int)(round((sz_grid[0] + 0.5) + (ni / 180.) * lon)); } void PARASOLFileData::geolocation_to_grid( const float * lat_lon, int * grid_idx ){ geolocation_to_grid (lat_lon[0], lat_lon[1], grid_idx[0], grid_idx[1]); } void PARASOLFileData::grid_to_geolocation( const int igrid[], float lat_minmax[], float lon_minmax[]) { // grid middle pixel lat,lon float lat, lon; grid_to_geolocation(igrid, lat, lon); double dlat = 0.5 * sz_cell; // 2*delta = size of a grid cell side along latitudes lat_minmax[0] = lat - dlat; lat_minmax[1] = lat + dlat; int ni = get_ncol (lat) / 2; double dlon = 180. / ni; lon_minmax[0] = lon - dlon; lon_minmax[1] = lon + dlon; } void PARASOLFileData::grid_to_geolocation(const int irow, const int icol, float & lat, float & lon) { check_grid_coord(irow, icol); lat = get_grid_lat(irow); int ni = get_ncol (lat) / 2; double dlon = 180. / ni; lon = dlon * (icol - (sz_grid [0] + .5)); } void PARASOLFileData::grid_to_geolocation(const int igrid[], float & lat, float & lon) { grid_to_geolocation (igrid[0], igrid[1], lat, lon); } void PARASOLFileData::grid_to_geolocation(const int igrid[], float pos[]) { grid_to_geolocation (igrid[0], igrid[1], pos[0], pos[1]); } void PARASOLFileData::set_grid_factor() { // algo build on the PARASOL level 1 Standard product manual Appendix A if (level==1) { grid_factor=1; } else if (level == 2) { if (processing_line==RADIATION_BUDGET) { grid_factor=3; } else if (processing_line==OCEAN_COLOR) { if (product=='A' || product=='B') grid_factor=1; else if (product=='C') grid_factor=3; } else if (processing_line==LAND_SURFACE) { if (product=='A') grid_factor=1; else if (product=='C') grid_factor=3; } } else if (level == 3) { if (processing_line==RADIATION_BUDGET) { grid_factor=3; } else if (processing_line==OCEAN_COLOR) { if (product=='B') grid_factor=1; else if (product=='C') grid_factor=3; } else if (processing_line==LAND_SURFACE) { if (product=='A' || product=='B') grid_factor=1; else if (product=='C') grid_factor=3; } } } bool PARASOLFileData::init_read_data_range( const int entry_idx, int * &start, int * &edges, int &rank ) { assert((start==NULL && edges==NULL) || (start!=NULL && edges!=NULL)); bool allocation_done=false; /* initialize the data selector range */ // EntryFormat *entry_format=const_cast<EntryFormat *>(get_entry_format(entry_idx)); vector<int> data_dimension=get_data_dimension(entry_idx); int my_rank=data_dimension.size(); if (rank!=-1 && rank!=my_rank) { bad_rank e(rank,my_rank); throw e; } // method sets the rank itself if (rank==-1) rank=my_rank; // Do allocations if needed if (start==NULL) { // read the whole data : start from 0 allocation_done=true; start=new int [rank]; // init to metacharacter -1 for (int i=0;i<rank;++i) start[i]=-1; } if (edges==NULL) { // read the whole data : edges from 0 allocation_done=true; edges=new int [2]; for (int i=0;i<rank;++i) edges[i]=-1; } // replace -1 metacharacter by values : 0 for starts, max_nb_val for edges for (int i=0;i<rank;++i) { if (start[i]==-1) start[i]=0; // use default if (edges[i]==-1) edges[i]=data_dimension[i]-start[i]; // use default } /* check data selector range validity */ for (int i=0;i<rank;++i) { if (start[i]<0 || start[i]>(data_dimension[i]-1)) { bad_index e(start[i],data_dimension[i]-1); throw e; } if (edges[i]<0 || edges[i]>(data_dimension[i]-start[i])) { bad_index e(edges[i],(data_dimension[i]-start[i])); throw e; } } return allocation_done; } const EntryFormat* PARASOLFileData::get_entry_format( const string & entry_name ) { // parameter name to index int entry_idx=this->data->get_data_file_format()->get_entry_index(entry_name); return get_entry_format(entry_idx); } const EntryFormat* PARASOLFileData::get_entry_format( const int & entry_idx ) { // parameter name to index if (entry_idx!=-1) { // retrieve the entry corresponding to var_name RecordFormat *rec_format=const_cast<RecordFormat *>(data->get_data_file_format()->get_data_format()); return &(*rec_format)[entry_idx]; } else // no entry with this name return NULL; } void * PARASOLFileData::read_data(void * data_buf, const char * var_name, int * start, int * stride, int * edges, int rank ) { // scaling shouldn't be applied to bitfieds types and some int types string s_var_name(var_name); // for == comparaisons // TODO add other bitfield and a clever way to discriminate when the "read_count_data" is preferable to "read_scaled_data". This can be done using the numeric type, the field name ??? if (s_var_name==(string)("dqx") || s_var_name==(string)("utc_hour") || s_var_name==(string)("utc_minute")) return read_count_data((unsigned char*)data_buf, var_name, start, edges, rank); else return read_scaled_data((double*)data_buf, var_name, start, edges, rank); } double * PARASOLFileData::read_scaled_data( double * scaled_data, const char * var_name, int * start, int * edges, int rank ) { // Sets the data selector range and do the needed allocation int var_idx=data->get_data_entry_index(var_name); bool data_range_allocated=init_read_data_range(var_idx,start,edges,rank); // process depends of the data type EntryFormat *var_format=const_cast<EntryFormat *>(get_entry_format(var_name)); // allocate scaled data if needed int buffer_size=1; for (int i=0;i<rank;++i) buffer_size*=edges[i]; // allocate the buffer for reading all the data if (scaled_data==NULL) { scaled_data=new double[buffer_size]; } // read the scaling factors double slope=1.; double offset=0.; unsigned short nb_bytes=0; get_scaling(var_name,slope,offset,nb_bytes); if (var_format!=NULL) { PARASOLDataType type=var_format->type; // the number of read values // count buffer type depends of the entry type if (type== UINT8) { unsigned char* count_data=NULL; count_data=static_cast<unsigned char*>(read_count_data(count_data,var_name,start,edges)); data->apply_scaling(scaled_data,count_data,slope,offset,buffer_size); delete[] count_data; } else if (type== UINT16) { unsigned short* count_data=NULL; count_data=static_cast<unsigned short*>(read_count_data(count_data,var_name,start,edges)); data->apply_scaling(scaled_data,count_data,slope,offset,buffer_size); delete[] count_data; } else if (type== INT16) { short* count_data=NULL; count_data=static_cast<short*>(read_count_data(count_data,var_name,start,edges)); data->apply_scaling(scaled_data,count_data,slope,offset,buffer_size); delete[] count_data; } else if (type== UINT32) { unsigned int * count_data=NULL; count_data=static_cast<unsigned int *>(read_count_data(count_data,var_name,start,edges)); data->apply_scaling(scaled_data,count_data,slope,offset,buffer_size); delete[] count_data; } else if (type== INT32) { int * count_data=NULL; count_data=static_cast<int*>(read_count_data(count_data,var_name,start,edges)); data->apply_scaling(scaled_data,count_data,slope,offset,buffer_size); delete[] count_data; // } else if (type== BIT2) { // bit<2>* count_data=NULL; // count_data=read_count_data(count_data,var_name,start,edges,dir); // } else if (type== BIT4) { // apply_scaling< bit<4> >(scaled_data,var_name,start,edges); // } else if (type== BIT8) { // apply_scaling< bit<8> >(scaled_data,var_name,start,edges); // } else if (type== BIT16) { // apply_scaling< bit<16> >(scaled_data,var_name,start,edges); // } else if (type== BIT32) { // apply_scaling< bit<32> >(scaled_data,var_name,start,edges); // } else { // cerr<<"In "<<__FILE__<<" at "<<__LINE__<<" : Unimplemented variable type"<<endl; } else if (type==B2) { short* count_data=NULL; count_data=static_cast<short*>(read_count_data(count_data,var_name,start,edges)); data->apply_scaling(scaled_data,count_data,slope,offset,buffer_size); delete[] count_data; } // for other types, it is supposed the scaling is 1 } // free selector range allocations if (data_range_allocated && start!=NULL && edges!=NULL) { delete[] start; start=NULL; delete[] edges; edges=NULL; } return scaled_data; } void * PARASOLFileData::read_count_data( void * buf, const char * var_name, int * start, int * edges, int rank ) { int entry_idx=this->data->get_data_file_format()->get_entry_index(var_name); if (entry_idx!=-1) buf=read_count_data(buf,entry_idx,start,edges); return buf; } void * PARASOLFileData::read_count_data( void * count_data, const int entry_idx, int * start, int * edges, int rank ) { // Sets the data selector range and do the needed allocation bool data_range_allocated=init_read_data_range(entry_idx,start,edges,rank); // process depends of the data type EntryFormat *var_format=const_cast<EntryFormat *>(get_entry_format(entry_idx)); if (var_format!=NULL) { // if not specified, set the authorized data range to be read //init_read_data_range(start,edges); // an entry with this name exists : find its type PARASOLDataType type=var_format->type; if (count_data==NULL) { // allocate the buffer for reading the data int buffer_size=1; for (int i=0;i<rank;++i) buffer_size*=edges[i]; // add the length of the entry -> for char and bit types buffer_size*=var_format->len; // allocate the buffer count_data=PARASOLFileReader::custom_new(count_data,buffer_size,type); } // read the file data->read_data(count_data,entry_idx,start,edges,rank); } // free selector range allocations if (data_range_allocated && start!=NULL && edges!=NULL) { delete[] start, start = NULL; delete[] edges, edges = NULL; } return count_data; } const int PARASOLFileData::get_nb_data() { return data->get_nb_data_record(); } const bool PARASOLFileData::is_geolocation_data_loaded( ) const { return (line_data!=NULL && col_data!=NULL); } void PARASOLFileData::free_geolocation_data() { delete[] line_data, line_data = NULL; delete[] col_data, col_data = NULL; } void PARASOLFileData::load_geolocation_data() { if (!is_geolocation_data_loaded()) { // cout<<get_filename()<<"->load_geolocation_data"<<endl; bool already_opened_data_file = data->is_file_loaded(); if (!already_opened_data_file) data->open_file(); if (data->get_nb_data_record()>0) { line_data = static_cast<unsigned short *>(read_count_data(NULL,"line")); col_data = static_cast<unsigned short *>(read_count_data(NULL,"col")); } // load grid to record indices table load_pix2data_map(); load_v_pixel(); if (!already_opened_data_file) data->close_file(); } } void PARASOLFileData::load_v_pixel() { // unused at this time ; } const bool PARASOLFileData::contain_data( const float & lat, const float & lon, const double & time ) { return ( (time==-1. || contain_time(time)) && contain_location(lat,lon) ); } const bool PARASOLFileData::contain_location( const float & lat, const float & lon ) { // convert (lat,lon) to (lin,col) float lat_lon[]={lat,lon}; int grid_idx[2]; geolocation_to_grid(lat_lon,grid_idx); if (grid_idx[0]!=-1 && grid_idx[1]!=-1) { return contain_pixel(grid_idx); } else return false; } const bool PARASOLFileData::contain_pixel( const int* pix_idx ) { int irec; return get_index(pix_idx,irec); } void PARASOLFileData::get_pixel( const int & irec, int pix[] ) { bool is_geolocation_already_loaded=is_geolocation_data_loaded(); if (!is_geolocation_already_loaded) load_geolocation_data(); pix[0]=line_data[irec]; pix[1]=col_data[irec]; if (!is_geolocation_already_loaded) free_geolocation_data(); } void PARASOLFileData::igrid2idata(const int igrid[], int & irec) { get_index (igrid, irec); } void PARASOLFileData::igrid2idata(const vector< int > & igrid, int & irec) { get_index (igrid, irec); } const bool PARASOLFileData::get_index(const vector <int> & v_ipix, int & irec) { std::map <PixelIndice, DataIndice>::iterator it; if (v_ipix.size() > 2) { // directional indice present in pixel vector <int> _v_ipix (2); copy (v_ipix.begin(), v_ipix.begin() + 2, _v_ipix.begin()); it = ipix2idata.find (_v_ipix); } else it = ipix2idata.find (v_ipix); bool ret; if (it == ipix2idata.end()) { // unexisting pixel irec = -1; ret = false; } else { irec = (it->second)[0]; ret = true; } // cout << "irec " << irec << endl; return ret; } const bool PARASOLFileData::get_index( const int* pix_idx, int & irec ) { irec = -1; vector <int> v_ipix (2); v_ipix [0] = pix_idx[0]; v_ipix [1] = pix_idx[1]; return get_index (v_ipix, irec); // if (pix_idx!=NULL) { // unsigned short lin_idx=pix_idx[0]; // unsigned short col_idx=pix_idx[1]; // bool is_geolocation_data_already_loaded=is_geolocation_data_loaded(); // if (!is_geolocation_data_already_loaded) // load_geolocation_data(); // // // line indexes are sorted -> do a dichotomic search to find the range for which line index = // size_t nb_data=get_nb_data(); // pair<unsigned short*, unsigned short*> result; // unsigned short *found_pix=NULL; // // the ordering of the line indexes depends of the level : 1->descending, other->ascending // if (level==1) { // result = equal_range(line_data, line_data + nb_data, lin_idx, PARASOLFileData::greater_comparator<unsigned short>); // } else { // result = equal_range(line_data, line_data + nb_data, lin_idx); // } // int line_range[2]; // line_range[0]= distance(line_data,result.first); // line_range[1]= distance(line_data,result.second); // if (line_range[0]<line_range[1]) { // // the data contain this line index -> search for the column in equal lines range // unsigned short* start_col_search = col_data + line_range[0]; // unsigned short* end_col_search = col_data + line_range[1]; // found_pix = find(start_col_search, end_col_search, col_idx); // if (found_pix!=NULL && found_pix!=end_col_search) { // irec=distance(col_data,found_pix); // found=true; // } // } // if (!is_geolocation_data_already_loaded) // free_geolocation_data(); // } else // cerr<<"In "<<__FILE__<<" at "<<__LINE__<<" NULL pixel index not allowed"<<endl; } const bool PARASOLFileData::get_index( const float & lat, const float & lon, int & irec ) { // convert (lat,lon) to (lin,col) float lat_lon[]={lat,lon}; int pix_idx[2]; geolocation_to_grid(lat_lon,pix_idx); if (pix_idx[0]!=-1 && pix_idx[1]!=-1) { return get_index(pix_idx,irec); } else return false; } void PARASOLFileData::get_scaling( const string & var_name, double & slope, double & offset, unsigned short & nb_bytes ) { int var_idx=data->get_data_entry_index(var_name); get_scaling(var_idx, slope, offset, nb_bytes); } void PARASOLFileData::get_scaling( const int var_idx, double & slope, double & offset, unsigned short & nb_bytes ) { if (!leader->is_record_loaded(SCALING_FACTORS)) leader->read_record(SCALING_FACTORS); int NB_PARAM_WITHOUT_SCALING=6; // the number of parametres in the data record that don't have a scaling set in the leader file. It seems to be the same value for all products (either l1, l2 and l3 ones) assert(var_idx>=0 && var_idx<(MyTools::string2int((leader->scaling_factors->nb_pix_param))+NB_PARAM_WITHOUT_SCALING)); if (var_idx>=0 && var_idx<NB_PARAM_WITHOUT_SCALING) { EntryFormat *var_format=const_cast<EntryFormat *>(get_entry_format(var_idx)); // record entry format description nb_bytes=PARASOLFileFormat::get_size_of(var_format->type); slope=1.; offset=0.; } else if (var_idx>=NB_PARAM_WITHOUT_SCALING && var_idx<(MyTools::string2int((leader->scaling_factors->nb_pix_param))+NB_PARAM_WITHOUT_SCALING) ) { // the 6th first parameters in the data record don't have any scaling factors set in the leader file. int param_nb=var_idx-NB_PARAM_WITHOUT_SCALING; // what is called the "param #" in the DPC nb_bytes=MyTools::string2int(leader->scaling_factors->nb_bytes[param_nb]); slope=MyTools::string2float(leader->scaling_factors->slope[param_nb]); offset=MyTools::string2float(leader->scaling_factors->offset[param_nb]); } else { // should never arrived here nb_bytes=0; slope=-DBL_MAX; offset=-DBL_MAX; } } const bool PARASOLFileData::is_file_loaded( ) { if (leader!=NULL && leader->is_file_loaded()) return true; else if (data!=NULL && data->is_file_loaded()) return true; else return false; } const int PARASOLFileData::get_max_direction( ) { return MAX_PARASOL_DIRECTION; } void PARASOLFileData::close_file( ) { if (leader!=NULL && leader->is_file_loaded()) leader->close_file(); if (data!=NULL && data->is_file_loaded()) data->close_file(); } vector<int> PARASOLFileData::get_data_dimension( const string & var_name ) { int entry_idx = data->get_data_entry_index(var_name); // entry index in the record return get_data_dimension(entry_idx); } vector<int> PARASOLFileData::get_data_dimension( const int entry_idx ) { vector<int> v; v.reserve(2); // at most 2 dimensions vector <EntryBlock> v_entry_block = data->get_entry_block(DATA, entry_idx); for (vector <EntryBlock>::iterator it = v_entry_block.begin() ; it != v_entry_block.end() ; ++it) { v.push_back(it->ntime); } return v; } void PARASOLFileData::idata2igrid(const int irec, int igrid[2]) { // validate record_index if (irec < 0 || irec >= data->get_nb_data_record()) { g_exception e(__FILE__,__LINE__, "Invalid record indice " + MyTools::to_string(irec)); throw e; } if (! is_geolocation_data_loaded()) { g_exception e(__FILE__,__LINE__, "Geolocation data not loaded. Consider to call load_geolocation_data()"); throw e; } igrid [0] = line_data [irec]; igrid [1] = col_data [irec]; } void PARASOLFileData::get_record_coord( const int irec, float &lat, float &lon ) { // read the col,line indexes of the record int igrid[2]; idata2igrid(irec, igrid); // col,line indexes to lat,lon float lat_range[] = {-1.,-1.}, lon_range[] = {-1.,-1.}; grid_to_geolocation(igrid, lat_range, lon_range); // compute the coordinates of the centre of the pixel lat = 0.5 * (lat_range[0] + lat_range[1]); lon = 0.5 * (lon_range[0] + lon_range[1]); } const bool PARASOLFileData::contain_location(const float &lat,const float &lon, const double &tolerance){ // convert (lat,lon) to (lin,col) float lat_lon[]={lat,lon}; float lat_minmax[]={lat,lon}; float lon_minmax[]={lat,lon}; int grid_idx[2]; geolocation_to_grid(lat_lon,grid_idx); if (grid_idx[0]!=-1 && grid_idx[1]!=-1) { grid_to_geolocation(grid_idx,lat_minmax,lon_minmax); float lat1 = (lat_minmax[0]+lat_minmax[1])/2.0; float lon1 = (lon_minmax[0]+lon_minmax[1])/2.0; if(lat1<lat-tolerance || lat+tolerance<lat1 ) return false; if(lon1<lon-tolerance || lon+tolerance<lon1 ) return false; return contain_pixel(grid_idx); } else return false; } const bool PARASOLFileData::contain_data( const float &lat, const float &lon, const double &time, const double &tolerance ) { return ( (time==-1. || contain_time(time)) && contain_location(lat,lon,tolerance) ); } const bool PARASOLFileData::get_index( const float & lat, const float & lon, int & irec, const float tolerance) { // convert (lat,lon) to (lin,col) float lat_lon[]={lat,lon}; float lat_minmax[]={lat,lon}; float lon_minmax[]={lat,lon}; int pix_idx[2]; irec=-1; geolocation_to_grid(lat_lon,pix_idx); if (pix_idx[0]!=-1 && pix_idx[1]!=-1) { grid_to_geolocation(pix_idx,lat_minmax,lon_minmax); float lat1 = (lat_minmax[0]+lat_minmax[1])/2.0; float lon1 = (lon_minmax[0]+lon_minmax[1])/2.0; if(lat1<lat-tolerance || lat+tolerance<lat1 ) return false; if(lon1<lon-tolerance || lon+tolerance<lon1 ) return false; return get_index(pix_idx,irec); } else return false; } const float PARASOLFileData::get_nearest_point_distance( const float & lat, const float & lon, const float coloc_tolerance ) { // convert (lat,lon) to (lin,col) float lat_lon[]={lat,lon}; float lat_minmax[]={lat,lon}; float lon_minmax[]={lat,lon}; int pix_idx[2]; double nearest_point_distance=-1.; geolocation_to_grid(lat_lon,pix_idx); if (pix_idx[0]!=-1 && pix_idx[1]!=-1) { grid_to_geolocation(pix_idx,lat_minmax,lon_minmax); float lat1 = (lat_minmax[0]+lat_minmax[1])/2.0; float lon1 = (lon_minmax[0]+lon_minmax[1])/2.0; if(lat1<lat-coloc_tolerance || lat+coloc_tolerance<lat1 ) return -1.; if(lon1<lon-coloc_tolerance || lon+coloc_tolerance<lon1 ) return -1.; nearest_point_distance=sqrt(pow(lat1-lat,2) + pow(lon1-lon,2)); return nearest_point_distance; } else return -1.; } void PARASOLFileData::load_pix2data_map() { free_pix2data_map(); // // number of available directions // char * v_ni = (char *)(read_count_data(NULL, "ni")); // int nrec = get_nb_data(); // int idir, ndir; // vector <int> ipix(3); // pixel indice in PARASOL grid [irow, icolumn, idirection] // vector <int> idata(2); // data indice [irecord, idirection] // // buffer linear indice // int ibuf; // for (int irec = 0 ; irec < nrec ; ++irec) { // // set pixel indices [irow, icolumn, idirection] // ndir = (int)(v_ni[irec]); // ipix[0] = line_data [irec]; // ipix[1] = col_data [irec]; // idata [0] = irec; // for (idir = 0 ; idir < ndir ; ++idir) { // ibuf = irec * nb_parasol_direction + idir; // ipix[2] = idir; // idata [1] = idir; // ipix2idata [ipix] = idata; // } // } int nrec = get_nb_data(); vector <int> ipix(2); // pixel indice in PARASOL grid [irow, icolumn] vector <int> idata(1); // data indice [irecord] for (int irec = 0 ; irec < nrec ; ++irec) { // set pixel indices [irow, icolumn, idirection] ipix[0] = line_data [irec]; ipix[1] = col_data [irec]; idata [0] = irec; ipix2idata [ipix] = idata; } } bool PARASOLFileData::is_earth_grid(const int irow, const int icol) const { // check row range if (irow < 1 || irow > sz_grid[0]) return false; // check col range. Validity dependqs of the row indice int ncol = sz_grid[1]; int ni = get_ncol (irow)/2; int icol_min = ncol/2 - ni + 1; int icol_max = ncol/2 + ni; if (icol < icol_min || icol > icol_max) return false; return true; } void PARASOLFileData::get_v_icol_neighbours(const int irow, const int icol, int dicol_min, int dicol_max, vector< int > & v_icol){ check_grid_coord (irow, icol); int ncol = sz_grid[1]; int ni = get_ncol (irow)/2; int icol_min = ncol/2 - ni + 1; int icol_max = ncol/2 + ni; // cout << "ni " << ni << " icol_min " << icol_min << " icol_max " << icol_max << endl; v_icol.clear(); if ((dicol_max - dicol_min + 1) >= (2 * ni) ) { // all columns requested MyTools::arange (v_icol, icol_min, icol_max + 1); } else { vector <int> v_tmp(0); // check icol min range int imin = (icol + dicol_min); if (imin >= icol_min) { // change date meridian not crossed MyTools::arange (v_icol, imin, icol + 1); } else { // change date meridian crossed MyTools::arange (v_icol, icol_min, icol + 1); // report remaining columns on east side int d = (icol_min - imin); MyTools::arange (v_tmp, icol_max - d + 1, icol_max + 1); MyTools::push_back (v_tmp, v_icol); } // check icol max range int imax = (icol + dicol_max); if (imax <= icol_max) { // change date meridian not crossed MyTools::arange (v_tmp, icol + 1, imax + 1); MyTools::push_back (v_tmp, v_icol); } else { // change date meridian crossed MyTools::arange (v_tmp, icol + 1, icol_max + 1); MyTools::push_back (v_tmp, v_icol); // report remaining columns on west side int d = (imax - icol_max); MyTools::arange (v_tmp, icol_min, icol_min + d); MyTools::push_back (v_tmp, v_icol); } } sort(v_icol.begin(), v_icol.end()); // cout << "irow " << irow << " icol " << icol << " dicol [" << dicol_min << ", " << dicol_max << "] " << MyTools::vec2str(v_icol) << endl; } void PARASOLFileData::get_neighbours_coord(const int irow, const int icol, int dirow_min, int dirow_max, int dicol_min, int dicol_max, vector< int > & v_irow, vector< int > & v_icol) { check_grid_coord (irow, icol); // int _d_icol = min (d_icol, icol_max / 2); // cout << "-----------------------------------------" << endl; // cout << "ipix [" << irow << ", " << icol << "] d_irow " << d_irow << " d_icol " << d_icol << endl; // cout << "irow range [" << irow_min << "," << irow_max << "] " << "icol range [" << icol_min << "," << icol_max << "]" << endl; // rows v_irow.clear(); int i; int irow_min = max (1, irow + dirow_min); int irow_max = min (sz_grid[0], irow + dirow_max); for (i = irow_min ; i <= irow_max ; ++i) v_irow.push_back(i); // search the row that has the biggest number of columns (ie the nearest one from equator, at indice sz_grid[0]/2 + 0.5) float irow_equator = sz_grid[0]/2 + 0.5; float dirow_near = 999999.; float dirow_equator; int irow_near = -9999; for (i = irow_min ; i <= irow_max ; ++i) { dirow_equator = fabs (i - irow_equator); if (dirow_equator < dirow_near) { dirow_near = dirow_equator; irow_near = i; } } if (irow_near == -9999) { g_exception e(__FILE__,__LINE__, "Invalid row indice range [" + MyTools::to_string(irow_min) + ", " + MyTools::to_string(irow_max) + "]"); throw e; } // columns v_icol.clear(); get_v_icol_neighbours (irow_near, icol, dicol_min, dicol_max, v_icol); // cout << "v_irow " << MyTools::vec2str(v_irow) << endl; // cout << "v_icol " << MyTools::vec2str(v_icol) << endl; } void PARASOLFileData::check_grid_coord(const int irow, const int icol) const { // int icol_max = get_ncol(irow); // cout << irow << " " << icol << " " << icol_max << endl; g_exception e; if (irow < 1 || irow > sz_grid[0]) { e.set (__FILE__, __LINE__, "Invalid row indice " + MyTools::to_string (irow) + ". Must be in [1, " + MyTools::to_string (sz_grid[0]) + "]"); throw e; } if (icol < 1 || icol > sz_grid[1]) { e.set (__FILE__, __LINE__, "Invalid column indice " + MyTools::to_string (icol) + ". Must be in [1, " + MyTools::to_string (sz_grid[1]) + "]"); throw e; } } void PARASOLFileData::free_viewing_directions_data() { delete [] v_alt_view, v_alt_view = NULL; delete [] v_saa, v_saa = NULL; delete [] v_vza, v_vza = NULL; delete [] v_raa, v_raa = NULL; delete [] v_ni, v_ni = NULL; delete [] v_sn, v_sn = NULL; delete [] v_x_sat, v_x_sat = NULL; delete [] v_y_sat, v_y_sat = NULL; delete [] v_z_sat, v_z_sat = NULL; } void PARASOLFileData::load_viewing_directions_data() { g_exception e; if (is_viewing_directions_data_loaded()) { e.set (__FILE__, __LINE__, "Viewing directions data have already been loaded"); throw e; } // requested parametres depend of the level int sz; switch (level) { case 1: // position of satellite set in the technological parameters sz = NB_MAX_PARASOL_SEQUENCE * NB_MAX_PARASOL_IMAGE_PER_SEQUENCE; v_x_sat = new double [sz]; v_y_sat = new double [sz]; v_z_sat = new double [sz]; leader->read_record(TECHNOLOGICAL_PARAMETERS); leader->techno_param->get_xyz_sat(v_x_sat, v_y_sat, v_z_sat); leader->free_record(TECHNOLOGICAL_PARAMETERS); v_alt_view = (short *)(read_count_data(NULL, "alt")); v_ni = (unsigned char *)(read_count_data(NULL, "ni")); v_sn = (unsigned char *)(read_count_data(NULL, "seq_nb")); break; case 2: v_alt_view = (short *)(read_count_data(NULL, "alt")); v_saa = (double *)(read_data(NULL, "phis")); v_vza = (double *)(read_data(NULL, "thetav")); v_raa = (double *)(read_data(NULL, "phi")); v_ni = (unsigned char *)(read_count_data(NULL, "ni")); break; case 3: e.set( __FILE__ , __LINE__ , "Method not implemented for L3 products" ); throw e; break; default: e.set( __FILE__ , __LINE__ , "Invalid level " + MyTools::to_string(level) ); throw e; break; }; } bool PARASOLFileData::is_viewing_directions_data_loaded() { return (v_alt_view != NULL); } void PARASOLFileData::get_viewing_directions(const vector< int > & ipix, vector< Observation > & v_obs) { g_exception e; if (! is_viewing_directions_data_loaded()) { e.set (__FILE__, __LINE__, "Viewing directions data must have been previously loaded. Consider calling load_viewing_directions_data() before"); throw e; } v_obs.clear(); v_obs.reserve (nb_parasol_direction); // retrieve record indice int irec; bool is_valid_pix = get_index(ipix, irec); if (is_valid_pix) { // cout << "ipix " << MyTools::vec2str(ipix) << " -> irec " << irec << endl; // available parametres depend of the level switch (level) { case 1: _get_viewing_directions_l1(ipix, irec, v_obs); break; case 2: _get_viewing_directions_l2(ipix, irec, v_obs); break; case 3: e.set( __FILE__ , __LINE__ , "Method not implemented for L3 products" ); throw e; break; default: e.set( __FILE__ , __LINE__ , "Invalid level " + MyTools::to_string(level) ); throw e; break; }; } } void PARASOLFileData::_get_viewing_directions_l1(const vector< int > & ipix, const int irec, vector< Observation > & v_obs) { // --- for each pixel identified by its indices [irow, icolumn, idirection], read int idir = 0, ndir = nb_parasol_direction; // latitude, longitude and altitude at center of viewed pixel float lat_view, lon_view, alt_view; // carthesian coordinates in ECR system of satellite position. double x_sat, y_sat, z_sat; // as double // sequence number unsigned short sn; // points representing the location of the viewed pixel and the satellite Geodetic::Point3D point; // Geocentric::Point3D point; Carthesian::Point3D point_sat, point_view; vector <int> igrid(3); // grid indice : [irow, icol, idir] vector <int> idata(1); // data buffer indice [irec] idata [0] = irec; // buffer linear indice int ibuf; int i_img = 4; // indice of the middle of sequence image // set pixel indices [irow, icolumn, idirection] igrid [0] = line_data [irec]; igrid [1] = col_data [irec]; // set the latitude, longitude and altitude of the viewed pixel (center) get_record_coord(irec, lat_view, lon_view); alt_view = v_alt_view [irec]; point.set (lat_view, lon_view, alt_view); point_view = point.to_carthesian(); // point_view = point.to_carthesian(); // cout << point << endl; // cout << point.to_carthesian(Earth::WGS84_MODEL) << endl; // cout << point.to_carthesian() << endl; // cout << point.to_carthesian(Earth::WGS84_MODEL).to_geocentric() << endl; // cout << point.to_carthesian().to_geocentric() << endl; // cout << point_view << endl; // cout << point_view.to_geocentric() << endl; // read satellite position in each direction ndir = (int)(v_ni[irec]); Observation obs; Carthesian::Segment3D viewing; // set directions to read range int idir_start = 0, idir_end = ndir; if (ipix.size() > 2) { idir_start = ipix[2], idir_end = idir_start + 1; if (idir_start >= ndir) // direction does not exists : skip next loop idir_start = idir_end; } // for (sn = 0 ; sn < 130 ; ++sn) { // for (i_img = 0 ; i_img < 9 ; ++i_img) { // x_sat = MyTools::to_num<double>((leader->techno_param->x_sat) [sn][i_img]) * 1e3; // km -> m // y_sat = MyTools::to_num<double>((leader->techno_param->y_sat) [sn][i_img]) * 1e3; // km -> m // z_sat = MyTools::to_num<double>((leader->techno_param->z_sat) [sn][i_img]) * 1e3; // km -> m // printf ("* seq = %d im = %d sat_pos = [%f, %f, %f]\n", sn + 1, i_img + 1, x_sat, y_sat, z_sat); // } // } for (idir = idir_start ; idir < idir_end ; ++idir) { ibuf = irec * nb_parasol_direction + idir; // --- read x, y, z coords of satellite. Central image is considered for all filters (image number = 4) sn = (unsigned short)(v_sn [ibuf]) - 1; // - 1 because starts at 1 in file, and here is used as indice from 0 // x_sat = MyTools::to_num<double>((leader->techno_param->x_sat) [sn][i_img]) * 1e3; // km -> m // y_sat = MyTools::to_num<double>((leader->techno_param->y_sat) [sn][i_img]) * 1e3; // km -> m // z_sat = MyTools::to_num<double>((leader->techno_param->z_sat) [sn][i_img]) * 1e3; // km -> m ibuf = sn * NB_MAX_PARASOL_IMAGE_PER_SEQUENCE + i_img; x_sat = v_x_sat [ibuf]; y_sat = v_y_sat [ibuf]; z_sat = v_z_sat [ibuf]; point_sat.set (x_sat, y_sat, z_sat); // --- construct viewing segment and store it viewing.set (point_sat, point_view); igrid[2] = idir; obs.set (lat_view, lon_view, alt_view, -1, idata, igrid, viewing); v_obs.push_back (obs); // printf ("--- irec = %d ; pixel [%d, %d, %d] ---\n", irec, igrid [0], igrid [1], idir); // printf (" * ni = %d sn = %d alt_view = %f\n", ndir, sn + 1, alt_view); // point = point_view.to_geodetic(); // printf (" * view : (%f, %f, %f) ; (%f, %f, %f)\n", point.lat, point.lon, point.alt, point_view.x, point_view.y, point_view.z); // point = point_sat.to_geodetic(); // printf (" * sat : (%f, %f, %f) ; (%f, %f, %f)\n", point.lat, point.lon, point.alt, point_sat.x, point_sat.y, point_sat.z); // printf (" * segment : distance %f\n", viewing.length()); } } // void PARASOLFileData::load_viewing_directions() { // g_exception e; // if (! is_viewing_directions_data_loaded()) { // e.set (__FILE__, __LINE__, "Viewing directions data must have been previously loaded. Considr calling load_viewing_directions_data() before"); // throw e; // } // // assert(is_geolocation_data_loaded()); // // init container if needed // viewing_directions.clear(); // // // available parametres depend of the level // switch (level) { // case 1: // _load_viewing_directions_l1(); // break; // case 2: // _load_viewing_directions_l2(); // break; // case 3: // e.set( __FILE__ , __LINE__ , "Method not implemented for L3 products" ); // throw e; // break; // default: // e.set( __FILE__ , __LINE__ , "Invalid level " + MyTools::to_string(level) ); // throw e; // break; // }; // } // // void PARASOLFileData::_load_viewing_directions_l1() { // // --- for each pixel identified by its indices [irow, icolumn, idirection], read // int irec = 0, nrec = get_nb_data(); // int irow, icol; // int idir = 0, ndir = nb_parasol_direction; // // latitude, longitude and altitude at center of viewed pixel // float lat_view, lon_view, alt_view; // // carthesian coordinates in ECR system of satellite position. // double x_sat, y_sat, z_sat; // as double // // sequence number // short sn; // // // points representing the location of the viewed pixel and the satellite // Geodetic::Point3D point; // Carthesian::Point3D point_sat, point_view; // vector <int> ipix(3); // // buffer linear indice // int ibuf; // int i_img = 4; // indice of the middle of sequence image // for (irec = 0 ; irec < nrec ; ++irec) { // // set pixel indices [irow, icolumn, idirection] // irow = line_data [irec]; // icol = col_data [irec]; // // set the latitude, longitude and altitude of the viewed pixel (center) // get_record_coord(irec, lat_view, lon_view); // alt_view = v_alt_view [irec]; // // point.set (lat_view, lon_view, alt_view); // point_view = point.to_carthesian(); // // // read satellite position in each direction // ndir = (int)(v_ni[irec]); // for (idir = 0 ; idir < ndir ; ++idir) { // ibuf = irec * nb_parasol_direction + idir; // // --- read x, y, z coords of satellite. Central image is considered for all filters (image number = 4) // sn = (short)(v_sn [ibuf]) - 1; // - 1 because starts at 1 in file, and here is used as indice from 0 // x_sat = MyTools::to_num<double>((leader->techno_param->x_sat) [sn][i_img]) * 1e3; // km -> m // y_sat = MyTools::to_num<double>((leader->techno_param->y_sat) [sn][i_img]) * 1e3; // km -> m // z_sat = MyTools::to_num<double>((leader->techno_param->z_sat) [sn][i_img]) * 1e3; // km -> m // point_sat.set (x_sat, y_sat, z_sat); // // // --- construct viewing segment and store it // ipix[0] = irow, ipix[1] = icol, ipix[2] = idir; // viewing_directions[ipix] = Carthesian::Segment3D (point_sat, point_view); // // // if (irec == 97552) { // // printf ("--- irec = %d ; pixel [%d, %d, %d] ---\n", irec, irow, icol, idir); // // printf (" * ni = %d sn = %d\n", ndir, sn + 1); // // point = point_view.to_geocentric(); // // printf (" * view : (%f, %f, %f) ; (%f, %f, %f)\n", point.lat, point.lon, point.alt, point_view.x, point_view.y, point_view.z); // // point = point_sat.to_geocentric(); // // printf (" * sat : (%f, %f, %f) ; (%f, %f, %f)\n", point.lat, point.lon, point.alt, point_sat.x, point_sat.y, point_sat.z); // // printf (" * segment : distance %f\n", viewing_directions[ipix].length()); // // } // // } // } // // delete[] v_alt_view; // // delete[] v_ni; // // delete[] v_sn; // } void PARASOLFileData::_get_viewing_directions_l2(const vector< int > & ipix, const int irec, vector< Observation > & v_obs) { // --- for each pixel identified by its indices [irow, icolumn, idirection], read int idir = 0, ndir = nb_parasol_direction; // latitude, longitude and altitude at center of viewed pixel float lat_view, lon_view, alt_view; // fixed satellite altitude float alt_sat = satellite_altitude; // relative azimuth, viewing azimuth, viewing zenith and solar azimuth angles double raa, vaa, vza, saa; // points representing the location of the viewed pixel and the satellite Geodetic::Point3D point_view; Carthesian::Point3D point_sat, point_view_xyz; vector <int> igrid(3); // grid indice : [irow, icol, idir] vector <int> idata(1); // data buffer indice [irec] idata [0] = irec; // buffer linear indice int ibuf; // set pixel indices [irow, icolumn, idirection] igrid [0] = line_data [irec]; igrid [1] = col_data [irec]; // set the latitude, longitude and altitude of the viewed pixel (center) get_record_coord(irec, lat_view, lon_view); alt_view = v_alt_view [irec]; point_view.set (lat_view, lon_view, alt_view); point_view_xyz = point_view.to_carthesian(); // constructs viewin points saa = v_saa [irec]; // compute directionnal paramtres ndir = (int)(v_ni[irec]); Observation obs; Carthesian::Segment3D viewing; for (idir = 0 ; idir < ndir ; ++idir) { ibuf = irec * nb_parasol_direction + idir; // --- compute lat, lon, alt of the satellite from viewing directions raa = v_raa [ibuf]; vaa = (saa - raa); vza = v_vza [ibuf]; // --- constructs satellite position from viewing angles Viewing::earth_to_sat_from_alt(point_view, vza, vaa, alt_sat, point_sat); // --- construct viewing segment and store it viewing.set (point_sat, point_view_xyz); igrid[2] = idir; obs.set (lat_view, lon_view, alt_view, -1, idata, igrid, viewing); v_obs.push_back (obs); // Geocentric::Point3D point_geo = point_sat.to_geocentric(); // printf ("--- irec = %d ; pixel [%d, %d, %d] ---\n", irec, irow, icol, idir); // printf (" * ni = %d ; vra = %f ; saa = %f ; vaa = %f ; vza = %f\n", ndir, v_raa [ibuf], v_saa [irec], v_saa [irec] - v_raa [ibuf], v_vza [ibuf]); // // printf (" dlat = %f ; dlon = %f ; alpha = %f\n", dlat, dlon, degrees (alpha)); // printf (" * view : (%f, %f, %f) ; (%f, %f, %f)\n", lat_view, lon_view, alt_view, point_view_xyz.x, point_view_xyz.y, point_view_xyz.z); // printf (" * sat : (%f, %f, %f) ; (%f, %f, %f)\n", point_geo.lat, point_geo.lon, point_geo.alt, point_sat.x, point_sat.y, point_sat.z); // printf (" * segment : distance %f\n", viewing_directions[ipix].length()); } } // void PARASOLFileData::_load_viewing_directions_l2() { // // --- preload needed variables // // // viewed pixel altitude // // short * v_alt_view = (short *)(read_count_data(NULL, "alt")); // // // solar azimuth angles. 1 per record // // double * v_saa = (double *)(read_data(NULL, "phis")); // // // viewing zenith angles. N_directions per record // // double * v_vza = (double *)(read_data(NULL, "thetav")); // // // relative azimuth angles. N_directions per record // // double * v_raa = (double *)(read_data(NULL, "phi")); // // // number of available directions // // char * v_ni = (char *)(read_count_data(NULL, "ni")); // // // --- for each pixel identified by its indices [irow, icolumn, idirection], read // int irec = 0, nrec = get_nb_data(); // int irow, icol; // int idir = 0, ndir = nb_parasol_direction; // // latitude, longitude and altitude at center of viewed pixel // float lat_view, lon_view, alt_view; // // fixed satellite altitude // float alt_sat = satellite_altitude; // // relative azimuth, viewing azimuth, viewing zenith and solar azimuth angles // double raa, vaa, vza, saa; // // points representing the location of the viewed pixel and the satellite // Geocentric::Point3D point_view; // Carthesian::Point3D point_sat; // vector <int> ipix(3); // // buffer linear indice // int ibuf; // for (irec = 0 ; irec < nrec ; ++irec) { // // set pixel indices [irow, icolumn, idirection] // irow = line_data [irec]; // icol = col_data [irec]; // // set the latitude, longitude and altitude of the viewed pixel (center) // get_record_coord(irec, lat_view, lon_view); // alt_view = v_alt_view [irec]; // point_view.set (lat_view, lon_view, alt_view); // // constructs viewin points // saa = v_saa [irec]; // // compute directionnal paramtres // ndir = (int)(v_ni[irec]); // for (idir = 0 ; idir < ndir ; ++idir) { // ibuf = irec * nb_parasol_direction + idir; // // --- compute lat, lon, alt of the satellite from viewing directions // raa = v_raa [ibuf]; // vaa = (saa - raa); // vza = v_vza [ibuf]; // // --- constructs satellite position from viewing angles // Viewing::earth_to_sat_from_alt(point_view, vza, vaa, alt_sat, point_sat); // // --- construct viewing segment and store it // ipix[0] = irow, ipix[1] = icol, ipix[2] = idir; // viewing_directions[ipix] = Carthesian::Segment3D (point_sat, point_view.to_carthesian()); // // if (irec == 499) { // Geocentric::Point3D point_geo = point_sat.to_geocentric(); // Carthesian::Point3D point_car = point_view.to_carthesian(); // printf ("--- irec = %d ; pixel [%d, %d, %d] ---\n", irec, irow, icol, idir); // printf (" * ni = %d ; vra = %f ; saa = %f ; vaa = %f ; vza = %f\n", ndir, v_raa [ibuf], v_saa [irec], v_saa [irec] - v_raa [ibuf], v_vza [ibuf]); // // printf (" dlat = %f ; dlon = %f ; alpha = %f\n", dlat, dlon, degrees (alpha)); // printf (" * view : (%f, %f, %f) ; (%f, %f, %f)\n", lat_view, lon_view, alt_view, point_car.x, point_car.y, point_car.z); // printf (" * sat : (%f, %f, %f) ; (%f, %f, %f)\n", point_geo.lat, point_geo.lon, point_geo.alt, point_sat.x, point_sat.y, point_sat.z); // printf (" * segment : distance %f\n", viewing_directions[ipix].length()); // } // // } // } // // delete[] v_alt_view; // // delete[] v_saa; // // delete[] v_vza; // // delete[] v_raa; // } unsigned char* PARASOLFileData::get_ndir_data() const { return v_ni; }