MegaPlat

Use this class to plat land across any number of townships, with all townships appearing on the same page.

The three methods for adding lands to the MegaPlat are:

  • .add_description(), for adding the full text of a land description.

  • .add_tract(), for adding a pytrs.Tract (already parsed).

  • .add_tracts(), for adding multiple pytrs.Tract objects (already parsed), such as pytrs.PLSSDesc or pytrs.TractList objects, which contain tracts.

See LotDefiner for how to work with the .lot_definer attribute.

See Settings for how to work with the .settings attribute.

See this discussion on working with multiple layers for using multiple colors for different tracts.

Example Image

(Resized from original output. Click to see full size.)

../_images/megaplat_153n96w-154n97w.png

Example Code

This results in the image above.

import pytrs
import pytrsplat

# Choose a settings preset.
mp_preset = pytrsplat.Settings.preset('megaplat_default')
# Adjust settings as desired.
mp_preset.set_font('header', typeface='Sans-Serif (Bold)', size=80)

megaplat = pytrsplat.MegaPlat(settings=mp_preset)
# If we've written lot definitions to .csv, we load them here.
megaplat.lot_definer.read_csv('some_lot_definitions.csv')
# Otherwise / additionally, we can assume 'default' lots.
megaplat.lot_definer.allow_defaults = True
megaplat.lot_definer.standard_lot_size = 40

# Add lands with `.add_description(), `.add_tract()`, or `.add_tracts()`.

land_desc = """T154N-R97W
Sec 14: NE/4
T153N-R96W
Sec 1: Lots 1 - 3
Sec 18: ALL"""
# `config` gets passed to pytrs for parsing.
megaplat.add_description(
    land_desc,
    config='n,w'    # Optional, control parsing of description.
)

tract = pytrs.Tract(
    desc='SW/4',
    trs='154n97w15',
    parse_qq=True,  # parse_qq=True is REQUIRED
    config='n,w'    # Optional, control parsing of description.
)
megaplat.add_tract(tract)

plss_desc = pytrs.PLSSDesc(
    'T154N-R97W Sec 16: ALL',
    parse_qq=True,  # parse_qq=True is REQUIRED
    config='n,w'    # Optional, control parsing of description.
)
megaplat.add_tracts(plss_desc)

# Executing the queue will fill in the plat.
megaplat.execute_queue()

# Save to PNG.
megaplat.output(fp=r'some\path\megaplat 153n96w-154n97w.png')
# or to PDF (or nearly any other image format)
megaplat.output(fp=r'some\path\megaplat 153n96w-154n97w.pdf')
# or as PNG image inside a zip file.
megaplat.output(fp=r'some\path\megaplat 153n96w-154n97w.zip', image_format='png')

Methods and Attributes

class pytrsplat.MegaPlat(settings: Settings = None, lot_definer: LotDefiner = None, max_dim: tuple[int, int] = None)

A dynamic plat showing multiple townships on the same page.

Does not allow for footers, and ‘headers’ are instead written at the center of each township. Consider using a .headerfont_rgba in the settings that is faint, to avoid obfuscating section lines, etc.

Warning

The dimensions of a MegaPlat output are determined by the number and spread of the townships in the tracts added to the queue. The resulting images can probably be extremely large. As a safeguard, specify max_dim=(int, int) as a limit to the dimensions you are willing to generate. If either of those dimensions is violated, it will raise a RuntimeError.

Note

The size of each component plat (one for each township) is controlled by .sec_length_px. And .body_marg_top_y serves as the margins on all four sides of the resulting group of plats.

Note

This will not allow Townships in the queue to be both North and South (i.e., '154n' and '27s' cannot coexist in the queue). Similarly, Ranges may not be both East and West ('97w' and '58e' cannot coexist). If either condition is violated, a ValueError will be raised.

__init__(settings: Settings = None, lot_definer: LotDefiner = None, max_dim: tuple[int, int] = None)
Parameters:
  • settings – The Settings object to control the behavior and appearance of this plat.

  • lot_definer – A LotDefiner object to use for defining lots in tracts that are added to the queue. (Can also be modified or replaced in the .lot_definer attribute later.)

  • max_dim – (Optional) Specify the largest dimensions that may be generated. If exceeded, a RuntimeError will be raised prior to plat generation.

add_description(txt: str, config: str = None, layer: str = None) TractList

Parse the land description and add the resulting tracts to the plat group. If one or more Twp/Rge’s are newly identified, plats will be created as needed.

Parameters:
  • txt – The land description.

  • config – The config parameters for parsing, to be passed through to the pytrs library. (See pyTRS documentation for details.)

  • layer – Name of the layer to add this description to.

Returns:

A pytrs.TractList containing the tracts in which the parser could not identify any lots or aliquots.

add_tract(tract: Tract, layer: str = None)

Add a tract to the queue.

Note

The tract must already be parsed for lots/QQs. (See pyTRS documentation for details.)

Parameters:
  • tractpytrs.Tract to add to the queue.

  • layer – Name of the layer to add these tracts to.

add_tracts(tracts: list[Tract] | TractList | PLSSDesc, layer=None) None

Add multiple tracts to the queue.

Note

The tracts must already be parsed for lots/QQs. (See pyTRS documentation for details.)

Parameters:
  • tracts – A collection of pytrs.Tract objects, such as a pytrs.PLSSDesc, pytrs.TractList, or any other iterable object that contains exclusively pytrs.Tract.

  • layer – Name of the layer to add these tracts to.

carve_description(txt: str, config: str = None, layer: str = None) TractList

Parse the land description and carve out the resulting tracts from the queue, so that they do not appear on the resulting plat.

(Affects only which lands get filled in on the plat. This carve-out will NOT prevent tracts from being written to the footer, if so configured.)

Note

All carve-outs override the queue for a given layer. In other words, when the queue is executed, all added lands will be platted for that layer, then all carved-out lands will be removed from that layer. This means that carved-out lands cannot be re-added to the queue for that same layer. They can be added to the queue for a different layer.

Carve-outs for any given layer can be cleared with .clear_layer_carveouts(layer=<name>).

Warning

Any lots or aliquots identified in this description will be removed from the layer. Be careful to use a ‘clean’ description that will not remove lands that should be kept.

Parameters:
  • txt – The land description.

  • config – The config parameters for parsing, to be passed through to the pytrs library. (See pyTRS documentation for details.)

  • layer – Name of the layer to carve this description from.

Returns:

A pytrs.TractList containing the tracts in which the parser could NOT identify any lots or aliquots.

carve_tract(tract: Tract, layer: str = None) None

Carve out lands (single tract) from the queue, so that they do not appear on the resulting plat.

(Affects only which lands get filled in on the plat. This carve-out will NOT prevent tracts from being written to the footer, if so configured.)

Note

The tract must already be parsed for lots/QQs. (See pyTRS documentation for details.)

Note

All carve-outs override the queue for a given layer. In other words, when the queue is executed, all added lands will be platted for that layer, then all carved-out lands will be removed from that layer. This means that carved-out lands cannot be re-added to the queue for that same layer. They can be added to the queue for a different layer.

Carve-outs for any given layer can be cleared with .clear_layer_carveouts(layer=<name>).

Warning

Any lots or aliquots identified in this tract will be removed from the layer. Be careful to use a ‘clean’ description that will not remove lands that should be kept.

Parameters:
  • tract – A pytrs.Tract that has been parsed into Lots and QQ’s. (Its Twp/Rge must match what is already in the queue.)

  • layer – Name of the layer to carve this tract from.

carve_tracts(tracts: list[Tract] | TractList | PLSSDesc, layer: str = None) None

Carve out lands (multiple tracts) from the plat, so that they do not appear on the resulting plat.

(Affects only which lands get filled in on the plat. This carve-out will NOT prevent tracts from being written to the footer, if so configured.)

Note

The tracts must already be parsed for lots/QQs. (See pyTRS documentation for details.)

Note

All carve-outs override the queue for a given layer. In other words, when the queue is executed, all added lands will be platted for that layer, then all carved-out lands will be removed from that layer. This means that carved-out lands cannot be re-added to the queue for that same layer. They can be added to the queue for a different layer.

Carve-outs for any given layer can be cleared with .clear_layer_carveouts(layer=<name>).

Warning

Any lots or aliquots identified in these tracts will be removed from the layer. Be careful to use ‘clean’ descriptions that will not remove lands that should be kept.

Parameters:
  • tracts – A collection of pytrs.Tract objects, such as a pytrs.PLSSDesc, pytrs.TractList, or any other iterable object that contains exclusively pytrs.Tract.

  • layer – Name of the layer to carve these tracts from.

clear_layer_carveouts(layer: str = None)

Clear the carve-outs for the specified 'layer'.

Parameters:

layer – Name of the layer to clear the carve-outs for.

clear_layer_queue(layer: str = None, include_carveouts=False)

Clear the contents of the queue for the specified 'layer'.

Parameters:
  • layer – Name of the layer to clear the queue for.

  • include_carveouts – (Optional) Also clear any carve-outs for this layer.

execute_queue(subset_twprges: list[str] = None, prompt_define=False) TractList

Execute the queue of tracts, and generate the plat.

Parameters:
  • subset_twprges – (Optional) Limit the generated images to this list of Twp/Rges (in the pyTRS format – e.g., ['154n97w', '155n97w']).

  • prompt_define – (Optional) If True, first check for undefined lots, and prompt the user in console to define them.

Returns:

A pytrs.TractList containing all tracts that could not be platted.

find_undefined_lots(allow_defaults: bool = None, fp: str | Path = None, **headers) dict[str, list[str]]

Find all tracts in the queue that have one or more lots that have not been defined. Optionally write them to a .csv file at path fp, to facilitate defining them externally.

Warning

If passing fp, any file at that path will be overwritten without warning.

Parameters:
  • allow_defaults – Whether to assume that all sections are ‘standard’, with typical lots (if any) in sections along the north and west township boundaries. If not specified here, will use whatever is configured in the lot_definer.allow_defaults attribute.

  • fp – (Optional) A filepath at which to create a .csv file containing the undefined lots.

  • headers – (Optional) If saving the undefined lots to a .csv file, pass keyword arguments to specify the desired headers. (Reference the docs for LotDefiner.save_to_csv() for the appropriate parameters.)

Returns:

A dict, keyed by Twp/Rge/Sec ('154n97w01'), whose values are a sorted list of lots for that Twp/Rge/Sec.

find_unplattable_tracts(allow_defaults: bool = None) TractList

Get a pytrs.TractList containing all tracts that cannot be platted with the currently provided lot definitions (optionally accounting for default lots, if so configured).

Note

If a tract has any aliquots and/or any lots that have been defined, it will be considered plattable, even if some of its lots have NOT been defined. To check for undefined lots, use the .find_undefined_lots() method.

Parameters:

allow_defaults – Whether to assume that all sections are ‘standard’, with typical lots (if any) in sections along the north and west township boundaries. If not specified here, will use whatever is configured in the lot_definer.allow_defaults attribute.

output(fp: str | Path = None, image_format: str = None, layers: list[str] = None, image_mode: str = 'RGB', **_kw) Image | None

Compile and return the merged image of the plat. Optionally save the results to disk, either as an image or as a .zip file containing the image.

Parameters:
  • fp – (Optional) If provided, save the output to the specified filepath.

  • image_format – (Optional) Override the image format of the file specified in fp. If not provided, will defer to the file extension in fp. (Only relevant if saving to file.)

  • layers – (Optional) Choose which image layers (in bottom-up order) to include in the output. (See Plat.DEFAULT_LAYER_NAMES for the standard layer names.) Nonexistent or empty layers will be ignored. Any custom layers created by .add_description(..., layer=<name>) (and similar methods) will be included by default, unless the layers= parameter is used here.

  • image_mode – Specify which image mode to convert the merged output to. Defaults to 'RGB'. (Reference PIL.Image.Image.convert() for further details.)

  • _kw – No effect. (Included to mirror .output() of other classes.)

Returns:

The generated image. If no layers have been configured and/or layers contains only layers that are nonexistent or empty, will return None instead.

prompt_define(allow_defaults: bool = None)

Prompt the user in console to define all lots that have not yet been defined for tracts in the queue. Any new lot definitions will be added to the .lot_definer.

(You may wish to save the results with .lot_definer.save_to_csv() so that they can be loaded and reused later.)

Parameters:

allow_defaults – Whether to assume that this section is ‘standard’, with typical lots (if any) in sections along the north and west township boundaries. If not specified here, will use whatever is configured in the .lot_definer.allow_defaults attribute.

write_lot_numbers(at_depth=2, only_for_queue: bool = None)

Write the lot numbers to the MegaPlat.

Note

Lot numbers will only be written for the Twp/Rge’s that were last processed with .execute_queue().

Parameters:
  • at_depth – Depth at which to write the lots. Default is 2 (i.e., quarter-quarters).

  • only_for_queue – (Optional) If True, only write section numbers for those sections that appear in the queue.