Skip to content

openavmkit.utilities.somers

get_depth_percent_ft

get_depth_percent_ft(depth_ft)

Calculate the relative depth of a lot compared to a standard 100 ft depth.

Robust to scalars, numpy arrays, lists, and pandas Series/Index. Non-numeric inputs are coerced to NaN. Negative depths -> NaN.

Source code in openavmkit/utilities/somers.py
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
def get_depth_percent_ft(depth_ft):
    """
    Calculate the relative depth of a lot compared to a standard 100 ft depth.

    Robust to scalars, numpy arrays, lists, and pandas Series/Index.
    Non-numeric inputs are coerced to NaN. Negative depths -> NaN.
    """
    # Optional pandas support (only used if pandas objects are passed)
    try:
        import pandas as pd  # type: ignore
        _HAS_PANDAS = True
    except Exception:
        pd = None
        _HAS_PANDAS = False

    # Preserve pandas Series output if that's what we got
    is_pandas_series = _HAS_PANDAS and isinstance(depth_ft, pd.Series)
    is_pandas_index = _HAS_PANDAS and isinstance(depth_ft, pd.Index)

    # Scalar detection (works for python + numpy scalars)
    is_scalar = np.isscalar(depth_ft) or isinstance(depth_ft, np.generic)

    # Coerce to a float ndarray (fixes bug)
    if depth_ft is None:
        arr = np.array(np.nan, dtype=float)
    elif is_pandas_series or is_pandas_index:
        # pd.to_numeric fixes object dtype, strings, None, etc.
        s = pd.to_numeric(depth_ft, errors="coerce")
        arr = s.to_numpy(dtype=float)
    else:
        # Handle lists/tuples/ndarrays/scalars; coerce to float
        arr = np.asarray(depth_ft)
        if arr.dtype == object:
            # Gracefully coerce mixed/object arrays to float (non-numeric -> NaN)
            if _HAS_PANDAS:
                arr = pd.to_numeric(arr.ravel(), errors="coerce").to_numpy(dtype=float).reshape(arr.shape)
            else:
                # Minimal fallback without pandas:
                def _to_float(x):
                    try:
                        return float(x)
                    except Exception:
                        return np.nan
                arr = np.vectorize(_to_float, otypes=[float])(arr)
        else:
            arr = arr.astype(float, copy=False)

    # Negative depths would produce complex numbers for fractional powers
    arr = np.where(arr < 0, np.nan, arr)

    # --- Compute ---
    value = (133.6 * (1.0 - np.exp(-0.0326 * np.power(arr, 0.813)))) / 100.0

    # Round-half-up to nearest 0.001
    value = np.floor(value * 1000.0 + 0.5) / 1000.0

    # Ensure exactly 1.0 at 100 ft (even after float noise)
    value = np.where(np.isclose(arr, 100.0, rtol=0.0, atol=1e-12), 1.0, value)

    # --- Return in a friendly shape/type ---
    if is_pandas_series:
        return pd.Series(value, index=depth_ft.index, name=getattr(depth_ft, "name", None))
    if is_scalar:
        return float(np.asarray(value).reshape(()))  # scalar python float
    return value

get_depth_percent_m

get_depth_percent_m(depth_m)

Calculate the relative depth of a lot compared to a standard 30.48 m depth.

This function expresses the lot’s depth as a proportion of a 30.48 m standard lot depth. For example, 0 m → 0.0, 30.48 m → 1.0, and values beyond 30.48 m → >1.0.

Parameters:

Name Type Description Default
depth_m ndarray or float

Depth of the lot in meters.

required

Returns:

Type Description
ndarray or float

Relative depth proportion(s), calculated as depth_m / 30.48.

Source code in openavmkit/utilities/somers.py
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
def get_depth_percent_m(depth_m: np.ndarray | float) -> np.ndarray | float:
    """
    Calculate the relative depth of a lot compared to a standard 30.48 m depth.

    This function expresses the lot’s depth as a proportion of a 30.48 m standard lot depth.
    For example, 0 m → 0.0, 30.48 m → 1.0, and values beyond 30.48 m → >1.0.

    Parameters
    ----------
    depth_m : numpy.ndarray or float
        Depth of the lot in meters.

    Returns
    -------
    numpy.ndarray or float
        Relative depth proportion(s), calculated as `depth_m / 30.48`.
    """
    depth_ft = depth_m / 0.3048
    return get_depth_percent_ft(depth_ft)

get_lot_value_ft

get_lot_value_ft(unit_value, frontage_ft, depth_ft)

Calculate the Somers system lot value from unit value and dimensions.

Given a unit lot value (per 1 ft frontage × 100 ft depth), frontage, and depth, compute the total lot value.

Parameters:

Name Type Description Default
unit_value ndarray or float

The value per Somers unit (1 ft of frontage × 100 ft of depth).

required
frontage_ft ndarray or float

Frontage of the lot in feet.

required
depth_ft ndarray or float

Depth of the lot in feet.

required

Returns:

Type Description
ndarray or float

The total Somers system value of the lot.

Source code in openavmkit/utilities/somers.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
def get_lot_value_ft(
    unit_value: np.ndarray | float,
    frontage_ft: np.ndarray | float,
    depth_ft: np.ndarray | float
) -> np.ndarray | float:
    """
    Calculate the Somers system lot value from unit value and dimensions.

    Given a unit lot value (per 1 ft frontage × 100 ft depth), frontage, and depth,
    compute the total lot value.

    Parameters
    ----------
    unit_value : numpy.ndarray or float
        The value per Somers unit (1 ft of frontage × 100 ft of depth).
    frontage_ft : numpy.ndarray or float
        Frontage of the lot in feet.
    depth_ft : numpy.ndarray or float
        Depth of the lot in feet.

    Returns
    -------
    numpy.ndarray or float
        The total Somers system value of the lot.
    """

    # Calculate the value of the lot using the Somers formula
    return get_depth_percent_ft(depth_ft) * unit_value * frontage_ft

get_lot_value_m

get_lot_value_m(unit_value, frontage_m, depth_m)

Calculate the Somers system lot value in metric units.

Given a unit value (per 1 m of frontage × 1 m of depth), frontage, and depth in meters, compute the total lot value.

Parameters:

Name Type Description Default
unit_value ndarray or float

The Somers unit-meter value (value per 1 m frontage × 1 m depth).

required
frontage_m ndarray or float

Frontage of the lot in meters.

required
depth_m ndarray or float

Depth of the lot in meters.

required

Returns:

Type Description
ndarray or float

The total Somers system value of the lot in the same shape as the inputs.

Source code in openavmkit/utilities/somers.py
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
def get_lot_value_m(
    unit_value: np.ndarray | float,
    frontage_m: np.ndarray | float,
    depth_m: np.ndarray | float
) -> np.ndarray | float:
    """
    Calculate the Somers system lot value in metric units.

    Given a unit value (per 1 m of frontage × 1 m of depth), frontage, and depth in meters,
    compute the total lot value.

    Parameters
    ----------
    unit_value : numpy.ndarray or float
        The Somers unit-meter value (value per 1 m frontage × 1 m depth).
    frontage_m : numpy.ndarray or float
        Frontage of the lot in meters.
    depth_m : numpy.ndarray or float
        Depth of the lot in meters.

    Returns
    -------
    numpy.ndarray or float
        The total Somers system value of the lot in the same shape as the inputs.
    """
    depth_ft = depth_m / 0.3048
    frontage_ft = frontage_m / 0.3048
    return get_lot_value_ft(unit_value, frontage_ft, depth_ft)

get_size_in_somers_units_ft

get_size_in_somers_units_ft(frontage_ft, depth_ft)

Get the size of a parcel or parcels in somers unit-feet.

Parameters:

Name Type Description Default
frontage_ft ndarray | float

The frontage of the parcel, in feet

required
depth_ft ndarray | float

The depth of the parcel, in feet

required

Returns:

Type Description
ndarray | float

The converted value in somers unit-feet

Source code in openavmkit/utilities/somers.py
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
def get_size_in_somers_units_ft(
    frontage_ft: np.ndarray | float, depth_ft: np.ndarray | float
):
    """
    Get the size of a parcel or parcels in somers unit-feet.

    Parameters
    ----------
    frontage_ft : np.ndarray | float
        The frontage of the parcel, in feet
    depth_ft : np.ndarray | float
        The depth of the parcel, in feet

    Returns
    -------
    np.ndarray | float
        The converted value in somers unit-feet
    """
    # How big is a lot, in somers unit-feet?

    # Normalize the depth:
    depth_percent = get_depth_percent_ft(depth_ft)

    # Multiply by frontage:
    somers_units = depth_percent * frontage_ft

    return somers_units

get_size_in_somers_units_m

get_size_in_somers_units_m(frontage_m, depth_m, land_area_sqm)

Get the size of a parcel or parcels in somers unit-meters

Parameters:

Name Type Description Default
frontage_m ndarray | float

The frontage of the parcel, in meters

required
depth_m ndarray | float

The depth of the parcel, in meters

required

Returns:

Type Description
ndarray | float

The converted value in somers unit-meters

Source code in openavmkit/utilities/somers.py
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
def get_size_in_somers_units_m(
    frontage_m: np.ndarray | float,
    depth_m: np.ndarray | float,
    land_area_sqm: np.ndarray | float,
):
    """
    Get the size of a parcel or parcels in somers unit-meters

    Parameters
    ----------
    frontage_m : np.ndarray | float
        The frontage of the parcel, in meters
    depth_m : np.ndarray | float
        The depth of the parcel, in meters

    Returns
    -------
    np.ndarray | float
        The converted value in somers unit-meters
    """
    frontage_ft = frontage_m / 0.3048
    depth_ft = depth_m / 0.3048
    land_area_sqft = land_area_sqm / 0.092903
    return get_size_in_somers_units_ft(frontage_ft, depth_ft, land_area_sqft)

get_unit_ft

get_unit_ft(lot_value, frontage_ft, depth_ft)

Calculate the Somers unit-foot value for a lot.

The Somers unit-foot value is defined as the lot's total value divided by the product of its frontage in feet and a standard depth of 100 feet: Somers unit-foot = lot_value / (frontage_ft * 100).

Parameters:

Name Type Description Default
lot_value ndarray or float

Total value of the lot.

required
frontage_ft ndarray or float

Frontage of the lot in feet.

required
depth_ft ndarray or float

Depth of the lot in feet (typically compared against a standard 100 ft).

required

Returns:

Type Description
ndarray or float

Somers unit-foot value(s), matching the shape of the inputs.

Source code in openavmkit/utilities/somers.py
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def get_unit_ft(
    lot_value: np.ndarray | float,
    frontage_ft: np.ndarray | float,
    depth_ft: np.ndarray | float
) -> np.ndarray | float:
    """
    Calculate the Somers unit-foot value for a lot.

    The Somers unit-foot value is defined as the lot's total value divided by the
    product of its frontage in feet and a standard depth of 100 feet:
    Somers unit-foot = lot_value / (frontage_ft * 100).

    Parameters
    ----------
    lot_value : numpy.ndarray or float
        Total value of the lot.
    frontage_ft : numpy.ndarray or float
        Frontage of the lot in feet.
    depth_ft : numpy.ndarray or float
        Depth of the lot in feet (typically compared against a standard 100 ft).

    Returns
    -------
    numpy.ndarray or float
        Somers unit-foot value(s), matching the shape of the inputs.
    """
    # Calculate the Somers unit-foot value
    return lot_value / (get_depth_percent_ft(depth_ft) * frontage_ft)

get_unit_m

get_unit_m(lot_value, frontage_m, depth_m)

Calculate the Somers unit-meter value for a lot.

Given a lot's total value, frontage, and depth in meters, compute the Somers unit-meter value (value per meter of frontage × meter of depth).

Parameters:

Name Type Description Default
lot_value ndarray or float

Total value of the lot.

required
frontage_m ndarray or float

Frontage of the lot in meters.

required
depth_m ndarray or float

Depth of the lot in meters.

required

Returns:

Type Description
ndarray or float

Somers unit-meter value(s) for the lot(s).

Source code in openavmkit/utilities/somers.py
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
def get_unit_m(
    lot_value: np.ndarray | float,
    frontage_m: np.ndarray | float,
    depth_m: np.ndarray | float
) -> np.ndarray | float:
    """
    Calculate the Somers unit-meter value for a lot.

    Given a lot's total value, frontage, and depth in meters, compute the Somers
    unit-meter value (value per meter of frontage × meter of depth).

    Parameters
    ----------
    lot_value : numpy.ndarray or float
        Total value of the lot.
    frontage_m : numpy.ndarray or float
        Frontage of the lot in meters.
    depth_m : numpy.ndarray or float
        Depth of the lot in meters.

    Returns
    -------
    numpy.ndarray or float
        Somers unit-meter value(s) for the lot(s).
    """
    # Convert to feet
    depth_ft = depth_m / 0.3048
    frontage_ft = frontage_m / 0.3048
    return get_unit_ft(lot_value, frontage_ft, depth_ft)