Map representing different coordinate systems. Coordinate definitions: * axes-coordinates goes from 0 to 1 in the domain. * data-coordinates are specified by the input x-y coordinates. * grid-coordinates goes from 0 to N and 0 to M for an N x M grid, where N and M match
| 304 | # ======================== |
| 305 | |
| 306 | class DomainMap: |
| 307 | """ |
| 308 | Map representing different coordinate systems. |
| 309 | |
| 310 | Coordinate definitions: |
| 311 | |
| 312 | * axes-coordinates goes from 0 to 1 in the domain. |
| 313 | * data-coordinates are specified by the input x-y coordinates. |
| 314 | * grid-coordinates goes from 0 to N and 0 to M for an N x M grid, |
| 315 | where N and M match the shape of the input data. |
| 316 | * mask-coordinates goes from 0 to N and 0 to M for an N x M mask, |
| 317 | where N and M are user-specified to control the density of streamlines. |
| 318 | |
| 319 | This class also has methods for adding trajectories to the StreamMask. |
| 320 | Before adding a trajectory, run `start_trajectory` to keep track of regions |
| 321 | crossed by a given trajectory. Later, if you decide the trajectory is bad |
| 322 | (e.g., if the trajectory is very short) just call `undo_trajectory`. |
| 323 | """ |
| 324 | |
| 325 | def __init__(self, grid, mask): |
| 326 | self.grid = grid |
| 327 | self.mask = mask |
| 328 | # Constants for conversion between grid- and mask-coordinates |
| 329 | self.x_grid2mask = (mask.nx - 1) / (grid.nx - 1) |
| 330 | self.y_grid2mask = (mask.ny - 1) / (grid.ny - 1) |
| 331 | |
| 332 | self.x_mask2grid = 1. / self.x_grid2mask |
| 333 | self.y_mask2grid = 1. / self.y_grid2mask |
| 334 | |
| 335 | self.x_data2grid = 1. / grid.dx |
| 336 | self.y_data2grid = 1. / grid.dy |
| 337 | |
| 338 | def grid2mask(self, xi, yi): |
| 339 | """Return nearest space in mask-coords from given grid-coords.""" |
| 340 | return round(xi * self.x_grid2mask), round(yi * self.y_grid2mask) |
| 341 | |
| 342 | def mask2grid(self, xm, ym): |
| 343 | return xm * self.x_mask2grid, ym * self.y_mask2grid |
| 344 | |
| 345 | def data2grid(self, xd, yd): |
| 346 | return xd * self.x_data2grid, yd * self.y_data2grid |
| 347 | |
| 348 | def grid2data(self, xg, yg): |
| 349 | return xg / self.x_data2grid, yg / self.y_data2grid |
| 350 | |
| 351 | def start_trajectory(self, xg, yg, broken_streamlines=True): |
| 352 | xm, ym = self.grid2mask(xg, yg) |
| 353 | self.mask._start_trajectory(xm, ym, broken_streamlines) |
| 354 | |
| 355 | def reset_start_point(self, xg, yg): |
| 356 | xm, ym = self.grid2mask(xg, yg) |
| 357 | self.mask._current_xy = (xm, ym) |
| 358 | |
| 359 | def update_trajectory(self, xg, yg, broken_streamlines=True): |
| 360 | if not self.grid.within_grid(xg, yg): |
| 361 | raise InvalidIndexError |
| 362 | xm, ym = self.grid2mask(xg, yg) |
| 363 | self.mask._update_trajectory(xm, ym, broken_streamlines) |
no outgoing calls
no test coverage detected
searching dependent graphs…