markdown.obisidian.personal.notation

Functions for making and managing notation cards
import os
from unittest import mock
import shutil
import tempfile

from fastcore.test import *
from pathvalidate import validate_filename 

from trouver.helper import _test_directory

Parse notation note

For the purposes of trouver, a notation note most usually starts in the format <Notation> [[<link_to_note>|denotes]] <explanation of what that notation denotes/is defined as> <optional paragraphs discussing aspects about the notation>. For example, “\(\deg D\) [[note_link|denotes]] the degree of the divisor \(D\)” would be an example of such a note.

If the word denotes is not given in a link to a note, then the note to which the first link points is considered the main note of the notation note. Alternatively, a notation note might also sometimes have a comment citing the source of the notation instead of links. Nevertheless, it is preferred that denotes is given in a link.

A notation note may have YAML frontmatter meta as well.


source

parse_notation_note

 parse_notation_note
                      (notation_note:Union[str,trouver.markdown.obsidian.v
                      ault.VaultNote], vault:Optional[os.PathLike]=None)

Parse information from the notation note.

Returns

  • tuple[Union[dict, None], str, ObsidianLink, MarkdownFile, MarkdownFile]
    • The first entry is the YAML frontmatter meta, if available.
    • The second entry is the notation string
    • The third entry is the name of the “main note” of the notation note. This is usual the linked note in the link [[<linked_note>|denotes]]. If no such main note exists, then this is None.
    • The fourth entry is the MarkdownFile consisting of the “main” content of the note, which excludes the information given by all of the other entries.
    • The fifth entry is the MarkdownFile consisting of the ending bulleted list, listing the notations used in the notation notes along with links to the notation notes describing these notations. If there is not such bulleted list, then this entry is None.

Raises

  • UserWarning
    • If the (non-YAML frontmatter meta) contents of the note do not start inn the form <Notation> [[<link_to_note>|denotes]]; the name of the notation note is included in the warning message.
  • ValueError
    • If the notation note is not formatted correctly by starting with the notation with dollar signs $.
  • AssertionError
    • If notation_note is not determined to be a notation note.
Type Default Details
notation_note typing.Union[str, trouver.markdown.obsidian.vault.VaultNote]
vault typing.Optional[os.PathLike] None The vault If None, then uses th
Returns tuple

parse_notation_note gets information about the notation note. Note that the MarkdownFile object main_mf that has the main content/description of the notation does not start with the pharse of the form <notation> [[<link>|denotes]].

vault = _test_directory() / 'test_vault_7'
notation_note = VaultNote(vault, name='some_reference_name_notation_Spec_A')
metadata, notation_str, main_of_notation, main_mf, mf_with_links_to_notations = parse_notation_note(notation_note, vault)

test_eq(metadata, {'detect_regex': [], 'latex_in_original': ['\\operatorname{Spec} A']})
test_eq(notation_str, '$\\operatorname{Spec} A$')
test_eq(main_of_notation, 'spectrum_of_a_ring')
test_eq(str(main_mf), 'the spectrum of the ring $A$.')
assert mf_with_links_to_notations is None # There is not a bulleted list at the end, so the last output is `None`.
vault = _test_directory() / 'test_vault_7'
notation_note = VaultNote(vault, name='poonen_curves_notation_zeta_X_s_zeta_function_of_variety')
metadata, notation_str, main_of_notation, main_mf, mf_with_links_to_notations = parse_notation_note(notation_note, vault)

test_eq(metadata, None)
test_eq(notation_str, r'$\zeta_{X}(s)$')
test_eq(main_of_notation, 'poonen_curves_3.4.1 DEFINITION')
test_eq(str(main_mf), 'the zeta function of the [[poonen_curves_1.0.2 DEFINITION|variety]] $X$ over $\\mathbb{F}_q$.\n\nIt is defined as\n\n$$\\zeta_X(s) = Z_X(q^{-s}).$$\n\nA priori, it is a formal series, but in fact [[poonen_curves_ 3.6_page_56|it converges]] for $\\operatorname{Re} s > \\dim X$.')
test_eq(str(mf_with_links_to_notations), '- [$Z_X$](poonen_curves_notation_Z_X_T)') # There is a bulleted list at the end, so the last output is `None`.

source

notation_in_note

 notation_in_note
                   (notation_note:Union[str,trouver.markdown.obsidian.vaul
                   t.VaultNote], vault:Optional[os.PathLike]=None)

Return the name of the note from which the notation comes from.

Parameters

  • notation_note - Union[str, VaultNote]
    • Either

      • The name of the notation note or
      • The VaultNote object of the notation note.
    The note name is expected to be unique inside the vault specified by vault. This is expected to contain 'notation' as a substring. Usually, this is expected to be formatted in one of the following forms: - '<reference_name>_notation_<rest_of_note_name>' - `‘notation.
  • vault - Pathlike or None
    • Defaults to None

Returns

  • str
    • The notation in LaTeX, including the dollar signs $.

Raises

notation_in_note identifies the notation LaTeX str that a notation note presents. Its output starts and ends with dollar signs.

vault = _test_directory() / 'test_vault_7'
notation_note = VaultNote(vault, name='some_reference_name_notation_Spec_A')
notation = notation_in_note(notation_note)
assert notation == r'$\operatorname{Spec} A$'

source

main_of_notation

 main_of_notation
                   (notation_note:trouver.markdown.obsidian.vault.VaultNot
                   e, as_note:bool=False)

Return the name of the note from which the notation comes from.

Raises

  • ValueError
    • If the notation note is not formatted correctly by starting with the notation with dollar signs $.
Type Default Details
notation_note VaultNote The VaultNote object representing the notation note.
as_note bool False If False, then returns the name of the note, and returns a VaultNote object with the same vault as notation_note otherwise. The vault used to get the VaultNote is the vault of notation_note.
Returns typing.Union[str, trouver.markdown.obsidian.vault.VaultNote, NoneType] The (name of the) main information note that notation_note comes from. Returns None if notation_note does not come from such a note.

We can identify the “main note” of a notation note with the main_of_notation method:

vault = _test_directory() / 'test_vault_7'
notation_note = VaultNote(vault, name='some_reference_name_notation_Spec_A')
test_eq(main_of_notation(notation_note), 'spectrum_of_a_ring')

We can also return this main note as a VaultNote object:

vault = _test_directory() / 'test_vault_7'
notation_note = VaultNote(vault, name='some_reference_name_notation_Spec_A')
main_note =  main_of_notation(notation_note, as_note=True)
assert isinstance(main_note, VaultNote)
test_eq(main_note.name, 'spectrum_of_a_ring')

If the notation note has no links, then main_of_notation returns None:

vault = _test_directory() / 'test_vault_7'
notation_note = VaultNote(vault, name='some_reference_name_notation_O_X_this_file_has_no_links')
main_note =  main_of_notation(notation_note)
assert main_note is None

main_note = main_of_notation(notation_note, as_note=True)
assert main_note is None

Notations in a standard information note

Find notations introduced in note


source

notation_str_in_a_standard_information_note

 notation_str_in_a_standard_information_note
                                              (info_note:trouver.markdown.
                                              obsidian.vault.VaultNote)

Return the LaTeX str’s with notations in a standard information note.

A LaTeX str is deemed to be a notation if it is surrounded by double asterisks **

Type Details
info_note VaultNote
Returns list Each str is a LaTeX str, beginning and trailing dollar signs $ (single or double) included.

We can obtain the notation str in an information note:

vault = _test_directory() / 'test_vault_7'
# A note with just one notation:
vn = VaultNote(vault, name='galois_group')
sample_output_1 = notation_str_in_a_standard_information_note(vn)
assert len(sample_output_1) == 1
assert sample_output_1[0].startswith('$')
assert sample_output_1[0].endswith('$')
assert not sample_output_1[0].startswith('$$')
assert not sample_output_1[0].endswith('$$')
print(sample_output_1)

# A note with a notation with double asterisks:
vn = VaultNote(vault, name='spectrum_of_a_ring')
sample_output_2 = notation_str_in_a_standard_information_note(vn)
assert len(sample_output_2) == 2
assert sample_output_2[1].startswith('$$')
assert sample_output_2[1].endswith('$$')
print(sample_output_2)

# A note with no notations:
assert not notation_str_in_a_standard_information_note(VaultNote(vault, name='no_notations_note_about_integral_domains'))
['$\\operatorname{Gal}(L/K)$']
['$\\operatorname{Spec} A$', '$$D(f) = \\{\\mathfrak{p} \\in \\operatorname{Spec} A: f \\not\\in \\mathfrak{p} \\}.$$']
# hide
# Test notation str with asterisks.
vault = _test_directory() / 'test_vault_7'
vn = VaultNote(vault, name='direct_and_inverse_images_of_sheaves')
sample_output = notation_str_in_a_standard_information_note(vn)
# sample_output
assert len(sample_output) == 2

Notation notes listed in see also section


source

notation_notes_linked_in_see_also_section

 notation_notes_linked_in_see_also_section
                                            (info_note:trouver.markdown.ob
                                            sidian.vault.VaultNote,
                                            vault:os.PathLike,
                                            as_vault_notes:bool=True)

Return a list of notation notes listed in the See Also section of the standard information note.

In the current implementation of this function, only “notation notes” that actually exist are included in the returned list.

Type Default Details
info_note VaultNote
vault PathLike Path to the vault directory.
as_vault_notes bool True If True, returns each notation note as a VaultNote object. Otherwise, returns the name of each notation note. Defaults to True.
Returns typing.Union[list[trouver.markdown.obsidian.vault.VaultNote], list[str]] Each entry corresponds to a notation note in the vault.

The notation_notes_linked_in_see_also_section method detects the Notation notes listed in bulleted links in the See Also section of a standard information note.

vault = _test_directory() / 'test_vault_7'
vn = VaultNote(vault, name='twist_of_a_graded_module')
sample_output = notation_notes_linked_in_see_also_section(vn, vault)
assert len(sample_output) == 1
assert isinstance(sample_output[0], VaultNote)
print(sample_output[0].name)
assert sample_output[0].exists()
foag_notation_M_n_bullet

Setting as_vault_notes=False returns the names of the notation notes.

vault = _test_directory() / 'test_vault_7'
vn = VaultNote(vault, name='twist_of_a_graded_module')
sample_output = notation_notes_linked_in_see_also_section(vn, vault, as_vault_notes=False)
assert len(sample_output) == 1
assert isinstance(sample_output[0], str)
print(sample_output[0])
foag_notation_M_n_bullet

If a “notation note” does not exist, then it is not included in the returned list.

Note that notation_notes_linked_in_see_also_section uses bulleted_links_of_type_in_section, which is turn uses note_is_of_type to get a list of linked notes of the type NOTATION_NOTE of the PersonalNoteTypeEnum class. In turn, a note file must exist for the note to be considered of any particular type under the current implementation of note_is_of_type.

vault = _test_directory() / 'test_vault_7'
vn = VaultNote(vault, name='note_with_links_to_non_existent_notation_notes')
sample_output = notation_notes_linked_in_see_also_section(vn, vault, as_vault_notes=True)
test_eq(sample_output, [])
sample_output = notation_notes_linked_in_see_also_section(vn, vault, as_vault_notes=False)
test_eq(sample_output, [])

Find all notation notes in a vault subdirectory


source

notations_and_main_notes

 notations_and_main_notes (vault:os.PathLike,
                           subdirectory:Optional[os.PathLike]=None, note:O
                           ptional[trouver.markdown.obsidian.vault.VaultNo
                           te]=None)

Return a dict with all of notation notes in a specified subdirectory of a vault and the names of the main notes of these notation notes.

Returns - dict

Raises

  • ValueError
    • If subdirectory and note are both None.
Type Default Details
vault PathLike Path to the vault directory.
subdirectory typing.Optional[os.PathLike] None Path to the subdirectory, relative to vault, to find the notation notes. Searches for all notation notes here and in subdirectories of this subdirectory. If None, then the note parameter is used to determined the subdirectory. Ifsubdirectoryis the empty str, then all notation notes in the vault are searched. Defaults toNone. | | note | typing.Optional[trouver.markdown.obsidian.vault.VaultNote] | None | A note in the vault. The directory that this note is in determines thesubdirectoryparameter if the argument passed tosubdirectoryis the blank str. This note can usually be an index note, e.g.’_index_silverman’. Defaults toNone, in which casesubdirectorymust be specified. | | **Returns** | **dict** | | **A key is the unique name of a notation note in the vault and its corresponding value is the name of the main note of the notation note. Each main note may not actually exist, but each notation note definitely exists. If the notation note has no main note (i.e. has no links to other notes), then the value isNone`.**

The notations_and_main_notes function returns all the notation notes in a subdirectory of a vault

vault = _test_directory() / 'test_vault_7'
sample_output = notations_and_main_notes(vault, subdirectory='')
print(sample_output)
assert 'foag_notation_M_n_bullet' in sample_output
assert 'some_reference_name_notation_O_X_this_file_has_no_links' in sample_output
assert sample_output['some_reference_name_notation_O_X_this_file_has_no_links'] is None
assert 'poonen_curves_notation_Z_X_T' in sample_output
{'foag_notation_M_n_bullet': 'twist_of_a_graded_module', 'some_reference_name_notation_k_t_formal_power_series_ring': 'some_note', 'some_reference_name_notation_O_X_this_file_has_no_links': None, 'some_reference_name_notation_Pic_C': 'divisor_class_group_of_a_curve', 'some_reference_name_notation_Spec_A': 'spectrum_of_a_ring', 'foag_notation_O_n': 'foag_15.2.1', 'foag_notation_O_text_Proj__S__n': 'foag_15.2.1', 'poonen_curves_notation_zeta_X_s_zeta_function_of_variety': 'poonen_curves_3.4.1 DEFINITION', 'poonen_curves_notation_Z_X_T': 'poonen_curves_3.4.1 DEFINITION', 'some_reference_name_notation_B_R': 'note_with_some_excessive_notation_notes', 'some_reference_name_notation_B_R_1': 'note_with_some_excessive_notation_notes', 'some_reference_name_notation_Jac_C': 'note_with_some_excessive_notation_notes', 'test_notation_note_for_latex_in_original_metadata_1': 'test_note_for_latex_in_original_metadata', 'test_notation_note_for_latex_in_original_metadata_2': 'test_note_for_latex_in_original_metadata', 'foag_notation__otimes_A_quad_obj_Mod_A_times_obj_Mod_A_longarrow_obj_Mod_A_': 'foag_1.3.5'}

Here is an example with a subdirectory specified:

vault = _test_directory() / 'test_vault_7'
sample_output = notations_and_main_notes(vault, subdirectory='some_other_folder')
print(sample_output)
assert 'foag_notation_M_n_bullet' not in sample_output
assert 'some_reference_name_notation_O_X_this_file_has_no_links' not in sample_output
assert 'poonen_curves_notation_Z_X_T' in sample_output
{'foag_notation_O_n': 'foag_15.2.1', 'foag_notation_O_text_Proj__S__n': 'foag_15.2.1', 'poonen_curves_notation_zeta_X_s_zeta_function_of_variety': 'poonen_curves_3.4.1 DEFINITION', 'poonen_curves_notation_Z_X_T': 'poonen_curves_3.4.1 DEFINITION', 'some_reference_name_notation_B_R': 'note_with_some_excessive_notation_notes', 'some_reference_name_notation_B_R_1': 'note_with_some_excessive_notation_notes', 'some_reference_name_notation_Jac_C': 'note_with_some_excessive_notation_notes'}

Alternatively, we can specify a subdirectory by a VaultNote object; the directory that the VaultNote object is the subdirectory:

vault = _test_directory() / 'test_vault_7'
vn = VaultNote(vault, name='galois_group')
sample_output = notations_and_main_notes(vault, subdirectory=None, note=vn)
print(sample_output)
assert 'foag_notation_M_n_bullet' in sample_output
assert 'some_reference_name_notation_O_X_this_file_has_no_links' in sample_output
assert sample_output['some_reference_name_notation_O_X_this_file_has_no_links'] is None
assert 'poonen_curves_notation_Z_X_T' not in sample_output
{'foag_notation_M_n_bullet': 'twist_of_a_graded_module', 'some_reference_name_notation_k_t_formal_power_series_ring': 'some_note', 'some_reference_name_notation_O_X_this_file_has_no_links': None, 'some_reference_name_notation_Pic_C': 'divisor_class_group_of_a_curve', 'some_reference_name_notation_Spec_A': 'spectrum_of_a_ring'}

Add notation notes to Notation index note


source

notations_to_add_in_index

 notations_to_add_in_index (vault:os.PathLike, notation_index_note=<class
                            'trouver.markdown.obsidian.vault.VaultNote'>,
                            subdirectory:Optional[os.PathLike]=None, note:
                            Optional[trouver.markdown.obsidian.vault.Vault
                            Note]=None)

Returns notations and links of notation notes to that ought to be added in the corresponding notation index, i.e. are in the reference folder but not linked by the notation index note.

If a notation note is not properly formatted, e.g. does not have a notation, then the notation and link for the notation note will not be included.

Raises - ValueError - If subdirectory and note are both None.

Type Default Details
vault PathLike Path to the vault directory.
notation_index_note type VaultNote The notation index note in the vault where the notations should be added to.
subdirectory typing.Optional[os.PathLike] None Path to the subdirectory, relative to vault, to find the notation notes. Searches for all notation notes here and in subdirectories of this subdirectory. If None, then the note parameter is used to determined the subdirectory. Ifsubdirectoryis the empty str, then all notation notes in the vault are searched. Defaults toNone. | | note | typing.Optional[trouver.markdown.obsidian.vault.VaultNote] | None | The directory that this note is in determines the argument tosubdirectoryparameter if it isNone. Defaults toNone, in which casesubdirectorymust be specified. | | **Returns** | **list** | | **Each tuple in the list consists of the notation str of the notation note (including surrounding dollar signs$`) and the (nonembedded) ObsidianLink object for a link to the notation note.**

We can identify notation notes which exist in a reference folder but are not linked in the notation index note for the reference:

# TODO: make test
# VaultNote.clear_cache()
vault = _test_directory() / 'test_vault_6'
reference = 'number_theory_reference_1'
note = VaultNote(vault, name=f'_index_{reference}')
notation_index_note = VaultNote(vault, name=f'_notation_{reference}')
sample_output = notations_to_add_in_index(vault, notation_index_note, note=note)
for notation_str, link in sample_output:
    print(notation_str, link.to_string())
$\mathbb{Z}/n\mathbb{Z}$ ![[number_theory_reference_1_notation_Z_nZ_ring_of_integers_modulo_n]]

source

index_notation_note_formatted_entry

 index_notation_note_formatted_entry (notation_str:str,
                                      link:trouver.markdown.obsidian.links
                                      .ObsidianLink)

Return a str formatted for an index notation note entry.

It is recommended to pass the outputs of notations_to_add_in_index to this function.

Type Details
notation_str str The str of the notation, including the surrounding dollar signs $.
link ObsidianLink The embedded link to the notation note.
Returns str

The index_notation_note_formatted_entry function returns a formatted str to add in the index notation note:

print(index_notation_note_formatted_entry(sample_output[0][0], sample_output[0][1]))
### $\mathbb{Z}/n\mathbb{Z}$
- ![[number_theory_reference_1_notation_Z_nZ_ring_of_integers_modulo_n]]

Making a notation note


source

make_a_notation_note

 make_a_notation_note
                       (main_note:trouver.markdown.obsidian.vault.VaultNot
                       e, vault:os.PathLike, notation:str,
                       description:str, notation_note_name:str,
                       destination:Optional[os.PathLike]=None,
                       overwrite:bool=False, add_to_main:bool=True)

Make a new notation note, optionally add a link to it in the See Also section of its main note, returns it.

The notation note is created in the same directory as the main note. The meta of the notation note has a latex_in_original section which lists the contents of the latex string in the main note from which the notation note comes from. This is so that the make_notation_notes_from_double_asts method can distinguish between notations for which a note has been created and for which a note has not been created.

Type Default Details
main_note VaultNote The note from which the notation originates.
vault PathLike
notation str The notation typed in latex. May or may not be surrounded by dollar signs
description str The rest of the text describing notation.
notation_note_name str The name of the new notation note to be created.
destination typing.Optional[os.PathLike] None The directory to create the new notation note in. If None, then creates the new notation note in the same place as the note specified by note_name
overwrite bool False If True, overwrite file of the same path as the new notation file to be written, if such a file exists. Otherwise, does nothing. Even if a link to the old notation note exists in main_note, a new link will still be added. Defaults to False.
add_to_main bool True If True, adds a link to the notation note in the See Also section of the main note.
Returns typing.Optional[trouver.markdown.obsidian.vault.VaultNote] The newly created notation note. If no note is created, then returns None.

We can make a notation note with the make_a_notation_note method.

with tempfile.TemporaryDirectory(prefix='tmp_dir_', dir=os.getcwd()) as tmp_dir:
    tmp_dir = Path(tmp_dir)
    temp_vault = tmp_dir / 'test_vault_7'
    shutil.copytree(_test_directory() / 'test_vault_7', temp_vault)

    note = VaultNote(temp_vault, name='galois_group')
    notation_note = make_a_notation_note(
        note, temp_vault, r'\operatorname{Gal}(L/K)', '', notation_note_name='some_reference_name_notation_Gal_L_K_galois_group')
    mf = MarkdownFile.from_vault_note(notation_note)
    assert mf.has_metadata()
    meta = mf.metadata()
    assert 'detect_regex' in meta
    assert 'latex_in_original' in meta
    print(meta, '\n')
    assert '\\operatorname{Gal}(L/K)' in meta['latex_in_original']
    print(mf, '\n')

    main_mf = MarkdownFile.from_vault_note(note)
    # print(main_mf)
    assert notation_note.name in str(main_mf)  # A link has been created
    # os.startfile(temp_vault)
    # input()
{'detect_regex': [], 'latex_in_original': ['\\operatorname{Gal}(L/K)']} 

---
detect_regex: []
latex_in_original: ["\\operatorname{Gal}(L/K)"]
---
$\operatorname{Gal}(L/K)$ [[galois_group|denotes]]  

Note that the surrounding dollar signs for LaTeX math mode can be included in the argument for notation:

with tempfile.TemporaryDirectory(prefix='tmp_dir_', dir=os.getcwd()) as tmp_dir:
    tmp_dir = Path(tmp_dir)
    temp_vault = tmp_dir / 'test_vault_7'
    shutil.copytree(_test_directory() / 'test_vault_7', temp_vault)

    note = VaultNote(temp_vault, name='galois_group')
    notation_note = make_a_notation_note(
        note, temp_vault, r'$\operatorname{Gal}(L/K)$', '', notation_note_name='some_reference_name_notation_Gal_L_K_galois_group')
    mf = MarkdownFile.from_vault_note(notation_note)
    assert mf.has_metadata()
    meta = mf.metadata()
    assert 'detect_regex' in meta
    assert 'latex_in_original' in meta
    print(meta, '\n')
    assert '\\operatorname{Gal}(L/K)' in meta['latex_in_original']
    print(mf, '\n')

    main_mf = MarkdownFile.from_vault_note(note)
    # print(main_mf)
    assert notation_note.name in str(main_mf)  # A link has been created
    # os.startfile(temp_vault)
    # input()
{'detect_regex': [], 'latex_in_original': ['\\operatorname{Gal}(L/K)']} 

---
detect_regex: []
latex_in_original: ["\\operatorname{Gal}(L/K)"]
---
$\operatorname{Gal}(L/K)$ [[galois_group|denotes]]  

Setting add_to_main=False only creates the notation note, but does not add a link to the notation note in the main note:

with tempfile.TemporaryDirectory(prefix='tmp_dir_', dir=os.getcwd()) as tmp_dir:
    tmp_dir = Path(tmp_dir)
    temp_vault = tmp_dir / 'test_vault_7'
    shutil.copytree(_test_directory() / 'test_vault_7', temp_vault)

    note = VaultNote(temp_vault, name='galois_group')
    notation_note = make_a_notation_note(
        note, temp_vault, r'\operatorname{Gal}(L/K)', '', notation_note_name='_reference_notation_Gal_L_K_galois_group',
        add_to_main=False)

    mf = MarkdownFile.from_vault_note(notation_note)
    assert mf.has_metadata()
    meta = mf.metadata()
    assert 'detect_regex' in meta
    assert 'latex_in_original' in meta
    print(meta, '\n')
    assert '\\operatorname{Gal}(L/K)' in meta['latex_in_original']
    print(mf, '\n')

    main_mf = MarkdownFile.from_vault_note(note)
    # print(main_mf)
    assert notation_note.name not in str(main_mf)  # No link has been created
{'detect_regex': [], 'latex_in_original': ['\\operatorname{Gal}(L/K)']} 

---
detect_regex: []
latex_in_original: ["\\operatorname{Gal}(L/K)"]
---
$\operatorname{Gal}(L/K)$ [[galois_group|denotes]]  

If the notation note of the specified name (notation_note_name) already exists, then by default no note is created and no link is added in the main note.

with tempfile.TemporaryDirectory(prefix='tmp_dir_', dir=os.getcwd()) as tmp_dir:
    tmp_dir = Path(tmp_dir)
    temp_vault = tmp_dir / 'test_vault_7'
    shutil.copytree(_test_directory() / 'test_vault_7', temp_vault)

    note = VaultNote(temp_vault, name='spectrum_of_a_ring')
    notation_note = make_a_notation_note(
        note, temp_vault, r'\operatorname{Spec} A', '', notation_note_name='some_reference_name_notation_Spec_A')

    assert notation_note is None

    main_mf = MarkdownFile.from_vault_note(note)
    # print(main_mf)
    assert main_mf.get_headings_and_text()['# See Also'].strip() == ''  # No link has been added

Setting overwrite=True, however, will overwrite the existing note. The method will also add a link to the (overwritten) notation note.

with tempfile.TemporaryDirectory(prefix='tmp_dir_', dir=os.getcwd()) as tmp_dir:
    tmp_dir = Path(tmp_dir)
    temp_vault = tmp_dir / 'test_vault_7'
    shutil.copytree(_test_directory() / 'test_vault_7', temp_vault)

    note = VaultNote(temp_vault, name='spectrum_of_a_ring')
    notation_note = make_a_notation_note(
        note, temp_vault, r'\operatorname{Spec} A', '', notation_note_name='some_reference_name_notation_Spec_A',
        overwrite=True)

    assert notation_note is not None

    main_mf = MarkdownFile.from_vault_note(note)
    assert notation_note.name in str(main_mf)
    notation_mf = MarkdownFile.from_vault_note(notation_note) 
    # notation_mf has been overwritten
    print(notation_mf)
---
detect_regex: []
latex_in_original: ["\\operatorname{Spec} A"]
---
$\operatorname{Spec} A$ [[spectrum_of_a_ring|denotes]] 

source

make_notation_notes_from_double_asts

 make_notation_notes_from_double_asts
                                       (main_note:trouver.markdown.obsidia
                                       n.vault.VaultNote,
                                       vault:os.PathLike,
                                       reference_name:str, destination:Opt
                                       ional[os.PathLike]=None,
                                       overwrite:bool=False,
                                       add_to_main:bool=True)

Make notation notes based on double asterisks surrounding LaTeX text in a standard information note.

Notations are deemed to be completely LaTeX text in info notes that are surrounded by double asterisks. In basicality, if such a LaTeX text (without surrounding dollars signs $ or $$) is listed in the latex_in_original metadata section of some notation note in the same directory as the info note whose main note is the info note in question, then a new notation note for that LaTeX text is not created. However, if there are multiple instances of the same LaTeX text, then some notation notes may be created so that the number of times the LaTeX text appears in the info note is the no more than the number of times the LaTeX text appears in latex_in_original metadata sections of notation notes (in the same directory as the info note whose main note is the info note).

For example, if there is an info note with notations A, A, 'A', 'A', and B and if there is a single notation note in the same directory as the info note with two 'A' and 'A' entries in its latex_in_original metadata section, then three notation notes will be created: two with 'A' listed in their latex_in_original sections, and one with 'B' listed in its latex_in_original section.

Raises

  • Warning
    • If there are notation notes whose main note is determined to be to main_note and whose notations “excessively cover” those in main_note, i.e. the notation notes have more notations than main_note introduces. The main note and the excessive notations are printed; the notations are printed instead of the notation notes because the same notation may span either multiple or single notation notes.
Type Default Details
main_note VaultNote The standard information note from which the notations are marked with double asterisks
vault PathLike The name of the reference; the notation note’s name will start with {reference_name}_notation_.
reference_name str
destination typing.Optional[os.PathLike] None The directory to create the new notation notes in. If None, then creates the new notation note in the same place as the note specified by note_name
overwrite bool False If True, overwrite file of the same path as the new notation file to be written, if such a file exists. Otherwise, does nothing. Defaults to False.
add_to_main bool True If True, adds links to the notation note in the See Also section of the main note.
Returns list The list of VaultNotes that are newly created/modified.

As described in markdown.obsidian.personal.machine_learning.notation_identification, we surround a LaTeX math mode string with double asterisks ** to indicate that the string introduces a notation.

The make_notation_notes_from_double_asts method parses LaTeX surrounded by double asterisks ** in a standard information note and automatically creates notation notes for said LaTeX.

with tempfile.TemporaryDirectory(prefix='tmp_dir_', dir=os.getcwd()) as tmp_dir:
    tmp_dir = Path(tmp_dir)
    temp_vault = tmp_dir / 'test_vault_6'
    shutil.copytree(_test_directory() / 'test_vault_6', temp_vault)

    # os.startfile(temp_vault)
    # input()
    info_note = VaultNote(temp_vault, name='reference_for_notation_notes_introducing_some_notations')
    new_notes = make_notation_notes_from_double_asts(info_note, temp_vault, 'reference_for_notation_notes')
    
    assert len(new_notes) == 3
    for new_note in new_notes:
        assert new_note.exists()
        assert notation_note_is_linked_in_see_also_section(new_note, info_note)
    # input()
    # TODO: add more tests - overwrite=True, add_to_main=False

In the following example, we prompt make_notation_notes_from_double_asts to make notation notes for an info note with no notations - nothing is modified:

with tempfile.TemporaryDirectory(prefix='tmp_dir_', dir=os.getcwd()) as tmp_dir:
    tmp_dir = Path(tmp_dir)
    temp_vault = tmp_dir / 'test_vault_6'
    shutil.copytree(_test_directory() / 'test_vault_6', temp_vault)

    info_note = VaultNote(temp_vault, name='reference_for_notation_notes_no_notations_introduced_here')
    info_note_content_before = info_note.text()
    new_notes = make_notation_notes_from_double_asts(info_note, temp_vault, 'reference_for_notation_notes')
    info_note_content_after = info_note.text()
    
    assert len(new_notes) == 0
    assert info_note_content_before == info_note_content_after

In the following example, we prompt make_notation_notes_from_double_asts on the same info note twice - no new notation notes are created the second time.

with tempfile.TemporaryDirectory(prefix='tmp_dir_', dir=os.getcwd()) as tmp_dir:
    tmp_dir = Path(tmp_dir)
    temp_vault = tmp_dir / 'test_vault_6'
    shutil.copytree(_test_directory() / 'test_vault_6', temp_vault)

    info_note = VaultNote(temp_vault, name='reference_for_notation_notes_introducing_some_notations')
    make_notation_notes_from_double_asts(info_note, temp_vault, 'milne_av')
    new_notes = make_notation_notes_from_double_asts(info_note, temp_vault, 'milne_av')
    assert len(new_notes) == 0

In the following example, an info note contains two of the same notation. One notation note for each of these notations is created, but with different names:

with tempfile.TemporaryDirectory(prefix='tmp_dir_', dir=os.getcwd()) as tmp_dir:
    tmp_dir = Path(tmp_dir)
    temp_vault = tmp_dir / 'test_vault_7'
    shutil.copytree(_test_directory() / 'test_vault_7', temp_vault)

    info_note = VaultNote(temp_vault, name='note_with_repeated_notation')
    new_notes = make_notation_notes_from_double_asts(info_note, temp_vault, 'some_reference_name')
    assert len(new_notes) == 2
    print(new_notes[0].name)
    print(new_notes[1].name)
some_reference_name_notation_Cl_K
some_reference_name_notation_Cl_K_1

In the following example, there are notation notes with the info note as their main note, but some of the notations in these notation notes cover those in the info note “excessively” - in this case, only notation notes to uncovered notations are created, and warnings are raised to indicate which notations are covered excessively.

with tempfile.TemporaryDirectory(prefix='tmp_dir_', dir=os.getcwd()) as tmp_dir:
    tmp_dir = Path(tmp_dir)
    temp_vault = tmp_dir / 'test_vault_7'
    shutil.copytree(_test_directory() / 'test_vault_7', temp_vault)

    info_note = VaultNote(temp_vault, name='note_with_some_excessive_notation_notes')
    new_notes = make_notation_notes_from_double_asts(info_note, temp_vault, 'some_reference_name')
    assert len(new_notes) == 1
C:\Users\hyunj\AppData\Local\Temp\ipykernel_23252\2876467275.py:57: UserWarning: The following note has the following excess notations: note_with_some_excessive_notation_notes, \mathcal{B}(\mathbb{R}), \operatorname{Jac}(C)
  warnings.warn(
# TODO: move notation notes to directory of main notes

Decomposition of notation

# #| export
# def decompose_notation_as_sequence(
#         notation # latex styled. Assumed to not be surrounded with `'$'`.
#         ) -> list:
#     """
#     **Parameters**
#     - notation - str
    
#     **Returns**
#     - list of str
#     """
#     str_index = 0
#     decomposition = []
#     while str_index < len(notation):
#         if notation[str_index] == '\\':
#             j = 1
#             while (str_index + j < len(notation)
#                     and notation[str_index + j] not in [' ', '\\', '{', '(']):
#                 j += 1
#             latex_command = notation[str_index:str_index + j]
#             decomposition.append(latex_command)
#             str_index += j
#         if str_index < len(notation):
#             decomposition.append(notation[str_index])
#         str_index += 1
#     return decomposition


# def compare_notations_for_sorting(
#         notation1, # latex styled. Assumed to not be surrounded with `'$'`.
#         notation2, # latex styled. Assumed to not be surrounded with `'$'`.
#         character_ordering_list
#         ) -> int:
#     """
#     **Parameters**
#     - notation - str
#         - latex styled. Assumed to not be covered with `'$'`.
    
#     **Returns**
#     - int
#         - 1 if `notation2` is considered to come "earlier", -1 if
#         `notation1` is considered to come "earlier", and 0 otherwise.
#     """
#     decomposition1 = decompose_notation_as_sequence(notation1)
#     decomposition2 = decompose_notation_as_sequence(notation2)
#     index1, index2 = 0, 0
#     while index1 < len(decomposition1) and index2 < len(decomposition2):
#         return  #TODO
#     if index1 < len(decomposition1):
#         return 1
#     if index2 < len(decomposition2):
#         return -1
#     return 0


# def _find_next_effective_character(decomposition, index):
#     while (index < len(decomposition)
#             and decomposition[index] in ['{', '}', '(', ')', '[', ']', r'\tilde',
#                                          r'\hat', r'\bar', 'r\overline']):
#         return
# decompose_notation_as_sequence(r'\tilde{K} (X)')
# decompose_notation_as_sequence(r'P(X;*,A)')
# decompose_notation_as_sequence(r'\operatorname{Spec} A')

Detect notations being used in reference

Regex from latex


source

regex_from_latex

 regex_from_latex (latex:str, replaceables:dict[str,set[str]]={'mathrm':
                   {'rm', 'mathrm', 'text', 'operatorname'},
                   'operatorname': {'rm', 'mathrm', 'text',
                   'operatorname'}, 'rm': {'rm', 'mathrm', 'text',
                   'operatorname'}, 'text': {'rm', 'mathrm', 'text',
                   'operatorname'}, 'mathbf': {'mathbf', 'bf'}, 'bf':
                   {'mathbf', 'bf'}, 'mathit': {'it', 'mathit'}, 'it':
                   {'it', 'mathit'}}, special_characters:list[str]=['.',
                   '+', '*', '?', '^', '$', '(', ')', '[', ']', '{', '}',
                   '|', '\\'])

Returns regex to match latex math mode string which is essentially equivalent to a specified latex math mode string.

The outputs of this function may not work correctly. The regex pattern does not have to fully match equivalent string.

Parameters

  • latex - str
    • The latex math mode string. Does not include math mode delimiters such as $, $$, \[ \] (although the characters '\[' and '\]' can still be part of the string, e.g. for optional arguments of a macro/operator). Can include “placeholders” r'', r'', r'', etc. to indicate substitutable/generics; the placeholders can be substituted with any string.
  • replaceables - dict[str, set[str]]
    • latex strings/commands which are considered “interreplacable”
  • special_characters - list[str]
    • characters to add a backslash '' in front of for regex. Defaults to a list consisting of special characters in regex.
text = r"""e"""
print(regex_from_latex(text, REPLACEABLES))
(?:[ \{\}]*?)e(?:[ \{\}]*?)(?:[ \{\}]*)

Get regex from notation note

So far, I have just made notation notes in the form '$math_mode_string$ denotes ...'. I want to add frontmatter metadata in notation notes to indicate regex to detect the notation with placeholders.


source

regex_from_notation_note

 regex_from_notation_note (vault:os.PathLike,
                           note:trouver.markdown.obsidian.vault.VaultNote)

Returns a regex str to detect the notation of the notation note.

The regex detection strings should be in a list labeled detect_regex in the yaml frontmatter. If multiple strings are in the list, then the regex will detect latex math mode strings roughly corresponding to any of them. If multiple strings are in the list, then they must be ordered “by priority”, with the higher priority regexes coming first. It is good to have these string in quotes "" to make sure that yaml can load them safely. When doing so, make sure to escape characters, e.g. backslash should be typed as \, etc.

The strings in detect_regex can include placeholders, cf. [regex_from_latex](https://hyunjongkimmath.github.io/trouver/markdown.obsidian.personal.notation.html#regex_from_latex).

Parameters - vault - PathLike - note - VaultNote

Returns - str - Of the regex used to detect the notation. The regex does not need to fully match instances of the notation.

# TODO: test