// // Convert MHM-2010 Maser CML output to Excel CSV. // #include #include #include #include #define DATA_MAX 32 float Data[DATA_MAX]; int DataIndex; FILE *ErrorFile; void Match(char *Line); int IsWhite (char c) { return (c == '\r') || (c == '\n') || (c == ' ') || (c == '\t'); } void Trim (char *s) { while (*s && IsWhite(s[strlen(s) - 1])) { s[strlen(s) - 1] = '\0'; } } #define N_IF 0 #define N_REG 1 #define N_VCO 2 #define N_VIh 3 #define N_VIo 4 #define N_LO 5 #define N_CAV 6 #define N_O 7 #define N_LS 8 #define N_TP 9 #define N_MP1 20 #define N_MP2 21 #define N_AC1 22 #define N_AC2 23 #define N_DCX 24 #define N_AUX 25 char *Names1[] = { "IF", "REG", "VCO", "VIh", "VIo", "LO", "CAV", "OO", "LS", "TP", "ISe", "IBat", "AVE", "VCOh", "MF", "VPC", "STC", "Pd", "VSc", "VBat", "MP1", "MP2", "AC1", "AC2", "DCX", "AUX", NULL }; #define TWENTY_SIX 26 char *Names2[] = { "IF ALARM", "VCO ALARM", "REG. LIMIT", "DC POWER", "AC POWER", "BATTERY IN USE", NULL }; int Matches; void Match(char *Line) { int Index; int n; char *p; char name[10]; for (Index = 0; Names1[Index] != NULL; Index += 1) { strcpy(name, Names1[Index]); strcat(name, ":"); p = strstr(Line, name); if (p) { p = strstr(p, ":"); if (p == NULL) { fprintf(stderr, "Format error: %s without ':' - %s\n"); return; } DataIndex = Index; n = sscanf(p + 1, "%f", &Data[DataIndex]); if (n != 1) { fprintf(stderr, "Format error: %s without value - %s\n", Line); return; } Matches += 1; } } for (Index = 0; Names2[Index] != NULL; Index += 1) { p = strstr(Line, Names2[Index]); if (p) { p = strstr(p, "["); if (p == NULL) { fprintf(stderr, "Format error: %s without '[' - %s\n"); return; } DataIndex = Index + TWENTY_SIX; n = sscanf(p + 1, "%f", &Data[DataIndex]); if (n != 1) { fprintf(stderr, "Format error: %s without value - %s\n", Line); return; } Matches += 1; DataIndex += 1; } } return; } // // I've seen occasional bad data from the MHM-2010. // This is an attempt to filter obviously wrong samples. // int Invalid () { if (Data[N_REG] == Data[N_VCO]) return 1; if (Data[N_VCO] == Data[N_VIh]) return 2; if (Data[N_REG] == Data[N_VIh]) return 3; if (Data[N_VIh] > 0) return 4; if (Data[N_VIo] > 0) return 5; if (Data[N_AC2] == Data[N_DCX] && Data[N_AC2] == Data[N_AUX]) return 6; return 0; } // // Read data file. // void Parse (FILE *File) { int Error; int Head, Foot; char Line[1000]; long LineCount; double Mjd; FILE *Output; LineCount = 0; Head = Foot = 0; DataIndex = 0; Matches = 0; while (fgets(Line, sizeof Line, File) != NULL) { Trim(Line); LineCount += 1; if (strstr(Line, "MASER INSTRUMENTATION") != NULL) { Head = 1; sscanf(Line, "%lf", &Mjd); } if (strstr(Line, "DATA SCAN COMPLETE") != NULL) { Foot = 1; } Match(Line); if (Head && Foot) { // // Output one row of data. // if (Matches != DATA_MAX) { fprintf(stderr, "Line %ld: Bad Data (Matches %d) Skipping\n", LineCount, Matches); fprintf(ErrorFile, "Line %ld: Bad Data (Matches %d) Skipping\n", LineCount, Matches); } else { Error = Invalid(); if (Error) { fprintf(stderr, "Line %ld: Bad Data (error %d) Skipping\n", LineCount, Error); Output = ErrorFile; fprintf(Output, "Line %ld: Bad Data (error %d) Skipping\n", LineCount, Error); } else { Output = stdout; } fprintf(Output, "%.5lf,", Mjd); for (DataIndex = 0; DataIndex < DATA_MAX; DataIndex += 1) { fprintf(Output, "%.3f,", Data[DataIndex]); } fprintf(Output, "\n"); } Head = Foot = 0; DataIndex = 0; Matches = 0; } } } void main (int argc, char *argv[]) { FILE *File; int Index; char Path[1000]; // // Open error file. // #define ERROR_FILE "cml_err.txt" fprintf(stderr, "** Opening %s\n", ERROR_FILE); ErrorFile = fopen(ERROR_FILE, "w"); if (ErrorFile == NULL) { fprintf(stderr, "Cannot open error file: %s\n", ERROR_FILE); } // // First row is legend. // printf("#MJD,"); for (Index = 0; Names1[Index] != NULL; Index += 1) { printf("%s,", Names1[Index]); } for (Index = 0; Names2[Index] != NULL; Index += 1) { printf("%s,", Names2[Index]); } printf("\n"); // // Get files from command line or files from stdin. // if (argc > 1) { if (strcmp(argv[1], "-") == 0) { fprintf(stderr, "** Reading CML data from stdin.\n"); Parse(stdin); } else { File = fopen(argv[1], "r"); if (File == NULL) { fprintf(stderr, "Open error: %s\n", argv[1]); exit(1); } Parse(File); fclose(File); } } else { fprintf(stderr, "** Reading CML filenames from stdin.\n"); while (fgets(Path, sizeof Path, stdin) != NULL) { Trim(Path); File = fopen(Path, "r"); if (File == NULL) { fprintf(stderr, "Open error: %s\n", Path); exit(1); } Parse(File); fclose(File); } } return; }