-------------------------------------------------- glyph_factory.c -------------------------------------------------- /** ** glyph_factory - use a bunch of files to convert data ** ** CREATED: 2014.04.12 ABS copied from xyz2csv ** MODIFIED: 2014.04.13 ABS debugged ** MODIFIED: 2014.04.14 ABS debugged column counting ** MODIFIED: 2014.04.15 ABS debugged ** MODIFIED: 2014.04.19 ABS added infinite tags ** MODIFIED: 2014.04.23 ABS debugged for demo ** MODIFIED: 2014.05.07 ABS debugged for Malaysia demo ** MODIFIED: 2014.05.19 ABS Git test ** MODIFIED: 2014.05.29 ABS Scale2 default; added ProgName ** MODIFIED: 2014.05.31 ABS added links ** MODIFIED: 2014.06.01 ABS more error handling ** MODIFIED: 2014.06.02 ABS bug: not reading last data line ** MODIFIED: 2014.06.09 ABS made tags more general ** MODIFIED: 2014.06.25 ABS made sure tags don't go over 62 chars ** MODIFIED: 2014.07.07 ABS desperate to fix tags garbling bug ** MODIFIED: 2014.07.15 ABS ditto ** MODIFIED: 2014.07.16 ABS ditto; fixed ** MODIFIED: 2014.07.16 ABS rewrote row_to_id to use malloc ** MODIFIED: 2014.09.10 ABS check for zero node num in link ** MODIFIED: 2014.09.25 ABS searching for zero node num in link bug **/ #include "glyph_factory.h" main(argc, argv) int argc; char** argv; { /* declare functions */ void read_glyph(); int write_glyph(); char *extract_filename(); char *replace(); void mem_setup(); void mem_test(); double atof(); /* declare local variables */ int id, row, current_data_row, current_data_col, current_glyph_row; int current_glyph_diff_row, old_id, v, s, tags_row, tags_index, data_col; int gr, gc, intDbl, current_links_row, len, z, h, r, c; int col_in_q, row_in_q; /* "column in question" & "row in question" */ int col_in, type_in, id_counter; double col_min, col_max; double normalized, data_val; int glyph_row_col2mapper_line[MAX_GLYPH_ROWS][NUM_GLYPH_COLS]; char col_tag[MAX_LINE]; char header_line[MAX_LINE]; char in_row[MAX_LINE]; char hdrArray[MAX_COLS][MAX_FIELD]; char colArray[MAX_COLS][MAX_FIELD]; char tagsTemplateArray[MAX_GLYPH_ROWS][MAX_FIELD]; char search_string[MAX_FIELD]; char string_H[MAX_COLS][MAX_FIELD]; char string_R[MAX_COLS][MAX_FIELD]; char string_C[MAX_COLS][MAX_FIELD]; char string_D[MAX_COLS][MAX_FIELD]; int junk_memory[JUNK_MEMORY_SIZE]; char* tmp_str; int num_lines, n, current_mapper_row, gl; int num_data_stats_lines; int num_glyph_diff_lines; int num_mapper_lines; int num_types_lines; int numActualDataColumns; /* long int row_to_id[MAX_LINK_LINES]; */ int *row_to_id = malloc(MAX_LINK_LINES*sizeof(int)); double dblArray[MAX_COLS]; /* one row of input data */ FILE *tg_fp; /* tags file */ FILE *ds_fp; /* data stats file */ FILE *gd_fp; /* glyph diffs file */ FILE *m_fp; /* mapper file */ FILE *l_fp; /* links file */ FILE *tt_fp; /* tags template file */ FILE *ty_fp; /* types file */ /* initialize global variables (including parameters) */ defaultParms(); parseArgs(argc, argv); numActualDataColumns = NumDataColumns - RowNames; ProgName = extract_filename(argv[0]); for(data_col = 1; data_col <= numActualDataColumns; data_col++) { strcpy(&ColNames[data_col][0], "cn:this_is_a_bug"); } if (Debug) { fprintf(stderr, "%s: DEBUG: Debug = %d\n", ProgName, Debug); fprintf(stderr, "%s: DEBUG: Memtest = %d\n", ProgName, Memtest); fprintf(stderr, "%s: DEBUG: NumDataLines = %d\n", ProgName, NumDataLines); fprintf(stderr, "%s: DEBUG: NumLinksLines = %d\n", ProgName, NumLinksLines); fprintf(stderr, "%s: DEBUG: NumDataColumns = %d\n", ProgName, NumDataColumns); fprintf(stderr, "%s: DEBUG: RowNames = %d\n", ProgName, RowNames); fprintf(stderr, "%s: DEBUG: numActualDataColumns = %d\n", ProgName, numActualDataColumns); fprintf(stderr, "%s: DEBUG: GlyphFile = %s\n", ProgName, GlyphFile); fprintf(stderr, "%s: DEBUG: NumGlyphLines = %d\n", ProgName, NumGlyphLines); fprintf(stderr, "%s: DEBUG: Decimate = %d\n", ProgName, Decimate); fprintf(stderr, "%s: DEBUG: Scale = %f\n", ProgName, Scale); fprintf(stderr, "%s: DEBUG: Scale2 = %f\n", ProgName, Scale2); fprintf(stderr, "%s: DEBUG: StartID = %d\n", ProgName, StartID); fprintf(stderr, "%s: DEBUG: TagsFlag = %d\n", ProgName, TagsFlag); fprintf(stderr, "%s: DEBUG: Without = %d\n", ProgName, Without); fprintf(stderr, "%s: DEBUG: ZScale = %f\n", ProgName, ZScale); } if (NumGlyphLines > MAX_GLYPH_ROWS) { fprintf(stderr, "%s: DEBUG: NumGlyphLines must be <= %d\n", ProgName, MAX_GLYPH_ROWS); } if (NumDataColumns > MAX_COLS) { fprintf(stderr, "%s: DEBUG: NumDataColumns must be <= %d\n", ProgName, MAX_COLS); } /* initialize local variables */ if (Memtest) { mem_setup(junk_memory); } for (gr = 0; gr < MAX_GLYPH_ROWS; gr++) { for (gc = 0; gc < NUM_GLYPH_COLS; gc++) { glyph_row_col2mapper_line[gr][gc] = FALSE; } } if (TagsFlag) { /* open tag file and write header */ tg_fp = fopen(TagsFile, "w"); if (tg_fp == NULL) { fprintf(stderr, "%s: ERROR: fopen of %s failed, error: %s\n", ProgName, TagsFile, strerror(errno)); exit(EXIT_FAILURE); } fprintf(tg_fp, "id,record_id,table_id,title,description\n"); tags_index = 0; } /* read */ /* The confusing thing about what we're doing here is that the input * data file and the template glyph file are both in Comm Separated Value * (CSV) form, and one line of input data will typically be associated * with many lines of glyph data. There are inconsistencies in different * CSV tools in terms of how rows and columns are numbered. In the * 'glyph_factory' suite as exposed to users through the command line * and input/output text files, row 0 is the text header, and data begins * with row 1. Columns are numbered starting with 1. In code internals * this may be different. */ /* read template glyph file */ read_glyph(GlyphFile, NumGlyphLines); /* ok? */ if ( Glyph_array[PARENT_ID_4][FirstGoodLine] != 0.0) { fprintf(stderr, "%s: ERROR: Glyph_array[PARENT_ID_4][%d] = %f, should be 0.0\n", ProgName, FirstGoodLine, Glyph_array[PARENT_ID_4][FirstGoodLine]); exit(EXIT_FAILURE); } /* one-time surgery */ Glyph_array[SCALE_X_25][FirstGoodLine] = Glyph_array[SCALE_X_25][FirstGoodLine]*Scale; Glyph_array[SCALE_Y_26][FirstGoodLine] = Glyph_array[SCALE_Y_26][FirstGoodLine]*Scale; Glyph_array[SCALE_Z_27][FirstGoodLine] = Glyph_array[SCALE_Z_27][FirstGoodLine]*Scale; /* KLUDGE -- when will it end? */ Glyph_array[SCALE_X_25][FirstGoodLine + 1] = Glyph_array[SCALE_X_25][FirstGoodLine + 1]*Scale2; Glyph_array[SCALE_Y_26][FirstGoodLine + 1] = Glyph_array[SCALE_Y_26][FirstGoodLine + 1]*Scale2; Glyph_array[SCALE_Z_27][FirstGoodLine + 1] = Glyph_array[SCALE_Z_27][FirstGoodLine + 1]*Scale2; /* read links file */ /* ToDo: do all files like this */ if (NumLinksLines != -1) { if (NumLinksLines == 0) { NumLinksLines = lines_in_file(LinksFile); if (Debug) { fprintf(stderr, "%s: DEBUG: new NumLinksLines = %d\n", ProgName, NumLinksLines); } } l_fp = fopen(LinksFile, "r"); if (l_fp == NULL) { fprintf(stderr, "%s: ERROR: fopen of %s failed, error: %s\n", ProgName, LinksFile, strerror(errno)); exit(EXIT_FAILURE); } for (current_links_row = 1; current_links_row <= NumLinksLines; current_links_row++) { /* links.txt file format: row_num_1,row_num_2,ratio,red,green,blue,link_name example: 1,2,0.1,255,0,0,link_1_to_2 */ fscanf(l_fp, "%d,%d,%f,%d,%d,%d,%s\n", &Links_row_num1[current_links_row], &Links_row_num2[current_links_row], &Links_ratio[current_links_row], &Links_red[current_links_row], &Links_green[current_links_row], &Links_blue[current_links_row], &Links_name[current_links_row]); if (Debug) { fprintf(stderr, "%s: DEBUG: current_links_row: %d\n", ProgName, current_links_row); fprintf(stderr, "%s: DEBUG: Links_row_num1: %d\n", ProgName, Links_row_num1[current_links_row]); fprintf(stderr, "%s: DEBUG: Links_row_num2: %d\n", ProgName, Links_row_num2[current_links_row]); fprintf(stderr, "%s: DEBUG: Links_ratio: %f\n", ProgName, Links_ratio[current_links_row]); fprintf(stderr, "%s: DEBUG: Links_red: %d\n", ProgName, Links_red[current_links_row]); fprintf(stderr, "%s: DEBUG: Links_green: %d\n", ProgName, Links_green[current_links_row]); fprintf(stderr, "%s: DEBUG: Links_blue: %d\n", ProgName, Links_blue[current_links_row]); fprintf(stderr, "%s: DEBUG: Links_name: %s\n", ProgName, Links_name[current_links_row]); } } } /* read data stats file */ num_lines = lines_in_file(DataStatsFile); NumStatLines = num_lines; ds_fp = fopen(DataStatsFile, "r"); for (n = 0; n < num_lines; n++) { if (Debug) { fprintf(stderr, "%s: DEBUG: old col_tag: %s\n", ProgName, col_tag); } fscanf(ds_fp, "%d,%lf,%lf,%s\n", &col_in_q, &col_min, &col_max, &col_tag); if (Debug) { fprintf(stderr, "%s: DEBUG: new col_tag: %s\n", ProgName, col_tag); } /* n goes from 0 to number of lines in the stats file - 1 */ DataStatsCol[n] = col_in_q; DataStatsMin[n] = col_min; DataStatsMax[n] = col_max; DataStatsRange[n] = DataStatsMax[n] - DataStatsMin[n]; if (Debug) { fprintf(stderr, "%s: DEBUG: n:%d, col:%d, name:%s, min:%f, max:%f, tag:%s, range:%f\n", ProgName, n, DataStatsCol[n], col_tag, DataStatsMin[n], DataStatsMax[n], ColNames[DataStatsCol[n]], DataStatsRange[n]); } } fclose(ds_fp); /* read glyph diff file */ num_lines = lines_in_file(GlyphDiffFile); NumGlyphDiffLines = num_lines; gd_fp = fopen(GlyphDiffFile, "r"); for (n = 0; n < num_lines; n++) { fscanf(gd_fp, "%d,%d:%lf,%lf\n", &row_in_q, &col_in_q, &col_min, &col_max); /* n goes from 0 to number of lines in the glyph diff file - 1 */ /* subtract the size of the glyph header to get useful row # */ GlyphDiffRow[n] = row_in_q - FirstGoodLine; GlyphDiffCol[n] = col_in_q; GlyphDiffMin[n] = col_min; GlyphDiffMax[n] = col_max; GlyphDiffRange[n] = GlyphDiffMax[n] - GlyphDiffMin[n]; if (Debug) { fprintf(stderr, "%s: DEBUG: n: %d, row: %d, col: %d, min: %f, max: %f\n", ProgName, n, row_in_q, col_in_q, col_min, col_max); } } fclose(gd_fp); /* read mapper file */ NumMapperLines = lines_in_file(MapperFile); m_fp = fopen(MapperFile, "r"); for (n = 0; n < NumMapperLines; n++) { fscanf(m_fp, "%d,%d:%d\n", &row_in_q, &col_in_q, &col_in); /* n goes from 0 to number of lines in the mapper file - 1 */ /* subtract the size of the glyph header to get useful row # */ MapperGlyphRow[n] = row_in_q - FirstGoodLine; MapperGlyphCol[n] = col_in_q; MapperDataCIn[n] = col_in; /* input column for this output row & col */ /* for reverse lookup -- so far unused */ glyph_row_col2mapper_line[MapperGlyphRow[n]][MapperGlyphCol[n]] = n; if (Debug) { fprintf(stderr, "%s: DEBUG: n: %d, row: %d, col: %d, col_in: %d\n", ProgName, n, MapperGlyphRow[n], MapperGlyphCol[n], MapperDataCIn[n]); } } fclose(m_fp); /* read tags template file */ tt_fp = fopen(TagsTemplateFile, "r"); if (tt_fp == NULL) { fprintf(stderr, "%s: ERROR: fopen of %s failed, error: %s\n", ProgName, TagsTemplateFile, strerror(errno)); exit(EXIT_FAILURE); } for (n = 0; n < NumGlyphLines; n++) { len = getl(tt_fp, in_row, MAX_LINE); /* strip newline from in_row */ for (z = 0; z < MAX_LINE; z++) { if (in_row[z] == '\n' || in_row[z] == '\r') { in_row[z] = EOS; } } strcpy(tagsTemplateArray[n], in_row); if (Debug) { fprintf(stderr, "%s: DEBUG: n: tagsTemplateArray[%d]: %s\n", ProgName, n, tagsTemplateArray[n]); } } fclose(tt_fp); #ifdef TYPE /* read antz type file */ /* this will be changed very rarely -- I think */ /* note col 0 is first column here */ num_lines = lines_in_file(TypeFile); ty_fp = fopen(TypeFile, "r"); for (n = 0; n < NUM_GLYPH_COLS - 1; n++) { fscanf(ty_fp, "%d,", &type_in); if (Debug) { fprintf(stderr, "%s: DEBUG: n: %d, type: %d\n", ProgName, n, type_in); } Types[n] = type_in; } fscanf(m_fp, "%f", &type_in); /* last one, no comma */ Types[n] = type_in; fclose(ty_fp); #endif /* read & process data file */ if (Debug) { fprintf(stderr, "%s: DEBUG: #0: tagsTemplateArray[0]: %s\n", ProgName, tagsTemplateArray[0]); } id = StartID; if (Debug) { fprintf(stderr, "%s: DEBUG: #1: tagsTemplateArray[0]: %s\n", ProgName, tagsTemplateArray[0]); } /* read header */ getl(stdin, header_line, MAX_LINE); if (Debug) { fprintf(stderr, "%s: DEBUG: header_line:%s\n", ProgName, header_line); } if (Debug) { fprintf(stderr, "%s: DEBUG: #2: tagsTemplateArray[0]: %s\n", ProgName, tagsTemplateArray[0]); } parse_csv_line_to_string(header_line, NumDataColumns, ColNames); if (Debug) { fprintf(stderr, "%s: DEBUG: #3: tagsTemplateArray[0]: %s\n", ProgName, tagsTemplateArray[0]); } if (Debug) { fprintf(stderr, "%s: DEBUG: ColNames[1]:%s\n", ProgName, ColNames[1]); fprintf(stderr, "%s: DEBUG: ColNames[2]:%s\n", ProgName, ColNames[2]); fprintf(stderr, "%s: DEBUG: ColNames[3]:%s\n", ProgName, ColNames[3]); fprintf(stderr, "%s: DEBUG: ColNames[4]:%s\n", ProgName, ColNames[4]); fprintf(stderr, "%s: DEBUG: ColNames[5]:%s\n", ProgName, ColNames[5]); fprintf(stderr, "%s: DEBUG: ColNames[6]:%s\n", ProgName, ColNames[6]); fprintf(stderr, "%s: DEBUG: ColNames[7]:%s\n", ProgName, ColNames[7]); fprintf(stderr, "%s: DEBUG: ColNames[8]:%s\n", ProgName, ColNames[8]); } /* prep static strings */ /***************************** __H1__ row name header 1 __R1__ row name 1 __C1__ column 1 name __D1__ column 1 data value __m1__ column 1 min data val __M1__ column 1 max data val *****************************/ if (RowNames >= 1) { for (r = 1; r <= RowNames; r++) { strcpy(string_H[r], ColNames[numActualDataColumns + r]); if (Debug) { fprintf(stderr, "%s: DEBUG: r:%d; string_H[r]:%s\n", ProgName, r, string_H[r]); } } } if (Debug) { fprintf(stderr, "%s: DEBUG: #4: tagsTemplateArray[0]: %s\n", ProgName, tagsTemplateArray[0]); } for (c = 1; c <= numActualDataColumns; c++) { strcpy(string_C[c], ColNames[c]); if (Debug) { fprintf(stderr, "%s: DEBUG: c:%d; string_C[c]:%s\n", ProgName, c, string_C[c]); } } if (Debug) { fprintf(stderr, "%s: DEBUG: #5: tagsTemplateArray[0]: %s\n", ProgName, tagsTemplateArray[0]); } /* loop while reading input data rows */ /* it is important for this loop to be able to run virtually endlesly -- no storing row data between loops */ if (Debug) { fprintf(stderr, "%s: DEBUG: #101: NumDataLines: %d\n", ProgName, NumDataLines); } for (current_data_row = 1; current_data_row <= NumDataLines; current_data_row++) { if (Debug) { fprintf(stderr, "%s: DEBUG: #6: tagsTemplateArray[0]: %s\n", ProgName, tagsTemplateArray[0]); } len = getl(stdin, in_row, MAX_LINE); if (Debug) { fprintf(stderr, "%s: DEBUG: #7: tagsTemplateArray[0]: %s\n", ProgName, tagsTemplateArray[0]); } /* strip newline from in_row */ for (z = 0; z < MAX_LINE; z++) { if (in_row[z] == '\n' || in_row[z] == '\r') { in_row[z] = EOS; } } if (Debug) { fprintf(stderr, "%s: DEBUG: #8: tagsTemplateArray[0]: %s\n", ProgName, tagsTemplateArray[0]); } parse_csv_line_to_string(in_row, NumDataColumns, colArray); if (Debug) { fprintf(stderr, "%s: DEBUG: #9: tagsTemplateArray[0]: %s\n", ProgName, tagsTemplateArray[0]); } /* parse numbers */ for (current_data_col = 1; current_data_col <= numActualDataColumns; current_data_col++) { sscanf(colArray[current_data_col], "%lf", &dblArray[current_data_col]); if (Debug) { fprintf(stderr, "%s: DEBUG: now dblArray[%d]:%lf\n", ProgName, current_data_col, dblArray[current_data_col]); } } if (Debug) { fprintf(stderr, "%s: DEBUG: #99: tagsTemplateArray[0]: %s\n", ProgName, tagsTemplateArray[0]); } /* new way for tags */ if (RowNames >= 1) { for (r = 1; r <= RowNames; r++) { strcpy(string_R[r], colArray[NumDataColumns - RowNames + r]); if (Debug) { fprintf(stderr, "%s: DEBUG: r:%d; string_R[r]:%s\n", ProgName, r, string_R[r]); } } } for (c = 1; c <= NumDataColumns - RowNames; c++) { strcpy(string_D[c], colArray[c]); if (Debug) { fprintf(stderr, "%s: DEBUG: c:%d; string_D[c]:%s\n", ProgName, c, string_D[c]); } } for (tags_row = 0; tags_row < NumGlyphLines; tags_row++) { if (Debug) { fprintf(stderr, "%s: DEBUG: tagsTemplateArray[%d]: %s\n", ProgName, tags_row, tagsTemplateArray[tags_row]); } strcpy(&Tags[tags_row][0], &tagsTemplateArray[tags_row][0]); if (Debug) { fprintf(stderr, "%s: DEBUG: just set Tags[%d]: %s\n", ProgName, tags_row, Tags[tags_row]); } for (h = 1; h <= RowNames; h++) { /* H */ sprintf(search_string, "__H%d__", h); tmp_str = replace(Tags[tags_row], search_string, string_H[h]); strcpy(&Tags[tags_row][0], tmp_str); if (Debug) { fprintf(stderr, "%s: DEBUG: H: h:%d; search_string:%s\n", ProgName, h, search_string); fprintf(stderr, "%s: DEBUG: tmp_str:%s\n", ProgName, tmp_str); } /* R */ sprintf(search_string, "__R%d__", h); tmp_str = replace(Tags[tags_row], search_string, string_R[h]); strcpy(&Tags[tags_row][0], tmp_str); if (Debug) { fprintf(stderr, "%s: DEBUG: R: h:%d; search_string:%s\n", ProgName, h, search_string); fprintf(stderr, "%s: DEBUG: tmp_str:%s\n", ProgName, tmp_str); } } for (h = 1; h <= numActualDataColumns; h++) { /* D */ sprintf(search_string, "__D%d__", h); tmp_str = replace(Tags[tags_row], search_string, string_D[h]); strcpy(&Tags[tags_row][0], tmp_str); if (Debug) { fprintf(stderr, "%s: DEBUG: D: h:%d; search_string:%s\n", ProgName, h, search_string); fprintf(stderr, "%s: DEBUG: tmp_str:%s\n", ProgName, tmp_str); } /* C */ sprintf(search_string, "__C%d__", h); tmp_str = replace(Tags[tags_row], search_string, string_C[h]); strcpy(&Tags[tags_row][0], tmp_str); if (Debug) { fprintf(stderr, "%s: DEBUG: C: h:%d; search_string:%s\n", ProgName, h, search_string); fprintf(stderr, "%s: DEBUG: tmp_str:%s\n", ProgName, tmp_str); } } /* end of replaces */ /* safety check */ for (v = 0; v < NumGlyphLines; v++) { Tags[v][62] = EOS; } TagsUsed[tags_row] = TRUE; /* GET RID OF */ } /* process & write */ /* special handling */ for (gl = 0; gl < NumGlyphLines; gl++) { Glyph_array[SELECTED_3][FirstGoodLine + gl] = 0.0; } /* magic */ /* this is very inefficient since the searchers are all done on each row -- better to have a data converter prepped with paramters already worked out for each column, and run a concise version of the algebra inside the loop */ if (Debug) { fprintf(stderr,"=== magic begins =="); fprintf(stderr,"==================="); fprintf(stderr,"==================="); fprintf(stderr,"===================\n"); } for (current_mapper_row = 0; current_mapper_row < NumMapperLines; current_mapper_row++) { for (current_data_col = 1; current_data_col <= NumDataColumns; current_data_col++) { if (MapperDataCIn[current_mapper_row] == current_data_col) { /* find stats row */ for (s = 0; s < NumStatLines; s++) { if (DataStatsCol[s] == current_data_col) { /* s stats is the line that mentions column current_data_col */ for (current_glyph_diff_row = 0; current_glyph_diff_row < NumGlyphDiffLines; current_glyph_diff_row++) { if (GlyphDiffRow[current_glyph_diff_row] == MapperGlyphRow[current_mapper_row] && GlyphDiffCol[current_glyph_diff_row] == MapperGlyphCol[current_mapper_row]) { /* g glyph_diff is the line that mentions column c */ if (Debug) { fprintf(stderr,"-------------------"); fprintf(stderr,"-------------------"); fprintf(stderr,"-------------------"); fprintf(stderr,"-------------------\n"); fprintf(stderr, "%s: DEBUG: s:%d g:%d dblArray[current_data_col]:%f\n", ProgName, s, current_glyph_diff_row, dblArray[current_data_col]); } /* simplify */ current_glyph_row = MapperGlyphRow[current_mapper_row]; /* this shouldn't work without - 1 ??? */ /* compute data */ normalized = (dblArray[current_data_col] - DataStatsMin[s])/DataStatsRange[s]; data_val = normalized*GlyphDiffRange[current_glyph_diff_row] + GlyphDiffMin[current_glyph_diff_row]; if (Debug) { fprintf(stderr, "%s: DEBUG: current_mapper_row:%d current_data_col:%d norm:%f data:%f\n", ProgName, current_mapper_row, current_data_col, normalized, data_val); } /* perform surgery */ /* in Glyph_array rows & cols start at 0 */ /* I don't understand why this works */ Glyph_array[MapperGlyphCol[current_mapper_row] - 1][FirstGoodLine + MapperGlyphRow[current_mapper_row]] = data_val; if (TagsFlag) { /* KLUDGE BELOW */ if (((MapperGlyphCol[current_mapper_row]) == Particular) && !TagsUsed[current_glyph_row]) { if (Debug) { fprintf(stderr, "%s: DEBUG: T: TagsUsed[%d]: %d\n", ProgName, current_glyph_row, TagsUsed[current_glyph_row]); } intDbl = (int)dblArray[current_data_col]; if (dblArray[current_data_col] == (double)intDbl) { if (RowNames) { sprintf(&Tags[current_glyph_row][0], "%s - %s:%d", RowName, &ColNames[current_data_col][0], intDbl); TagsUsed[current_glyph_row] = TRUE; } else { sprintf(&Tags[current_glyph_row][0], "row %d column %d - %s:%d", current_data_row, current_data_col, &ColNames[current_data_col][0], intDbl); TagsUsed[current_glyph_row] = TRUE; } } else { if (RowNames) { sprintf(&Tags[current_glyph_row][0], "%s - %s:%f", RowName, &ColNames[current_data_col][0], dblArray[current_data_col]); TagsUsed[current_glyph_row] = TRUE; } else { sprintf(&Tags[current_glyph_row][0], "Row %d column %d - %s:%f", current_data_row, current_data_col, &ColNames[current_data_col][0], dblArray[current_data_col]); TagsUsed[current_glyph_row] = TRUE; } } } else if (!TagsUsed[current_glyph_row]) { if (Debug) { fprintf(stderr, "%s: DEBUG: F: TagsUsed[%d]: %d\n", ProgName, current_glyph_row, TagsUsed[current_glyph_row]); } sprintf(&Tags[current_glyph_row][0], "ROW %d", current_data_row); } } if (Debug) { fprintf(stderr, "%s: DEBUG: MapperGlyphCol[current_mapper_row] - 1: %d\n", ProgName, MapperGlyphCol[current_mapper_row] - 1); fprintf(stderr, "%s: DEBUG: MapperGlyphRow[current_mapper_row]: %d\n", ProgName, MapperGlyphRow[current_mapper_row]); fprintf(stderr, "%s: DEBUG: Tags[%d] = %s\n", ProgName, current_glyph_row, &Tags[current_glyph_row][0]); } } /* end if*/ } /* end for g */ } /* end if */ } /* end for s */ } /* end if */ } /* end for c */ } /* end for m */ if (Memtest) { fprintf(stderr, "%s: Memtest #1\n", ProgName); mem_test(junk_memory); } if (NumLinksLines != -1) { if (current_data_row >= MAX_LINK_LINES) { fprintf(stderr, "%s: ERROR: setting row_id[%d] beyond end: %d\n", ProgName, current_data_row, MAX_LINK_LINES); exit(EXIT_FAILURE); } row_to_id[current_data_row] = id; } if (Memtest) { fprintf(stderr, "%s: Memtest #2\n", ProgName); mem_test(junk_memory); } old_id = id; id = write_glyph(NumGlyphLines, id); if (Debug) { fprintf(stderr, "%s: DEBUG: current_data_row = %d\n", ProgName, current_data_row); fprintf(stderr, "%s: DEBUG: id = %d\n", ProgName, id); } if (TagsFlag) { /* write tags */ if (Debug) { fprintf(stderr, "%s: DEBUG: about to write some tags\n", ProgName); for (v = 0; v < NumGlyphLines; v++) { fprintf(stderr, "%s: DEBUG: Tags[%d] = %s\n", ProgName, v, Tags[v]); } } v = 0; for (id_counter = old_id; id_counter < id; id_counter++) { if (v < Without) { fprintf(tg_fp, "%d,%d,0,\"%s\",\"unused\"\n", tags_index++, id_counter, RowName); } else { fprintf(tg_fp, "%d,%d,0,\"%s\",\"unused\"\n", tags_index++, id_counter, Tags[v]); } v++; } } } /* end for current_data_row */ if (NumLinksLines != -1) { if (Debug) { for (current_links_row = 1; current_links_row <= NumDataLines; current_links_row++) { fprintf(stderr, "%s: DEBUG: recap: row_to_id[%d] = %d\n", ProgName, current_links_row, row_to_id[current_links_row]); } } } /* write links */ if (NumLinksLines != -1) { for (current_links_row = 1; current_links_row <= NumLinksLines; current_links_row++) { id++; /* assume leftover id from above OK */ if (Debug) { fprintf(stderr, "%s: DEBUG: writing links: current_links_row = %d\n", ProgName, current_links_row); fprintf(stderr, "%s: DEBUG: writing links: id = %d\n", ProgName, id); fprintf(stderr, "%s: DEBUG: writing links: Links_row_num1[] = %d\n", ProgName, Links_row_num1[current_links_row]); fprintf(stderr, "%s: DEBUG: writing links: row_to_id[Links_row_num1[]] = %d\n", ProgName, row_to_id[Links_row_num1[current_links_row]]); fprintf(stderr, "%s: DEBUG: writing links: row_to_id[Links_row_num2[]] = %d\n", ProgName, row_to_id[Links_row_num2[current_links_row]]); } if(row_to_id[Links_row_num2[current_links_row]] == 0) { fprintf(stderr, "%s: ERROR: attempt to write link to node zero\n", argv[0]); exit(EXIT_FAILURE); } print_CSV_line( id, /* int id */ ANTZ_TYPE_LINK, /* int type */ 0, /* int sel */ row_to_id[Links_row_num1[current_links_row]], /* int pid */ 1, /* int branch_level */ row_to_id[Links_row_num2[current_links_row]], /* int ci */ 0, /* int nc */ 0, /* int cc */ Links_ratio[current_links_row], /* float ratio */ 1.0, /* float xs */ 1.0, /* float ys */ 1.0, /* float zs */ 0.0, /* float xt */ 0.0, /* float yt */ 0.0, /* float zt */ ANTZ_GEOM_CYLINDER, /* int geometry */ ANTZ_TOPO_LINK, /* int topo */ Links_red[current_links_row], /* int r */ Links_green[current_links_row], /* int g*/ Links_blue[current_links_row], /* int b */ 255, /* int a */ TagsFlag, /* Bool tag_flag */ Links_name[current_links_row], /* char* tag_str */ tg_fp /* tag fp */ ); } /* end for */ } /* end if */ free(row_to_id); } /* end main */ /* * defaultParms - initialize global variables */ defaultParms() { Memtest = FALSE; NumDataLines = 1; NumGlyphLines = 1; NumLinksLines = -1; NumDataColumns = 1; Particular = SCALE_X_25 + 1; RowNames = FALSE; StartID = 300; Decimate = 0; Scale = 1.0; Scale2 = 1.0; TagsFlag = FALSE; Without = 1; ZScale = 1.0; strcpy(GlyphFile, "glyph_in.csv"); strcpy(DataStatsFile, "data_stats.txt"); strcpy(LinksFile, "links.txt"); strcpy(MapperFile, "mapper.txt"); strcpy(GlyphDiffFile, "glyph_diff.txt"); strcpy(TagsFile, "ANTzTag0001.csv"); strcpy(TagsTemplateFile, "tags_template.txt"); strcpy(TypeFile, "types.txt"); } /* end defaultParms() */ /* * parseArgs - parse arguments into global variables */ parseArgs(argc, argv) int argc; char** argv; { int i; for (i = 0; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'D' : Debug = TRUE; break; case 'c' : NumDataColumns = atoi(&argv[++i][0]); break; case 'd' : Decimate = atoi(&argv[++i][0]); break; case 'e' : strcpy(TagsTemplateFile, &argv[++i][0]); break; case 'g' : NumGlyphLines = atoi(&argv[++i][0]); break; case 'G' : strcpy(GlyphFile, &argv[++i][0]); break; case 'h' : help(argv); exit(EXIT_FAILURE); break; case 'i' : StartID = atoi(&argv[++i][0]); break; case 'l' : NumLinksLines = atoi(&argv[++i][0]); break; case 'L' : strcpy(LinksFile, &argv[++i][0]); break; case 'M' : Memtest = TRUE; break; case 'n' : NumDataLines = atoi(&argv[++i][0]); break; case 'p' : Particular = atoi(&argv[++i][0]); break; case 'r' : RowNames = TRUE; break; case 'R' : RowNames = atoi(&argv[++i][0]); break; case 's' : Scale = atof(&argv[++i][0]); break; case 'S' : Scale2 = atof(&argv[++i][0]); break; case 't' : TagsFlag = TRUE; break; case 'T' : strcpy(TagsFile, &argv[++i][0]); break; case 'u' : usage(argv); exit(EXIT_FAILURE); break; case 'w' : Without = atoi(&argv[++i][0]); break; case 'z' : ZScale = atof(&argv[++i][0]); break; default: fprintf(stderr, "%s: ERROR: illegal flag: %s\n", argv[0], argv[i]); exit(EXIT_FAILURE); break; } /* end switch */ } /* end if */ } /* end for(i) */ } /* end parseArgs() */ /* * getl - modified from Kernighan & Ritchie to take stream */ int getl(stream, s, lim) /* get line into s, return length */ FILE *stream; char s[]; int lim; { int c, i; i = 0; while (--lim > 0 && (c = getc(stream)) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = c; s[i] = EOS; return(i); } /* end getl() */ /* * lines_in_file - from Stacktrace */ int lines_in_file(filename) char filename[]; { FILE *fp; /* */ int c; /* Nb. int (not char) for the EOF */ unsigned long newline_count = 0; /* count the newline characters */ fp = fopen(filename, "r"); if (fp == NULL) { fprintf(stderr, "%s: ERROR: fopen of %s failed, error: %s\n", ProgName, filename, strerror(errno)); exit(EXIT_FAILURE); } while ( (c=fgetc(fp)) != EOF ) { if ( c == '\n' ) { newline_count++; } } fclose(fp); return newline_count; } /* end lines_in_file() */ /* * extract_filename() */ char * extract_filename(char *str) { int ch = '/'; size_t len; char *pdest; char *inpfile = NULL; // Search backwards for last backslash in filepath pdest = strrchr(str, ch); // if backslash not found in filepath if(pdest == NULL ) { printf( "Result:\t%c not found\n", ch ); pdest = str; // The whole name is a file in current path? } else { pdest++; // Skip the backslash itself. } // extract filename from file path len = strlen(pdest); inpfile = malloc(len+1); // Make space for the zero. strncpy(inpfile, pdest, len+1); // Copy including zero. return inpfile; } /* * parse_csv_line_to_string() * */ parse_csv_line_to_string(src_line, num_cols, dest_str_array) char* src_line; int num_cols; char dest_str_array[MAX_COLS][MAX_FIELD]; { char single_char; int col_num = 1; int in_char_num = 0; int out_char_num = 0; if (Debug != FALSE) { fprintf(stderr, "%s: parse_csv_line_to_string(): DEBUG: src_line: >%s<\n", ProgName, src_line); } while (col_num <= num_cols) { single_char = src_line[in_char_num]; while ((single_char != ',') && (single_char != EOS) && (single_char != '\n') && (single_char != '\r')) { dest_str_array[col_num][out_char_num++] = single_char; single_char = src_line[++in_char_num]; } dest_str_array[col_num][out_char_num] = EOS; if (dest_str_array[col_num][0] == EOS) { strcpy(&dest_str_array[col_num][0], MissingValues); } if (Debug != FALSE) { fprintf(stderr, "%s: DEBUG: parse_csv_line_to_string: dest_str_array[%d]: >%s<\n", ProgName, col_num, dest_str_array[col_num]); } /* in_char_num now points to first input comma */ #ifdef SUPER_DEBUG if (Debug != FALSE) { fprintf(stderr, "DEBUG: parse_csv_line_to_string(): src_line[%d] = %c (should be comma)\n", in_char_num, src_line[in_char_num]); } #endif in_char_num++; out_char_num = 0; col_num++; } } /* end parse_csv_line_to_string() */ /* * mem_setup() * */ void mem_setup(int_array) int *int_array; { int i; for (i = 0; i < JUNK_MEMORY_SIZE; i++) { int_array[i] = GOOD_NUMBER; } } /* * mem_test() * */ void mem_test(int_array) int *int_array; { int i; for (i = 0; i < JUNK_MEMORY_SIZE; i++) { if (int_array[i] != GOOD_NUMBER) { fprintf(stderr, "%s: ERROR: bad memory value: %d at i: %d\n", ProgName, int_array[i], i); exit(EXIT_FAILURE); } } } /* * replace () * * from: bytes.com/topic/c/answers/223500-how-replace-substring-string-using-c * */ #include #include #include char *replace(const char *s, const char *old, const char *new) { char *ret; int i, count = 0; size_t newlen = strlen(new); size_t oldlen = strlen(old); for (i = 0; s[i] != '\0'; i++) { if (strstr(&s[i], old) == &s[i]) { count++; i += oldlen - 1; } } ret = malloc(i + count * (newlen - oldlen)); if (ret == NULL) exit(EXIT_FAILURE); i = 0; while (*s) { if (strstr(s, old) == s) { strcpy(&ret[i], new); i += newlen; s += oldlen; } else ret[i++] = *s++; } ret[i] = '\0'; return ret; } #ifdef UNIT_TEST int main(void) { char mystr[] = "##this is##a examp#le"; char *newstr = NULL; puts(mystr); newstr = replace(mystr, "##", "****"); printf("%s\n", newstr); free(newstr); return 0; } #endif -------------------------------------------------- glyph_factory.h -------------------------------------------------- /* * glyph_factory.h -- include file for glyph_factory.c */ /* includes */ #include "synglyphx.h" /* constants */ #define MAX_CODE (5) #define STRING_EQUAL (0) #define MAX_COLS (512) #define ERROR_CODE (-1) #define NO_MATCH (-1) #define UNIVERSAL_PARENT (0) #define START_ID (33) #define NUM_GLYPH_COLS (95) #define MAX_LINK_LINES (4000000) /* 4 million */ #define MAX_FIELD (128) #define CIRCLE_DEG (360.0) #define GOOD_NUMBER (33333) #define JUNK_MEMORY_SIZE (65536) /* global variables */ char Tags[MAX_GLYPH_ROWS][MAX_LINE]; /* tags */ int DataStatsCol[MAX_COLS]; double DataStatsMin[MAX_COLS]; double DataStatsMax[MAX_COLS]; double DataStatsRange[MAX_COLS]; char ColNames[MAX_COLS][MAX_FIELD];/* for tags */ char RowName[MAX_LINE]; /* for tags */ int TagNum; /* incremented index that everybody writes ??? */ int Links_row_num1[MAX_LINK_LINES]; int Links_row_num2[MAX_LINK_LINES]; int Links_red[MAX_LINK_LINES]; int Links_green[MAX_LINK_LINES]; int Links_blue[MAX_LINK_LINES]; float Links_ratio[MAX_LINK_LINES]; char Links_name[MAX_LINK_LINES][MAX_LINE]; char *ProgName; /* name of this program -- malloced elsewhere */ int GlyphDiffRow[MAX_GLYPH_ROWS]; int GlyphDiffCol[MAX_GLYPH_ROWS]; double GlyphDiffMin[MAX_GLYPH_ROWS]; double GlyphDiffMax[MAX_GLYPH_ROWS]; double GlyphDiffRange[MAX_GLYPH_ROWS]; int NumMapperLines; int NumStatLines; int NumGlyphDiffLines; int MapperGlyphRow[MAX_COLS]; int MapperGlyphCol[MAX_COLS]; int MapperDataCIn[MAX_COLS]; int TagsUsed[MAX_GLYPH_ROWS]; int Types[NUM_GLYPH_COLS]; /* flag-settable parameters (global variables) */ int Debug; /* Boolean: TRUE = debug writes */ int Memtest; /* Boolean: TRUE = memory test */ int Decimate; /* */ float Scale; /* */ float Scale2; /* */ float ZScale; /* */ int NumDataLines; /* */ int NumDataColumns; /* */ int NumGlyphLines; /* */ int NumLinksLines; /* */ int NumMapperLines; /* */ char MissingValues[MAX_FIELD]; /* */ int Particular; /* */ int RowNames; /* Boolean */ int StartID; /* */ int TagsFlag; /* Boolean */ char TagsFile[MAX_LINE]; /* tags file name */ char DataStatsFile[MAX_LINE]; /* */ char LinksFile[MAX_LINE]; /* */ char MapperFile[MAX_LINE]; /* */ char GlyphDiffFile[MAX_LINE]; /* */ char TypeFile[MAX_LINE]; /* */ char TagsTemplateFile[MAX_LINE]; /* */ int Without; /* */ /* macros */ -------------------------------------------------- glyph_tools.c -------------------------------------------------- /** ** glyph_tools: contains: ** ** read_glyph() ** write_glyph() **/ #include "synglyphx.h" /* * read_glyph - read from a CSV file into Glyph_array[][] */ void read_glyph(filename, num_lines) char * filename; int num_lines; { /* declare local variables */ int len, col, i_col, d_col, line_num; char temp_char; char input_line[MAX_GLYPH_LINE]; char data_array[MAX_GLYPH_LINE]; FILE* g_fp; /* init local variables */ FirstGoodLine = 0; /* read */ g_fp = fopen(GlyphFile, "r"); if (g_fp == NULL) { fprintf(stderr, "%s: ERROR: fopen failed, error: %s\n", "read_glyph()", strerror(errno)); exit(0); } len = getl(g_fp, &input_line, MAX_GLYPH_LINE); /* text header */ for (line_num = 1; line_num < num_lines; line_num++) { len = getl(g_fp, &input_line, MAX_GLYPH_LINE); if (len == 0) { fprintf(stderr, "%s: ERROR: zero length line number %d\n", "read_glyph()", line_num); break; } i_col = 0; for (col = 0; col < NUM_COLUMNS - 1; col++) { d_col = 0; temp_char = input_line[i_col]; while (temp_char != ',') { temp_char = input_line[i_col++]; data_array[d_col++] = temp_char; } data_array[d_col - 1] = EOS; sscanf(data_array, "%f", &Glyph_array[col][line_num]); } d_col = 0; temp_char = input_line[i_col]; while (temp_char != ',') { temp_char = input_line[i_col++]; data_array[d_col++] = temp_char; } data_array[d_col - 1] = EOS; sscanf(data_array, "%f", &Glyph_array[NUM_COLUMNS - 1][line_num]); if ((!FirstGoodLine) && (Glyph_array[1][line_num] == 5.0)) { FirstGoodLine = line_num; } if (Glyph_array[NUM_COLUMNS - 1][line_num] != 420.0) { fprintf(stderr, "%s: ERROR: record %d was: %f, should be 420.0\n", NUM_COLUMNS - 1, "read_glyph()", Glyph_array[NUM_COLUMNS - 1][line_num]); exit(0); } } fclose(g_fp); } /* * write_glyph - write from Glyph_array[][] into a CSV file */ int write_glyph(num_lines, start_id) int num_lines; int start_id; { int col, row, temp_int; for (row = FirstGoodLine; row < num_lines; row++) { if (FirstGoodLine == row) { First_id = Glyph_array[ID_0][row]; } /* do all surgery here */ Glyph_array[ID_0][row] = Glyph_array[ID_0][row] - First_id + start_id; Glyph_array[DATA_2][row] = Glyph_array[ID_0][row]; /* anything with parent zero stays that way */ if (Glyph_array[PARENT_ID_4][row] != 0.0) { Glyph_array[PARENT_ID_4][row] = Glyph_array[PARENT_ID_4][row] - First_id + start_id; } Glyph_array[RECORD_ID_92][row] = Glyph_array[ID_0][row]; /* end of surgery */ for (col = 0; col < NUM_COLUMNS; col++) { temp_int = (int)Glyph_array[col][row]; if ((float)temp_int == Glyph_array[col][row]) { fprintf(stdout, "%d", (int)Glyph_array[col][row]); } else if (col == COLOR_R_55 || col == COLOR_G_56 || col == COLOR_B_57 || col == COLOR_INDEX_54 || col == COLOR_A_58) { fprintf(stdout, "%d", (int)Glyph_array[col][row]); } else { fprintf(stdout, "%f", Glyph_array[col][row]); } if (col < NUM_COLUMNS - 1) { fprintf(stdout, ","); } } fprintf(stdout, "\n"); } return start_id + num_lines - FirstGoodLine; } -------------------------------------------------- help.c -------------------------------------------------- /* * help - give program help */ #include help(argv) char** argv; { fprintf(stderr, "%s: HELP:\n", argv[0]); fprintf(stderr, "\n"); fprintf(stderr, " glyph_factory - generalized tool for converting csv\n"); fprintf(stderr, " input data to ANTz files\n"); fprintf(stderr, "\n"); } /* end of help */ -------------------------------------------------- usage.c -------------------------------------------------- /* * usage - give program usage */ #include usage(argv) char** argv; { fprintf(stderr, "%s: USAGE: %s [flags] > outfile\n", argv[0], argv[0]); fprintf(stderr, "\n"); fprintf(stderr, " flag meaning default \n"); fprintf(stderr, " ------------- -------------------------- ----------\n"); fprintf(stderr, " -D debug FALSE \n"); fprintf(stderr, " -c number of input columns 1 \n"); fprintf(stderr, " -d decimate amount (1/d) 0 (don't)\n"); fprintf(stderr, " -e tags template input file tags_template.txt\n"); fprintf(stderr, " 0.0 = ignore \n"); fprintf(stderr, " -G glyph file name glyph_in.csv\n"); fprintf(stderr, " -g number of glyph lines 1 \n"); fprintf(stderr, " -h help on this program FALSE\n"); fprintf(stderr, " -i start id for glyph rows 300\n"); fprintf(stderr, " -l number of links lines -1 (unused)\n"); fprintf(stderr, " -L links input file name links.txt\n"); fprintf(stderr, " -M memory test (debug) FALSE\n"); fprintf(stderr, " -n number of input lines 1 \n"); fprintf(stderr, " -p which particular column\n"); fprintf(stderr, " for tags (if no template) 26 (scale x)\n"); fprintf(stderr, " -r 1 rowname column (compat.) FALSE\n"); fprintf(stderr, " -R number of rowname columns 0\n"); fprintf(stderr, " -s scale 1st glyph 1.0\n"); fprintf(stderr, " -S scale 2nd glyph 1.0\n"); fprintf(stderr, " -t output tags FALSE\n"); fprintf(stderr, " -T tags output file name ANTzTag0001.csv\n"); fprintf(stderr, " -u usage (this message) FALSE\n"); fprintf(stderr, " -w glyph lines to omit tags\n"); fprintf(stderr, " (without) 1\n"); fprintf(stderr, " -z z scale 1.0 \n"); fprintf(stderr, "\n"); } /* end of usage */ -------------------------------------------------- synglyphx.h -------------------------------------------------- /* * synglyphx.h */ /* includes */ #include #include #include #include #include #include /* constants */ #define TRUE (1) #define FALSE (0) #define NUM_COLUMNS (94) #define MAX_GLYPH_ROWS (400) #define MAX_GLYPH_LINE (4096) #define MAX_LINE (255) #define EOS (0) #define ANTZ_TYPE_PIN (5) #define ANTZ_TYPE_LINK (7) #define ANTZ_GEOM_CUBE_WIRE (0) #define ANTZ_GEOM_CUBE (1) #define ANTZ_GEOM_SPHERE_WIRE (2) #define ANTZ_GEOM_SPHERE (3) #define ANTZ_GEOM_CONE_WIRE (4) #define ANTZ_GEOM_CONE (5) #define ANTZ_GEOM_TOROID_WIRE (6) #define ANTZ_GEOM_TOROID (7) #define ANTZ_GEOM_DODEC_WIRE (8) #define ANTZ_GEOM_DODEC (9) #define ANTZ_GEOM_OCTO_WIRE (10) #define ANTZ_GEOM_OCTO (11) #define ANTZ_GEOM_TETRA_WIRE (12) #define ANTZ_GEOM_TETRA (13) #define ANTZ_GEOM_ICOS_WIRE (14) #define ANTZ_GEOM_ICOS (15) #define ANTZ_GEOM_PIN (16) #define ANTZ_GEOM_PIN_WIRE (17) #define ANTZ_GEOM_CYLINDER_WIRE (18) #define ANTZ_GEOM_CYLINDER (19) #define ANTZ_TOPO_LINK (0) #define ANTZ_TOPO_CUBE (1) #define ANTZ_TOPO_SPHERE (2) #define ANTZ_TOPO_TORUS (3) #define ANTZ_TOPO_CYLINDER (4) #define ANTZ_TOPO_PIN (5) #define ANTZ_TOPO_ROD (6) #define ANTZ_TOPO_POINT (7) #define ID_0 (0) #define TYPE_1 (1) #define DATA_2 (2) #define SELECTED_3 (3) #define PARENT_ID_4 (4) #define BRANCH_LEVEL_5 (5) #define CHILD_ID_6 (6) #define CHILD_INDEX_7 (7) #define CHILD_COUNT_8 (8) #define CH_INPUT_ID_9 (9) #define CH_OUTPUT_ID_10 (10) #define CH_LAST_UPDATED_11 (11) #define AVERAGE_12 (12) #define SAMPLE_13 (13) #define AUX_A_X_14 (14) #define AUX_A_Y_15 (15) #define AUX_A_Z_16 (16) #define AUX_B_X_17 (17) #define AUX_B_Y_18 (18) #define AUX_B_Z_19 (19) #define COLOR_SHIFT_20 (20) #define ROTATE_VEC_X_21 (21) #define ROTATE_VEC_Y_22 (22) #define ROTATE_VEC_Z_23 (23) #define ROTATE_VEC_S_24 (24) #define SCALE_X_25 (25) #define SCALE_Y_26 (26) #define SCALE_Z_27 (27) #define TRANSLATE_X_28 (28) #define TRANSLATE_Y_29 (29) #define TRANSLATE_Z_30 (30) #define TAG_OFFSET_X_31 (31) #define TAG_OFFSET_Y_32 (32) #define TAG_OFFSET_Z_33 (33) #define ROTATE_RATE_X_34 (34) #define ROTATE_RATE_Y_35 (35) #define ROTATE_RATE_Z_36 (36) #define ROTATE_X_37 (37) #define ROTATE_Y_38 (38) #define ROTATE_Z_39 (39) #define SCALE_RATE_X_40 (40) #define SCALE_RATE_Y_41 (41) #define SCALE_RATE_Z_42 (42) #define TRANSLATE_RATE_X_43 (43) #define TRANSLATE_RATE_X_44 (44) #define TRANSLATE_RATE_X_45 (45) #define TRANSLATE_VEC_X_46 (46) #define TRANSLATE_VEC_X_47 (47) #define TRANSLATE_VEC_X_48 (48) #define SHADER_49 (49) #define GEOMETRY_50 (50) #define LINE_WIDTH_51 (51) #define POINT_SIZE_52 (52) #define RATIO_53 (53) #define COLOR_INDEX_54 (54) #define COLOR_R_55 (55) #define COLOR_G_56 (56) #define COLOR_B_57 (57) #define COLOR_A_58 (58) #define COLOR_FADE_59 (59) #define TEXTURE_ID_60 (60) #define HIDE_61 (61) #define FREEZE_62 (62) #define TOPO_63 (63) #define FACET_64 (64) #define AUTO_ZOOM_X_65 (65) #define AUTO_ZOOM_Y_66 (66) #define AUTO_ZOOM_Z_67 (67) #define TRIGGER_HI_X_68 (68) #define TRIGGER_HI_Y_69 (69) #define TRIGGER_HI_Z_70 (70) #define TRIGGER_LO_X_71 (71) #define TRIGGER_LO_Y_72 (72) #define TRIGGER_LO_Z_73 (73) #define SET_HI_X_74 (74) #define SET_HI_X_75 (75) #define SET_HI_X_76 (76) #define SET_LO_X_77 (77) #define SET_LO_Y_78 (78) #define SET_LO_Z_79 (79) #define PROXIMITY_X_80 (80) #define PROXIMITY_Y_81 (81) #define PROXIMITY_Z_82 (82) #define PROXIMITY_MODE_X_85 (83) #define PROXIMITY_MODE_Y_85 (84) #define PROXIMITY_MODE_Z_85 (85) #define SEGMENTS_X_86 (86) #define SEGMENTS_Y_87 (87) #define SEGMENTS_Z_88 (88) #define TAG_MODE_89 (89) #define FORMAT_ID_90 (90) #define TABLE_ID_91 (91) #define RECORD_ID_92 (92) #define SIZE_93 (93) /* flag-settable parameters (global variables) */ int Debug; /* Boolean: TRUE = debug writes */ char GlyphFile[MAX_LINE]; /* glyph file name */ /* global vars used by glyph_tools */ int FirstGoodLine; int First_id; float Glyph_array[NUM_COLUMNS][MAX_GLYPH_ROWS]; -------------------------------------------------- Makefile -------------------------------------------------- O_FILES = glyph_factory.o glyph_tools.o print_CSV_line.o usage.o help.o CFLAGS = -lc -g -lm CC = gcc glyph_factory: $(O_FILES) $(CC) $(CFLAGS) -o glyph_factory.exe $(O_FILES) -------------------------------------------------- Test -------------------------------------------------- # dest=/cygdrive/c/Users/Alan/Antz2014/antz_msw_2013-11-21/usr/csv # cp cities.txt test_data9.txt awk 'BEGIN{FS=",";OFS=",";} {print $1,$2,$3,$4,$5,$6,$7}' cities.txt > test_data7.txt # cp test_data7.txt test_data.csv # ./Rscript > data_stats.txt # cp glyph1.csv file1.txt cp glyph2.csv file2.txt # python ~/swdev/Python/glyph_diff/glyph_diff.py 5 4 > glyph_diff.txt # cp file1.txt glyph_in.csv # cp test_data9.txt test_data.csv # # uncomment this to test breaking the DIFF below # # head -3 test_data9.txt > test_data.csv ./glyph_factory.exe -c 9 -l 4 -R 2 -t -w 0 -G glyph_in.csv -g `wc -l glyph_in.csv` -n `wc -l test_data.csv` < test_data.csv > test_body.csv # cat head.csv test_body.csv > test_out.csv # cp test_out.csv ${dest} cp test_out.csv ANTz0001.csv cp ANTz0001.csv ${dest} cp ANTzTag0001.csv ${dest} cp glyph1.csv ${dest} cp glyph2.csv ${dest} # echo HERE IS THE DIFF: diff ANTz0001.csv ANTz0001_good.csv -------------------------------------------------- data_stats.txt -------------------------------------------------- 1,-90.000000,90.000000,Lat 2,-180.000000,180.000000,Lon 3,1388308.000000,10413386.000000,Pop 4,119.860000,1098.400000,Size 5,-250.000000,1898.000000,Year 6,130000.000000,389000.000000,Millionaires 7,1.000000,2.000000,R_groups -------------------------------------------------- glyph_diff.txt -------------------------------------------------- 7,29:-180.000000,180.000000 7,30:-90.000000,90.000000 9,26:0.320000,1.140000 9,27:0.320000,1.140000 9,28:0.320000,1.140000 9,55:0.000000,2.000000 9,56:50.000000,255.000000 9,57:101.000000,0.000000 9,58:101.000000,0.000000 10,26:0.320000,1.140000 10,27:0.320000,1.140000 10,28:0.320000,1.140000 10,55:0.000000,2.000000 10,56:50.000000,255.000000 10,57:101.000000,0.000000 10,58:101.000000,0.000000 11,26:0.320000,1.140000 11,27:0.320000,1.140000 11,28:0.320000,1.140000 11,55:0.000000,2.000000 11,56:50.000000,255.000000 11,57:101.000000,0.000000 11,58:101.000000,0.000000 12,26:0.320000,1.140000 12,27:0.320000,1.140000 12,28:0.320000,1.140000 12,55:0.000000,2.000000 12,56:50.000000,255.000000 12,57:101.000000,0.000000 12,58:101.000000,0.000000 13,26:0.320000,1.140000 13,27:0.320000,1.140000 13,28:0.320000,1.140000 13,55:0.000000,2.000000 13,56:50.000000,255.000000 13,57:101.000000,0.000000 13,58:101.000000,0.000000 14,26:0.320000,1.140000 14,27:0.320000,1.140000 14,28:0.320000,1.140000 14,55:0.000000,2.000000 14,56:50.000000,255.000000 14,57:101.000000,0.000000 14,58:101.000000,0.000000 -------------------------------------------------- mapper.txt -------------------------------------------------- 7,29:2 7,30:1 9,26:3 9,27:3 9,28:3 9,55:3 9,56:3 9,57:3 9,58:3 10,26:4 10,27:4 10,28:4 10,55:4 10,56:4 10,57:4 10,58:4 11,26:5 11,27:5 11,28:5 11,55:5 11,56:5 11,57:5 11,58:5 12,26:6 12,27:6 12,28:6 12,55:6 12,56:6 12,57:6 12,58:6 13,26:7 13,27:7 13,28:7 13,55:7 13,56:7 13,57:7 13,58:7 14,26:8 14,27:8 14,28:8 14,55:8 14,56:8 14,57:8 14,58:8 -------------------------------------------------- types.txt -------------------------------------------------- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 -------------------------------------------------- cities.txt -------------------------------------------------- Lat,Lon,Pop,Size,Year,Millionaires,R_groups,Name,Nickname 40.7127,-74.0059,8405837,468.5,1898,389000,2,New_York_City,Big_Apple 48.8567,2.3508,10413386,1098.4,-250,219000,2,Paris,Lity_of_Light 51.507222,-0.1275,8308369,606.95,43,281000,1,London,London_Town 48.133333,11.566667,1388308,119.86,1158,130000,1,Munich,Munchen -90,-180,1388308,119.86,1158,130000,1,SW,SouthWest 90,180,1388308,119.86,1158,130000,1,NE,NorthEast -------------------------------------------------- links.txt -------------------------------------------------- 1,2,0.10,255,0,0,link_1_to_2 2,3,0.15,0,255,0,link_2_to_3 3,4,0.20,0,0,255,link_3_to_4 4,1,0.25,255,255,0,link_4_to_1 -------------------------------------------------- glyph1.csv -------------------------------------------------- id,type,data,selected,parent_id,branch_level,child_id,child_index,child_count,ch_input_id,ch_output_id,ch_last_updated,average,sample,aux_a_x,aux_a_y,aux_a_z,aux_b_x,aux_b_y,aux_b_z,color_shift,rotate_vec_x,rotate_vec_y,rotate_vec_z,rotate_vec_s,scale_x,scale_y,scale_z,translate_x,translate_y,translate_z,tag_offset_x,tag_offset_y,tag_offset_z,rotate_rate_x,rotate_rate_y,rotate_rate_z,rotate_x,rotate_y,rotate_z,scale_rate_x,scale_rate_y,scale_rate_z,translate_rate_x,translate_rate_y,translate_rate_z,translate_vec_x,translate_vec_y,translate_vec_z,shader,geometry,line_width,point_size,ratio,color_index,color_r,color_g,color_b,color_a,color_fade,texture_id,hide,freeze,topo,facet,auto_zoom_x,auto_zoom_y,auto_zoom_z,trigger_hi_x,trigger_hi_y,trigger_hi_z,trigger_lo_x,trigger_lo_y,trigger_lo_z,set_hi_x,set_hi_y,set_hi_z,set_lo_x,set_lo_y,set_lo_z,proximity_x,proximity_y,proximity_z,proximity_mode_x,proximity_mode_y,proximity_mode_z,segments_x,segments_y,segments_z,tag_mode,format_id,table_id,record_id,size 1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0.1,0,50,101,101,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 2,1,2,0,0,0,0,2,3,0,0,0,0,1,0,0,0,0,0,0,0,0,0.158972,0.22353,-0.961646,1,1,1,-1.422125,-0.499645,13.602648,0,0,0,0,0,0,15.920006,35.420013,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0.1,0,50,101,101,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.945756,0,0,0,0,0,16,16,0,0,0,0,0,420 3,1,3,0,2,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,-1,1,1,1,-0.5,0,571.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0.1,0,50,101,101,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 4,1,4,0,2,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,-90,7,0,0,0,0,0,0,90,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0.1,0,50,101,101,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 5,1,5,0,2,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,-1,0,0,1,1,1,85,0,7,0,0,0,0,0,0,90,270,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0.1,0,50,101,101,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 6,6,6,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0.1,3,0,0,255,150,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,420 32,5,32,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,-180,-90,0,0,0,5.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,1,0,0.1,0,50,101,101,255,0,0,0,0,5,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 33,5,33,0,32,1,0,5,6,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,0,50,101,101,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 34,5,34,1,33,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0.32,0.32,0.32,0,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,0,50,101,101,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 35,5,35,1,33,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0.32,0.32,0.32,-15,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,0,50,101,101,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 36,5,36,1,33,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0.32,0.32,0.32,-30,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,0,50,101,101,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 37,5,37,1,33,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0.32,0.32,0.32,-45,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,0,50,101,101,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 38,5,38,1,33,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0.32,0.32,0.32,-60,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,0,50,101,101,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 39,5,39,1,33,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0.32,0.32,0.32,-75,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,0,50,101,101,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 -------------------------------------------------- glyph2.csv -------------------------------------------------- id,type,data,selected,parent_id,branch_level,child_id,child_index,child_count,ch_input_id,ch_output_id,ch_last_updated,average,sample,aux_a_x,aux_a_y,aux_a_z,aux_b_x,aux_b_y,aux_b_z,color_shift,rotate_vec_x,rotate_vec_y,rotate_vec_z,rotate_vec_s,scale_x,scale_y,scale_z,translate_x,translate_y,translate_z,tag_offset_x,tag_offset_y,tag_offset_z,rotate_rate_x,rotate_rate_y,rotate_rate_z,rotate_x,rotate_y,rotate_z,scale_rate_x,scale_rate_y,scale_rate_z,translate_rate_x,translate_rate_y,translate_rate_z,translate_vec_x,translate_vec_y,translate_vec_z,shader,geometry,line_width,point_size,ratio,color_index,color_r,color_g,color_b,color_a,color_fade,texture_id,hide,freeze,topo,facet,auto_zoom_x,auto_zoom_y,auto_zoom_z,trigger_hi_x,trigger_hi_y,trigger_hi_z,trigger_lo_x,trigger_lo_y,trigger_lo_z,set_hi_x,set_hi_y,set_hi_z,set_lo_x,set_lo_y,set_lo_z,proximity_x,proximity_y,proximity_z,proximity_mode_x,proximity_mode_y,proximity_mode_z,segments_x,segments_y,segments_z,tag_mode,format_id,table_id,record_id,size 1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0.1,0,50,101,101,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 2,1,2,0,0,0,0,2,3,0,0,0,0,1,0,0,0,0,0,0,0,0,0.213611,0.197668,-0.956712,1,1,1,-1.910913,-0.268285,13.558512,0,0,0,0,0,0,16.920008,47.220005,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0.1,0,50,101,101,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8.945756,0,0,0,0,0,16,16,0,0,0,0,0,420 3,1,3,0,2,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,-1,1,1,1,-0.5,0,571.75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0.1,0,50,101,101,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 4,1,4,0,2,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,-90,7,0,0,0,0,0,0,90,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0.1,0,50,101,101,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 5,1,5,0,2,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,-1,0,0,1,1,1,85,0,7,0,0,0,0,0,0,90,270,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0.1,0,50,101,101,255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 6,6,6,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0.1,3,0,0,255,150,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,420 32,5,32,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,180,90,0,0,0,5.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,1,0,0.1,0,50,101,101,255,0,0,0,0,5,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 33,5,33,0,32,1,0,5,6,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,0,50,101,101,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 34,5,34,1,33,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1.14,1.14,1.14,0,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,2,255,0,0,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 35,5,35,1,33,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1.14,1.14,1.14,-15,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,2,255,0,0,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 36,5,36,1,33,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1.14,1.14,1.14,-30,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,2,255,0,0,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 37,5,37,1,33,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1.14,1.14,1.14,-45,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,2,255,0,0,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 38,5,38,1,33,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1.14,1.14,1.14,-60,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,2,255,0,0,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 39,5,39,1,33,2,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1.14,1.14,1.14,-75,0,0,0,1.5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,1,0,0.1,2,255,0,0,255,0,0,0,0,3,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,16,16,0,0,0,0,0,420 --------------------------------------------------