[25834] | 1 | Index: ../trunk-jpl/src/m/shp/shpwrite.py
|
---|
| 2 | ===================================================================
|
---|
| 3 | --- ../trunk-jpl/src/m/shp/shpwrite.py (nonexistent)
|
---|
| 4 | +++ ../trunk-jpl/src/m/shp/shpwrite.py (revision 25065)
|
---|
| 5 | @@ -0,0 +1,60 @@
|
---|
| 6 | +try:
|
---|
| 7 | + import shapefile
|
---|
| 8 | +except ImportError:
|
---|
| 9 | + print("could not import shapefile, PyShp has not been installed, no shapefile reading capabilities enabled")
|
---|
| 10 | +
|
---|
| 11 | +def shpwrite(shp, filename): #{{{
|
---|
| 12 | + '''
|
---|
| 13 | + SHPREAD - write a shape file from a contour structure
|
---|
| 14 | +
|
---|
| 15 | + The current implementation of shpwrite depends on PyShp.
|
---|
| 16 | +
|
---|
| 17 | + Usage:
|
---|
| 18 | + shpwrite(shp, filename)
|
---|
| 19 | +
|
---|
| 20 | + Example:
|
---|
| 21 | + shpwrite(shp, 'domainoutline.shp')
|
---|
| 22 | +
|
---|
| 23 | + See also SHPREAD
|
---|
| 24 | +
|
---|
| 25 | + Sources:
|
---|
| 26 | + - https://github.com/GeospatialPython/pyshp
|
---|
| 27 | +
|
---|
| 28 | + TODO:
|
---|
| 29 | + - Should we check if there is only one element (see how MATLAB's shaperead
|
---|
| 30 | + and shapewrite handle single shapes versus multiple shapes)?
|
---|
| 31 | + '''
|
---|
| 32 | +
|
---|
| 33 | + # Sanity checks
|
---|
| 34 | + for shape in shp:
|
---|
| 35 | + print(shape)
|
---|
| 36 | +
|
---|
| 37 | + if shp[0].Geometry == 'Point':
|
---|
| 38 | + shapeType = 1
|
---|
| 39 | + elif shp[0].Geometry == 'Line':
|
---|
| 40 | + shapeType = 3
|
---|
| 41 | + elif shp[0].Geometry == 'Polygon':
|
---|
| 42 | + shapeType = 5
|
---|
| 43 | + else:
|
---|
| 44 | + raise Exception('shpwrite error: geometry \'{}\' is not currently supported'.format(shp[0].Geometry))
|
---|
| 45 | +
|
---|
| 46 | + sf = shapefile.Writer(filename, shapeType=shapeType)
|
---|
| 47 | +
|
---|
| 48 | + for i in range(len(shp)):
|
---|
| 49 | + sf.field('name', 'C') # TODO: Allow shape ids/names to be passed through
|
---|
| 50 | + if shapeType == 1: # POINT
|
---|
| 51 | + sf.point(shp[i].x, shp[i].y)
|
---|
| 52 | + elif shapeType == 3: # POLYLINE
|
---|
| 53 | + points = []
|
---|
| 54 | + for j in range(len(shp[i].x)):
|
---|
| 55 | + points.append([shp[i].x[j], shp[i].y[j]])
|
---|
| 56 | + sf.line(line)
|
---|
| 57 | + elif shapeType == 5: # POLYGON
|
---|
| 58 | + points = []
|
---|
| 59 | + for j in range(len(shp[i].x)):
|
---|
| 60 | + points.append([shp[i].x[j], shp[i].y[j]])
|
---|
| 61 | + sf.poly(points)
|
---|
| 62 | + sf.null()
|
---|
| 63 | + sf.record(str(i))
|
---|
| 64 | + sf.close()
|
---|
| 65 | +#}}}
|
---|
| 66 | Index: ../trunk-jpl/src/m/shp/shpwrite.m
|
---|
| 67 | ===================================================================
|
---|
| 68 | --- ../trunk-jpl/src/m/shp/shpwrite.m (revision 25064)
|
---|
| 69 | +++ ../trunk-jpl/src/m/shp/shpwrite.m (revision 25065)
|
---|
| 70 | @@ -9,10 +9,6 @@
|
---|
| 71 | %
|
---|
| 72 | % See also SHPREAD
|
---|
| 73 |
|
---|
| 74 | -
|
---|
| 75 | -%initialize number of profile
|
---|
| 76 | -count=0;
|
---|
| 77 | -
|
---|
| 78 | contours=struct([]);
|
---|
| 79 | for i=1:length(shp),
|
---|
| 80 | if strcmpi(shp(i).Geometry,'Point'),
|
---|
| 81 | @@ -21,11 +17,13 @@
|
---|
| 82 | contours(i).Geometry='Polygon';
|
---|
| 83 | elseif strcmpi(shp(i).Geometry,'Line'),
|
---|
| 84 | contours(i).Geometry='Line';
|
---|
| 85 | + else,
|
---|
| 86 | + error(['shpwrite error: geometry ' shp(i).Geometry ' not currently supported']);
|
---|
| 87 | end
|
---|
| 88 | contours(i).id=i;
|
---|
| 89 | contours(i).X=shp(i).x;
|
---|
| 90 | contours(i).Y=shp(i).y;
|
---|
| 91 | end
|
---|
| 92 | -
|
---|
| 93 | +
|
---|
| 94 | shapewrite(contours,filename);
|
---|
| 95 | end
|
---|
| 96 | Index: ../trunk-jpl/src/m/mesh/meshintersect3d.py
|
---|
| 97 | ===================================================================
|
---|
| 98 | --- ../trunk-jpl/src/m/mesh/meshintersect3d.py (revision 25064)
|
---|
| 99 | +++ ../trunk-jpl/src/m/mesh/meshintersect3d.py (revision 25065)
|
---|
| 100 | @@ -6,9 +6,11 @@
|
---|
| 101 |
|
---|
| 102 | from pairoptions import pairoptions
|
---|
| 103 |
|
---|
| 104 | +
|
---|
| 105 | def meshintersect3d(x, y, z, xs, ys, zs, *args): #{{{
|
---|
| 106 | '''
|
---|
| 107 | - MESHINTERSECT - returns indices (into x, y, and z) of common values between (x, y, z) and (xs, ys, zs) (i.e. x(index) = xs; y(index) = ys).
|
---|
| 108 | + MESHINTERSECT - returns indices (into x, y, and z) of common values between
|
---|
| 109 | + (x, y, z) and (xs, ys, zs) (i.e. x(index) = xs; y(index) = ys).
|
---|
| 110 | '''
|
---|
| 111 |
|
---|
| 112 | # Process options
|
---|
| 113 | Index: ../trunk-jpl/src/m/coordsystems/laea.py
|
---|
| 114 | ===================================================================
|
---|
| 115 | --- ../trunk-jpl/src/m/coordsystems/laea.py (nonexistent)
|
---|
| 116 | +++ ../trunk-jpl/src/m/coordsystems/laea.py (revision 25065)
|
---|
| 117 | @@ -0,0 +1,15 @@
|
---|
| 118 | +def laea(lat, long): #{{{
|
---|
| 119 | + '''
|
---|
| 120 | + LAEA - Lambert Azimuthal Equal Area projection at lat, long projection
|
---|
| 121 | + center.
|
---|
| 122 | +
|
---|
| 123 | + Usage:
|
---|
| 124 | + string = laea(45, -90)
|
---|
| 125 | +
|
---|
| 126 | + Example:
|
---|
| 127 | + string = laea(45, -90)
|
---|
| 128 | + return string = '+proj=laea +lat_0=45 +lon_0=-90 +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs'
|
---|
| 129 | + '''
|
---|
| 130 | +
|
---|
| 131 | + return '+proj=laea +lat_0={} +lon_0={} +x_0=0 +y_0=0 +ellps=WGS84 +units=m +no_defs'.format(lat, long)
|
---|
| 132 | +#}}}
|
---|
| 133 | Index: ../trunk-jpl/src/m/coordsystems/gdaltransform.m
|
---|
| 134 | ===================================================================
|
---|
| 135 | --- ../trunk-jpl/src/m/coordsystems/gdaltransform.m (revision 25064)
|
---|
| 136 | +++ ../trunk-jpl/src/m/coordsystems/gdaltransform.m (revision 25065)
|
---|
| 137 | @@ -19,9 +19,9 @@
|
---|
| 138 | % Bamber's Greeland projection
|
---|
| 139 | % +proj=stere +lat_0=90 +lat_ts=71 +lon_0=-39 +k=1 +x_0=0 +y_0=0 +a=6378273 +b=6356889.448564109 +units=m +no_defs
|
---|
| 140 | %
|
---|
| 141 | -% To get proj.4 string from EPSG, use gdalsrsinfo. Example:
|
---|
| 142 | +% To get proj.4 string from EPSG, use gdalsrsinfo. Example:
|
---|
| 143 | %
|
---|
| 144 | -% gdalsrsinfo epsg:4326 | grep "PROJ.4" | sed "s/PROJ.4 : //"
|
---|
| 145 | +% gdalsrsinfo epsg:4326 | grep "PROJ.4" | sed "s/PROJ.4 : //"
|
---|
| 146 |
|
---|
| 147 | %give ourselves unique file names
|
---|
| 148 | filename_in = tempname();
|
---|
| 149 | Index: ../trunk-jpl/src/m/geometry/AboveGround.py
|
---|
| 150 | ===================================================================
|
---|
| 151 | --- ../trunk-jpl/src/m/geometry/AboveGround.py (nonexistent)
|
---|
| 152 | +++ ../trunk-jpl/src/m/geometry/AboveGround.py (revision 25065)
|
---|
| 153 | @@ -0,0 +1,8 @@
|
---|
| 154 | +import numpy as np
|
---|
| 155 | +
|
---|
| 156 | +def function AboveGround(lat, long, r, height): #{{{
|
---|
| 157 | + r = r + height
|
---|
| 158 | + x = r * np.cos(np.deg2rad(lat)) * np.cos(np.deg2rad(long))
|
---|
| 159 | + y = r * np.cos(np.deg2rad(lat)) * np.sin(np.deg2rad(long))
|
---|
| 160 | + z = r * np.sin(np.deg2rad(lat))
|
---|
| 161 | +#}}}
|
---|
| 162 | Index: ../trunk-jpl/src/m/classes/plotoptions.py
|
---|
| 163 | ===================================================================
|
---|
| 164 | --- ../trunk-jpl/src/m/classes/plotoptions.py (revision 25064)
|
---|
| 165 | +++ ../trunk-jpl/src/m/classes/plotoptions.py (revision 25065)
|
---|
| 166 | @@ -1,4 +1,5 @@
|
---|
| 167 | from collections import OrderedDict
|
---|
| 168 | +
|
---|
| 169 | import pairoptions
|
---|
| 170 |
|
---|
| 171 |
|
---|
| 172 | @@ -6,8 +7,8 @@
|
---|
| 173 | '''
|
---|
| 174 | PLOTOPTIONS class definition
|
---|
| 175 |
|
---|
| 176 | - Usage:
|
---|
| 177 | - plotoptions = plotoptions(*arg)
|
---|
| 178 | + Usage:
|
---|
| 179 | + plotoptions = plotoptions(*arg)
|
---|
| 180 | '''
|
---|
| 181 |
|
---|
| 182 | def __init__(self, *arg): # {{{
|
---|
| 183 | @@ -35,7 +36,7 @@
|
---|
| 184 | def buildlist(self, *arg): #{{{
|
---|
| 185 | #check length of input
|
---|
| 186 | if len(arg) % 2:
|
---|
| 187 | - raise TypeError('Invalid parameter / value pair arguments')
|
---|
| 188 | + raise TypeError('Invalid parameter/value pair arguments')
|
---|
| 189 |
|
---|
| 190 | #go through args and build list (like pairoptions)
|
---|
| 191 | rawoptions = pairoptions.pairoptions(*arg)
|
---|
| 192 | @@ -102,7 +103,7 @@
|
---|
| 193 | if len(nums) != 2:
|
---|
| 194 | continue
|
---|
| 195 | if False in [x.isdigit() for x in nums]:
|
---|
| 196 | - raise ValueError('error: in option i - j both i and j must be integers')
|
---|
| 197 | + raise ValueError('error: in option i-j both i and j must be integers')
|
---|
| 198 | for j in range(int(nums[0]) - 1, int(nums[1])):
|
---|
| 199 | self.list[j].addfield(field, rawlist[i][1])
|
---|
| 200 |
|
---|
| 201 | Index: ../trunk-jpl/src/m/classes/basin.m
|
---|
| 202 | ===================================================================
|
---|
| 203 | --- ../trunk-jpl/src/m/classes/basin.m (revision 25064)
|
---|
| 204 | +++ ../trunk-jpl/src/m/classes/basin.m (revision 25065)
|
---|
| 205 | @@ -18,42 +18,39 @@
|
---|
| 206 | end
|
---|
| 207 | methods
|
---|
| 208 | function self = basin(varargin) % {{{
|
---|
| 209 | - switch nargin
|
---|
| 210 | - case 0
|
---|
| 211 | - self=setdefaultparameters(self);
|
---|
| 212 | - otherwise
|
---|
| 213 | + self=setdefaultparameters(self);
|
---|
| 214 |
|
---|
| 215 | - self=setdefaultparameters(self);
|
---|
| 216 | - options=pairoptions(varargin{:});
|
---|
| 217 | -
|
---|
| 218 | - %recover field values:
|
---|
| 219 | - self.boundaries=getfieldvalue(options,'boundaries',{});
|
---|
| 220 | - self.name=getfieldvalue(options,'name','');
|
---|
| 221 | - self.continent=getfieldvalue(options,'continent','');
|
---|
| 222 | + if nargin>0,
|
---|
| 223 | + options=pairoptions(varargin{:});
|
---|
| 224 | +
|
---|
| 225 | + %recover field values:
|
---|
| 226 | + self.boundaries=getfieldvalue(options,'boundaries',{});
|
---|
| 227 | + self.name=getfieldvalue(options,'name','');
|
---|
| 228 | + self.continent=getfieldvalue(options,'continent','');
|
---|
| 229 |
|
---|
| 230 | - %figure out projection string:
|
---|
| 231 | + %figure out projection string:
|
---|
| 232 | + if exist(options,'epsg'),
|
---|
| 233 | + if exist(options,'proj'),
|
---|
| 234 | + error(['Error in constructor for basin ' self.name '. Cannot supply epsg and proj at the same time!']);
|
---|
| 235 | + end
|
---|
| 236 | + epsg=getfieldvalue(options,'epsg');
|
---|
| 237 | + proj=epsg2proj(epsg); %convert to PROJ.4 format
|
---|
| 238 | + elseif exist(options,'proj'),
|
---|
| 239 | if exist(options,'epsg'),
|
---|
| 240 | - if exist(options,'proj'),
|
---|
| 241 | - error(['Error in constructor for boundary ' self.shppath '.Cannot supply epsg and proj at the same time!']);
|
---|
| 242 | - end
|
---|
| 243 | - epsg=getfieldvalue(options,'epsg');
|
---|
| 244 | - %convert into proj4:
|
---|
| 245 | - proj=epsg2proj(epsg);
|
---|
| 246 | - elseif exist(options,'proj'),
|
---|
| 247 | - if exist(options,'epsg'),
|
---|
| 248 | - error(['Error in constructor for boundary ' self.shppath '.Cannot supply epsg and proj at the same time!']);
|
---|
| 249 | - end
|
---|
| 250 | - proj=getfieldvalue(options,'proj');
|
---|
| 251 | - else
|
---|
| 252 | - proj= '+proj=longlat +datum=WGS84 +no_defs';
|
---|
| 253 | + error(['Error in constructor for basin ' self.name '. Cannot supply proj and epsg at the same time!']);
|
---|
| 254 | end
|
---|
| 255 | - self.proj=proj;
|
---|
| 256 | + proj=getfieldvalue(options,'proj');
|
---|
| 257 | + else
|
---|
| 258 | + proj='+proj=longlat +datum=WGS84 +no_defs';
|
---|
| 259 | + end
|
---|
| 260 | +
|
---|
| 261 | + self.proj=proj;
|
---|
| 262 | end
|
---|
| 263 | end % }}}
|
---|
| 264 | function self = setdefaultparameters(self) % {{{
|
---|
| 265 | self.name='';
|
---|
| 266 | self.continent='';
|
---|
| 267 | - self.proj='+proj=longlat +datum=WGS84 +no_defs '; %EPSG 4326
|
---|
| 268 | + self.proj='+proj=longlat +datum=WGS84 +no_defs'; %EPSG 4326
|
---|
| 269 | self.boundaries={};
|
---|
| 270 |
|
---|
| 271 | end % }}}
|
---|
| 272 | @@ -92,11 +89,11 @@
|
---|
| 273 | options=pairoptions(varargin{:});
|
---|
| 274 | extension=getfieldvalue(options,'extension',1);
|
---|
| 275 |
|
---|
| 276 | - [path,nme,ext]=fileparts(self.name);
|
---|
| 277 | + [path,name,ext]=fileparts(self.name);
|
---|
| 278 | if extension,
|
---|
| 279 | - output=[nme ext];
|
---|
| 280 | + output=[name ext];
|
---|
| 281 | else
|
---|
| 282 | - output=nme;
|
---|
| 283 | + output=name;
|
---|
| 284 | end
|
---|
| 285 | end % }}}
|
---|
| 286 | function plot(self,varargin) % {{{
|
---|
| 287 | @@ -173,7 +170,7 @@
|
---|
| 288 | inshapefile=getfieldvalue(options,'shapefile');
|
---|
| 289 | outputshapefile=getfieldvalue(options,'outputshapefile','');
|
---|
| 290 |
|
---|
| 291 | - if (exist(options,'epsgshapefile') & exist(options,'projshapefile')),
|
---|
| 292 | + if (exist(options,'epsgshapefile') & exist(options,'projshapefile')),
|
---|
| 293 | error('Basin shapefilecrop error message: cannot specify epsgshapefile and projshapefile at the same time');
|
---|
| 294 | end
|
---|
| 295 | if exist(options,'epsgshapefile'),
|
---|
| 296 | @@ -185,7 +182,7 @@
|
---|
| 297 | end
|
---|
| 298 |
|
---|
| 299 |
|
---|
| 300 | - %create list of contours that have critical length > threshold: (in lat,long)
|
---|
| 301 | + %create list of contours that have critical length > threshold (in lat,long):
|
---|
| 302 | contours=shpread(inshapefile);
|
---|
| 303 | llist=[];
|
---|
| 304 | for i=1:length(contours),
|
---|
| 305 | @@ -211,8 +208,8 @@
|
---|
| 306 | flags=zeros(length(contours),1);
|
---|
| 307 | for i=1:length(contours),
|
---|
| 308 | h=contours(i);
|
---|
| 309 | - in=inpolygon(h.x,h.y,ba.x,ba.y);
|
---|
| 310 | - if ~isempty(find(in==0)),
|
---|
| 311 | + isin=inpolygon(h.x,h.y,ba.x,ba.y);
|
---|
| 312 | + if ~isempty(find(isin==0)),
|
---|
| 313 | flags(i)=1;
|
---|
| 314 | end
|
---|
| 315 | end
|
---|
| 316 | Index: ../trunk-jpl/src/m/qmu/helpers.py
|
---|
| 317 | ===================================================================
|
---|
| 318 | --- ../trunk-jpl/src/m/qmu/helpers.py (revision 25064)
|
---|
| 319 | +++ ../trunk-jpl/src/m/qmu/helpers.py (revision 25065)
|
---|
| 320 | @@ -1,8 +1,9 @@
|
---|
| 321 | -import numpy as np
|
---|
| 322 | from collections import OrderedDict
|
---|
| 323 | from copy import deepcopy
|
---|
| 324 |
|
---|
| 325 | +import numpy as np
|
---|
| 326 |
|
---|
| 327 | +
|
---|
| 328 | class struct(object):
|
---|
| 329 | '''An empty struct that can be assigned arbitrary attributes'''
|
---|
| 330 | pass
|
---|
| 331 | @@ -10,40 +11,41 @@
|
---|
| 332 |
|
---|
| 333 | class Lstruct(list):
|
---|
| 334 | '''
|
---|
| 335 | -An empty struct that can be assigned arbitrary attributes
|
---|
| 336 | - but can also be accesed as a list. Eg. x.y = 'hello', x[:] = ['w', 'o', 'r', 'l', 'd']
|
---|
| 337 | + An empty struct that can be assigned arbitrary attributes but can also be
|
---|
| 338 | + accesed as a list. Eg. x.y = 'hello', x[:] = ['w', 'o', 'r', 'l', 'd']
|
---|
| 339 |
|
---|
| 340 | -Note that 'x' returns the array and x.__dict__ will only return
|
---|
| 341 | - attributes other than the array
|
---|
| 342 | + Note that 'x' returns the array and x.__dict__ will only return attributes
|
---|
| 343 | + other than the array
|
---|
| 344 |
|
---|
| 345 | -List-based and struct-based behaviors work normally, however they are referenced
|
---|
| 346 | - as if the other does not exist; len(x) corresponds only to
|
---|
| 347 | - the list component of x, len(x.a) corresponds to x.a, x.__dict__
|
---|
| 348 | - corresponds only to the non-x-list attributes
|
---|
| 349 | + List-based and struct-based behaviors work normally, however they are
|
---|
| 350 | + referenced as if the other does not exist; len(x) corresponds only to the
|
---|
| 351 | + list component of x, len(x.a) corresponds to x.a, x.__dict__ corresponds
|
---|
| 352 | + only to the non-x-list attributes
|
---|
| 353 |
|
---|
| 354 | -Example uses:
|
---|
| 355 | + Examples:
|
---|
| 356 |
|
---|
| 357 | -x = Lstruct(1, 2, 3, 4) -> [1, 2, 3, 4]
|
---|
| 358 | - x.a = 'hello'
|
---|
| 359 | - len(x) -> 4
|
---|
| 360 | - x.append(5)
|
---|
| 361 | - len(x) -> 5
|
---|
| 362 | - x[2] -> 3
|
---|
| 363 | - x.a -> 'hello'
|
---|
| 364 | - print x -> [1, 2, 3, 4, 5]
|
---|
| 365 | - x.__dict__ -> {'a':'hello'}
|
---|
| 366 | - x.b = [6, 7, 8, 9]
|
---|
| 367 | - x.b[-1] -> 9
|
---|
| 368 | - len(x.b) -> 4
|
---|
| 369 | + x = Lstruct(1, 2, 3, 4) -> [1, 2, 3, 4]
|
---|
| 370 | + x.a = 'hello'
|
---|
| 371 | + len(x) -> 4
|
---|
| 372 | + x.append(5)
|
---|
| 373 | + len(x) -> 5
|
---|
| 374 | + x[2] -> 3
|
---|
| 375 | + x.a -> 'hello'
|
---|
| 376 | + print x -> [1, 2, 3, 4, 5]
|
---|
| 377 | + x.__dict__ -> {'a':'hello'}
|
---|
| 378 | + x.b = [6, 7, 8, 9]
|
---|
| 379 | + x.b[-1] -> 9
|
---|
| 380 | + len(x.b) -> 4
|
---|
| 381 |
|
---|
| 382 | -Other valid constructors:
|
---|
| 383 | - x = Lstruct(1, 2, 3, a = 'hello') -> x.a -> 'hello', x -> [1, 2, 3]
|
---|
| 384 | - x = Lstruct(1, 2, 3)(a = 'hello')
|
---|
| 385 | - x = Lstruct([1, 2, 3], x = 'hello')
|
---|
| 386 | - x = Lstruct((1, 2, 3), a = 'hello')
|
---|
| 387 | + Other valid constructors:
|
---|
| 388 | + x = Lstruct(1, 2, 3, a = 'hello') -> x.a -> 'hello', x -> [1, 2, 3]
|
---|
| 389 | + x = Lstruct(1, 2, 3)(a = 'hello')
|
---|
| 390 | + x = Lstruct([1, 2, 3], x = 'hello')
|
---|
| 391 | + x = Lstruct((1, 2, 3), a = 'hello')
|
---|
| 392 |
|
---|
| 393 | -Credit: https://github.com/Vectorized/Python-Attribute-List
|
---|
| 394 | -'''
|
---|
| 395 | + Sources:
|
---|
| 396 | + -https://github.com/Vectorized/Python-Attribute-List
|
---|
| 397 | + '''
|
---|
| 398 |
|
---|
| 399 | def __new__(self, *args, **kwargs):
|
---|
| 400 | return super(Lstruct, self).__new__(self, args, kwargs)
|
---|
| 401 | @@ -62,36 +64,34 @@
|
---|
| 402 |
|
---|
| 403 | class OrderedStruct(object):
|
---|
| 404 | '''
|
---|
| 405 | -A form of dictionary-like structure that maintains the
|
---|
| 406 | - ordering in which its fields/attributes and their
|
---|
| 407 | - corresponding values were added.
|
---|
| 408 | + A form of dictionary-like structure that maintains the ordering in which
|
---|
| 409 | + its fields/attributes and their corresponding values were added.
|
---|
| 410 |
|
---|
| 411 | -OrderedDict is a similar device, however this class
|
---|
| 412 | - can be used as an "ordered struct/class" giving
|
---|
| 413 | - it much more flexibility in practice. It is
|
---|
| 414 | + OrderedDict is a similar device, however this class can be used as an
|
---|
| 415 | + "ordered struct/class" giving it much more flexibility in practice. It is
|
---|
| 416 | also easier to work with fixed valued keys in-code.
|
---|
| 417 |
|
---|
| 418 | -Eg:
|
---|
| 419 | -OrderedDict: # a bit clumsy to use and look at
|
---|
| 420 | - x['y'] = 5
|
---|
| 421 | + Example:
|
---|
| 422 | + OrderedDict: # a bit clumsy to use and look at
|
---|
| 423 | + x['y'] = 5
|
---|
| 424 |
|
---|
| 425 | -OrderedStruct: # nicer to look at, and works the same way
|
---|
| 426 | - x.y = 5
|
---|
| 427 | - OR
|
---|
| 428 | - x['y'] = 5 # supports OrderedDict-style usage
|
---|
| 429 | + OrderedStruct: # nicer to look at, and works the same way
|
---|
| 430 | + x.y = 5
|
---|
| 431 | + OR
|
---|
| 432 | + x['y'] = 5 # supports OrderedDict-style usage
|
---|
| 433 |
|
---|
| 434 | -Supports: len(x), str(x), for-loop iteration.
|
---|
| 435 | -Has methods: x.keys(), x.values(), x.items(), x.iterkeys()
|
---|
| 436 | + Supports: len(x), str(x), for-loop iteration.
|
---|
| 437 | + Has methods: x.keys(), x.values(), x.items(), x.iterkeys()
|
---|
| 438 |
|
---|
| 439 | -Usage:
|
---|
| 440 | - x = OrderedStruct()
|
---|
| 441 | - x.y = 5
|
---|
| 442 | - x.z = 6
|
---|
| 443 | - OR
|
---|
| 444 | - x = OrderedStruct('y', 5, 'z', 6)
|
---|
| 445 | + Usage:
|
---|
| 446 | + x = OrderedStruct()
|
---|
| 447 | + x.y = 5
|
---|
| 448 | + x.z = 6
|
---|
| 449 | + OR
|
---|
| 450 | + x = OrderedStruct('y', 5, 'z', 6)
|
---|
| 451 |
|
---|
| 452 | - # note below that the output fields as iterables are always
|
---|
| 453 | - # in the same order as the inputs
|
---|
| 454 | + note below that the output fields as iterables are always in the same
|
---|
| 455 | + order as the inputs
|
---|
| 456 |
|
---|
| 457 | x.keys() -> ['y', 'z']
|
---|
| 458 | x.values() -> [5, 6]
|
---|
| 459 | @@ -110,16 +110,18 @@
|
---|
| 460 | ('x', 5)
|
---|
| 461 | ('y', 6)
|
---|
| 462 |
|
---|
| 463 | - Note: to access internal fields use dir(x)
|
---|
| 464 | - (input fields will be included, but
|
---|
| 465 | - are not technically internals)
|
---|
| 466 | + Note: to access internal fields use dir(x) (input fields will be included,
|
---|
| 467 | + but are not technically internals)
|
---|
| 468 | '''
|
---|
| 469 |
|
---|
| 470 | def __init__(self, *args):
|
---|
| 471 | - '''Provided either nothing or a series of strings, construct a structure that will,
|
---|
| 472 | -when accessed as a list, return its fields in the same order in which they were provided'''
|
---|
| 473 | + '''
|
---|
| 474 | + Provided either nothing or a series of strings, construct a structure
|
---|
| 475 | + that will, when accessed as a list, return its fields in the same order
|
---|
| 476 | + in which they were provided
|
---|
| 477 | + '''
|
---|
| 478 |
|
---|
| 479 | - # keys and values
|
---|
| 480 | + # keys and values
|
---|
| 481 | self._k = []
|
---|
| 482 | self._v = []
|
---|
| 483 |
|
---|
| 484 | @@ -184,9 +186,11 @@
|
---|
| 485 | yield(a, b)
|
---|
| 486 |
|
---|
| 487 | def __copy__(self):
|
---|
| 488 | - # shallow copy, hard copies of trivial attributes,
|
---|
| 489 | - # references to structures like lists/OrderedDicts
|
---|
| 490 | - # unless redefined as an entirely different structure
|
---|
| 491 | + '''
|
---|
| 492 | + shallow copy, hard copies of trivial attributes,
|
---|
| 493 | + references to structures like lists/OrderedDicts
|
---|
| 494 | + unless redefined as an entirely different structure
|
---|
| 495 | + '''
|
---|
| 496 | newInstance = type(self)()
|
---|
| 497 | for k, v in list(self.items()):
|
---|
| 498 | exec(('newInstance.%s = v') % (k))
|
---|
| 499 | @@ -193,11 +197,13 @@
|
---|
| 500 | return newInstance
|
---|
| 501 |
|
---|
| 502 | def __deepcopy__(self, memo=None):
|
---|
| 503 | - # hard copy of all attributes
|
---|
| 504 | - # same thing but call deepcopy recursively
|
---|
| 505 | - # technically not how it should be done,
|
---|
| 506 | - # (see https://docs.python.org/2/library/copy.html #copy.deepcopy )
|
---|
| 507 | - # but will generally work in this case
|
---|
| 508 | + '''
|
---|
| 509 | + hard copy of all attributes
|
---|
| 510 | + same thing but call deepcopy recursively
|
---|
| 511 | + technically not how it should be done,
|
---|
| 512 | + (see https://docs.python.org/2/library/copy.html #copy.deepcopy )
|
---|
| 513 | + but will generally work in this case
|
---|
| 514 | + '''
|
---|
| 515 | newInstance = type(self)()
|
---|
| 516 | for k, v in list(self.items()):
|
---|
| 517 | exec(('newInstance.%s = deepcopy(v)') % (k))
|
---|
| 518 | @@ -211,7 +217,7 @@
|
---|
| 519 | i = self._k.index(key)
|
---|
| 520 | k = self._k.pop(i)
|
---|
| 521 | v = self._v.pop(i)
|
---|
| 522 | - #exec('del self.%s')%(key)
|
---|
| 523 | + #exec('del self.%s')%(key)
|
---|
| 524 | return (k, v)
|
---|
| 525 |
|
---|
| 526 | def keys(self):
|
---|
| 527 | @@ -226,8 +232,10 @@
|
---|
| 528 |
|
---|
| 529 | def isempty(x):
|
---|
| 530 | '''
|
---|
| 531 | - returns true if object is + -infinity, NaN, None, '', has length 0, or is an
|
---|
| 532 | - array/matrix composed only of such components (includes mixtures of "empty" types)'''
|
---|
| 533 | + returns true if object is +/-infinity, NaN, None, '', has length 0, or is
|
---|
| 534 | + an array/matrix composed only of such components (includes mixtures of
|
---|
| 535 | + "empty" types)
|
---|
| 536 | + '''
|
---|
| 537 |
|
---|
| 538 | if type(x) in [list, np.ndarray, tuple]:
|
---|
| 539 | if np.size(x) == 0:
|
---|
| 540 | @@ -261,8 +269,11 @@
|
---|
| 541 |
|
---|
| 542 |
|
---|
| 543 | def fieldnames(x, ignore_internals=True):
|
---|
| 544 | - '''returns a list of fields of x
|
---|
| 545 | - ignore_internals ignores all fieldnames starting with '_' and is True by default'''
|
---|
| 546 | + '''
|
---|
| 547 | + returns a list of fields of x
|
---|
| 548 | + ignore_internals ignores all fieldnames starting with '_' and is True by
|
---|
| 549 | + default
|
---|
| 550 | + '''
|
---|
| 551 | result = list(vars(x).keys())
|
---|
| 552 |
|
---|
| 553 | if ignore_internals:
|
---|
| 554 | @@ -272,8 +283,11 @@
|
---|
| 555 |
|
---|
| 556 |
|
---|
| 557 | def isfield(x, y, ignore_internals=True):
|
---|
| 558 | - '''is y is a field of x?
|
---|
| 559 | - ignore_internals ignores all fieldnames starting with '_' and is True by default'''
|
---|
| 560 | + '''
|
---|
| 561 | + is y is a field of x?
|
---|
| 562 | + ignore_internals ignores all fieldnames starting with '_' and is True by
|
---|
| 563 | + default
|
---|
| 564 | + '''
|
---|
| 565 | return str(y) in fieldnames(x, ignore_internals)
|
---|
| 566 |
|
---|
| 567 |
|
---|
| 568 | @@ -280,7 +294,8 @@
|
---|
| 569 | def fileparts(x):
|
---|
| 570 | '''
|
---|
| 571 | given: "path/path/.../file_name.ext"
|
---|
| 572 | - returns: [path, file_name, ext] (list of strings)'''
|
---|
| 573 | + returns: [path, file_name, ext] (list of strings)
|
---|
| 574 | + '''
|
---|
| 575 | try:
|
---|
| 576 | a = x[:x.rindex('/')] #path
|
---|
| 577 | b = x[x.rindex('/') + 1:] #full filename
|
---|
| 578 | @@ -296,17 +311,17 @@
|
---|
| 579 |
|
---|
| 580 | def fullfile(*args):
|
---|
| 581 | '''
|
---|
| 582 | - use:
|
---|
| 583 | + usage:
|
---|
| 584 | + fullfile(path, path, ... , file_name + ext)
|
---|
| 585 |
|
---|
| 586 | - fullfile(path, path, ... , file_name + ext)
|
---|
| 587 | returns: "path/path/.../file_name.ext"
|
---|
| 588 |
|
---|
| 589 | with all arguments as strings with no "/"s
|
---|
| 590 |
|
---|
| 591 | regarding extensions and the '.':
|
---|
| 592 | - as final arguments ('file.doc') or ('file' + '.doc') will work
|
---|
| 593 | - ('final', '.doc'), and the like, will not (you'd get 'final/.doc')
|
---|
| 594 | -'''
|
---|
| 595 | + as final arguments ('file.doc') or ('file' + '.doc') will work
|
---|
| 596 | + ('final', '.doc'), and the like, will not (you'd get 'final/.doc')
|
---|
| 597 | + '''
|
---|
| 598 | result = str(args[0])
|
---|
| 599 | for i in range(len(args[1:])):
|
---|
| 600 | # if last argument wasn't empty, add a '/' between it and the next argument
|
---|
| 601 | @@ -320,8 +335,11 @@
|
---|
| 602 | def findline(fidi, s):
|
---|
| 603 | '''
|
---|
| 604 | returns full first line containing s (as a string), or None
|
---|
| 605 | +
|
---|
| 606 | Note: will include any newlines or tabs that occur in that line,
|
---|
| 607 | - use str(findline(f, s)).strip() to remove these, str() in case result is None'''
|
---|
| 608 | + use str(findline(f, s)).strip() to remove these, str() in case result is
|
---|
| 609 | + None
|
---|
| 610 | + '''
|
---|
| 611 | for line in fidi:
|
---|
| 612 | if s in line:
|
---|
| 613 | return line
|
---|
| 614 | @@ -330,20 +348,21 @@
|
---|
| 615 |
|
---|
| 616 | def empty_nd_list(shape, filler=0., as_numpy_ndarray=False):
|
---|
| 617 | '''
|
---|
| 618 | -returns a python list of the size/shape given (shape must be int or tuple)
|
---|
| 619 | + returns a python list of the size/shape given (shape must be int or tuple)
|
---|
| 620 | the list will be filled with the optional second argument
|
---|
| 621 |
|
---|
| 622 | filler is 0.0 by default
|
---|
| 623 |
|
---|
| 624 | - as_numpy_ndarray will return the result as a numpy.ndarray and is False by default
|
---|
| 625 | + as_numpy_ndarray will return the result as a numpy.ndarray and is False by
|
---|
| 626 | + default
|
---|
| 627 |
|
---|
| 628 | - Note: the filler must be either None/np.nan/float('NaN'), float/double, or int
|
---|
| 629 | - other numpy and float values such as +/- np.inf will also work
|
---|
| 630 | + Note: the filler must be either None/np.nan/float('NaN'), float/double, or
|
---|
| 631 | + int. other numpy and float values such as +/- np.inf will also work
|
---|
| 632 |
|
---|
| 633 | -use:
|
---|
| 634 | - empty_nd_list((5, 5), 0.0) # returns a 5x5 matrix of 0.0's
|
---|
| 635 | - empty_nd_list(5, None) # returns a 5 long array of NaN
|
---|
| 636 | -'''
|
---|
| 637 | + Usage:
|
---|
| 638 | + empty_nd_list((5, 5), 0.0) # returns a 5x5 matrix of 0.0's
|
---|
| 639 | + empty_nd_list(5, None) # returns a 5 long array of NaN
|
---|
| 640 | + '''
|
---|
| 641 | result = np.empty(shape)
|
---|
| 642 | result.fill(filler)
|
---|
| 643 | if not as_numpy_ndarray:
|
---|
| 644 | Index: ../trunk-jpl/src/m/mech/analyticaldamage.py
|
---|
| 645 | ===================================================================
|
---|
| 646 | --- ../trunk-jpl/src/m/mech/analyticaldamage.py (revision 25064)
|
---|
| 647 | +++ ../trunk-jpl/src/m/mech/analyticaldamage.py (revision 25065)
|
---|
| 648 | @@ -1,6 +1,6 @@
|
---|
| 649 | import numpy as np
|
---|
| 650 | +
|
---|
| 651 | from averaging import averaging
|
---|
| 652 | -#from plotmodel import plotmodel
|
---|
| 653 | from thomasparams import thomasparams
|
---|
| 654 |
|
---|
| 655 |
|
---|
| 656 | Index: ../trunk-jpl/src/m/plot/applyoptions.m
|
---|
| 657 | ===================================================================
|
---|
| 658 | --- ../trunk-jpl/src/m/plot/applyoptions.m (revision 25064)
|
---|
| 659 | +++ ../trunk-jpl/src/m/plot/applyoptions.m (revision 25065)
|
---|
| 660 | @@ -307,7 +307,6 @@
|
---|
| 661 | end
|
---|
| 662 | end
|
---|
| 663 |
|
---|
| 664 | -
|
---|
| 665 | %text (default value is empty, not NaN...)
|
---|
| 666 | if exist(options,'text');
|
---|
| 667 | textstring=getfieldvalue(options,'text');
|
---|
| 668 | @@ -351,7 +350,7 @@
|
---|
| 669 | scaleruler(options);
|
---|
| 670 | end
|
---|
| 671 |
|
---|
| 672 | -%streamliness
|
---|
| 673 | +%streamlines
|
---|
| 674 | if exist(options,'streamlines'),
|
---|
| 675 | plot_streamlines(md,options);
|
---|
| 676 | end
|
---|
| 677 | Index: ../trunk-jpl/src/m/plot/plot_manager.py
|
---|
| 678 | ===================================================================
|
---|
| 679 | --- ../trunk-jpl/src/m/plot/plot_manager.py (revision 25064)
|
---|
| 680 | +++ ../trunk-jpl/src/m/plot/plot_manager.py (revision 25065)
|
---|
| 681 | @@ -1,14 +1,3 @@
|
---|
| 682 | -
|
---|
| 683 | -from checkplotoptions import checkplotoptions
|
---|
| 684 | -from plot_mesh import plot_mesh
|
---|
| 685 | -from plot_BC import plot_BC
|
---|
| 686 | -from plot_elementnumbering import plot_elementnumbering
|
---|
| 687 | -from plot_vertexnumbering import plot_vertexnumbering
|
---|
| 688 | -from processmesh import processmesh
|
---|
| 689 | -from processdata import processdata
|
---|
| 690 | -from plot_unit import plot_unit
|
---|
| 691 | -from applyoptions import applyoptions
|
---|
| 692 | -
|
---|
| 693 | try:
|
---|
| 694 | from osgeo import gdal
|
---|
| 695 | overlaysupport = True
|
---|
| 696 | @@ -16,8 +5,17 @@
|
---|
| 697 | print('osgeo/gdal for python not installed, overlay plots are not enabled')
|
---|
| 698 | overlaysupport = False
|
---|
| 699 |
|
---|
| 700 | +from applyoptions import applyoptions
|
---|
| 701 | +from checkplotoptions import checkplotoptions
|
---|
| 702 | +from plot_BC import plot_BC
|
---|
| 703 | +from plot_mesh import plot_mesh
|
---|
| 704 | +from plot_elementnumbering import plot_elementnumbering
|
---|
| 705 | if overlaysupport:
|
---|
| 706 | from plot_overlay import plot_overlay
|
---|
| 707 | +from plot_unit import plot_unit
|
---|
| 708 | +from plot_vertexnumbering import plot_vertexnumbering
|
---|
| 709 | +from processdata import processdata
|
---|
| 710 | +from processmesh import processmesh
|
---|
| 711 |
|
---|
| 712 |
|
---|
| 713 | def plot_manager(md, options, fig, axgrid, gridindex):
|
---|
| 714 | @@ -26,9 +24,12 @@
|
---|
| 715 |
|
---|
| 716 | 'fig' is a handle to the figure instance created by plotmodel.
|
---|
| 717 |
|
---|
| 718 | - 'ax' is a handle to the axes instance created by plotmodel. This is
|
---|
| 719 | + 'axgrid' is a handle to the axes instance created by plotmodel. This is
|
---|
| 720 | currently generated using matplotlib's AxesGrid toolkit.
|
---|
| 721 |
|
---|
| 722 | + 'gridindex' is passed through to specialized plot* functions and
|
---|
| 723 | + applyoptions.
|
---|
| 724 | +
|
---|
| 725 | Usage:
|
---|
| 726 | plot_manager(md, options, fig, ax)
|
---|
| 727 |
|
---|
| 728 | @@ -36,9 +37,14 @@
|
---|
| 729 | '''
|
---|
| 730 | #parse options and get a structure of options
|
---|
| 731 | options = checkplotoptions(md, options)
|
---|
| 732 | +
|
---|
| 733 | #get data to be plotted
|
---|
| 734 | data = options.getfieldvalue('data')
|
---|
| 735 | +
|
---|
| 736 | #add ticklabel has a default option
|
---|
| 737 | + #
|
---|
| 738 | + # TODO: Check why we are doing this and if it is absolutely necessary (see
|
---|
| 739 | + # also src/m/plot/plot_mesh.py, src/m/plot/applyoptions.py)
|
---|
| 740 | options.addfielddefault('ticklabels', 'on')
|
---|
| 741 |
|
---|
| 742 | ax = axgrid[gridindex]
|
---|
| 743 | @@ -57,8 +63,7 @@
|
---|
| 744 | if isinstance(data, str):
|
---|
| 745 | if data == 'mesh':
|
---|
| 746 | plot_mesh(md, options, fig, axgrid, gridindex)
|
---|
| 747 | -
|
---|
| 748 | - #fig.delaxes(fig.axes[1]) # hack to remove colorbar after the fact
|
---|
| 749 | + #fig.delaxes(fig.axes[1]) # hack to remove colorbar after the fact
|
---|
| 750 | return
|
---|
| 751 | elif data == 'BC':
|
---|
| 752 | plot_BC(md, options, fig, axgrid, gridindex)
|
---|
| 753 | Index: ../trunk-jpl/src/m/plot/plot_overlay.py
|
---|
| 754 | ===================================================================
|
---|
| 755 | --- ../trunk-jpl/src/m/plot/plot_overlay.py (revision 25064)
|
---|
| 756 | +++ ../trunk-jpl/src/m/plot/plot_overlay.py (revision 25065)
|
---|
| 757 | @@ -1,24 +1,31 @@
|
---|
| 758 | -import numpy as np
|
---|
| 759 | -from processmesh import processmesh
|
---|
| 760 | -from processdata import processdata
|
---|
| 761 | -from xy2ll import xy2ll
|
---|
| 762 | +import os
|
---|
| 763 | +
|
---|
| 764 | import matplotlib.pyplot as plt
|
---|
| 765 | import matplotlib as mpl
|
---|
| 766 | -import os
|
---|
| 767 | try:
|
---|
| 768 | from mpl_toolkits.basemap import Basemap
|
---|
| 769 | except ImportError:
|
---|
| 770 | print('Basemap toolkit not installed')
|
---|
| 771 | +import numpy as np
|
---|
| 772 | try:
|
---|
| 773 | from osgeo import gdal
|
---|
| 774 | except ImportError:
|
---|
| 775 | print('osgeo/gdal for python not installed, plot_overlay is disabled')
|
---|
| 776 |
|
---|
| 777 | +from processdata import processdata
|
---|
| 778 | +from processmesh import processmesh
|
---|
| 779 | +from xy2ll import xy2ll
|
---|
| 780 |
|
---|
| 781 | +
|
---|
| 782 | def plot_overlay(md, data, options, ax):
|
---|
| 783 | '''
|
---|
| 784 | - Function for plotting a georeferenced image. This function is called
|
---|
| 785 | - from within the plotmodel code.
|
---|
| 786 | + Function for plotting a georeferenced image. Called from plot_manager by
|
---|
| 787 | + call to plotmodel.
|
---|
| 788 | +
|
---|
| 789 | + Usage:
|
---|
| 790 | + plot_overlay(md, data, options, ax)
|
---|
| 791 | +
|
---|
| 792 | + See also: PLOTMODEL
|
---|
| 793 | '''
|
---|
| 794 |
|
---|
| 795 | x, y, z, elements, is2d, isplanet = processmesh(md, [], options)
|
---|
| 796 | @@ -80,7 +87,7 @@
|
---|
| 797 | plt.hist(arr.flatten(), bins=256, range=(0., 1.))
|
---|
| 798 | plt.title('histogram of overlay image, use for setting overlaylims')
|
---|
| 799 | plt.show()
|
---|
| 800 | - plt.sca(ax) # return to original axes / figure
|
---|
| 801 | + plt.sca(ax) # return to original axes/figure
|
---|
| 802 |
|
---|
| 803 | # get parameters from cropped geotiff
|
---|
| 804 | trans = gtif.GetGeoTransform()
|
---|
| 805 | Index: ../trunk-jpl/src/m/plot/plotmodel.m
|
---|
| 806 | ===================================================================
|
---|
| 807 | --- ../trunk-jpl/src/m/plot/plotmodel.m (revision 25064)
|
---|
| 808 | +++ ../trunk-jpl/src/m/plot/plotmodel.m (revision 25065)
|
---|
| 809 | @@ -9,7 +9,7 @@
|
---|
| 810 | numberofplots=options.numberofplots;
|
---|
| 811 |
|
---|
| 812 | %get number of subplots
|
---|
| 813 | -subplotwidth=ceil(sqrt(options.numberofplots));
|
---|
| 814 | +subplotwidth=ceil(sqrt(numberofplots));
|
---|
| 815 |
|
---|
| 816 | %if nlines and ncols specified, then bypass.
|
---|
| 817 | if ~exist(options.list{1},'nlines') & ~exist(options.list{1},'ncols')
|
---|
| 818 | @@ -103,7 +103,7 @@
|
---|
| 819 | end
|
---|
| 820 | end % }}}
|
---|
| 821 |
|
---|
| 822 | - %Use zbuffer renderer (snoother colors) and white background
|
---|
| 823 | + %Use zbuffer renderer (smoother colors) and white background
|
---|
| 824 | set(f,'Renderer','zbuffer','color',getfieldvalue(options.list{1},'figurebackgroundcolor','w'));
|
---|
| 825 |
|
---|
| 826 | %Go through all data plottable and close window if an error occurs
|
---|
| 827 | @@ -124,5 +124,5 @@
|
---|
| 828 | rethrow(me);
|
---|
| 829 | end
|
---|
| 830 | else
|
---|
| 831 | - error('plotmodel error message: no output data found. ');
|
---|
| 832 | + error('plotmodel error message: no output data found.');
|
---|
| 833 | end
|
---|
| 834 | Index: ../trunk-jpl/src/m/plot/plot_manager.m
|
---|
| 835 | ===================================================================
|
---|
| 836 | --- ../trunk-jpl/src/m/plot/plot_manager.m (revision 25064)
|
---|
| 837 | +++ ../trunk-jpl/src/m/plot/plot_manager.m (revision 25065)
|
---|
| 838 | @@ -14,9 +14,7 @@
|
---|
| 839 |
|
---|
| 840 | %figure out if this is a special plot
|
---|
| 841 | if ischar(data),
|
---|
| 842 | -
|
---|
| 843 | switch data,
|
---|
| 844 | -
|
---|
| 845 | case 'boundaries',
|
---|
| 846 | plot_boundaries(md,options,subplotwidth,i);
|
---|
| 847 | return;
|
---|
| 848 | @@ -32,23 +30,18 @@
|
---|
| 849 | case 'highlightelements',
|
---|
| 850 | plot_highlightelements(md,options,subplotwidth,i);
|
---|
| 851 | return;
|
---|
| 852 | -
|
---|
| 853 | case 'qmumean',
|
---|
| 854 | plot_qmumean(md,options,nlines,ncols,i);
|
---|
| 855 | return;
|
---|
| 856 | -
|
---|
| 857 | case 'qmustddev',
|
---|
| 858 | plot_qmustddev(md,options,nlines,ncols,i);
|
---|
| 859 | return;
|
---|
| 860 | -
|
---|
| 861 | case 'qmuhistnorm',
|
---|
| 862 | plot_qmuhistnorm(md,options,nlines,ncols,i);
|
---|
| 863 | return;
|
---|
| 864 | -
|
---|
| 865 | case 'qmu_mass_flux_segments',
|
---|
| 866 | plot_qmu_mass_flux_segments(md,options,nlines,ncols,i);
|
---|
| 867 | return;
|
---|
| 868 | -
|
---|
| 869 | case 'part_hist',
|
---|
| 870 | plot_parthist(md,options,nlines,ncols,i);
|
---|
| 871 | return;
|
---|
| 872 | @@ -120,10 +113,8 @@
|
---|
| 873 | case 'segments'
|
---|
| 874 | plot_segments(md,options,subplotwidth,i,data)
|
---|
| 875 | return
|
---|
| 876 | -
|
---|
| 877 | case 'quiver'
|
---|
| 878 | data=[md.initialization.vx md.initialization.vy]; %Go ahead and try plot_unit
|
---|
| 879 | -
|
---|
| 880 | case {'strainrate_tensor','strainrate','strainrate_principal','strainrate_principalaxis1','strainrate_principalaxis2','strainrate_principalaxis3',...
|
---|
| 881 | 'stress_tensor','stress','stress_principal','stress_principalaxis1','stress_principalaxis2','stress_principalaxis3',...
|
---|
| 882 | 'deviatoricstress_tensor','deviatoricstress','deviatoricstress_principal','deviatoricstress_principalaxis1','deviatoricstress_principalaxis2','deviatoricstress_principalaxis3'},
|
---|
| 883 | @@ -137,13 +128,10 @@
|
---|
| 884 | return;
|
---|
| 885 | case 'transient_results',
|
---|
| 886 | plot_transient_results(md,options,subplotwidth,i);
|
---|
| 887 | -
|
---|
| 888 | case 'transient_field',
|
---|
| 889 | plot_transient_field(md,options,subplotwidth,i);
|
---|
| 890 | return;
|
---|
| 891 | -
|
---|
| 892 | otherwise,
|
---|
| 893 | -
|
---|
| 894 | if ismember(data,properties('model')),
|
---|
| 895 | data=eval(['md.' data ';']);
|
---|
| 896 | else
|
---|
| 897 | @@ -158,19 +146,19 @@
|
---|
| 898 | return;
|
---|
| 899 | end
|
---|
| 900 |
|
---|
| 901 | -%Figure out if this is a semi-transparent plot.
|
---|
| 902 | +%Figure out if this is a Google Maps plot.
|
---|
| 903 | if exist(options,'googlemaps'),
|
---|
| 904 | plot_googlemaps(md,data,options,nlines,ncols,i);
|
---|
| 905 | return;
|
---|
| 906 | end
|
---|
| 907 |
|
---|
| 908 | -%Figure out if this is a semi-transparent plot.
|
---|
| 909 | +%Figure out if this is a landsat plot.
|
---|
| 910 | if getfieldvalue(options,'landsat',0),
|
---|
| 911 | plot_landsat(md,data,options,nlines,ncols,i);
|
---|
| 912 | return;
|
---|
| 913 | end
|
---|
| 914 |
|
---|
| 915 | -%Figure out if this is a semi-transparent plot.
|
---|
| 916 | +%Figure out if this is a gridded plot.
|
---|
| 917 | if exist(options,'gridded'),
|
---|
| 918 | plot_gridded(md,data,options,nlines,ncols,i);
|
---|
| 919 | return;
|
---|
| 920 | Index: ../trunk-jpl/src/m/shp/shpread.py
|
---|
| 921 | ===================================================================
|
---|
| 922 | --- ../trunk-jpl/src/m/shp/shpread.py (nonexistent)
|
---|
| 923 | +++ ../trunk-jpl/src/m/shp/shpread.py (revision 25065)
|
---|
| 924 | @@ -0,0 +1,136 @@
|
---|
| 925 | +from os import path
|
---|
| 926 | +try:
|
---|
| 927 | + import shapefile
|
---|
| 928 | +except ImportError:
|
---|
| 929 | + print("could not import shapefile, PyShp has not been installed, no shapefile reading capabilities enabled")
|
---|
| 930 | +
|
---|
| 931 | +from pairoptions import pairoptions
|
---|
| 932 | +
|
---|
| 933 | +
|
---|
| 934 | +def shpread(filename, *args): #{{{
|
---|
| 935 | + '''
|
---|
| 936 | + SHPREAD - read a shape file and build a dict
|
---|
| 937 | +
|
---|
| 938 | + This routine reads a shape file .shp and builds a dict array containing the
|
---|
| 939 | + fields x and y corresponding to the coordinates, one for the filename
|
---|
| 940 | + of the shp file, for the density, for the nodes, and a field closed to
|
---|
| 941 | + indicate if the domain is closed. If this initial shapefile is point only,
|
---|
| 942 | + the fields closed and points are ommited.
|
---|
| 943 | + The first argument is the .shp file to be read and the second one
|
---|
| 944 | + (optional) indicates if the last point shall be read (1 to read it, 0 not
|
---|
| 945 | + to).
|
---|
| 946 | +
|
---|
| 947 | + The current implementation of shpread depends on PyShp.
|
---|
| 948 | +
|
---|
| 949 | + Usage:
|
---|
| 950 | + dict = shpread(filename)
|
---|
| 951 | +
|
---|
| 952 | + Example:
|
---|
| 953 | + From underling PyShp implementation, "The shapefile format is actually
|
---|
| 954 | + a collection of three files. You specify the base filename of the
|
---|
| 955 | + shapefile or the complete filename of any of the shapefile component
|
---|
| 956 | + files.""
|
---|
| 957 | +
|
---|
| 958 | + dict = shpread('domainoutline.shp')
|
---|
| 959 | + OR
|
---|
| 960 | + dict = shpread('domainoutline.dbf')
|
---|
| 961 | + OR
|
---|
| 962 | + dict = shpread('domainoutline')
|
---|
| 963 | +
|
---|
| 964 | + "OR any of the other 5+ formats which are potentially part of a
|
---|
| 965 | + shapefile. The library does not care about file extensions". We do,
|
---|
| 966 | + however, check that a file with the base filename or base filename with
|
---|
| 967 | + .shp extension exists.
|
---|
| 968 | +
|
---|
| 969 | + See also EXPDOC, EXPWRITEASVERTICES
|
---|
| 970 | +
|
---|
| 971 | + Sources:
|
---|
| 972 | + - https://github.com/GeospatialPython/pyshp
|
---|
| 973 | + '''
|
---|
| 974 | +
|
---|
| 975 | + #recover options
|
---|
| 976 | + options = pairoptions(*args)
|
---|
| 977 | +
|
---|
| 978 | + #some checks
|
---|
| 979 | + if not (path.isfile(filename) or path.isfile(filename + '.shp')):
|
---|
| 980 | + raise RuntimeError('shpread error message: file {} or {}.shp not found!'.format(filename, filename))
|
---|
| 981 | +
|
---|
| 982 | + #read shapefile
|
---|
| 983 | + sf = shapefile.Reader(filename)
|
---|
| 984 | +
|
---|
| 985 | + Dicts = []
|
---|
| 986 | +
|
---|
| 987 | + #retrieve ID (if it exists)
|
---|
| 988 | + fields = sf.fields
|
---|
| 989 | + for i in range(1, len(fields)): # skip over first field, which is "DeletionFlag"
|
---|
| 990 | + if fields[i][0] == 'id':
|
---|
| 991 | + name = str(sf.record(i - 1)[0]) # record index is offset by one, again, because of "DeletionFlag"
|
---|
| 992 | + break
|
---|
| 993 | +
|
---|
| 994 | + shapes = sf.shapes()
|
---|
| 995 | + for i in range(len(shapes)):
|
---|
| 996 | + Dict = {}
|
---|
| 997 | + shape = shapes[i]
|
---|
| 998 | + if shape.shapeType == shapefile.POINT:
|
---|
| 999 | + Dict['x'] = shape.points[0][0]
|
---|
| 1000 | + Dict['y'] = shape.points[0][1]
|
---|
| 1001 | + Dict['density'] = 1
|
---|
| 1002 | + Dict['Geometry'] = 'Point'
|
---|
| 1003 | + elif shape.shapeType == shapefile.POLYLINE:
|
---|
| 1004 | + num_points = len(shape.points)
|
---|
| 1005 | + x = []
|
---|
| 1006 | + y = []
|
---|
| 1007 | + for j in range(num_points):
|
---|
| 1008 | + point = shape.points[j]
|
---|
| 1009 | + x.append(point[0])
|
---|
| 1010 | + y.append(point[1])
|
---|
| 1011 | + Dict['x'] = x
|
---|
| 1012 | + Dict['y'] = y
|
---|
| 1013 | + Dict['nods'] = num_points
|
---|
| 1014 | + Dict['density'] = 1
|
---|
| 1015 | + Dict['closed'] = 1
|
---|
| 1016 | + Dict['BoundingBox'] = shape.bbox
|
---|
| 1017 | + Dict['Geometry'] = 'Line'
|
---|
| 1018 | + elif shape.shapeType == shapefile.POLYGON:
|
---|
| 1019 | + num_points = len(shape.points)
|
---|
| 1020 | + x = []
|
---|
| 1021 | + y = []
|
---|
| 1022 | + for j in range(num_points):
|
---|
| 1023 | + point = shape.points[j]
|
---|
| 1024 | + x.append(point[0])
|
---|
| 1025 | + y.append(point[1])
|
---|
| 1026 | + Dict['x'] = x
|
---|
| 1027 | + Dict['y'] = y
|
---|
| 1028 | + Dict['nods'] = num_points
|
---|
| 1029 | + Dict['density'] = 1
|
---|
| 1030 | + Dict['closed'] = 1
|
---|
| 1031 | + Dict['BoundingBox'] = shape.bbox
|
---|
| 1032 | + Dict['Geometry'] = 'Polygon'
|
---|
| 1033 | + else:
|
---|
| 1034 | + # NOTE: We could do this once before looping over shapes as all
|
---|
| 1035 | + # shapes in the file must be of the same type, but we would
|
---|
| 1036 | + # need to have a second check anyway in order to know how to
|
---|
| 1037 | + # parse the points. So, let's just assume the file is not
|
---|
| 1038 | + # malformed.
|
---|
| 1039 | + #
|
---|
| 1040 | + raise Exception('shpread error: geometry {} is not currently supported'.format(shape.shapeTypeName))
|
---|
| 1041 | + name = ''
|
---|
| 1042 | + fields = sf.fields
|
---|
| 1043 | + for j in range(1, len(fields)): # skip over first field, which is "DeletionFlag"
|
---|
| 1044 | + fieldname = fields[j][0]
|
---|
| 1045 | + # 'id' field gets special treatment
|
---|
| 1046 | + if fieldname == 'id':
|
---|
| 1047 | + name = str(sf.record(j - 1)[0]) # record index is offset by one, again, because of "DeletionFlag"
|
---|
| 1048 | + else:
|
---|
| 1049 | + Dict[fieldname] = sf.record(j - 1)[0]
|
---|
| 1050 | + Dict['name'] = name
|
---|
| 1051 | + Dicts.append(Dict)
|
---|
| 1052 | +
|
---|
| 1053 | + invert = options.getfieldvalue('invert', 0)
|
---|
| 1054 | + if invert:
|
---|
| 1055 | + for i in range(len(Dicts)):
|
---|
| 1056 | + Dicts[i].x = np.flipud(Dicts[i].x)
|
---|
| 1057 | + Dicts[i].y = np.flipud(Dicts[i].y)
|
---|
| 1058 | +
|
---|
| 1059 | + return Dicts
|
---|
| 1060 | +#}}}
|
---|
| 1061 | Index: ../trunk-jpl/src/m/shp/shpread.m
|
---|
| 1062 | ===================================================================
|
---|
| 1063 | --- ../trunk-jpl/src/m/shp/shpread.m (revision 25064)
|
---|
| 1064 | +++ ../trunk-jpl/src/m/shp/shpread.m (revision 25065)
|
---|
| 1065 | @@ -1,22 +1,22 @@
|
---|
| 1066 | function Struct=shpread(filename,varargin)
|
---|
| 1067 | -%SHPREAD - read a shape file and build a Structure
|
---|
| 1068 | +%SHPREAD - read a shape file and build a struct
|
---|
| 1069 | %
|
---|
| 1070 | -% This routine reads a shape file .shp and builds a Structure containing the
|
---|
| 1071 | -% fields x and y corresponding to the coordinates, one for the filename of
|
---|
| 1072 | -% the shp file, for the density, for the nodes, and a field closed to
|
---|
| 1073 | -% indicate if the domain is closed.
|
---|
| 1074 | -% If this initial shapefile is point only, the fields closed and
|
---|
| 1075 | -% points are ommited
|
---|
| 1076 | -% The first argument is the .shp file to be read and the second one (optional)
|
---|
| 1077 | -% indicates if the last point shall be read (1 to read it, 0 not to).
|
---|
| 1078 | +% This routine reads a shape file .shp and builds a structure array
|
---|
| 1079 | +% containing the fields x and y corresponding to the coordinates, one for the
|
---|
| 1080 | +% filename of the shp file, for the density, for the nodes, and a field
|
---|
| 1081 | +% closed to indicate if the domain is closed. If this initial shapefile is
|
---|
| 1082 | +% point only, the fields closed and points are omitted.
|
---|
| 1083 | +% The first argument is the .shp file to be read and the second one
|
---|
| 1084 | +% (optional) indicates if the last point shall be read (1 to read it, 0 not
|
---|
| 1085 | +% to).
|
---|
| 1086 | %
|
---|
| 1087 | -% Usage:
|
---|
| 1088 | -% Struct=shpread(filename)
|
---|
| 1089 | +% Usage:
|
---|
| 1090 | +% Struct=shpread(filename)
|
---|
| 1091 | %
|
---|
| 1092 | -% Example:
|
---|
| 1093 | -% Struct=shpread('domainoutline.shp')
|
---|
| 1094 | +% Example:
|
---|
| 1095 | +% Struct=shpread('domainoutline.shp')
|
---|
| 1096 | %
|
---|
| 1097 | -% See also EXPDOC, EXPWRITEASVERTICES
|
---|
| 1098 | +% See also EXPDOC, EXPWRITEASVERTICES
|
---|
| 1099 |
|
---|
| 1100 | %recover options
|
---|
| 1101 | options=pairoptions(varargin{:});
|
---|
| 1102 | @@ -26,9 +26,6 @@
|
---|
| 1103 | error(['shpread error message: file ' filename ' not found!']);
|
---|
| 1104 | end
|
---|
| 1105 |
|
---|
| 1106 | -%initialize number of profile
|
---|
| 1107 | -count=0;
|
---|
| 1108 | -
|
---|
| 1109 | %read shapefile
|
---|
| 1110 | shp=shaperead(filename);
|
---|
| 1111 |
|
---|
| 1112 | @@ -35,7 +32,7 @@
|
---|
| 1113 | Struct=struct([]);
|
---|
| 1114 | fields=fieldnames(shp);
|
---|
| 1115 | for i=1:length(shp),
|
---|
| 1116 | - if strcmpi(shp(i).Geometry,'Polygon'),
|
---|
| 1117 | + if strcmpi(shp(i).Geometry,'Point'),
|
---|
| 1118 | x=shp(i).X'; y=shp(i).Y';
|
---|
| 1119 | ids=find(isnan(x));
|
---|
| 1120 | x(ids)=[]; y(ids)=[];
|
---|
| 1121 | @@ -42,9 +39,7 @@
|
---|
| 1122 |
|
---|
| 1123 | Struct(end+1).x=x;
|
---|
| 1124 | Struct(end).y=y;
|
---|
| 1125 | - Struct(end).nods=length(x);
|
---|
| 1126 | Struct(end).density=1;
|
---|
| 1127 | - Struct(end).closed=1;
|
---|
| 1128 | if isfield(shp,'id'),
|
---|
| 1129 | Struct(end).name=num2str(shp(i).id);
|
---|
| 1130 | else
|
---|
| 1131 | @@ -56,9 +51,7 @@
|
---|
| 1132 | Struct(end).(field)=shp(i).(field);
|
---|
| 1133 | end
|
---|
| 1134 | end
|
---|
| 1135 | - end
|
---|
| 1136 | -
|
---|
| 1137 | - if strcmpi(shp(i).Geometry,'Line'),
|
---|
| 1138 | + elseif strcmpi(shp(i).Geometry,'Line'),
|
---|
| 1139 | x=shp(i).X'; y=shp(i).Y';
|
---|
| 1140 | ids=find(isnan(x));
|
---|
| 1141 | x(ids)=[]; y(ids)=[];
|
---|
| 1142 | @@ -79,10 +72,7 @@
|
---|
| 1143 | Struct(end).(field)=shp(i).(field);
|
---|
| 1144 | end
|
---|
| 1145 | end
|
---|
| 1146 | - end
|
---|
| 1147 | -
|
---|
| 1148 | -
|
---|
| 1149 | - if strcmpi(shp(i).Geometry,'Point'),
|
---|
| 1150 | + elseif strcmpi(shp(i).Geometry,'Polygon'),
|
---|
| 1151 | x=shp(i).X'; y=shp(i).Y';
|
---|
| 1152 | ids=find(isnan(x));
|
---|
| 1153 | x(ids)=[]; y(ids)=[];
|
---|
| 1154 | @@ -89,7 +79,9 @@
|
---|
| 1155 |
|
---|
| 1156 | Struct(end+1).x=x;
|
---|
| 1157 | Struct(end).y=y;
|
---|
| 1158 | + Struct(end).nods=length(x);
|
---|
| 1159 | Struct(end).density=1;
|
---|
| 1160 | + Struct(end).closed=1;
|
---|
| 1161 | if isfield(shp,'id'),
|
---|
| 1162 | Struct(end).name=num2str(shp(i).id);
|
---|
| 1163 | else
|
---|
| 1164 | Index: ../trunk-jpl/src/m/mesh/planet/gmsh/gmshplanet.py
|
---|
| 1165 | ===================================================================
|
---|
| 1166 | --- ../trunk-jpl/src/m/mesh/planet/gmsh/gmshplanet.py (revision 25064)
|
---|
| 1167 | +++ ../trunk-jpl/src/m/mesh/planet/gmsh/gmshplanet.py (revision 25065)
|
---|
| 1168 | @@ -1,4 +1,3 @@
|
---|
| 1169 | -import os
|
---|
| 1170 | import subprocess
|
---|
| 1171 |
|
---|
| 1172 | import numpy as np
|
---|
| 1173 | @@ -9,7 +8,7 @@
|
---|
| 1174 | from pairoptions import *
|
---|
| 1175 |
|
---|
| 1176 |
|
---|
| 1177 | -def gmshplanet(*varargin):
|
---|
| 1178 | +def gmshplanet(*args):
|
---|
| 1179 | '''
|
---|
| 1180 | GMSHPLANET - mesh generation for a sphere. Very specific code for gmsh from $ISSM_DIR/src/demos/simple_geo/sphere.geo
|
---|
| 1181 |
|
---|
| 1182 | @@ -33,7 +32,7 @@
|
---|
| 1183 | raise RuntimeError('gmshplanet: Gmsh major version %s not supported!' % gmshmajorversion)
|
---|
| 1184 |
|
---|
| 1185 | #process options
|
---|
| 1186 | - options = pairoptions(*varargin)
|
---|
| 1187 | + options = pairoptions(*args)
|
---|
| 1188 | #options = deleteduplicates(options, 1)
|
---|
| 1189 |
|
---|
| 1190 | #recover parameters:
|
---|
| 1191 | Index: ../trunk-jpl/src/m/coordsystems/gdaltransform.py
|
---|
| 1192 | ===================================================================
|
---|
| 1193 | --- ../trunk-jpl/src/m/coordsystems/gdaltransform.py (revision 25064)
|
---|
| 1194 | +++ ../trunk-jpl/src/m/coordsystems/gdaltransform.py (revision 25065)
|
---|
| 1195 | @@ -5,31 +5,35 @@
|
---|
| 1196 |
|
---|
| 1197 | from loadvars import *
|
---|
| 1198 |
|
---|
| 1199 | +
|
---|
| 1200 | def gdaltransform(x, y, proj_in, proj_out): #{{{
|
---|
| 1201 | '''
|
---|
| 1202 | GDALTRANSFORM - switch from one projection system to another
|
---|
| 1203 |
|
---|
| 1204 | - Usage:
|
---|
| 1205 | - [x, y] = gdaltransform(x1, y1, epsg_in, epsg_out)
|
---|
| 1206 | + Usage:
|
---|
| 1207 | + [x, y] = gdaltransform(x1, y1, epsg_in, epsg_out)
|
---|
| 1208 |
|
---|
| 1209 | - Example:
|
---|
| 1210 | - [x, y] = gdaltranform(md.mesh.long, md.mesh.lat, 'EPSG:4326', 'EPSG:3031')
|
---|
| 1211 | + Example:
|
---|
| 1212 | + [x, y] = gdaltranform(md.mesh.long, md.mesh.lat, 'EPSG:4326', 'EPSG:3031')
|
---|
| 1213 |
|
---|
| 1214 | - For reference:
|
---|
| 1215 | - EPSG: 4326 (lat, long)
|
---|
| 1216 | - EPSG: 3341 (Greenland, UPS 45W, 70N)
|
---|
| 1217 | - EPSG: 3031 (Antarctica, UPS 0E, 71S)
|
---|
| 1218 | + For reference:
|
---|
| 1219 | + EPSG: 4326 (lat, long)
|
---|
| 1220 | + EPSG: 3341 (Greenland, UPS 45W, 70N)
|
---|
| 1221 | + EPSG: 3031 (Antarctica, UPS 0E, 71S)
|
---|
| 1222 |
|
---|
| 1223 | - ll2xy default projection Antarctica:
|
---|
| 1224 | - +proj = stere +lat_0=-90 +lat_ts=-71 +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378273 +b=6356889.448564109 +units=m +no_defs
|
---|
| 1225 | - ll2xy default projection Greenland:
|
---|
| 1226 | - +proj = stere +lat_0=90 +lat_ts=70 +lon_0=-45 +k=1 +x_0=0 +y_0=0 +a=6378273 +b=6356889.448564109 +units=m +no_defs
|
---|
| 1227 | - Bamber's Greenland projection
|
---|
| 1228 | - +proj = stere +lat_0=90 +lat_ts=71 +lon_0=-39 +k=1 +x_0=0 +y_0=0 +a=6378273 +b=6356889.448564109 +units=m +no_defs
|
---|
| 1229 | + ll2xy default projection Antarctica:
|
---|
| 1230 | + +proj = stere +lat_0=-90 +lat_ts=-71 +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378273 +b=6356889.448564109 +units=m +no_defs
|
---|
| 1231 | + ll2xy default projection Greenland:
|
---|
| 1232 | + +proj = stere +lat_0=90 +lat_ts=70 +lon_0=-45 +k=1 +x_0=0 +y_0=0 +a=6378273 +b=6356889.448564109 +units=m +no_defs
|
---|
| 1233 | + Bamber's Greenland projection
|
---|
| 1234 | + +proj = stere +lat_0=90 +lat_ts=71 +lon_0=-39 +k=1 +x_0=0 +y_0=0 +a=6378273 +b=6356889.448564109 +units=m +no_defs
|
---|
| 1235 |
|
---|
| 1236 | - To get proj.4 string form EPSG, use gdalsrsinfo. Example:
|
---|
| 1237 | + To get proj.4 string form EPSG, use gdalsrsinfo. Example:
|
---|
| 1238 |
|
---|
| 1239 | - gdalsrsinfo epsg:4326 | grep "PROJ.4" | sed "s/PROJ.4 : //"
|
---|
| 1240 | + gdalsrsinfo epsg:4326 | grep "PROJ.4" | sed "s/PROJ.4 : //"
|
---|
| 1241 | +
|
---|
| 1242 | + TODO:
|
---|
| 1243 | + - Remove shlex and follow subprocess pattern implemented in src/m/coordsystems/epsg2proj.py
|
---|
| 1244 | '''
|
---|
| 1245 |
|
---|
| 1246 | # Give ourselves unique file names
|
---|
| 1247 | @@ -41,7 +45,7 @@
|
---|
| 1248 | file_in.write(b'%8g %8g\n' % (x.flatten(1) y.flatten(1)))
|
---|
| 1249 | file_in.close()
|
---|
| 1250 |
|
---|
| 1251 | - args = shlex.split('gdaltransform -s_srs %s -t_srs %s < %s > %s' % (proj_in, proj_out, filename_in, filename_out))
|
---|
| 1252 | + args = shlex.split('gdaltransform -s_srs {} -t_srs {} < {} > {}'.format(proj_in, proj_out, filename_in, filename_out))
|
---|
| 1253 | subprocess.check_call(args) # Will raise CalledProcessError if return code is not 0
|
---|
| 1254 |
|
---|
| 1255 | A = loadvars(filename_out)
|
---|
| 1256 | @@ -52,4 +56,6 @@
|
---|
| 1257 |
|
---|
| 1258 | os.remove(filename_in)
|
---|
| 1259 | os.remove(filename_out)
|
---|
| 1260 | +
|
---|
| 1261 | + return [xout, yout]
|
---|
| 1262 | #}}}
|
---|
| 1263 | Index: ../trunk-jpl/src/m/geometry/polyarea.py
|
---|
| 1264 | ===================================================================
|
---|
| 1265 | --- ../trunk-jpl/src/m/geometry/polyarea.py (nonexistent)
|
---|
| 1266 | +++ ../trunk-jpl/src/m/geometry/polyarea.py (revision 25065)
|
---|
| 1267 | @@ -0,0 +1,28 @@
|
---|
| 1268 | +import math
|
---|
| 1269 | +
|
---|
| 1270 | +import numpy as np
|
---|
| 1271 | +
|
---|
| 1272 | +
|
---|
| 1273 | +def polyarea: #{{{
|
---|
| 1274 | + '''
|
---|
| 1275 | + POLYAREA - returns the area of the 2-D polygon defined by the vertices in
|
---|
| 1276 | + lists x and y
|
---|
| 1277 | +
|
---|
| 1278 | + Partial implementation of MATLAB's polyarea function. If x and y are
|
---|
| 1279 | + lists of the same length, then polyarea returns the scalar area of the
|
---|
| 1280 | + polygon defined by x and y.
|
---|
| 1281 | +
|
---|
| 1282 | + Usage:
|
---|
| 1283 | + a = polyarea(x, y)
|
---|
| 1284 | +
|
---|
| 1285 | + Sources:
|
---|
| 1286 | + - https://www.mathworks.com/help/matlab/ref/polyarea.html
|
---|
| 1287 | + - https://stackoverflow.com/questions/24467972/calculate-area-of-polygon-given-x-y-coordinates
|
---|
| 1288 | + - https://en.wikipedia.org/wiki/Shoelace_formula
|
---|
| 1289 | +
|
---|
| 1290 | + TODO:
|
---|
| 1291 | + - Test that output falls within some tolerance of MATLAB's polyarea
|
---|
| 1292 | + function.
|
---|
| 1293 | + '''
|
---|
| 1294 | + return 0.5 * np.abs(np.dot(x, np.roll(y, 1)) - np.dot(y, np.roll(x, 1)))
|
---|
| 1295 | +#}}}
|
---|
| 1296 | Index: ../trunk-jpl/src/m/classes/boundary.py
|
---|
| 1297 | ===================================================================
|
---|
| 1298 | --- ../trunk-jpl/src/m/classes/boundary.py (nonexistent)
|
---|
| 1299 | +++ ../trunk-jpl/src/m/classes/boundary.py (revision 25065)
|
---|
| 1300 | @@ -0,0 +1,176 @@
|
---|
| 1301 | +import math
|
---|
| 1302 | +
|
---|
| 1303 | +import numpy as np
|
---|
| 1304 | +
|
---|
| 1305 | +from epsg2proj import epsg2proj
|
---|
| 1306 | +from pairoptions import pairoptions
|
---|
| 1307 | +from shpread import shpread
|
---|
| 1308 | +
|
---|
| 1309 | +
|
---|
| 1310 | +class boundary(object): #{{{
|
---|
| 1311 | + '''
|
---|
| 1312 | + BOUNDARY class definition
|
---|
| 1313 | +
|
---|
| 1314 | + Usage:
|
---|
| 1315 | + boundary = boundary()
|
---|
| 1316 | + '''
|
---|
| 1317 | +
|
---|
| 1318 | + def __init__(self, *args): #{{{
|
---|
| 1319 | + self.boundaries = []
|
---|
| 1320 | + self.name = ''
|
---|
| 1321 | + self.continent = ''
|
---|
| 1322 | + self.proj = epsg2proj(4326)
|
---|
| 1323 | +
|
---|
| 1324 | + self.setdefaultparameters()
|
---|
| 1325 | +
|
---|
| 1326 | + if len(args):
|
---|
| 1327 | + options = pairoptions(*args)
|
---|
| 1328 | +
|
---|
| 1329 | + #recover field values
|
---|
| 1330 | + self.shppath = options.getfieldvalue('shppath', '')
|
---|
| 1331 | + self.shpfilename = options.getfieldvalue('shpfilename', '')
|
---|
| 1332 | + self.orientation = options.getfieldvalue('orientation', 'normal')
|
---|
| 1333 | +
|
---|
| 1334 | + #figure out projection string:
|
---|
| 1335 | + if options.exist('epsg'):
|
---|
| 1336 | + if options.exist('proj'):
|
---|
| 1337 | + raise RuntimeError('Error in constructor for boundary {}. Cannot supply epsg and proj at the same time!'.format(self.shppath))
|
---|
| 1338 | + epsg = options.getfieldvalue('epsg')
|
---|
| 1339 | + proj = epsg2proj(epsg) # convert to PROJ.4 format
|
---|
| 1340 | + elif options.exist('proj'):
|
---|
| 1341 | + if options.exist('epsg'):
|
---|
| 1342 | + raise RuntimeError('Error in constructor for boundary {}. Cannot supply proj and epsg at the same time!'.format(self.shppath))
|
---|
| 1343 | + proj = options.getfieldvalue('proj')
|
---|
| 1344 | + else:
|
---|
| 1345 | + proj = '+proj=longlat +datum=WGS84 +no_defs'
|
---|
| 1346 | +
|
---|
| 1347 | + self.proj = proj
|
---|
| 1348 | + #}}}
|
---|
| 1349 | +
|
---|
| 1350 | + def __repr__(self): #{{{
|
---|
| 1351 | + s = ' boundary parameters:\n'
|
---|
| 1352 | + s += '{}\n'.format(fielddisplay(self, 'shppath', 'path to filename for this boundary'))
|
---|
| 1353 | + s += '{}\n'.format(fielddisplay(self, 'shpfilename', 'shape file name'))
|
---|
| 1354 | + s += '{}\n'.format(fielddisplay(self, 'orientation', 'orientation (default is \'normal\', can be \'reverse\')'))
|
---|
| 1355 | + s += '{}\n'.format(fielddisplay(self, 'proj', 'shape file projection string (follows PROJ.4 standard)'))
|
---|
| 1356 | +
|
---|
| 1357 | + return s
|
---|
| 1358 | + #}}}
|
---|
| 1359 | +
|
---|
| 1360 | + def setdefaultparameters(self): #{{{
|
---|
| 1361 | + self.shppath = ''
|
---|
| 1362 | + self.shpfilename = ''
|
---|
| 1363 | + self.orientation = 'normal'
|
---|
| 1364 | + self.proj = '+proj=longlat +datum=WGS84 +no_defs' #EPSG 4326
|
---|
| 1365 | +
|
---|
| 1366 | + return self
|
---|
| 1367 | + #}}}
|
---|
| 1368 | +
|
---|
| 1369 | + def name(self): #{{{
|
---|
| 1370 | + output = self.shpfilename
|
---|
| 1371 | +
|
---|
| 1372 | + return output
|
---|
| 1373 | + #}}}
|
---|
| 1374 | +
|
---|
| 1375 | + def edges(self): #{{{
|
---|
| 1376 | + #read domain
|
---|
| 1377 | + path, name, ext = fileparts(shp.shpfilename)
|
---|
| 1378 | + if ext != 'shp':
|
---|
| 1379 | + ext = 'shp'
|
---|
| 1380 | + output = shpread('{}/{}.{}'.format(self.shppath, name, ext))
|
---|
| 1381 | +
|
---|
| 1382 | + #do we reverse?
|
---|
| 1383 | + if self.orientation == 'reverse':
|
---|
| 1384 | + output.x = np.flipud(output.x)
|
---|
| 1385 | + output.y = np.flipud(output.y)
|
---|
| 1386 | + #}}}
|
---|
| 1387 | +
|
---|
| 1388 | + def plot(self, *args): #{{{
|
---|
| 1389 | + #recover options
|
---|
| 1390 | + options = pairoptions(*args)
|
---|
| 1391 | +
|
---|
| 1392 | + #parse input
|
---|
| 1393 | + # TODO: Sort out what options we should set (see
|
---|
| 1394 | + # src/m/classes/boundary.m)
|
---|
| 1395 | +
|
---|
| 1396 | + if options.exist('epsg'):
|
---|
| 1397 | + if options.exist('proj'):
|
---|
| 1398 | + raise RuntimeError('Boundary plot error message: cannot specify epsg and proj at the same time for plot projection')
|
---|
| 1399 | + proj = epsg2proj(options.getfieldvalue('epsg'))
|
---|
| 1400 | + elif options.exist('proj'):
|
---|
| 1401 | + proj = options.getfieldvalue('proj')
|
---|
| 1402 | + else:
|
---|
| 1403 | + proj = epsg2proj(4326)
|
---|
| 1404 | +
|
---|
| 1405 | + #read domain
|
---|
| 1406 | + path, name, ext = fileparts(shp.shpfilename)
|
---|
| 1407 | + if ext != 'shp':
|
---|
| 1408 | + ext = 'shp'
|
---|
| 1409 | + domain = shpread('{}/{}.{}'.format(self.shppath, name, ext))
|
---|
| 1410 | +
|
---|
| 1411 | + #convert boundary to another reference frame #{{{
|
---|
| 1412 | + for i in range(len(domain)):
|
---|
| 1413 | + try:
|
---|
| 1414 | + x, y = gdaltransform(domain[i].x, domain[i].y, self.proj, proj)
|
---|
| 1415 | + except error as e:
|
---|
| 1416 | + print(e)
|
---|
| 1417 | + print(self)
|
---|
| 1418 | +
|
---|
| 1419 | + # TODO: Figure out how to recover figure here: do we pass 'fig' and
|
---|
| 1420 | + # 'ax' in args?
|
---|
| 1421 | + #for i in range(len(domain)):
|
---|
| 1422 | + # x = domain[i].x * unitmultiplier
|
---|
| 1423 | + # y = domain[i].y * unitmultiplier
|
---|
| 1424 | + # if len(x) == 1:
|
---|
| 1425 | + #}}}
|
---|
| 1426 | +
|
---|
| 1427 | + #TODO: Finish translating from MATLAB after test2004.py runs without plot
|
---|
| 1428 | + #}}}
|
---|
| 1429 | +
|
---|
| 1430 | + def checkconsistency(self, *args): #{{{
|
---|
| 1431 | + #recover options
|
---|
| 1432 | + options = pairoptions(*args)
|
---|
| 1433 | + tolerance = getfieldvalue(options, 'tolerance', 1e-5)
|
---|
| 1434 | +
|
---|
| 1435 | + #recover edges
|
---|
| 1436 | + edges = self.edges()
|
---|
| 1437 | +
|
---|
| 1438 | + if edges.Geometry == 'Point':
|
---|
| 1439 | + return
|
---|
| 1440 | + else:
|
---|
| 1441 | + #check that we don't have two identical vertices
|
---|
| 1442 | + x = edges.x
|
---|
| 1443 | + y = edges.y
|
---|
| 1444 | + distance = math.sqrt((x[:-2] - x[1:-1]) ** 2 + (y[:-2] - y[1:-1]) ** 2)
|
---|
| 1445 | + dmax = distance.max()
|
---|
| 1446 | + isidentical = np.where(np.asarray(distance) < dmax * tolerance)
|
---|
| 1447 | + for elem in isidentical: # distance should be a 1D array, but return from np.where is a tuple of arrays
|
---|
| 1448 | + if len(elem) != 0:
|
---|
| 1449 | + raise Exception('boundary {} has two vertices extermely close to one another'.format(shpfilename))
|
---|
| 1450 | +
|
---|
| 1451 | + def plot3d(self, *args): #{{{
|
---|
| 1452 | + #recover options
|
---|
| 1453 | + options = pairoptions(*args)
|
---|
| 1454 | +
|
---|
| 1455 | + #parse input
|
---|
| 1456 | + # TODO: Sort out what options we should set (see
|
---|
| 1457 | + # src/m/classes/boundary.m)
|
---|
| 1458 | +
|
---|
| 1459 | + if options.exist('epsg'):
|
---|
| 1460 | + if options.exist('proj'):
|
---|
| 1461 | + raise RuntimeError('Boundary plot error message: cannot specify epsg and proj at the same time for plot projection')
|
---|
| 1462 | + proj = epsg2proj(options.getfieldvalue('epsg'))
|
---|
| 1463 | + elif options.exist('proj'):
|
---|
| 1464 | + proj = options.getfieldvalue('proj')
|
---|
| 1465 | + else:
|
---|
| 1466 | + proj = epsg2proj(4326)
|
---|
| 1467 | +
|
---|
| 1468 | + #read domain
|
---|
| 1469 | + path, name, ext = fileparts(shp.shpfilename)
|
---|
| 1470 | + if ext != 'shp':
|
---|
| 1471 | + ext = 'shp'
|
---|
| 1472 | + domain = shpread('{}/{}.{}'.format(self.shppath, name, ext))
|
---|
| 1473 | +
|
---|
| 1474 | + #TODO: Finish translating from MATLAB after test2004.py runs without plot
|
---|
| 1475 | + #}}}
|
---|
| 1476 | +#}}}
|
---|
| 1477 | Index: ../trunk-jpl/src/m/classes/sealevelmodel.m
|
---|
| 1478 | ===================================================================
|
---|
| 1479 | --- ../trunk-jpl/src/m/classes/sealevelmodel.m (revision 25064)
|
---|
| 1480 | +++ ../trunk-jpl/src/m/classes/sealevelmodel.m (revision 25065)
|
---|
| 1481 | @@ -162,10 +162,10 @@
|
---|
| 1482 | list=unique(list);
|
---|
| 1483 | end % }}}
|
---|
| 1484 | function addbasin(self,bas) % {{{
|
---|
| 1485 | - if ~strcmpi(class(bas),'basin')
|
---|
| 1486 | - error('addbasin method only takes a ''basin'' class object as input');
|
---|
| 1487 | - end;
|
---|
| 1488 | - self.basins{end+1}=bas;
|
---|
| 1489 | + if ~strcmpi(class(bas),'basin')
|
---|
| 1490 | + error('addbasin method only takes a ''basin'' class object as input');
|
---|
| 1491 | + end;
|
---|
| 1492 | + self.basins{end+1}=bas;
|
---|
| 1493 | end % }}}
|
---|
| 1494 | function intersections(self,varargin) % {{{
|
---|
| 1495 |
|
---|
| 1496 | Index: ../trunk-jpl/src/m/classes/sealevelmodel.py
|
---|
| 1497 | ===================================================================
|
---|
| 1498 | --- ../trunk-jpl/src/m/classes/sealevelmodel.py (revision 25064)
|
---|
| 1499 | +++ ../trunk-jpl/src/m/classes/sealevelmodel.py (revision 25065)
|
---|
| 1500 | @@ -10,21 +10,22 @@
|
---|
| 1501 | from private import private
|
---|
| 1502 | from TwoDToThreeD import TwoDToThreeD
|
---|
| 1503 |
|
---|
| 1504 | +
|
---|
| 1505 | class sealevelmodel(object):
|
---|
| 1506 | '''
|
---|
| 1507 | SEALEVELMODEL class definition
|
---|
| 1508 |
|
---|
| 1509 | - Usage:
|
---|
| 1510 | - slm = sealevelmodel(*args)
|
---|
| 1511 | + Usage:
|
---|
| 1512 | + slm = sealevelmodel(*args)
|
---|
| 1513 |
|
---|
| 1514 | - where args is a variable list of options
|
---|
| 1515 | + where args is a variable list of options
|
---|
| 1516 |
|
---|
| 1517 | - Example:
|
---|
| 1518 | - slm = sealevelmodel(
|
---|
| 1519 | - 'icecap', md_greenland,
|
---|
| 1520 | - 'icecap', md_antarctica,
|
---|
| 1521 | - 'earth', md_earth
|
---|
| 1522 | - )
|
---|
| 1523 | + Example:
|
---|
| 1524 | + slm = sealevelmodel(
|
---|
| 1525 | + 'icecap', md_greenland,
|
---|
| 1526 | + 'icecap', md_antarctica,
|
---|
| 1527 | + 'earth', md_earth
|
---|
| 1528 | + )
|
---|
| 1529 | '''
|
---|
| 1530 |
|
---|
| 1531 | def __init__(self, *args): #{{{
|
---|
| 1532 | @@ -58,11 +59,11 @@
|
---|
| 1533 | #}}}
|
---|
| 1534 |
|
---|
| 1535 | def __repr__(self): # {{{
|
---|
| 1536 | - s = '%s\n' % fielddisplay(self, 'icecaps', 'ice caps')
|
---|
| 1537 | - s += '%s\n' % fielddisplay(self, 'earth', 'earth')
|
---|
| 1538 | - s += '%s\n' % fielddisplay(self, 'settings', 'settings properties')
|
---|
| 1539 | - s += '%s\n' % fielddisplay(self, 'cluster', 'cluster parameters (number of cpus...')
|
---|
| 1540 | - s += '%s\n' % fielddisplay(self, 'miscellaneous', 'miscellaneous fields')
|
---|
| 1541 | + s = '{}\n'.format(fielddisplay(self, 'icecaps', 'ice caps'))
|
---|
| 1542 | + s += '{}\n'.format(fielddisplay(self, 'earth', 'earth'))
|
---|
| 1543 | + s += '{}\n'.format(fielddisplay(self, 'settings', 'settings properties'))
|
---|
| 1544 | + s += '{}\n'.format(fielddisplay(self, 'cluster', 'cluster parameters (number of cpus...'))
|
---|
| 1545 | + s += '{}\n'.format(fielddisplay(self, 'miscellaneous', 'miscellaneous fields'))
|
---|
| 1546 | #}}}
|
---|
| 1547 |
|
---|
| 1548 | def setdefaultparameters(self): # {{{
|
---|
| 1549 | @@ -84,7 +85,7 @@
|
---|
| 1550 | # Is the coupler turned on?
|
---|
| 1551 | for i in range(len(slm.icecaps)):
|
---|
| 1552 | if slm.icecaps[i].transient.iscoupler == 0:
|
---|
| 1553 | - warnings.warn('sealevelmodel checkconsistency error: icecap model %s should have the transient coupler option turned on!' % slm.icecaps[i].miscellaneous.name)
|
---|
| 1554 | + warnings.warn('sealevelmodel checkconsistency error: icecap model {} should have the transient coupler option turned on!'.format(slm.icecaps[i].miscellaneous.name))
|
---|
| 1555 |
|
---|
| 1556 | if slm.earth.transient.iscoupler == 0:
|
---|
| 1557 | warnings.warn('sealevelmodel checkconsistency error: earth model should have the transient coupler option turned on!')
|
---|
| 1558 | @@ -92,18 +93,18 @@
|
---|
| 1559 | # Check that the transition vectors have the right size
|
---|
| 1560 | for i in range(len(slm.icecaps)):
|
---|
| 1561 | if slm.icecaps[i].mesh.numberofvertices != len(slm.earth.slr.transitions[i]):
|
---|
| 1562 | - raise RuntimeError('sealevelmodel checkconsistency issue with size of transition vector for ice cap: %i name: %s' % (i, slm.icecaps[i].miscellaneous.name))
|
---|
| 1563 | + raise RuntimeError('sealevelmodel checkconsistency issue with size of transition vector for ice cap: {} name: {}'.format(i, slm.icecaps[i].miscellaneous.name))
|
---|
| 1564 |
|
---|
| 1565 | # Check that run frequency is the same everywhere
|
---|
| 1566 | for i in range(len(slm.icecaps)):
|
---|
| 1567 | if slm.icecaps[i].slr.geodetic_run_frequency != slm.earth.geodetic_run_frequency:
|
---|
| 1568 | - raise RuntimeError('sealevelmodel checkconsistency error: icecap model %s should have the same run frequency as earth!' % slm.icecaps[i].miscellaneous.name)
|
---|
| 1569 | + raise RuntimeError('sealevelmodel checkconsistency error: icecap model {} should have the same run frequency as earth!'.format(slm.icecaps[i].miscellaneous.name))
|
---|
| 1570 |
|
---|
| 1571 | # Make sure steric_rate is the same everywhere
|
---|
| 1572 | for i in range(len(slm.icecaps)):
|
---|
| 1573 | md = slm.icecaps[i]
|
---|
| 1574 | if np.nonzero(md.slr.steric_rate - slm.earth.slr.steric_rate[slm.earth.slr.transitions[i]]) != []:
|
---|
| 1575 | - raise RuntimeError('steric rate on ice cap %s is not the same as for the earth' % md.miscellaneous.name)
|
---|
| 1576 | + raise RuntimeError('steric rate on ice cap {} is not the same as for the earth'.format(md.miscellaneous.name))
|
---|
| 1577 | #}}}
|
---|
| 1578 |
|
---|
| 1579 | def mergeresults(self): # {{{
|
---|
| 1580 | @@ -137,7 +138,7 @@
|
---|
| 1581 |
|
---|
| 1582 | def listcaps(self): # {{{
|
---|
| 1583 | for i in range(len(self.icecaps)):
|
---|
| 1584 | - print('%i: %s' % (i, self.icecaps[i].miscellaneous.name))
|
---|
| 1585 | + print('{}: {}'.format(i, self.icecaps[i].miscellaneous.name))
|
---|
| 1586 | #}}}
|
---|
| 1587 |
|
---|
| 1588 | def continents(self): # {{{
|
---|
| 1589 | @@ -184,7 +185,7 @@
|
---|
| 1590 | yei = mdi.mesh.y[mdi.mesh.elements] * onesmatrix / 3
|
---|
| 1591 | zei = mdi.mesh.z[mdi.mesh.elements] * onesmatrix / 3
|
---|
| 1592 |
|
---|
| 1593 | - print('Computing vertex intersections for basin %s' % self.basins[i].name)
|
---|
| 1594 | + print('Computing vertex intersections for basin {}'.format(self.basins[i].name))
|
---|
| 1595 |
|
---|
| 1596 | self.transitions.append(meshintersect3d(self.earth.mesh.x, self.earth.mesh.y, self.earth.mesh.z, mdi.mesh.x, mdi.mesh.y, mdi.mesh.z, 'force', force))
|
---|
| 1597 | self.eltransitions.append(meshintersect3d(xe, ye, ze, xei, yei, zei, 'force', force))
|
---|
| 1598 | Index: ../trunk-jpl/src/m/classes/basin.py
|
---|
| 1599 | ===================================================================
|
---|
| 1600 | --- ../trunk-jpl/src/m/classes/basin.py (nonexistent)
|
---|
| 1601 | +++ ../trunk-jpl/src/m/classes/basin.py (revision 25065)
|
---|
| 1602 | @@ -0,0 +1,214 @@
|
---|
| 1603 | +import math
|
---|
| 1604 | +
|
---|
| 1605 | +from boundary import boundary
|
---|
| 1606 | +from epsg2proj import epsg2proj
|
---|
| 1607 | +from helpers import fileparts
|
---|
| 1608 | +from laea import laea
|
---|
| 1609 | +from pairoptions import pairoptions
|
---|
| 1610 | +from polyarea import polyarea
|
---|
| 1611 | +from shpread import shpread
|
---|
| 1612 | +
|
---|
| 1613 | +
|
---|
| 1614 | +class basin(object): #{{{
|
---|
| 1615 | + '''
|
---|
| 1616 | + BASIN class definition
|
---|
| 1617 | +
|
---|
| 1618 | + Usage:
|
---|
| 1619 | + basin = basin()
|
---|
| 1620 | + '''
|
---|
| 1621 | +
|
---|
| 1622 | + def __init__(self, *args): #{{{
|
---|
| 1623 | + self.boundaries = []
|
---|
| 1624 | + self.name = ''
|
---|
| 1625 | + self.continent = ''
|
---|
| 1626 | + self.proj = epsg2proj(4326)
|
---|
| 1627 | +
|
---|
| 1628 | + self.setdefaultparameters()
|
---|
| 1629 | +
|
---|
| 1630 | + if len(args):
|
---|
| 1631 | + options = pairoptions(*args)
|
---|
| 1632 | +
|
---|
| 1633 | + #recover field values
|
---|
| 1634 | + self.boundaries = options.getfieldvalue('boundaries', [])
|
---|
| 1635 | + self.name = options.getfieldvalue('name', '')
|
---|
| 1636 | + self.continent = options.getfieldvalue('continent', '')
|
---|
| 1637 | +
|
---|
| 1638 | + # figure out projection string
|
---|
| 1639 | + if options.exist('epsg'):
|
---|
| 1640 | + if options.exist('proj'):
|
---|
| 1641 | + raise RuntimeError('Error in constructor for basin %s. Cannot supply epsg and proj at the same time!'.format(self.name))
|
---|
| 1642 | + epsg = options.getfieldvalue('epsg', '')
|
---|
| 1643 | + proj = epsg2proj(epsg)#convert to PROJ.4 format
|
---|
| 1644 | + elif options.exist('proj'):
|
---|
| 1645 | + if options.exist('epsg'):
|
---|
| 1646 | + raise RuntimeError('Error in constructor for basin {}. Cannot supply proj and epsg at the same time!'.format(self.name))
|
---|
| 1647 | + proj = options.getfieldvalue('proj', '')
|
---|
| 1648 | + else:
|
---|
| 1649 | + proj = '+proj=longlat +datum=WGS84 +no_defs'
|
---|
| 1650 | +
|
---|
| 1651 | + self.proj = proj
|
---|
| 1652 | + #}}}
|
---|
| 1653 | +
|
---|
| 1654 | + def __repr__(self): # {{{
|
---|
| 1655 | + s = ' basin parameters:\n'
|
---|
| 1656 | + s += '{}\n'.format(fielddisplay(self, 'continent', 'continent name'))
|
---|
| 1657 | + s += '{}\n'.format(fielddisplay(self, 'name', 'basin name'))
|
---|
| 1658 | + s += '{}\n'.format(fielddisplay(self, 'proj', 'basin projection string (follows PROJ.4 standard'))
|
---|
| 1659 | + s += '{}\n'.format(fielddisplay(self, 'boundaries','list of boundary objects'))
|
---|
| 1660 | + for i in range(len(self.boundaries)):
|
---|
| 1661 | + s += ' boundary #{}: {}\n'.format((i + 1), self.boundaries[i])
|
---|
| 1662 | +
|
---|
| 1663 | + return s
|
---|
| 1664 | + #}}}
|
---|
| 1665 | +
|
---|
| 1666 | + def setdefaultparameters(self): # {{{
|
---|
| 1667 | + self.name = ''
|
---|
| 1668 | + self.continent = ''
|
---|
| 1669 | + self.proj = '+proj=longlat +datum=WGS84 +no_defs' #EPSG 4326
|
---|
| 1670 | + self.boundaries = []
|
---|
| 1671 | +
|
---|
| 1672 | + return self
|
---|
| 1673 | + #}}}
|
---|
| 1674 | +
|
---|
| 1675 | + def isnameany(self, *args): #{{{
|
---|
| 1676 | + for arg in args:
|
---|
| 1677 | + if arg == self.name:
|
---|
| 1678 | + return 1
|
---|
| 1679 | + return 0
|
---|
| 1680 | + #}}}
|
---|
| 1681 | +
|
---|
| 1682 | + def iscontinentany(self, *args): #{{{
|
---|
| 1683 | + for arg in args:
|
---|
| 1684 | + if arg == self.continent:
|
---|
| 1685 | + return 1
|
---|
| 1686 | + return 0
|
---|
| 1687 | + #}}}
|
---|
| 1688 | +
|
---|
| 1689 | + def outputname(self, *args): #{{{
|
---|
| 1690 | + #recover options
|
---|
| 1691 | + options = pairoptions(*args)
|
---|
| 1692 | + extension = options.getfieldvalue('extension', 1)
|
---|
| 1693 | +
|
---|
| 1694 | + path, name, ext = fileparts(*args)
|
---|
| 1695 | + if extension:
|
---|
| 1696 | + output = '{}{}'.format(name, ext)
|
---|
| 1697 | + else:
|
---|
| 1698 | + output = name
|
---|
| 1699 | +
|
---|
| 1700 | + return output
|
---|
| 1701 | + #}}}
|
---|
| 1702 | +
|
---|
| 1703 | + def plot(self, *args): #{{{
|
---|
| 1704 | + #add option
|
---|
| 1705 | + for i in range(len(self.boundaries)):
|
---|
| 1706 | + self.boundaries[i].plot('proj', self.proj, *args)
|
---|
| 1707 | + #}}}
|
---|
| 1708 | +
|
---|
| 1709 | + def plot3d(self, *args): #{{{
|
---|
| 1710 | + #add option
|
---|
| 1711 | + for i in range(len(self.boundaries)):
|
---|
| 1712 | + self.boundaries[i].plot3d(*args)
|
---|
| 1713 | + #}}}
|
---|
| 1714 | +
|
---|
| 1715 | + def contour(self, *args): #{{{
|
---|
| 1716 | + #recover options
|
---|
| 1717 | + options = pairoptions(*args)
|
---|
| 1718 | + x = []
|
---|
| 1719 | + y = []
|
---|
| 1720 | +
|
---|
| 1721 | + #go through boundaries, recover edges and project them in the basin epsg reference frame
|
---|
| 1722 | + for i in range(len(self.boundaries)):
|
---|
| 1723 | + boundary = self.boundaries[i]
|
---|
| 1724 | + contour = boundary.edges()
|
---|
| 1725 | + contour.x, contour.y = gdaltransform(contour.x, contour.y, boundary.proj, self.proj)
|
---|
| 1726 | + x = [[x], [contour.x]]
|
---|
| 1727 | + y = [[y], [contour.y]]
|
---|
| 1728 | +
|
---|
| 1729 | + #close the contour
|
---|
| 1730 | + if x[-1] != x[0] or y[-1] != y[0]:
|
---|
| 1731 | + x.append(x[0])
|
---|
| 1732 | + y.append(y[0])
|
---|
| 1733 | +
|
---|
| 1734 | + setattr(out, 'x', x)
|
---|
| 1735 | + setattr(out, 'y', y)
|
---|
| 1736 | + setattr(out, 'nods', len(x))
|
---|
| 1737 | +
|
---|
| 1738 | + return out
|
---|
| 1739 | + #}}}
|
---|
| 1740 | +
|
---|
| 1741 | + def checkconsistency(self, *args): #{{{
|
---|
| 1742 | + #recover options
|
---|
| 1743 | + options = pairoptions(*args)
|
---|
| 1744 | +
|
---|
| 1745 | + #figure out if two boundaries are identical
|
---|
| 1746 | + for i in range(len(self.boundaries)):
|
---|
| 1747 | + namei = self.boundaries[i].shpfilename
|
---|
| 1748 | + for j in range(1, len(self.boundaries)):
|
---|
| 1749 | + namej = self.boundaries[j].shpfilename
|
---|
| 1750 | + if namei == namej:
|
---|
| 1751 | + raise RuntimeError('Basin {} has two identical boundaries named {}'.format(self.name, namei))
|
---|
| 1752 | +
|
---|
| 1753 | + #go through boundaries and check their consistency
|
---|
| 1754 | + for i in range(len(self.boundaries)):
|
---|
| 1755 | + boundary == self.boundaries[i]
|
---|
| 1756 | + boundary.checkconsistency()
|
---|
| 1757 | + #}}}
|
---|
| 1758 | +
|
---|
| 1759 | + def contourplot(self, *args): #{{{
|
---|
| 1760 | + contour = self.contour()
|
---|
| 1761 | + plot(contour.x, contour.y, 'r*-')
|
---|
| 1762 | + #}}}
|
---|
| 1763 | +
|
---|
| 1764 | + def shapefilecrop(self, *args): #{{{
|
---|
| 1765 | + #recover options
|
---|
| 1766 | + options = pairoptions(*args)
|
---|
| 1767 | + threshold = options.getfieldvalue('threshold', .65) #.65 degrees lat, long
|
---|
| 1768 | + inshapefile = options.getfieldvalue('shapefile')
|
---|
| 1769 | + outshapefile = options.getfieldvalue('outshapefile', '')
|
---|
| 1770 | +
|
---|
| 1771 | + if options.exist('epsgshapefile') and options.exist('projshapefile'):
|
---|
| 1772 | + raise RuntimeError('Basin shapefilecrop error messgae: cannot specify epsgshapefile and projshapefile at the same time')
|
---|
| 1773 | +
|
---|
| 1774 | + if options.exist('epsgshapefile'):
|
---|
| 1775 | + projshapefile = epsg2proj(options.getfieldvalue('epsgshapefile'))
|
---|
| 1776 | + elif options.exist('projshapefile'):
|
---|
| 1777 | + projshapefile = options.getfieldvalue('projshapefile')
|
---|
| 1778 | + else:
|
---|
| 1779 | + raise RuntimeError('Basin shapefilecrop error message: epsgshapefile or projshapefile should be specified')
|
---|
| 1780 | +
|
---|
| 1781 | + #create list of contours that have critical length > threshold (in lat, long)
|
---|
| 1782 | + contours = shpread(inshapefile)
|
---|
| 1783 | + llist = []
|
---|
| 1784 | + for i in range(len(contours)):
|
---|
| 1785 | + contour = contours[i]
|
---|
| 1786 | + carea = polyarea(contour.x, contour.y)
|
---|
| 1787 | + clength = math.sqrt(carea)
|
---|
| 1788 | + if clength < threshold:
|
---|
| 1789 | + llist = np.concatenate(llist, i)
|
---|
| 1790 | + setattr(contours, llist, [])
|
---|
| 1791 | +
|
---|
| 1792 | + #project onto reference frame
|
---|
| 1793 | + for i in range(len(contours)):
|
---|
| 1794 | + h = contours[i]
|
---|
| 1795 | + h.x, h.y = gdaltransform(h.x, h.y, projshapefile, self.proj)
|
---|
| 1796 | + contours[i].x = h.x
|
---|
| 1797 | + contours[i].y = h.y
|
---|
| 1798 | +
|
---|
| 1799 | + #only keep the contours that are inside the basin (take centroids)
|
---|
| 1800 | + ba = self.contour()
|
---|
| 1801 | + flags = np.zeros(len(contours))
|
---|
| 1802 | + for i in range(len(contours))
|
---|
| 1803 | + h = contours[i]
|
---|
| 1804 | + isin = inpolygon(h.x, h.y, ba.x, ba.y)
|
---|
| 1805 | + if len(np.where(isin == 0, isin, isin)):
|
---|
| 1806 | + flags[i] = 1
|
---|
| 1807 | + pos = flags.nonzero()
|
---|
| 1808 | + contours[pos] = []
|
---|
| 1809 | +
|
---|
| 1810 | + #Two options
|
---|
| 1811 | + if outputshapefile == '':
|
---|
| 1812 | + output = contours
|
---|
| 1813 | + else:
|
---|
| 1814 | + shpwrite(contours, outputshapefile)
|
---|
| 1815 | + #}}}
|
---|
| 1816 | +#}}}
|
---|
| 1817 | Index: ../trunk-jpl/src/m/classes/boundary.m
|
---|
| 1818 | ===================================================================
|
---|
| 1819 | --- ../trunk-jpl/src/m/classes/boundary.m (revision 25064)
|
---|
| 1820 | +++ ../trunk-jpl/src/m/classes/boundary.m (revision 25065)
|
---|
| 1821 | @@ -19,35 +19,32 @@
|
---|
| 1822 | end
|
---|
| 1823 | methods
|
---|
| 1824 | function self = boundary(varargin) % {{{
|
---|
| 1825 | - switch nargin
|
---|
| 1826 | - case 0
|
---|
| 1827 | - self=setdefaultparameters(self);
|
---|
| 1828 | - otherwise
|
---|
| 1829 | - self=setdefaultparameters(self);
|
---|
| 1830 | - options=pairoptions(varargin{:});
|
---|
| 1831 | -
|
---|
| 1832 | - %recover field values:
|
---|
| 1833 | - self.shppath=getfieldvalue(options,'shppath','');
|
---|
| 1834 | - self.shpfilename=getfieldvalue(options,'shpfilename','');
|
---|
| 1835 | - self.orientation=getfieldvalue(options,'orientation','normal');
|
---|
| 1836 | + self=setdefaultparameters(self);
|
---|
| 1837 |
|
---|
| 1838 | - %figure out projection string:
|
---|
| 1839 | + if nargin > 0,
|
---|
| 1840 | + options=pairoptions(varargin{:});
|
---|
| 1841 | +
|
---|
| 1842 | + %recover field values:
|
---|
| 1843 | + self.shppath=getfieldvalue(options,'shppath','');
|
---|
| 1844 | + self.shpfilename=getfieldvalue(options,'shpfilename','');
|
---|
| 1845 | + self.orientation=getfieldvalue(options,'orientation','normal');
|
---|
| 1846 | +
|
---|
| 1847 | + %figure out projection string:
|
---|
| 1848 | + if exist(options,'epsg'),
|
---|
| 1849 | + if exist(options,'proj'),
|
---|
| 1850 | + error(['Error in constructor for boundary ' self.shppath '. Cannot supply epsg and proj at the same time!']);
|
---|
| 1851 | + end
|
---|
| 1852 | + epsg=getfieldvalue(options,'epsg');
|
---|
| 1853 | + proj=epsg2proj(epsg); % convert to PROJ.4 format
|
---|
| 1854 | + elseif exist(options,'proj'),
|
---|
| 1855 | if exist(options,'epsg'),
|
---|
| 1856 | - if exist(options,'proj'),
|
---|
| 1857 | - error(['Error in constructor for boundary ' self.shppath '.Cannot supply epsg and proj at the same time!']);
|
---|
| 1858 | - end
|
---|
| 1859 | - epsg=getfieldvalue(options,'epsg');
|
---|
| 1860 | - %convert into proj4:
|
---|
| 1861 | - proj=epsg2proj(epsg);
|
---|
| 1862 | - elseif exist(options,'proj'),
|
---|
| 1863 | - if exist(options,'epsg'),
|
---|
| 1864 | - error(['Error in constructor for boundary ' self.shppath '.Cannot supply epsg and proj at the same time!']);
|
---|
| 1865 | - end
|
---|
| 1866 | - proj=getfieldvalue(options,'proj');
|
---|
| 1867 | - else
|
---|
| 1868 | - proj= '+proj=longlat +datum=WGS84 +no_defs';
|
---|
| 1869 | + error(['Error in constructor for boundary ' self.shppath '. Cannot supply proj and epsg at the same time!']);
|
---|
| 1870 | end
|
---|
| 1871 | - self.proj=proj;
|
---|
| 1872 | + proj=getfieldvalue(options,'proj');
|
---|
| 1873 | + else
|
---|
| 1874 | + proj= '+proj=longlat +datum=WGS84 +no_defs';
|
---|
| 1875 | + end
|
---|
| 1876 | + self.proj=proj;
|
---|
| 1877 | end
|
---|
| 1878 | end % }}}
|
---|
| 1879 | function self = setdefaultparameters(self) % {{{
|
---|
| 1880 | @@ -54,7 +51,7 @@
|
---|
| 1881 | self.shppath='';
|
---|
| 1882 | self.shpfilename='';
|
---|
| 1883 | self.orientation='normal';
|
---|
| 1884 | - self.proj='+proj=longlat +datum=WGS84 +no_defs '; %EPSG 4326
|
---|
| 1885 | + self.proj='+proj=longlat +datum=WGS84 +no_defs'; %EPSG 4326
|
---|
| 1886 | end % }}}
|
---|
| 1887 | function disp(self) % {{{
|
---|
| 1888 | disp(sprintf(' boundary parameters:'));
|
---|
| 1889 | @@ -69,19 +66,19 @@
|
---|
| 1890 | output=self.shpfilename;
|
---|
| 1891 | end % }}}
|
---|
| 1892 | function output=edges(self) % {{{
|
---|
| 1893 | -
|
---|
| 1894 | - %read domain:
|
---|
| 1895 | - [path,name,ext]=fileparts(self.shpfilename);
|
---|
| 1896 | - if ~strcmpi(ext,'shp'),
|
---|
| 1897 | - ext='shp';
|
---|
| 1898 | - end
|
---|
| 1899 | - output=shpread([self.shppath '/' name '.' ext]);
|
---|
| 1900 |
|
---|
| 1901 | - %do we reverse?
|
---|
| 1902 | - if strcmpi(self.orientation,'reverse'),
|
---|
| 1903 | - output.x=flipud(output.x);
|
---|
| 1904 | - output.y=flipud(output.y);
|
---|
| 1905 | - end
|
---|
| 1906 | + %read domain:
|
---|
| 1907 | + [path,name,ext]=fileparts(self.shpfilename);
|
---|
| 1908 | + if ~strcmpi(ext,'shp'),
|
---|
| 1909 | + ext='shp';
|
---|
| 1910 | + end
|
---|
| 1911 | + output=shpread([self.shppath '/' name '.' ext]);
|
---|
| 1912 | +
|
---|
| 1913 | + %do we reverse?
|
---|
| 1914 | + if strcmpi(self.orientation,'reverse'),
|
---|
| 1915 | + output.x=flipud(output.x);
|
---|
| 1916 | + output.y=flipud(output.y);
|
---|
| 1917 | + end
|
---|
| 1918 | end % }}}
|
---|
| 1919 | function plot(self,varargin) % {{{
|
---|
| 1920 | %recover options
|
---|
| 1921 | @@ -100,10 +97,9 @@
|
---|
| 1922 | fontsize=getfieldvalue(options,'fontsize',10);
|
---|
| 1923 | label=getfieldvalue(options,'label','on');
|
---|
| 1924 |
|
---|
| 1925 | - if (exist(options,'epsg') & exist(options,'proj')),
|
---|
| 1926 | - error('Boundary plot error message: cannot specify epsg and proj at the same time for plot projection');
|
---|
| 1927 | - end
|
---|
| 1928 | - if exist(options,'epsg'),
|
---|
| 1929 | + if (exist(options,'epsg'),
|
---|
| 1930 | + if exist(options,'proj')),
|
---|
| 1931 | + error('Boundary plot error message: cannot specify epsg and proj at the same time for plot projection');
|
---|
| 1932 | proj=epsg2proj(getfieldvalue(options,'epsg'));
|
---|
| 1933 | elseif exist(options,'proj'),
|
---|
| 1934 | proj=getfieldvalue(options,'proj');
|
---|
| 1935 | @@ -118,7 +114,7 @@
|
---|
| 1936 | end
|
---|
| 1937 | domain=shpread([self.shppath '/' name '.' ext]);
|
---|
| 1938 |
|
---|
| 1939 | - %convert boundary to another reference frame: {{{
|
---|
| 1940 | + %convert boundary to another reference frame: {{{
|
---|
| 1941 | for i=1:length(domain),
|
---|
| 1942 | try,
|
---|
| 1943 | [x,y] = gdaltransform(domain(i).x,domain(i).y,self.proj,proj);
|
---|
| 1944 | @@ -168,7 +164,7 @@
|
---|
| 1945 | dmax=max(distance);
|
---|
| 1946 | isidentical=find(distance<dmax*tolerance);
|
---|
| 1947 | if ~isempty(isidentical),
|
---|
| 1948 | - error(['boundary ' shpfilename ' has two vertices extremely close to one another']);
|
---|
| 1949 | + error(['boundary ' shpfilename ' has two vertices extremely close to one another']);
|
---|
| 1950 | end
|
---|
| 1951 | end
|
---|
| 1952 | end % }}}
|
---|
| 1953 | @@ -189,6 +185,16 @@
|
---|
| 1954 | fontsize=getfieldvalue(options,'fontsize',10);
|
---|
| 1955 | label=getfieldvalue(options,'label','on');
|
---|
| 1956 |
|
---|
| 1957 | + if (exist(options,'epsg'),
|
---|
| 1958 | + if exist(options,'proj')),
|
---|
| 1959 | + error('Boundary plot error message: cannot specify epsg and proj at the same time for plot projection');
|
---|
| 1960 | + proj=epsg2proj(getfieldvalue(options,'epsg'));
|
---|
| 1961 | + elseif exist(options,'proj'),
|
---|
| 1962 | + proj=getfieldvalue(options,'proj');
|
---|
| 1963 | + else
|
---|
| 1964 | + proj=epsg2proj(4326);
|
---|
| 1965 | + end
|
---|
| 1966 | +
|
---|
| 1967 | %read domain:
|
---|
| 1968 | [path,name,ext]=fileparts(self.shpfilename);
|
---|
| 1969 | if ~strcmpi(ext,'shp'),
|
---|
| 1970 | Index: ../trunk-jpl/src/m/plot/plotmodel.py
|
---|
| 1971 | ===================================================================
|
---|
| 1972 | --- ../trunk-jpl/src/m/plot/plotmodel.py (revision 25064)
|
---|
| 1973 | +++ ../trunk-jpl/src/m/plot/plotmodel.py (revision 25065)
|
---|
| 1974 | @@ -1,6 +1,3 @@
|
---|
| 1975 | -import numpy as np
|
---|
| 1976 | -from plotoptions import plotoptions
|
---|
| 1977 | -from plot_manager import plot_manager
|
---|
| 1978 | from math import ceil, sqrt
|
---|
| 1979 |
|
---|
| 1980 | try:
|
---|
| 1981 | @@ -8,23 +5,37 @@
|
---|
| 1982 | from mpl_toolkits.axes_grid1 import ImageGrid
|
---|
| 1983 | except ImportError:
|
---|
| 1984 | print("could not import pylab, matplotlib has not been installed, no plotting capabilities enabled")
|
---|
| 1985 | +import numpy as np
|
---|
| 1986 |
|
---|
| 1987 | +from plot_manager import plot_manager
|
---|
| 1988 | +from plotoptions import plotoptions
|
---|
| 1989 |
|
---|
| 1990 | +
|
---|
| 1991 | def plotmodel(md, *args):
|
---|
| 1992 | - ''' at command prompt, type 'plotdoc()' for additional documentation
|
---|
| 1993 | '''
|
---|
| 1994 | + PLOTMODEL - At command prompt, type 'plotdoc()' for additional
|
---|
| 1995 | + documentation.
|
---|
| 1996 |
|
---|
| 1997 | + TODO:
|
---|
| 1998 | + - Fix 'plotdoc()', as it is not currently working.
|
---|
| 1999 | + '''
|
---|
| 2000 | +
|
---|
| 2001 | #First process options
|
---|
| 2002 | options = plotoptions(*args)
|
---|
| 2003 | - #get number of subplots
|
---|
| 2004 | - subplotwidth = ceil(sqrt(options.numberofplots))
|
---|
| 2005 | +
|
---|
| 2006 | #Get figure number and number of plots
|
---|
| 2007 | figurenumber = options.figurenumber
|
---|
| 2008 | numberofplots = options.numberofplots
|
---|
| 2009 |
|
---|
| 2010 | - #get hold
|
---|
| 2011 | - hold = options.list[0].getfieldvalue('hold', False)
|
---|
| 2012 | + #get number of subplots
|
---|
| 2013 | + subplotwidth = ceil(sqrt(numberofplots))
|
---|
| 2014 |
|
---|
| 2015 | + # TODO: Check that commenting this out is correct; we do not need a hold
|
---|
| 2016 | + # under matplotlib, right?
|
---|
| 2017 | + #
|
---|
| 2018 | + # #get hold
|
---|
| 2019 | + # hold = options.list[0].getfieldvalue('hold', False)
|
---|
| 2020 | +
|
---|
| 2021 | #if nrows and ncols specified, then bypass
|
---|
| 2022 | if options.list[0].exist('nrows'):
|
---|
| 2023 | nrows = options.list[0].getfieldvalue('nrows')
|
---|
| 2024 | @@ -43,14 +54,18 @@
|
---|
| 2025 | nrows = int(nrows)
|
---|
| 2026 |
|
---|
| 2027 | #check that nrows and ncols were given at the same time!
|
---|
| 2028 | - if not nr == nc:
|
---|
| 2029 | - raise Exception('error: nrows and ncols need to be specified together, or not at all')
|
---|
| 2030 | + if nr != nc:
|
---|
| 2031 | + raise Exception('plotmodel error message: nrows and ncols need to be specified together, or not at all')
|
---|
| 2032 |
|
---|
| 2033 | - #Go through plots
|
---|
| 2034 | + # Go through plots
|
---|
| 2035 | + #
|
---|
| 2036 | + # NOTE: The following is where Python + matplolib differs substantially in
|
---|
| 2037 | + # implementation and inteface from MATLAB.
|
---|
| 2038 | + #
|
---|
| 2039 | + # Sources:
|
---|
| 2040 | + # - https://matplotlib.org/api/_as_gen/mpl_toolkits.axes_grid1.axes_grid.ImageGrid.html
|
---|
| 2041 | + #
|
---|
| 2042 | if numberofplots:
|
---|
| 2043 | - #if plt.fignum_exists(figurenumber):
|
---|
| 2044 | - # plt.cla()
|
---|
| 2045 | -
|
---|
| 2046 | #if figsize specified
|
---|
| 2047 | if options.list[0].exist('figsize'):
|
---|
| 2048 | figsize = options.list[0].getfieldvalue('figsize')
|
---|
| 2049 | @@ -62,36 +77,64 @@
|
---|
| 2050 | backgroundcolor = options.list[0].getfieldvalue('backgroundcolor', (0.7, 0.7, 0.7))
|
---|
| 2051 | fig.set_facecolor(backgroundcolor)
|
---|
| 2052 |
|
---|
| 2053 | - translator = {'on': 'each',
|
---|
| 2054 | - 'off': 'None',
|
---|
| 2055 | - 'one': 'single'}
|
---|
| 2056 | - # options needed to define plot grid
|
---|
| 2057 | + # options needed to define plot grid
|
---|
| 2058 | plotnum = options.numberofplots
|
---|
| 2059 | if plotnum == 1:
|
---|
| 2060 | plotnum = None
|
---|
| 2061 | - direction = options.list[0].getfieldvalue('direction', 'row') # row, column
|
---|
| 2062 | - axes_pad = options.list[0].getfieldvalue('axes_pad', 0.25)
|
---|
| 2063 | - add_all = options.list[0].getfieldvalue('add_all', True) # True, False
|
---|
| 2064 | - share_all = options.list[0].getfieldvalue('share_all', True) # True, False
|
---|
| 2065 | - label_mode = options.list[0].getfieldvalue('label_mode', 'L') # 1, L, all
|
---|
| 2066 | +
|
---|
| 2067 | + # NOTE: The inline comments for each of the following parameters are
|
---|
| 2068 | + # taken from https://matplotlib.org/api/_as_gen/mpl_toolkits.axes_grid1.axes_grid.ImageGrid.html
|
---|
| 2069 | + #
|
---|
| 2070 | + direction = options.list[0].getfieldvalue('direction', 'row') # {"row", "column"}, default: "row"
|
---|
| 2071 | + axes_pad = options.list[0].getfieldvalue('axes_pad', 0.25) # float or (float, float), default : 0.02; Padding or (horizonal padding, vertical padding) between axes, in inches
|
---|
| 2072 | + add_all = options.list[0].getfieldvalue('add_all', True) # bool, default: True
|
---|
| 2073 | + share_all = options.list[0].getfieldvalue('share_all', True) # bool, default: False
|
---|
| 2074 | + label_mode = options.list[0].getfieldvalue('label_mode', 'L') # {"L", "1", "all"}, default: "L"; Determines which axes will get tick labels: "L": All axes on the left column get vertical tick labels; all axes on the bottom row get horizontal tick labels;. "1": Only the bottom left axes is labelled. "all": all axes are labelled.
|
---|
| 2075 | +
|
---|
| 2076 | + # Translate MATLAB colorbar mode to matplotlib
|
---|
| 2077 | + #
|
---|
| 2078 | + # TODO:
|
---|
| 2079 | + # - Add 'edge' option (research if there is a corresponding option in
|
---|
| 2080 | + # MATLAB)?
|
---|
| 2081 | + #
|
---|
| 2082 | colorbar = options.list[0].getfieldvalue('colorbar', 'on') # on, off (single)
|
---|
| 2083 | - cbar_mode = translator[colorbar]
|
---|
| 2084 | - cbar_location = options.list[0].getfieldvalue('colorbarpos', 'right') # right, top
|
---|
| 2085 | - cbar_size = options.list[0].getfieldvalue('colorbarsize', '5%')
|
---|
| 2086 | - cbar_pad = options.list[0].getfieldvalue('colorbarpad', 0.025) # None or %
|
---|
| 2087 |
|
---|
| 2088 | - axgrid = ImageGrid(fig, 111,
|
---|
| 2089 | - nrows_ncols=(nrows, ncols),
|
---|
| 2090 | - direction=direction,
|
---|
| 2091 | - axes_pad=axes_pad,
|
---|
| 2092 | - add_all=add_all,
|
---|
| 2093 | - share_all=share_all,
|
---|
| 2094 | - label_mode=label_mode,
|
---|
| 2095 | - cbar_mode=cbar_mode,
|
---|
| 2096 | - cbar_location=cbar_location,
|
---|
| 2097 | - cbar_size=cbar_size,
|
---|
| 2098 | - cbar_pad=cbar_pad)
|
---|
| 2099 | + if colorbar == 'on':
|
---|
| 2100 | + colorbar = 'each'
|
---|
| 2101 | + elif colorbar == 'one':
|
---|
| 2102 | + colorbar = 'single'
|
---|
| 2103 | + elif colorbar == 'off':
|
---|
| 2104 | + colorbar = 'None'
|
---|
| 2105 | + else:
|
---|
| 2106 | + raise RuntimeError('plotmodel error: colorbar mode \'{}\' is not a valid option'.format(colorbar))
|
---|
| 2107 |
|
---|
| 2108 | + cbar_mode = colorbar # {"each", "single", "edge", None }, default: None
|
---|
| 2109 | + cbar_location = options.list[0].getfieldvalue('colorbarpos', 'right') # {"left", "right", "bottom", "top"}, default: "right"
|
---|
| 2110 | + cbar_pad = options.list[0].getfieldvalue('colorbarpad', 0.025) # float, default: None
|
---|
| 2111 | + cbar_size = options.list[0].getfieldvalue('colorbarsize', '5%') # size specification (see Size.from_any), default: "5%"
|
---|
| 2112 | +
|
---|
| 2113 | + # NOTE: Second parameter is:
|
---|
| 2114 | + #
|
---|
| 2115 | + # rect(float, float, float, float) or int
|
---|
| 2116 | + #
|
---|
| 2117 | + # The axes position, as a (left, bottom, width, height) tuple or as a
|
---|
| 2118 | + # three-digit subplot position code (e.g., "121").
|
---|
| 2119 | + #
|
---|
| 2120 | + axgrid = ImageGrid(
|
---|
| 2121 | + fig,
|
---|
| 2122 | + 111,
|
---|
| 2123 | + nrows_ncols=(nrows, ncols),
|
---|
| 2124 | + direction=direction,
|
---|
| 2125 | + axes_pad=axes_pad,
|
---|
| 2126 | + add_all=add_all,
|
---|
| 2127 | + share_all=share_all,
|
---|
| 2128 | + label_mode=label_mode,
|
---|
| 2129 | + cbar_mode=cbar_mode,
|
---|
| 2130 | + cbar_location=cbar_location,
|
---|
| 2131 | + cbar_size=cbar_size,
|
---|
| 2132 | + cbar_pad=cbar_pad
|
---|
| 2133 | + )
|
---|
| 2134 | +
|
---|
| 2135 | if cbar_mode == 'None':
|
---|
| 2136 | for ax in axgrid.cbar_axes:
|
---|
| 2137 | fig._axstack.remove(ax)
|
---|
| 2138 | Index: ../trunk-jpl/src/m/plot/plot_unit.py
|
---|
| 2139 | ===================================================================
|
---|
| 2140 | --- ../trunk-jpl/src/m/plot/plot_unit.py (revision 25064)
|
---|
| 2141 | +++ ../trunk-jpl/src/m/plot/plot_unit.py (revision 25065)
|
---|
| 2142 | @@ -1,6 +1,4 @@
|
---|
| 2143 | from cmaptools import getcolormap, truncate_colormap
|
---|
| 2144 | -from plot_quiver import plot_quiver
|
---|
| 2145 | -import numpy as np
|
---|
| 2146 | try:
|
---|
| 2147 | import matplotlib as mpl
|
---|
| 2148 | import matplotlib.pyplot as plt
|
---|
| 2149 | @@ -9,17 +7,20 @@
|
---|
| 2150 | from mpl_toolkits.mplot3d.art3d import Poly3DCollection
|
---|
| 2151 | except ImportError:
|
---|
| 2152 | print("could not import pylab, matplotlib has not been installed, no plotting capabilities enabled")
|
---|
| 2153 | +import numpy as np
|
---|
| 2154 |
|
---|
| 2155 | +from plot_quiver import plot_quiver
|
---|
| 2156 |
|
---|
| 2157 | +
|
---|
| 2158 | def plot_unit(x, y, z, elements, data, is2d, isplanet, datatype, options, fig, axgrid, gridindex):
|
---|
| 2159 | - """
|
---|
| 2160 | + '''
|
---|
| 2161 | PLOT_UNIT - unit plot, display data
|
---|
| 2162 |
|
---|
| 2163 | Usage:
|
---|
| 2164 | - plot_unit(x, y, z, elements, data, is2d, isplanet, datatype, options)
|
---|
| 2165 | + plot_unit(x, y, z, elements, data, is2d, isplanet, datatype, options)
|
---|
| 2166 |
|
---|
| 2167 | See also: PLOTMODEL, PLOT_MANAGER
|
---|
| 2168 | - """
|
---|
| 2169 | + '''
|
---|
| 2170 | #if we are plotting 3d replace the current axis
|
---|
| 2171 | if not is2d:
|
---|
| 2172 | axgrid[gridindex].axis('off')
|
---|
| 2173 | @@ -227,21 +228,16 @@
|
---|
| 2174 | else:
|
---|
| 2175 | raise ValueError('plot_unit error: 3D node plot not supported yet')
|
---|
| 2176 | return
|
---|
| 2177 | -
|
---|
| 2178 | # }}}
|
---|
| 2179 | # {{{ plotting P1 Patch (TODO)
|
---|
| 2180 | -
|
---|
| 2181 | elif datatype == 4:
|
---|
| 2182 | print('plot_unit message: P1 patch plot not implemented yet')
|
---|
| 2183 | return
|
---|
| 2184 | -
|
---|
| 2185 | # }}}
|
---|
| 2186 | # {{{ plotting P0 Patch (TODO)
|
---|
| 2187 | -
|
---|
| 2188 | elif datatype == 5:
|
---|
| 2189 | print('plot_unit message: P0 patch plot not implemented yet')
|
---|
| 2190 | return
|
---|
| 2191 | -
|
---|
| 2192 | # }}}
|
---|
| 2193 | else:
|
---|
| 2194 | raise ValueError('datatype = %d not supported' % datatype)
|
---|
| 2195 | Index: ../trunk-jpl/src/m/plot/applyoptions.py
|
---|
| 2196 | ===================================================================
|
---|
| 2197 | --- ../trunk-jpl/src/m/plot/applyoptions.py (revision 25064)
|
---|
| 2198 | +++ ../trunk-jpl/src/m/plot/applyoptions.py (revision 25065)
|
---|
| 2199 | @@ -1,17 +1,17 @@
|
---|
| 2200 | -import numpy as np
|
---|
| 2201 | from cmaptools import getcolormap
|
---|
| 2202 | -from plot_contour import plot_contour
|
---|
| 2203 | -from plot_streamlines import plot_streamlines
|
---|
| 2204 | -from expdisp import expdisp
|
---|
| 2205 | -
|
---|
| 2206 | try:
|
---|
| 2207 | - from matplotlib.ticker import MaxNLocator
|
---|
| 2208 | import matplotlib as mpl
|
---|
| 2209 | import matplotlib.pyplot as plt
|
---|
| 2210 | + from matplotlib.ticker import MaxNLocator
|
---|
| 2211 | except ImportError:
|
---|
| 2212 | print("could not import pylab, matplotlib has not been installed, no plotting capabilities enabled")
|
---|
| 2213 | +import numpy as np
|
---|
| 2214 |
|
---|
| 2215 | +from expdisp import expdisp
|
---|
| 2216 | +from plot_contour import plot_contour
|
---|
| 2217 | +from plot_streamlines import plot_streamlines
|
---|
| 2218 |
|
---|
| 2219 | +
|
---|
| 2220 | def applyoptions(md, data, options, fig, axgrid, gridindex):
|
---|
| 2221 | '''
|
---|
| 2222 | APPLYOPTIONS - apply options to current plot
|
---|
| 2223 | @@ -19,10 +19,10 @@
|
---|
| 2224 | 'plotobj' is the object returned by the specific plot call used to
|
---|
| 2225 | render the data. This object is used for adding a colorbar.
|
---|
| 2226 |
|
---|
| 2227 | - Usage:
|
---|
| 2228 | - applyoptions(md, data, options)
|
---|
| 2229 | + Usage:
|
---|
| 2230 | + applyoptions(md, data, options)
|
---|
| 2231 |
|
---|
| 2232 | - See also: PLOTMODEL, PARSE_OPTIONS
|
---|
| 2233 | + See also: PLOTMODEL, PARSE_OPTIONS
|
---|
| 2234 | '''
|
---|
| 2235 |
|
---|
| 2236 | # get handle to current figure and axes instance
|
---|
| 2237 | @@ -33,9 +33,11 @@
|
---|
| 2238 | fontsize = options.getfieldvalue('fontsize', 8)
|
---|
| 2239 | fontweight = options.getfieldvalue('fontweight', 'normal')
|
---|
| 2240 | fontfamily = options.getfieldvalue('fontfamily', 'sans - serif')
|
---|
| 2241 | - font = {'fontsize': fontsize,
|
---|
| 2242 | - 'fontweight': fontweight,
|
---|
| 2243 | - 'family': fontfamily}
|
---|
| 2244 | + font = {
|
---|
| 2245 | + 'fontsize': fontsize,
|
---|
| 2246 | + 'fontweight': fontweight,
|
---|
| 2247 | + 'family': fontfamily
|
---|
| 2248 | + }
|
---|
| 2249 | # }}}
|
---|
| 2250 | # {{{ title
|
---|
| 2251 | if options.exist('title'):
|
---|