Ranging data
Where Roi
is the central container for positional data, RangeCollection
is the central container for mass/charge ranging data. This contains the range data in an accessible format for both the user and for APAV facilities that use mass ranging. The RangeCollection
container manages many (or few) Range
objects for each range.
A single mass/charge range
The Range
object defines a single half-open interval on the mass spectrum, and assigns it an Ion
.
Note
All ranging activities in APAV involving an interval on the mass spectrum, take the interval as a half-open interval. If the interval goes from mass m0 to mass m1, then the interval is [m0, m1) where m = m0 is included but m = m1 is not.
To create a range for O2 on the interval [31.5, 33):
>>> import apav as ap
>>> O2 = ap.Range("O2", (31.5, 33))
>>> print(O2)
Range: O2, Min: 31.5, Max: 33, Vol: 1, Color: (0, 0, 0)
The lower and upper limits can be modified:
>>> O2.lower = 31
>>> print(O2)
Range: O2, Min: 31, Max: 33, Vol: 1, Color: (0, 0, 0)
But the lower value cannot be set equal, or above the upper value and vice versa:
>>> O2.lower = 40
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-11-fdbbc8818585> in <module>
----> 1 o2.lower = 40
~\PycharmProjects\apav\apav\core\range.py in lower(self, new)
85 validate.positive_number(new)
86 if new >= self._upper:
---> 87 raise ValueError(f"Lower bound for {self.composition} ({new}) cannot be >= upper bound ({self.upper})")
88 self._lower = new
89
ValueError: Lower bound for O2 (40) cannot be >= upper bound (33)
The interval on the mass spectrum can be retrieved:
>>> O2.interval
(31, 33)
We can test whether or not 2 ranges intersect:
>>> O2 = ap.Range("O2", (31.5, 33)
>>> Cu = ap.Range("Cu", (30, 31))
>>> O2.intersects(Cu)
False
>>> Cu2 = ap.Range("Cu", (30, 32))
>>> O2.intersects(Cu2)
True
Remembering a Range
interval is half-open:
>>> O2 = ap.Range("O2", (31.5, 33)
>>> Cu = ap.Range("Cu", (30, 31.5))
>>> O2.intersects(Cu)
False
Other properties can be found in the API reference.
Collections of ranges
The RangeCollection
is responsible for containing and operating on a collection of Range
instances. Typically, this class is constructed from a file via RangeCollection.from_rng()
or RangeCollection.from_rrng()
for loading data from common *.RNG or *.RRNG range files from IVAS or other software into a RangedCollection
.
Note
The ranged mass spectrum can be visualized using apav.analysis.RangedMassSpectrum
The RangeCollection
can be constructed without any Range
, an empty RangeCollection
can be initialized as simply:
>>> import apav as ap
>>> rng_col = ap.RangedCollection()
Then multiple Range
objects can be added:
>>> rng_col.add(ap.Range("Cu", (30, 31.5)))
>>> rng_col.add(ap.Range("O2", (31.5, 32)))
>>> rng_col.add(ap.Range("Cu", (32, 33)))
>>> print(rng_col)
RangeCollection
Number of ranges: 3
Mass range: 30 - 33
Number of unique elements: 2
Elements: ('Cu', 'O')
Composition Min (Da) Max (Da) Volume Color (RGB 0-1)
------------- ---------- ---------- -------- -----------------
Cu 30 31.5 1 (0, 0, 0)
O2 31.5 32 1 (0, 0, 0)
Cu 32 33 1 (0, 0, 0)
Alternatively the Range
objects can be passed into the constructor:
>>> rngs = [ap.Range("Cu", (30, 31.5)),
ap.Range("O2", (31.5, 32)),
ap.Range("Cu", (32, 33))]
>>> rng_col = ap.RangeCollection(rngs)
There cannot be overlapping ranges in a RangeCollection
:
>>> rng_col.add(ap.Range("O2", (32.5, 34)))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-19-bc12e9d521c5> in <module>
----> 1 rng_col.add(ap.Range("O2", (32.5, 34)))
~\PycharmProjects\apav\apav\core\range.py in add(self, new)
315 for r in self.ranges:
316 if r.intersects(new):
--> 317 raise ValueError("Mass ranges cannot coincide")
318 self._ranges.append(new)
319
ValueError: Mass ranges cannot coincide
If a mass Range
needs to be modified, it can be removed and a new range added. Modifying the first copper range to start at 28:
>>> rng_col.remove_by_mass(30)
>>> rng_col.add(ap.Range("Cu", (28, 31.5)))
RangeCollection
Number of ranges: 3
Mass range: 28 - 33
Number of unique elements: 2
Elements: O, Cu
Composition Min (Da) Max (Da) Volume Color (RGB 0-1)
------------- ---------- ---------- -------- -----------------
Cu 28 31.5 1 (0, 0, 0)
O2 31.5 32 1 (0, 0, 0)
Cu 32 33 1 (0, 0, 0)
Or see RangeCollection.replace()
.