or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

chart-composition.mdchart-creation.mdconfiguration-theming.mddata-handling.mdencodings-channels.mdexpressions-conditions.mdindex.mdparameters-interactions.mdrendering-output.mdtransformations.md

expressions-conditions.mddocs/

0

# Expressions & Conditions

1

2

Expression system for calculated fields, conditional logic, and dynamic values using Vega expression language with mathematical, string, and logical operations. Expressions enable sophisticated data transformations and conditional visualizations.

3

4

## Capabilities

5

6

### Expression API

7

8

Comprehensive expression interface providing access to mathematical, string, logical, and utility functions from the Vega expression language.

9

10

```python { .api }

11

class ExpressionAPI:

12

"""Main expression interface with extensive function library."""

13

14

# Constants

15

NaN: float

16

PI: float

17

E: float

18

LN2: float

19

LN10: float

20

LOG2E: float

21

LOG10E: float

22

SQRT1_2: float

23

SQRT2: float

24

25

# Mathematical functions

26

def abs(self, value):

27

"""Absolute value."""

28

29

def acos(self, value):

30

"""Arccosine in radians."""

31

32

def asin(self, value):

33

"""Arcsine in radians."""

34

35

def atan(self, value):

36

"""Arctangent in radians."""

37

38

def atan2(self, y, x):

39

"""Two-argument arctangent."""

40

41

def ceil(self, value):

42

"""Ceiling (round up to integer)."""

43

44

def clamp(self, value, min_val, max_val):

45

"""Clamp value to range [min, max]."""

46

47

def cos(self, value):

48

"""Cosine."""

49

50

def exp(self, value):

51

"""Exponential function (e^x)."""

52

53

def floor(self, value):

54

"""Floor (round down to integer)."""

55

56

def log(self, value):

57

"""Natural logarithm."""

58

59

def max(self, *values):

60

"""Maximum of values."""

61

62

def min(self, *values):

63

"""Minimum of values."""

64

65

def pow(self, base, exponent):

66

"""Power function (base^exponent)."""

67

68

def random(self):

69

"""Random number [0, 1)."""

70

71

def round(self, value):

72

"""Round to nearest integer."""

73

74

def sin(self, value):

75

"""Sine."""

76

77

def sqrt(self, value):

78

"""Square root."""

79

80

def tan(self, value):

81

"""Tangent."""

82

83

# String functions

84

def indexof(self, string, substring):

85

"""Index of substring in string."""

86

87

def join(self, array, separator=None):

88

"""Join array elements into string."""

89

90

def lastindexof(self, string, substring):

91

"""Last index of substring in string."""

92

93

def length(self, string_or_array):

94

"""Length of string or array."""

95

96

def lower(self, string):

97

"""Convert to lowercase."""

98

99

def pad(self, string, length, character=None, align=None):

100

"""Pad string to specified length."""

101

102

def regexp(self, string, pattern, flags=None):

103

"""Test string against regular expression."""

104

105

def replace(self, string, pattern, replacement):

106

"""Replace substring or pattern."""

107

108

def slice(self, string_or_array, start, end=None):

109

"""Extract substring or subarray."""

110

111

def split(self, string, separator, limit=None):

112

"""Split string into array."""

113

114

def substring(self, string, start, end=None):

115

"""Extract substring."""

116

117

def trim(self, string):

118

"""Remove leading/trailing whitespace."""

119

120

def truncate(self, string, length, align=None, ellipsis=None):

121

"""Truncate string to specified length."""

122

123

def upper(self, string):

124

"""Convert to uppercase."""

125

126

# Array functions

127

def extent(self, array):

128

"""Min and max values of array."""

129

130

def indexof_array(self, array, value):

131

"""Index of value in array."""

132

133

def lastindexof_array(self, array, value):

134

"""Last index of value in array."""

135

136

def peek(self, array):

137

"""Last element of array."""

138

139

def reverse(self, array):

140

"""Reverse array."""

141

142

def sort(self, array):

143

"""Sort array."""

144

145

# Date/time functions

146

def now(self):

147

"""Current timestamp."""

148

149

def datetime(self, year, month=None, day=None, hour=None, minute=None, second=None, millisecond=None):

150

"""Create date from components."""

151

152

def date(self, datetime):

153

"""Extract date part."""

154

155

def day(self, datetime):

156

"""Day of month (1-31)."""

157

158

def dayofyear(self, datetime):

159

"""Day of year (1-366)."""

160

161

def year(self, datetime):

162

"""Year."""

163

164

def quarter(self, datetime):

165

"""Quarter (0-3)."""

166

167

def month(self, datetime):

168

"""Month (0-11)."""

169

170

def hours(self, datetime):

171

"""Hours (0-23)."""

172

173

def minutes(self, datetime):

174

"""Minutes (0-59)."""

175

176

def seconds(self, datetime):

177

"""Seconds (0-59)."""

178

179

def milliseconds(self, datetime):

180

"""Milliseconds (0-999)."""

181

182

def time(self, datetime):

183

"""Time in milliseconds since epoch."""

184

185

def timezoneoffset(self, datetime):

186

"""Timezone offset in minutes."""

187

188

def utc(self, year, month=None, day=None, hour=None, minute=None, second=None, millisecond=None):

189

"""Create UTC date."""

190

191

# Logical functions

192

def if_(self, test, then, else_=None):

193

"""Conditional expression."""

194

195

def isArray(self, value):

196

"""Test if value is array."""

197

198

def isBoolean(self, value):

199

"""Test if value is boolean."""

200

201

def isDate(self, value):

202

"""Test if value is date."""

203

204

def isDefined(self, value):

205

"""Test if value is defined."""

206

207

def isFinite(self, value):

208

"""Test if value is finite number."""

209

210

def isNaN(self, value):

211

"""Test if value is NaN."""

212

213

def isNumber(self, value):

214

"""Test if value is number."""

215

216

def isObject(self, value):

217

"""Test if value is object."""

218

219

def isRegExp(self, value):

220

"""Test if value is regular expression."""

221

222

def isString(self, value):

223

"""Test if value is string."""

224

225

def isValid(self, value):

226

"""Test if value is valid (not null, undefined, or NaN)."""

227

228

def inrange(self, value, min_val, max_val):

229

"""Test if value is in range [min, max]."""

230

231

# Format functions

232

def format(self, value, specifier):

233

"""Format number with d3-format specifier."""

234

235

def timeFormat(self, datetime, specifier):

236

"""Format date with d3-time-format specifier."""

237

238

def timeParse(self, string, specifier):

239

"""Parse date string with d3-time-format specifier."""

240

241

def utcFormat(self, datetime, specifier):

242

"""Format UTC date."""

243

244

def utcParse(self, string, specifier):

245

"""Parse UTC date string."""

246

247

# Type conversion functions

248

def toBoolean(self, value):

249

"""Convert to boolean."""

250

251

def toDate(self, value):

252

"""Convert to date."""

253

254

def toNumber(self, value):

255

"""Convert to number."""

256

257

def toString(self, value):

258

"""Convert to string."""

259

260

# Statistical functions

261

def sampleNormal(self, mu=None, sigma=None):

262

"""Sample from normal distribution."""

263

264

def cumulativeNormal(self, value, mu=None, sigma=None):

265

"""Cumulative normal distribution."""

266

267

def densityNormal(self, value, mu=None, sigma=None):

268

"""Normal probability density."""

269

270

def quantileNormal(self, p, mu=None, sigma=None):

271

"""Normal quantile function."""

272

273

def sampleLogNormal(self, mu=None, sigma=None):

274

"""Sample from log-normal distribution."""

275

276

def cumulativeLogNormal(self, value, mu=None, sigma=None):

277

"""Cumulative log-normal distribution."""

278

279

def densityLogNormal(self, value, mu=None, sigma=None):

280

"""Log-normal probability density."""

281

282

def quantileLogNormal(self, p, mu=None, sigma=None):

283

"""Log-normal quantile function."""

284

285

def sampleUniform(self, min_val=None, max_val=None):

286

"""Sample from uniform distribution."""

287

288

def cumulativeUniform(self, value, min_val=None, max_val=None):

289

"""Cumulative uniform distribution."""

290

291

def densityUniform(self, value, min_val=None, max_val=None):

292

"""Uniform probability density."""

293

294

def quantileUniform(self, p, min_val=None, max_val=None):

295

"""Uniform quantile function."""

296

297

# Color functions

298

def rgb(self, r, g, b):

299

"""Create RGB color."""

300

301

def hsl(self, h, s, l):

302

"""Create HSL color."""

303

304

def lab(self, l, a, b):

305

"""Create Lab color."""

306

307

def hcl(self, h, c, l):

308

"""Create HCL color."""

309

310

def luminance(self, color):

311

"""Calculate color luminance."""

312

313

def contrast(self, color1, color2):

314

"""Calculate color contrast ratio."""

315

316

# Geographic functions

317

def geoArea(self, feature):

318

"""Geographic area of feature."""

319

320

def geoBounds(self, feature):

321

"""Geographic bounds of feature."""

322

323

def geoCentroid(self, feature):

324

"""Geographic centroid of feature."""

325

326

def geoContains(self, feature, point):

327

"""Test if feature contains point."""

328

329

# Global expression instance

330

expr = ExpressionAPI()

331

```

332

333

### Datum Reference

334

335

Object for referencing fields in the current data record within expressions.

336

337

```python { .api }

338

class DatumExpression:

339

"""Reference to current data record fields."""

340

341

def __getattr__(self, field_name):

342

"""Access field by name: datum.fieldname"""

343

344

def __getitem__(self, field_name):

345

"""Access field by key: datum['field name']"""

346

347

# Global datum instance

348

datum = DatumExpression()

349

```

350

351

### Conditional Functions

352

353

Functions for creating conditional logic and branching expressions.

354

355

```python { .api }

356

def condition(predicate, if_true, if_false=None):

357

"""

358

Create conditional encoding.

359

360

Parameters:

361

- predicate: Test condition (parameter, selection, or expression)

362

- if_true: Value/encoding when condition is true

363

- if_false: Value/encoding when condition is false

364

365

Returns:

366

dict: Conditional specification

367

"""

368

369

def when(predicate):

370

"""

371

Start conditional chain.

372

373

Parameters:

374

- predicate: Test condition

375

376

Returns:

377

ChainedWhen: Object for method chaining

378

"""

379

380

class ChainedWhen:

381

def then(self, value):

382

"""Value when condition is true."""

383

384

class Then:

385

def when(self, predicate):

386

"""Additional condition."""

387

388

def otherwise(self, value):

389

"""Final fallback value."""

390

```

391

392

## Usage Examples

393

394

### Mathematical Expressions

395

396

```python

397

import altair as alt

398

399

# Basic mathematical operations

400

chart = alt.Chart(data).mark_circle().encode(

401

x='x:Q',

402

y='y:Q',

403

size=alt.expr('sqrt(datum.value) * 10')

404

)

405

406

# Complex calculations

407

chart = alt.Chart(data).mark_point().encode(

408

x='x:Q',

409

y='y:Q'

410

).transform_calculate(

411

distance=alt.expr('sqrt(pow(datum.x - 50, 2) + pow(datum.y - 50, 2))'),

412

angle=alt.expr('atan2(datum.y - 50, datum.x - 50) * 180 / PI')

413

)

414

```

415

416

### String Manipulations

417

418

```python

419

# String processing

420

chart = alt.Chart(data).mark_text().encode(

421

x='x:Q',

422

y='y:Q',

423

text=alt.expr('upper(slice(datum.name, 0, 3))')

424

).transform_calculate(

425

short_name=alt.expr('length(datum.name) > 10 ? truncate(datum.name, 10) : datum.name'),

426

initials=alt.expr('split(datum.name, " ")[0][0] + split(datum.name, " ")[1][0]')

427

)

428

```

429

430

### Date/Time Operations

431

432

```python

433

# Date calculations

434

chart = alt.Chart(data).mark_line().encode(

435

x='date:T',

436

y='value:Q'

437

).transform_calculate(

438

year=alt.expr('year(datum.date)'),

439

quarter=alt.expr('quarter(datum.date)'),

440

day_of_year=alt.expr('dayofyear(datum.date)'),

441

is_weekend=alt.expr('day(datum.date) == 0 || day(datum.date) == 6')

442

)

443

```

444

445

### Conditional Logic

446

447

```python

448

# Simple conditional

449

chart = alt.Chart(data).mark_circle().encode(

450

x='x:Q',

451

y='y:Q',

452

color=alt.expr('datum.value > 50 ? "red" : "blue"')

453

)

454

455

# Complex conditional chain

456

chart = alt.Chart(data).mark_circle().encode(

457

x='x:Q',

458

y='y:Q',

459

color=alt.when(

460

alt.datum.value > 80

461

).then(

462

alt.value('red')

463

).when(

464

alt.datum.value > 60

465

).then(

466

alt.value('orange')

467

).when(

468

alt.datum.value > 40

469

).then(

470

alt.value('yellow')

471

).otherwise(

472

alt.value('blue')

473

)

474

)

475

```

476

477

### Statistical Expressions

478

479

```python

480

# Statistical calculations

481

chart = alt.Chart(data).mark_circle().encode(

482

x='x:Q',

483

y='y:Q',

484

size=alt.expr('densityNormal(datum.value, 50, 15) * 1000')

485

).transform_calculate(

486

z_score=alt.expr('(datum.value - 50) / 15'),

487

percentile=alt.expr('cumulativeNormal(datum.value, 50, 15)')

488

)

489

```

490

491

### Color Expressions

492

493

```python

494

# Color calculations

495

chart = alt.Chart(data).mark_circle().encode(

496

x='x:Q',

497

y='y:Q',

498

color=alt.expr('hsl(datum.value * 360 / 100, 0.7, 0.5)'),

499

stroke=alt.expr('contrast("white", hsl(datum.value * 360 / 100, 0.7, 0.5)) > 4.5 ? "black" : "white"')

500

)

501

```

502

503

### Validation and Type Checking

504

505

```python

506

# Data validation expressions

507

chart = alt.Chart(data).mark_circle().encode(

508

x='x:Q',

509

y='y:Q',

510

opacity=alt.expr('isValid(datum.value) && isFinite(datum.value) ? 1.0 : 0.3')

511

).transform_filter(

512

alt.expr('isDefined(datum.x) && isDefined(datum.y)')

513

)

514

```

515

516

### Parameter Integration

517

518

```python

519

# Using parameters in expressions

520

threshold = alt.param(value=50)

521

multiplier = alt.param(value=2)

522

523

chart = alt.Chart(data).add_params(

524

threshold, multiplier

525

).mark_circle().encode(

526

x='x:Q',

527

y='y:Q',

528

size=alt.expr(f'max(10, min(500, datum.value * {multiplier}))'),

529

color=alt.expr(f'datum.value > {threshold} ? "red" : "blue"')

530

)

531

```

532

533

## Types

534

535

```python { .api }

536

from typing import Union, Any, Dict

537

538

# Expression types

539

ExpressionString = str

540

ExpressionRef = Dict[str, Any]

541

Expression = Union[ExpressionString, ExpressionRef]

542

543

# Conditional types

544

ConditionalPredicate = Union[str, Dict[str, Any]]

545

ConditionalValue = Union[Any, Dict[str, Any]]

546

547

# Datum field reference

548

DatumRef = Union[str, Dict[str, Any]]

549

550

# Function result types

551

BooleanExpression = Expression

552

NumberExpression = Expression

553

StringExpression = Expression

554

DateExpression = Expression

555

ColorExpression = Expression

556

ArrayExpression = Expression

557

```