or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

array-creation.mdbinning-histogramming.mdcoordinate-systems.mdcore-data-structures.mdindex.mdinput-output.mdmathematical-operations.mdreduction-operations.mdscipy-integration.mdshape-operations.mdspatial-operations.mdtesting-utilities.mdunits-system.mdvisualization.md

units-system.mddocs/

0

# Units System

1

2

Comprehensive physical unit system with predefined units, unit conversion, arithmetic operations, and alias management. Scipp's unit system provides automatic unit propagation through all operations, ensuring dimensional consistency and preventing common scientific computing errors.

3

4

## Capabilities

5

6

### Unit Class

7

8

Core unit representation with arithmetic operations and string parsing.

9

10

```python { .api }

11

class Unit:

12

"""Physical unit with arithmetic operations and parsing"""

13

14

def __init__(self, unit_string):

15

"""

16

Create Unit from string representation

17

18

Args:

19

unit_string (str): Unit string (e.g., 'm', 'kg*m/s^2', 'mm/s')

20

21

Examples:

22

Unit('m') # meter

23

Unit('kg*m/s^2') # force unit (Newton)

24

Unit('mm') # millimeter

25

Unit('1/s') # frequency unit

26

"""

27

28

def __mul__(self, other):

29

"""Multiply units: m * s -> m*s"""

30

31

def __truediv__(self, other):

32

"""Divide units: m / s -> m/s"""

33

34

def __pow__(self, exponent):

35

"""Raise unit to power: m^2 for area"""

36

37

def __eq__(self, other):

38

"""Check unit equality"""

39

40

def __str__(self):

41

"""String representation of unit"""

42

43

def __repr__(self):

44

"""Detailed string representation"""

45

```

46

47

### Unit Conversion

48

49

Functions for converting between compatible units and checking dimensional consistency.

50

51

```python { .api }

52

def to_unit(x, unit):

53

"""

54

Convert variable to specified unit

55

56

Args:

57

x (Variable or DataArray): Input with units

58

unit (Unit or str): Target unit

59

60

Returns:

61

Variable or DataArray: Converted to target unit

62

63

Raises:

64

UnitError: If units are incompatible

65

"""

66

```

67

68

### Predefined Units

69

70

Common physical units available as module constants.

71

72

```python { .api }

73

# Dimensionless

74

dimensionless: Unit # Dimensionless quantity

75

one: Unit # Alias for dimensionless

76

77

# Length units

78

m: Unit # meter

79

mm: Unit # millimeter

80

angstrom: Unit # angstrom (10^-10 m)

81

82

# Time units

83

s: Unit # second

84

us: Unit # microsecond

85

ns: Unit # nanosecond

86

87

# Mass units

88

kg: Unit # kilogram

89

90

# Temperature units

91

K: Unit # kelvin

92

93

# Angle units

94

rad: Unit # radian

95

deg: Unit # degree

96

97

# Energy units

98

meV: Unit # millielectronvolt

99

100

# Count units

101

counts: Unit # count unit for discrete quantities

102

103

# Special units

104

default_unit: Unit # Marker for default unit behavior

105

```

106

107

### Unit Aliases

108

109

Management system for custom unit aliases and shortcuts.

110

111

```python { .api }

112

class UnitAliases:

113

"""Manager for unit aliases and shortcuts"""

114

115

def __setitem__(self, alias, unit):

116

"""

117

Define a new unit alias

118

119

Args:

120

alias (str): Alias name

121

unit (str or Unit or Variable): Unit definition

122

123

Raises:

124

ValueError: If unit already has an alias

125

"""

126

127

def __delitem__(self, alias):

128

"""Remove an existing alias"""

129

130

def clear(self):

131

"""Remove all aliases"""

132

133

def scoped(self, **kwargs):

134

"""

135

Context manager for temporary aliases

136

137

Args:

138

**kwargs: Mapping from alias names to units

139

140

Returns:

141

Context manager for temporary aliases

142

"""

143

144

def keys(self):

145

"""Iterator over alias names"""

146

147

def values(self):

148

"""Iterator over aliased units"""

149

150

def items(self):

151

"""Iterator over (alias, unit) pairs"""

152

153

# Global alias manager instance

154

aliases: UnitAliases

155

```

156

157

## Usage Examples

158

159

### Basic Unit Operations

160

161

```python

162

import scipp as sc

163

164

# Create variables with units

165

length = sc.scalar(5.0, unit='m')

166

time = sc.scalar(2.0, unit='s')

167

168

# Unit arithmetic through operations

169

velocity = length / time # Automatically gets 'm/s' unit

170

area = length * length # Automatically gets 'm^2' unit

171

172

# Check units

173

print(velocity.unit) # 'm/s'

174

print(area.unit) # 'm^2'

175

176

# Unit compatibility checking

177

try:

178

length + time # Will raise UnitError - incompatible units

179

except sc.UnitError as e:

180

print(f"Cannot add length and time: {e}")

181

```

182

183

### Working with Predefined Units

184

185

```python

186

# Use predefined units

187

distance = sc.array(dims=['x'], values=[1, 2, 3], unit=sc.units.m)

188

temperature = sc.array(dims=['sensor'], values=[273, 298, 373], unit=sc.units.K)

189

190

# Angle calculations with proper units

191

angles = sc.linspace('angle', 0, 2*3.14159, 100, unit=sc.units.rad)

192

angles_deg = sc.linspace('angle', 0, 360, 100, unit=sc.units.deg)

193

194

# Convert between angle units

195

angles_converted = sc.to_unit(angles_deg, sc.units.rad)

196

197

# Energy units for scientific applications

198

energies = sc.array(dims=['detector'], values=[1, 5, 10, 50], unit=sc.units.meV)

199

200

# Counting statistics

201

detector_counts = sc.array(dims=['bin'], values=[100, 150, 80], unit=sc.units.counts)

202

```

203

204

### Unit Conversion

205

206

```python

207

# Convert between compatible units

208

length_m = sc.scalar(1000, unit='mm')

209

length_converted = sc.to_unit(length_m, 'm') # Result: 1.0 m

210

211

# Convert complex units

212

force = sc.scalar(10, unit='kg*m/s^2') # Newton

213

force_in_base = sc.to_unit(force, 'kg*m/s^2') # Same unit

214

215

# Temperature conversion (if supported)

216

temp_celsius = sc.scalar(25, unit='degC')

217

# temp_kelvin = sc.to_unit(temp_celsius, 'K') # Would be 298.15 K

218

```

219

220

### Custom Unit Aliases

221

222

```python

223

# Define custom aliases for convenience

224

sc.units.aliases['speed'] = 'm/s'

225

sc.units.aliases['pressure'] = 'kg/(m*s^2)'

226

227

# Use aliases in calculations

228

velocity = sc.scalar(10, unit='speed')

229

print(velocity.unit) # Will display as 'speed'

230

231

# Temporary aliases with context manager

232

with sc.units.aliases.scoped(temp='K', dist='mm'):

233

temperature = sc.scalar(300, unit='temp')

234

position = sc.scalar(5.2, unit='dist')

235

236

# Aliases are automatically removed after context

237

```

238

239

### Advanced Unit Manipulations

240

241

```python

242

# Create complex derived units

243

acceleration = sc.scalar(9.81, unit='m/s^2')

244

mass = sc.scalar(2.0, unit='kg')

245

force = mass * acceleration # Result: kg*m/s^2 (Newton)

246

247

# Work with dimensionless quantities

248

ratio = sc.scalar(0.75, unit=sc.units.dimensionless)

249

percentage = ratio * 100 # Still dimensionless

250

251

# Unit exponentiation

252

volume = sc.pow(length, 3) # m^3

253

print(volume.unit) # 'm^3'

254

255

# Complex unit expressions

256

power = force * velocity # kg*m^2/s^3 (Watt)

257

energy = power * time # kg*m^2/s^2 (Joule)

258

```

259

260

### Scientific Units in Practice

261

262

```python

263

import numpy as np

264

265

# Neutron scattering data with proper units

266

wavelength = sc.array(dims=['detector'], values=[1.8, 2.0, 2.2], unit=sc.units.angstrom)

267

energy = sc.array(dims=['detector'], values=[25.3, 20.4, 16.7], unit=sc.units.meV)

268

269

# Scattering angle calculation

270

scattering_angles = sc.linspace('angle', 0, 180, 181, unit=sc.units.deg)

271

q_vector = 4 * sc.sin(scattering_angles / 2) / wavelength # Momentum transfer

272

273

# Time-of-flight calculations

274

distance = sc.scalar(10.0, unit=sc.units.m) # Sample-detector distance

275

velocity = sc.sqrt(2 * energy / sc.scalar(1.67e-27, unit='kg')) # Neutron velocity

276

time_of_flight = distance / velocity # Automatically in seconds

277

278

# Statistical analysis with count data

279

raw_counts = sc.array(dims=['bin'], values=[120, 98, 156, 89], unit=sc.units.counts)

280

measurement_time = sc.scalar(300, unit=sc.units.s)

281

count_rate = raw_counts / measurement_time # counts/s

282

283

# Uncertainty propagation with units

284

count_uncertainty = sc.sqrt(raw_counts) # Poisson statistics

285

rate_uncertainty = count_uncertainty / measurement_time # Propagated uncertainty

286

```

287

288

### Unit Error Handling

289

290

```python

291

# Unit compatibility checking

292

try:

293

length = sc.scalar(5, unit='m')

294

time = sc.scalar(2, unit='s')

295

invalid = length + time # Incompatible units

296

except sc.UnitError as e:

297

print(f"Unit error: {e}")

298

299

# Dimensionless function requirements

300

try:

301

angle_with_units = sc.scalar(1.57, unit='rad')

302

result = sc.exp(angle_with_units) # Should fail - exp requires dimensionless

303

except sc.UnitError as e:

304

print(f"Function requires dimensionless input: {e}")

305

306

# Correct usage

307

dimensionless_value = sc.scalar(1.57, unit=sc.units.dimensionless)

308

result = sc.exp(dimensionless_value) # Works correctly

309

```