feat: Added USDA converter - #50
Conversation
mentaljam
left a comment
There was a problem hiding this comment.
Requested redesign: texture-class adapters
This change should not introduce a generated, Python-only utility module plus
per-PTF input_adapters.usda_texture status metadata. The proposed utility is
a fixed table of twelve USDA classes, and the current metadata is not used by
any PTF. As implemented, users must call the converter themselves and then
pass numeric fractions to a PTF; that exposes an implementation detail and
does not provide a cross-target PTF feature.
Please redesign this as a first-class input type and a compiler-lowered
derived-input mechanism.
Specification model
- Add an adapter registry under
specs/adapters/. Each adapter has its own
schema and defines its logical input and output contract. The USDA adapter
defines one strictusda_texture_classinput and the numericsand,
silt, andclayoutputs. - Make registered adapter input types available to all PTF specifications.
A PTF may explicitly declare a parameter with typeusda_texture_class. - Let a PTF explicitly bind adapter outputs to derived numeric inputs used by
its formula. For example, atexture_classparameter can be lowered to
derivedsand,silt, andclayvalues. Do not infer this from variable
names occurring in the formula. - Require source-backed scientific evidence on the PTF binding: it must
establish that the published PTF's particle-size definitions are compatible
with this adapter. An adapter is available to every PTF, but no PTF may use
it without this explicit claim. - Preserve a published categorical texture-class predictor as categorical.
Do not replace it with representative fractions unless the source actually
supports that model transformation.
The following is an illustrative target syntax, not a request to accept this
exact YAML before the schema and IR are designed:
inputs:
- name: texture_class
type: usda_texture_class
derived_inputs:
sand: { adapter: usda_texture, input: texture_class, component: sand }
silt: { adapter: usda_texture, input: texture_class, component: silt }
clay: { adapter: usda_texture, input: texture_class, component: clay }
implementation:
variables:
- name: theta_33
expr: ...texture_class is the only public input in this example. Its declared type
selects the strict USDA class contract. Each derived_inputs entry explicitly
states that one numeric formula symbol comes from the named component of the
usda_texture adapter applied to that input. The formula may consequently
refer to sand, silt, and clay as ordinary scalar symbols. It does not
accept them from the caller, and the generator does not guess the binding from
their names. theta_33 is only a placeholder for the normal, source-backed
PTF expression.
The semantic IR should contain the explicit derived-input bindings. Renderers
then insert the target-local adapter call before evaluating the normal numeric
formula. sand, silt, and clay therefore remain ordinary scalar symbols
in the formula and do not become hidden or magical inputs.
Target implementations
The adapter implementation is a small fixed table and should be handwritten
once in each retained target. It is not necessary to generate that table from
YAML. The generator's responsibility is to lower declared adapter bindings
and render calls to the target-local implementation.
The public PTF API accepts texture_class; users should not have to manually
compose a public conversion call with a numerical PTF call. A public standalone
converter may still be exported as a convenience API, but it has the same
strict contract and is not the primary integration mechanism.
Python must implement the adapter in the direct CPython/NumPy extension, not
as a Python dictionary lookup or numpy.vectorize wrapper. PTFs accepting
texture classes must retain array inputs, broadcasting, and out behaviour.
The C extension may use compact internal class codes, but it must accept the
documented exact Unicode class values at its public boundary.
Python contract
The generated Python type surface should use an exact Literal[...] union of
the twelve canonical lowercase USDA names. There should be no StrEnum,
case-folding, trimming, hyphen/underscore substitution, aliases, abbreviations,
or fuzzy matching. Invalid input is a caller error: the API must enforce the
contract rather than repair input data.
This is a semantic redesign, so the current generated module, its generated
tests, the one-off USDA utility specification/schema, and the current
input_adapters.usda_texture status model should be replaced rather than
extended.
|
One further clarification on the runtime representation and where string parsing should live. The generated PTF core should operate only on the target's native categorical representation. String parsing should not be part of the generated PTF implementation or adapter lowering. For the retained targets:
Codegen should generate the categorical type/constants and the mapping from that categorical representation to representative fractions. For example, C/C++/CPython may use a generated lookup table, while Rust may use an idiomatic generated conversion such as String-to-category conversion is a target-level convenience and should be handwritten where useful rather than modeled in the specification or generalized in codegen. This keeps the generator focused on scientific data and computation rather than target-specific text handling. For example, the Rust helper can simply implement impl FromStr for UsdaTexture {
type Err = ParseUsdaTextureError;
fn from_str(value: &str) -> Result<Self, Self::Err> {
match value {
"sand" => Ok(Self::Sand),
"loamy sand" => Ok(Self::LoamySand),
"sandy loam" => Ok(Self::SandyLoam),
// ...
_ => Err(ParseUsdaTextureError),
}
}
}Similarly, CPython can have a handwritten parser optimized for its actual input representation. The intended separation is therefore: The mandatory preparation step discussed above remains unchanged: raw string arrays are converted once into the prepared categorical representation, and PTFs accept only that prepared representation. This avoids repeated string parsing while keeping both the specification model and code generation simple. |
No description provided.