/*************************************************************************** * 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. * ***************************************************************************/ #ifndef PARASOLDATAFILE_H #define PARASOLDATAFILE_H #include "parasolfilereader.h" /** * Interface for managing the reading of a PARASOL data file. * @warning this class is designed to be general and treat all PARASOL data files BUT it only has been fully implemented and tested for * -> RB 2 products * @author Nicolas PASCAL */ class PARASOLData : public PARASOLFileReader { friend class PARASOLFileData; PARASOLDataFormat *data_file_format; public: DataFileDescriptorRecord *data_file_descriptor; protected: string filename; // record storage classes DataRecord *data; virtual void read_data_file(const string &data_filename); /** * @brief check if a record has been read. * @return true if the record has already been read */ const bool is_record_loaded(const Record &rec); /** * @brief Free the objects used to store the values read in the file records */ void free_records(); /** * @brief Initialize a record class * @param rec the record code * @return the initialized object (or NULL in case of problem) */ PARASOLFileRecord* init_record(const Record &rec); /** * @brief access to ones record file offset * If the record isn't in the data data file, it returns -1 * @param rec the record code * @return the record's offset in the data file */ const int get_record_offset(const Record &rec); /** * @brief access to the RecordFormat object that describes the name, type, offset and length of each record entry * @param rec the record code * @return the RecordFormat corresponding to @a record code */ virtual const RecordFormat* get_record_format(const Record &rec); /** * @brief access to one record entry * @param rec the record code * @return the entry corresponding to @a record code */ PARASOLFileRecord* get_record(const Record &rec); /** * @brief This method implements the interface of PARASOLFileReader, which is an abstraction for describing a group of repeated entries either in a data record or in a leader one. * In th particular case of data record (so on, here), @a nb_val as the particular meaning of "number of viewing directions" * @param record_code the code of the record * @param entry_group_start the first entry of the group * @param entry_group_end (output) the last entry of the group. For entries of one value, the next entrie * @param nb_val (output) the number of viewing directions. For entries of one value, 1 */ // // void get_entry_group_range( const Record & record_code, // // const RecordFormat::iterator &entry_group_start, // // RecordFormat::iterator &entry_group_end, // // int &nb_val); /** * @brief returns the size (in bytes) an a group that contains the given entry. If the entry is not repeated in a record, returns 0 * @throw bad_parametre_idx if the entry idx is invalid for the current product * @param entry_idx index of the entry (product specific) * @return the size of the container group, in bytes. O if the entry is not in a group */ // const int get_entry_group_size(const int entry_idx); /** * @brief returns the size (in bytes) an a group that contains the given entry. If the entry is not repeated in a record, returns 0 * @throw bad_parametre_idx if the entry idx is invalid for the current product * @param entry_idx index of the entry (product specific) * @return the size of the container group, in bytes. O if the entry is not in a group */ // const int get_entry_group_size(const Record rec, const int entry_idx); /** * @brief returns the number of times an entry group is repeated in the data record. If the entry is not repeated in a record, returns 1 * @throw bad_parametre_idx if the entry idx is invalid for the current product * @param entry_idx index of the entry (product specific) * @return the number of times the group is repeated */ // const int get_entry_group_nb_val(const Record rec, const int entry_idx) const; /** * @brief return the block describing the given entry : the number of times the entry is repeated and the size in bytes of the group * @param rec current record * @param entry_idx indice of the entry * @return the block(s) of the entry. If the entry is composed of a unique value, returns an empty vector */ vector get_entry_block (const Record rec, const int entry_idx) const; /** * @brief access to the offset of an entry, relative to the record start * @param rec the concerned record. Unused here. Set it to DATA * @param entry_idx index of the entry * @param record_idx index of the data record to read * @param direction_index index of the direction (useful only for directionnal parameters) * @param val_index unused * @return the offset, from the record start */ // const int get_entry_offset( const Record rec, const int entry_idx, const int record_idx=-1, const int direction_index=-1, const int val_index=-1); /** * @brief apply the scaling to a count data * @param scaled_data the output scaled data. Must be allocated * @param count_data the input count data. Musn't be NULL * @param slope the slope * @param offset the offset * @param nb_val the number of values */ template void apply_scaling(double* scaled_data, const T* count_data, const double & slope, const double & offset, const int & nb_val, const T count_fill_value=T(0)); public: PARASOLData( const string data_filename=""); virtual ~PARASOLData(); /** * Print the data file descriptor on the standard output */ void print_data_file_descriptor(); virtual void print_data(){;}; /** * @brief read the data in the parasol data file * @warning start, edges and rank must be given and valid * @param buf the buffer to be fill. MUST BE ALLOCATED * @param param_index the index of the parameter to extract * @param start the start data record index. DON'T USE IT * @param edges the number of data records to read. DON'T USE IT * @param dir_idx the index of the direction for directionnal parameters. DON'T USE IT * @return true if the data have been read without problem */ bool read_data(void* buf, const int ¶m_index, int * start, int * edges, const int rank ); /** * @brief access to the data file format for a given product * @return the data file format */ const PARASOLDataFormat * get_data_file_format() { return data_file_format; } /** * @brief access to the number of data' records contained in the file * @warning it starts at 0 for the 1st pixel data record. So it differs of 2 compared to the record number read in the data file : nb_data_record = record_number_in_file - 2 * @return the number of data records */ const int get_nb_data_record() const; /** * @brief access to the size of one data record * @return the size of one data record in bytes */ const int get_sz_data_record() const; /** * @brief retrieve the index of a parameter's in the data record * If the entry isn't a parameter,throws an bad_parametre Exception * @param var_name the name of the variable * @return the entry index */ const int get_data_entry_index(const string &var_name) const; /** * @brief retrieve the number of values that will be read for the given variable using the given indexes * @param var_name the name of the variable * @param edges the number of records to read. -1 = all * @param dir_idx the index of the direction to read (for directionnal parameters). -1 = all * @return the number of possible values */ const int get_nb_val(const string &var_name, const int edges=-1, const int dir_idx=-1) const; /** * @brief retrieve the number of values that will be read for the given variable using the given indexes * @param var_index the index of the variable * @param edges the number of records to read. -1 = all * @param dir_idx the index of the direction to read (for directionnal parameters). -1 = all * @return the number of possible values */ const int get_nb_val(const int &var_index,const int edges=-1, const int dir_idx=-1) const; }; template void PARASOLData::apply_scaling( double* scaled_data, const T* count_data, const double & slope, const double & offset, const int & nb_val, const T count_fill_value ) { // the fill value to use in the scaled data double decoded_fill_value=-DBL_MAX; // the fill values used in the count data int level=PARASOLFileFormat::get_level(this->product); T missing_value=PARASOLFileFormat::get_missing_value(level); T out_of_range_value=PARASOLFileFormat::get_out_of_range_value(level); // apply the scaling T count_val; for (int i = 0 ; i apply the scaling scaled_data[i]=offset+slope*count_val; } } #endif