def _parse(self, value): """ Parse media type string into components :attr value: Media type value e.g. text/html;level=2;q=0.4 :type value: str, bytes :returns: MediaType instance """ full_type, parameters = padded_split(value.strip(), ';', 1) full_type = '*/*' if full_type == '*' else full_type type, subtype = padded_split(full_type, '/', 1) if type is None or subtype is None: raise ParseError() # type can only be a wildcard with subtype if type == '*' and subtype != '*': raise ParseError() def fix_param(x): key, value = padded_split(x, '=', 1) if not key or not value: raise ParseError() if str.isdigit(value): value = int(value) return (key, value) parameters = OrderedDict([ fix_param(param) for param in parameters.split(";") ]) if parameters else {} kwargs = dict(type=type, subtype=subtype, parameters=parameters) return kwargs
def ionic_strength(molalities, charges=None, units=None, substances=None, substance_factory=Substance.from_formula, warn=True): """ Calculates the ionic strength Parameters ---------- molalities: array_like or dict Optionally with unit (amount / mass). when dict: mapping substance key to molality. charges: array_like Charge of respective ion, taken for substances when None. units: object (optional, default: None) Attributes accessed: molal. substances: dict, optional Mapping of substance keys to Substance instances (used when molalities is a dict). substance_factory: callback Used if `substances` is a string. warn: bool Issue a warning if molalities violates net charge neutrality. Examples -------- >>> ionic_strength([1e-3, 3e-3], [3, -1]) == .5 * (9 + 3) * 1e-3 True >>> ionic_strength({'Mg+2': 6, 'PO4-3': 4}) 30.0 """ tot = None if charges is None: if substances is None: substances = ' '.join(molalities.keys()) if isinstance(substances, str): substances = OrderedDict([(k, substance_factory(k)) for k in substances.split()]) charges, molalities = zip(*[(substances[k].charge, v) for k, v in molalities.items()]) if len(molalities) != len(charges): raise ValueError("molalities and charges of different lengths") for b, z in zip(molalities, charges): if tot is None: tot = b * z**2 else: tot += b * z**2 if warn: net = None for b, z in zip(molalities, charges): if net is None: net = b * z else: net += b * z if not allclose(net, tot * 0, atol=tot * 1e-14): warnings.warn("Molalities not charge neutral: %s" % str(net)) return tot / 2
def __init__(self, word, columns): word = OrderedDict(zip(columns, word.split())) self.idx = int(word.pop('idx')) self.token = word.pop('token') self.lemma = word.pop('lemma') self.tag = word.pop('tag') self._extras = word.copy()
def ionic_strength(molalities, charges=None, units=None, substances=None, substance_factory=Substance.from_formula, warn=True): """ Calculates the ionic strength Parameters ---------- molalities: array_like or dict Optionally with unit (amount / mass). when dict: mapping substance key to molality. charges: array_like Charge of respective ion, taken for substances when None. units: object (optional, default: None) Attributes accessed: molal. substances: dict, optional Mapping of substance keys to Substance instances (used when molalities is a dict). substance_factory: callback Used if `substances` is a string. warn: bool Issue a warning if molalities violates net charge neutrality. Examples -------- >>> ionic_strength([1e-3, 3e-3], [3, -1]) == .5 * (9 + 3) * 1e-3 True >>> ionic_strength({'Mg+2': 6, 'PO4-3': 4}) 30.0 """ tot = None if charges is None: if substances is None: substances = ' '.join(molalities.keys()) if isinstance(substances, str): substances = OrderedDict([(k, substance_factory(k)) for k in substances.split()]) charges, molalities = zip(*[(substances[k].charge, v) for k, v in molalities.items()]) if len(molalities) != len(charges): raise ValueError("molalities and charges of different lengths") for b, z in zip(molalities, charges): if tot is None: tot = b * z**2 else: tot += b * z**2 if warn: net = None for b, z in zip(molalities, charges): if net is None: net = b * z else: net += b * z if not allclose(net, tot*0, atol=tot*1e-14): warnings.warn("Molalities not charge neutral: %s" % str(net)) return tot/2
def _simplify_feature_value(self, name, value): """Return simplified and more pythonic feature values.""" if name == 'prefix': channel_modes, channel_chars = value.split(')') channel_modes = channel_modes[1:] # [::-1] to reverse order and go from lowest to highest privs value = OrderedDict(list(zip(channel_modes, channel_chars))[::-1]) return value elif name == 'chanmodes': value = value.split(',') return value elif name == 'targmax': max_available = {} for sort in value.split(','): command, limit = sort.split(':') command = command.casefold() max_available[command] = limit_to_number(limit) return max_available elif name == 'chanlimit': limit_available = {} for sort in value.split(','): chan_types, limit = sort.split(':') for prefix in chan_types: limit_available[prefix] = limit_to_number(limit) return limit_available elif name in _limits: value = limit_to_number(value) return value else: return value
def compact_etable_plot(df, title=None, size=2.2, col_wrap=8, xticks=np.arange(0, 7), yticks=np.arange(-2, 3), xlim=(0.0, 6.0), ylim=(-2.5, 2.5), marker='', ms=0, lw=1, aspect=0.7, scores=None): if not scores: scores = OrderedDict( fa_atr='green', fa_rep='red', fa_sol='blue', fa_elec='orange', lk_ball_wtd='purple', score='black', ) elif isinstance(scores, str): colors = 'black red green blue orange purple'.split() tmp = OrderedDict() for i, k in enumerate(scores.split()): tmp[k] = colors[i] scores = tmp sns.set(style="ticks") grid = sns.FacetGrid(df, col='t', size=size, col_wrap=col_wrap, aspect=aspect) grid.map(plt.axhline, y=0, ls=":", c='.5') for score, col in list(scores.items()): grid.map(plt.plot, 'dist', score, marker=marker, lw=lw, ms=ms, color=col) grid.set(xticks=xticks, yticks=yticks, xlim=xlim, ylim=ylim) grid.fig.tight_layout(h_pad=1, w_pad=0) if title: grid.fig.suptitle(title) return grid
def get_dropout(self, conv_drop='', blocks=0): if conv_drop.startswith('all-'): dropout = float(conv_drop.split('-')[1]) conv_drop = OrderedDict() for i in range(1, blocks + 1): conv_drop.setdefault(i, dropout) return conv_drop elif conv_drop.startswith('bet-'): import numpy as np dropout = conv_drop.split('-') dropout = [float(dropout[1]), float(dropout[2])] dropout = np.arange(dropout[0], dropout[1], (dropout[1] - dropout[0]) / blocks) conv_drop = OrderedDict() for i in range(1, blocks + 1): conv_drop.setdefault(i, round(dropout[i - 1], 3)) return conv_drop
def ionic_strength(molalities, charges=None, b0=1, units=None, substances=None, substance_factory=Substance.from_formula): """ Calculates the ionic strength Parameters ---------- molalities: array_like or dict Optionally with unit (amount / mass). when dict: mapping substance key to molality. charges: array_like Charge of respective ion, taken for substances when None. units: object (optional, default: None) Attributes accessed: molal. substances: dict, optional Mapping of substance keys to Substance instances (used when molalities is a dict). substance_factory: callback Used if `substances` is a string. Examples -------- >>> ionic_strength([1e-3, 3e-3], [3, -1]) == .5 * (9 + 3) * 1e-3 True >>> ionic_strength({'Mg+2': 6, 'PO4-3': 4}) 30.0 """ tot = 0 if charges is None: if substances is None: substances = ' '.join(molalities.keys()) if isinstance(substances, str): substances = OrderedDict([(k, substance_factory(k)) for k in substances.split()]) charges, molalities = zip(*[(substances[k].charge, v) for k, v in molalities.items()]) if len(molalities) != len(charges): raise ValueError("molalities and charges of different lengths") for b, z in zip(molalities, charges): tot += b * z**2 return tot / 2
def ionic_strength(molalities, charges=None, b0=1, units=None, substances=None, substance_factory=Substance.from_formula): """ Calculates the ionic strength Parameters ---------- molalities: array_like or dict Optionally with unit (amount / mass). when dict: mapping substance key to molality. charges: array_like Charge of respective ion, taken for substances when None. units: object (optional, default: None) Attributes accessed: molal. substances: dict, optional Mapping of substance keys to Substance instances (used when molalities is a dict). substance_factory: callback Used if `substances` is a string. Examples -------- >>> ionic_strength([1e-3, 3e-3], [3, -1]) == .5 * (9 + 3) * 1e-3 True >>> ionic_strength({'Mg+2': 6, 'PO4-3': 4}) 30.0 """ tot = 0 if charges is None: if substances is None: substances = ' '.join(molalities.keys()) if isinstance(substances, str): substances = OrderedDict([(k, substance_factory(k)) for k in substances.split()]) charges, molalities = zip(*[(substances[k].charge, v) for k, v in molalities.items()]) if len(molalities) != len(charges): raise ValueError("molalities and charges of different lengths") for b, z in zip(molalities, charges): tot += b * z**2 return tot/2
def parse_ascconv(ascconv_str, str_delim='"'): '''Parse the 'ASCCONV' format from `input_str`. Parameters ---------- ascconv_str : str The string we are parsing str_delim : str, optional String delimiter. Typically '"' or '""' Returns ------- prot_dict : OrderedDict Meta data pulled from the ASCCONV section. attrs : OrderedDict Any attributes stored in the 'ASCCONV BEGIN' line Raises ------ AsconvParseError A line of the ASCCONV section could not be parsed. ''' attrs, content = ASCCONV_RE.match(ascconv_str).groups() attrs = OrderedDict((tuple(x.split('=')) for x in attrs.split())) # Normalize string start / end markers to something Python understands content = content.replace(str_delim, '"""').replace("\\", "\\\\") # Use Python's own parser to parse modified ASCCONV assignments tree = ast.parse(content) prot_dict = OrderedDict() for assign in tree.body: atoms = assign2atoms(assign) obj_to_index, key = obj_from_atoms(atoms, prot_dict) obj_to_index[key] = _get_value(assign) return prot_dict, attrs
class SMParser(object): TOKENS = ( 'TITLE', 'SUBTITLE', 'ARTIST', 'TITLETRANSLIT', 'SUBTITLETRANSLIT', 'ARTISTTRANSLIT', 'CREDIT', 'BANNER', 'BACKGROUND', 'LYRICSPATH', 'CDTITLE', 'MUSIC', 'OFFSET', 'SAMPLESTART', 'SAMPLELENGTH', 'SELECTABLE', 'DISPLAYBPM', 'BPMS', 'STOPS', 'BGCHANGES', ) BOM_CHAR = '\xef\xbb\xbf' SECTION_HEADER = '//--' STYLES = ('dance-single', 'dance-double') DIFFICULTIES = ('Easy', 'Medium', 'Hard') FOOT_RATINGS = range(1, 11) STEP_TYPES = '0123' def __init__(self, simfile): self.charts = {} self._simfile = simfile self._parse_header_tokens() self._parse_sections() def _parse_header_tokens(self): for line in StringIO(self._simfile): try: token, value = (line.strip() .replace(self.BOM_CHAR, '') .split(':')[:2]) except ValueError: continue if token[1:] in self.TOKENS: setattr(self, token[1:], value.strip(';')) if token[1:] == 'BPMS': self.BPMS = OrderedDict([measure.split('=') for measure in self.BPMS.split(',')]) elif line.startswith(self.SECTION_HEADER): break def _parse_sections(self): def _dos_to_unix(s): return s.replace('\r', '') parsing = False parsing_measure = False measure_counter = 1 for line in StringIO(self._simfile): line = _dos_to_unix(line.strip()) if not parsing and not line.startswith(self.SECTION_HEADER): continue elif line.startswith(self.SECTION_HEADER): # parse section header parsing = True style = 'Double' if 'double' in line else 'Single' self.charts[style] = self.charts.setdefault(style, {}) elif parsing and ':' in line: # Parse #INFO section value = line.split(':')[0] if value in self.DIFFICULTIES: difficulty = value self.charts[style][difficulty] = {} elif value in self.FOOT_RATINGS: self.charts[style][difficulty]['foot rating'] = value elif ',' in value: self.charts[style][difficulty]['?'] = value elif all((c in self.STEP_TYPES for c in line)) and line != '': # parse individual measures if parsing_measure: measure['steps'].append(line) else: measure = {'measure': measure_counter, 'steps': [line]} parsing_measure = True self.charts[style][difficulty]['chart'] = self.charts[style][ difficulty].setdefault('chart', []) elif line.startswith(',') and parsing_measure: # stop parsing measure self.charts[style][difficulty]['chart'].append(measure) parsing_measure = False measure_counter += 1 elif line.startswith(';') and parsing: # stop parsing section parsing, parsing_measure = False, False measure_counter = 1
def balance_stoichiometry(reactants, products, substances=None, substance_factory=Substance.from_formula, parametric_symbols=None, underdetermined=True, allow_duplicates=False): """ Balances stoichiometric coefficients of a reaction Parameters ---------- reactants : iterable of reactant keys products : iterable of product keys substances : OrderedDict or string or None Mapping reactant/product keys to instances of :class:`Substance`. substance_factory : callback parametric_symbols : generator of symbols Used to generate symbols for parametric solution for under-determined system of equations. Default is numbered "x-symbols" starting from 1. underdetermined : bool Allows to find a non-unique solution (in addition to a constant factor across all terms). Set to ``False`` to disallow (raise ValueError) on e.g. "C + O2 -> CO + CO2". Set to ``None`` if you want the symbols replaced so that the coefficients are the smallest possible positive (non-zero) integers. allow_duplicates : bool If False: raises an excpetion if keys appear in both ``reactants`` and ``products``. Examples -------- >>> ref = {'C2H2': 2, 'O2': 3}, {'CO': 4, 'H2O': 2} >>> balance_stoichiometry({'C2H2', 'O2'}, {'CO', 'H2O'}) == ref True >>> ref2 = {'H2': 1, 'O2': 1}, {'H2O2': 1} >>> balance_stoichiometry('H2 O2'.split(), ['H2O2'], 'H2 O2 H2O2') == ref2 True >>> reac, prod = 'CuSCN KIO3 HCl'.split(), 'CuSO4 KCl HCN ICl H2O'.split() >>> Reaction(*balance_stoichiometry(reac, prod)).string() '4 CuSCN + 7 KIO3 + 14 HCl -> 4 CuSO4 + 7 KCl + 4 HCN + 7 ICl + 5 H2O' >>> balance_stoichiometry({'Fe', 'O2'}, {'FeO', 'Fe2O3'}, underdetermined=False) Traceback (most recent call last): ... ValueError: The system was under-determined >>> r, p = balance_stoichiometry({'Fe', 'O2'}, {'FeO', 'Fe2O3'}) >>> list(set.union(*[v.free_symbols for v in r.values()])) [x1] >>> b = balance_stoichiometry({'Fe', 'O2'}, {'FeO', 'Fe2O3'}, underdetermined=None) >>> b == ({'Fe': 3, 'O2': 2}, {'FeO': 1, 'Fe2O3': 1}) True >>> d = balance_stoichiometry({'C', 'CO'}, {'C', 'CO', 'CO2'}, underdetermined=None, allow_duplicates=True) >>> d == ({'CO': 2}, {'C': 1, 'CO2': 1}) True Returns ------- balanced reactants : dict balanced products : dict """ import sympy from sympy import ( MutableDenseMatrix, gcd, zeros, linsolve, numbered_symbols, Wild, Symbol, Integer, Tuple, preorder_traversal as pre ) _intersect = sorted(set.intersection(*map(set, (reactants, products)))) if _intersect: if allow_duplicates: if underdetermined is not None: raise NotImplementedError("allow_duplicates currently requires underdetermined=None") if set(reactants) == set(products): raise ValueError("cannot balance: reactants and products identical") # For each duplicate, try to drop it completely: for dupl in _intersect: try: result = balance_stoichiometry( [sp for sp in reactants if sp != dupl], [sp for sp in products if sp != dupl], substances=substances, substance_factory=substance_factory, underdetermined=underdetermined, allow_duplicates=True) except Exception: continue else: return result for perm in product(*[(False, True)]*len(_intersect)): # brute force (naive) r = set(reactants) p = set(products) for remove_reac, dupl in zip(perm, _intersect): if remove_reac: r.remove(dupl) else: p.remove(dupl) try: result = balance_stoichiometry( r, p, substances=substances, substance_factory=substance_factory, parametric_symbols=parametric_symbols, underdetermined=underdetermined, allow_duplicates=False) except ValueError: continue else: return result else: raise ValueError("Failed to remove duplicate keys: %s" % _intersect) else: raise ValueError("Substances on both sides: %s" % str(_intersect)) if substances is None: substances = OrderedDict([(k, substance_factory(k)) for k in chain(reactants, products)]) if isinstance(substances, str): substances = OrderedDict([(k, substance_factory(k)) for k in substances.split()]) if type(reactants) == set: # we don't want isinstance since it might be "OrderedSet" reactants = sorted(reactants) if type(products) == set: products = sorted(products) subst_keys = list(reactants) + list(products) cks = Substance.composition_keys(substances.values()) if parametric_symbols is None: parametric_symbols = numbered_symbols('x', start=1, integer=True, positive=True) # ?C2H2 + ?O2 -> ?CO + ?H2O # Ax = 0 # A: x: # # C2H2 O2 CO H2O # C -2 0 1 0 x0 = 0 # H -2 0 0 2 x1 0 # O 0 -2 1 1 x2 0 # x3 def _get(ck, sk): return substances[sk].composition.get(ck, 0) * (-1 if sk in reactants else 1) for ck in cks: # check that all components are present on reactant & product sides for rk in reactants: if substances[rk].composition.get(ck, 0) != 0: break else: any_pos = any(substances[pk].composition.get(ck, 0) > 0 for pk in products) any_neg = any(substances[pk].composition.get(ck, 0) < 0 for pk in products) if any_pos and any_neg: pass # negative and positive parts among products, no worries else: raise ValueError("Component '%s' not among reactants" % ck) for pk in products: if substances[pk].composition.get(ck, 0) != 0: break else: any_pos = any(substances[pk].composition.get(ck, 0) > 0 for pk in reactants) any_neg = any(substances[pk].composition.get(ck, 0) < 0 for pk in reactants) if any_pos and any_neg: pass # negative and positive parts among reactants, no worries else: raise ValueError("Component '%s' not among products" % ck) A = MutableDenseMatrix([[_get(ck, sk) for sk in subst_keys] for ck in cks]) symbs = list(reversed([next(parametric_symbols) for _ in range(len(subst_keys))])) sol, = linsolve((A, zeros(len(cks), 1)), symbs) wi = Wild('wi', properties=[lambda k: not k.has(Symbol)]) cd = reduce(gcd, [1] + [1/m[wi] for m in map( lambda n: n.match(symbs[-1]/wi), pre(sol)) if m is not None]) sol = sol.func(*[arg/cd for arg in sol.args]) def remove(cont, symb, remaining): subsd = dict(zip(remaining/symb, remaining)) cont = cont.func(*[(arg/symb).expand().subs(subsd) for arg in cont.args]) if cont.has(symb): raise ValueError("Bug, please report an issue at https://github.com/bjodah/chempy") return cont done = False for idx, symb in enumerate(symbs): for expr in sol: iterable = expr.args if expr.is_Add else [expr] for term in iterable: if term.is_number: done = True break if done: break if done: break for expr in sol: if (expr/symb).is_number: sol = remove(sol, symb, MutableDenseMatrix(symbs[idx+1:])) break for symb in symbs: cd = 1 for expr in sol: iterable = expr.args if expr.is_Add else [expr] for term in iterable: if term.is_Mul and term.args[0].is_number and term.args[1] == symb: cd = gcd(cd, term.args[0]) if cd != 1: sol = sol.func(*[arg.subs(symb, symb/cd) for arg in sol.args]) integer_one = 1 # need 'is' check, SyntaxWarning when checking against literal if underdetermined is integer_one: from ._release import __version__ if int(__version__.split('.')[1]) > 6: warnings.warn( # deprecated because comparison with ``1`` problematic (True==1) ("Pass underdetermined == None instead of ``1`` (depreacted since 0.7.0," " will_be_missing_in='0.9.0')"), ChemPyDeprecationWarning) underdetermined = None if underdetermined is None: sol = Tuple(*[Integer(x) for x in _solve_balancing_ilp_pulp(A)]) fact = gcd(sol) sol = MutableDenseMatrix([e/fact for e in sol]).reshape(len(sol), 1) sol /= reduce(gcd, sol) if 0 in sol: raise ValueError("Superfluous species given.") if underdetermined: if any(x == sympy.nan for x in sol): raise ValueError("Failed to balance reaction") else: for x in sol: if len(x.free_symbols) != 0: raise ValueError("The system was under-determined") if not all(residual == 0 for residual in A * sol): raise ValueError("Failed to balance reaction") def _x(k): coeff = sol[subst_keys.index(k)] return int(coeff) if underdetermined is None else coeff return ( OrderedDict([(k, _x(k)) for k in reactants]), OrderedDict([(k, _x(k)) for k in products]) )
def gdx_to_df(gdx_file, symbol, type='L', domain_info=None): def __get_set(gdx_file, set_name): if sys.platform in ['linux2', 'darwin']: proc = subprocess.Popen(['gdxdump %s Symb=%s Format=csv NoHeader' % (gdx_file, set_name), ""], stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT) elif sys.platform in ['win32']: proc = subprocess.Popen(['gdxdump', '%s' % gdx_file, 'Symb=%s' % set_name, 'Format=csv', 'NoHeader', ''], stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT) else: raise GamsAddOnException('ERROR {platform} not handled'.format(platform=sys.platform)) (out, err) = proc.communicate() try: csv_in = csv.reader(out.split('\n'), delimiter=',') return [int(row[0]) for row in csv_in if row] except ValueError: csv_in = csv.reader(out.split('\n'), delimiter=',') return [row[0] for row in csv_in if row] def __int(v): try: return int(v) except ValueError: return v def __float(v): try: return float(v) except ValueError: return v if domain_info is None: domain_info = DomainInfo(gdx_file) if symbol not in domain_info.symbols: raise GamsAddOnException('"%s" not in Domain of "%s"' % (symbol, gdx_file)) sets = domain_info.get_sets(symbol) index = OrderedDict() if sets is None: index['Idx'] = [1] sets = ['Idx'] else: for s in sets: if s in domain_info.symbols: set_values = __get_set(gdx_file, s) set_name = s while set_name in index.keys(): set_name = set_name + s index[set_name] = set_values elif s == '*': index[s] = ['---PLACEHOLDER---'] else: raise GamsAddOnException('Set "%s" of "%s" not in Domain of "%s"' % (s, symbol, gdx_file)) # print index.values()+[['l', 'm']] if domain_info.symbols[symbol][0] in ['Var', 'Equ']: multi_index = MultiIndex.from_product([index[s] for s in sets] + [['L', 'M', 'LO', 'UP', 'SCALE']]) df = DataFrame(0.0, index=multi_index, columns=[symbol]) df.index.names = index.keys() + ['Type'] else: multi_index = MultiIndex.from_product([index[s] for s in index.keys()]) df = DataFrame(0.0, index=multi_index, columns=[symbol]) df.index.names = index.keys() if sys.platform in ['linux2', 'darwin']: proc = subprocess.Popen(['gdxdump %s Symb=%s FilterDef=N' % (gdx_file, symbol), ""], stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT) elif sys.platform in ['win32']: proc = subprocess.Popen(['gdxdump', '%s' % gdx_file, 'Symb=%s' % symbol, 'FilterDef=N', ''], stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT) else: raise GamsAddOnException('ERROR {platform} not handled'.format(platform=sys.platform)) (out, err) = proc.communicate() out = out.replace('\n', '') content = re.search(r'/.*/', out).group(0)[1:-1].replace('\'', '').strip().split(',') if err: raise GamsAddOnException('ERROR: {err}'.format(err=err)) elif content is []: raise GamsAddOnException('ERROR: No content found for {symbol}'.format(symbol=symbol)) else: indices = [] values = [] if domain_info.symbols[symbol][0] in ['Set']: df[symbol] = False for data in content: if '.' in data: indices.append(tuple([__int(d) for d in data.strip().split('.')])) else: indices.append(__int(data.strip())) values.append(True) else: for data in content: data = data.strip().split(' ') if len(data) == 1: indices.append(1) values.append(__float(data[0])) else: index = data[0] if '.' in index: index = tuple([__int(i) for i in index.split('.')]) indices.append(index) elif index in ['L', 'M', 'UP', 'LO', 'SCALE']: index = (1, index) indices.append(index) else: indices.append(__int(index)) values.append(__float(data[1])) try: # print 'NAME:', symbol, indices, values, len(values), df if len(values) == 1 and values[0] == '': return df else: # df.loc[indices, symbol] = values # print df.index df.loc[indices, symbol] = values # for i,idx in enumerate(indices): # df.loc[idx, symbol] = values[i] except KeyError as ke: print 'Warning', ke if '*' in df.index.names: for i, idx in enumerate(indices): df.loc[idx, symbol] = True df.drop('---PLACEHOLDER---', inplace=True) if type is not None and 'Type' in df.index.names: # print type # print df.head() return df.query('Type == "%s"' % type) else: return df
class SMParser(object): TOKENS = ( 'TITLE', 'SUBTITLE', 'ARTIST', 'TITLETRANSLIT', 'SUBTITLETRANSLIT', 'ARTISTTRANSLIT', 'CREDIT', 'BANNER', 'BACKGROUND', 'LYRICSPATH', 'CDTITLE', 'MUSIC', 'OFFSET', 'SAMPLESTART', 'SAMPLELENGTH', 'SELECTABLE', 'DISPLAYBPM', 'BPMS', 'STOPS', 'BGCHANGES', ) BOM_CHAR = '\xef\xbb\xbf' SECTION_HEADER = '//--' STYLES = ('dance-single', 'dance-double') DIFFICULTIES = ('Easy', 'Medium', 'Hard') FOOT_RATINGS = range(1, 11) STEP_TYPES = '0123' def __init__(self, simfile): self.charts = {} self._simfile = simfile self._parse_header_tokens() self._parse_sections() def _parse_header_tokens(self): for line in StringIO(self._simfile): try: token, value = (line.strip().replace(self.BOM_CHAR, '').split(':')[:2]) except ValueError: continue if token[1:] in self.TOKENS: setattr(self, token[1:], value.strip(';')) if token[1:] == 'BPMS': self.BPMS = OrderedDict( [measure.split('=') for measure in self.BPMS.split(',')]) elif line.startswith(self.SECTION_HEADER): break def _parse_sections(self): def _dos_to_unix(s): return s.replace('\r', '') parsing = False parsing_measure = False measure_counter = 1 for line in StringIO(self._simfile): line = _dos_to_unix(line.strip()) if not parsing and not line.startswith(self.SECTION_HEADER): continue elif line.startswith(self.SECTION_HEADER): # parse section header parsing = True style = 'Double' if 'double' in line else 'Single' self.charts[style] = self.charts.setdefault(style, {}) elif parsing and ':' in line: # Parse #INFO section value = line.split(':')[0] if value in self.DIFFICULTIES: difficulty = value self.charts[style][difficulty] = {} elif value in self.FOOT_RATINGS: self.charts[style][difficulty]['foot rating'] = value elif ',' in value: self.charts[style][difficulty]['?'] = value elif all((c in self.STEP_TYPES for c in line)) and line != '': # parse individual measures if parsing_measure: measure['steps'].append(line) else: measure = {'measure': measure_counter, 'steps': [line]} parsing_measure = True self.charts[style][difficulty]['chart'] = self.charts[style][ difficulty].setdefault('chart', []) elif line.startswith(',') and parsing_measure: # stop parsing measure self.charts[style][difficulty]['chart'].append(measure) parsing_measure = False measure_counter += 1 elif line.startswith(';') and parsing: # stop parsing section parsing, parsing_measure = False, False measure_counter = 1
def varsplit(ref, alts, info, frmt, gts): """ Split a variant with multiple alternate alleles into separate records to aid in annotation. >>> n = varsplit('TA', ['TAA', 'TAAA', 'T'], 'AF=0.2,0.3,0.1;KKKK', ... 'GT:DP:PL', ['1/2:81:281,5,9,58,0,115,338,46,116,809', ... '0/0:86:0,30,323,31,365,483,38,291,325,567']) >>> next(n) ('TA', 'TAA', 'KKKK;ORIG_ALLELES=TA/TAA,TAAA,T;ORIG_ALLELE_i=1', 'GT:PL', ['1/.:281,5,9', '0/0:0,30,323']) >>> next(n) ('TA', 'TAAA', 'KKKK;ORIG_ALLELES=TA/TAA,TAAA,T;ORIG_ALLELE_i=2', 'GT:PL', ['./1:281,58,115', '0/0:0,31,483']) >>> next(n) ('TA', 'T', 'KKKK;ORIG_ALLELES=TA/TAA,TAAA,T;ORIG_ALLELE_i=3', 'GT:PL', ['./.:281,338,809', '0/0:0,38,567']) # test new snp eff ANN= field >>> n = varsplit('G', ['A', 'C', 'T'], ... 'ANN=A|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.|||||||', ... 'GT:DP:PL', ['1/2:81:281,5,9,58,0,115,338,46,116,809']) >>> next(n) ('G', 'A', 'ANN=A|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||,A|.|.|.|.|.|.|.|.|.||||||;ORIG_ALLELES=G/A,C,T;ORIG_ALLELE_i=1', 'GT:PL', ['1/.:281,5,9']) >>> next(n) ('G', 'C', 'ANN=C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||,C|.|.|.|.|.|.|.|.|.||||||;ORIG_ALLELES=G/A,C,T;ORIG_ALLELE_i=2', 'GT:PL', ['./1:281,58,115']) >>> next(n) ('G', 'T', 'ANN=T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.||||||,T|.|.|.|.|.|.|.|.|.|||||||;ORIG_ALLELES=G/A,C,T;ORIG_ALLELE_i=3', 'GT:PL', ['./.:281,338,809']) >>> next(n) Traceback (most recent call last): ... StopIteration # test older snpeff EFF= field >>> n = varsplit('TTCC', ['T', 'TTCCTCC'], 'EFF=CODON_CHANGE_PLUS_CODON_DELETION(MODERATE||gaggaa/gaa|EE28E|196|MICAL3|protein_coding|CODING|ENST00000498573|1|1|WARNING_TRANSCRIPT_NO_START_CODON),CODON_CHANGE_PLUS_CODON_DELETION(MODERATE||gaggaa/gaa|EE4E|188|MICAL3|protein_coding|CODING|ENST00000578984|1|1|WARNING_TRANSCRIPT_INCOMPLETE),CODON_CHANGE_PLUS_CODON_DELETION(MODERATE||gaggaa/gaa|EE998E|2002|MICAL3|protein_coding|CODING|ENST00000441493|21|1),CODON_INSERTION(MODERATE||gag/gaGGAg|E28EE|196|MICAL3|protein_coding|CODING|ENST00000498573|1|2|WARNING_TRANSCRIPT_NO_START_CODON),CODON_INSERTION(MODERATE||gag/gaGGAg|E4EE|188|MICAL3|protein_coding|CODING|ENST00000578984|1|2|WARNING_TRANSCRIPT_INCOMPLETE),CODON_INSERTION(MODERATE||gag/gaGGAg|E998EE|2002|MICAL3|protein_coding|CODING|ENST00000441493|21|2),DOWNSTREAM(MODIFIER||2412||966|MICAL3|protein_coding|CODING|ENST00000400561||2),DOWNSTREAM(MODIFIER||2415||966|MICAL3|protein_coding|CODING|ENST00000400561||1),DOWNSTREAM(MODIFIER||2422||966|MICAL3|protein_coding|CODING|ENST00000444520||2),DOWNSTREAM(MODIFIER||2425||966|MICAL3|protein_coding|CODING|ENST00000444520||1)', 'GT:DP:PL', ['1/2:81:281,5,9,58,0,115,338']) >>> next(n) ('TTCC', 'T', 'EFF=CODON_CHANGE_PLUS_CODON_DELETION(MODERATE||gaggaa/gaa|EE28E|196|MICAL3|protein_coding|CODING|ENST00000498573|1|1|WARNING_TRANSCRIPT_NO_START_CODON),CODON_CHANGE_PLUS_CODON_DELETION(MODERATE||gaggaa/gaa|EE4E|188|MICAL3|protein_coding|CODING|ENST00000578984|1|1|WARNING_TRANSCRIPT_INCOMPLETE),CODON_CHANGE_PLUS_CODON_DELETION(MODERATE||gaggaa/gaa|EE998E|2002|MICAL3|protein_coding|CODING|ENST00000441493|21|1),DOWNSTREAM(MODIFIER||2415||966|MICAL3|protein_coding|CODING|ENST00000400561||1),DOWNSTREAM(MODIFIER||2425||966|MICAL3|protein_coding|CODING|ENST00000444520||1);ORIG_ALLELES=TTCC/T,TTCCTCC;ORIG_ALLELE_i=1', 'GT:PL', ['1/.:281,5,9']) >>> next(n) ('TTCC', 'TTCCTCC', 'EFF=CODON_INSERTION(MODERATE||gag/gaGGAg|E28EE|196|MICAL3|protein_coding|CODING|ENST00000498573|1|2|WARNING_TRANSCRIPT_NO_START_CODON),CODON_INSERTION(MODERATE||gag/gaGGAg|E4EE|188|MICAL3|protein_coding|CODING|ENST00000578984|1|2|WARNING_TRANSCRIPT_INCOMPLETE),CODON_INSERTION(MODERATE||gag/gaGGAg|E998EE|2002|MICAL3|protein_coding|CODING|ENST00000441493|21|2),DOWNSTREAM(MODIFIER||2412||966|MICAL3|protein_coding|CODING|ENST00000400561||2),DOWNSTREAM(MODIFIER||2422||966|MICAL3|protein_coding|CODING|ENST00000444520||2);ORIG_ALLELES=TTCC/T,TTCCTCC;ORIG_ALLELE_i=2', 'GT:PL', ['./1:281,58,115']) >>> next(n) Traceback (most recent call last): ... StopIteration """ if len(alts) == 1: yield ref, alts[0], infostr(info, ()), frmt, gts raise StopIteration if not isinstance(info, dict): info = OrderedDict((kv[0], (kv[1] if len(kv) > 1 else None)) for kv in (x.split('=') for x in info.split(';'))) fmts = frmt.split(':') gts = [OrderedDict(zip(fmts, x.split(':'))) for x in gts] for i, g in enumerate(gts): if 'GT' in g: gts[i]['__sep'] = "|" if "|" in g['GT'] else "/" gts[i]['GT'] = g['GT'].split(gts[i]['__sep']) for i, alt in enumerate(alts, start=1): if any('GT' in g for g in gts): fixed_genos = fix_genos(gts, i) else: fixed_genos = gts if fixed_genos: fields = [f for f in fixed_genos[0].keys() if f != "__sep"] # ordered else: fields = [] info_sub = fix_info(info, alt, alts) # now we temporarily replace info[field] with ann info_sub['ORIG_ALLELES'] = '%s/%s' % (ref, ",".join(alts)) info_sub['ORIG_ALLELE_i'] = str(i) ret = ref, alt, infostr(info_sub), ":".join(fields), fmt_genos( fixed_genos) yield ret
def balance_stoichiometry(reactants, products, substances=None, substance_factory=Substance.from_formula, parametric_symbols=None, underdetermined=True, allow_duplicates=False): """ Balances stoichiometric coefficients of a reaction Parameters ---------- reactants : iterable of reactant keys products : iterable of product keys substances : OrderedDict or string or None Mapping reactant/product keys to instances of :class:`Substance`. substance_factory : callback parametric_symbols : generator of symbols Used to generate symbols for parametric solution for under-determined system of equations. Default is numbered "x-symbols" starting from 1. underdetermined : bool Allows to find a non-unique solution (in addition to a constant factor across all terms). Set to ``False`` to disallow (raise ValueError) on e.g. "C + O2 -> CO + CO2". Set to ``None`` if you want the symbols replaced so that the coefficients are the smallest possible positive (non-zero) integers. allow_duplicates : bool If False: raises an excpetion if keys appear in both ``reactants`` and ``products``. Examples -------- >>> ref = {'C2H2': 2, 'O2': 3}, {'CO': 4, 'H2O': 2} >>> balance_stoichiometry({'C2H2', 'O2'}, {'CO', 'H2O'}) == ref True >>> ref2 = {'H2': 1, 'O2': 1}, {'H2O2': 1} >>> balance_stoichiometry('H2 O2'.split(), ['H2O2'], 'H2 O2 H2O2') == ref2 True >>> reac, prod = 'CuSCN KIO3 HCl'.split(), 'CuSO4 KCl HCN ICl H2O'.split() >>> Reaction(*balance_stoichiometry(reac, prod)).string() '4 CuSCN + 7 KIO3 + 14 HCl -> 4 CuSO4 + 7 KCl + 4 HCN + 7 ICl + 5 H2O' >>> balance_stoichiometry({'Fe', 'O2'}, {'FeO', 'Fe2O3'}, underdetermined=False) Traceback (most recent call last): ... ValueError: The system was under-determined >>> r, p = balance_stoichiometry({'Fe', 'O2'}, {'FeO', 'Fe2O3'}) >>> list(set.union(*[v.free_symbols for v in r.values()])) [x1] >>> b = balance_stoichiometry({'Fe', 'O2'}, {'FeO', 'Fe2O3'}, underdetermined=None) >>> b == ({'Fe': 3, 'O2': 2}, {'FeO': 1, 'Fe2O3': 1}) True >>> d = balance_stoichiometry({'C', 'CO'}, {'C', 'CO', 'CO2'}, underdetermined=None, allow_duplicates=True) >>> d == ({'CO': 2}, {'C': 1, 'CO2': 1}) True Returns ------- balanced reactants : dict balanced products : dict """ import sympy from sympy import ( MutableDenseMatrix, gcd, zeros, linsolve, numbered_symbols, Wild, Symbol, Integer, Tuple, preorder_traversal as pre ) _intersect = sorted(set.intersection(*map(set, (reactants, products)))) if _intersect: if allow_duplicates: if underdetermined is not None: raise NotImplementedError("allow_duplicates currently requires underdetermined=None") if set(reactants) == set(products): raise ValueError("cannot balance: reactants and products identical") # For each duplicate, try to drop it completely: for dupl in _intersect: try: result = balance_stoichiometry( [sp for sp in reactants if sp != dupl], [sp for sp in products if sp != dupl], substances=substances, substance_factory=substance_factory, underdetermined=underdetermined, allow_duplicates=True) except Exception: continue else: return result for perm in product(*[(False, True)]*len(_intersect)): # brute force (naive) r = set(reactants) p = set(products) for remove_reac, dupl in zip(perm, _intersect): if remove_reac: r.remove(dupl) else: p.remove(dupl) try: result = balance_stoichiometry( r, p, substances=substances, substance_factory=substance_factory, parametric_symbols=parametric_symbols, underdetermined=underdetermined, allow_duplicates=False) except Exception: continue else: return result else: raise ValueError("Failed to remove duplicate keys: %s" % _intersect) else: raise ValueError("Substances on both sides: %s" % str(_intersect)) if substances is None: substances = OrderedDict([(k, substance_factory(k)) for k in chain(reactants, products)]) if isinstance(substances, str): substances = OrderedDict([(k, substance_factory(k)) for k in substances.split()]) if type(reactants) == set: # we don't want isinstance since it might be "OrderedSet" reactants = sorted(reactants) if type(products) == set: products = sorted(products) subst_keys = list(reactants) + list(products) cks = Substance.composition_keys(substances.values()) if parametric_symbols is None: parametric_symbols = numbered_symbols('x', start=1, integer=True, positive=True) # ?C2H2 + ?O2 -> ?CO + ?H2O # Ax = 0 # A: x: # # C2H2 O2 CO H2O # C -2 0 1 0 x0 = 0 # H -2 0 0 2 x1 0 # O 0 -2 1 1 x2 0 # x3 def _get(ck, sk): return substances[sk].composition.get(ck, 0) * (-1 if sk in reactants else 1) for ck in cks: # check that all components are present on reactant & product sides for rk in reactants: if substances[rk].composition.get(ck, 0) != 0: break else: raise ValueError("Component '%s' not among reactants" % ck) for pk in products: if substances[pk].composition.get(ck, 0) != 0: break else: raise ValueError("Component '%s' not among products" % ck) A = MutableDenseMatrix([[_get(ck, sk) for sk in subst_keys] for ck in cks]) symbs = list(reversed([next(parametric_symbols) for _ in range(len(subst_keys))])) sol, = linsolve((A, zeros(len(cks), 1)), symbs) wi = Wild('wi', properties=[lambda k: not k.has(Symbol)]) cd = reduce(gcd, [1] + [1/m[wi] for m in map( lambda n: n.match(symbs[-1]/wi), pre(sol)) if m is not None]) sol = sol.func(*[arg/cd for arg in sol.args]) def remove(cont, symb, remaining): subsd = dict(zip(remaining/symb, remaining)) cont = cont.func(*[(arg/symb).expand().subs(subsd) for arg in cont.args]) if cont.has(symb): raise ValueError("Bug, please report an issue at https://github.com/bjodah/chempy") return cont done = False for idx, symb in enumerate(symbs): for expr in sol: iterable = expr.args if expr.is_Add else [expr] for term in iterable: if term.is_number: done = True break if done: break if done: break for expr in sol: if (expr/symb).is_number: sol = remove(sol, symb, MutableDenseMatrix(symbs[idx+1:])) break for symb in symbs: cd = 1 for expr in sol: iterable = expr.args if expr.is_Add else [expr] for term in iterable: if term.is_Mul and term.args[0].is_number and term.args[1] == symb: cd = gcd(cd, term.args[0]) if cd != 1: sol = sol.func(*[arg.subs(symb, symb/cd) for arg in sol.args]) if underdetermined is 1: from ._release import __version__ if int(__version__.split('.')[1]) > 6: warnings.warn( # deprecated because comparison with ``1`` problematic (True==1) ("Pass underdetermined == None instead of ``1`` (depreacted since 0.7.0," " will_be_missing_in='0.9.0')"), ChemPyDeprecationWarning) underdetermined = None if underdetermined is None: sol = Tuple(*[Integer(x) for x in _solve_balancing_ilp_pulp(A)]) fact = gcd(sol) sol = MutableDenseMatrix([e/fact for e in sol]).reshape(len(sol), 1) sol /= reduce(gcd, sol) if 0 in sol: raise ValueError("Superfluous species given.") if underdetermined: if any(x == sympy.nan for x in sol): raise ValueError("Failed to balance reaction") else: for x in sol: if len(x.free_symbols) != 0: raise ValueError("The system was under-determined") if not all(residual == 0 for residual in A * sol): raise ValueError("Failed to balance reaction") def _x(k): coeff = sol[subst_keys.index(k)] return int(coeff) if underdetermined is None else coeff return ( OrderedDict([(k, _x(k)) for k in reactants]), OrderedDict([(k, _x(k)) for k in products]) )
def read(filename): """Create a |Geoset| instance from a DS9 region file. .. note:: This will break if the region file was not written using `write`! Parameters ---------- filename : str Path to the DS9 region file to be loaded. Returns ------- out : |Geoset| A |Geoset| instance build using the polygons stored in the DS9 region file. """ def parse_ds9_attrs(attrstr, global_attrs=False): attrstr = attrstr + ' junk' if not global_attrs: attrstr = 'junk ' + attrstr j = [0] + [i for i in range(len(attrstr)) if attrstr[i] == '='] + [-1] keys, vals = [], [] for j1, j2 in zip(j[:-1], j[1:]): val, key = attrstr[j1+1:j2].rsplit(' ', 1) if ((val[0], val[-1]) == ('"', '"') or (val[0], val[-1]) == ('{', '}')): val = val[1:-1] keys.append(key) vals.append(val) return zip(keys[:-1], vals[1:]) with open(filename, 'r') as file: lines = file.readlines() geoset = _geoset.Geoset(None) i0, j0, k0 = None, None, None for line in lines: line = line.split('\n')[0] # Skip comments and blank lines: if line.startswith('#') or not line: continue # Parse global attributes: elif line.startswith('global'): attrs = parse_ds9_attrs(line, global_attrs=True) attrs = OrderedDict(attrs) geoset.attrs = attrs # Parse coordinate system: elif line in ['physical', 'fk5']: if geoset.attrs is None: geoset.attrs = OrderedDict() geoset.attrs['coordsys'] = line # Build geoset: elif line.startswith('polygon'): coords, delim, attrs = line.partition('(')[-1].partition(')') coords, attrs = coords.replace(',', ' '), attrs.split('#')[-1] # Make polygon xy = [float(i) for i in coords.split()] x, y = xy[0::2], xy[1::2] poly = geometry.Polygon(zip(x, y)) # Test if polygon is a hole: is_hole = False if 'background' in attrs: is_hole = True attrs = attrs.split('background')[-1] # Get item/geo/poly structure indices: idx_list = parse_ds9_attrs(attrs) for idx in idx_list: tag, n = idx[1].split() n = int(n) if tag == 'item': i = n elif tag == 'geo': j = n elif tag == 'poly': k = n if i != i0: geo = _geoset.Geo(poly) item = _geoset.Item(geo) geoset.items.append(item) elif j != j0: geo = _geoset.Geo(poly) item.geos.append(geo) elif k != k0: geo.geo = geo.geo.union(poly) elif is_hole: geo.geo = geo.geo.difference(poly) i0, j0, k0 = i, j, k return geoset