ujimushi(@旧sradjp(15364))の日記

旧スラドの日記の引越先です

Juliaのテキストファイル処理 [ボケ]

茶番(少しの間お遊びにおつきあい下さい)

4月26日金曜日の会社の夕方休憩時間中,いつもの通りZennとかQiitaのJulia情報を探していたところ, ふと一つの記事が目についた。

Juliaでテキストファイルを読み込みたい

その書き出しはこんな感じだった。

「Julia テキストファイル 読み込み」でググってもパッとする記事が引っかからないので ...

え゛っ

同じキーワードでググって,確かにreadline(s)とか使っているものが多いけどそこそこ ちゃんとしてるのが引っかかるじゃんとか思って…

で記事を読んで…

え゛っ

これがこの著者の「パッとする記事」なのか?

そこで私はふと考える。

これは日本のJuliaユーザーに対する侮辱だ。いや中小企業でパッとしない立場の 数学者でもないプログラマーでもない,なんちゃって一人研究部署のJuliaユーザーに対する 挑戦だ。

私は祝一平氏でもないしすごぶる甘等でもないので,誰の挑戦でも受ける訳ではないし, おごられるアップルパイも全ては食べられないが,この挑戦は受けるべきではないか?

挑戦を受けるためにはまず調査だ。「彼を知り己を知れば百戦殆からず」とは誰の言葉だったか。

家に帰ってJuliaユーザーご用達「二冊の鈍器」実践Julia入門Juliaプログラミング大全の中身をパラパラと開いてみる。 何と二冊合わせても「大全」の13.2ストリームぐらいしか言及がない。

ふむ

認めよう。確かに情報は少ない。

しかし,この記事を「パッとする記事」だとすると世界に対して日本のJuliaユーザーレベルに疑いをもたれてしまう。

それなら,低辺のJuliaユーザーであるこの私が「パッとする記事」を書くことで日本のJuliaユーザーの格は 相対的に飛躍的に上昇するだろう。

ならば書くしかない。この私が。

テキストファイル処理

だんだん飽きてきたので,この辺で普通の口調に戻して進めたいと思います。

まず,Juliaのopen関数の戻り値は次の通りIOStreamなので,変数はfileよりioの方が適切です。

julia> io = open("mozc_julia_latex_dict.txt", "r")
IOStream(<file mozc_julia_latex_dict.txt>)

元記事はPythonの影響かとも思ったのですが,

>>> file = open('mozc_julia_latex_dict.txt', 'r')
>>> type(file)
<class '_io.TextIOWrapper'>

とIOのラッパーだったりするので,確実なところだとC言語の影響でしょうか?

で,ここでテキストファイルの読み込み方は大きく三種類。ベタ,原理主義,最小限です。

ベタな方法は次の通り。

io = open("mozc_julia_latex_dict.txt", "r")
text = read(io, String)
close(io)
println(text)

「ベタ」というのは close忘れがあること,処理中の変数が全部外に流れるので 処理中変数の海にさらされることが多いためです。

また,クローズしたioが中ぶらりんになるのも今一つです。 ただ,Windows OSではファイルclose処理が遅く「あえて」全体の処理が終わるまでクローズしない という技等に使えます。

なお, zipfile.readerで開いたファイルがclose出来ない 等での回答でもあるように,Windowsではclose忘れが致命的になることが多いので, ちゃんとしたい時は次の「原理主義」を使う方がいいでしょう。

次は原理主義です。

text = open("mozc_julia_latex_dict.txt", "r") do io
    read(io, String)
end
println(text)

私が「原理主義」と呼ぶのは「close忘れがない」ためです。 また,do節の中で複雑な処理をして最終行にtextに入れる値を置けば 応用も効きやすいので基本はこれを使うべきです。

ただ,ネットの情報ではdo節の最終行を返り値として代入できることを知らないのか printlnで内容を表示している例が多いですが,基本は上のような形で使うべきです。 べき,べき,べき。だから「原理主義」。

次は「最小限」です。

text = read("mozc_julia_latex_dict.txt", String)
println(text)

元々,Julia言語を使っているのは「自分が書くコードを最小にできそう」「自分が書くコードを少なくするためだったら何でもする」という理由からなので,私は断然「最小限」を選びます。

第1引数が関数の関数(余談)

余談にはなるのですが, text = open("in.txt", "r") do io ... のような書き方ができるのは, open(f:Function, arg...; kwargs...)のように第1引数に関数を取れる関数がある時に記述できます。

ですので,

text = open(io -> read(io, String), "mozc_julia_latex_dict.txt", "r")

も「原理主義」のソースと同じ意味になります。

過去の日記の例を解説

実はテキスト処理についてはPlots.jlのGRバックエンド用フォントパッチ(Linux用)にさらっと使用例があります。

といっても元がテキストファイルではなく,コマンドの実行結果のテキスト情報を使っている違いがあります。 該当部分は次の通りです。

function gr_custom_fontlist_linux()
    コマンド出力 = pipeline(`fc-list`, `egrep "[.](ttf|ttc|otf)"`,`cut -d : -f 1`)
    読込(x) = read(x, String)
    終端改行削除(x) = chomp(x)
    行分割(x) = split(x, "\n")
    ファイル名抽出(x) = basename(x)
    fnames = コマンド出力 |> 読込 |> 終端改行削除 |> 行分割 .|> ファイル名抽出
    Dict([(chopsuffix(f, r"[.](ttf|ttc|otf)") , f) for f in fnames])
end

コマンド出力のところは,fc-listのテキスト出力の各行を : で区切って1列目を選択して出力しています。 ですので次の読込で読み込む文字列と同じになります。

読込のところの文字列は次のような感じです。

"""
/usr/share/fonts/truetype/lato/Lato-Medium.ttf
/usr/share/fonts/truetype/noto/NotoSansTelugu-CondensedThin.ttf
/usr/share/fonts/truetype/msttcorefonts/comicbd.ttf
/usr/share/fonts/truetype/noto/NotoSerifHebrew-CondensedLight.ttf
/usr/share/fonts/truetype/noto/NotoSans-SemiCondensedExtraLightItalic.ttf
/usr/share/fonts/truetype/noto/NotoSansGurmukhi-ExtraCondensedMedium.ttf
/usr/share/fonts/truetype/noto/NotoSerif-ExtraCondensedThinItalic.ttf
/usr/share/fonts/truetype/noto/NotoSerifKhmer-Medium.ttf
/usr/share/fonts/opentype/inter/InterDisplay-MediumItalic.otf
/usr/share/fonts/truetype/noto/NotoSansEthiopic-ExtraLight.ttf
/usr/share/fonts/truetype/noto/NotoSansArabic-CondensedThin.ttf
"""

行分割のところで次のようなパス文字列配列に変換します。

["/usr/share/fonts/truetype/lato/Lato-Medium.ttf",
 "/usr/share/fonts/truetype/noto/NotoSansTelugu-CondensedThin.ttf",
 "/usr/share/fonts/truetype/msttcorefonts/comicbd.ttf",
 "/usr/share/fonts/truetype/noto/NotoSerifHebrew-CondensedLight.ttf",
 "/usr/share/fonts/truetype/noto/NotoSans-SemiCondensedExtraLightItalic.ttf",
 "/usr/share/fonts/truetype/noto/NotoSansGurmukhi-ExtraCondensedMedium.ttf",
 "/usr/share/fonts/truetype/noto/NotoSerif-ExtraCondensedThinItalic.ttf",
 "/usr/share/fonts/truetype/noto/NotoSerifKhmer-Medium.ttf",
 "/usr/share/fonts/opentype/inter/InterDisplay-MediumItalic.otf",
 "/usr/share/fonts/truetype/noto/NotoSansEthiopic-ExtraLight.ttf",
 "/usr/share/fonts/truetype/noto/NotoSansArabic-CondensedThin.ttf",
 ...
 ]

ファイル名抽出のところでパス文字配列のファイル名文字列部分だけ抽出します。

["Lato-Medium.ttf",
 "NotoSansTelugu-CondensedThin.ttf",
 "comicbd.ttf",
 "NotoSerifHebrew-CondensedLight.ttf",
 "NotoSans-SemiCondensedExtraLightItalic.ttf",
 "NotoSansGurmukhi-ExtraCondensedMedium.ttf",
 "NotoSerif-ExtraCondensedThinItalic.ttf",
 "NotoSerifKhmer-Medium.ttf",
 "InterDisplay-MediumItalic.otf",
 "NotoSansEthiopic-ExtraLight.ttf",
 "NotoSansArabic-CondensedThin.ttf",
 ...
 ]

といった感じで処理を進めています。

限界...

とまぁこれぐらいが今日私が書ける限界になります。 最後までボケにつき合っていただいてありがとうございました。

thickness_scaling(Plots.jl(GR))

tickを書こうとして少し調査中で分からないものを待っているといつまでも進まないので 手間はかかっても分かるものを進めることとしたい今日この頃。 今回はthickness_scalingアトリビュートを紹介します。

plot関連のアトリビュートです。 実はtickの太さを変えようとした時に,このパラメータしかいじれなさそうということが分かりました。 しかも,このパラメータを変えると,grid等の大きさも変わります。 個別には変えられません。

デフォルトの値1から線の太さを何倍にするか?を指定するパラメータです。 文字の大きさも変わるのはご愛嬌。

別名

  • thickness_scaling
  • thickness_scalings
  • thicknessscalings

デフォルトの値

1(Real)です。

使用例

まずは使用例です。線の太さ,文字の大きさが変わりますが,marginが変になることが特徴です。(苦笑) 線の太さを3倍にしている例です。デフォルトのマージンだと見るも無残なので 上側のマージンだけ調整しています。 ちなみにマージンは負の値も可能なので,結構自由自で調整できます。

using Plots
import GR
gr()

plt_01 = plot(sin; thickness_scaling=3, title="thickness_\\nscaling=3",
              top_margin=(-2.5, :cm), legend=false)

savefig(plt_01, "thickness_scaling3.png")

マージンを全部修正(個人の感想です)してみます。

using Plots
import GR
gr()

plt_02 = plot(sin; thickness_scaling=3, title="thickness_\\nscaling=3\\nmargin fix",
              left_margin=(-1.5, :cm), top_margin=(-4.0, :cm), legend=false,
              bottom_margin=(-0.5, :cm))

savefig(plt_02, "thickness_scaling3_fix.png")

線は太くなりましたが,ずい分文字も大きくなっています。

元々はグラフのサイズを大きくした時に簡単に文字を大きくする用のパラメータな気がします。

using Plots
import GR
gr()
plt_03 = plot(sin; thickness_scaling=3, 
              title="thickness_scaling=3 large size",
              left_margin=(-1.5, :cm), top_margin=(-1, :cm), legend=false,
              bottom_margin=(-0.5, :cm), size=(1600, 1200))

savefig(plt_03, "thickness_scaling3_fix_large.png")

これをサイズだけ大きくしたものと比べてみます。

using Plots
import GR
gr()
plt_04 = plot(sin; title="no thickness_scaling, large size", size=(1600, 1200))

savefig(plt_04, "no_thickness_scaling_large.png")

線も細く,文字がちんちくりんになりますね。

マージンが自動でいい値にならない不満はありますが,グラフのサイズを大きくする時に 使えるアトリビュートではないかと思います。

How to custom unicode completions?[勝手に回答]

やっぱり続くよ勝手に回答。今回は How to custom unicode completions?。いつものDiscourse julialangからの質問です。

というか後数時間も経つといっぱい回答が出てると思いますが…

Julia言語のREPLのunicode補完をカスタマイズしたいんだけど,どうしたらいい?的な質問です。

質問の場合だと次のような感じでしょうか7

import REPL

REPL.REPLCompletions.latex_symbols["\\doubleflat"] = "𝄫"
REPL.REPLCompletions.latex_symbols["\\doublesharp"] = "𝄪"

なお,Google日本語入力で実現する方法は私の日記のJuliaのREPL上のLaTeX入力をMozc(Google日本語入力)で実現する に情報があります。

REPLによるPlotsオブジェクト探訪

Plots.jlに関してREPLを使った少しお遊びの内容です。 バージョン1なので,gr()は省略します。

Juliaを立ち上げてPlotsモジュールを読み込みます。

   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.10.2 (2024-03-01)
 _/ |\__'_|_|_|\__'_|  |  Official https://julialang.org/ release
|__/                   |

julia> using Plots

Plotオブジェクトをpltに代入します。

julia> plt = plot(sin)
Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.

そして,plt.と入力してからキーを押します。

julia> plt.⭾
           
attr            backend
init            inset_subplots
layout          n
o               series_list
spmap           subplots

と候補がでてきます。

backendを確認してみます。

julia> plt.backend
Plots.GRBackend()

このように今のバックエンドが表示されます。

続きを読む

title(location|(font[hv]align))(Plots.jl(GR))追加情報

今回の内容はtitle(|location|font(family|size|color|rotation|[vh]align)) (Plots.jl(GR)) の追加情報になります。

まぁ何というか公式のアトリビュートのドキュメントに

Atrribute Aliases Default Type Description
titlelocation ... :center Symbol ...

ってあったので,シンボル型だとうのみにしていたのだが,どうもタプルでの指定も可能らしい… というのが,この記事の主な内容になります。

一応,titleのポジション指定の概念図を次に示します。 赤字の部分が指定する感じです。 といっても前回のmargin関係の図の流用です。

続きを読む

((top|bottom|left|right)_|)margin(Plots.jl(GR))

ほぼ初めてのfontやテキスト以外のアトリビュートの説明になります。 この説明をするのは,title_locationでもplot_titlelocation と同じようなことができることが分かったため,マージン関係を 説明しておいた方がいいと判断したためです。

早速説明していきます。

概念図

大作です(?)。 前回のtitle_locationと似たような図です。なお,前回確認し忘れていましたが,plot_title=""(空文字)の時は plot_titlevspan0相当となります。たとえ値を個別に設定したとしてもです。

続きを読む

最近のubuntuで英語キーボードのCapsLockキーをHyperキーとして利用する

方法は次の通り。

  1. TweaksのCaps Lock behaviorCaps Lock を追加のHyperにするにチェックマークを入れる
  2. ~/.config/xkb/symbols/capslockの設定ファイルを次のように作成してログインし直す
xkb_symbols "hyper" {
    key <CAPS> { [ Hyper_L ] };
    modifier_map Mod3 { <CAPS> };
    modifier_map Mod3  { <HYPR> };
    modifier_map Lock  { <LVL5> };
};

本来は「1.」の設定だけでうまくいくはずなのだが, Hyperキーが「Mod4」でSuperキーと被っているので CapsLockを入力するとSuperキーとして認識されうまくいかない。

そこで,何も使っていない「Mod3」にHyperキーを移動するのだが ここで,CapsLockだけ移動すると本家本元のHyperキーが 「Mod4」に残っててやはりSuperキーと認識されてうまくいかないので, 元のHyperキーも「Mod3」に移動する。 「LVL5」の設定はどうでもいいおまけ。

という意味だと自分自身では解釈している。

この設定も1,2年かけて調べて試行錯誤してようやく分かった内容だ。といってもHyperキーに対応しているアプリは今となってはほとんどなく, ほぼEmacsのための設定だ。

Kinesisではコントロールキーが親指側にあり, CapsLockをHyperキーとしてEmacsの独自キーバインドとして追加するとショートカットの幅が広がり,非常に重宝している。