{ "cells": [ { "cell_type": "markdown", "id": "3295c2eb", "metadata": {}, "source": [ "# Factory methods — quick object creation\n", "\n", "Several WOLFHECE classes provide **factory methods** to create instances\n", "in a single call, without setting attributes one by one.\n", "\n", "This notebook groups them for `header_wolf`, `WolfArray`, `vector`, `zone` and `Zones`.\n", "Each section is self-contained; see the dedicated tutorials for in-depth usage." ] }, { "cell_type": "code", "execution_count": 1, "id": "f86f3bfa", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from pathlib import Path\n", "import tempfile\n", "\n", "tmpdir = Path(tempfile.mkdtemp())" ] }, { "cell_type": "markdown", "id": "cc8876f0", "metadata": {}, "source": [ "---\n", "\n", "## 1. `header_wolf` factories\n", "\n", "| Factory | Input | Key feature |\n", "|---------|-------|-------------|\n", "| `make(orig, nb, d)` | origin + cell count + resolution | Simplest one-liner |\n", "| `make_from_xybounds_grid(xbounds, ybounds, d)` | spatial bounds + resolution | `grid_to_align` snaps origin |\n", "| `from_slices(x_slice, y_slice, d)` | Python slices + resolution | Handy for sub-windows |\n", "| `from_dict(d)` | dict | Deserialization / config files |" ] }, { "cell_type": "code", "execution_count": 2, "id": "14ebd947", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "make : 100x80, orig=(220000.0, 130000.0), d=(1.0, 1.0)\n", "from_xybounds : 50x40, orig=(220000.0, 130000.0), d=(2.0, 2.0)\n", "aligned : orig=(220003.0, 130002.0) (snapped to h)\n", "from_slices : 50x40, orig=(10.0, 5.0)\n" ] } ], "source": [ "from wolfhece.wolf_array import header_wolf\n", "\n", "# --- make: origin + cell count + resolution ---\n", "h = header_wolf().make(\n", " orig=(220000.0, 130000.0),\n", " nb=(100, 80),\n", " d=(1.0, 1.0),\n", ")\n", "print(f\"make : {h.nbx}x{h.nby}, orig=({h.origx}, {h.origy}), d=({h.dx}, {h.dy})\")\n", "\n", "# --- make_from_xybounds_grid: from spatial bounds ---\n", "h2 = header_wolf.make_from_xybounds_grid(\n", " xbounds=(220000.0, 220100.0),\n", " ybounds=(130000.0, 130080.0),\n", " d=(2.0, 2.0),\n", ")\n", "print(f\"from_xybounds : {h2.nbx}x{h2.nby}, orig=({h2.origx}, {h2.origy}), d=({h2.dx}, {h2.dy})\")\n", "\n", "# --- with grid alignment (snaps origin to existing grid) ---\n", "h3 = header_wolf.make_from_xybounds_grid(\n", " xbounds=(220003.7, 220100.0),\n", " ybounds=(130002.1, 130080.0),\n", " d=(1.0, 1.0),\n", " grid_to_align=h,\n", ")\n", "print(f\"aligned : orig=({h3.origx}, {h3.origy}) (snapped to h)\")\n", "\n", "# --- from_slices: index ranges ---\n", "h4 = header_wolf.from_slices(\n", " x_slice=slice(10, 60),\n", " y_slice=slice(5, 45),\n", " d=(1.0, 1.0),\n", ")\n", "print(f\"from_slices : {h4.nbx}x{h4.nby}, orig=({h4.origx}, {h4.origy})\")" ] }, { "cell_type": "markdown", "id": "72e2f515", "metadata": {}, "source": [ "---\n", "\n", "## 2. `WolfArray` / `WolfArrayModel` factories\n", "\n", "| Creation path | Code | Notes |\n", "|---------------|------|-------|\n", "| From header (empty) | `WolfArray(srcheader=h)` | Array filled with ones |\n", "| From header + numpy | `WolfArray(srcheader=h, np_source=arr)` | Wraps existing array |\n", "| From file | `WolfArray(fname='dem.bin')` | `.bin`, `.tif`, `.npy`, `.vrt` |\n", "| Clone / crop | `WolfArray(mold=other, crop=bbox)` | Deep copy, optional crop |\n", "| Merge multiple | `WolfArrayModel.merge([a, b, c])` | Union of several arrays |\n", "| From XYZ file | `WolfArrayModel.set_general_frame_from_xyz(f, dx, dy)` | Text XYZ |\n", "| Reproject CRS | `WolfArrayModel.from_other_epsg_coo(f, …)` | GDAL reprojection |" ] }, { "cell_type": "code", "execution_count": 3, "id": "585f41f4", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "From header : shape=100x80, dtype=float32\n", "From np_source : min=0.000, max=1.000\n", "Clone : same origin? True\n", "Cropped clone : shape=50x40\n" ] } ], "source": [ "from wolfhece.wolf_array import WolfArray, header_wolf\n", "from wolfhece.wolf_array._header_wolf import WOLF_ARRAY_FULL_SINGLE\n", "\n", "# --- From header (empty array) ---\n", "h = header_wolf().make(orig=(220000.0, 130000.0), nb=(100, 80), d=(1.0, 1.0))\n", "wa = WolfArray(srcheader=h, whichtype=WOLF_ARRAY_FULL_SINGLE)\n", "print(f\"From header : shape={wa.nbx}x{wa.nby}, dtype={wa.array.dtype}\")\n", "\n", "# --- From header + numpy array ---\n", "data = np.random.rand(100, 80).astype(np.float32)\n", "wa2 = WolfArray(srcheader=h, np_source=data, whichtype=WOLF_ARRAY_FULL_SINGLE)\n", "print(f\"From np_source : min={wa2.array.min():.3f}, max={wa2.array.max():.3f}\")\n", "\n", "# --- Clone (deep copy) ---\n", "wa3 = WolfArray(mold=wa2)\n", "print(f\"Clone : same origin? {wa3.origx == wa2.origx}\")\n", "\n", "# --- Clone + crop ---\n", "wa4 = WolfArray(mold=wa2, crop=[[220010.0, 220060.0], [130010.0, 130050.0]])\n", "print(f\"Cropped clone : shape={wa4.nbx}x{wa4.nby}\")" ] }, { "cell_type": "code", "execution_count": 5, "id": "6c42b623", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "_new_like : shape=100x80, all zeros? False\n", "crop_array : shape=60x40\n", "merge : shape=100x40\n" ] } ], "source": [ "from wolfhece.wolf_array import WolfArrayModel\n", "\n", "# --- _new_like: empty array with same geometry ---\n", "wa_empty = wa2._new_like()\n", "print(f\"_new_like : shape={wa_empty.nbx}x{wa_empty.nby}, all zeros? {(wa_empty.array == 0)}\")\n", "\n", "# --- crop_array: extract sub-region ---\n", "wa_sub = wa2.crop_array([[220020.0, 220080.0], [130020.0, 130060.0]])\n", "print(f\"crop_array : shape={wa_sub.nbx}x{wa_sub.nby}\")\n", "\n", "# --- merge: combine several arrays ---\n", "h_left = header_wolf().make(orig=(0.0, 0.0), nb=(50, 40), d=(1.0, 1.0))\n", "h_right = header_wolf().make(orig=(50.0, 0.0), nb=(50, 40), d=(1.0, 1.0))\n", "a_left = WolfArrayModel(srcheader=h_left)\n", "a_right = WolfArrayModel(srcheader=h_right)\n", "merged = WolfArrayModel.merge([a_left, a_right])\n", "print(f\"merge : shape={merged.nbx}x{merged.nby}\")" ] }, { "cell_type": "markdown", "id": "12163556", "metadata": {}, "source": [ "---\n", "\n", "## 3. `vector` / `vectorModel` factories\n", "\n", "| Factory | Input | Notes |\n", "|---------|-------|-------|\n", "| Constructor `fromnumpy=` | `(N,2)` or `(N,3)` array | In-constructor |\n", "| Constructor `fromlist=` | List of tuples | In-constructor |\n", "| Constructor `fromshapely=` | Shapely geometry | LineString or Polygon |\n", "| `make_from_numpy(arr)` | Classmethod | Same as above, explicit name |\n", "| `make_from_list(lst)` | Classmethod | Same as above, explicit name |\n", "| `make_from_shapely(obj)` | Classmethod | Same as above, explicit name |\n", "| `deepcopy()` | Instance | Full deep copy |" ] }, { "cell_type": "code", "execution_count": 8, "id": "5404f8a5", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "from numpy : from_numpy, 3 vertices\n", "from list : from_list, 3 vertices\n", "from shapely: from_shapely, 3 vertices\n", "classmethod : classmethod_numpy, 3 vertices\n" ] } ], "source": [ "from wolfhece.PyVertexvectors import vector, wolfvertex\n", "\n", "# --- From numpy array ---\n", "coords = np.array([\n", " [220000.0, 130000.0],\n", " [220050.0, 130050.0],\n", " [220100.0, 130000.0],\n", "])\n", "v1 = vector(fromnumpy=coords, name='from_numpy')\n", "print(f\"from numpy : {v1.myname}, {v1.nbvertices} vertices\")\n", "\n", "# --- From list of tuples ---\n", "v2 = vector(fromlist=[(0, 0), (10, 20), (30, 10)], name='from_list')\n", "print(f\"from list : {v2.myname}, {v2.nbvertices} vertices\")\n", "\n", "# --- From Shapely ---\n", "from shapely.geometry import LineString\n", "ls = LineString([(0, 0), (50, 50), (100, 0)])\n", "v3 = vector(fromshapely=ls, name='from_shapely')\n", "print(f\"from shapely: {v3.myname}, {v3.nbvertices} vertices\")\n", "\n", "# --- Classmethod equivalents ---\n", "v4 = vector.make_from_numpy(coords, name='classmethod_numpy')\n", "print(f\"classmethod : {v4.myname}, {v4.nbvertices} vertices\")" ] }, { "cell_type": "code", "execution_count": 9, "id": "37d06486", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "manual : 11 vertices\n", "deepcopy : copied, 11 vertices\n", "as numpy : shape=(11, 2)\n", "as shapely : LineString, length=110.5\n" ] } ], "source": [ "# --- Vertex-by-vertex construction ---\n", "v5 = vector(name='manual')\n", "for x in np.linspace(0, 100, 11):\n", " v5.add_vertex(wolfvertex(x, 10.0 * np.sin(x / 15.0), 0.0))\n", "print(f\"manual : {v5.nbvertices} vertices\")\n", "\n", "# --- Deep copy ---\n", "v6 = v5.deepcopy(name='copied')\n", "print(f\"deepcopy : {v6.myname}, {v6.nbvertices} vertices\")\n", "\n", "# --- Round-trip: vector <-> numpy <-> shapely ---\n", "arr = v5.asnparray() # -> (N, 2)\n", "line = v5.asshapely_ls() # -> LineString\n", "print(f\"as numpy : shape={arr.shape}\")\n", "print(f\"as shapely : {line.geom_type}, length={line.length:.1f}\")" ] }, { "cell_type": "markdown", "id": "8bc757ca", "metadata": {}, "source": [ "---\n", "\n", "## 4. `zone` / `zoneModel` factories\n", "\n", "| Factory | Input | Notes |\n", "|---------|-------|-------|\n", "| Constructor `fromshapely=` | Shapely Polygon/MultiPolygon | Auto-imports geometry |\n", "| `add_vector(v)` | Existing vector | Build zone programmatically |\n", "| `deepcopy()` | Instance | Full deep copy with all vectors |" ] }, { "cell_type": "code", "execution_count": 10, "id": "cec1f4c8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "from shapely : from_shapely, 1 vector(s)\n", "built : built, 2 vector(s)\n", "deepcopy : copy_of_built, 2 vector(s)\n" ] } ], "source": [ "from wolfhece.PyVertexvectors import zone\n", "from shapely.geometry import Polygon\n", "\n", "# --- From Shapely polygon ---\n", "poly = Polygon([(0, 0), (100, 0), (100, 50), (0, 50)])\n", "z1 = zone(fromshapely=poly, name='from_shapely')\n", "print(f\"from shapely : {z1.myname}, {z1.nbvectors} vector(s)\")\n", "\n", "# --- Programmatic: create zone, add vectors ---\n", "z2 = zone(name='built')\n", "z2.add_vector(v1) # reuse vector from above\n", "z2.add_vector(v2)\n", "print(f\"built : {z2.myname}, {z2.nbvectors} vector(s)\")\n", "\n", "# --- Deep copy ---\n", "z3 = z2.deepcopy(name='copy_of_built')\n", "print(f\"deepcopy : {z3.myname}, {z3.nbvectors} vector(s)\")" ] }, { "cell_type": "markdown", "id": "65afe9e2", "metadata": {}, "source": [ "---\n", "\n", "## 5. `Zones` / `ZonesModel` factories\n", "\n", "| Factory | Input | Notes |\n", "|---------|-------|-------|\n", "| Constructor `filename=` | `.vec`, `.vecz`, `.shp`, `.gpkg`, `.gdb`, `.dxf` | Auto-detect format |\n", "| `import_shapefile(fn)` | `.shp` path | With column / bbox filters |\n", "| `import_GeoDataFrame(gdf)` | GeoDataFrame | From GeoPandas directly |\n", "| `import_dxf(fn)` | `.dxf` path | AutoCAD import |\n", "| `import_gpkg(fn)` | `.gpkg` path | GeoPackage |\n", "| `create_zone(name)` | — | Add new empty zone |\n", "| `add_zone(z)` | Existing zone | Append a zone |\n", "| `deepcopy()` | Instance | Full deep copy |" ] }, { "cell_type": "code", "execution_count": 12, "id": "a5e6a2fa", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:root:Finding min and max values\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Zones: 2 zone(s)\n", "Reloaded: 2 zone(s)\n" ] } ], "source": [ "from wolfhece.PyVertexvectors import Zones\n", "\n", "# --- Build programmatically ---\n", "zs = Zones()\n", "new_zone = zs.create_zone(name='zone_A')\n", "new_zone.add_vector(v1, forceparent=True) # add vector to zone, and zone to zones (forceparent)\n", "\n", "zs.add_zone(z1, forceparent=True) # reuse zone from above\n", "print(f\"Zones: {zs.nbzones} zone(s)\")\n", "\n", "# --- Save as .vecz and reload ---\n", "vecz_path = str(tmpdir / 'demo.vecz')\n", "zs.saveas(vecz_path)\n", "\n", "zs2 = Zones(filename=vecz_path)\n", "print(f\"Reloaded: {zs2.nbzones} zone(s)\")" ] }, { "cell_type": "code", "execution_count": 13, "id": "d2545b24", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:root:Importing GeoDataFrame\n", "INFO:root:Converting DataFrame into zones\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "GeoDataFrame: 2 rows\n", " id geometry\n", "0 zone_A LINESTRING Z (220000 130000 -99999, 220050 130...\n", "1 from_shapely POLYGON ((0 0, 100 0, 100 50, 0 50, 0 0))\n", "\n", "Re-imported: 2 zone(s)\n" ] } ], "source": [ "# --- Round-trip via GeoDataFrame ---\n", "gdf = zs.export_GeoDataFrame()\n", "print(f\"GeoDataFrame: {len(gdf)} rows\")\n", "print(gdf.head())\n", "\n", "zs3 = Zones()\n", "zs3.import_GeoDataFrame(gdf)\n", "print(f\"\\nRe-imported: {zs3.nbzones} zone(s)\")" ] }, { "cell_type": "code", "execution_count": 14, "id": "15240079", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Deep copy: 2 zone(s)\n" ] } ], "source": [ "# --- Deep copy ---\n", "zs_copy = zs.deepcopy()\n", "print(f\"Deep copy: {zs_copy.nbzones} zone(s)\")" ] }, { "cell_type": "markdown", "id": "6566c251", "metadata": {}, "source": [ "---\n", "\n", "## Summary\n", "\n", "| Class | Quick creation | From file | From Shapely / numpy | Deep copy |\n", "|-------|----------------|-----------|----------------------|-----------|\n", "| `header_wolf` | `make(orig, nb, d)` | `read_header(fn)` | — | `make_from_header(h)` |\n", "| `WolfArray` | `WolfArray(srcheader=h)` | `WolfArray(fname=f)` | `np_source=arr` | `WolfArray(mold=wa)` |\n", "| `vector` | `vector(name=n)` | via parent `Zones` | `fromnumpy=`, `fromshapely=` | `deepcopy()` |\n", "| `zone` | `zone(name=n)` | via parent `Zones` | `fromshapely=` | `deepcopy()` |\n", "| `Zones` | `Zones()` + `create_zone()` | `Zones(filename=f)` | `import_GeoDataFrame(gdf)` | `deepcopy()` |\n", "\n", "See also:\n", "- [header_wolf tutorial](header_wolf.ipynb)\n", "- [WolfArray tutorial](wolfarray.ipynb)\n", "- [Zones, zone, vector tutorial](zones_zone_vector_vertex.ipynb)" ] } ], "metadata": { "kernelspec": { "display_name": "python311", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.9" } }, "nbformat": 4, "nbformat_minor": 5 }