Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 45 additions & 7 deletions interpret/specification.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ def create_curvegen(csvv, covariator, regions, farmer='full', specconf=None, get

# Clause to set curve baseline extents if configured.
clipping_cfg = specconf.get('clipping', False)
clipmodel = None
if clipping_cfg:
# Validate clipping configuration option.
user_assert(clipping_cfg in ['boatpose', 'downdog', True, 'corpsepose', 'plankpose'],
Expand Down Expand Up @@ -375,7 +376,19 @@ def create_curvegen(csvv, covariator, regions, farmer='full', specconf=None, get
curve_global_extrema = curve_extrema(curve)
baselineexts = {r: curve_global_extrema for r in regions}

def transform(region, curve):
# instead of accepting exactly one curve, transform can now accept one or more curves
def transform(region, *curves):
# for the special corpsepose/plankpose clipping configurations, we need both current model curve and clip-model curve to perform transform
if clipping_cfg in ['corpsepose', 'plankpose']:
# force there to be exactly two curves in that case: clip_reference_curve and current model curve: curves
user_assert(len(curves) == 2, "corpsepose/plankpose requires both clip-model and target curves")
clip_reference_curve, curve = curves
# for other clipping configurations, we only need the current model curve
else:
user_assert(len(curves) == 1, "expected a single curve for transform")
curve = curves[0]
clip_reference_curve = None

if isinstance(curve, smart_curve.SmartCurve):
final_curve = curve
else:
Expand Down Expand Up @@ -420,9 +433,20 @@ def transform(region, curve):
direction=ucurve_direction,
)
else: # 'corpsepose' or 'plankpose'
# making sure the clip model's (low-risk) curve was passed in to clip against
user_assert(
clip_reference_curve is not None,
"clip-model curve was not provided to clipping transform"
)

# if not in right curve format already, convert
if not isinstance(clip_reference_curve, smart_curve.SmartCurve):
clip_reference_curve = smart_curve.CoefficientsCurve(
clip_reference_curve.ccs, weathernames
)

# Also shift clipmodel down
clip_curve = othermodels[specconf.get('clip-model')].current_curves[region]
clip_curve = smart_curve.ShiftedCurve(clip_curve, -clip_curve.univariate(baselineexts[region]))
clip_curve = smart_curve.ShiftedCurve(clip_reference_curve, -clip_reference_curve.univariate(baselineexts[region]))

if clipping_cfg == 'corpsepose':
final_curve = smart_curve.MinimumCurve(final_curve, clip_curve)
Expand Down Expand Up @@ -450,21 +474,35 @@ def transform(region, curve):

return final_curve

# By default, transform only receives the current model's curve
transform_curvegens = [curr_curvegen]

# For corpsepose/plankpose, transform now needs two curves:
# 1) the clip-model reference curve (minlost_lo)
# 2) the current model curve (minlost_hi)
# so clipping does not depend on the cache lookup of the clip-model's curve
if clipping_cfg in ['corpsepose', 'plankpose']:
transform_curvegens = [othermodels[clipmodel].curvegen, curr_curvegen]

# Pass the prepared curve generator(s) into transform
# In the corpsepose/plankpose case this supplies two curves
# Otherwise it preserves the original single-curve behavior
if clipping_cfg and specconf.get('goodmoney', False):
final_curvegen = curvegen.TransformCurveGenerator(transform, "Clipping and Good Money transformation", curr_curvegen)
final_curvegen = curvegen.TransformCurveGenerator(transform, "Clipping and Good Money transformation", *transform_curvegens)
elif clipping_cfg:
final_curvegen = curvegen.TransformCurveGenerator(transform, "Clipping transformation", curr_curvegen)
final_curvegen = curvegen.TransformCurveGenerator(transform, "Clipping transformation", *transform_curvegens)
elif specconf.get('goodmoney', False):
final_curvegen = curvegen.TransformCurveGenerator(transform, "Good Money transformation", curr_curvegen)
final_curvegen = curvegen.TransformCurveGenerator(transform, "Good Money transformation", *transform_curvegens)
else:
final_curvegen = curvegen.TransformCurveGenerator(transform, "Smart curve transformation", curr_curvegen)
final_curvegen = curvegen.TransformCurveGenerator(transform, "Smart curve transformation", *transform_curvegens)
final_curvegen.deltamethod_passthrough = True

if covariator:
final_curvegen = curvegen.FarmerCurveGenerator(final_curvegen, covariator, farmer)

return final_curvegen


def prepare_interp_raw(csvv, weatherbundle, economicmodel, qvals, farmer='full', specconf=None, config=None):
"""

Expand Down