def register_result(result0, sym, state, keep_provenance=False): """ Enters the quantity that was just calculated into the database :param result0: quantity Q() :param sym: name of the quantity :param state: contains known quantities as ordered dict, along with flags and output """ if not keep_provenance: result0.provenance = [] result0.name = sym[:] if hasattr(result0, 'depth'): del result0.depth if sym in state and '__allowupdate__' not in state.flags: state.printit( '<div style="color: green;">Warning: Updated value of \\(%s\\)</div><br>' % (latex_name(sym))) state[sym] = result0 if '__fracunits__' not in state.flags: for u in result0.units: if u.denominator != 1: #oddly, ints have and floats don't state.printit( '<div style="color: green;">Warning: Units have non-integer exponents %s</div><br>' % u) if "__checkunits__" in state.flags: if len(sym) == 1 or sym[1] in "_0123456789[" or sym[0] == "[": if sym[0] in typicalunits and result0.units != typicalunits[ sym[0]][0]: state.printit( '<div style="color: green;">Warning: \\(%s\\) looks like a %s, but units are strange</div><br>' % (latex_name(sym), typicalunits[sym[0]][1]))
def show_work(result, sym, flags, error=False, addon="", skipsteps=False): """ Shows the steps in getting from formula to calculated value. This function is called not only by calc(), but also by convert_units() and deal_with_errors() to show steps in calculations. :param result: value and provenance of the quantity Q() :param sym: name of the quantity :param flags: Switches that determine how much detail is shown :param error: True if used to show an error in a step of a calculation :param addon: Used when called from convert_units(ConversionIn) :param skipsteps: True when intermediate steps are to be skipped :return: tuple containing detailed output, brief output """ output = [] logput = [] math = not 'plain math' in flags if math: writer = quantities.latex_writer if not "__latex__" in flags: logput.append('''<span style="color:navy; cursor:pointer; font-size:15pt;" onclick="insertAtCaret('commands','%s ', 0)">''' % sym) output.append('''<span style="color:navy; cursor:pointer; font-size:15pt;" onclick="insertAtCaret('commands','%s ', 0)">''' % sym) else: writer = quantities.ascii_writer subs = latex_subs if math else None d = result.setdepth() if math: template1 = "\(%s = %s%s\)<br>" template2 = "<br>\(\\ \\ \\ =%s%s\)<br>" else: template1 = "%s = %s%s" if d <= 0 else "%s = \n = %s%s" template2 = " = %s%s" task = result.steps(-1, writer, subs, ()) # task if '__hidenumbers__' in flags: task = result.steps(-1, quantities.latex_writer, subs) name = latex_name(sym) if math else sym output.append(template1 % (name, task, addon)) logput.append(template1 % (name, task, addon)) if not skipsteps: for dd in range(1, d + 1): if dd == 1: first = result.steps(dd, writer, subs, flags) if '__hidenumbers__' in flags: first = result.steps(dd, quantities.latex_writer, subs, {'__hidenumbers__'}) if first != task: output.append(template2 % (first, addon)) else: output.append(template2 % (result.steps(dd, writer, subs, flags), addon)) # intermediate steps result_str = result.steps(0, writer, subs, flags) # result if '__hideunits__' in flags: task = result.steps(-1, writer, subs, flags) if result_str != task and not error and not ('__hidenumbers__' in flags and d == 0): logput.append(template2 % (result_str, addon)) output.append(template2 % (result_str, addon)) if math and not '__latex__' in flags: logput.append('<br></span>') output.append('<br></span>') return output, logput
def consume_identifier(charlist): cl2 = [] charlist.pop(0) while charlist: if charlist[0] == " ": charlist.pop(0) break cl2.append(charlist.pop(0)) return "\\(%s\\)" % latex_name("".join(cl2))
def consume_identifier(charlist): cl2 = [] charlist.pop(0) while charlist: if charlist[0] == " ": charlist.pop(0) break cl2.append(charlist.pop(0)) space = '' if charlist and charlist[0] in '.,?)' else ' ' return "\\(%s\\)" % latex_name("".join(cl2)) + space
def convert_units(input_type, command, quant, units, state): """ Shows the quantity in different units, either once only ('in') or from now on ('using') :param input_type: Whether conversion is with "using" or "in" :param command: user input :param quant: Q() to be converted :param units: requested units :param state: contains known quantities as ordered dict, along with flags and output :raise CalcError: if requested units are unknown """ flags2 = set(i for i in state.flags if i != '__hideunits__') if input_type == ConversionUsing: prefu = units.split() for p in prefu: if p not in unitquant: raise CalcError( "PQCalc does not recognize the unit '%s', so 'using' does not work. Try 'in' instead." % p) try: q = state[quant.strip()] + Q(0.0) except KeyError: raise CalcError("The quantity '%s' is not defined yet. Check for typos." % quant.strip()) q.name = "" q.provenance = None outp, _ = show_work(q, quant, flags2) output = (outp[:-1]) state[quant.strip()].prefu = set(prefu) q = state[quant.strip()] + Q(0.0) outp, _ = show_work(q, quant, flags2) output.extend(outp[-2 if not 'plain math' in state.flags else -1:]) else: tmp = interpret(units, state) try: qq = state[quant.strip()] / tmp except KeyError: raise CalcError("The quantity '%s' is not defined yet. Check for typos." % quant.strip()) addon = ("\mathrm{\ %s}" % quantities.latex_name(units)) if state.mob != "ipud" else units output, _ = show_work(qq, quant, flags2, addon=addon) state.printit('\n'.join(output))
def markup_all_but_math(line): """ :param line: String containing the comment :return: String with variables and chemistry marked-up in LateX """ interpretation = [] for item in (it for word in split_at_punctuation(line) for it in autodetect(word)): if item[0] == "!": interpretation.append('\\(\\ce{%s}\\)' % item[1]) elif item[0] == "{": interpretation.append(format_image(item[1])) elif item[0] == "N": if 'E' in item[1] or 'e' in item[1]: numbertext = '\\(' + latex_number(item[1]) + '\\)' else: numbertext = item[1] interpretation.append(clickable(item[1], numbertext)) elif item[0] == "i": numbertext = item[1] if not '.' in numbertext: numbertext = numbertext.rstrip() + '.' interpretation.append(clickable(numbertext, item[1])) elif item[0] == "_": try: delim = ' ' if item[1].endswith(' ') else '' interpretation.append( clickable( item[1], '\\(%s\\)%s' % (latex_name(item[1].rstrip()), delim))) except: interpretation.append(item[1]) else: interpretation.append(format_natural_language(item[1])) return ''.join(interpretation)
def create_unknown(sym, state): state.printnlog('''<span style="color:navy; font-size:15pt; cursor:pointer" onclick="insertAtCaret('commands','%s ', 0)">''' % sym) state.printnlog("\(%s =\\ ?\)<br>" % latex_name(sym)) state.printnlog('<br></span>')
def create_unknown(sym, state): state.printnlog( '''<span title="%s" style="color:navy; font-size:12pt; cursor:pointer" onclick="insertAtCaret('commands','%s = ', 0)">''' % (pronounce(sym), sym)) state.printnlog("\(%s =\\ ?\)<br>" % latex_name(sym)) state.printnlog('<br></span>')
def convert_units(input_type, command, quant, units, state): """ Shows the quantity in different units, either once only ('in') or from now on ('using') :param input_type: Whether conversion is with "using" or "in" :param command: user input :param quant: Q() to be converted :param units: requested units :param state: contains known quantities as ordered dict, along with flags and output :raise CalcError: if requested units are unknown """ flags2 = set(i for i in state.flags if i != '__hideunits__') if input_type == ConversionUsing: print(repr(state[quant.strip()])) if units in ['°ΔC', '°aC']: prefu = [units] q = state[quant.strip()] + Q(0.0) if units == '°aC' and unitquant['K'].units != q.units: raise CalcError( "Only quantities in kelvin may be converted to celsius") else: prefu = units.split() for p in prefu: if p not in unitquant: raise CalcError( "PQCalc does not recognize the unit '%s', so 'using' does not work. Try 'in' instead." % p) try: q = state[quant.strip()] + Q(0.0) except KeyError: raise CalcError( "The quantity '%s' is not defined yet. Check for typos." % quant.strip()) q.name = '' q.provenance = None q.comment = '' outp, _ = show_work(q, quant, flags2) output = (outp[:-1]) state[quant.strip()].prefu = set(prefu) q_old = state[quant.strip()] if q_old.provenance: # when called by calc2 q_old.name = '' q_old.provenance = None q = q_old + Q(0.0) q.comment = '' outp, _ = show_work(q, quant, flags2) output.extend(outp[-2 if not 'plain math' in state.flags else -1:]) q = state[quant.strip()] + Q(0.0) q.name = "" q.provenance = None _, logp = show_work(q, quant, flags2) state.printit('\n'.join(output)) state.logit('\n'.join(logp)) print(repr(state[quant.strip()])) else: tmp = interpret(units, state, warning=False) try: qq = state[quant.strip()] / tmp except KeyError: raise CalcError( "The quantity '%s' is not defined yet. Check for typos." % quant.strip()) addon = ( "\mathrm{\ %s}" % quantities.latex_name(units)) if state.mob != "ipud" else units work = show_work(qq, quant, flags2, addon=addon) state.printwork(work)
def show_work(result, sym, flags, error=False, addon="", skipsteps=False): """ Shows the steps in getting from formula to calculated value. This function is called not only by calc(), but also by convert_units() and deal_with_errors() to show steps in calculations. :param result: value and provenance of the quantity Q() :param sym: name of the quantity :param flags: Switches that determine how much detail is shown :param error: True if used to show an error in a step of a calculation :param addon: Used when called from convert_units(ConversionIn) :param skipsteps: True when intermediate steps are to be skipped :return: tuple containing detailed output, brief output """ output = [] logput = [] math = not 'plain math' in flags if math: writer = quantities.latex_writer if not "__latex__" in flags: logput.append( '''<span title='%s' style="color:navy; cursor:pointer; font-size:12pt;" onclick="insertAtCaret('commands','%s ', 0)">''' % (pronounce(sym, result.units), sym)) output.append( '''<span title='%s' style="color:navy; cursor:pointer; font-size:12pt;" onclick="insertAtCaret('commands','%s ', 0)">''' % (pronounce(sym, result.units), sym)) else: writer = quantities.ascii_writer subs = latex_subs if math else None d = result.setdepth() if math: template1 = "\(%s = %s%s\)%s<br>" template2 = "<br>\(\\ \\ \\ =%s%s\)<br>" else: template1 = "%s = %s%s%s" if d <= 0 else "%s = %s\n = %s%s" template2 = " = %s%s" task = result.steps(-1, writer, subs, ()) # task if '__hidenumbers__' in flags: task = result.steps(-1, quantities.latex_writer, subs) name = latex_name(sym) if math else sym output.append(template1 % (name, task, addon, markup_comment(result.comment))) logput.append(template1 % (name, task, addon, markup_comment(result.comment))) if not skipsteps: for dd in range(1, d + 1): if dd == 1: first = result.steps(dd, writer, subs, flags) if '__hidenumbers__' in flags: first = result.steps(dd, quantities.latex_writer, subs, {'__hidenumbers__'}) if first != task: output.append(template2 % (first, addon)) else: output.append(template2 % (result.steps( dd, writer, subs, flags), addon)) # intermediate steps result_str = result.steps(0, writer, subs, flags) # result if '__hideunits__' in flags: task = result.steps(-1, writer, subs, flags) if result_str != task and not error and not ('__hidenumbers__' in flags and d == 0): logput.append(template2 % (result_str, addon)) output.append(template2 % (result_str, addon)) if math and not '__latex__' in flags: logput.append('<br></span>') output.append('<br></span>') return output, logput
def show_work(result, sym, flags, error=False, addon="", skipsteps=False): """ Shows the steps in getting from formula to calculated value. This function is called not only by calc(), but also by convert_units() and deal_with_errors() to show steps in calculations. :param result: value and provenance of the quantity Q() :param sym: name of the quantity :param flags: Switches that determine how much detail is shown :param error: True if used to show an error in a step of a calculation :param addon: Used when called from convert_units(ConversionIn) :param skipsteps: True when intermediate steps are to be skipped :return: tuple containing detailed output, brief output """ output = [] logput = [] math = not 'plain math' in flags if math: writer = quantities.latex_writer if not "__latex__" in flags: logput.append('''<span style="cursor:pointer" onclick="insertAtCaret('commands','%s ', 0)">''' % sym) output.append('''<span style="cursor:pointer" onclick="insertAtCaret('commands','%s ', 0)">''' % sym) else: writer = quantities.ascii_writer subs = {"%s / %s": "\\dfrac{%s}{%s}", "%s * %s": "%s \\cdot %s", "%s ^ %s": "{%s}^{%s}", "exp(%s)": "e^{%s}", "log(%s)": "\\mathrm{log}(%s)", "ln(%s)": "\\mathrm{ln}(%s)", "sin(%s)": "\\mathrm{sin}(%s)", "cos(%s)": "\\mathrm{cos}(%s)", "tan(%s)": "\\mathrm{tan}(%s)", "sqrt(%s)": "\\sqrt{%s}", "quadn(%s": "\\mathrm{quadn}(%s", "quadp(%s": "\\mathrm{quadp}(%s", "average(%s": "\\mathrm{average(%s", "minimum(%s": "\\mathrm{minimum(%s", "maximum(%s": "\\mathrm{maximum(%s", "absolute(%s": "\\mathrm{absolute(%s", "moredigits(%s)": "\\mathrm{moredigits}(%s)", "uncertainty(%s)": "\\mathrm{uncertainty}(%s)", } if math else None d = result.setdepth() if math: template1 = "\(%s = %s%s\)<br>" template2 = "<br>\(\\ \\ \\ =%s%s\)<br>" else: template1 = "%s = %s%s" if d <= 0 else "%s = \n = %s%s" template2 = " = %s%s" flaugs = dict(uncert=("__showuncert__" in flags), hideunits=("__hideunits__" in flags), hidenumbers=("__hidenumbers__" in flags)) task = result.steps(-1, writer, subs, flaugs) # task if flaugs['hidenumbers']: task = result.steps(-1, quantities.latex_writer, subs) name = latex_name(sym) if math else sym output.append(template1 % (name, task, addon)) logput.append(template1 % (name, task, addon)) if not skipsteps: for dd in range(1, d + 1): if dd == 1: first = result.steps(dd, writer, subs, flaugs) if flaugs['hidenumbers']: first = result.steps(dd, quantities.latex_writer, subs, dict(hidenumbers=True)) if first != task: output.append(template2 % (first, addon)) else: output.append(template2 % (result.steps(dd, writer, subs, flaugs), addon)) # intermediate steps result_str = result.steps(0, writer, subs, flaugs) # result if result_str != task and not error and not (flaugs['hidenumbers'] and d == 0): logput.append(template2 % (result_str, addon)) output.append(template2 % (result_str, addon)) if math and not '__latex__' in flags: logput.append('<br></span>') output.append('<br></span>') return output, logput