-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathbrewcolors.ado
480 lines (329 loc) · 14.2 KB
/
brewcolors.ado
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
********************************************************************************
* Description of the Program - *
* This program is used to download/install additional color references. The *
* program either builds/installs additional colors into Stata, or will build *
* lookup tables used to transform the RGB colorspace to colors that represent *
* how the graph would be viewed by someone with one of the three types of *
* colorblindness. This can be helpful for proofing graphs prior to publishing *
* as a quality assurance/quality control method to ensure the graph can be *
* viewed and interpretted correctly by the widest audience possible. *
* *
* Data Requirements - *
* none *
* *
* System Requirements - *
* Gunzip *
* *
* Program Output - *
* *
* Lines - *
* 479 *
* *
********************************************************************************
*! brewcolors
*! v 1.0.4
*! 03AUG2018
// Drop the program from memory if loaded
cap prog drop brewcolors
// Define new program
prog def brewcolors, rclass
// Version number specification
version 13.1
// Syntax for program (make adds to color DB, install install's colors)
syntax anything(name = source) [, MAke INSTall COLors(string asis) ///
REPlace OVERride ]
// Check for brewscheme Mata library
qui: brewlibcheck
// Check for any optional arguments to add a comma to the command string
if `"`make'`install'`colors'"' == "" loc optstring ","
// Build local macro with the command string
loc cmdstring brewcolors `source'`optstring' `make' `install' ///
colors(`colors') `replace' `override'
// Preserve current state of the data
preserve
// Clear any data from memory
clear
// Check for/build directory
dirfile `c(sysdir_personal)', p(style)
// Check for/build directory
dirfile `c(sysdir_personal)', p(brewcolors)
// Make sure source is valid
if `"`source'"' == "xkcd" {
// Load and parse the xkcd data
xkcd, `make' `install' colors(`colors') `replace' cmd(`cmdstring') `override'
// Loop over each of the return name macros
foreach nm in `r(colnms)' {
// Return the individual color name/RGB
ret loc `nm' `r(`nm')'
} // End Loop over returned values
} // End else block for invalid source argument
// If colorblind argument is passed
else if `"`source'"' == "new" {
// Call color blind routine
colorinstaller, `make' `install' colors(`colors') `replace' cmd(`cmdstring') `override'
// Return the sub routine's return value
ret loc colorpath `r(colorpath)'
} // End ELSE IF Block for the argument new passed to the program
// Restore data to original state
restore
// End program
end
// Drop program if previously loaded in memory
cap prog drop colorinstaller
// Sub routine for user defined named colors
prog def colorinstaller, rclass
// Syntax for sub routine
syntax, colors(string asis) [ make install cmd(passthru) replace override ]
// Set the number of observations
qui: set obs `: word count `colors''
// Create palette and RGB string variables
qui: g palette = ""
qui: g str11 rgb = ""
// Loop over arguments passed in the color string
forv i = 1/`: word count `colors'' {
// Get the word string
loc wrd `: word `i' of `colors''
// Tokenizes the color string argument
gettoken palname rgb : wrd
// If 4 total tokens assume the rgb token contains the rgb color string
if `: word count `rgb'' == 3 loc colorstring `rgb'
// If only 3 tokens in total, assume no name and construct palette name/
// color string macros
else if `: word count `rgb'' == 2 {
loc colorstring `palname' `: word 1 of `rgb'' `: word 2 of `rgb''
loc palname udc`palname'_`: word 1 of `rgb''_`: word 2 of `rgb''
} // End ELSEIF Block for no user specified name
// Create a meta string
loc metastring "User Defined Color - "
// Generate the palette name
qui: replace palette = "`palname'"'
// Generate the rgb value
qui: replace rgb = "`colorstring'"
// Generate the rest of the variables
brewcolorvars, meta(`"`metastring'"' + palette) colorb `cmd'
} // End Loop over color arguments
// Check install option
if `"`install'"' != "" {
// Loop over records
forv i = 1/`: word count `colors'' {
// Store filename in local macro
loc fname `"`c(sysdir_personal)'style/color-`palname'.style"'
// Create new file wit the color definition
qui: file open newcolor using `"`fname'"', w replace
// Write a version number
qui: file write newcolor `"*! v 0.0.0 `c(current_date)' `c(current_time)'"' _n
// Write color attribution
qui: file write newcolor `"*! Color defined by the user: `c(username)'"' _n
// Add a sequence ID to the file
qui: file write newcolor `"sequence `: di seqid[`i']'"' _n
// Write the color name
qui: file write newcolor `"label "`: di meta[`i']'""' _n(2)
// Write the color definition to the file
qui: file write newcolor `"set rgb "`: di rgb[`i']'""' _n(2)
// Close the file
qui: file close newcolor
} // End Loop over records
} // End IF Block for color installation
// Check for make option
if `"`make'"' != "" {
// Save the dataset with the colors
qui: save `"`c(sysdir_personal)'brewcolors/colorsBy`c(username)'.dta"', replace
brewColorMaker `c(sysdir_personal)'brewcolors/colorsBy`c(username)'.dta, `replace' `override'
// Return the file path for the colors created by the user
ret loc colorpath `"`c(sysdir_personal)'brewcolors/colorsBy`c(username)'.dta"'
} // End IF Block to make the color file
// End of subroutine definition
end
// Drop program if previously loaded in memory
cap prog drop xkcd
// Define sub-routine to get xkcd named color list
prog def xkcd, rclass
// Define syntax
syntax [, make install colors(string asis) replace cmd(passthru) override ]
// For the xkcd colors
import delimited using "https://xkcd.com/color/rgb.txt", delim("#") clear
// Get the licensing attribution
loc license "`: di v2[1]'"
// Drop first record with licensing data
qui: drop in 1
// Make sure all letters are lowercased
qui: replace v2 = lower(v2)
// Remove unnecessary words from color/palette names
qui: replace v1 = subinstr(v1, `"'"', "", .)
qui: replace v1 = subinstr(v1, "and ", "", .)
qui: replace v1 = subinstr(v1, "/", "", .)
// Sort Colors alphabetically
qui: sort v1
// Add XKCD Ref to meta
qui: replace v1 = "XKCD - " + proper(v1)
// Replace spaces in color names with underscores
qui: g palette = _n
qui: tostring palette, replace
qui: replace palette = "xkcd" + palette
// Get length of palette name string
qui: g x = length(v1)
// Drop the random character at the end of the color name that won't disappear otherwise
qui: replace v1 = substr(v1, 1, x - 1)
// Convert colors from Hexadecimal to decimal RGB values
hextorgb, hex(v2)
// Compress data
qui: compress
// Drop variables that are no longer used
qui: drop v2 x
// Null local macro to return all color names
loc retnames
// Generate sequence ID number
qui: g tmpid = 6999 + _n
// Loop over observations
forv i = 1/949 {
// Check installation option
if "`install'" != "" {
// Store color name
loc thecolorname `: di palette[`i']'
// Check to see if it is a color the user wants to install or all
if (`: list thecolorname in colors' == 1 | "`install'" != "" | ///
`"`colors'"' == "all") {
// Build local macros to return to the user
ret loc `thecolorname' `"`: di rgb[`i']'"'
// Update return names
loc retnames `retnames' `thecolorname'
// Store filename in local macro
loc fname `"`c(sysdir_personal)'style/color-`thecolorname'.style"'
// Create new file wit the color definition
qui: file open newcolor using `"`fname'"', w replace
// Write the license info into the first line
qui: file write newcolor `"*! `: subinstr loc license `"#"' "", all'"' _n
// Write a version number
qui: file write newcolor `"*! v 0.0.0 `c(current_date)' `c(current_time)'"' _n
// Write color attribution
qui: file write newcolor `"*! Color names from XKCD.com survey (http://blog.xkcd.com/2010/05/03/color-survey-results/)"' _n
// Add a sequence ID to the file
qui: file write newcolor `"sequence `: di tmpid[`i']'"' _n
// Write the color name
qui: file write newcolor `"label "`: di v1[`i']'""' _n(2)
// Write the color definition to the file
qui: file write newcolor `"set rgb "`: di rgb[`i']'""' _n(2)
// Close the file
qui: file close newcolor
} // End IF Block for installable colors
// If not installed skip to next iteration
else continue
} // End IF Block to install xkcd colors
} // End Loop to return values
// Return the local with the return names
ret loc colnms `retnames'
// Create required variables
qui: brewcolorvars, meta(v1) colorb `cmd' seqid(palette + strofreal(tmpid))
// Drop variables that are no longer needed
qui: drop v1 tmpid
// Save the dataset
qui: save `"`c(sysdir_personal)'brewcolors/brewxkcd.dta"', replace
// Check make option
if `"`make'"' != "" brewColorMaker `c(sysdir_personal)'brewcolors/brewxkcd.dta, `replace' `override'
// End of program
end
// Drop program if previously loaded in memory
cap prog drop brewcolorvars
// Defines subroutine for adding standard variables for color definitions
prog def brewcolorvars
// Define syntax structure
syntax [, seqid(string asis) meta(string asis) COLORBlindvars cmd(string asis) ]
// Check for palette name and RGB string variables
cap confirm v rgb palette
// If these variables do not exist throw an error and exit
if _rc != 0 {
// Print error message for user
di as err "The brewcolorvars subroutine called by `cmd' requires " ///
"the variables palette (color/palette name) and rgb (the Stata " ///
"formatted RGB string) to be present in the dataset currently in " ///
"memory."
// Error code
err 198
} // End IF Block for bad data
// Check for colorblindvars parameter
if `"`colorblindvars'"' != "" {
// Set the macro with the names of the color blind variables for sorting
loc colorblindvars achromatopsia protanopia deuteranopia tritanopia
// Generate color blindness variables
qui: brewtransform rgb
} // End IF Block for color blindness variables
// Add variables to existing file
foreach v in colorblind lcd photocopy print {
// Check if variable already exists
cap confirm v `v'
// Initialize variables w/extended missing values
if _rc != 0 qui: g `v' = .n
else qui: replace `v' = .n
} // End Loop for meta variables
// Add id variables
foreach v in pcolor colorid maxcolors {
// Add variables used for IDs
qui: g `v' = 1
} // End Loop over ID variables
// Check for sequence ID argument
if `"`seqid'"' != "" {
// Create a sequence ID variable
qui: g seqid = `seqid'
} // End IF Block for user specified sequence id
// If no argument passed
else {
// Generic sequence ID
qui: g seqid = palette + strofreal(pcolor) + strofreal(colorid)
} // End ELSE Block for no sequence ID argument
// Check if meta is a variable or string
cap confirm v `meta'
// If argument is a variable generate the meta variable from the variable passed
qui: g meta = `meta'
// Specify the display order of the variables
order palette colorblind print photocopy lcd colorid pcolor rgb ///
maxcolors seqid meta `colorblindvars'
// Variable labels
la var palette "Name of Color Palette"
la var colorblind "Colorblind Indicator"
la var print "Print Indicator"
la var photocopy "Photocopy Indicator"
la var lcd "LCD/Laptop Indicator"
la var colorid "Within pcolor ID for individual color look ups"
la var pcolor "Palette by Colors Selected ID"
la var rgb "Red-Green-Blue Values to Build Scheme Files"
la var maxcolors "Maximum number of colors allowed for the palette"
la var seqid "Sequential ID for property lookups"
la var meta "Meta-Data Palette Characteristics (see char _meta[*] for more info)"
la var achromatopsia "Achromatopsic Vision RGB Transformed Equivalent"
la var protanopia "Protanopic Vision RGB Transformed Equivalent"
la var deuteranopia "Deuteranopic Vision RGB Transformed Equivalent"
la var tritanopia "Tritanopic Vision RGB Transformed Equivalent"
// End of subroutine definition
end
// Drop program if previously loaded in memory
cap prog drop brewColorMaker
// Define program
prog def brewColorMaker
// Syntax
syntax anything(name = filename id = "Colors to install") [, replace override ]
// Append to existing colordb if it exists
cap confirm new file `"`c(sysdir_personal)'brewcolors/colordb.dta"'
// If file does not exist
if _rc == 0 | `"`replace'"' != "" {
// Call the color database program
brewcolordb, `replace' `override'
// Load colordb file
qui: use `"`c(sysdir_personal)'brewcolors/colordb.dta"', clear
// Append existing data
qui: append using `"`filename'"'
// Drop any duplicate color references
qui: duplicates drop
// Save data as first instance of colordb
qui: save `"`c(sysdir_personal)'brewcolors/colordb.dta"', replace
} // End ELSE Block for non-existent color database
// If file exists
else {
// Append existing data
qui: append using `"`c(sysdir_personal)'brewcolors/colordb.dta"'
// Drop any duplicate color references
qui: duplicates drop
// Save over file
qui: save `"`c(sysdir_personal)'brewcolors/colordb.dta"', replace
} // End IF Block for existing color database
// End of program definition
end