]> Devoid-pointer.net GitWeb - libHPCS.git/commitdiff
Read signal step from the datafile header instead of guessing it by
authorMichal Malý <madcatxster@devoid-pointer.net>
Thu, 18 Aug 2016 15:04:40 +0000 (17:04 +0200)
committerMichal Malý <madcatxster@devoid-pointer.net>
Thu, 18 Aug 2016 15:04:40 +0000 (17:04 +0200)
ChemStation versions and signal types

libhpcs.c
libhpcs_p.h

index c40b70e08988541a23d5c586e5ccb96960bcc7a2..827ac5d480c57c20d8bea4f12e8c8757136a88ee 100644 (file)
--- 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;
index e78ba1269508d9710dcb2b31fb6929dd6fc33576..00981ec8b7e264505eaea5e475c10d52422ad8e1 100644 (file)
@@ -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