Coverage for src/colorspace/demos.py: 100%

270 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-10-29 15:11 +0000

1 

2def demoplot(colors, type_, n = 7, ax = None, **kwargs): 

3 """Create Demo Plots 

4 

5 This function is intended to be used by the GUI 

6 (:py:func:`choose_palette <colorspace.choose_palette.choose_palette>`) 

7 to visualize the color palette selected for a series of different 

8 types of plots. It can, however, also be used directly if needed. 

9 

10 

11 Arguments: 

12 colors: The colors, any type which can be handled by  

13 :py:func:`palette <colorspace.palettes.palette>`. 

14 type_ (str): Name of the demo function to be called. 

15 Not case sensitive. 

16 n (int): Number of colors for the plot. Only used if argument `colors` 

17 is a palette where a dedicated number of colors must be drawn first. 

18 Defaults to 7. 

19 title (None, str): used to draw the figure title, if specified (str). 

20 Forwarded to different plot types. 

21 ax (None, matplotlib.axes.Axes): If `None` a new matplotlib figure will 

22 be created. If `ax` inherits from `matplotlib.axes.Axes` this object 

23 will be used to create the demoplot. Handy to create multiple subplots. 

24 Forwarded to different plot types. 

25 **kwargs: Forwarded to the corresponding demo plot functions. 

26 

27 Examples: 

28 

29 >>> # Importing modules 

30 >>> from colorspace import * 

31 >>> from colorspace.colorlib import * 

32 >>> 

33 >>> # Custom list of hex colors (n = 5) 

34 >>> hexlist = ["#BCBE57", "#DEDFC0", "#F1F1F1", "#F7D3E7", "#FB99D7"] 

35 >>> hexlist 

36 >>> #: A (HCL based) colorobject with (n = 3) 

37 >>> colorobj = HCL([0, 90, 180], [60, 60, 60], [60, 60, 60]) 

38 >>> colorobj 

39 >>> #: Default diverging HCL palette 

40 >>> hclpalette = diverging_hcl() 

41 >>> hclpalette 

42 >>> #: Default color palette shipped with the package 

43 >>> berlin = hcl_palettes(name = "Berlin").get_palettes()[0] 

44 >>> berlin 

45 >>> #: Demoplots 

46 >>> demoplot(hexlist, "Bar"); 

47 >>> #: 

48 >>> demoplot(colorobj, "Lines"); 

49 >>> #: 

50 >>> demoplot(hclpalette, "Pie", n = 4); 

51 >>> #: 

52 >>> demoplot(berlin.colors(), "Matrix", n = 11); 

53 >>> 

54 >>> #: Using custom subplots and plot titles 

55 >>> from matplotlib import pyplot as plt 

56 >>> from colorspace import protan, deutan, desaturate 

57 >>> fig, axes = plt.subplots(2, 2) 

58 >>> colors = diverging_hcl("Green-Orange").colors(7) 

59 >>> demoplot(colors, "Bar", 

60 >>> title = "Original", ax = axes[0, 0]); 

61 >>> demoplot(protan(colors), "Bar", 

62 >>> title = "Protanope vision", ax = axes[0, 1]); 

63 >>> demoplot(deutan(colors), "Bar", 

64 >>> title = "Deuteranope vision", ax = axes[1, 0]); 

65 >>> demoplot(desaturate(colors), "Bar", 

66 >>> title = "Desaturated", ax = axes[1, 1]); 

67 >>> plt.show() 

68 

69 

70 Raises: 

71 TypeError: If `type_` is not a str. 

72 ValueError: If `type_` is not an available demo plot type. 

73 TypeError: If `n` is not int. 

74 ValueError: `n` must be a positive int. 

75 """ 

76 

77 from .palettes import palette 

78 from . import demos 

79 from re import match, compile, IGNORECASE 

80 

81 # Sanity checks 

82 if not isinstance(type_, str): 

83 raise TypeError("argument `type_` must be str") 

84 if not isinstance(n, int): 

85 raise TypeError("argument `n` must be int") 

86 if not n > 0: 

87 raise ValueError("argument `n` must be a positive int (number of colors)") 

88 

89 # The palette class does all the checks and conversions for different 

90 # types of objects such as a single string hex color, lists of hex colors, 

91 # colorobjects, palette objects, and hclpalettes. 

92 colors = palette(colors, n = n).colors() 

93 

94 # Replace missing values with white 

95 colors = ["#FFFFFF" if x is None else x for x in colors] 

96 

97 # Loading available demo plot types (functions) 

98 available_types = [] 

99 for rec in dir(demos): 

100 if not rec == "demoplot" and match("^[A-Za-z]*$", rec): 

101 available_types.append(rec) 

102 

103 # Is the user asking for an available demo plot? 

104 fun = None 

105 check = compile(f"^{type_}$", IGNORECASE) 

106 for avtype in available_types: 

107 if not check.match(avtype): continue 

108 fun = avtype 

109 

110 # Not found? 

111 if fun is None: 

112 raise ValueError(f"no demoplot available for {type_}. Available: {', '.join(available_types)}") 

113 

114 # Calling the required plotting function 

115 fun = getattr(demos, fun) 

116 if ax is None: 

117 return fun(colors, **kwargs) 

118 else: 

119 return fun(colors, ax = ax, **kwargs) 

120 

121 

122def _demoplot_set_labels(ax, **kwargs): 

123 """Setting axis and labels for demoplots. 

124 

125 Args: 

126 **kwargs: named arguments to set different labels of the demoplots. 

127 Considered are `title`, `xlable`, and `ylabel` only. 

128 

129 Returns: 

130 No return. 

131 """ 

132 

133 from matplotlib import pyplot as plt 

134 

135 # Hide axis ticks and frame (box) 

136 ax.axes.xaxis.set_ticks([]) 

137 ax.axes.yaxis.set_ticks([]) 

138 ax.set_frame_on(False) 

139 

140 # In case the user specified title, xlabel, or ylabel as a string 

141 # we will call ax.set_title, ax.set_xlabel, and ax.set_ylabel respectively. 

142 # For the title boldface font will be used. 

143 for x in ["title", "xlabel", "ylabel"]: 

144 if x in kwargs.keys(): 

145 if isinstance(kwargs[x], str): 

146 fn = getattr(ax, "set_{:s}".format(x)) 

147 fn(kwargs[x], fontweight = "bold" if x == "title" else "regular") 

148 

149 

150def Bar(colors, ax = None, **kwargs): 

151 """Bar Plot Demo 

152 

153 Args: 

154 colors (list of str): List of hex colors. 

155 ax (None or matplotlib.axes.Axes): If none a new matplotlib figure will 

156 be created. If `ax` inherits from `matplotlib.axes.Axes` this object 

157 will be used to create the demoplot. Handy to create multiple subplots. 

158 **kwargs: Optional; Strings can be set for `title = "My title"`,  

159 `xlabel = "My x label"` and `ylabel = "My y label"`.  

160 

161 Returns: 

162 Returns a new figure object if `ax` equals `None`, else the 

163 same object as provided on `ax` is returned. 

164 

165 Raises: 

166 ValueError: If `ax` is neither none nor an object which inherits from 

167 `matplotlib.axes.Axes`. 

168 """ 

169 

170 import matplotlib.pyplot as plt 

171 import numpy as np 

172 from matplotlib.axes import Axes 

173 

174 if not isinstance(ax, (Axes, type(None))): 

175 raise TypeError("argument `ax` must be None or inherit from matplotlib.axes.Axes") 

176 

177 # Replace missing values with white 

178 colors = ["#FFFFFF" if x is None else x for x in colors] 

179 

180 # Open new figure in case the user has not specified the `ax` 

181 # input argument (matplotlib.axes.Axes) but use `ax = None` (default). 

182 # In this case this function will also auto-show the image at the end 

183 # of the function. 

184 if ax is None: 

185 fig = plt.figure() 

186 ax = plt.gca() 

187 showfig = True 

188 else: 

189 showfig = False 

190 

191 # Get random data 

192 np.random.seed(1) 

193 width = 0.9 / len(colors) 

194 

195 lower = [1.1, 1.9, 0.7, 0.3] 

196 offset = [0.5, 1.1, 1.5, 0.8] 

197 

198 # Creating the plot 

199 for i in range(0, len(lower)): 

200 x = i + np.arange(0, len(colors)) * width 

201 y = lower[i] + np.abs(np.sin(offset[i] + 1 + \ 

202 np.arange(0, len(colors), dtype = float))) / 3 

203 ax.bar(x, y, color = colors, width = width) 

204 

205 

206 # Set and draw axis and labels for the demoplots 

207 _demoplot_set_labels(ax, **kwargs) 

208 

209 if not showfig: 

210 return ax 

211 else: 

212 plt.show() 

213 return fig 

214 

215 

216def Pie(colors, ax = None, **kwargs): 

217 """Pie Chart Demo 

218 

219 Args: 

220 colors (list of str): List of hex colors. 

221 ax (None or matplotlib.axes.Axes): If none a new matplotlib figure will 

222 be created. If `ax` inherits from `matplotlib.axes.Axes` this object 

223 will be used to create the demoplot. Handy to create multiple subplots. 

224 **kwargs: Optional; Strings can be set for `title = "My title"`, 

225 `xlabel = "My x label"` and `ylabel = "My y label"`. 

226 

227 Returns: 

228 Returns a new figure object if `ax` equals `None`, else the 

229 same object as provided on `ax` is returned. 

230 

231 Raises: 

232 ValueError: If `ax` is neither none nor an object which inherits from 

233 `matplotlib.axes.Axes`. 

234 """ 

235 

236 import matplotlib.pyplot as plt 

237 import numpy as np 

238 from matplotlib.axes import Axes 

239 

240 if not isinstance(ax, (Axes, type(None))): 

241 raise TypeError("argument `ax` must be None or inherit from matplotlib.axes.Axes") 

242 

243 # Replace missing values with white 

244 colors = ["#FFFFFF" if x is None else x for x in colors] 

245 

246 # Open new figure in case the user has not specified the `ax` 

247 # input argument (matplotlib.axes.Axes) but use `ax = None` (default). 

248 # In this case this function will also auto-show the image at the end 

249 # of the function. 

250 if ax is None: 

251 fig = plt.figure() 

252 ax = plt.gca() 

253 showfig = True 

254 else: 

255 showfig = False 

256 

257 # Generate pie plot 

258 x = 0.01 + np.abs(np.sin(1.5 + np.arange(0, len(colors)))) 

259 ax.pie(x, colors = colors, 

260 wedgeprops = {"edgecolor": "0", "linewidth": 1, "antialiased": True}) 

261 

262 # Set and draw axis and labels for the demoplots 

263 _demoplot_set_labels(ax, **kwargs) 

264 

265 if not showfig: 

266 return ax 

267 else: 

268 plt.show() 

269 return fig 

270 

271 

272def Spine(colors, ax = None, **kwargs): 

273 """Spine Plot Demo 

274 

275 Args: 

276 colors (list of str): List of hex colors. 

277 ax (None or matplotlib.axes.Axes): If none a new matplotlib figure will 

278 be created. If `ax` inherits from `matplotlib.axes.Axes` this object 

279 will be used to create the demoplot. Handy to create multiple subplots. 

280 **kwargs: Optional; Strings can be set for `title = "My title"`, 

281 `xlabel = "My x label"` and `ylabel = "My y label"`. 

282 

283 Returns: 

284 Returns a new figure object if `ax` equals `None`, else the 

285 same object as provided on `ax` is returned. 

286 

287 Raises: 

288 ValueError: If `ax` is neither none nor an object which inherits from 

289 `matplotlib.axes.Axes`. 

290 """ 

291 

292 import matplotlib.pyplot as plt 

293 from matplotlib.patches import Rectangle 

294 import numpy as np 

295 from matplotlib.axes import Axes 

296 

297 if not isinstance(ax, (Axes, type(None))): 

298 raise TypeError("argument `ax` must be None or inherit from matplotlib.axes.Axes") 

299 

300 # Replace missing values with white 

301 colors = ["#FFFFFF" if x is None else x for x in colors] 

302 

303 # Open new figure in case the user has not specified the `ax` 

304 # input argument (matplotlib.axes.Axes) but use `ax = None` (default). 

305 # In this case this function will also auto-show the image at the end 

306 # of the function. 

307 if ax is None: 

308 fig = plt.figure() 

309 ax = plt.gca() 

310 showfig = True 

311 else: 

312 showfig = False 

313 

314 # Data 

315 offset = 0.015 

316 widths = [0.05, 0.1, 0.15, 0.1, 0.2, 0.08, 0.12, 0.16, 0.04] 

317 k = len(widths) 

318 n = len(colors) 

319 heights = [np.power(np.arange(1, n + 1, dtype = float) / n, 1. / p) for p in \ 

320 [2.5, 1.2, 2.7, 1, 1.3, 0.7, 0.4, 0.2, 1.7]] 

321 

322 # Plot 

323 x = 0. 

324 for i in range(0,k): 

325 y = 0. 

326 heights[i] = heights[i] / sum(heights[i]) # Scale 

327 for j in range(0,n): 

328 rect = Rectangle((x,y), widths[i], heights[i][j], color = colors[j]) 

329 ax.add_patch(rect) 

330 y += heights[i][j] 

331 x += offset + widths[i] 

332 

333 # Set and draw axis and labels for the demoplots 

334 _demoplot_set_labels(ax, **kwargs) 

335 

336 if not showfig: 

337 return ax 

338 else: 

339 plt.show() 

340 return fig 

341 

342 

343def Heatmap(colors, ax = None, **kwargs): 

344 """Heat Map Demo 

345 

346 Dataset source: Digitized from a topographic map by Ross Ihaka. These data 

347 should not be regarded as accurate. 

348 

349 Dataset description: Maunga Whau (Mt Eden) is one of about 50 

350 volcanos in the Auckland volcanic field. This data set gives topographic 

351 information for Maunga Whau on a 10m by 10m grid. A matrix with 87 rows 

352 and 61 columns, rows corresponding to grid lines running east to west and 

353 columns to grid lines running south to north. 

354 

355 Args: 

356 colors (list of str): List of hex colors. 

357 ax (None or matplotlib.axes.Axes): If none a new matplotlib figure will 

358 be created. If `ax` inherits from `matplotlib.axes.Axes` this object 

359 will be used to create the demoplot. Handy to create multiple subplots. 

360 **kwargs: Optional; Strings can be set for `title = "My title"`, 

361 `xlabel = "My x label"` and `ylabel = "My y label"`. 

362 

363 Returns: 

364 Returns a new figure object if `ax` equals `None`, else the 

365 same object as provided on `ax` is returned. 

366 

367 Raises: 

368 ValueError: If `ax` is neither none nor an object which inherits from 

369 `matplotlib.axes.Axes`. 

370 """ 

371 

372 import matplotlib.pyplot as plt 

373 import numpy as np 

374 from matplotlib.axes import Axes 

375 

376 from matplotlib.colors import LinearSegmentedColormap 

377 from .colorlib import hexcols 

378 

379 if not isinstance(ax, (Axes, type(None))): 

380 raise TypeError("argument `ax` must be None or inherit from matplotlib.axes.Axes") 

381 

382 # Replace missing values with white 

383 colors = ["#FFFFFF" if x is None else x for x in colors] 

384 

385 # Open new figure in case the user has not specified the `ax` 

386 # input argument (matplotlib.axes.Axes) but use `ax = None` (default). 

387 # In this case this function will also auto-show the image at the end 

388 # of the function. 

389 if ax is None: 

390 fig = plt.figure() 

391 ax = plt.gca() 

392 showfig = True 

393 else: 

394 showfig = False 

395 

396 # Get coordinates 

397 cobj = hexcols(colors) 

398 cobj.to("sRGB") 

399 r = cobj.get("R"); g = cobj.get("G"); b = cobj.get("B") 

400 

401 # Create cmap 

402 pos = np.linspace(0, 1, len(colors), dtype = float) 

403 cdict = {'red':[], 'green':[], 'blue':[]} 

404 for i in range(0, len(colors)): 

405 cdict['red'].append( (pos[i], r[i], r[i]) ) 

406 cdict['green'].append( (pos[i], g[i], g[i]) ) 

407 cdict['blue'].append( (pos[i], b[i], b[i]) ) 

408 cmap = LinearSegmentedColormap("custom", cdict, len(colors)) 

409 

410 # Loading vulcano 

411 data = get_volcano_data() 

412 

413 # Plotting data 

414 ax.imshow(data, cmap = cmap, aspect = "auto") 

415 

416 #ax.axis("off") 

417 ax.axes.xaxis.set_ticks([]) 

418 ax.axes.yaxis.set_ticks([]) 

419 ax.set_frame_on(False) 

420 

421 # Set and draw axis and labels for the demoplots 

422 _demoplot_set_labels(ax, **kwargs) 

423 

424 if not showfig: 

425 return ax 

426 else: 

427 plt.show() 

428 return fig 

429 

430 

431 

432def Matrix(colors, ax = None, **kwargs): 

433 """Matrix (Image) Demo Plot 

434 

435 Args: 

436 colors (list of str): List of hex colors. 

437 ax (None or matplotlib.axes.Axes): If none a new matplotlib figure will 

438 be created. If `ax` inherits from `matplotlib.axes.Axes` this object 

439 will be used to create the demoplot. Handy to create multiple subplots. 

440 **kwargs: Optional; Strings can be set for `title = "My title"`, 

441 `xlabel = "My x label"` and `ylabel = "My y label"`. 

442 

443 Returns: 

444 Returns a new figure object if `ax` equals `None`, else the 

445 same object as provided on `ax` is returned. 

446 

447 Raises: 

448 ValueError: If `ax` is neither none nor an object which inherits from 

449 `matplotlib.axes.Axes`. 

450 """ 

451 

452 import matplotlib.pyplot as plt 

453 import numpy as np 

454 from matplotlib.axes import Axes 

455 

456 from matplotlib.colors import LinearSegmentedColormap 

457 from .colorlib import hexcols 

458 

459 if not isinstance(ax, (Axes, type(None))): 

460 raise TypeError("argument `ax` must be None or inherit from matplotlib.axes.Axes") 

461 

462 # Replace missing values with white 

463 colors = ["#FFFFFF" if x is None else x for x in colors] 

464 

465 # Open new figure in case the user has not specified the `ax` 

466 # input argument (matplotlib.axes.Axes) but use `ax = None` (default). 

467 # In this case this function will also auto-show the image at the end 

468 # of the function. 

469 if ax is None: 

470 fig = plt.figure() 

471 ax = plt.gca() 

472 showfig = True 

473 else: 

474 showfig = False 

475 

476 # Get coordinates 

477 cobj = hexcols(colors) 

478 cobj.to("sRGB") 

479 r = cobj.get("R"); g = cobj.get("G"); b = cobj.get("B") 

480 

481 # Create cmap 

482 pos = np.linspace(0, 1, len(colors), dtype = float) 

483 cdict = {'red':[], 'green':[], 'blue':[]} 

484 for i in range(0, len(colors)): 

485 cdict['red'].append( (pos[i], r[i], r[i]) ) 

486 cdict['green'].append( (pos[i], g[i], g[i]) ) 

487 cdict['blue'].append( (pos[i], b[i], b[i]) ) 

488 cmap = LinearSegmentedColormap("custom", cdict, len(colors)) 

489 

490 # Get random data 

491 np.random.seed(1) 

492 data = np.random.uniform(0., float(len(colors)), 100).reshape((10,10)) 

493 

494 # Plotting data 

495 ax.imshow(data, cmap = cmap) 

496 

497 # Set and draw axis and labels for the demoplots 

498 _demoplot_set_labels(ax, **kwargs) 

499 

500 if not showfig: 

501 return ax 

502 else: 

503 plt.show() 

504 return fig 

505 

506#def Scatter(colors, fig = None): 

507# 

508# import matplotlib.pyplot as plt 

509# import numpy as np 

510# 

511# # Open figure if input "fig" is None, else use 

512# # input "fig" handler. 

513# if fig is None: 

514# fig = plt.figure() 

515# showfig = True 

516# else: 

517# showfig = False 

518# 

519# # Data 

520# x0 = np.sin(np.pi * np.arange(1,61) / 30) / 5 

521# y0 = np.cos(np.pi * np.arange(1,61) / 30) / 5 

522# xr = [0.1, -0.6, -0.7, -0.9, 0.4, 1.3, 1.0] 

523# yr = [0.3, 1.0, 0.1, -0.9, -0.8, -0.4, 0.6] 

524# 

525# # Requires scipy 

526# 

527# x = 0.01 + np.abs(np.sin(1.5 + np.arange(0, len(colors)))) 

528# plt.pie(x, colors = colors) 

529# plt.axis("off") 

530# 

531# if not showfig: return fig 

532# else: plt.show() 

533 

534def Lines(colors, ax = None, **kwargs): 

535 """Line Plot Demo 

536 

537 Args: 

538 colors (list of str): List of hex colors. 

539 ax (None or matplotlib.axes.Axes): If none a new matplotlib figure will 

540 be created. If `ax` inherits from `matplotlib.axes.Axes` this object 

541 will be used to create the demoplot. Handy to create multiple subplots. 

542 **kwargs: Optional; Strings can be set for `title = "My title"`, 

543 `xlabel = "My x label"` and `ylabel = "My y label"`. 

544 

545 Returns: 

546 Returns a new figure object if `ax` equals `None`, else the 

547 same object as provided on `ax` is returned. 

548 

549 Raises: 

550 ValueError: If `ax` is neither none nor an object which inherits from 

551 `matplotlib.axes.Axes`. 

552 """ 

553 

554 import matplotlib.pyplot as plt 

555 import numpy as np 

556 from matplotlib.axes import Axes 

557 

558 if not isinstance(ax, (Axes, type(None))): 

559 raise TypeError("argument `ax` must be None or inherit from matplotlib.axes.Axes") 

560 

561 # Replace missing values with white 

562 colors = ["#FFFFFF" if x is None else x for x in colors] 

563 

564 # Open new figure in case the user has not specified the `ax` 

565 # input argument (matplotlib.axes.Axes) but use `ax = None` (default). 

566 # In this case this function will also auto-show the image at the end 

567 # of the function. 

568 if ax is None: 

569 fig = plt.figure() 

570 ax = plt.gca() 

571 showfig = True 

572 else: 

573 showfig = False 

574 

575 # Data 

576 n = len(colors) 

577 s = range(2, n + 2) 

578 

579 lwd = 6 

580 if n > 5: lwd -= 1 

581 if n > 15: lwd -= 1 

582 if n > 25: lwd -= 1 

583 

584 for i in range(0, len(colors)): 

585 j = n - 1 - i 

586 # Plotting two lines to get the overlays correctly 

587 ax.plot([1 / s[i], 2. + 1. / s[j]], 

588 [s[i], s[j]], 

589 color = colors[i], linewidth = lwd, 

590 solid_capstyle = "round") 

591 ax.plot([2. + 1. / s[i], 4. - 1. / s[i], 6. - 1 / s[i]], 

592 [s[i], s[i], s[j]], 

593 color = colors[j], linewidth = lwd, 

594 solid_capstyle = "round") 

595 

596 # Set and draw axis and labels for the demoplots 

597 _demoplot_set_labels(ax, **kwargs) 

598 

599 if not showfig: 

600 return ax 

601 else: 

602 plt.show() 

603 return fig 

604 

605 

606def Map(colors, ax = None, **kwargs): 

607 """Map Demo Plot 

608 

609 Args: 

610 colors (list of str): List of hex colors. 

611 ax (None or matplotlib.axes.Axes): If none a new matplotlib figure will 

612 be created. If `ax` inherits from `matplotlib.axes.Axes` this object 

613 will be used to create the demoplot. Handy to create multiple subplots. 

614 **kwargs: Optional; Strings can be set for `title = "My title"`, 

615 `xlabel = "My x label"` and `ylabel = "My y label"`. In addition 

616 `edgecolor = <color>` can be used to specify custom edge color of the 

617 polygons. 

618 

619 Returns: 

620 Returns a new figure object if `ax` equals `None`, else the 

621 same object as provided on `ax` is returned. 

622 

623 Raises: 

624 ValueError: If `ax` is neither none nor an object which inherits from 

625 `matplotlib.axes.Axes`. 

626 """ 

627 

628 import matplotlib.pyplot as plt 

629 import numpy as np 

630 from matplotlib.axes import Axes 

631 

632 if not isinstance(ax, (Axes, type(None))): 

633 raise TypeError("argument `ax` must be None or inherit from matplotlib.axes.Axes") 

634 

635 # Replace missing values with white 

636 colors = ["#FFFFFF" if x is None else x for x in colors] 

637 

638 # Open new figure in case the user has not specified the `ax` 

639 # input argument (matplotlib.axes.Axes) but use `ax = None` (default). 

640 # In this case this function will also auto-show the image at the end 

641 # of the function. 

642 if ax is None: 

643 fig = plt.figure() 

644 ax = plt.gca() 

645 showfig = True 

646 else: 

647 showfig = False 

648 

649 

650 # Returns a PatchCollection with the polygons for the map and 

651 # a numpy array with the values used for the color coding. 

652 collection,vals = get_map_data() 

653 

654 # Convert the numeric values into int [0, n-1] to pick 

655 # the correct colors for each polygon given the user input 

656 # object `colors`. 

657 n = len(colors) 

658 vals = np.floor((vals - np.min(vals)) / (np.max(vals) - np.min(vals)) * (n - 1)) 

659 vals = np.fmin(vals, n - 1) 

660 cols = [colors[int(x)] for x in vals] 

661 

662 # Setting facecolor of the polygons 

663 collection.set_facecolor(cols) 

664 edgecolor = "black" if not "edgecolor" in kwargs.keys() else kwargs["edgecolor"] 

665 collection.set_edgecolor(edgecolor) 

666 

667 # Draw map 

668 ax.add_collection(collection) 

669 ax.autoscale_view() 

670 ax.set_aspect("equal") 

671 

672 # Set and draw axis and labels for the demoplots 

673 _demoplot_set_labels(ax, **kwargs) 

674 

675 if not showfig: 

676 return ax 

677 else: 

678 plt.show() 

679 return fig 

680 

681 

682def Spectrum(*args, **kwargs): 

683 """Color Spectrum Demo Plot 

684 

685 Plotting example. Simply interfaces the specplot function. 

686 

687 Args: 

688 *args (list of str): List of hex colors. 

689 **kwargs: Additional arguments forwarded to `specplot()`, 

690 typically `fig` (matplotlib Figure). 

691 """ 

692 

693 from colorspace import specplot 

694 return specplot(rgb = True, *args, **kwargs) 

695 

696 

697def get_volcano_data(array = False): 

698 """Topographic Information on Auckland's Maunga Whau Volcano 

699 

700 Maunga Whau (Mt Eden) is one of about 50 volcanos in the Auckland 

701 volcanic field. This data set gives topographic information for 

702 Maunga Whau on a 10m by 10m grid. 

703 

704 Args: 

705 array (bool): should the return be a list (default) or 2d 

706 numpy array? 

707 

708 Returns: 

709 Returns a list of length 67 where each entry is a list of int 

710 of lenth 87 if `asarray = False` (default). If `asarray = True` 

711 an int numpy array of shape `(67, 87)` will be returned. 

712 

713 Raises: 

714 ValueError: If input `asarray` is not bool. 

715 """ 

716 

717 import os 

718 from numpy import asarray 

719 

720 if not isinstance(array, bool): 

721 raise ValueError("argument `asarray` must be bool") 

722 

723 # Loading the data set 

724 resource_package = os.path.dirname(__file__) 

725 volcano = os.path.join(resource_package, "data", "volcano.dat") 

726 

727 # Reading the data set; create recursive list 

728 data = [] 

729 with open(volcano, "r") as fid: 

730 for line in fid.readlines(): 

731 data.append([int(x) for x in line.split()]) 

732 

733 # Return data 

734 if array: 

735 return asarray(data) 

736 else: 

737 data.reverse() 

738 return(data) 

739 

740def get_map_data(): 

741 """Load Map Data 

742 

743 Reading a file called `map.json` shipped with the package which 

744 contains the definition of the different areas (polygons) and  

745 values to draw the map. 

746 

747 Contains polygons representing the southern US states 

748 Alabama, Georgia, and South Carolona with simulated data. 

749 

750 Returns: 

751 list: List of length `2`. The first entry is a `PatchCollection` object 

752 (`matplotlib.collections`) which sonsists of a series of `Polygon`s 

753 for the different districts. The second entry is a `numpy.ndarray` 

754 (float) containing the values used to color-code the areas. 

755 """ 

756 import os 

757 import json 

758 

759 from matplotlib import pyplot as plt 

760 from matplotlib.collections import PatchCollection 

761 from matplotlib.patches import Polygon 

762 from colorspace.demos import get_map_data 

763 from numpy import column_stack, asarray 

764 

765 

766 # Loading the data set 

767 resource_package = os.path.dirname(__file__) 

768 mapdata = os.path.join(resource_package, "data", "map.json") 

769 

770 with open(mapdata, "r") as fid: mapdata = json.loads(fid.readline()) 

771 

772 patches = [] 

773 values = [] 

774 

775 # Prepare the data for return 

776 for key,vals in mapdata.items(): 

777 polygon = Polygon(column_stack((vals["x"], vals["y"]))) 

778 patches.append(polygon) 

779 values.append(vals["value"][0]) 

780 

781 return [PatchCollection(patches), asarray(values)] 

782