kwcoco.sensorchan_spec module¶
This is an extension of kwcoco.channel_spec
, which augments channel
information with an associated sensor attribute. Eventually, this will entirely
replace the channel spec.
Example
>>> # xdoctest: +REQUIRES(module:lark)
>>> # hack for 3.6
>>> from kwcoco import sensorchan_spec
>>> import kwcoco
>>> kwcoco.SensorChanSpec = sensorchan_spec.SensorChanSpec
>>> self = kwcoco.SensorChanSpec.coerce('sensor0:B1|B8|B8a|B10|B11,sensor1:B11|X.2|Y:2:6,sensor2:r|g|b|disparity|gauss|B8|B11,sensor3:r|g|b|flowx|flowy|distri|B10|B11')
>>> self.normalize()
- class kwcoco.sensorchan_spec.SensorSpec(spec)[source]¶
Bases:
NiceRepr
A simple wrapper for sensors in case we want to do anything fancy with them later. For now they are just a string.
- class kwcoco.sensorchan_spec.SensorChanSpec(spec: str)[source]¶
Bases:
NiceRepr
The public facing API for the sensor / channel specification
Example
>>> # xdoctest: +REQUIRES(module:lark) >>> from kwcoco.sensorchan_spec import SensorChanSpec >>> self = SensorChanSpec('(L8,S2):BGR,WV:BGR,S2:nir,L8:land.0:4') >>> s1 = self.normalize() >>> s2 = self.concise() >>> streams = self.streams() >>> print(s1) >>> print(s2) >>> print('streams = {}'.format(ub.repr2(streams, sv=1, nl=1))) L8:BGR,S2:BGR,WV:BGR,S2:nir,L8:land.0|land.1|land.2|land.3 (L8,S2,WV):BGR,L8:land:4,S2:nir streams = [ L8:BGR, S2:BGR, WV:BGR, S2:nir, L8:land.0|land.1|land.2|land.3, ]
Example
>>> # Check with generic sensors >>> # xdoctest: +REQUIRES(module:lark) >>> from kwcoco.sensorchan_spec import SensorChanSpec >>> import kwcoco >>> self = SensorChanSpec('(*):BGR,*:BGR,*:nir,*:land.0:4') >>> self.concise().normalize() >>> s1 = self.normalize() >>> s2 = self.concise() >>> print(s1) >>> print(s2) *:BGR,*:BGR,*:nir,*:land.0|land.1|land.2|land.3 (*,*):BGR,*:(nir,land:4) >>> import kwcoco >>> c = kwcoco.ChannelSpec.coerce('BGR,BGR,nir,land.0:8') >>> c1 = c.normalize() >>> c2 = c.concise() >>> print(c1) >>> print(c2)
Example
>>> # Check empty channels >>> # xdoctest: +REQUIRES(module:lark) >>> from kwcoco.sensorchan_spec import SensorChanSpec >>> import kwcoco >>> print(SensorChanSpec('*:').normalize()) *: >>> print(SensorChanSpec('sen:').normalize()) sen: >>> print(SensorChanSpec('sen:').normalize().concise()) sen: >>> print(SensorChanSpec('sen:').concise().normalize().concise()) sen:
- classmethod coerce(data)[source]¶
Attempt to interpret the data as a channel specification
- Returns
SensorChanSpec
Example
>>> # xdoctest: +REQUIRES(module:lark) >>> from kwcoco.sensorchan_spec import * # NOQA >>> from kwcoco.sensorchan_spec import SensorChanSpec >>> data = SensorChanSpec.coerce(3) >>> assert SensorChanSpec.coerce(data).normalize().spec == '*:u0|u1|u2' >>> data = SensorChanSpec.coerce(3) >>> assert data.spec == 'u0|u1|u2' >>> assert SensorChanSpec.coerce(data).spec == 'u0|u1|u2' >>> data = SensorChanSpec.coerce('u:3') >>> assert data.normalize().spec == '*:u.0|u.1|u.2'
- streams()[source]¶
- Returns
List of sensor-names and fused channel specs
- Return type
List[FusedSensorChanSpec]
- late_fuse(*others)[source]¶
Example
>>> # xdoctest: +REQUIRES(module:lark) >>> import kwcoco >>> from kwcoco import sensorchan_spec >>> import kwcoco >>> kwcoco.SensorChanSpec = sensorchan_spec.SensorChanSpec # hack for 3.6 >>> a = kwcoco.SensorChanSpec.coerce('A|B|C,edf') >>> b = kwcoco.SensorChanSpec.coerce('A12') >>> c = kwcoco.SensorChanSpec.coerce('') >>> d = kwcoco.SensorChanSpec.coerce('rgb') >>> print(a.late_fuse(b).spec) >>> print((a + b).spec) >>> print((b + a).spec) >>> print((a + b + c).spec) >>> print(sum([a, b, c, d]).spec) A|B|C,edf,A12 A|B|C,edf,A12 A12,A|B|C,edf A|B|C,edf,A12 A|B|C,edf,A12,rgb >>> import kwcoco >>> a = kwcoco.SensorChanSpec.coerce('A|B|C,edf').normalize() >>> b = kwcoco.SensorChanSpec.coerce('A12').normalize() >>> c = kwcoco.SensorChanSpec.coerce('').normalize() >>> d = kwcoco.SensorChanSpec.coerce('rgb').normalize() >>> print(a.late_fuse(b).spec) >>> print((a + b).spec) >>> print((b + a).spec) >>> print((a + b + c).spec) >>> print(sum([a, b, c, d]).spec) *:A|B|C,*:edf,*:A12 *:A|B|C,*:edf,*:A12 *:A12,*:A|B|C,*:edf *:A|B|C,*:edf,*:A12,*: *:A|B|C,*:edf,*:A12,*:,*:rgb >>> print((a.late_fuse(b)).concise()) >>> print(((a + b)).concise()) >>> print(((b + a)).concise()) >>> print(((a + b + c)).concise()) >>> print((sum([a, b, c, d])).concise()) *:(A|B|C,edf,A12) *:(A|B|C,edf,A12) *:(A12,A|B|C,edf) *:(A|B|C,edf,A12,) *:(A|B|C,edf,A12,,r|g|b)
Example
>>> # Test multi-arg case >>> import kwcoco >>> a = kwcoco.SensorChanSpec.coerce('A|B|C,edf') >>> b = kwcoco.SensorChanSpec.coerce('A12') >>> c = kwcoco.SensorChanSpec.coerce('') >>> d = kwcoco.SensorChanSpec.coerce('rgb') >>> others = [b, c, d] >>> print(a.late_fuse(*others).spec) >>> print(kwcoco.SensorChanSpec.late_fuse(a, b, c, d).spec) A|B|C,edf,A12,rgb A|B|C,edf,A12,rgb
- matching_sensor(sensor)[source]¶
Get the components corresponding to a specific sensor
- Parameters
sensor (str) – the name of the sensor to match
Example
>>> # xdoctest: +REQUIRES(module:lark) >>> import kwcoco >>> self = kwcoco.SensorChanSpec.coerce('(S1,S2):(a|b|c),S2:c|d|e') >>> sensor = 'S2' >>> new = self.matching_sensor(sensor) >>> print(f'new={new}') new=S2:a|b|c,S2:c|d|e >>> print(self.matching_sensor('S1')) S1:a|b|c >>> print(self.matching_sensor('S3')) S3:
- property chans¶
Returns the channel-only spec, ONLY if all of the sensors are the same
Example
>>> # xdoctest: +REQUIRES(module:lark) >>> import kwcoco >>> self = kwcoco.SensorChanSpec.coerce('(S1,S2):(a|b|c),S2:c|d|e') >>> import pytest >>> with pytest.raises(Exception): >>> self.chans >>> print(self.matching_sensor('S1').chans.spec) >>> print(self.matching_sensor('S2').chans.spec) a|b|c a|b|c,c|d|e
- class kwcoco.sensorchan_spec.FusedSensorChanSpec(sensor, chans)[source]¶
Bases:
SensorChanSpec
A single sensor a corresponding fused channels.
- property chans¶
- property spec¶
- class kwcoco.sensorchan_spec.SensorChanNode(sensor, chan)[source]¶
Bases:
object
TODO: just replace this with the spec class itself?
- property spec¶
- class kwcoco.sensorchan_spec.FusedChanNode(chan)[source]¶
Bases:
object
TODO: just replace this with the spec class itself?
Example
s = FusedChanNode(‘a|b|c.0|c.1|c.2’) c = s.concise() print(s) print(c)
- property spec¶
- class kwcoco.sensorchan_spec.SensorChanTransformer(concise_channels=1, concise_sensors=1)[source]¶
Bases:
Transformer
Given a parsed tree for a sensor-chan spec, can transform it into useful forms.
Todo
Make the classes that hold the underlying data more robust such that they either use the existing channel spec or entirely replace it. (probably the former). Also need to add either a FusedSensorChan node that is restircted to only a single sensor and group of fused channels.
- kwcoco.sensorchan_spec.normalize_sensor_chan(spec)[source]¶
Example
>>> # xdoctest: +REQUIRES(module:lark) >>> from kwcoco.sensorchan_spec import * # NOQA >>> spec = 'L8:mat:4,L8:red,S2:red,S2:forest|brush,S2:mat.0|mat.1|mat.2|mat.3' >>> r1 = normalize_sensor_chan(spec) >>> spec = 'L8:r|g|b,L8:r|g|b' >>> r2 = normalize_sensor_chan(spec) >>> print(f'r1={r1}') >>> print(f'r2={r2}') r1=L8:mat.0|mat.1|mat.2|mat.3,L8:red,S2:red,S2:forest|brush,S2:mat.0|mat.1|mat.2|mat.3 r2=L8:r|g|b,L8:r|g|b
- kwcoco.sensorchan_spec.concise_sensor_chan(spec)[source]¶
Example
>>> # xdoctest: +REQUIRES(module:lark) >>> from kwcoco.sensorchan_spec import * # NOQA >>> spec = 'L8:mat.0|mat.1|mat.2|mat.3,L8:red,S2:red,S2:forest|brush,S2:mat.0|mat.1|mat.2|mat.3' >>> concise_spec = concise_sensor_chan(spec) >>> normed_spec = normalize_sensor_chan(concise_spec) >>> concise_spec2 = concise_sensor_chan(normed_spec) >>> assert concise_spec2 == concise_spec >>> print(concise_spec) (L8,S2):(mat:4,red),S2:forest|brush