-
Notifications
You must be signed in to change notification settings - Fork 9
/
brewcolordb.ado
337 lines (230 loc) · 9.81 KB
/
brewcolordb.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
********************************************************************************
* Description of the Program - *
* This program is used to build a dataset with the names and RGB values of all *
* color styles defined by Stata that are part of the base installation of the *
* program. It will be used when proofing graphs from the perspective of *
* different forms of color blindness. *
* *
* Program Output - *
* *
* Lines - *
* 333 *
* *
********************************************************************************
*! brewcolordb
*! v 1.0.3
*! 09NOV2016
// Drop the program from memory if loaded
cap prog drop brewcolordb
// Define a program
prog def brewcolordb, rclass
// Version of Stata that should be used to interpret the code
version 13.1
// Defines syntax structure of program
syntax [, DISplay REPlace OVERride]
if `"`override'"' == "" {
// Print warning message
di as res "This program needs to clear all data currently in memory. " ///
"If this is ok hit enter, otherwise enter the letter 'n' and hit enter " ///
"to exit the program without clearing data from memory." _request(_perm)
// Check response
if lower(`"`perm'"') == "n" exit
// Or clear data from memory
else clear
} // End IF BLOCK for no override option
// Clear data from memory
else clear
// Store the name of the personal subdirectory
loc personal `c(sysdir_personal)'
// Check to see if the personal ADOPATH directory exists
qui: dirfile `: subinstr loc personal "personal/" "", all', p(personal)
// Set the rebuild parameter conditional on the replace argument
if `"`replace'"' != "" loc rebuild rebuild
// Remove tilde and replace with HOME environmental variable for color db subdirectory
qui: dirfile `c(sysdir_personal)', p(brewcolors) `rebuild'
// Remove tilde and replace with HOME environmental variable for color db subdirectory
qui: dirfile `c(sysdir_personal)', p(style) `rebuild'
// Check for file
cap confirm new file `"`c(sysdir_personal)'brewcolors/colordb.dta"'
// If file does not exist or replace option passed
if _rc == 0 | `"`replace'"' != "" {
// Get list of color style file names
loc colors `: dir `"`c(sysdir_base)'/style/"' files "color*.style", respect'
// Clean up the file names
loc colors : list clean colors
// Remove quotation marks from color file names
loc colors `: subinstr loc colors `"""' "", all'
// Set observations
qui: set obs 2
// Create entry for color black
qui: g id = "black"
// Create RGB balues for color black
qui: g v1 = cond(_n == 1, "sequence 1", "0 0 0")
// Loop over the list of files
forv i = 1/`: word count `colors'' {
// Keep the current data preserved in memory
preserve
// Get the color style file name
loc name `: word `i' of `colors''
// Load the color style file into memory
qui: insheet using `"`c(sysdir_base)'style/`name'"', clear
// Get the color name
getColorName `name'
// Use the color name for the ID field
qui: g id = "`r(colorname)'"
// Reserve space for a temp file in memory
tempfile `i'
// Save the current data set in the tempfile reserved above
qui: save ``i''.dta, replace
// Restore memory to previous state (e.g., first color style file)
restore
// Append this color style to the existing data set
qui: append using ``i''.dta
} // End Loop over the color style files
// Generate a file id (row number)
qui: g fileid = _n
// Count the number of lines per file
qui: bys id (fileid): g lines = _N
// Create a row id for the lines from each color style file
qui: bys id (fileid): g linenum = _n
// Get the sequence number
qui: g seqid = v1 if regexm(v1, "^sequence") == 1
// Remove the word sequence
qui: replace seqid = trim(itrim(subinstr(seqid, "sequence ", "", .)))
// Make the sequence ID variable numeric
qui: destring seqid, replace
// Carry the value for the rest of the color
bys id (fileid): replace seqid = seqid[_n -1] if mi(seqid)
// Keep only the records that contain the RGB values
qui: keep if lines == linenum
// Replace the value for the color style none
qui: replace v1 = "" if id == "none"
// Rename v1 to something more informative
rename v1 rgb
// Check display option
if `"`display'"' != "" {
// Write the table header
di as text _dup(80) `"_"' _n _skip(10) "Color Name" _skip(10) ///
"RGB" _n _dup(80) "_" _n
} // End If Block for Display Header
// Loop over the observations
forv v = 1/`: word count `colors'' {
// Check display option
if `"`display'"' != "" {
// Print the data to the screen
di as res _skip(10) id[`v'] _col(30) rgb[`v']
} // End IF Block for display option
// Return the color value in the name of the color
ret loc `: di id[`v']' `"`: di rgb[`v']'"'
} // End Loop
// Check display option
if `"`display'"' != "" {
// Add footer
di as text _dup(80) "_"
} // End IF Block for display option
// Set the display order of the variables
order id rgb
// Keep only the needed variables
qui: keep id rgb seqid
// Clean up rgb values
qui: replace rgb = trim(itrim(rgb))
// Rename variable
qui: rename id palette
// Make sequence ID string
qui: tostring seqid, replace
// Make sequence ID follow logic used for rest of suite
qui: replace seqid = palette + seqid
// Generate meta data fields
foreach v in colorblind print lcd photocopy {
// Generate variables with null values
qui: g `v' = .n
} // End Loop over meta properties
// Generate a meta data field
qui: g meta = "Stata"
// Create a max colors value
qui: g maxcolors = 1
// Create colorid
qui: g colorid = 1
// Create palette ID
qui: g pcolor = 1
// Add metadata
la var palette "Name of Stata Colorstyle"
la var rgb "RGB Value of Stata Colorstyle"
// Optimize data storage
qui: compress
// Drop any duplicate values
qui: duplicates drop
// Translate colorblind equivalent RGB values
qui: brewtransform rgb
// Loop over value variables
foreach v of var rgb achromatopsia protanopia deuteranopia ///
tritanopia {
// Replace the value for the color style none
qui: replace `v' = "none" if palette == "none"
// Make sure black and white are constant
qui: replace `v' = "0 0 0" if palette == "black"
qui: replace `v' = "255 255 255" if palette == "white"
} // End of loop over value columns
// Save to the brewscheme created directories
qui: save `"`c(sysdir_personal)'brewcolors/colordb.dta"', replace
// Loop over records
forv i = 1/`c(N)' {
// open new files for named colors
loc rootnm `: di palette[`i']'
// Store filename in local macro
loc styleroot `"`c(sysdir_personal)'style/color-"'
// Create new file wit the color definition
qui: file open achrom using `"`styleroot'`rootnm'_achromatopsia.style"', w replace
// Create new file wit the color definition
qui: file open protan using `"`styleroot'`rootnm'_protanopia.style"', w replace
// Create new file wit the color definition
qui: file open deuter using `"`styleroot'`rootnm'_deuteranopia.style"', w replace
// Create new file wit the color definition
qui: file open tritan using `"`styleroot'`rootnm'_tritanopia.style"', w replace
// Loop over the file connections
foreach fnm in achrom protan deuter tritan {
// Write a version number
qui: file write `fnm' `"*! v 0.0.0 `c(current_date)' `c(current_time)'"' _n
// Write color attribution
qui: file write `fnm' `"*! Color defined by the user: `c(username)'"' _n
// Add a sequence ID to the file
qui: file write `fnm' `"sequence `: di seqid[`i']'"' _n
} // End Loop over Stata defined colors
// Write the color name
qui: file write achrom `"label "`rootnm'_achromatopsia""' _n(2)
qui: file write protan `"label "`rootnm'_protanopia""' _n(2)
qui: file write deuter `"label "`rootnm'_deuteranopia""' _n(2)
qui: file write tritan `"label "`rootnm'_tritanopia""' _n(2)
// Write the color definition to the file
qui: file write achrom `"set rgb "`: di achromatopsia[`i']'""' _n(2)
qui: file write protan `"set rgb "`: di protanopia[`i']'""' _n(2)
qui: file write deuter `"set rgb "`: di deuteranopia[`i']'""' _n(2)
qui: file write tritan `"set rgb "`: di tritanopia[`i']'""' _n(2)
// Close the file
qui: file close achrom
qui: file close protan
qui: file close deuter
qui: file close tritan
} // End Loop over records
} // End IF Block for case where replace option is passed or file does not exist
// Otherwise
else {
// Print message to console
di as res `"The file "' ///
`"`c(sysdir_personal)'brewcolors/colordb.dta already exists "' ///
`"and will not be overwritten"'
} // End ELSE Block for existing file without overwrite
// end of program
end
// Utility subroutine to parse the color name from a color style file name
prog def getColorName, rclass
// Accepts only single mandatory argument of the color style file name
syntax anything(name = cfname id = "Color style file name")
// Remove the opening of the color style file name
loc cname `: subinstr loc cfname `"color-"' "", all'
// Remove the file extension
loc cname `: subinstr loc cname `".style"' "", all'
// Return the value
ret loc colorname `cname'
// End of subroutine
end