def test_parse_conc(conc_str, mw, kwargs, parsed, converted, error): from itertools import combinations_with_replacement converted['uM'] = converted['nM'] / 1000 converted['ug/uL'] = converted['ng/uL'] / 1000 with error: assert parse_conc(conc_str, **kwargs) == parsed with error: assert parse_conc_nM(conc_str, mw, **kwargs) == converted['nM'] with error: assert parse_conc_uM(conc_str, mw, **kwargs) == converted['uM'] with error: assert parse_conc_ng_uL(conc_str, mw, **kwargs) == converted['ng/uL'] with error: assert parse_conc_ug_uL(conc_str, mw, **kwargs) == converted['ug/uL'] for unit, value in converted.items(): q_given = parsed mw_given = mw if unit != q_given.unit else None q_expected = Quantity(value, unit) q_converted = convert_conc_unit(q_given, mw_given, unit) assert q_converted == pytest.approx( q_expected, abs=Quantity(1e-6, unit), )
def _parse_quantity(quantity_str, expected_units, default_unit, unit_type): try: if default_unit: quantity = Quantity.from_string_or_float(quantity_str, default_unit) else: quantity = Quantity.from_string(quantity_str) except ValueError: raise ParseError( "can't interpret {quantity_str!r} as a {unit_type}", quantity_str=quantity_str, unit_type=unit_type, ) from None if quantity.unit not in expected_units: raise ParseError( lambda e: f"can't interpret {e.quantity_str!r} as a {unit_type}, did you mean '{Quantity(e.quantity.value, did_you_mean(e.quantity.unit, e.expected_units))}'?", quantity=quantity, quantity_str=quantity_str, expected_units=expected_units, unit_type=unit_type, ) return quantity
def parse_conc(conc_str): if not conc_str: return None try: conc = float(conc_str) except ValueError: pass else: return Quantity(conc, 'ng/µL') try: return Quantity.from_string(conc_str) except ValueError: pass raise ValueError(f"cannot parse {conc_str!r} as a concentration")
def parse_time(time_str, default_unit=None): # First, try parsing the time using a custom syntax, e.g. '1m30': time_pattern = r'(\d+)([hm])(\d+)' if m := re.fullmatch(time_pattern, time_str): value = 60 * int(m.group(1)) + int(m.group(3)) unit = {'h': 'm', 'm': 's'}[m.group(2)] return Quantity(value, unit)
def is_numeric(x): from stepwise import Quantity try: float(x) except ValueError: pass else: return True try: Quantity.from_anything(x) except ValueError: pass else: return True return False
def from_product(cls, product): maker = cls() args = product.maker_args maker.products = [product] maker.dependencies = set() maker.vendor = args['vendor'] maker.label_products = False if 'seq' in args: maker.product_seqs = [args['seq']] if 'conc' in args: maker.product_conc = Quantity.from_string(args['conc']) if 'volume' in args: maker.product_volume = Quantity.from_string(args['volume']) if 'molecule' in args: maker.product_molecule = args['molecule'] return maker
def _calc_mass_ug(self): try: stock_conc_ug_uL = convert_conc_unit(self.stock_conc, self.mw, 'µg/µL') except ParseError: err = ConfigError(sample=self) err.brief = "can't calculate mass in µg for sample: {sample.name!r}" err.info += "MW: {sample.mw}" err.info += "stock conc: {sample.stock_conc}" err.info += "volume: {sample.stock_conc}" raise err else: return Quantity(stock_conc_ug_uL.value * self.volume_uL, 'µg')
def from_product(cls, product): maker = cls() args = product.maker_args maker.products = [product] if 'deps' in args: maker.dependencies = {x.strip() for x in args['deps'].split(',')} if 'seq' in args: maker._product_seqs = [args['seq']] if 'conc' in args: maker._product_concs = [Quantity.from_string(args['conc'])] if 'volume' in args: maker._product_volumes = [Quantity.from_string(args['volume'])] if 'molecule' in args: maker._product_molecules = [args['molecule']] if 'cwd' in args: cwd = expanduser(args['cwd']) elif 'expt' in args: import exmemo root = expanduser(args.get('project', getcwd())) work = exmemo.Workspace.from_path(root) expt = work.pick_experiment(args['expt']) cwd = expt.root_dir.resolve() else: cwd = getcwd() load_cmd = ' '.join(args.by_index[1:]) if not load_cmd: raise QueryError("no stepwise command specified", culprit=product) with cd(cwd): maker.protocol = stepwise.load(load_cmd).protocol maker._protocol_str = maker.protocol.format_text() return maker
def get_product_conc(self): return Quantity(200, 'ng/µL')
def approx_Q(x): q = Quantity.from_anything(x) return pytest.approx(q, abs=Quantity(1e-6, q.unit))
def parse_conc(x): return Quantity.from_string_or_float(x, 'µg/µL')
def get_product_conc(self): min_pmol = min( x.pmol for x in self.reaction.iter_reagents_by_flag('fragment')) return Quantity(1e3 * min_pmol / self.volume_uL, 'nM')
def get_product_volume(self): return Quantity(self.elute_volume_uL, 'µL')
def ng_uL(x): return Quantity(x, 'ng/µL')
def get_product_conc(self): return Quantity.from_string(self.conc)
def get_product_conc(self): return Quantity(self.product_conc_ng_uL, 'ng/µL')