Coverage for src / thunderfish / fishshapes.py: 99%

307 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-15 17:50 +0000

1"""Manipulate and plot fish outlines. 

2 

3## Fish shapes 

4 

5Fish shapes are dictionaries with the keys 'body', 'fin0', 'fin1' ..., 

6and 'eye'. The values are 2D arrays with x-y coordinates (first 

7dimension is points, second dimension coordinates) of the respective 

8pathes. 

9 

10All fish shapes of this module are accessible via these dictionaries: 

11 

12- `fish_shapes`: dictionary holding all electric fish shapes. 

13- `fish_top_shapes`: dictionary holding electric fish shapes viewed from top. 

14- `fish_side_shapes`: dictionary holding electric fish shapes viewed from the side. 

15 

16These are the shapes of various fish species: 

17 

18- `Alepto_top`: *Apteronotus leptorhynchus* viewed from top. 

19- `Alepto_male_side`: Male *Apteronotus leptorhynchus* viewed from the side. 

20- `Eigenmannia_top`: *Eigenmannia virescens* viewed from top. 

21- `Eigenmannia_side`: *Eigenmannia virescens* viewed from the side. 

22- `Gpetersii_top`: *Ganthonemus petersii* viewed from top. 

23- `Gpetersii_side`: *Ganthonemus petersii* viewed from the side. 

24 

25Helper function for selecting a particular fish shape: 

26 

27- `fish_shape()`: get a dictinary containing shapes of a fish. 

28 

29## Plotting 

30 

31- `plot_fish()`: plot body, fins and eye of an electric fish. 

32- `plot_object()`: plot circular object. 

33- `plot_fishfinder()`: plot a fishfinder with electrodes and wires. 

34- `plot_pathes()`: plot pathes. 

35 

36## Fish surface and normals from shapes 

37 

38- `fish_surface()`: generate meshgrid of one side of the fish from shape. 

39- `surface_normals()`: normal vectors on a surface. 

40 

41## General path manipulations 

42 

43You may use these functions to extract and fine tune pathes from SVG 

44files in order to assemble fish shapes for this module. See 

45`export_fish_demo()` for a use case. 

46 

47- `extract_path()`: convert SVG pathes to numpy arrays with path coordinates. 

48- `bbox_pathes()`: common bounding box of pathes. 

49- `translate_pathes()`: translate pathes in place. 

50- `center_pathes()`: translate pathes to their common origin in place. 

51- `rotate_pathes()`: rotate pathes in place. 

52- `flipy_pathes()`: flip pathes in y-direction in place. 

53- `flipx_pathes()`: flip pathes in x-direction in place. 

54- `export_path()`: print coordinates of path for import as numpy array. 

55- `mirror_path()`: complete path of half a fish outline by appending the mirrored path. 

56- `normalize_path()`: normalize fish outline to unit length. 

57- `bend_path()`: bend and scale a path. 

58 

59## Exporting fish outlines from pathes 

60 

61- `export_fish()`: serialize coordinates of fish outlines as a dictionary. 

62- `export_fish_demo()`: code demonstrating how to export fish outlines from SVG file. 

63 

64""" 

65 

66import numpy as np 

67import matplotlib as mpl 

68import matplotlib.pyplot as plt 

69import matplotlib.transforms as mpt 

70 

71from matplotlib.path import Path 

72from matplotlib.patches import PathPatch, Circle, Rectangle 

73 

74 

75Alepto_top = dict(body=np.array([ 

76 [-5.00000000e-01, 0.00000000e+00], [-4.99802704e-01, 1.23222860e-03], 

77 [-4.95374557e-01, 2.57983066e-03], [-4.84420392e-01, 3.29085947e-03], 

78 [-4.72487909e-01, 4.03497963e-03], [-4.13995354e-01, 4.39637211e-03], 

79 [-3.90529212e-01, 5.14049228e-03], [-3.67089631e-01, 5.88461244e-03], 

80 [-3.43596916e-01, 6.65006783e-03], [-3.20104187e-01, 7.39418800e-03], 

81 [-2.97063253e-01, 8.11708180e-03], [-2.79461930e-01, 8.49142780e-03], 

82 [-2.61664711e-01, 9.24382081e-03], [-2.38198570e-01, 1.03918950e-02], 

83 [-2.14732428e-01, 1.14974077e-02], [-1.91239699e-01, 1.26242555e-02], 

84 [-1.67773558e-01, 1.37511034e-02], [-1.44307403e-01, 1.52605701e-02], 

85 [-1.09307508e-01, 1.71314946e-02], [-8.58413531e-02, 1.86197349e-02], 

86 [-6.23486380e-02, 2.01079753e-02], [-3.88824966e-02, 2.12348231e-02], 

87 [-1.54429155e-02, 2.19789433e-02], [1.95835670e-02, 2.31057367e-02], 

88 [4.30231346e-02, 2.38498569e-02], [6.65424230e-02, 2.49767047e-02], 

89 [8.99820050e-02, 2.57421601e-02], [1.13448146e-01, 2.64862803e-02], 

90 [1.36914287e-01, 2.91013032e-02], [1.60380442e-01, 3.28431304e-02], 

91 [1.83873157e-01, 3.43101008e-02], [2.06914105e-01, 3.54369487e-02], 

92 [2.18819919e-01, 3.58196764e-02], [2.42339207e-01, 3.65850229e-02], 

93 [2.72903364e-01, 3.57933339e-02], [2.75411585e-01, 3.56061065e-02], 

94 [2.74126982e-01, 3.73081344e-02], [2.60251756e-01, 4.14908387e-02], 

95 [2.47930096e-01, 4.96419915e-02], [2.39119358e-01, 6.08413919e-02], 

96 [2.39547832e-01, 7.56059835e-02], [2.44279733e-01, 7.95534778e-02], 

97 [2.54298155e-01, 7.66782524e-02], [2.69627591e-01, 6.28724285e-02], 

98 [2.82177993e-01, 4.80249888e-02], [2.88316671e-01, 3.79294791e-02], 

99 [2.89271585e-01, 3.54368942e-02], [2.92213886e-01, 3.54205663e-02], 

100 [3.01203973e-01, 3.58192954e-02], [3.12737740e-01, 4.10493520e-02], 

101 [3.24670128e-01, 3.99438067e-02], [3.36177308e-01, 3.88170133e-02], 

102 [3.48109696e-01, 3.76902090e-02], [3.71177217e-01, 3.54366112e-02], 

103 [3.94643358e-01, 3.24601523e-02], [4.18136073e-01, 2.91010093e-02], 

104 [4.41602228e-01, 2.61033022e-02], [4.65041796e-01, 2.27229002e-02], 

105 [4.77000757e-01, 2.01078773e-02], [4.88938465e-01, 1.57516176e-02], 

106 [4.97051671e-01, 9.88149348e-03], [5.00000000e-01, 4.58499286e-03], 

107 [5.00000000e-01, -4.58499286e-03], [4.97051671e-01, -9.88149348e-03], 

108 [4.88938465e-01, -1.57516176e-02], [4.77000757e-01, -2.01078773e-02], 

109 [4.65041796e-01, -2.27229002e-02], [4.41602228e-01, -2.61033022e-02], 

110 [4.18136073e-01, -2.91010093e-02], [3.94643358e-01, -3.24601523e-02], 

111 [3.71177217e-01, -3.54366112e-02], [3.48109696e-01, -3.76902090e-02], 

112 [3.36177308e-01, -3.88170133e-02], [3.24670128e-01, -3.99438067e-02], 

113 [3.12737740e-01, -4.10493520e-02], [3.01203973e-01, -3.58192954e-02], 

114 [2.92213886e-01, -3.54205663e-02], [2.89271585e-01, -3.54368942e-02], 

115 [2.88316671e-01, -3.79294791e-02], [2.82177993e-01, -4.80249888e-02], 

116 [2.69627591e-01, -6.28724285e-02], [2.54298155e-01, -7.66782524e-02], 

117 [2.44279733e-01, -7.95534778e-02], [2.39547832e-01, -7.56059835e-02], 

118 [2.39119358e-01, -6.08413919e-02], [2.47930096e-01, -4.96419915e-02], 

119 [2.60251756e-01, -4.14908387e-02], [2.74126982e-01, -3.73081344e-02], 

120 [2.75411585e-01, -3.56061065e-02], [2.72903364e-01, -3.57933339e-02], 

121 [2.42339207e-01, -3.65850229e-02], [2.18819919e-01, -3.58196764e-02], 

122 [2.06914105e-01, -3.54369487e-02], [1.83873157e-01, -3.43101008e-02], 

123 [1.60380442e-01, -3.28431304e-02], [1.36914287e-01, -2.91013032e-02], 

124 [1.13448146e-01, -2.64862803e-02], [8.99820050e-02, -2.57421601e-02], 

125 [6.65424230e-02, -2.49767047e-02], [4.30231346e-02, -2.38498569e-02], 

126 [1.95835670e-02, -2.31057367e-02], [-1.54429155e-02, -2.19789433e-02], 

127 [-3.88824966e-02, -2.12348231e-02], [-6.23486380e-02, -2.01079753e-02], 

128 [-8.58413531e-02, -1.86197349e-02], [-1.09307508e-01, -1.71314946e-02], 

129 [-1.44307403e-01, -1.52605701e-02], [-1.67773558e-01, -1.37511034e-02], 

130 [-1.91239699e-01, -1.26242555e-02], [-2.14732428e-01, -1.14974077e-02], 

131 [-2.38198570e-01, -1.03918950e-02], [-2.61664711e-01, -9.24382081e-03], 

132 [-2.79461930e-01, -8.49142780e-03], [-2.97063253e-01, -8.11708180e-03], 

133 [-3.20104187e-01, -7.39418800e-03], [-3.43596916e-01, -6.65006783e-03], 

134 [-3.67089631e-01, -5.88461244e-03], [-3.90529212e-01, -5.14049228e-03], 

135 [-4.13995354e-01, -4.39637211e-03], [-4.72487909e-01, -4.03497963e-03], 

136 [-4.84420392e-01, -3.29085947e-03], [-4.95374557e-01, -2.57983066e-03], 

137 [-4.99802704e-01, -1.23222860e-03], [-5.00000000e-01, -0.00000000e+00],])) 

138"""Outline of an *Apteronotus leptorhynchus* viewed from top, modified from Krahe 2004.""" 

139 

140Alepto_male_side = dict(body=np.array([ 

141 [2.80332097e-01, 5.51361973e-02], [2.41127905e-01, 5.93460338e-02], 

142 [1.91463866e-01, 6.22667811e-02], [1.37379023e-01, 6.17716006e-02], 

143 [6.91234340e-02, 5.72953633e-02], [-1.36051588e-02, 4.74838393e-02], 

144 [-7.55221954e-02, 3.64211032e-02], [-1.60157310e-01, 2.45651115e-02], 

145 [-2.32035003e-01, 1.55421483e-02], [-2.99079447e-01, 9.70960800e-03], 

146 [-3.62251791e-01, 6.27265707e-03], [-4.20527920e-01, 4.22449025e-03], 

147 [-4.72735573e-01, 5.39606712e-03], [-4.80154179e-01, 5.86398206e-03], 

148 [-4.92605065e-01, 1.01411700e-02], [-4.97402289e-01, 5.91543079e-03], 

149 [-5.00000000e-01, -2.84973497e-03], [-4.97832769e-01, -1.17981289e-02], 

150 [-4.93106950e-01, -1.43380199e-02], [-4.81164618e-01, -8.19215843e-03], 

151 [-4.72578673e-01, -6.17623988e-03], [-4.45390092e-01, -5.96123217e-03], 

152 [-3.74805165e-01, -9.05994885e-03], [-3.33716813e-01, -1.08317142e-02], 

153 [-3.08099380e-01, -1.15017063e-02], [-2.82451613e-01, -1.30396176e-02], 

154 [-2.34498580e-01, -2.21834040e-02], [-1.86892658e-01, -3.26728000e-02], 

155 [-1.08738732e-01, -4.99024273e-02], [-3.50753879e-02, -5.94218882e-02], 

156 [3.28767168e-02, -6.58397526e-02], [1.25319086e-01, -7.21513968e-02], 

157 [1.99523049e-01, -7.99740378e-02], [2.37035792e-01, -8.44828747e-02], 

158 [2.74475366e-01, -8.68964223e-02], [3.12742824e-01, -8.34038539e-02], 

159 [3.36340505e-01, -7.82231053e-02], [3.55492327e-01, -7.21451373e-02], 

160 [3.74670470e-01, -6.45564453e-02], [3.82920881e-01, -6.06824741e-02], 

161 [3.84828678e-01, -5.92550189e-02], [3.86562866e-01, -5.99353293e-02], 

162 [3.90753372e-01, -6.01589140e-02], [4.03494946e-01, -5.90960625e-02], 

163 [4.38474761e-01, -6.13270959e-02], [4.61389913e-01, -6.47960654e-02], 

164 [4.77010163e-01, -6.86433853e-02], [4.84437594e-01, -6.89404377e-02], 

165 [4.90842798e-01, -6.82840746e-02], [4.94567181e-01, -6.58050993e-02], 

166 [4.95443985e-01, -6.30972916e-02], [4.94497789e-01, -6.10849673e-02], 

167 [4.91729699e-01, -6.00016418e-02], [4.84298546e-01, -5.78808424e-02], 

168 [4.93112897e-01, -5.45550751e-02], [4.97742360e-01, -5.12667865e-02], 

169 [5.00000000e-01, -4.73196051e-02], [4.99521047e-01, -4.36153642e-02], 

170 [4.96159278e-01, -3.87756472e-02], [4.86402575e-01, -3.18513601e-02], 

171 [4.67134496e-01, -2.06920393e-02], [4.39218141e-01, -5.92866768e-03], 

172 [4.25010402e-01, 4.45359743e-03], [4.14788070e-01, 1.39860522e-02], 

173 [3.93656086e-01, 2.44160739e-02], [3.75679976e-01, 2.94323719e-02], 

174 [3.61404254e-01, 3.69002336e-02], [3.37900061e-01, 4.40458301e-02], 

175 [3.11463577e-01, 4.97553861e-02],]), 

176 fin0=np.array([ 

177 [3.29593304e-01, -7.95912942e-02], [3.27561074e-01, -8.48367727e-02], 

178 [3.08709726e-01, -9.90609655e-02], [2.80934315e-01, -1.08062137e-01], 

179 [2.58017473e-01, -1.12878542e-01], [2.35142157e-01, -1.14467112e-01], 

180 [2.18081531e-01, -1.12354592e-01], [1.98185626e-01, -1.10721292e-01], 

181 [1.78099090e-01, -1.13640193e-01], [1.59752865e-01, -1.18762090e-01], 

182 [1.40752841e-01, -1.20266781e-01], [1.27904629e-01, -1.17712356e-01], 

183 [1.19134213e-01, -1.12284346e-01], [1.09580014e-01, -1.04436264e-01], 

184 [8.20184710e-02, -9.60992771e-02], [5.05598670e-02, -9.57289587e-02], 

185 [2.74790284e-02, -1.04021601e-01], [3.92704920e-03, -1.08834461e-01], 

186 [-3.12710137e-02, -1.08965162e-01], [-5.88865488e-02, -1.03820945e-01], 

187 [-7.82549598e-02, -9.45428978e-02], [-9.94601687e-02, -8.20174601e-02], 

188 [-1.29941640e-01, -7.01658118e-02], [-1.58259295e-01, -6.73695625e-02], 

189 [-1.86001442e-01, -7.01570717e-02], [-2.14339679e-01, -6.79007296e-02], 

190 [-2.38708971e-01, -5.78982409e-02], [-2.55168178e-01, -4.41230328e-02], 

191 [-2.71293058e-01, -3.28785160e-02], [-2.88416341e-01, -2.86291802e-02], 

192 [-3.06103856e-01, -2.82461534e-02], [-3.22345146e-01, -2.47128040e-02], 

193 [-3.38333410e-01, -1.44124470e-02], [-3.43264223e-01, -1.03691894e-02], 

194 [-3.08609907e-01, -1.12571357e-02], [-2.86088545e-01, -1.25633719e-02], 

195 [-2.59977440e-01, -1.65414204e-02], [-2.16119429e-01, -2.64072955e-02], 

196 [-1.68443229e-01, -3.68996138e-02], [-1.12717944e-01, -4.88585839e-02], 

197 [-7.07908982e-02, -5.51259999e-02], [-1.80906639e-02, -6.16068166e-02], 

198 [2.75299392e-02, -6.53080983e-02], [7.71390030e-02, -6.85205021e-02], 

199 [1.21071140e-01, -7.25104674e-02], [1.78723549e-01, -7.85286909e-02], 

200 [2.32100395e-01, -8.40268652e-02], [2.74938812e-01, -8.74456073e-02], 

201 [3.10041908e-01, -8.43007220e-02],]), 

202 eye=np.array([0.4, 0.0, 0.01])) 

203"""Outline of an *Apteronotus leptorhynchus* male viewed from the side.""" 

204 

205Eigenmannia_top = dict(body=np.array([ 

206 [-5.00000000e-01, 0.00000000e+00], [-4.84515329e-01, 4.41536208e-03], 

207 [-4.76913801e-01, 5.34924846e-03], [-3.94680346e-01, 8.25734868e-03], 

208 [-2.74106007e-01, 8.94059314e-03], [-1.35145770e-01, 1.09559947e-02], 

209 [2.36080412e-02, 1.40941342e-02], [1.36968804e-01, 1.51550643e-02], 

210 [2.15041020e-01, 1.96734219e-02], [2.83582110e-01, 2.36895289e-02], 

211 [3.20834553e-01, 2.63067663e-02], [3.46646908e-01, 2.77590937e-02], 

212 [3.68462758e-01, 2.97229886e-02], [3.62525174e-01, 3.12766064e-02], 

213 [3.57215426e-01, 3.25163153e-02], [3.51347983e-01, 3.44809486e-02], 

214 [3.46108357e-01, 3.83290703e-02], [3.44207747e-01, 4.53621620e-02], 

215 [3.46387987e-01, 5.39648157e-02], [3.54784122e-01, 6.69720204e-02], 

216 [3.67470562e-01, 8.11691502e-02], [3.80987875e-01, 9.13148567e-02], 

217 [3.90738756e-01, 9.39276818e-02], [3.95854520e-01, 9.06728175e-02], 

218 [3.99717109e-01, 8.49081236e-02], [3.96997843e-01, 6.54750599e-02], 

219 [3.89101023e-01, 4.11631100e-02], [3.86289062e-01, 3.71837960e-02], 

220 [3.94553267e-01, 3.78052325e-02], [4.03373690e-01, 3.72181278e-02], 

221 [4.20207675e-01, 3.56696607e-02], [4.37553246e-01, 3.46018748e-02], 

222 [4.59139056e-01, 3.15068918e-02], [4.79811600e-01, 2.68634593e-02], 

223 [4.92810472e-01, 1.97499259e-02], [4.98594784e-01, 1.11517021e-02], 

224 [5.00000000e-01, 5.62393850e-03], [5.00000000e-01, -5.62393850e-03], 

225 [4.98594784e-01, -1.11517021e-02], [4.92810472e-01, -1.97499259e-02], 

226 [4.79811600e-01, -2.68634593e-02], [4.59139056e-01, -3.15068918e-02], 

227 [4.37553246e-01, -3.46018748e-02], [4.20207675e-01, -3.56696607e-02], 

228 [4.03373690e-01, -3.72181278e-02], [3.94553267e-01, -3.78052325e-02], 

229 [3.86289062e-01, -3.71837960e-02], [3.89101023e-01, -4.11631100e-02], 

230 [3.96997843e-01, -6.54750599e-02], [3.99717109e-01, -8.49081236e-02], 

231 [3.95854520e-01, -9.06728175e-02], [3.90738756e-01, -9.39276818e-02], 

232 [3.80987875e-01, -9.13148567e-02], [3.67470562e-01, -8.11691502e-02], 

233 [3.54784122e-01, -6.69720204e-02], [3.46387987e-01, -5.39648157e-02], 

234 [3.44207747e-01, -4.53621620e-02], [3.46108357e-01, -3.83290703e-02], 

235 [3.51347983e-01, -3.44809486e-02], [3.57215426e-01, -3.25163153e-02], 

236 [3.62525174e-01, -3.12766064e-02], [3.68462758e-01, -2.97229886e-02], 

237 [3.46646908e-01, -2.77590937e-02], [3.20834553e-01, -2.63067663e-02], 

238 [2.83582110e-01, -2.36895289e-02], [2.15041020e-01, -1.96734219e-02], 

239 [1.36968804e-01, -1.51550643e-02], [2.36080412e-02, -1.40941342e-02], 

240 [-1.35145770e-01, -1.09559947e-02], [-2.74106007e-01, -8.94059314e-03], 

241 [-3.94680346e-01, -8.25734868e-03], [-4.76913801e-01, -5.34924846e-03], 

242 [-4.84515329e-01, -4.41536208e-03], [-5.00000000e-01, -0.00000000e+00],])) 

243"""Outline of an *Eigenmannia virescens* viewed from top.""" 

244 

245Eigenmannia_side = dict(body=np.array([ 

246 [7.39835590e-02, 4.57421567e-02], [1.36190672e-01, 5.20008556e-02], 

247 [1.88575637e-01, 5.31087788e-02], [2.55693889e-01, 4.90162062e-02], 

248 [2.91989388e-01, 4.57421567e-02], [3.30997244e-01, 4.08310609e-02], 

249 [3.60079352e-01, 3.50312357e-02], [3.86267547e-01, 2.72057399e-02], 

250 [4.09748495e-01, 1.88510343e-02], [4.30914243e-01, 1.02069720e-02], 

251 [4.43253678e-01, 5.18028074e-03], [4.61959655e-01, -3.75313831e-03], 

252 [4.82422519e-01, -1.50677197e-02], [4.93493046e-01, -2.26243878e-02], 

253 [4.97325280e-01, -2.75603439e-02], [5.00000000e-01, -3.36538136e-02], 

254 [4.99855343e-01, -3.81556262e-02], [4.97829629e-01, -4.26574388e-02], 

255 [4.95229403e-01, -4.49683083e-02], [4.93207934e-01, -4.68450344e-02], 

256 [4.90607707e-01, -4.83870578e-02], [4.92124870e-01, -5.04085273e-02], 

257 [4.93063234e-01, -5.27193968e-02], [4.93063190e-01, -5.47905000e-02], 

258 [4.91905677e-01, -5.65722031e-02], [4.87982621e-01, -5.83539496e-02], 

259 [4.81889151e-01, -5.99909526e-02], [4.72187579e-01, -6.31614903e-02], 

260 [4.57251469e-01, -6.96684443e-02], [4.42315315e-01, -7.44390846e-02], 

261 [4.31434877e-01, -7.64563096e-02], [4.21852452e-01, -8.03091592e-02], 

262 [4.12030260e-01, -8.11773161e-02], [3.97297016e-01, -8.61380457e-02], 

263 [3.84200775e-01, -9.05200184e-02], [3.71589870e-01, -9.38291926e-02], 

264 [3.58008292e-01, -9.50424035e-02], [3.33452813e-01, -9.34053571e-02], 

265 [2.99075185e-01, -8.68572582e-02], [2.70427177e-01, -8.11276391e-02], 

266 [2.32775500e-01, -7.31023958e-02], [2.00034918e-01, -6.81912999e-02], 

267 [1.71386866e-01, -6.43481085e-02], [1.37488988e-01, -5.96768656e-02], 

268 [8.87168470e-02, -5.53444400e-02], [3.71504052e-02, -5.08426274e-02], 

269 [-8.94935470e-03, -4.47741911e-02], [-6.68009664e-02, -3.60218095e-02], 

270 [-1.11819296e-01, -3.02864735e-02], [-1.55609841e-01, -2.46444281e-02], 

271 [-2.01855938e-01, -1.98208625e-02], [-2.61607520e-01, -1.41655641e-02], 

272 [-3.02124011e-01, -9.83500080e-03], [-3.47551590e-01, -8.19795443e-03], 

273 [-3.86021794e-01, -7.21576125e-03], [-4.19580907e-01, -5.90618477e-03], 

274 [-4.49047446e-01, -5.00584824e-03], [-4.82606558e-01, -4.29793979e-03], 

275 [-4.93367213e-01, -3.88865654e-03], [-4.96609514e-01, -3.33497643e-03], 

276 [-4.98599358e-01, -2.28352992e-03], [-5.00000000e-01, -4.13646830e-04], 

277 [-4.99911798e-01, 1.42799787e-03], [-4.97749085e-01, 3.02268669e-03], 

278 [-4.94153971e-01, 3.94706050e-03], [-4.48842818e-01, 5.27946155e-03], 

279 [-3.90932887e-01, 5.88974836e-03], [-3.04988822e-01, 7.10408527e-03], 

280 [-2.43785835e-01, 8.93052803e-03], [-1.87718481e-01, 1.20250559e-02], 

281 [-1.39987578e-01, 1.55534240e-02], [-9.58582596e-02, 1.92113768e-02], 

282 [-4.87936436e-02, 2.54739303e-02], [-1.20172913e-02, 3.11685979e-02], 

283 [3.65545828e-02, 3.98634200e-02],]), 

284 fin0=np.array([ 

285 [-3.23227396e-01, -8.73526322e-03], [-3.17729007e-01, -1.49720903e-02], 

286 [-3.11901320e-01, -2.06301173e-02], [-2.94537996e-01, -2.87329729e-02], 

287 [-2.73702014e-01, -3.62471102e-02], [-2.48814582e-01, -4.42901541e-02], 

288 [-2.26392044e-01, -4.89203820e-02], [-2.11413629e-01, -4.97652813e-02], 

289 [-1.97592770e-01, -4.71608105e-02], [-1.88292360e-01, -4.37113973e-02], 

290 [-1.77575020e-01, -4.26201918e-02], [-1.63230314e-01, -4.13425351e-02], 

291 [-1.45633053e-01, -4.58128611e-02], [-1.32102997e-01, -5.21132245e-02], 

292 [-1.22627830e-01, -5.98022925e-02], [-1.16274541e-01, -6.51393895e-02], 

293 [-1.01226326e-01, -6.99292162e-02], [-8.87826127e-02, -7.09420732e-02], 

294 [-7.63388990e-02, -7.02186163e-02], [-6.41845810e-02, -6.63566715e-02], 

295 [-4.99997329e-02, -6.35107453e-02], [-3.86044383e-02, -6.71556184e-02], 

296 [-2.83003535e-02, -7.56835222e-02], [-1.41203129e-02, -8.28817968e-02], 

297 [1.21728460e-03, -8.66205668e-02], [1.22140543e-02, -8.75385740e-02], 

298 [2.16240177e-02, -8.43285373e-02], [3.27836777e-02, -8.13081568e-02], 

299 [3.98554860e-02, -8.02952999e-02], [4.86770343e-02, -7.96350762e-02], 

300 [5.81904230e-02, -8.20450399e-02], [6.47198980e-02, -8.65937577e-02], 

301 [7.29857310e-02, -9.36024194e-02], [8.47509570e-02, -9.91141438e-02], 

302 [1.00477612e-01, -1.02776515e-01], [1.28258936e-01, -1.02826321e-01], 

303 [1.45605097e-01, -1.02460349e-01], [1.59342462e-01, -9.97657918e-02], 

304 [1.76140399e-01, -9.72111283e-02], [1.89366052e-01, -9.61800377e-02], 

305 [2.03938918e-01, -9.84587276e-02], [2.14786136e-01, -1.02170949e-01], 

306 [2.24046592e-01, -1.08953357e-01], [2.34464605e-01, -1.14112491e-01], 

307 [2.47925953e-01, -1.18114112e-01], [2.65013334e-01, -1.19108779e-01], 

308 [2.83520819e-01, -1.15835465e-01], [2.98329467e-01, -1.08650574e-01], 

309 [3.15014321e-01, -1.04499489e-01], [3.28805304e-01, -1.04273408e-01], 

310 [3.39387031e-01, -1.06211982e-01], [3.52278630e-01, -1.03431974e-01], 

311 [3.61896180e-01, -1.00567165e-01], [3.67032403e-01, -9.80662488e-02], 

312 [3.71589870e-01, -9.38289761e-02], [3.58008292e-01, -9.50421869e-02], 

313 [3.33452813e-01, -9.34051405e-02], [3.06441808e-01, -8.84940880e-02], 

314 [2.35043362e-01, -7.35981699e-02], [1.65011316e-01, -6.31802003e-02], 

315 [1.25654422e-01, -5.85499724e-02], [9.49792270e-02, -5.56561016e-02], 

316 [4.05741354e-02, -5.11056947e-02], [-1.24746680e-03, -4.58268936e-02], 

317 [-5.20302500e-02, -3.81131387e-02], [-1.01805114e-01, -3.16101258e-02], 

318 [-1.51874267e-01, -2.50855445e-02], [-2.01943420e-01, -2.02074944e-02], 

319 [-2.61607516e-01, -1.41653476e-02], [-3.02124016e-01, -9.83478430e-03], 

320 [-3.12840355e-01, -9.28491550e-03],]), 

321 eye=np.array([0.46, -0.03, 0.005])) 

322"""Outline of an *Eigenmannia virescens* viewed from the side.""" 

323 

324Gpetersii_top = dict(body=np.array([ 

325 [-5.00000000e-01, 0.00000000e+00], [-4.98907255e-01, 2.70675451e-03], 

326 [-4.95224935e-01, 4.98692300e-03], [-4.90164100e-01, 6.33588717e-03], 

327 [-4.86097610e-01, 6.53956463e-03], [-4.82786611e-01, 6.60371808e-03], 

328 [-4.79368466e-01, 6.66911518e-03], [-4.75847352e-01, 6.73594857e-03], 

329 [-4.72227445e-01, 6.80441093e-03], [-4.68512920e-01, 6.87469491e-03], 

330 [-4.64707956e-01, 6.94699319e-03], [-4.60816728e-01, 7.02149842e-03], 

331 [-4.56843412e-01, 7.09840326e-03], [-4.52792185e-01, 7.17790040e-03], 

332 [-4.48667224e-01, 7.26018248e-03], [-4.44472704e-01, 7.34544217e-03], 

333 [-4.40212803e-01, 7.43387214e-03], [-4.35891696e-01, 7.52566504e-03], 

334 [-4.31513560e-01, 7.62101355e-03], [-4.27082571e-01, 7.72011032e-03], 

335 [-4.22602906e-01, 7.82314803e-03], [-4.18078741e-01, 7.93031933e-03], 

336 [-4.13514253e-01, 8.04181689e-03], [-4.08913618e-01, 8.15783338e-03], 

337 [-4.04281012e-01, 8.27856145e-03], [-3.99620612e-01, 8.40419377e-03], 

338 [-3.94936595e-01, 8.53492300e-03], [-3.90233135e-01, 8.67094182e-03], 

339 [-3.85514411e-01, 8.81244288e-03], [-3.80784598e-01, 8.95961884e-03], 

340 [-3.76047873e-01, 9.11266238e-03], [-3.71308412e-01, 9.27176615e-03], 

341 [-3.66570392e-01, 9.43712281e-03], [-3.61837989e-01, 9.60892505e-03], 

342 [-3.57115379e-01, 9.78736550e-03], [-3.52406739e-01, 9.97263685e-03], 

343 [-3.47716245e-01, 1.01649318e-02], [-3.43048074e-01, 1.03644429e-02], 

344 [-3.38406402e-01, 1.05713629e-02], [-3.33795405e-01, 1.07858844e-02], 

345 [-3.29219260e-01, 1.10082002e-02], [-3.24682143e-01, 1.12385028e-02], 

346 [-3.20188231e-01, 1.14769850e-02], [-3.15741700e-01, 1.17238394e-02], 

347 [-3.11346727e-01, 1.19792586e-02], [-3.07007487e-01, 1.22434354e-02], 

348 [-3.02469744e-01, 1.25292477e-02], [-2.97839001e-01, 1.28158813e-02], 

349 [-2.93275530e-01, 1.30920628e-02], [-2.88774618e-01, 1.33584584e-02], 

350 [-2.84331553e-01, 1.36157341e-02], [-2.79941621e-01, 1.38645562e-02], 

351 [-2.75600107e-01, 1.41055908e-02], [-2.71302299e-01, 1.43395042e-02], 

352 [-2.67043484e-01, 1.45669625e-02], [-2.62818947e-01, 1.47886318e-02], 

353 [-2.58623976e-01, 1.50051785e-02], [-2.54453857e-01, 1.52172685e-02], 

354 [-2.50303877e-01, 1.54255682e-02], [-2.46169321e-01, 1.56307436e-02], 

355 [-2.42045478e-01, 1.58334610e-02], [-2.37927633e-01, 1.60343865e-02], 

356 [-2.33811073e-01, 1.62341864e-02], [-2.29691084e-01, 1.64335267e-02], 

357 [-2.25562953e-01, 1.66330737e-02], [-2.21421967e-01, 1.68334935e-02], 

358 [-2.17263412e-01, 1.70354524e-02], [-2.13082575e-01, 1.72396165e-02], 

359 [-2.08874743e-01, 1.74466519e-02], [-2.04635201e-01, 1.76572249e-02], 

360 [-2.00359237e-01, 1.78720016e-02], [-1.96042137e-01, 1.80916482e-02], 

361 [-1.91679187e-01, 1.83168309e-02], [-1.87265675e-01, 1.85482158e-02], 

362 [-1.82796886e-01, 1.87864692e-02], [-1.78268108e-01, 1.90322571e-02], 

363 [-1.73674627e-01, 1.92862459e-02], [-1.69011730e-01, 1.95491016e-02], 

364 [-1.64274702e-01, 1.98214905e-02], [-1.59458831e-01, 2.01040786e-02], 

365 [-1.54876765e-01, 2.03808505e-02], [-1.50542259e-01, 2.06624447e-02], 

366 [-1.46207582e-01, 2.09641308e-02], [-1.41872739e-01, 2.12846589e-02], 

367 [-1.37537731e-01, 2.16227790e-02], [-1.33202563e-01, 2.19772413e-02], 

368 [-1.28867239e-01, 2.23467957e-02], [-1.24531760e-01, 2.27301926e-02], 

369 [-1.20196132e-01, 2.31261818e-02], [-1.15860356e-01, 2.35335136e-02], 

370 [-1.11524437e-01, 2.39509380e-02], [-1.07188379e-01, 2.43772051e-02], 

371 [-1.02852183e-01, 2.48110650e-02], [-9.85158544e-02, 2.52512678e-02], 

372 [-9.41793959e-02, 2.56965637e-02], [-8.98428110e-02, 2.61457026e-02], 

373 [-8.55061031e-02, 2.65974348e-02], [-8.11692756e-02, 2.70505102e-02], 

374 [-7.68323318e-02, 2.75036791e-02], [-7.24952752e-02, 2.79556914e-02], 

375 [-6.81581092e-02, 2.84052973e-02], [-6.38208372e-02, 2.88512469e-02], 

376 [-5.94834626e-02, 2.92922903e-02], [-5.51459887e-02, 2.97271776e-02], 

377 [-5.08084190e-02, 3.01546588e-02], [-4.64707569e-02, 3.05734841e-02], 

378 [-4.21330057e-02, 3.09824036e-02], [-3.77951689e-02, 3.13801673e-02], 

379 [-3.34572499e-02, 3.17655254e-02], [-2.91192521e-02, 3.21372280e-02], 

380 [-2.47811788e-02, 3.24940251e-02], [-2.04430334e-02, 3.28346669e-02], 

381 [-1.61048195e-02, 3.31579034e-02], [-1.17665402e-02, 3.34624847e-02], 

382 [-7.42819918e-03, 3.37471610e-02], [-3.08979968e-03, 3.40106823e-02], 

383 [1.24865487e-03, 3.42517987e-02], [5.58716106e-03, 3.44692604e-02], 

384 [9.92571550e-03, 3.46618174e-02], [1.46201447e-02, 3.48571853e-02], 

385 [1.92777267e-02, 3.50697277e-02], [2.37992814e-02, 3.52944714e-02], 

386 [2.81998991e-02, 3.55299272e-02], [3.24946703e-02, 3.57746059e-02], 

387 [3.66986852e-02, 3.60270183e-02], [4.08270342e-02, 3.62856753e-02], 

388 [4.48948076e-02, 3.65490876e-02], [4.89170960e-02, 3.68157661e-02], 

389 [5.29089894e-02, 3.70842215e-02], [5.68855785e-02, 3.73529647e-02], 

390 [6.08619534e-02, 3.76205066e-02], [6.48532046e-02, 3.78853578e-02], 

391 [6.88744224e-02, 3.81460293e-02], [7.29406971e-02, 3.84010318e-02], 

392 [7.70671192e-02, 3.86488761e-02], [8.12687789e-02, 3.88880731e-02], 

393 [8.55607667e-02, 3.91171336e-02], [8.99581728e-02, 3.93345683e-02], 

394 [9.44760878e-02, 3.95388881e-02], [9.91296018e-02, 3.97286039e-02], 

395 [1.03933805e-01, 3.99022264e-02], [1.08903789e-01, 4.00582663e-02], 

396 [1.14054642e-01, 4.01952347e-02], [1.17834449e-01, 4.02735051e-02], 

397 [1.21464088e-01, 4.03177574e-02], [1.25361081e-01, 4.03400333e-02], 

398 [1.29496398e-01, 4.03422149e-02], [1.33841006e-01, 4.03261843e-02], 

399 [1.38365875e-01, 4.02938238e-02], [1.43041974e-01, 4.02470155e-02], 

400 [1.47840270e-01, 4.01876413e-02], [1.52731734e-01, 4.01175836e-02], 

401 [1.57687333e-01, 4.00387245e-02], [1.62678036e-01, 3.99529460e-02], 

402 [1.67674813e-01, 3.98621303e-02], [1.72648631e-01, 3.97681595e-02], 

403 [1.77570460e-01, 3.96729159e-02], [1.82411269e-01, 3.95782814e-02], 

404 [1.87142025e-01, 3.94861383e-02], [1.91733698e-01, 3.93983686e-02], 

405 [1.96157257e-01, 3.93168546e-02], [2.00383670e-01, 3.92434783e-02], 

406 [2.04383906e-01, 3.91801218e-02], [2.08128934e-01, 3.91286674e-02], 

407 [2.11589723e-01, 3.90909971e-02], [2.14737240e-01, 3.90689931e-02], 

408 [2.12686797e-01, 4.35945731e-02], [2.09370932e-01, 4.90028591e-02], 

409 [2.06521214e-01, 5.37246134e-02], [2.04069750e-01, 5.78713813e-02], 

410 [2.01948645e-01, 6.15547081e-02], [2.00090006e-01, 6.48861392e-02], 

411 [1.98425939e-01, 6.79772197e-02], [1.96888549e-01, 7.09394950e-02], 

412 [1.95409943e-01, 7.38845104e-02], [1.93922227e-01, 7.69238111e-02], 

413 [1.92357507e-01, 8.01689425e-02], [1.90647889e-01, 8.37314498e-02], 

414 [1.88621089e-01, 8.79487819e-02], [1.86458315e-01, 9.24949589e-02], 

415 [1.84373392e-01, 9.69521163e-02], [1.82377447e-01, 1.01313322e-01], 

416 [1.80481608e-01, 1.05571643e-01], [1.78697002e-01, 1.09720148e-01], 

417 [1.77034758e-01, 1.13751904e-01], [1.75506002e-01, 1.17659979e-01], 

418 [1.74121863e-01, 1.21437441e-01], [1.72893469e-01, 1.25077357e-01], 

419 [1.71831946e-01, 1.28572795e-01], [1.70912462e-01, 1.32062919e-01], 

420 [1.69673781e-01, 1.37398586e-01], [1.68551414e-01, 1.42827662e-01], 

421 [1.67594629e-01, 1.48234120e-01], [1.66852697e-01, 1.53501933e-01], 

422 [1.66374886e-01, 1.58515074e-01], [1.66210468e-01, 1.63157516e-01], 

423 [1.66408711e-01, 1.67313232e-01], [1.67018885e-01, 1.70866193e-01], 

424 [1.68090261e-01, 1.73700374e-01], [1.69672107e-01, 1.75699747e-01], 

425 [1.71946252e-01, 1.76778701e-01], [1.75330935e-01, 1.76759167e-01], 

426 [1.79335065e-01, 1.75658590e-01], [1.83654362e-01, 1.73730954e-01], 

427 [1.87984545e-01, 1.71230243e-01], [1.92021332e-01, 1.68410438e-01], 

428 [1.95460443e-01, 1.65525524e-01], [1.98288699e-01, 1.62567524e-01], 

429 [2.01008859e-01, 1.59273085e-01], [2.03549954e-01, 1.55804760e-01], 

430 [2.05927459e-01, 1.52185189e-01], [2.08156845e-01, 1.48437015e-01], 

431 [2.10253586e-01, 1.44582880e-01], [2.12233153e-01, 1.40645424e-01], 

432 [2.14111019e-01, 1.36647290e-01], [2.15902657e-01, 1.32611119e-01], 

433 [2.17623539e-01, 1.28559552e-01], [2.19289138e-01, 1.24515232e-01], 

434 [2.20914927e-01, 1.20500800e-01], [2.22516621e-01, 1.16537119e-01], 

435 [2.24093642e-01, 1.12596583e-01], [2.25635202e-01, 1.08661555e-01], 

436 [2.27140388e-01, 1.04726305e-01], [2.28608285e-01, 1.00785102e-01], 

437 [2.30037979e-01, 9.68322151e-02], [2.31428556e-01, 9.28619142e-02], 

438 [2.32779102e-01, 8.88684682e-02], [2.34088702e-01, 8.48461463e-02], 

439 [2.35356443e-01, 8.07892177e-02], [2.36581411e-01, 7.66919517e-02], 

440 [2.37762692e-01, 7.25486175e-02], [2.38899370e-01, 6.83534843e-02], 

441 [2.39990533e-01, 6.41008214e-02], [2.41035267e-01, 5.97848980e-02], 

442 [2.42032656e-01, 5.53999834e-02], [2.42981787e-01, 5.09403468e-02], 

443 [2.43881746e-01, 4.64002574e-02], [2.44731618e-01, 4.17739844e-02], 

444 [2.48004373e-01, 3.96335251e-02], [2.53635676e-01, 4.06269030e-02], 

445 [2.58426595e-01, 4.15200350e-02], [2.62587153e-01, 4.23139380e-02], 

446 [2.66327377e-01, 4.30096290e-02], [2.69857289e-01, 4.36081248e-02], 

447 [2.73386916e-01, 4.41104425e-02], [2.77136095e-01, 4.45185137e-02], 

448 [2.81686172e-01, 4.49167415e-02], [2.86059572e-01, 4.52505561e-02], 

449 [2.90315087e-01, 4.55181830e-02], [2.94511509e-01, 4.57178472e-02], 

450 [2.98707633e-01, 4.58477742e-02], [3.02962251e-01, 4.59061892e-02], 

451 [3.07334157e-01, 4.58913175e-02], [3.11882144e-01, 4.58013842e-02], 

452 [3.16163999e-01, 4.56260578e-02], [3.20364728e-01, 4.53392745e-02], 

453 [3.24552010e-01, 4.49599161e-02], [3.28754468e-01, 4.45083053e-02], 

454 [3.33000723e-01, 4.40047646e-02], [3.37319396e-01, 4.34696166e-02], 

455 [3.41739110e-01, 4.29231841e-02], [3.46288486e-01, 4.23857894e-02], 

456 [3.50619754e-01, 4.29679988e-02], [3.54195757e-01, 4.55158258e-02], 

457 [3.58046266e-01, 4.57683865e-02], [3.61404779e-01, 4.41255618e-02], 

458 [3.64409935e-01, 4.03824460e-02], [3.68329272e-01, 3.86496012e-02], 

459 [3.72644259e-01, 3.78587189e-02], [3.76950817e-01, 3.70760234e-02], 

460 [3.81238037e-01, 3.62610245e-02], [3.85495013e-01, 3.53732317e-02], 

461 [3.89710839e-01, 3.43721549e-02], [3.93874609e-01, 3.32173035e-02], 

462 [3.97975415e-01, 3.18681874e-02], [4.02040813e-01, 3.03843958e-02], 

463 [4.06171694e-01, 2.88827227e-02], [4.10325795e-01, 2.73247743e-02], 

464 [4.14453652e-01, 2.56705391e-02], [4.18505801e-01, 2.38800060e-02], 

465 [4.22432777e-01, 2.19131636e-02], [4.26185115e-01, 1.97300005e-02], 

466 [4.29713351e-01, 1.72905055e-02], [4.32968019e-01, 1.45546672e-02], 

467 [4.35899655e-01, 1.14824744e-02], [4.37947185e-01, 9.20518422e-03], 

468 [4.40409231e-01, 8.23893126e-03], [4.43933454e-01, 7.71247651e-03], 

469 [4.48362633e-01, 7.48160487e-03], [4.53539545e-01, 7.40210123e-03], 

470 [4.59306972e-01, 7.32975048e-03], [4.65888477e-01, 7.11072685e-03], 

471 [4.72579311e-01, 6.83103276e-03], [4.77520884e-01, 6.62053683e-03], 

472 [4.81282017e-01, 6.44392261e-03], [4.84431531e-01, 6.26587366e-03], 

473 [4.87538245e-01, 6.05107355e-03], [4.91170982e-01, 5.76420583e-03], 

474 [4.96599033e-01, 4.75791906e-03], [5.00000000e-01, 2.45820721e-03], 

475 [5.00000000e-01, -2.45820721e-03], [4.96599033e-01, -4.75791906e-03], 

476 [4.91170982e-01, -5.76420583e-03], [4.87538245e-01, -6.05107355e-03], 

477 [4.84431531e-01, -6.26587366e-03], [4.81282017e-01, -6.44392261e-03], 

478 [4.77520884e-01, -6.62053683e-03], [4.72579311e-01, -6.83103276e-03], 

479 [4.65888477e-01, -7.11072685e-03], [4.59306972e-01, -7.32975048e-03], 

480 [4.53539545e-01, -7.40210123e-03], [4.48362633e-01, -7.48160487e-03], 

481 [4.43933454e-01, -7.71247651e-03], [4.40409231e-01, -8.23893126e-03], 

482 [4.37947185e-01, -9.20518422e-03], [4.35899655e-01, -1.14824744e-02], 

483 [4.32968019e-01, -1.45546672e-02], [4.29713351e-01, -1.72905055e-02], 

484 [4.26185115e-01, -1.97300005e-02], [4.22432777e-01, -2.19131636e-02], 

485 [4.18505801e-01, -2.38800060e-02], [4.14453652e-01, -2.56705391e-02], 

486 [4.10325795e-01, -2.73247743e-02], [4.06171694e-01, -2.88827227e-02], 

487 [4.02040813e-01, -3.03843958e-02], [3.97975415e-01, -3.18681874e-02], 

488 [3.93874609e-01, -3.32173035e-02], [3.89710839e-01, -3.43721549e-02], 

489 [3.85495013e-01, -3.53732317e-02], [3.81238037e-01, -3.62610245e-02], 

490 [3.76950817e-01, -3.70760234e-02], [3.72644259e-01, -3.78587189e-02], 

491 [3.68329272e-01, -3.86496012e-02], [3.64409935e-01, -4.03824460e-02], 

492 [3.61404779e-01, -4.41255618e-02], [3.58046266e-01, -4.57683865e-02], 

493 [3.54195757e-01, -4.55158258e-02], [3.50619754e-01, -4.29679988e-02], 

494 [3.46288486e-01, -4.23857894e-02], [3.41739110e-01, -4.29231841e-02], 

495 [3.37319396e-01, -4.34696166e-02], [3.33000723e-01, -4.40047646e-02], 

496 [3.28754468e-01, -4.45083053e-02], [3.24552010e-01, -4.49599161e-02], 

497 [3.20364728e-01, -4.53392745e-02], [3.16163999e-01, -4.56260578e-02], 

498 [3.11882144e-01, -4.58013842e-02], [3.07334157e-01, -4.58913175e-02], 

499 [3.02962251e-01, -4.59061892e-02], [2.98707633e-01, -4.58477742e-02], 

500 [2.94511509e-01, -4.57178472e-02], [2.90315087e-01, -4.55181830e-02], 

501 [2.86059572e-01, -4.52505561e-02], [2.81686172e-01, -4.49167415e-02], 

502 [2.77136095e-01, -4.45185137e-02], [2.73386916e-01, -4.41104425e-02], 

503 [2.69857289e-01, -4.36081248e-02], [2.66327377e-01, -4.30096290e-02], 

504 [2.62587153e-01, -4.23139380e-02], [2.58426595e-01, -4.15200350e-02], 

505 [2.53635676e-01, -4.06269030e-02], [2.48004373e-01, -3.96335251e-02], 

506 [2.44731618e-01, -4.17739844e-02], [2.43881746e-01, -4.64002574e-02], 

507 [2.42981787e-01, -5.09403468e-02], [2.42032656e-01, -5.53999834e-02], 

508 [2.41035267e-01, -5.97848980e-02], [2.39990533e-01, -6.41008214e-02], 

509 [2.38899370e-01, -6.83534843e-02], [2.37762692e-01, -7.25486175e-02], 

510 [2.36581411e-01, -7.66919517e-02], [2.35356443e-01, -8.07892177e-02], 

511 [2.34088702e-01, -8.48461463e-02], [2.32779102e-01, -8.88684682e-02], 

512 [2.31428556e-01, -9.28619142e-02], [2.30037979e-01, -9.68322151e-02], 

513 [2.28608285e-01, -1.00785102e-01], [2.27140388e-01, -1.04726305e-01], 

514 [2.25635202e-01, -1.08661555e-01], [2.24093642e-01, -1.12596583e-01], 

515 [2.22516621e-01, -1.16537119e-01], [2.20914927e-01, -1.20500800e-01], 

516 [2.19289138e-01, -1.24515232e-01], [2.17623539e-01, -1.28559552e-01], 

517 [2.15902657e-01, -1.32611119e-01], [2.14111019e-01, -1.36647290e-01], 

518 [2.12233153e-01, -1.40645424e-01], [2.10253586e-01, -1.44582880e-01], 

519 [2.08156845e-01, -1.48437015e-01], [2.05927459e-01, -1.52185189e-01], 

520 [2.03549954e-01, -1.55804760e-01], [2.01008859e-01, -1.59273085e-01], 

521 [1.98288699e-01, -1.62567524e-01], [1.95460443e-01, -1.65525524e-01], 

522 [1.92021332e-01, -1.68410438e-01], [1.87984545e-01, -1.71230243e-01], 

523 [1.83654362e-01, -1.73730954e-01], [1.79335065e-01, -1.75658590e-01], 

524 [1.75330935e-01, -1.76759167e-01], [1.71946252e-01, -1.76778701e-01], 

525 [1.69672107e-01, -1.75699747e-01], [1.68090261e-01, -1.73700374e-01], 

526 [1.67018885e-01, -1.70866193e-01], [1.66408711e-01, -1.67313232e-01], 

527 [1.66210468e-01, -1.63157516e-01], [1.66374886e-01, -1.58515074e-01], 

528 [1.66852697e-01, -1.53501933e-01], [1.67594629e-01, -1.48234120e-01], 

529 [1.68551414e-01, -1.42827662e-01], [1.69673781e-01, -1.37398586e-01], 

530 [1.70912462e-01, -1.32062919e-01], [1.71831946e-01, -1.28572795e-01], 

531 [1.72893469e-01, -1.25077357e-01], [1.74121863e-01, -1.21437441e-01], 

532 [1.75506002e-01, -1.17659979e-01], [1.77034758e-01, -1.13751904e-01], 

533 [1.78697002e-01, -1.09720148e-01], [1.80481608e-01, -1.05571643e-01], 

534 [1.82377447e-01, -1.01313322e-01], [1.84373392e-01, -9.69521163e-02], 

535 [1.86458315e-01, -9.24949589e-02], [1.88621089e-01, -8.79487819e-02], 

536 [1.90647889e-01, -8.37314498e-02], [1.92357507e-01, -8.01689425e-02], 

537 [1.93922227e-01, -7.69238111e-02], [1.95409943e-01, -7.38845104e-02], 

538 [1.96888549e-01, -7.09394950e-02], [1.98425939e-01, -6.79772197e-02], 

539 [2.00090006e-01, -6.48861392e-02], [2.01948645e-01, -6.15547081e-02], 

540 [2.04069750e-01, -5.78713813e-02], [2.06521214e-01, -5.37246134e-02], 

541 [2.09370932e-01, -4.90028591e-02], [2.12686797e-01, -4.35945731e-02], 

542 [2.14737240e-01, -3.90689931e-02], [2.11589723e-01, -3.90909971e-02], 

543 [2.08128934e-01, -3.91286674e-02], [2.04383906e-01, -3.91801218e-02], 

544 [2.00383670e-01, -3.92434783e-02], [1.96157257e-01, -3.93168546e-02], 

545 [1.91733698e-01, -3.93983686e-02], [1.87142025e-01, -3.94861383e-02], 

546 [1.82411269e-01, -3.95782814e-02], [1.77570460e-01, -3.96729159e-02], 

547 [1.72648631e-01, -3.97681595e-02], [1.67674813e-01, -3.98621303e-02], 

548 [1.62678036e-01, -3.99529460e-02], [1.57687333e-01, -4.00387245e-02], 

549 [1.52731734e-01, -4.01175836e-02], [1.47840270e-01, -4.01876413e-02], 

550 [1.43041974e-01, -4.02470155e-02], [1.38365875e-01, -4.02938238e-02], 

551 [1.33841006e-01, -4.03261843e-02], [1.29496398e-01, -4.03422149e-02], 

552 [1.25361081e-01, -4.03400333e-02], [1.21464088e-01, -4.03177574e-02], 

553 [1.17834449e-01, -4.02735051e-02], [1.14054642e-01, -4.01952347e-02], 

554 [1.08903789e-01, -4.00582663e-02], [1.03933805e-01, -3.99022264e-02], 

555 [9.91296018e-02, -3.97286039e-02], [9.44760878e-02, -3.95388881e-02], 

556 [8.99581728e-02, -3.93345683e-02], [8.55607667e-02, -3.91171336e-02], 

557 [8.12687789e-02, -3.88880731e-02], [7.70671192e-02, -3.86488761e-02], 

558 [7.29406971e-02, -3.84010318e-02], [6.88744224e-02, -3.81460293e-02], 

559 [6.48532046e-02, -3.78853578e-02], [6.08619534e-02, -3.76205066e-02], 

560 [5.68855785e-02, -3.73529647e-02], [5.29089894e-02, -3.70842215e-02], 

561 [4.89170960e-02, -3.68157661e-02], [4.48948076e-02, -3.65490876e-02], 

562 [4.08270342e-02, -3.62856753e-02], [3.66986852e-02, -3.60270183e-02], 

563 [3.24946703e-02, -3.57746059e-02], [2.81998991e-02, -3.55299272e-02], 

564 [2.37992814e-02, -3.52944714e-02], [1.92777267e-02, -3.50697277e-02], 

565 [1.46201447e-02, -3.48571853e-02], [9.92571550e-03, -3.46618174e-02], 

566 [5.58716106e-03, -3.44692604e-02], [1.24865487e-03, -3.42517987e-02], 

567 [-3.08979968e-03, -3.40106823e-02], [-7.42819918e-03, -3.37471610e-02], 

568 [-1.17665402e-02, -3.34624847e-02], [-1.61048195e-02, -3.31579034e-02], 

569 [-2.04430334e-02, -3.28346669e-02], [-2.47811788e-02, -3.24940251e-02], 

570 [-2.91192521e-02, -3.21372280e-02], [-3.34572499e-02, -3.17655254e-02], 

571 [-3.77951689e-02, -3.13801673e-02], [-4.21330057e-02, -3.09824036e-02], 

572 [-4.64707569e-02, -3.05734841e-02], [-5.08084190e-02, -3.01546588e-02], 

573 [-5.51459887e-02, -2.97271776e-02], [-5.94834626e-02, -2.92922903e-02], 

574 [-6.38208372e-02, -2.88512469e-02], [-6.81581092e-02, -2.84052973e-02], 

575 [-7.24952752e-02, -2.79556914e-02], [-7.68323318e-02, -2.75036791e-02], 

576 [-8.11692756e-02, -2.70505102e-02], [-8.55061031e-02, -2.65974348e-02], 

577 [-8.98428110e-02, -2.61457026e-02], [-9.41793959e-02, -2.56965637e-02], 

578 [-9.85158544e-02, -2.52512678e-02], [-1.02852183e-01, -2.48110650e-02], 

579 [-1.07188379e-01, -2.43772051e-02], [-1.11524437e-01, -2.39509380e-02], 

580 [-1.15860356e-01, -2.35335136e-02], [-1.20196132e-01, -2.31261818e-02], 

581 [-1.24531760e-01, -2.27301926e-02], [-1.28867239e-01, -2.23467957e-02], 

582 [-1.33202563e-01, -2.19772413e-02], [-1.37537731e-01, -2.16227790e-02], 

583 [-1.41872739e-01, -2.12846589e-02], [-1.46207582e-01, -2.09641308e-02], 

584 [-1.50542259e-01, -2.06624447e-02], [-1.54876765e-01, -2.03808505e-02], 

585 [-1.59458831e-01, -2.01040786e-02], [-1.64274702e-01, -1.98214905e-02], 

586 [-1.69011730e-01, -1.95491016e-02], [-1.73674627e-01, -1.92862459e-02], 

587 [-1.78268108e-01, -1.90322571e-02], [-1.82796886e-01, -1.87864692e-02], 

588 [-1.87265675e-01, -1.85482158e-02], [-1.91679187e-01, -1.83168309e-02], 

589 [-1.96042137e-01, -1.80916482e-02], [-2.00359237e-01, -1.78720016e-02], 

590 [-2.04635201e-01, -1.76572249e-02], [-2.08874743e-01, -1.74466519e-02], 

591 [-2.13082575e-01, -1.72396165e-02], [-2.17263412e-01, -1.70354524e-02], 

592 [-2.21421967e-01, -1.68334935e-02], [-2.25562953e-01, -1.66330737e-02], 

593 [-2.29691084e-01, -1.64335267e-02], [-2.33811073e-01, -1.62341864e-02], 

594 [-2.37927633e-01, -1.60343865e-02], [-2.42045478e-01, -1.58334610e-02], 

595 [-2.46169321e-01, -1.56307436e-02], [-2.50303877e-01, -1.54255682e-02], 

596 [-2.54453857e-01, -1.52172685e-02], [-2.58623976e-01, -1.50051785e-02], 

597 [-2.62818947e-01, -1.47886318e-02], [-2.67043484e-01, -1.45669625e-02], 

598 [-2.71302299e-01, -1.43395042e-02], [-2.75600107e-01, -1.41055908e-02], 

599 [-2.79941621e-01, -1.38645562e-02], [-2.84331553e-01, -1.36157341e-02], 

600 [-2.88774618e-01, -1.33584584e-02], [-2.93275530e-01, -1.30920628e-02], 

601 [-2.97839001e-01, -1.28158813e-02], [-3.02469744e-01, -1.25292477e-02], 

602 [-3.07007487e-01, -1.22434354e-02], [-3.11346727e-01, -1.19792586e-02], 

603 [-3.15741700e-01, -1.17238394e-02], [-3.20188231e-01, -1.14769850e-02], 

604 [-3.24682143e-01, -1.12385028e-02], [-3.29219260e-01, -1.10082002e-02], 

605 [-3.33795405e-01, -1.07858844e-02], [-3.38406402e-01, -1.05713629e-02], 

606 [-3.43048074e-01, -1.03644429e-02], [-3.47716245e-01, -1.01649318e-02], 

607 [-3.52406739e-01, -9.97263685e-03], [-3.57115379e-01, -9.78736550e-03], 

608 [-3.61837989e-01, -9.60892505e-03], [-3.66570392e-01, -9.43712281e-03], 

609 [-3.71308412e-01, -9.27176615e-03], [-3.76047873e-01, -9.11266238e-03], 

610 [-3.80784598e-01, -8.95961884e-03], [-3.85514411e-01, -8.81244288e-03], 

611 [-3.90233135e-01, -8.67094182e-03], [-3.94936595e-01, -8.53492300e-03], 

612 [-3.99620612e-01, -8.40419377e-03], [-4.04281012e-01, -8.27856145e-03], 

613 [-4.08913618e-01, -8.15783338e-03], [-4.13514253e-01, -8.04181689e-03], 

614 [-4.18078741e-01, -7.93031933e-03], [-4.22602906e-01, -7.82314803e-03], 

615 [-4.27082571e-01, -7.72011032e-03], [-4.31513560e-01, -7.62101355e-03], 

616 [-4.35891696e-01, -7.52566504e-03], [-4.40212803e-01, -7.43387214e-03], 

617 [-4.44472704e-01, -7.34544217e-03], [-4.48667224e-01, -7.26018248e-03], 

618 [-4.52792185e-01, -7.17790040e-03], [-4.56843412e-01, -7.09840326e-03], 

619 [-4.60816728e-01, -7.02149842e-03], [-4.64707956e-01, -6.94699319e-03], 

620 [-4.68512920e-01, -6.87469491e-03], [-4.72227445e-01, -6.80441093e-03], 

621 [-4.75847352e-01, -6.73594857e-03], [-4.79368466e-01, -6.66911518e-03], 

622 [-4.82786611e-01, -6.60371808e-03], [-4.86097610e-01, -6.53956463e-03], 

623 [-4.90164100e-01, -6.33588717e-03], [-4.95224935e-01, -4.98692300e-03], 

624 [-4.98907255e-01, -2.70675451e-03], [-5.00000000e-01, -0.00000000e+00],])) 

625"""Outline of an *Gnathonemus petersii* viewed from top.""" 

626 

627Gpetersii_side = dict(body=np.array([ 

628 [3.28398160e-01, 5.06559092e-02], [3.19199094e-01, 5.38197145e-02], 

629 [3.11056574e-01, 5.67169119e-02], [3.03696263e-01, 5.93946914e-02], 

630 [2.96843822e-01, 6.19002432e-02], [2.90224916e-01, 6.42807572e-02], 

631 [2.83565204e-01, 6.65834236e-02], [2.76590351e-01, 6.88554323e-02], 

632 [2.69026018e-01, 7.11439734e-02], [2.60597868e-01, 7.34962371e-02], 

633 [2.51261770e-01, 7.59025132e-02], [2.43304744e-01, 7.78395380e-02], 

634 [2.35356403e-01, 7.96898763e-02], [2.27413394e-01, 8.14533275e-02], 

635 [2.19472365e-01, 8.31296909e-02], [2.11529962e-01, 8.47187659e-02], 

636 [2.03582833e-01, 8.62203518e-02], [1.95627625e-01, 8.76342480e-02], 

637 [1.87660985e-01, 8.89602539e-02], [1.79679560e-01, 9.01981688e-02], 

638 [1.71679998e-01, 9.13477919e-02], [1.63658946e-01, 9.24089228e-02], 

639 [1.55613050e-01, 9.33813608e-02], [1.47538958e-01, 9.42649051e-02], 

640 [1.39433318e-01, 9.50593552e-02], [1.31292776e-01, 9.57645104e-02], 

641 [1.23120936e-01, 9.63719552e-02], [1.14971217e-01, 9.67676996e-02], 

642 [1.06847368e-01, 9.69472966e-02], [9.87430764e-02, 9.69522341e-02], 

643 [9.06520304e-02, 9.68239998e-02], [8.25679181e-02, 9.66040816e-02], 

644 [7.44844274e-02, 9.63339672e-02], [6.63952465e-02, 9.60551445e-02], 

645 [5.82940635e-02, 9.58091011e-02], [5.01745663e-02, 9.56373250e-02], 

646 [4.20304431e-02, 9.55813039e-02], [3.38553820e-02, 9.56825256e-02], 

647 [2.57298350e-02, 9.58827923e-02], [1.76079099e-02, 9.60920363e-02], 

648 [9.48768052e-03, 9.63204279e-02], [1.36979063e-03, 9.65782091e-02], 

649 [-6.74511599e-03, 9.68756218e-02], [-1.48563955e-02, 9.72229079e-02], 

650 [-2.29634043e-02, 9.76303093e-02], [-3.10654983e-02, 9.81080680e-02], 

651 [-3.91620340e-02, 9.86664259e-02], [-4.72523675e-02, 9.93156249e-02], 

652 [-5.53358549e-02, 1.00065907e-01], [-6.34118526e-02, 1.00927514e-01], 

653 [-7.18993466e-02, 1.02261625e-01], [-8.11969648e-02, 1.04253362e-01], 

654 [-8.90809864e-02, 1.05638275e-01], [-9.53015070e-02, 1.04903992e-01], 

655 [-1.02836258e-01, 1.02264667e-01], [-1.10086242e-01, 9.86850726e-02], 

656 [-1.17131132e-01, 9.44949291e-02], [-1.24050604e-01, 9.00239548e-02], 

657 [-1.30924330e-01, 8.56018686e-02], [-1.37851925e-01, 8.14694061e-02], 

658 [-1.44838326e-01, 7.73740401e-02], [-1.51858499e-01, 7.32981929e-02], 

659 [-1.58924240e-01, 6.92790656e-02], [-1.66047343e-01, 6.53538597e-02], 

660 [-1.73239603e-01, 6.15597764e-02], [-1.80512814e-01, 5.79340171e-02], 

661 [-1.87878771e-01, 5.45137830e-02], [-1.95349269e-01, 5.13362755e-02], 

662 [-2.02936102e-01, 4.84386959e-02], [-2.10670820e-01, 4.57953884e-02], 

663 [-2.18446301e-01, 4.33277308e-02], [-2.26244579e-01, 4.10351911e-02], 

664 [-2.34068253e-01, 3.89156690e-02], [-2.41919921e-01, 3.69670639e-02], 

665 [-2.49802182e-01, 3.51872756e-02], [-2.57717636e-01, 3.35742036e-02], 

666 [-2.65668880e-01, 3.21257476e-02], [-2.73658515e-01, 3.08398071e-02], 

667 [-2.81689139e-01, 2.97142819e-02], [-2.89763351e-01, 2.87470714e-02], 

668 [-2.97883750e-01, 2.79360754e-02], [-3.06009884e-01, 2.72879374e-02], 

669 [-3.14146832e-01, 2.68972145e-02], [-3.22397750e-01, 2.67791098e-02], 

670 [-3.30694484e-01, 2.69229164e-02], [-3.38968880e-01, 2.73179271e-02], 

671 [-3.47152784e-01, 2.79534348e-02], [-3.55178043e-01, 2.88187325e-02], 

672 [-3.62976502e-01, 2.99031130e-02], [-3.69491245e-01, 3.10922787e-02], 

673 [-3.75027729e-01, 3.30847269e-02], [-3.81405217e-01, 3.62096529e-02], 

674 [-3.88406343e-01, 4.02454207e-02], [-3.95813736e-01, 4.49703940e-02], 

675 [-4.03410029e-01, 5.01629368e-02], [-4.10977853e-01, 5.56014128e-02], 

676 [-4.18299839e-01, 6.10641860e-02], [-4.25158619e-01, 6.63296202e-02], 

677 [-4.31760708e-01, 7.17542834e-02], [-4.38394579e-01, 7.77938083e-02], 

678 [-4.44929264e-01, 8.41654014e-02], [-4.51237520e-01, 9.05858251e-02], 

679 [-4.57192105e-01, 9.67718415e-02], [-4.62665777e-01, 1.02440213e-01], 

680 [-4.67531294e-01, 1.07307702e-01], [-4.71931542e-01, 1.11312203e-01], 

681 [-4.78923098e-01, 1.15752170e-01], [-4.86766570e-01, 1.17829063e-01], 

682 [-4.94275150e-01, 1.15910154e-01], [-5.00000000e-01, 1.10078411e-01], 

683 [-4.99192237e-01, 1.02492362e-01], [-4.95460406e-01, 9.53394385e-02], 

684 [-4.90446832e-01, 8.86539346e-02], [-4.85474910e-01, 8.23552411e-02], 

685 [-4.80116940e-01, 7.63023767e-02], [-4.74386527e-01, 7.03935158e-02], 

686 [-4.68507746e-01, 6.45968551e-02], [-4.62704674e-01, 5.88805917e-02], 

687 [-4.57087282e-01, 5.31415261e-02], [-4.51221030e-01, 4.74785794e-02], 

688 [-4.45249806e-01, 4.20462447e-02], [-4.39272028e-01, 3.66480353e-02], 

689 [-4.33386114e-01, 3.10874644e-02], [-4.27293901e-01, 2.49068083e-02], 

690 [-4.21087150e-01, 1.80749383e-02], [-4.16972691e-01, 1.18889928e-02], 

691 [-4.14100660e-01, 5.57059642e-03], [-4.13927617e-01, -2.87320530e-03], 

692 [-4.16518117e-01, -1.03191259e-02], [-4.21249030e-01, -1.68743839e-02], 

693 [-4.26080311e-01, -2.35119600e-02], [-4.31143825e-01, -2.98817748e-02], 

694 [-4.36565107e-01, -3.57666535e-02], [-4.42259695e-01, -4.15631093e-02], 

695 [-4.48046856e-01, -4.73643011e-02], [-4.53759024e-01, -5.32064303e-02], 

696 [-4.59228634e-01, -5.91256981e-02], [-4.64931315e-01, -6.50893424e-02], 

697 [-4.70589921e-01, -7.07522385e-02], [-4.75576511e-01, -7.69772899e-02], 

698 [-4.78536384e-01, -8.45179044e-02], [-4.74937079e-01, -9.12035958e-02], 

699 [-4.66829596e-01, -9.29521810e-02], [-4.61234889e-01, -9.14597979e-02], 

700 [-4.55669467e-01, -8.90770697e-02], [-4.49258458e-01, -8.57384117e-02], 

701 [-4.42087882e-01, -8.14195162e-02], [-4.34243761e-01, -7.60960754e-02], 

702 [-4.25812116e-01, -6.97437814e-02], [-4.17545810e-01, -6.28897517e-02], 

703 [-4.10849771e-01, -5.68192385e-02], [-4.05159512e-01, -5.14279217e-02], 

704 [-3.99837805e-01, -4.65592652e-02], [-3.94247419e-01, -4.20567325e-02], 

705 [-3.87639055e-01, -3.76642221e-02], [-3.80497028e-01, -3.35435708e-02], 

706 [-3.73372036e-01, -2.99473943e-02], [-3.66154758e-01, -2.67737367e-02], 

707 [-3.58735871e-01, -2.39206424e-02], [-3.51006055e-01, -2.12861559e-02], 

708 [-3.43031055e-01, -1.88366028e-02], [-3.35174557e-01, -1.68266393e-02], 

709 [-3.27215655e-01, -1.52099446e-02], [-3.19183889e-01, -1.39534630e-02], 

710 [-3.11108797e-01, -1.30241389e-02], [-3.03019606e-01, -1.23889110e-02], 

711 [-2.94902329e-01, -1.21051718e-02], [-2.86785465e-01, -1.22505295e-02], 

712 [-2.78689352e-01, -1.28241713e-02], [-2.70634327e-01, -1.38252844e-02], 

713 [-2.62640729e-01, -1.52530562e-02], [-2.54843728e-01, -1.70549007e-02], 

714 [-2.47426741e-01, -1.90690048e-02], [-2.40252617e-01, -2.12696898e-02], 

715 [-2.33188150e-01, -2.36395350e-02], [-2.26100136e-01, -2.61611196e-02], 

716 [-2.18855371e-01, -2.88170232e-02], [-2.11320649e-01, -3.15898249e-02], 

717 [-2.03362765e-01, -3.44621040e-02], [-1.94848516e-01, -3.74164400e-02], 

718 [-1.85644696e-01, -4.04354121e-02], [-1.77857648e-01, -4.29185708e-02], 

719 [-1.70156514e-01, -4.54297763e-02], [-1.62430938e-01, -4.80126941e-02], 

720 [-1.54702578e-01, -5.06686981e-02], [-1.46993089e-01, -5.33991620e-02], 

721 [-1.39324130e-01, -5.62054598e-02], [-1.31717358e-01, -5.90889651e-02], 

722 [-1.24194428e-01, -6.20510518e-02], [-1.15662563e-01, -6.55718263e-02], 

723 [-1.05305133e-01, -7.02341332e-02], [-9.63092593e-02, -7.46194507e-02], 

724 [-8.86323630e-02, -7.85171774e-02], [-8.22318645e-02, -8.17167120e-02], 

725 [-7.70651844e-02, -8.40074533e-02], [-7.27307320e-02, -8.52544279e-02], 

726 [-6.61297323e-02, -8.61569494e-02], [-5.88746549e-02, -8.65921485e-02], 

727 [-5.10837990e-02, -8.66425980e-02], [-4.28754638e-02, -8.63908707e-02], 

728 [-3.43679487e-02, -8.59195395e-02], [-2.56795531e-02, -8.53111772e-02], 

729 [-1.69285762e-02, -8.46483565e-02], [-8.23331730e-03, -8.40136504e-02], 

730 [2.87924220e-04, -8.34896316e-02], [8.52573555e-03, -8.31566770e-02], 

731 [1.66602603e-02, -8.29060392e-02], [2.47824955e-02, -8.26453400e-02], 

732 [3.28955760e-02, -8.23839938e-02], [4.10026368e-02, -8.21314148e-02], 

733 [4.91068127e-02, -8.18970175e-02], [5.72112386e-02, -8.16902162e-02], 

734 [6.53190496e-02, -8.15204252e-02], [7.34333805e-02, -8.13970590e-02], 

735 [8.15573663e-02, -8.13295317e-02], [8.96941418e-02, -8.13272578e-02], 

736 [9.73182938e-02, -8.14294047e-02], [1.05133937e-01, -8.16889268e-02], 

737 [1.13212537e-01, -8.20789122e-02], [1.21487501e-01, -8.25701110e-02], 

738 [1.29892236e-01, -8.31332728e-02], [1.38360149e-01, -8.37391475e-02], 

739 [1.46824648e-01, -8.43584849e-02], [1.55219140e-01, -8.49620349e-02], 

740 [1.63477033e-01, -8.55205474e-02], [1.71531735e-01, -8.60047721e-02], 

741 [1.79316652e-01, -8.63854590e-02], [1.87152832e-01, -8.66480710e-02], 

742 [1.95714938e-01, -8.68587711e-02], [2.03988092e-01, -8.70050279e-02], 

743 [2.12037249e-01, -8.70805828e-02], [2.19927361e-01, -8.70791767e-02], 

744 [2.27723383e-01, -8.69945509e-02], [2.35490269e-01, -8.68204465e-02], 

745 [2.43292970e-01, -8.65506046e-02], [2.51196443e-01, -8.61787663e-02], 

746 [2.59265639e-01, -8.56986728e-02], [2.67565512e-01, -8.51040652e-02], 

747 [2.76161016e-01, -8.43886846e-02], [2.84315032e-01, -8.35517227e-02], 

748 [2.92367976e-01, -8.24952891e-02], [3.00378722e-01, -8.12485380e-02], 

749 [3.08356779e-01, -7.98455322e-02], [3.16311653e-01, -7.83203346e-02], 

750 [3.24252851e-01, -7.67070080e-02], [3.32189881e-01, -7.50396152e-02], 

751 [3.40132248e-01, -7.33522191e-02], [3.48089461e-01, -7.16788824e-02], 

752 [3.56071026e-01, -7.00536680e-02], [3.64026861e-01, -6.84887979e-02], 

753 [3.72009305e-01, -6.69046200e-02], [3.80051766e-01, -6.54556124e-02], 

754 [3.88122672e-01, -6.43368550e-02], [3.96190448e-01, -6.37434279e-02], 

755 [4.04340123e-01, -6.37872322e-02], [4.12476471e-01, -6.41239731e-02], 

756 [4.20403940e-01, -6.51405095e-02], [4.28117275e-01, -6.73846014e-02], 

757 [4.35523022e-01, -7.11297084e-02], [4.42484598e-01, -7.53221252e-02], 

758 [4.49115562e-01, -7.98271859e-02], [4.55502974e-01, -8.46869603e-02], 

759 [4.61733900e-01, -8.99435183e-02], [4.67658749e-01, -9.54772245e-02], 

760 [4.73314668e-01, -1.01437536e-01], [4.78657130e-01, -1.07622152e-01], 

761 [4.83476951e-01, -1.14118977e-01], [4.88829477e-01, -1.20095662e-01], 

762 [4.96557440e-01, -1.21699267e-01], [5.00000000e-01, -1.15512690e-01], 

763 [4.98665409e-01, -1.07139467e-01], [4.95396547e-01, -9.99420672e-02], 

764 [4.90643016e-01, -9.32118670e-02], [4.85494221e-01, -8.69406630e-02], 

765 [4.80139213e-01, -8.08541451e-02], [4.74769874e-01, -7.47571744e-02], 

766 [4.69820081e-01, -6.91463092e-02], [4.64751557e-01, -6.43078085e-02], 

767 [4.59059041e-01, -5.97235164e-02], [4.52382076e-01, -5.49860206e-02], 

768 [4.44360207e-01, -4.96879085e-02], [4.41478998e-01, -4.45081546e-02], 

769 [4.42186082e-01, -3.43341453e-02], [4.41285932e-01, -2.62902902e-02], 

770 [4.36671579e-01, -1.97961477e-02], [4.30482679e-01, -1.44337295e-02], 

771 [4.24302435e-01, -9.31069238e-03], [4.18173472e-01, -4.20392632e-03], 

772 [4.11837700e-01, 9.23360322e-04], [4.05352767e-01, 6.03208266e-03], 

773 [3.98776322e-01, 1.10831558e-02], [3.92166014e-01, 1.60374948e-02], 

774 [3.85579490e-01, 2.08560149e-02], [3.79074399e-01, 2.54996310e-02], 

775 [3.73613887e-01, 2.91974775e-02], [3.67336756e-01, 3.27992505e-02], 

776 [3.59583302e-01, 3.68507411e-02], [3.51083120e-01, 4.10070508e-02], 

777 [3.42565805e-01, 4.49232811e-02], [3.34760953e-01, 4.82545334e-02]]), 

778 fin0=np.array([ 

779 [-9.23715076e-02, 1.07240277e-01], [-9.35295965e-02, 1.07594433e-01], 

780 [-9.67256646e-02, 1.08568249e-01], [-1.01542414e-01, 1.10028743e-01], 

781 [-1.07562547e-01, 1.11842936e-01], [-1.14368767e-01, 1.13877847e-01], 

782 [-1.21543774e-01, 1.16000494e-01], [-1.28670272e-01, 1.18077899e-01], 

783 [-1.35330963e-01, 1.19977081e-01], [-1.41134680e-01, 1.21576288e-01], 

784 [-1.46606509e-01, 1.23053436e-01], [-1.52060241e-01, 1.24502551e-01], 

785 [-1.57506075e-01, 1.25921270e-01], [-1.62954205e-01, 1.27307227e-01], 

786 [-1.68414830e-01, 1.28658058e-01], [-1.73898145e-01, 1.29971399e-01], 

787 [-1.79414348e-01, 1.31244885e-01], [-1.84887478e-01, 1.32455496e-01], 

788 [-1.90359489e-01, 1.33335047e-01], [-1.96015001e-01, 1.33209743e-01], 

789 [-2.01162399e-01, 1.31563565e-01], [-2.04627703e-01, 1.28316201e-01], 

790 [-2.07067923e-01, 1.23267049e-01], [-2.08878927e-01, 1.16897283e-01], 

791 [-2.10020541e-01, 1.12297166e-01], [-2.11393373e-01, 1.06917040e-01], 

792 [-2.12954078e-01, 1.01093164e-01], [-2.14659311e-01, 9.51617962e-02], 

793 [-2.16465726e-01, 8.94591952e-02], [-2.18365897e-01, 8.41154074e-02], 

794 [-2.20352206e-01, 7.88099956e-02], [-2.22436308e-01, 7.35689663e-02], 

795 [-2.24659365e-01, 6.84031347e-02], [-2.27062539e-01, 6.33233164e-02], 

796 [-2.29686992e-01, 5.83403267e-02], [-2.32573887e-01, 5.34649810e-02], 

797 [-2.36430031e-01, 4.83943841e-02], [-2.41498676e-01, 4.29607364e-02], 

798 [-2.46187623e-01, 3.83728372e-02], [-2.48885034e-01, 3.58636954e-02], 

799 [-2.48622153e-01, 3.57912618e-02], [-2.46557549e-01, 3.62272274e-02], 

800 [-2.43025387e-01, 3.70044307e-02], [-2.38266996e-01, 3.81013749e-02], 

801 [-2.32523708e-01, 3.94965634e-02], [-2.26036853e-01, 4.11684994e-02], 

802 [-2.19047762e-01, 4.30956865e-02], [-2.11797764e-01, 4.52566278e-02], 

803 [-2.04528191e-01, 4.76298267e-02], [-1.97480374e-01, 5.01937866e-02], 

804 [-1.91394789e-01, 5.27029072e-02], [-1.86459609e-01, 5.49493825e-02], 

805 [-1.81052095e-01, 5.75526666e-02], [-1.75250688e-01, 6.04617194e-02], 

806 [-1.69133831e-01, 6.36255006e-02], [-1.62779966e-01, 6.69929702e-02], 

807 [-1.56267535e-01, 7.05130879e-02], [-1.49674979e-01, 7.41348134e-02], 

808 [-1.43080740e-01, 7.78071067e-02], [-1.36563261e-01, 8.14789275e-02], 

809 [-1.30200984e-01, 8.50992356e-02], [-1.24072349e-01, 8.86169909e-02], 

810 [-1.18255800e-01, 9.19811531e-02], [-1.12829778e-01, 9.51406820e-02], 

811 [-1.07872725e-01, 9.80445375e-02], [-1.03463084e-01, 1.00641679e-01], 

812 [-9.96792947e-02, 1.02881067e-01], [-9.65998008e-02, 1.04711661e-01], 

813 [-9.43030437e-02, 1.06082421e-01], [-9.28674653e-02, 1.06942306e-01]]), 

814 fin1=np.array([ 

815 [-5.63562109e-02, -8.66230690e-02], [-5.80378311e-02, -8.77598862e-02], 

816 [-6.25544177e-02, -9.07828740e-02], [-6.91135601e-02, -9.51108371e-02], 

817 [-7.69228473e-02, -1.00162580e-01], [-8.51898685e-02, -1.05356908e-01], 

818 [-9.31222129e-02, -1.10112625e-01], [-9.99878561e-02, -1.13889019e-01], 

819 [-1.06504731e-01, -1.17311843e-01], [-1.13074811e-01, -1.20683973e-01], 

820 [-1.19721672e-01, -1.23894532e-01], [-1.26468889e-01, -1.26832643e-01], 

821 [-1.33340040e-01, -1.29387427e-01], [-1.40358701e-01, -1.31448008e-01], 

822 [-1.47580880e-01, -1.32990365e-01], [-1.54940053e-01, -1.33335047e-01], 

823 [-1.61577933e-01, -1.30712902e-01], [-1.67054395e-01, -1.26102505e-01], 

824 [-1.71669835e-01, -1.20355834e-01], [-1.75809346e-01, -1.14080721e-01], 

825 [-1.79869801e-01, -1.07847816e-01], [-1.83893833e-01, -1.01567472e-01], 

826 [-1.87727742e-01, -9.52536460e-02], [-1.91491183e-01, -8.89575805e-02], 

827 [-1.95303810e-01, -8.27305179e-02], [-1.99285279e-01, -7.66237008e-02], 

828 [-2.03323939e-01, -7.09497866e-02], [-2.07222716e-01, -6.56608257e-02], 

829 [-2.11321456e-01, -6.03101264e-02], [-2.15707243e-01, -5.49148986e-02], 

830 [-2.20467161e-01, -4.94923522e-02], [-2.25688295e-01, -4.40596970e-02], 

831 [-2.31457727e-01, -3.86341430e-02], [-2.37862543e-01, -3.32328999e-02], 

832 [-2.46515829e-01, -2.68980564e-02], [-2.55762572e-01, -2.13588469e-02], 

833 [-2.63822695e-01, -1.73872025e-02], [-2.69995895e-01, -1.48443106e-02], 

834 [-2.73581870e-01, -1.35913585e-02], [-2.73905506e-01, -1.34429496e-02], 

835 [-2.70916623e-01, -1.39170287e-02], [-2.65183910e-01, -1.49680871e-02], 

836 [-2.57298969e-01, -1.66581465e-02], [-2.47853402e-01, -1.90492292e-02], 

837 [-2.37438812e-01, -2.22033569e-02], [-2.27950178e-01, -2.55768430e-02], 

838 [-2.20118830e-01, -2.83655326e-02], [-2.12826783e-01, -3.08912332e-02], 

839 [-2.05971274e-01, -3.32032068e-02], [-1.99449541e-01, -3.53507153e-02], 

840 [-1.93158823e-01, -3.73830207e-02], [-1.86996359e-01, -3.93493848e-02], 

841 [-1.80859385e-01, -4.12990695e-02], [-1.74645142e-01, -4.32813368e-02], 

842 [-1.68250866e-01, -4.53454486e-02], [-1.61573797e-01, -4.75406669e-02], 

843 [-1.54511172e-01, -4.99162535e-02], [-1.46960230e-01, -5.25214703e-02], 

844 [-1.38818209e-01, -5.54055794e-02], [-1.31057252e-01, -5.82788279e-02], 

845 [-1.23738218e-01, -6.13446244e-02], [-1.16211608e-01, -6.47801054e-02], 

846 [-1.08665309e-01, -6.84191129e-02], [-1.01287211e-01, -7.20954885e-02], 

847 [-9.42652035e-02, -7.56430740e-02], [-8.77871747e-02, -7.88957112e-02], 

848 [-8.20410142e-02, -8.16872418e-02], [-7.72146108e-02, -8.38515077e-02], 

849 [-7.01142594e-02, -8.57539808e-02], [-6.08611143e-02, -8.65416398e-02]]), 

850 fin2=np.array([ 

851 [-4.95709300e-01, 9.71361627e-02], [-4.94727751e-01, 9.40282315e-02], 

852 [-4.92102953e-01, 8.63001401e-02], [-4.89531928e-01, 7.93902959e-02], 

853 [-4.87029725e-01, 7.32981516e-02], [-4.84335965e-01, 6.75182749e-02], 

854 [-4.81551826e-01, 6.25554763e-02], [-4.78127088e-01, 5.76995014e-02], 

855 [-4.74138256e-01, 5.27407642e-02], [-4.69901081e-01, 4.78822911e-02], 

856 [-4.65707580e-01, 4.32915371e-02], [-4.61429843e-01, 3.88748202e-02], 

857 [-4.56778758e-01, 3.47247641e-02], [-4.52133680e-01, 3.06597385e-02], 

858 [-4.47773120e-01, 2.62910115e-02], [-4.43994422e-01, 2.12957780e-02], 

859 [-4.40936734e-01, 1.58644670e-02], [-4.38682055e-01, 1.00694929e-02], 

860 [-4.37395623e-01, 3.93321716e-03], [-4.37251179e-01, -2.22422408e-03], 

861 [-4.38411278e-01, -8.31550780e-03], [-4.40881051e-01, -1.40008006e-02], 

862 [-4.44310154e-01, -1.91401554e-02], [-4.48235249e-01, -2.40147279e-02], 

863 [-4.52186381e-01, -2.88922787e-02], [-4.55951262e-01, -3.38845300e-02], 

864 [-4.59685991e-01, -3.88613661e-02], [-4.63182959e-01, -4.39898598e-02], 

865 [-4.66221839e-01, -4.94607809e-02], [-4.69128507e-01, -5.63647484e-02], 

866 [-4.71915070e-01, -6.41181386e-02], [-4.74263992e-01, -7.12979021e-02], 

867 [-4.75857737e-01, -7.64809898e-02], [-4.76376517e-01, -7.82540679e-02], 

868 [-4.75295478e-01, -7.70124597e-02], [-4.72622968e-01, -7.39633741e-02], 

869 [-4.68700403e-01, -6.95271204e-02], [-4.63869200e-01, -6.41240080e-02], 

870 [-4.58470778e-01, -5.81743460e-02], [-4.52846552e-01, -5.20984438e-02], 

871 [-4.47337939e-01, -4.63166105e-02], [-4.42286358e-01, -4.12491555e-02], 

872 [-4.37409139e-01, -3.64697530e-02], [-4.32541922e-01, -3.13144948e-02], 

873 [-4.27898895e-01, -2.59396949e-02], [-4.23628692e-01, -2.04557516e-02], 

874 [-4.19879947e-01, -1.49730632e-02], [-4.16801293e-01, -9.60202801e-03], 

875 [-4.14541365e-01, -4.45304422e-03], [-4.13248797e-01, 3.63489840e-04], 

876 [-4.13063337e-01, 4.59529287e-03], [-4.14062952e-01, 8.03555956e-03], 

877 [-4.16210151e-01, 1.20244157e-02], [-4.19333841e-01, 1.64554100e-02], 

878 [-4.23262931e-01, 2.12220910e-02], [-4.27826327e-01, 2.62180073e-02], 

879 [-4.32852937e-01, 3.13367077e-02], [-4.38171670e-01, 3.64717406e-02], 

880 [-4.43611431e-01, 4.15166547e-02], [-4.49001130e-01, 4.63649986e-02], 

881 [-4.54169673e-01, 5.09103210e-02], [-4.58945968e-01, 5.50461704e-02], 

882 [-4.65985656e-01, 6.14539934e-02], [-4.72468848e-01, 6.79891568e-02], 

883 [-4.78279615e-01, 7.43791294e-02], [-4.83358777e-01, 8.04000934e-02], 

884 [-4.87647158e-01, 8.58282310e-02], [-4.91085578e-01, 9.04397245e-02], 

885 [-4.93614861e-01, 9.40107561e-02], [-4.95175827e-01, 9.63175081e-02]]), 

886 eye=np.array([0.36, -0.01, 0.015])) 

887"""Outline of an *Gnathonemus petersii* viewed from the side.""" 

888 

889fish_shapes = dict(Alepto_top=Alepto_top, 

890 Alepto_male_side=Alepto_male_side, 

891 Eigenmannia_top=Eigenmannia_top, 

892 Eigenmannia_side=Eigenmannia_side, 

893 Gpetersii_top=Gpetersii_top, 

894 Gpetersii_side=Gpetersii_side) 

895"""Dictionary holding all electric fish shapes.""" 

896 

897fish_top_shapes = dict(Alepto=Alepto_top, 

898 Eigenmannia=Eigenmannia_top, 

899 Gpetersii=Gpetersii_top) 

900"""Dictionary holding electric fish shapes viewed from top.""" 

901 

902fish_side_shapes = dict(Alepto_male=Alepto_male_side, 

903 Eigenmannia=Eigenmannia_side, 

904 Gpetersii=Gpetersii_side) 

905"""Dictionary holding electric fish shapes viewed from the side.""" 

906 

907 

908def fish_shape(fish): 

909 """Get a dictinary containing shapes of a fish. 

910 

911 Parameters 

912 ---------- 

913 fish: string or tuple or dict 

914 Specifies a fish to show: 

915 - any of the strings defining a shape contained in the `fish_shapes` dictionary, 

916 - a tuple with the name of the fish as the first element and 'top' or 'side' as the second element, 

917 - a dictionary with at least a 'body' key holding pathes to be drawn. 

918 

919 Returns 

920 ------- 

921 fish: dict 

922 Dictionary with at least a 'body' key holding pathes to be drawn. 

923 """ 

924 if not isinstance(fish, dict): 

925 if isinstance(fish, (tuple, list)): 

926 if fish[1] == 'top': 

927 fish = fish_top_shapes[fish[0]] 

928 else: 

929 fish = fish_side_shapes[fish[0]] 

930 else: 

931 fish = fish_shapes[fish] 

932 return fish 

933 

934 

935def plot_fish(ax, fish, pos=(0, 0), direction=(1, 0), size=20.0, bend=0, scaley=1, 

936 bodykwargs={}, finkwargs={}, eyekwargs=None): 

937 """Plot body, fins and eye of an electric fish. 

938 

939 Parameters 

940 ---------- 

941 ax: matplotlib axes 

942 Axes where to draw the fish. 

943 fish: string or tuple or dict 

944 Specifies a fish to show: 

945 - any of the strings defining a shape contained in the `fish_shapes` dictionary, 

946 - a tuple with the name of the fish as the first element and 'top' or 'side' as the second element, 

947 - a dictionary with at least a 'body' key holding pathes to be drawn. 

948 pos: tuple of floats 

949 Coordinates of the fish's position (its center). 

950 direction: tuple of floats 

951 Coordinates of a vector defining the orientation of the fish. 

952 size: float 

953 Size of the fish. 

954 bend: float 

955 Bending angle of the fish's tail in degree. 

956 scaley: float 

957 Scale factor applied in y direction after bending and rotation to 

958 compensate for differently scaled axes. 

959 bodykwargs: dict 

960 Key-word arguments for PathPatch used to draw the fish's body. 

961 finkwargs: dict 

962 Key-word arguments for PathPatch used to draw the fish's fins. 

963 

964 Returns 

965 ------- 

966 bpatch: matplotlib.patches.PathPatch 

967 The fish's body. Can be used for set_clip_path(). 

968 

969 Example 

970 ------- 

971 

972 ``` 

973 fig, ax = plt.subplots() 

974 bodykwargs=dict(lw=1, edgecolor='k', facecolor='k') 

975 finkwargs=dict(lw=1, edgecolor='k', facecolor='grey') 

976 fish = (('Eigenmannia', 'side'), (0, 0), (1, 0), 20.0, -25) 

977 plot_fish(ax, *fish, bodykwargs=bodykwargs, finkwargs=finkwargs) 

978 ax.set_xlim(-15, 15) 

979 ax.set_ylim(-10, 10) 

980 plt.show() 

981 ``` 

982 """ 

983 fish = fish_shape(fish) 

984 bpatch = None 

985 size_fac = 1.1 

986 bbox = bbox_pathes(*fish.values()) 

987 trans = mpl.transforms.Affine2D() 

988 angle = np.arctan2(direction[1], direction[0]) 

989 trans.rotate(angle) 

990 #trans.scale(dxu/dyu, dyu/dxu) # what is the right scaling???? 

991 trans.scale(1, scaley) 

992 trans.translate(*pos) 

993 for part, verts in fish.items(): 

994 if part == 'eye': 

995 if eyekwargs is not None: 

996 verts = np.array(verts)*size*size_fac 

997 verts[:2] = trans.transform_point(verts[:2]) 

998 if not 'zorder' in eyekwargs: 

999 eyekwargs['zorder'] = 20 

1000 ax.add_patch(Circle(verts[:2], verts[2], **eyekwargs)) 

1001 continue 

1002 verts = bend_path(verts, bend, size, size_fac) 

1003 codes = np.zeros(len(verts)) 

1004 codes[:] = Path.LINETO 

1005 codes[0] = Path.MOVETO 

1006 codes[-1] = Path.CLOSEPOLY 

1007 path = Path(verts, codes) 

1008 #pixelx = np.abs(np.diff(ax.get_window_extent().get_points()[:,0]))[0] 

1009 #pixely = np.abs(np.diff(ax.get_window_extent().get_points()[:,1]))[0] 

1010 #xmin, xmax = ax.get_xlim() 

1011 #ymin, ymax = ax.get_ylim() 

1012 #dxu = np.abs(xmax - xmin)/pixelx 

1013 #dyu = np.abs(ymax - ymin)/pixely 

1014 path = path.transformed(trans) 

1015 kwargs = bodykwargs if part == 'body' else finkwargs 

1016 if not 'zorder' in kwargs: 

1017 kwargs['zorder'] = 0 if part == 'body' else 10 

1018 patch = PathPatch(path, **kwargs) 

1019 if part == 'body': 

1020 bpatch = patch 

1021 ax.add_patch(patch) 

1022 return bpatch 

1023 

1024 

1025def plot_object(ax, pos=(0, 0), radius=1.0, **kwargs): 

1026 """Plot circular object. 

1027 

1028 Parameters 

1029 ---------- 

1030 ax: matplotlib axes 

1031 Axes where to draw the object. 

1032 pos: tuple of floats 

1033 Coordinates of the objects's position (its center). 

1034 radius: float 

1035 Radius of the cirular object. 

1036 kwargs: key word arguments 

1037 Arguments for Circle used to draw the obkect. 

1038 """ 

1039 ax.add_patch(Circle(pos, radius, **kwargs)) 

1040 

1041 

1042def plot_fishfinder(ax, pos, direction, length, handle=0.05, 

1043 central_ground=False, wires=False, 

1044 rodkwargs=dict(edgecolor='none', facecolor='gray'), 

1045 poskwargs=dict(edgecolor='none', facecolor='red'), 

1046 negkwargs=dict(edgecolor='none', facecolor='blue'), 

1047 gndkwargs=dict(edgecolor='none', facecolor='black'), 

1048 lw=1, zorder=50): 

1049 """Plot a fishfinder with electrodes and wires. 

1050 

1051 Parameters 

1052 ---------- 

1053 ax: matplotlib axes 

1054 Axes where to draw the fishfinder. 

1055 pos: tuple of floats 

1056 Coordinates of the fishfinder's position (its center). 

1057 direction: tuple of floats 

1058 Coordinates defining the orientation of the fishfinder. 

1059 length: float 

1060 Length of the fishfinder (center of positive electrode 

1061 minus center of negative electrode). 

1062 handle: float 

1063 Length of handle (rod beyond the negative electrode) 

1064 as a fraction of the `length` of fishfinder. 

1065 central_ground: bool 

1066 Add a central ground electrode. 

1067 wires: bool, 'postop' or 'negtop' 

1068 Draw wires for each electrode. 

1069 - True or 'postop': draw wire of positive electrode on top. 

1070 - 'negtop': draw wire of negative electrode on top. 

1071 Return the coordinates of the endpoints of the wires. 

1072 rodkwargs: dict 

1073 Key-word arguments for Rectangle used to draw the rod. 

1074 poskwargs: dict 

1075 Key-word arguments for Rectangle used to draw the positive electrode. 

1076 negkwargs: dict 

1077 Key-word arguments for Rectangle used to draw the negative electrode. 

1078 gndkwargs: dict 

1079 Key-word arguments for Rectangle used to draw the ground electrode. 

1080 lw: float 

1081 Width of the lines used for drawing the wires. 

1082 zorder: int 

1083 zorder for the fishfinder. 

1084 

1085 Returns 

1086 ------- 

1087 negpos: tuple of floats 

1088 Coordinates of center of negative electrode. 

1089 pospos: tuple of floats 

1090 Coordinates of center of positive electrode. 

1091 negwirepos: tuple of floats 

1092 If `wire`, the end of the wire of the negative electrode. 

1093 poswirepos: tuple of floats 

1094 If `wire`, the end of the wire of the positive electrode. 

1095 gndwirepos: tuple of floats 

1096 If `central_ground` and `wire`, the end of the wire of 

1097 the ground electrode. 

1098 """ 

1099 width = 0.07*length 

1100 transform = mpt.Affine2D().rotate(np.arctan2(direction[1], direction[0])).translate(*pos) 

1101 

1102 ax.add_patch(Rectangle((-(0.5+handle)*length, -0.5*width), 

1103 (1+handle+0.05)*length, width, 

1104 transform=transform + ax.transData, 

1105 zorder=zorder, **rodkwargs)) 

1106 ax.add_patch(Rectangle((0.5*length-0.4*width, -0.6*width), 

1107 0.8*width, 1.2*width, 

1108 transform=transform + ax.transData, 

1109 zorder=zorder+2, **poskwargs)) 

1110 ax.add_patch(Rectangle((-0.5*length-0.4*width, -0.6*width), 

1111 0.8*width, 1.2*width, 

1112 transform=transform + ax.transData, 

1113 zorder=zorder+2, **negkwargs)) 

1114 nodes = [(-0.5*length, 0), (0.5*length, 0)] 

1115 if central_ground: 

1116 ax.add_patch(Rectangle((-0.4*width, -0.6*width), 

1117 0.8*width, 1.2*width, 

1118 transform=transform + ax.transData, 

1119 zorder=zorder+2, **gndkwargs)) 

1120 if wires: 

1121 offs = 0.03*width*lw 

1122 if wires == 'negtop': 

1123 offs *= -1 

1124 if central_ground: 

1125 offs *= 2 

1126 color = negkwargs.get('facecolor') 

1127 ax.plot((-0.5*length, -(0.5+handle)*length), (-offs, -offs), 

1128 color=color, lw=lw, solid_capstyle='butt', 

1129 transform=transform + ax.transData, zorder=zorder+1) 

1130 color = poskwargs.get('facecolor') 

1131 ax.plot((0.5*length, -(0.5+handle)*length), (offs, offs), 

1132 color=color, lw=lw, solid_capstyle='butt', transform=transform + 

1133 ax.transData, zorder=zorder+1) 

1134 nodes.extend(((-(0.5+handle)*length, -offs), (-(0.5+handle)*length, offs))) 

1135 if central_ground: 

1136 color = gndkwargs.get('facecolor') 

1137 ax.plot((0, -(0.5+handle)*length), (0, 0), 

1138 color=color, lw=lw, solid_capstyle='butt', 

1139 transform=transform + ax.transData, zorder=zorder+1) 

1140 nodes.append((-(0.5+handle)*length, 0)) 

1141 nodes = transform.transform(nodes) 

1142 return nodes 

1143 

1144 

1145def plot_pathes(ax, *vertices, **kwargs): 

1146 """Plot pathes. 

1147 

1148 Parameters 

1149 ---------- 

1150 ax: matplotlib axes 

1151 Axes where to draw the path. 

1152 vertices: one or more 2D arrays 

1153 The coordinates of pathes to be plotted 

1154 (first column x-coordinates, second colum y-coordinates). 

1155 kwargs: key word arguments 

1156 Arguments for PathPatch used to draw the path. 

1157 """ 

1158 for verts in vertices: 

1159 codes = np.zeros(len(verts)) 

1160 codes[:] = Path.LINETO 

1161 codes[0] = Path.MOVETO 

1162 codes[-1] = Path.CLOSEPOLY 

1163 path = Path(verts, codes) 

1164 ax.add_patch(PathPatch(path, **kwargs)) 

1165 bbox = bbox_pathes(*vertices) 

1166 center = np.mean(bbox, axis=0) 

1167 bbox -= center 

1168 bbox *= 1.2 

1169 bbox += center 

1170 ax.set_xlim(*bbox[:,0]) 

1171 ax.set_ylim(*bbox[:,1]) 

1172 

1173 

1174def fish_surface(fish, pos=(0, 0), direction=(1, 0), size=20.0, bend=0, 

1175 gamma=1.0): 

1176 """Generate meshgrid of one side of the fish from shape. 

1177  

1178 Parameters 

1179 ---------- 

1180 fish: string or tuple or dict 

1181 Specifies a fish to show: 

1182 - any of the strings defining a shape contained in the `fish_shapes` dictionary, 

1183 - a tuple with the name of the fish and 'top' or 'side', 

1184 - a dictionary with at least a 'body' key holding pathes to be drawn. 

1185 pos: tuple of floats 

1186 Coordinates of the fish's position (its center). 

1187 direction: tuple of floats 

1188 Coordinates of a vector defining the orientation of the fish. 

1189 size: float 

1190 Size of the fish. 

1191 bend: float 

1192 Bending angle of the fish's tail in degree. 

1193 gamma: float 

1194 Gamma distortion of the ellipse. The ellipse equation is raised 

1195 to the power of gamma before its smaller diameter is scaled up 

1196 from one to the actual value. 

1197 

1198 Returns 

1199 ------- 

1200 xx: 2D array of floats 

1201 x-coordinates in direction of body axis. 

1202 yy: 2D array of floats 

1203 y-coordinates in direction upwards from body axis. 

1204 zz: 2D array of floats 

1205 z-coordinates of fish surface, outside of fish NaN. 

1206 """ 

1207 if direction[1] != 0: 

1208 raise ValueError('rotation not supported by fish_surface yet.') 

1209 fish = fish_shape(fish) 

1210 bbox = bbox_pathes(*fish.values()) 

1211 size_fac = -1.05*0.5/bbox[0,0] 

1212 path = bend_path(fish['body'], bend, size, size_fac) 

1213 # split in top and bottom half: 

1214 minxi = np.argmin(path[:,0]) 

1215 maxxi = np.argmax(path[:,0]) 

1216 i0 = min(minxi, maxxi) 

1217 i1 = max(minxi, maxxi) 

1218 path0 = path[i0:i1,:] 

1219 path1 = np.vstack((path[i0::-1,:], path[:i1:-1,:])) 

1220 if np.mean(path0[:,1]) < np.mean(path1[:,1]): 

1221 path0, path1 = path1, path0 

1222 # make sure x coordinates are monotonically increasing: 

1223 pm = np.maximum.accumulate(path0[:,0]) 

1224 path0 = np.delete(path0, np.where(path0[:,0] < pm)[0], axis=0) 

1225 pm = np.maximum.accumulate(path1[:,0]) 

1226 path1 = np.delete(path1, np.where(path1[:,0] < pm)[0], axis=0) 

1227 # rotate: XXX 

1228 # translate: 

1229 minx = path[minxi,0] + pos[0] 

1230 maxx = path[maxxi,0] + pos[0] 

1231 path0 += pos[:2] 

1232 path1 += pos[:2] 

1233 # interpolate: 

1234 n = 5*max(len(path0), len(path1)) 

1235 #n = 200 

1236 x = np.linspace(minx, maxx, n) 

1237 upperpath = np.zeros((len(x), 2)) 

1238 upperpath[:,0] = x 

1239 upperpath[:,1] = np.interp(x, path0[:,0], path0[:,1]) 

1240 lowerpath = np.zeros((len(x), 2)) 

1241 lowerpath[:,0] = x 

1242 lowerpath[:,1] = np.interp(x, path1[:,0], path1[:,1]) 

1243 # ellipse origin and semi axes: 

1244 midline = np.array(upperpath) 

1245 midline[:,1] = np.mean(np.vstack((upperpath[:,1], lowerpath[:,1])), axis=0) 

1246 diamy = upperpath[:,1] - midline[:,1] 

1247 diamz = 0.3*diamy # take it from the top view! 

1248 # apply ellipse: 

1249 y = np.linspace(np.min(midline[:,1]-diamy), np.max(midline[:,1]+diamy), n//2) 

1250 xx, yy = np.meshgrid(x ,y) 

1251 zz = diamz * (np.sqrt(1.0 - ((yy-midline[:,1])/diamy)**2))**gamma 

1252 return xx, yy, zz 

1253 

1254 

1255def surface_normals(xx, yy, zz): 

1256 """Normal vectors on a surface. 

1257 

1258 Compute surface normals on a surface as returned by `fish_surface()`. 

1259 

1260 Parameters 

1261 ---------- 

1262 xx: 2D array of floats 

1263 Mesh grid of x coordinates. 

1264 yy: 2D array of floats 

1265 Mesh grid of y coordinates. 

1266 zz: 2D array of floats 

1267 z-coordinates of surface on the xx and yy coordinates. 

1268 

1269 Returns 

1270 ------- 

1271 nx: 2D array of floats 

1272 x-coordinates of normal vectors for each point in xx and yy. 

1273 ny: 2D array of floats 

1274 y-coordinates of normal vectors for each point in xx and yy. 

1275 nz: 2D array of floats 

1276 z-coordinates of normal vectors for each point in xx and yy. 

1277 """ 

1278 dx = xx[0,1] - xx[0,0] 

1279 dy = yy[1,0] - yy[0,0] 

1280 nx = np.zeros(xx.shape) 

1281 nx[:,:-1] = -np.diff(zz, axis=1)/dx 

1282 ny = np.zeros(xx.shape) 

1283 ny[:-1,:] = -np.diff(zz, axis=0)/dy 

1284 nz = np.ones(xx.shape) 

1285 norm = np.sqrt(nx*nx+ny*ny+1) 

1286 return nx/norm, ny/norm, nz/norm 

1287 

1288 

1289def extract_path(svgfile, path_index, npoints): 

1290 """Convert SVG pathes to numpy array with path coordinates. 

1291 

1292 Draw a fish outline in inkscape and save it to a svg file. 

1293 

1294 Install the svgpathtools package 

1295 (https://github.com/mathandy/svgpathtools): 

1296 ``` 

1297 pip install svgpathtools 

1298 ``` 

1299  

1300 Parameters 

1301 ---------- 

1302 svgfile: string 

1303 Name of the svg file containing the path. 

1304 path_index: int 

1305 Index selecting the path. 

1306 npoints: int 

1307 Number of points to spread out on the path. 

1308 

1309 Returns 

1310 ------- 

1311 vertices: 2D array 

1312 The coordinates of the outline of a fish. 

1313 npoints rows of x and y coordinates. 

1314 """ 

1315 from svgpathtools import svg2paths2 

1316 

1317 paths, attributes, svg_attributes = svg2paths2(svgfile) 

1318 path = paths[path_index] 

1319 vertices = np.zeros((npoints, 2)) 

1320 for i in range(npoints): 

1321 p = path.point(i/npoints) 

1322 vertices[i, 0] = p.real 

1323 vertices[i, 1] = p.imag 

1324 return vertices 

1325 

1326 

1327def bbox_pathes(*vertices): 

1328 """Common bounding box of pathes. 

1329 

1330 Parameters 

1331 ---------- 

1332 vertices: one or more 2D arrays 

1333 The coordinates of pathes 

1334 (first column x-coordinates, second colum y-coordinates). 

1335 

1336 Returns 

1337 ------- 

1338 bbox: 2D array 

1339 Bounding box of the pathes: [[x0, y0], [x1, y1]] 

1340 """ 

1341 # get bounding box of all pathes: 

1342 bbox = np.zeros((2, 2)) 

1343 first = True 

1344 for verts in vertices: 

1345 if len(verts.shape) != 2: 

1346 continue 

1347 vbbox = np.array([[np.min(verts[:,0]), np.min(verts[:,1])], 

1348 [np.max(verts[:,0]), np.max(verts[:,1])]]) 

1349 if first: 

1350 bbox = vbbox 

1351 first = False 

1352 else: 

1353 bbox[0,0] = min(bbox[0,0], vbbox[0,0]) 

1354 bbox[0,1] = min(bbox[0,1], vbbox[0,1]) 

1355 bbox[1,0] = max(bbox[1,0], vbbox[1,0]) 

1356 bbox[1,1] = max(bbox[1,1], vbbox[1,1]) 

1357 return bbox 

1358 

1359 

1360def translate_pathes(dx, dy, *vertices): 

1361 """Translate pathes in place. 

1362 

1363 Parameters 

1364 ---------- 

1365 dx: float 

1366 Shift in x direction. 

1367 dy: float 

1368 Shift in y direction. 

1369 vertices: one or more 2D arrays 

1370 The coordinates of pathes to be translated 

1371 (first column x-coordinates, second colum y-coordinates). 

1372 """ 

1373 for verts in vertices: 

1374 verts[:,0] += dx 

1375 verts[:,1] += dy 

1376 

1377 

1378def center_pathes(*vertices): 

1379 """Translate pathes to their common origin in place. 

1380 

1381 Parameters 

1382 ---------- 

1383 vertices: one or more 2D arrays 

1384 The coordinates of pathes to be centered 

1385 (first column x-coordinates, second colum y-coordinates). 

1386 """ 

1387 center = np.mean(bbox_pathes(*vertices), axis=1) 

1388 # shift: 

1389 for verts in vertices: 

1390 verts[:,0] -= center[0] 

1391 verts[:,1] -= center[1] 

1392 

1393 

1394def rotate_pathes(theta, *vertices): 

1395 """Rotate pathes in place. 

1396 

1397 Parameters 

1398 ---------- 

1399 theta: float 

1400 Rotation angle in degrees. 

1401 vertices: one or more 2D arrays 

1402 The coordinates of pathes to be rotated 

1403 (first column x-coordinates, second colum y-coordinates). 

1404 """ 

1405 theta *= np.pi/180.0 

1406 # rotation matrix: 

1407 c = np.cos(theta) 

1408 s = np.sin(theta) 

1409 rm = np.array(((c, -s), (s, c))) 

1410 # rotation: 

1411 for verts in vertices: 

1412 verts[:,:] = np.dot(verts, rm) 

1413 

1414 

1415def flipx_pathes(*vertices): 

1416 """Flip pathes in x-direction in place. 

1417 

1418 Parameters 

1419 ---------- 

1420 vertices: one or more 2D arrays 

1421 The coordinates of pathes to be flipped 

1422 (first column x-coordinates, second colum y-coordinates). 

1423 """ 

1424 for verts in vertices: 

1425 verts[:,0] = -verts[:,0] 

1426 

1427 

1428def flipy_pathes(*vertices): 

1429 """Flip pathes in y-direction in place. 

1430 

1431 Parameters 

1432 ---------- 

1433 vertices: one or more 2D arrays 

1434 The coordinates of pathes to be flipped 

1435 (first column x-coordinates, second colum y-coordinates). 

1436 """ 

1437 for verts in vertices: 

1438 verts[:,1] = -verts[:,1] 

1439 

1440 

1441def mirror_path(vertices1): 

1442 """Complete path of half a fish outline by appending the mirrored path. 

1443 

1444 It is sufficient to draw half of a top view of a fish. Import with 

1445 extract_path() and use this function to add the missing half of the 

1446 outline to the path. The outline is mirrored on the x-axis. 

1447 

1448 Parameters 

1449 ---------- 

1450 vertices1: 2D array 

1451 The coordinates of one half of the outline of a fish 

1452 (first column x-coordinates, second colum y-coordinates). 

1453 

1454 Returns 

1455 ------- 

1456 vertices: 2D array 

1457 The coordinates of the complete outline of a fish. 

1458 """ 

1459 vertices2 = np.array(vertices1[::-1,:]) 

1460 vertices2[:,1] *= -1 

1461 vertices = np.concatenate((vertices1, vertices2)) 

1462 return vertices 

1463 

1464 

1465def normalize_path(*vertices): 

1466 """Normalize and shift path in place. 

1467 

1468 The path extent in x direction is normalized to one and its center 

1469 is shifted to the origin. 

1470 

1471 Parameters 

1472 ---------- 

1473 vertices: one or more 2D arrays 

1474 The coordinates of the outline of a fish 

1475 (first column x-coordinates, second colum y-coordinates). 

1476 """ 

1477 bbox = bbox_pathes(*vertices) 

1478 for verts in vertices: 

1479 verts[:,1] -= np.mean(bbox[:,1]) 

1480 verts[:,0] -= bbox[0,0] 

1481 verts /= bbox[1,0] - bbox[0,0] 

1482 verts[:,0] -= 0.5 

1483 

1484 

1485def bend_path(path, bend, size, size_fac=1.0): 

1486 """Bend and scale a path. 

1487 

1488 Parameters 

1489 ---------- 

1490 path: 2D array 

1491 The coordinates of a path. 

1492 bend: float 

1493 Angle for bending in degrees. 

1494 size: float 

1495 Scale path to this size. 

1496 size_fac: float 

1497 Scale path even more, but keep size for calculating the bending. 

1498 

1499 Returns 

1500 ------- 

1501 path: 2D array 

1502 The coordinates of the bent and scaled path. 

1503 """ 

1504 path = np.array(path) 

1505 path *= size_fac*size 

1506 if np.abs(bend) > 1.e-8: 

1507 sel = path[:,0]<0.0 

1508 xp = path[sel,0] # all negative x coordinates of path 

1509 yp = path[sel,1] # y coordinates of all negative x coordinates of path 

1510 r = -180.0*0.5*size/bend/np.pi # radius of circle on which to bend the tail 

1511 beta = xp/r # angle on circle for each y coordinate 

1512 R = r-yp # radius of point 

1513 path[sel,0] = -np.abs(R*np.sin(beta)) # transformed x coordinates 

1514 path[sel,1] = r-R*np.cos(beta) # transformed y coordinates 

1515 return path 

1516 

1517 

1518def export_path(vertices): 

1519 """Print coordinates of path for import as numpy array. 

1520 

1521 The variable name, a leading 'np.array([' and the closing '])' 

1522 are not printed. 

1523 

1524 Parameters 

1525 ---------- 

1526 vertices: 2D array 

1527 The coordinates of the path 

1528 (first column x-coordinates, second colum y-coordinates). 

1529 """ 

1530 n = 2 

1531 for k, v in enumerate(vertices): 

1532 if k%n == 0: 

1533 print(' ', end='') 

1534 print(' [%.8e, %.8e],' % (v[0], v[1]), end='') 

1535 if k%n == n-1 and k < len(vertices)-1: 

1536 print('') 

1537 

1538 

1539def export_fish(name, body, *fins): 

1540 """Serialize coordinates of fish outlines as a dictionary. 

1541 

1542 Writes a dictionary with name 'name' and keys 'body', 'fin0', 'fin1', ... 

1543 holding the pathes. 

1544 

1545 Copy these coordinates from the console and paste them into this module. 

1546 Give it a proper name and don't forget to add it to the fish_shapes dictionary 

1547 to make it know to plot_fish(). 

1548 

1549 Parameters 

1550 ---------- 

1551 name: string 

1552 Name of the variable. 

1553 body: 2D array 

1554 The coordinates of fish's body 

1555 (first column x-coordinates, second colum y-coordinates). 

1556 fins: zero or more 2D arrays 

1557 The coordinates of the fish's fins 

1558 (first column x-coordinates, second colum y-coordinates). 

1559 

1560 Returns 

1561 ------- 

1562 fish: dict 

1563 A dictionary holding the pathes that can be passed directly to plot_fish(). 

1564 """ 

1565 print('%s = dict(body=np.array([' % name) 

1566 export_path(body) 

1567 fish = dict(body=body) 

1568 for k, f in enumerate(fins): 

1569 print(']),') 

1570 print(' fin%d=np.array([' % k) 

1571 export_path(f) 

1572 fish['fin%d' % k] = f 

1573 print(']))') 

1574 return fish 

1575 

1576 

1577def export_fish_demo(): 

1578 """Code demonstrating how to export a fish outline from SVG file. 

1579 """ 

1580 body = extract_path('fish.svg', 0, 300) 

1581 fin0 = extract_path('fish.svg', 1, 70) 

1582 fin1 = extract_path('fish.svg', 2, 70) 

1583 verts = (body, fin0, fin1) 

1584 # look at the path: 

1585 fig, ax = plt.subplots() 

1586 plot_pathes(ax, *verts) 

1587 ax.set_aspect('equal') 

1588 plt.show() 

1589 # fix path: 

1590 center_pathes(*verts) 

1591 rotate_pathes(-90.0, *verts) 

1592 #verts[:,1] *= 0.8 # change aspect ratio 

1593 #verts = verts[1:,:] # remove first point 

1594 #translate_pathes(0.0, -np.min(verts[:,1]), verts) 

1595 # mirror, normalize and export path: 

1596 #verts = mirror_path(verts) 

1597 normalize_path(*verts) 

1598 fish = export_fish('fish_side', *verts) 

1599 # plot outline: 

1600 fig, ax = plt.subplots() 

1601 plot_fish(ax, fish, size=1.0/1.1, 

1602 bodykwargs=dict(lw=1, edgecolor='k', facecolor='r'), 

1603 finkwargs=dict(lw=1, edgecolor='k', facecolor='b')) 

1604 ax.set_xlim(-1, 1) 

1605 ax.set_ylim(-0.5, 0.5) 

1606 plt.show() 

1607 

1608 

1609def main(): 

1610 """Plot some fish shapes and surface normals. 

1611 """ 

1612 bodykwargs = dict(lw=1, edgecolor='k', facecolor='none') 

1613 finkwargs = dict(lw=1, edgecolor='k', facecolor='grey') 

1614 eyekwargs = dict(lw=1, edgecolor='white', facecolor='grey') 

1615 var = ['zz', 'nx', 'ny', 'nz'] 

1616 fig, ax = plt.subplots() 

1617 for k in range(4): 

1618 y = (1.5-k)*9 

1619 fish = (('Alepto_male', 'side'), (0, y), (1, 0), 20.0, 0) 

1620 xx, yy, zz = fish_surface(*fish, gamma=0.5) 

1621 nx, ny, nz = surface_normals(xx, yy, zz) 

1622 a = [zz, nx, ny, nz] 

1623 th = np.nanmax(np.abs(a[k])) 

1624 ax.contourf(xx[0,:], yy[:,0], -a[k], 20, vmin=-th, vmax=th, cmap='RdYlBu') 

1625 plot_fish(ax, *fish, bodykwargs=bodykwargs, finkwargs=finkwargs, eyekwargs=eyekwargs) 

1626 ax.text(-11, y+2, var[k]) 

1627 fish = (('Alepto_male', 'side'), (20, -9), (1, 0), 23.0, 10) 

1628 xx, yy, zz = fish_surface(*fish, gamma=0.8) 

1629 nv = surface_normals(xx, yy, zz) 

1630 ilumn = [-0.05, 0.1, 1.0] 

1631 dv = np.zeros(nv[0].shape) 

1632 for nc, ic in zip(nv, ilumn): 

1633 dv += nc*ic 

1634 #ax.contourf(xx[0,:], yy[:,0], dv, 20, cmap='gist_gray') 

1635 ax.contourf(xx[0,:], yy[:,0], dv, levels=[np.nanmin(dv), np.nanmin(dv)+0.99*(np.nanmax(dv)-np.nanmin(dv)), np.nanmax(dv)], cmap='gist_gray') 

1636 plot_fish(ax, *fish, bodykwargs=bodykwargs, finkwargs=finkwargs, eyekwargs=eyekwargs) 

1637 bodykwargs = dict(lw=1, edgecolor='k', facecolor='k') 

1638 fish = (('Alepto', 'top'), (23, 0), (2, 1), 16.0, 25) 

1639 plot_fish(ax, *fish, bodykwargs=bodykwargs, finkwargs=finkwargs) 

1640 fish = (('Eigenmannia', 'top'), (23, 8), (1, 0.3), 16.0, -15) 

1641 plot_fish(ax, *fish, bodykwargs=bodykwargs, finkwargs=finkwargs) 

1642 fish = (('Eigenmannia', 'side'), (20, 18), (1, 0), 20.0, -25) 

1643 plot_fish(ax, *fish, bodykwargs=bodykwargs, finkwargs=finkwargs, eyekwargs=eyekwargs) 

1644 plot_fishfinder(ax, (38, 13), (1, 2), 18, handle=0.2, 

1645 central_ground=True, wires=True, lw=2) 

1646 plot_fishfinder(ax, (38, -8), (1, 2), 18, central_ground=False) 

1647 ax.set_xlim(-15, 45) 

1648 ax.set_ylim(-20, 24) 

1649 ax.set_aspect('equal') 

1650 plt.show() 

1651 

1652 

1653if __name__ == '__main__': 

1654 #export_fish_demo() 

1655 main() 

1656