Contrasts
A contrast is one structure measured under another SLD condition: the
same film in D2O and in H2O, or a monolayer with deuterated and
hydrogenated tails. Each contrast is an ordinary Model, with its own
scale, background and resolution; what the contrasts have in common is
shared in one of two ways:
- by identity: an assembly or material is one object used by several models, so it has one set of parameters;
- by equality: a parameter of one model follows the corresponding parameter of another, where the objects must differ (a hydrated layer whose solvent differs between contrasts).
The Project offers two routes to that state. Adding a contrast
derives a new model from a reference with derive_contrast: assemblies
the substitutions do not touch are shared, touched ones are copied with
every parameter tied to the reference's except those of the replacement.
from easyreflectometry.contrasts import ReplaceFormula
from easyreflectometry.contrasts import ReplaceMaterial
h2o_index = project.add_contrast(0, 'Film in H2O', [ReplaceMaterial(d2o, h2o)])
h_tails = project.add_contrast(0, 'h-tails', [ReplaceFormula(tail_layer, 'C32H64')])
project.parameter_models(film_layer.thickness) # [0, 1, 2]: one parameter of three models
Linking contrasts ties two models that exist already. Parameters
correspond by their path within the model, so the models need the same
layout: the same assemblies and layers, with materials of the same kind
(a MaterialDensity and a plain Material do not correspond);
plan_link raises LayoutMismatch otherwise. The plan changes nothing:
each LinkRow says what linking would do with one pair of parameters
('tie', 'skip', 'already_tied', 'conflict'), and with the
reason. Scale and background always stay per contrast. A material's
chemistry (CHEMISTRY: SLD, density, scattering lengths) is
'undecided' until materials='tie' or materials='skip' is given,
since contrasts usually differ in it.
plan = project.plan_link(follower_index, reference_index, materials='skip')
[(row.path, row.action, row.reason) for row in plan.rows]
record = project.apply_link(plan) # ties the 'tie' rows, all or none
project.unlink(record) # restores each follower's value and bounds from before the link
apply_link refuses a plan with undecided rows, or one the project has
outdated since it was made. Project.detach frees a shared parameter in
one model, which then gets its own copy of the assembly. The derivation
of each contrast, the links and the sharing are saved with the project.
See the
contrasts tutorial for a
worked example.
contrasts
Contrasts: one structure measured under several SLD conditions.
Each contrast is an ordinary :class:~easyreflectometry.model.Model with its
own scale, background and resolution. What the contrasts have in common is
shared in one of two ways:
- by identity: an assembly or material is one object used by several models, so it has one set of parameters;
- by equality: a parameter of one model follows the corresponding
parameter of another (
constrain_equal), where the objects must differ, e.g. a hydrated layer whose solvent differs between contrasts.
:func:derive_contrast builds a new contrast from a reference model and a
list of substitutions; :func:plan_link lays out the equalities that would
tie the parameters of two existing models. :class:~easyreflectometry.project.Project
wraps both (add_contrast, plan_link/apply_link/unlink,
detach).
CHEMISTRY = frozenset({'sld', 'isld', 'density', 'scattering_length_real', 'scattering_length_imag'})
module-attribute
ReplaceMaterial
dataclass
Use new wherever the reference uses old (a material, or a mixture's component).
Source code in src/easyreflectometry/contrasts.py
62 63 64 65 66 67 | |
ReplaceFormula
dataclass
Give the contrast's copy of target another chemical formula (isotopic substitution).
Source code in src/easyreflectometry/contrasts.py
70 71 72 73 74 75 | |
UnsupportedSubstitution
Bases: ValueError
A substitution :func:derive_contrast cannot carry out; nothing was built.
Source code in src/easyreflectometry/contrasts.py
54 55 | |
LinkPlan
dataclass
Source code in src/easyreflectometry/contrasts.py
228 229 230 231 232 233 234 235 236 237 238 | |
outdated(current)
Paths of the rows to tie that current (the same link, planned now) no longer allows:
the parameters changed, or the row is already tied, shared with another model, ...
Source code in src/easyreflectometry/contrasts.py
234 235 236 237 238 | |
LinkRow
dataclass
One pair of corresponding parameters of two models and what linking does with it.
action is 'tie', 'skip', 'already_tied', 'conflict' or
'undecided' (a chemistry parameter: set it to 'tie' or 'skip').
Source code in src/easyreflectometry/contrasts.py
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | |
LinkRecord
dataclass
The equalities one :meth:Project.apply_link made, so they can be undone together.
Source code in src/easyreflectometry/contrasts.py
250 251 252 253 254 255 256 257 | |
LayoutMismatch
Bases: ValueError
Two models whose parameters do not correspond one to one.
Source code in src/easyreflectometry/contrasts.py
58 59 | |
derive_contrast(reference, *, name, substitutions=None)
A new contrast of reference's structure; reference is not changed.
Assemblies the substitutions do not touch are shared with reference.
An assembly they touch is copied: its materials are shared except the
replaced ones, its layers are new, and every independent parameter of the
copy is tied to the reference's except those of the replacements (and the
scattering lengths of a re-formulated material). So a hydrated layer in
another solvent keeps the reference's thickness, roughness and solvent
fraction, and its effective SLD follows the dry material it still shares.
Scale, background and resolution are copied by value and stay independent.
Raises:
| Type | Description |
|---|---|
UnsupportedSubstitution
|
A target is not part of |
Source code in src/easyreflectometry/contrasts.py
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 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 124 125 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 | |
substitution_candidates(model)
What :func:derive_contrast can substitute in model, each once, in sample order.
Returns:
| Type | Description |
|---|---|
tuple[list, list]
|
The materials and mixture components a :class: |
Source code in src/easyreflectometry/contrasts.py
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 | |
plan_link(follower, reference, *, owners, follower_index, materials=None)
The equalities that would tie follower's parameters to reference's; nothing is changed.
Parameters correspond by their path within the model, so the two layouts
must match. Scale and background stay per contrast; parameters that are
one object, derived, disabled or followed by something else are skipped
with a reason; a parameter the follower shares with a third model is
skipped as well (tying it would move that model too). Chemistry
parameters (:data:CHEMISTRY) are 'undecided' unless materials is
'tie' or 'skip'.
Raises:
| Type | Description |
|---|---|
LayoutMismatch
|
The models' parameters do not correspond one to one. |
Source code in src/easyreflectometry/contrasts.py
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | |
follows(parameter, leader)
Whether parameter is a plain equality tie to leader.
Source code in src/easyreflectometry/contrasts.py
355 356 357 358 359 360 361 362 363 | |
tie_corresponding(copy, reference, excluded=frozenset())
Tie every independent parameter of copy to the reference parameter at the same path.
Parameters that are the same object, have no counterpart or are listed in
excluded (by id) are left alone. Returns the parameters tied.
Source code in src/easyreflectometry/contrasts.py
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | |
snapshot(parameter)
The state :func:restore gives back to parameter (a tie replaces its value, bounds and uncertainty).
Source code in src/easyreflectometry/contrasts.py
260 261 262 263 264 265 266 267 268 | |
restore(parameter, state)
Source code in src/easyreflectometry/contrasts.py
271 272 273 274 275 276 277 | |