From: Michal MalĂ˝ Date: Thu, 18 Aug 2016 15:04:40 +0000 (+0200) Subject: Read signal step from the datafile header instead of guessing it by X-Git-Url: https://gitweb.devoid-pointer.net/?a=commitdiff_plain;h=38850071bb72b1866892b6c92645d6349f2b792c;p=libHPCS.git Read signal step from the datafile header instead of guessing it by ChemStation versions and signal types --- diff --git a/libhpcs.c b/libhpcs.c index c40b70e..827ac5d 100644 --- a/libhpcs.c +++ b/libhpcs.c @@ -113,6 +113,8 @@ enum HPCS_RetCode hpcs_read_mdata(const char* filename, struct HPCS_MeasuredData enum HPCS_RetCode ret; enum HPCS_GenType gentype; enum HPCS_ChemStationVer cs_ver; + double signal_step; + double signal_shift; if (mdata == NULL) return HPCS_E_NULLPTR; @@ -167,34 +169,14 @@ enum HPCS_RetCode hpcs_read_mdata(const char* filename, struct HPCS_MeasuredData } } - switch (mdata->file_type) { - case HPCS_TYPE_CE_ANALOG: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_WORK_PARAM_OLD_STEP, mdata->sampling_rate, gentype); - break; - case HPCS_TYPE_CE_CCD: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_CCD_STEP, mdata->sampling_rate, gentype); - break; - case HPCS_TYPE_CE_CURRENT: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, guess_current_step(cs_ver, gentype), mdata->sampling_rate, gentype); - break; - case HPCS_TYPE_CE_DAD: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_DAD_STEP, mdata->sampling_rate, gentype); - break; - case HPCS_TYPE_CE_POWER: - case HPCS_TYPE_CE_VOLTAGE: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, guess_elec_sigstep(cs_ver, mdata->file_type), mdata->sampling_rate, gentype); - break; - case HPCS_TYPE_CE_PRESSURE: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_WORK_PARAM_STEP, mdata->sampling_rate, gentype); - break; - case HPCS_TYPE_CE_TEMPERATURE: - pret = read_signal(datafile, &mdata->data, &mdata->data_count, CE_WORK_PARAM_OLD_STEP * 10.0, mdata->sampling_rate, gentype); - break; - case HPCS_TYPE_UNKNOWN: - ret = HPCS_E_UNKNOWN_TYPE; - goto out; + pret = fetch_signal_step(datafile, &signal_step, &signal_shift, OLD_FORMAT(gentype)); + if (pret != PARSE_OK) { + PR_DEBUG("Cannot read signal step and shift\n"); + ret = HPCS_E_PARSE_ERROR; + goto out; } + pret = read_signal(datafile, &mdata->data, &mdata->data_count, signal_step, signal_shift, mdata->sampling_rate, gentype); if (pret != PARSE_OK) { PR_DEBUG("Cannot parse data in the file\n"); ret = HPCS_E_PARSE_ERROR; @@ -362,6 +344,70 @@ static enum HPCS_ChemStationVer detect_chemstation_version(const char*const vers return CHEMSTAT_UNKNOWN; } +static enum HPCS_ParseCode fetch_signal_step(FILE *datafile, double *step, double *shift, bool old_format) +{ + int32_t version; + double _step; + double _shift; + HPCS_offset veroff; + HPCS_offset shiftoff; + HPCS_offset stepoff; + + if (old_format) { + veroff = DATA_OFFSET_SIGSTEP_VERSION_OLD; + shiftoff = DATA_OFFSET_SIGSTEP_SHIFT_OLD; + stepoff = DATA_OFFSET_SIGSTEP_STEP_OLD; + } else { + veroff = DATA_OFFSET_SIGSTEP_VERSION; + shiftoff = DATA_OFFSET_SIGSTEP_SHIFT; + stepoff = DATA_OFFSET_SIGSTEP_STEP; + } + + fseek(datafile, veroff, SEEK_SET); + if (feof(datafile)) + return PARSE_E_OUT_OF_RANGE; + if (ferror(datafile)) + return PARSE_E_CANT_READ; + if (fread(&version, LARGE_SEGMENT_SIZE, 1, datafile) < 1) + return PARSE_E_CANT_READ; + + be_to_cpu_val(version); + switch (version) { + case 1: + *step = SIGSTEP_V1; + *shift = 0.0; + return PARSE_OK; + case 2: + *step = SIGSTEP_V2; + *shift = 0.0; + return PARSE_OK; + default: + break; + } + + fseek(datafile, shiftoff, SEEK_SET); + if (feof(datafile)) + return PARSE_E_OUT_OF_RANGE; + if (ferror(datafile)) + return PARSE_E_CANT_READ; + if (fread(&_shift, DOUBLE_SEGMENT_SIZE, 1, datafile) < 1) + return PARSE_E_CANT_READ; + + fseek(datafile, stepoff, SEEK_SET); + if (feof(datafile)) + return PARSE_E_OUT_OF_RANGE; + if (ferror(datafile)) + return PARSE_E_CANT_READ; + if (fread(&_step, DOUBLE_SEGMENT_SIZE, 1, datafile) < 1) + return PARSE_E_CANT_READ; + + be_to_cpu_val(_shift); + be_to_cpu_val(_step); + *shift = _shift; + *step = _step; + + return PARSE_OK; +} static bool file_type_description_is_readable(const char*const description) { @@ -382,28 +428,6 @@ static bool gentype_is_readable(const enum HPCS_GenType gentype) } } -static HPCS_step guess_current_step(const enum HPCS_ChemStationVer version, const enum HPCS_GenType gentype) -{ - if (version == CHEMSTAT_B0625 || OLD_FORMAT(gentype)) - return CE_WORK_PARAM_OLD_STEP * 10.0; - - return CE_CURRENT_STEP; -} - -static HPCS_step guess_elec_sigstep(const enum HPCS_ChemStationVer version, const enum HPCS_FileType file_type) -{ - if (version != CHEMSTAT_B0625) { - switch (file_type) { - case HPCS_TYPE_CE_POWER: - return CE_ENERGY_STEP; - default: - return CE_WORK_PARAM_OLD_STEP; - } - } - - return CE_WORK_PARAM_STEP; -} - static void guess_sampling_rate(const enum HPCS_ChemStationVer version, struct HPCS_MeasuredData *mdata) { switch (version) { @@ -916,7 +940,7 @@ out: } static enum HPCS_ParseCode read_signal(FILE* datafile, struct HPCS_TVPair** pairs, size_t* pairs_count, - const HPCS_step step, const double sampling_rate, const enum HPCS_GenType gentype) + const double signal_step, const double signal_shift, const double sampling_rate, const enum HPCS_GenType gentype) { const double time_step = 1 / (60 * sampling_rate); size_t alloc_size = (size_t)((60 * sampling_rate) + 0.5); @@ -1012,13 +1036,13 @@ static enum HPCS_ParseCode read_signal(FILE* datafile, struct HPCS_TVPair** pair be_to_cpu(lraw); _v = *(int32_t*)lraw; - value = _v * step; + value = _v * signal_step + signal_shift; } else { int16_t _v; be_to_cpu(raw); _v = *(int16_t*)raw; - value += _v * step; + value += _v * signal_step + signal_shift; } (*pairs)[data_segments_read].time = time; diff --git a/libhpcs_p.h b/libhpcs_p.h index e78ba12..00981ec 100644 --- a/libhpcs_p.h +++ b/libhpcs_p.h @@ -43,7 +43,6 @@ enum HPCS_ParseCode { }; typedef size_t HPCS_offset; -typedef double HPCS_step; typedef size_t HPCS_segsize; const char FILE_TYPE_ID_ADC_A[] = "ADC CHANNEL A"; @@ -79,14 +78,6 @@ const char MON_OCT_STR[] = "Oct"; const char MON_NOV_STR[] = "Nov"; const char MON_DEC_STR[] = "Dec"; -/* Precision of measured values. */ -const HPCS_step CE_CURRENT_STEP = 0.01; -const HPCS_step CE_CCD_STEP = 0.0000596046450027643; -const HPCS_step CE_DAD_STEP = 0.000476837158203; -const HPCS_step CE_ENERGY_STEP = 0.00000459365687208207; -const HPCS_step CE_WORK_PARAM_STEP = 0.001; -const HPCS_step CE_WORK_PARAM_OLD_STEP = 0.000083333333; - /* Hardcoded sampling rates */ const double CE_WORK_PARAM_SAMPRATE = 1.67; @@ -100,6 +91,9 @@ const HPCS_offset DATA_OFFSET_METHOD_NAME = 0xA0E; const HPCS_offset DATA_OFFSET_CS_VER = 0xE11; const HPCS_offset DATA_OFFSET_CS_REV = 0xEDA; const HPCS_offset DATA_OFFSET_SAMPLING_RATE = 0x101C; +const HPCS_offset DATA_OFFSET_SIGSTEP_VERSION = 0x1026; +const HPCS_offset DATA_OFFSET_SIGSTEP_SHIFT = 0x1274; +const HPCS_offset DATA_OFFSET_SIGSTEP_STEP = 0x127C; const HPCS_offset DATA_OFFSET_Y_UNITS = 0x104C; const HPCS_offset DATA_OFFSET_DEVSIG_INFO = 0x1075; const HPCS_offset DATA_OFFSET_DATA_START = 0x1800; @@ -109,6 +103,9 @@ const HPCS_offset DATA_OFFSET_SAMPLE_INFO_OLD = 0x019; const HPCS_offset DATA_OFFSET_OPERATOR_NAME_OLD = 0x095; const HPCS_offset DATA_OFFSET_DATE_OLD = 0x0B3; const HPCS_offset DATA_OFFSET_METHOD_NAME_OLD = 0x0E5; +const HPCS_offset DATA_OFFSET_SIGSTEP_VERSION_OLD = 0x21E; +const HPCS_offset DATA_OFFSET_SIGSTEP_SHIFT_OLD = 0x27C; +const HPCS_offset DATA_OFFSET_SIGSTEP_STEP_OLD = 0x284; const HPCS_offset DATA_OFFSET_Y_UNITS_OLD = 0x245; const HPCS_offset DATA_OFFSET_DEVSIG_INFO_OLD = 0x255; const HPCS_offset DATA_OFFSET_DATA_START_OLD = 0x400; @@ -153,6 +150,10 @@ const char BIN_MARKER_JUMP = (const char)(0x80); const HPCS_segsize SMALL_SEGMENT_SIZE = 1; const HPCS_segsize SEGMENT_SIZE = 2; const HPCS_segsize LARGE_SEGMENT_SIZE = 4; +const HPCS_segsize DOUBLE_SEGMENT_SIZE = 8; + +const double SIGSTEP_V1 = 0.1; +const double SIGSTEP_V2 = 0.00240841663372301; const char HPCS_OK_STR[] = "OK."; const char HPCS_E_NULLPTR_STR[] = "Null pointer to measured data struct."; @@ -174,9 +175,8 @@ static enum HPCS_ParseCode autodetect_file_type(FILE* datafile, enum HPCS_FileTy static enum HPCS_DataCheckCode check_for_marker(const char* segment, size_t* const next_marker_idx); static enum HPCS_ChemStationVer detect_chemstation_version(const char*const version_string); static bool gentype_is_readable(const enum HPCS_GenType gentype); -static HPCS_step guess_current_step(const enum HPCS_ChemStationVer version, const enum HPCS_GenType gentype); -static HPCS_step guess_elec_sigstep(const enum HPCS_ChemStationVer version, const enum HPCS_FileType file_type); static void guess_sampling_rate(const enum HPCS_ChemStationVer version, struct HPCS_MeasuredData* mdata); +static enum HPCS_ParseCode fetch_signal_step(FILE * datafile, double *step, double *shift, bool old_format); static bool file_type_description_is_readable(const char*const description); static enum HPCS_ParseCode next_native_line(HPCS_UFH fh, HPCS_NChar* line, int32_t length); static HPCS_UFH open_data_file(const char* filename); @@ -191,7 +191,7 @@ static enum HPCS_ParseCode read_file_type_description(FILE* datafile, char** con static enum HPCS_ParseCode read_generic_type(FILE* datafile, enum HPCS_GenType* gentype); static enum HPCS_ParseCode read_method_info_file(HPCS_UFH fh, struct HPCS_MethodInfo* minfo); static enum HPCS_ParseCode read_signal(FILE* datafile, struct HPCS_TVPair** pairs, size_t* pairs_count, - const HPCS_step step, const double sampling_rate, const enum HPCS_GenType gentype); + const double sigal_step, const double signal_shift, const double sampling_rate, const enum HPCS_GenType gentype); static enum HPCS_ParseCode read_sampling_rate(FILE* datafile, double* sampling_rate, const bool old_format); static enum HPCS_ParseCode read_string_at_offset(FILE* datafile, const HPCS_offset, char** const result, const bool read_as_wchar); static void remove_trailing_newline(HPCS_NChar* s); @@ -242,6 +242,7 @@ static enum HPCS_ParseCode __unix_data_to_utf8(char** target, const char* bytes, #ifdef _HPCS_LITTLE_ENDIAN #define be_to_cpu(bytes) reverse_endianness((char*)bytes, sizeof(bytes)); +#define be_to_cpu_val(v) do { char *b = (char *)&v; const size_t sz = sizeof(v); reverse_endianness(b, sz); } while (0) void reverse_endianness(char* bytes, size_t sz) { size_t i; @@ -255,6 +256,7 @@ void reverse_endianness(char* bytes, size_t sz) { #elif defined _HPCS_BIG_ENDIAN #define be_to_cpu(bytes) +#define be_to_cpu_val(v) #else #error "Endiannes has not been determined." #endif