コード例 #1
0
ファイル: tools.py プロジェクト: gesellkammer/maelzel
def m21JupyterHook(enable=True) -> None:
    """
    Set an ipython-hook to display music21 objects inline on the
    ipython notebook
    """
    if not misc.inside_jupyter():
        logger.debug("m21JupyterHook: not inside ipython/jupyter, skipping")
        return
    from IPython.core.getipython import get_ipython
    from IPython.core import display
    from IPython.display import Image, display
    ip = get_ipython()
    formatter = ip.display_formatter.formatters['image/png']
    if enable:
        def showm21(stream: m21.stream.Stream):
            fmt = config['m21.displayhook.format']
            filename = str(stream.write(fmt))
            return display(Image(filename=filename))
            # return display.Image(filename=filename)._repr_png_()

        dpi = formatter.for_type(m21.Music21Object, showm21)
        return dpi
    else:
        logger.debug("disabling display hook")
        formatter.for_type(m21.Music21Object, None)
コード例 #2
0
ファイル: tools.py プロジェクト: gesellkammer/maelzel
def setJupyterHookForClass(cls, func, fmt='image/png'):
    """
    Register func as a displayhook for class `cls`
    """
    if not misc.inside_jupyter():
        logger.debug("_setJupyterHookForClass: not inside IPython/jupyter, skipping")
        return
    import IPython
    ip = IPython.get_ipython()
    formatter = ip.display_formatter.formatters[fmt]
    return formatter.for_type(cls, func)
コード例 #3
0
ファイル: tools.py プロジェクト: gesellkammer/maelzel
def jupyterShowImage(path: str):
    """
    Show an image inside (inline) of a jupyter notebook

    Args:
        path: the path to the image file

    """
    if not misc.inside_jupyter():
        logger.error("jupyter is not available")
        return

    img = jupyterMakeImage(path)
    return jupyterDisplay(img)
コード例 #4
0
ファイル: tools.py プロジェクト: gesellkammer/maelzel
def pngShow(pngpath:str, forceExternal=False, app:str='') -> None:
    """
    Show a png either inside jupyter or with an external app

    Args:
        pngpath: the path to a png file
        forceExternal: if True, it will show in an external app even
            inside jupyter. Otherwise it will show inside an external
            app if running a normal session and show an embedded
            image if running inside a notebook

    """
    if misc.inside_jupyter() and not forceExternal:
        jupyterShowImage(pngpath)
    else:
        environment.viewPng(pngpath, app=app)
コード例 #5
0
ファイル: tools.py プロジェクト: gesellkammer/maelzel
def jupyterMakeImage(path: str) -> JupyterImage:
    """
    Makes a jupyter Image, which can be displayed inline inside
    a notebook

    Args:
        path: the path to the image file

    Returns:
        an IPython.core.display.Image

    """
    if not misc.inside_jupyter():
        raise RuntimeError("Not inside a Jupyter session")

    scalefactor = config.get('show.scalefactor', 1.0)
    if scalefactor != 1.0:
        imgwidth, imgheight = imgSize(path)
        width = imgwidth*scalefactor
    else:
        width = None
    return JupyterImage(filename=path, embed=True, width=width)
コード例 #6
0
ファイル: tools.py プロジェクト: gesellkammer/maelzel
    :return: the string to be shown alongside the notated pitch
    """
    # cents can be also negative (see self.cents)
    pivot = int(round(100 / divsPerSemitone))
    dist = min(centsdev%pivot, -centsdev%pivot)
    if dist <= 2:
        return ""
    if centsdev < 0:
        # NB: this is not a normal - sign! We do this to avoid it being confused
        # with a syllable separator during rendering (this is currently the case
        # in musescore
        return f"–{-centsdev}"
    return str(int(centsdev))


if misc.inside_jupyter():
    from IPython.core.display import (display as jupyterDisplay, 
                                      Image as JupyterImage)


def setJupyterHookForClass(cls, func, fmt='image/png'):
    """
    Register func as a displayhook for class `cls`
    """
    if not misc.inside_jupyter():
        logger.debug("_setJupyterHookForClass: not inside IPython/jupyter, skipping")
        return
    import IPython
    ip = IPython.get_ipython()
    formatter = ip.display_formatter.formatters[fmt]
    return formatter.for_type(cls, func)
コード例 #7
0
ファイル: environment.py プロジェクト: gesellkammer/maelzel
import sys
import shutil
from typing import List, Optional as Opt
from emlib import misc
import logging
import music21 as m21
import appdirs

insideJupyter = misc.inside_jupyter()

logger = logging.getLogger("maelzel")


def hasBinary(binary: str) -> bool:
    if shutil.which(binary):
        return True
    return False


def defaultImageViewer() -> Opt[str]:
    """
    Returns a command string or None if no default was found.
    For that case, use emlib.misc.open_with_standard_app
    """
    if sys.platform == 'linux':
        if hasBinary('feh'):
            return 'feh --image-bg white'
        elif hasBinary('imv'):
            return 'imv -b "#ffffff"'
    return None
コード例 #8
0
ファイル: combtones.py プロジェクト: gesellkammer/maelzel
def _get_jupyter_display():
    if not misc.inside_jupyter():
        return None
    from IPython.display import display
    return display
コード例 #9
0
ファイル: combtones.py プロジェクト: gesellkammer/maelzel
def difftone_sources(result: pitch_t,
                     maxdist=0.5,
                     gap=13.0,
                     minnote=None,
                     maxnote="C8",
                     intervals=None,
                     resolution=1,
                     display=False) -> RecordList:
    """
    find two notes which produce a difference tone near the given note
    
    result: 
        the resulting difference tone, as Note, notename or midinote
    maxdist: 
        the maximum distance between the expected result and the generated tone,
        in semitones (0.5 == 50 cents)
    gap: 
        the distance between the resulting difference tone and the lowest of 
        the two originating notes
    intervals: 
        accepted intervals between the notes. If None is given, a set of intervals
        based on resolution is used
    resolution: 
        the resolution of the pitch grid, in semitones. A resolution of 1 will 
        search for the given difftone along all semitones between minnote and 
        maxnote

    Returns a List of Difftones
    """
    midiresult = asmidi(result)
    maxnote = asmidi(maxnote)
    minnote = minnote or midiresult + gap
    if minnote is None:
        minnote = midiresult + gap
    else:
        minnote = max(minnote, midiresult + gap)
    assert maxnote > minnote
    intervals = intervals or list(frange(resolution, 7, resolution))
    pairs = _difftone_find_source(result,
                                  maxdist,
                                  minnote=minnote,
                                  maxnote=maxnote,
                                  intervals=intervals,
                                  resolution=resolution)
    difftones = [
        Difftone(note0=Note(midi0),
                 note1=Note(midi1),
                 desired=Note(midiresult)) for midi0, midi1 in pairs
    ]
    reclist = RecordList(difftones, fields=Difftone._fields)
    if display:
        # ipython?
        chordseq = EventSeq(
            [Chord(diff.note0, diff.note1, diff.diff) for diff in difftones])
        if misc.inside_jupyter():
            chordseq.show(split=midiresult + 5)
            disp = _get_jupyter_display()
            disp(reclist)
        else:
            chordseq.show()
            print(reclist)
    return reclist