2018 年版が古くなったので更新。
国内・海外出張共通
国内出張
- (物理学会のとき) 名札
海外出張
- パスポート
- e-ticket の印刷と PDF
- 現地の Google Maps の offline map
- ワインケース
- ヨーロッパ用 Mac の AC ケーブル
- ヨーロッパ用のコンセントアダプタ
- 現地通貨
- 銀行の海外出金用カード
- オイスターカード(London の場合)
2018 年版が古くなったので更新。
愛知県常滑市で「NAMIMONOGATARI2021」(以降、波物語)という野外音楽フェスが 2021 年 8 月 29 日に開催されました。報道によれば、緊急事態宣言下で 7392 人の参加者があり、会場での酒販・飲酒、一部参加者のマスク非着用が認められ、また参加者同士の距離を十分に取らない身体接触や出演者も煽る形での声出しが行われました。
愛知県等の発表資料によると、波物語に関係する新型コロナウイルスの陽性者は、9 月 19 日現在で 47 名です。この内訳は次の通りです。
このうち、クラスター(10L)の 27 名、および岡崎市 10 代男性から同居家族(岡崎市 40 代女性、同 10 代男性)への拡大を 1 つの経路図として図示したものが、次の図です。
ここで注意したいのが、名古屋市管轄や愛知県管轄の陽性事例は接触経路が 8 月から非公表になったということです。そのため、岡崎市・豊川市・豊橋市・豊田市以外に居住する事例の場合、接触経路は不明です。つまり、仮に 2 次感染があったとしても、それが明らかになるのはこの図では岡崎市事例と豊橋市事例のみになります。
この図では岡崎市・豊橋市在住者は 3 名だけですので、大雑把には 3 分の 1 の確率で(保健所の追跡可能な)2 次感染が発生すると言えます。単純計算で 27 名中 9 名が 2 次感染をさらなる 2 名に起こしていたとすると、2 次感染の人数は 18 名程度と推測できます。
また、愛知県は単にクラスター 10L とだけ公表しておりその中でどのような接触経路が存在したかまでは公開していないため、先頭の稲沢市 20 代女性が全員に感染させた、いわゆるスーパースプレッダーであったという意味でもありません。感染日と、発症・受診・検査の時期は人によって異なります。あくまでこの図は陽性判明の時系列を表しているにすぎません。
この感染経路図の作成方法については、愛知県・岐阜県の感染経路図を可視化した際に書いた記事を参照してください。(この頃はまだ 329 事例でしたが、結局愛知だけで 10 万事例を超えたのにまだ継続しています。)
oxon.hatenablog.com
oxon.hatenablog.com
愛知県が通常「クラスター」として認定し公表するのは、次の条件を満たしている場合だと考えられます。
※ ただし、豊橋市の高校でかなりの生徒に感染が広がった事例は、同一時間、同一場所ではないということでクラスター認定されなかった。
※ また、保健所の基準で濃厚接触ではなく接触が疑わしい程度だと、同じ職場で 10 名を超えていてもクラスター認定されない場合がある(例えば愛知県内の最初のデルタ株事例は職場感染を含め合計 26 名までの拡大が追跡されたが、職場内での接触経路は公開されずクラスター認定もなかった)。
しかし、この波物語クラスターは本当に愛知県がこれまで採用してきた「クラスター」の定義に合致するかは怪しいところです。27 人もいて、接触を辿れる同一のグループ行動を音楽フェス内でしていたとは考えにくいと思います。実際、愛知県外の事例は大規模な人数ではなく、またこの 27 人の居住地もあまりにバラバラです。
9 月 2 日の稲沢市の 20 代男性は稲沢市の消防士であることが報道から分かっており、この方は友人 2 人と参加したと発表されています。したがって、この 27 人はいくつかのグループに分割するのが自然であり(会場で同じ日に感染したものの、互いに接触していない複数のグループに分かれる)、愛知県がこれまで「クラスター」と呼んでいた形態とは異なるのではないかと思います。
また時系列を追ってみると分かりますが、稲沢市在住者 4 名が先頭に固まっていること、9 月 10 日の東海市事例は当初、経路不明(塗り潰し)として公表されていたこと、後半は名古屋市在住者が多数を占めることなどから、この「クラスター」と愛知県が呼んでいるものは、会場内で同時多発したいくつかの小規模クラスターなのではないかと自分は推測しますれます。またもし普段から行動をともにしている友人同士だった場合、たまたま波物語の開催時期に重なっただけで、その前からもしくは事後に友人同士で感染していた(した)可能性もあります。
2 次感染は無視したとして、7392 人の参加者のうち判明しているだけで 45 名の陽性事例が 14 日間にわたり発生したことになります。愛知県の 10〜20 代人口は約 150 万人です。また 9 月 1〜14 日の期間における愛知県内 10〜20 代の陽性事例は 6777 事例(10 代 2456、20 代 4321)です。したがって、これまた非常に単純な計算をすると (45/7392) / (6777/1500000) = 1.35 倍の確率で波物語は陽性事例が発生しやすい状況であったということになります。クラスターとして認定されていなかったり、参加した旨を申告していない感染者も実際にはいるでしょうから、多めに見積もって約 2 倍だと考えましょう。
これを多いと見るか、それとも大したことないと考えるかは、ちょっと難しいところです。(完全に偏見と、自分自身のクラブに行ったりしていた 20 年前の経験ですが)そもそも波物語の客層は新型コロナウイルスに感染しやすい交友関係を持っていた可能性があります。つまり、波物語に参加しなくても、遅かれ早かれどうせ友達同士で感染していたであろう人たちが、波物語をきっかけに感染した可能性があります。
例えば名古屋大学の学生数は約 15000 人ですが、このうち 9/1〜14 の期間で大学から公表された感染者数は 4 名です。上述の愛知県内 150 万人の 10〜20 代の感染事例 6777 と比較すると、10 分の 1 程度の発生頻度でしかなく、新型コロナに感染しやすい層としにくい層がいるのは明らかです。
波物語だけを敵視しなくても、4 人程度の若者同士の会食は愛知県内で 2000 回よりは桁で多く発生していると思われ、そのような場は県内全体の平均的な感染確率よりも高い環境であり、第 5 波の感染拡大に圧倒的に寄与しているはずです。
もちろん野外音楽フェスでもライブでも感染対策をするに越したことはありません。しかし「自粛の要請」という意味の分からない日本語を行政が振りかざし、特定のフェスにだけ愛知県知事が検証委員会を作って槍玉にあげるのは、「やっている感」を出したり怨嗟の吐口にするだけであって、日本全体、愛知県全体の感染拡大防止としては効果が薄いのではないかと思います。
この大雑把な計算で野外音楽フェスのリスク評価をするのは難しいですが、愛知県内全体の感染に比べて特に問題視するようなことではない、というのが自分の印象です。もっと定量的な評価は愛知県や国がしっかり行う必要があると思います。(感染拡大自体を自分は問題視しているので、波物語が感染防止対策を徹底しなかったのは問題視されるべきだが、波物語だけを攻撃するのは違うのではないか、ということです。)
計算間違いや、より定量的な評価方法などがあれば、ご指摘ください。
4 月から開始した愛知・岐阜における新型コロナ感染経路の可視化は、既に報告件数 20000 件超を扱うようになりました。
このうち会食や職場など様々な感染経路が存在しますが、10 歳未満の子供の新型コロナの感染経路の実態はどうなっているのか。より個人的な観点からは、我が家の子供達が小学校や保育園で感染してくるか、また家庭内感染へと広がりうるのか。そういうことを実際の感染事例から概観してみたいと思います。
※1 この記事に書く内容は、あくまで愛知県、名古屋市、豊田市、岡崎市、豊橋市、岐阜県、岐阜市の公開データに基づきます。そのため、症例の詳細や保健所や当事者しか知らない感染経路の本当のところは分かりません。
※2 これは医療関係者でも感染症の専門家でもなんでもない、素人の blog 記事です。
※3 10 歳未満に限っているのは、10 代を含めると(公開データが年代別になっており)18 歳以上の行動パターンと区別が困難になるためです。
国民の多くに新型コロナ対策が浸透し、それでもなお第 3 波が愛知県で広まり始めたのは 2020 年 10 月中旬のことです。このうち、11 月 1 日以降の陽性報告で陽性者の年齢が「10 歳未満」「0 歳」「1 歳未満」となっている事例と、それら事例に接触者・濃厚接触者として関連づけられている事例のみで、全ての感染経路図を作成しました。
かなり巨大な PDF として GitHub に公開しています。「2021-01-08(愛知、10 歳未満の子供を含むクラスターのみを表示)」というリンクがそれです。
github.com
PDF への直リンクはこちらです。
https://github.com/akira-okumura/COVID-19/raw/master/PDF/Aichi2021-01-08_kids.pdf
さてこのうち、保育施設で発生した大きいクラスターは 2 件のみです。小学校では自分の知る限り報道に出る規模のクラスターは発生していません。
1 つ目は愛知県がクラスター 3E と呼んでいる名古屋市の保育施設で発生したもの。これは職員と思われる 20〜40 代の方々と、施設利用者である 10 歳未満の子供たちで構成されます。ここで、報告順が左から並んでいるからといって、先頭の方がウイルスを持ち込んだかのように解釈しないでください。感染日と発症日と陽性確定日は人によって前後するためです。また線が繋がっているからといって接触している、感染させた、とは限りません。多数の線が出ているからといって「スーパースプレッダー」というわけでもありません。
このうち、施設職員と母親(と思われる)に繋がっている子供は 9 名中 1 名のみですが存在します。すなわち、もし施設内でまず感染が広がり、その後この子供が家庭内感染を起こしたとすると、感染をある場所から他の場所へ広げていることになります。逆に家庭内で先に感染が起き、その後施設内でクラスターを発生させた可能性もありますが、その場合もやはり、10 歳未満の子供が他の場所へ拡大させる役割を持つことが分かります。
この図からは少なくとも感染の上流がどちらであったかは判断つきません。しかし 10 歳未満の子供(おそらく 6 歳以下)が感染を他の場所へ移動することは間違いありません。
2 つ目は同様に名古屋市内の保育施設もしくは学校のクラスター 3 Gです。これも 3E と同様、20〜60 代の職員と思われる方々と子供たちで構成されます。ここでも 9 名の子供のうち 1 名は家庭内感染と繋がっているため、他の場所へと感染を拡大させる場合があることが分かります。
クラスター 3E と 3G の事例の子供たちは家族構成が比較的似通っている(30〜40 代の両親もしくは片親、兄弟姉妹など)と考えられるため、このような家族構成の子供 18 事例中、ウイルスを他の集団に移動させたのは 2 事例だと言えます。ただし、他の家庭でも感染は起きていたのに、無症状かつ PCR 検査にかからなかった可能性は排除できません。
それぞれの施設内でどのように感染が広まったかは明らかになっていないため、子供達が遊ぶときに互いにベタベタ触ったのか、それとも子供や職員の飛沫感染が起きたのかは分かりません。しかし、子供から家庭感染への拡大が起きにくいことを考えると、子供から職員へ移したという可能性は低いのではないかと思います。親子の接触に比べると、子供と職員の接触は薄いためです。
ここで、10 歳未満ではありませんが、飲み会による感染を起こさないと思われる高校生のクラスター事例も見てみましょう。
学校内でどのように感染が広がったかは報道にありませんが、高校生と思われる 10 代の 28 名のうち、家庭内感染は 4 件のみです。小さい子供に比べると親子の接触は減っていると思われますが(経験談)、3G・3E の 18 事例中の 2 事例と同程度の、28 事例中の 4 事例です。
ただし、このクラスターは全部で 45 名いるはずなのですが、岐阜県の公表データからは 38 名しか経路図として接続できることができませんでした。7 事例が家庭内感染もしくは他の生徒の事例として隠れているかもしれません。
こちらの事例は、おそらく最初の 4 名は 3 世代の家庭内感染(濃厚接触)です。最後の 10 歳未満の 2 名は、このうち真ん中の 10 歳未満の 2 名との「関連からの検査」として公表されています。「関連からの検査」という書き方は、その濃厚接触ではないが、その発生した集団内になんらかの形で属していた場合に使われる表現です。同居家族であれば「接触」や「濃厚接触者」として書かれる場合が多いはずです。
つまり、これら 4 名の 10 歳未満の子供たちは同じ集団に属しており、濃厚接触かどうかは追跡調査で判明しなかったものの、集団内で感染が起きたということです。その集団に大人がいるはずですが、大人への感染は確認されなかったと言えます。したがって、単純には 10 歳未満の子供同士で感染させ合う可能性があるということです。(インフルエンザでも学級閉鎖が起きるので当たり前ですが)
こちらの事例では、中央の縦 1 列に 10 歳未満の子供が 3 名おり、これは先頭から繋がる何らかの集団(保育施設など)と思われます。
このうち 1 番下の女の子はこの左側の集団を含め 4 つの異なる大人へと繋がっています。つまり、4 つの集団のうちどれが感染の上流かは分かりませんが、子供を媒介として複数の集団へ感染を拡大させる場合もあるということです。
こちらの例では、大人から子供に感染し、それが他の子供へ感染し、さらに大人へ移すという事例です。もし子供から大人は移りにくい、子供同士は移りにくいというのが事実だとしても、それらの低い確率を掛け合わせた事例というのも、これだけ感染者が増えてくると存在するということです。ただし稀です。
多くの子供の感染事例のうち、頻繁に目にするのが感染経路不明の親(父親が多い)から家庭内感染をしたと思われる事例です。特にこれらの家庭(と思われる)を取り上げた理由はありませんが、典型例です。
父親が外からもらってきたのか、母親がもらってきたのかは発症日と感染日に時間差があるため、これらの図では分かりません。ただし、傾向として父親が先に陽性確定する事例が多いということです。
現在、愛知県内、岐阜県内では様々なクラスターが発生しており、当然そのようなクラスターに含まれる大人の中には、小さい子供を持つ方たちも多くいます。そのような場合、クラスターの末端に子供がくるというのもたまに見かけます。
当たり前ではありますが、子供から子供へも感染させる、子供から大人へも感染させる、そして大人から子供へ家庭内感染させたと思われる事例が圧倒的に多いということが確認できました。ここで取り上げた事例以外にも多数の経路が載っていますので、興味のある方は全体 PDF を眺めてみてください。
https://github.com/akira-okumura/COVID-19/raw/master/PDF/Aichi2021-01-08_kids.pdf
我が家の考え方としては、次の通りです。
2020 年の 4 月から愛知・岐阜の新型コロナの報告事例観察を継続しています。
oxon.hatenablog.com
さて、年末年始の帰省による人の移動で新型コロナが地方に広められてしまうのではないかという心配がありました。(発掘できなかったのですが)年末年始に診療にあたる医師が帰省してきた感染者の診察を何件かしているという Twitter の投稿も見かけました。
また実際、2021/1/5 の愛知県の発表では「東京などから年末年始に帰省して県内の実家で発症した例も複数含まれる」ということで、それが全国的な感染拡大にどのような影響を与えるのか心配なところです。
www.tokai-tv.com
そこで、2020 年 11 月以降の愛知県内の陽性報告事例のうち、住居地が愛知県・岐阜県・三重県以外の事例のみを抽出したのが上の図です。これを見ると、10〜30 代の大都市圏(東京都 + 千葉県 + 神奈川県、大阪府、京都府など)に居住する若者が愛知県内で発症する事例が、12/29 以降に突然、頻発するようになったのが分かります。年末年始の帰省によって、大都市圏から地方へ(この場合は愛知県ですが)新型コロナウイルスが拡散されるのが改めて確認されました。
No | 発表日 | 年代・性別 | 住居地 | 接触状況 |
---|---|---|---|---|
6353 | 11月3日 | 30代男性 | 東京都 | 10月31日まで東京都に滞在 |
8509 | 11月21日 | 40代男性 | 福井県 | |
13553 | 12月18日 | 50代男性 | 千葉県 | |
13564 | 12月18日 | 40代男性 | 沖縄県 | |
13759 | 12月18日 | 30代男性 | 東京都 | |
13795 | 12月19日 | 40代男性 | 千葉県 | |
13963 | 12月19日 | 20代男性 | 兵庫県 | |
14215 | 12月21日 | 40代男性 | 大阪府 | No.12325,12324と接触 |
14565 | 12月23日 | 50代男性 | 福岡県 | |
15285 | 12月26日 | 30代男性 | 石川県 | フィリピン |
15511 | 12月27日 | 50代男性 | 東京都 | |
15907 | 12月29日 | 20代男性 | 神奈川県 | |
16043 | 12月29日 | 50代男性 | 京都府 | |
16100 | 12月30日 | 30代男性 | 福岡県 | No.15711と接触 |
16389 | 12月31日 | 60代男性 | 東京都 | |
16422 | 12月31日 | 20代男性 | 東京都 | |
16618 | 1月1日 | 20代男性 | 東京都 | |
16722 | 1月1日 | 20代女性 | 東京都 | |
16724 | 1月1日 | 10代男性 | 京都府 | 京都府事例と接触 |
16766 | 1月1日 | 20代男性 | 東京都 | |
16825 | 1月2日 | 20代男性 | 大阪府 | |
16831 | 1月2日 | 20代女性 | 東京都 | |
16834 | 1月2日 | 30代女性 | 東京都 | 東京都事例と接触 |
16874 | 1月2日 | 30代男性 | 東京都 | |
16957 | 1月3日 | 20代男性 | 茨城県 | No.16295と接触 |
17112 | 1月3日 | 30代女性 | 東京都 | |
17137 | 1月4日 | 10代男性 | 北海道 | 北海道事例と接触 |
17138 | 1月4日 | 20代男性 | 大阪府 | 大阪府事例と接触 |
17321 | 1月5日 | 20代女性 | 東京都 | |
17337 | 1月5日 | 20代男性 | 大阪府 | |
17383 | 1月5日 | 20代男性 | 群馬県 | |
17402 | 1月5日 | 20代男性 | 東京都 | |
17404 | 1月5日 | 20代女性 | 東京都 | |
17458 | 1月5日 | 20代男性 | 千葉県 | 千葉県事例と接触 |
17521 | 1月5日 | 20代男性 | 東京都 | |
17768 | 1月6日 | 10代男性 | 福井県 | No.17216と接触 |
17802 | 1月6日 | 20代女性 | 京都府 | |
17804 | 1月6日 | 60代男性 | 静岡県 | |
17886 | 1月6日 | 20代男性 | 京都府 | |
17900 | 1月6日 | 30代男性 | 東京都 | |
17952 | 1月7日 | 20代女性 | 東京都 | |
18415 | 1月8日 | 20代男性 | 奈良県 | |
18642 | 1月8日 | 20代女性 | 東京都 |
少なくとも 1 月 8 日(発症日ではなく公表日)の時点でこのような事例が愛知県内だけで 30 件発生しています*1。愛知県人口が 750 万人で、多くの帰省を受け入れる県・道の人口がおよそ 10 倍の 7500 万人と見積もると、全国で同様の事例が 200〜300 件は発生しているのではないかと推測されます。多くの場合、帰省中に家族や旧友と飲食をしていると考えられるので、この 200 件に少なくない数がさらなる感染者数として上乗せされると推測されます。
このうちの 9 事例では、帰省中の愛知県内での接触により感染拡大が起きている可能性があります。
*1:ただし、そのうち 16110 と 16957 の 2 件は、帰省中に愛知県内で感染したと思われる。
TeX Live 2018 + Mojave の環境までは LaTeXiT で Feynman diagram を描くときは阪大の山中さんのページを参考にしていましたが、Catalina + TeX Live 2019 にしたら図がちょん切れるようになった(bounding box がおかしくなった)ので、解決する方法の覚え書きです。
詳細は StackExchange にも質問で書きました。
latex
+ dvipdf
は使わない(そもそも、dvipdf
だと図が真っ白になる)dvipdfm
にすると図がちょん切れるので、これも使わない\usepackage{feynmp}
だけでなく \DeclareGraphicsRule{*}{mps}{*}{}
も追加するmpost
の実行後、pdflatex
で PDF を出力させる古いやり方だと \usepackage{feynmp}
を追加するだけでしたが、これだけだと mpost
コマンドの生成する拡張子なしの PS ファイルを pdflatex
が正しく取り扱えません。そのため、古いやり方では latex
と dvipdf
を使って DVI を経由させていたのだと思います。
\DeclareGraphicsRule{*}{mps}{*}{}
も追加することで、拡張子のないファイルを pdflatex
が扱えるようになるので、TeX Live 2019 や 2020 で現れる dvipdf
もしくは dvipdfm
の問題(仕様?)を回避することができます。
TeX Live 2018 まで問題なかった山中さんのやり方で dvipdf
を dvipdfm
にすると絵は出てきますが、下がちょん切れていますね。
Homebrew を使って IPython を導入する際、brew install
を使うやり方と、pip3 install
をやり方の主に 2 つの方法があると思います。前者でやると IPython 起動時に PYTHONPATH を勝手に書き換えてしまうことが分かり、少しはまりました。そもそも ipython
コマンドというのは bash script だったり、Python script だったり、環境によって違うのだということを知りました。
macOS 10.15.5 です。
これは書くまでもありませんが、https://brew.sh/の説明通りに次のコマンドを実行します。
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
brew install ipython
の場合(非推奨)さて、IPython を入れたいのだから brew install ipython
と単純にやると次のようになります。
$ brew install ipython
$ rehash
$ which python
/usr/bin/python
$ which python2
/usr/bin/python2
$ which python3
/usr/bin/python3
$ which ipython
/usr/local/bin/ipython
$ which pip
pip not found
$ which pip3
/usr/bin/pip3
つまり、macOS 標準の Python をデフォルトとして維持したまま ipython
コマンドだけ入ります(実際には他にも色々と入りますが)。pip3
も入りません。
そして ipython
の中身は次の bash script です。PYTHONPATH
を勝手に書き換えてしまいます。
$ cat `which ipython` #!/bin/bash PYTHONPATH="/usr/local/Cellar/ipython/7.15.0/libexec/lib/python3.8/site-packages:/usr/local/Cellar/ipython/7.15.0/libexec/vendor/lib/python3.8/site-packages" exec "/usr/local/Cellar/ipython/7.15.0/libexec/bin/ipython" "$@"
これで PyROOT を使おうと思っても PYTHONPATH
から ROOTSYS/lib
が消えてしまい、おかしいおかしいと悩んでしまいました。これは bug じゃないかと思いますが、Homebrew の issue report をどこに上げるのかよく分からなかったので、放置しています。
brew install python
を先にする場合(非推奨)$ brew install python $ rehash $ which python /usr/bin/python $ which python2 /usr/bin/python2 $ which python3 /usr/local/bin/python3 $ which pip pip not found $ which pip3 /usr/local/bin/pip3
python3
コマンドが /usr/local/bin
に入り、python
と python2
は OS 標準です。この場合だと、pip3
も入りました。
$ brew install ipython
$ rehash
$ which ipython
/usr/local/bin/ipython
ipython
の中身は同じです。
$ cat `which ipython` #!/bin/bash PYTHONPATH="/usr/local/Cellar/ipython/7.15.0/libexec/lib/python3.8/site-packages:/usr/local/Cellar/ipython/7.15.0/libexec/vendor/lib/python3.8/site-packages" exec "/usr/local/Cellar/ipython/7.15.0/libexec/bin/ipython" "$@"
pip3 install
の場合(推奨)$ brew install python $ rehash $ pip3 install ipython $ rehash
brew install python
の後に rehash
を忘れないようにしましょう。そうしないと、/usr/bin/pip3
が使われてしまいます。
cat `which ipython` #!/usr/local/opt/python/bin/python3.7 # -*- coding: utf-8 -*- import re import sys from IPython import start_ipython if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) sys.exit(start_ipython())
$ cat `which ipython3` #!/usr/local/opt/python/bin/python3.7 # -*- coding: utf-8 -*- import re import sys from IPython import start_ipython if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) sys.exit(start_ipython())
はい、こっちだと PYTHONPATH
を勝手に書き換えませんし、bash ではなく Python です。こちらのやり方が推奨です。
これは conda create
で新しい環境を作ったときに入った ipython
コマンドの中身です。また中身が違いますが、ほとんど一緒です。
#!/Users/oxon/anaconda3/envs/sstcam_root/bin/python # -*- coding: utf-8 -*- import re import sys from IPython import start_ipython if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) sys.exit(start_ipython())
macOS Catalina もしくは Monterey で PyVISA と PySerial を使うときの覚え書きです。PyVISA のほうは普通にやると、はまります。詳しい人向けの結論を先に書くと、NI-GPIB を先に入れないと NI-VISA が入らない、です。
※(2022/4/15 更新)Monterey の場合を加筆しました。
brew install python
で)pip3 install pyvisa
で)pip3 install pyserial
で)NI-VISA Runtime 19.0.0
macOS Monterey 12.2.1
pip3 install pyvisa
で)以前にこういう記事を書いたのですが、かなり情報が古くなってしまいました。当時は 32 bit と 64 bit が混在している時代で、Python も 32 bit だったり、National Instruments も Mac 用のドライバの配布が遅かったりと、苦労していました。 oxon.hatenablog.com Mojave から Catalina 環境に移行するにあたり、少し PyVISA ではまったので、記録に残しておきます。
うちの学生向けに書くので、比較的丁寧です。
VISA(Virtual Instrument Software Architecture) というのは、いろいろな実験室の計測装置を共通のソフトウェアで簡単に使えるようにしましょうという規格です。「査証」やクレジットカードの VISA とは関係がありません。
実験室にある計測装置の背面を見てみると、電源ケーブル以外に色々なケーブルを接続できることに気がつきます。古い機種だと RS-232C と呼ばれる規格の端子がついています(シリアルポートとも呼ばれます)。これは 9 本の剥き出しのピン(オスの場合)だったり、9 本のピンが差し込めるようになっているメスのポートだったりします。昔は計算機側にもこのポートが 2 つずつ付いていることが多かったのですが、今どきは付いていません。しかし実験室では、特にデータ転送速度を重視しない機器(低圧電源や回転ステージなど)ではいまだに使われることが多いです。
少し時代が経ち、オシロスコープのようにデータ量の多い装置では GPIB(IEEE の規格は IEEE 488)というケーブルの規格が使われるようになりました。最近はあまり見かけませんし、元々 GPIB 搭載の可能な機種でもオプション扱いのものが多かったと思うので、20〜30 年前くらいの高いデジタルオシロスコープなんかに付いていたりします(安いものにもついていたと思いますが、30 年前の安いものは既に廃棄処分されていると思います)。見た目がゴツくて格好いいやつです。写真はリンク先を参照。
最近だと、USB 端子がつく機種も増えました。むしろ新しい機種で USB すら付いていない製品やそんなものを販売する会社は、手を出さないほうがいいんじゃないかという気がします。USB 1.1(最大 12 Mbps)は低速の用途にも良いですし、USB 2.0(最大 480 Mbps)ならオシロスコープのようなデータ量の多い装置にも十分耐えられます。USB 3.0(最大 5 Gbps)以降を使用している機種は、2020 年現在、まだ多くないと思います。
オシロスコープのように通信量が大きい装置は、USB ではなく Ethernet ポートを備えたものもあります。機種によって 100 Mbps だったり 1 Gbps だったり 10 Gbps だったり、様々です。自分が実験で使う場合は USB 2 より Ethernet のほうが転送速度が早いため Ethernet を使いますが、この記事で説明するにはネットワークの設定の説明が面倒なのと、実験室ごとに設定がいろいろ変わるので、Ethernet の説明は省き USB 中心で説明します。
さて、VISA の話に戻ると、こういう異なるケーブルや通信プロトコルごとにソフトウェアを書き換えるのは面倒なので、一括で同じように扱えるようにしようというのが、VISA です。例えば何か計算機からコマンドを周辺機器に送るとき、もしくは周辺機器から計算機にデータが送られてくるとき、VISA 経由でやれば、どのケーブルやプロトコルを使用しているのかはほとんど気にしなくて良くなります。
PyVISA は、Python から VISA に対応した周辺機器とやり取りするための機能を提供してくれます。macOS Catalina に Homebrew で Python 3 を導入している場合、次のように pip3
コマンドで PyVISA をインストールします。
$ pip3 install pyvisa
後述する NI-GPIB や NI-VISA のインストールされた環境では、この PyVISA を使うことによって周辺機器と簡単に通信することができるようになります。次の例は、IPython から Tektronix の MSO4102B というオシロスコープに接続してシリアルナンバーなどの情報を得ているところです。
$ ipython In [1]: import visa In [2]: rm = visa.ResourceManager() In [3]: rm.list_resources() Out[3]: ('USB0::0x0699::0x041B::C022756::INSTR',) In [4]: usb = rm.open_resource(rm.list_resources()[0]) In [5]: usb.query('*IDN?') Out[5]: 'TEKTRONIX,MSO4102B-L,C022756,CF:91.1CT FV:v2.90 \n'
RS-232C での通信の場合は、ボーレート(baud rate)やデリミター(delimiter)などを気に掛ける必要がありましたが、VISA なら勝手にうまいことやってくれます。
デバイスドライバの部分は、PyVISA 自身はやっていません。macOS の場合、PyVISA は National Instruments(NI)の NI-VISA というデバイスドライバーをバックエンドとして使用しています。
バージョン番号は適宜最新のもので読み替えてください。
macOS Monterey から、NI の機能拡張を使うには一手間かかるようになったので、事前にこの作業をします。この作業をすることで、macOS に NI を信頼できる開発者として認識させます。
まず Mac を再起動し、その際に Cmd-R を長押ししてリカバリーモード(recovery mode)に入ります。その後、Tools メニューから Terminal を開き、次のコマンドを実行します。
spctl kext-consent add SKTKK2QZ74
この SKTKK2QZ74
は NI の developer ID です。
spctl kext-consent list
で、SKTKK2QZ74
が表示されるのを確認し、再起動しましょう(そのまま reboot
と入力・実行すれば良い)。
PyVISA を使うには NI-VISA が必要で、NI-VISA を Catalina に入れるには NI-GPIB を先に入れる必要があります。リンク先から、Supported OS に MacOS、Version に 19.5 を選択してディスクイメージ(拡張子 .dmg)をダウンロードします。
NI-488.2 19.5.dmg を開くと NI-488.2 19.5.pkg が現れるので、これを開き、あとは指示に従ってインストールします。これは GPIB を Mac で使用するための NI 社製のデバイスドライバーです。再起動が必要です。
macOS 10.13 と 10.14 しか対応していないとなっていますが、10.15 で動作します。
もしも .pkg を開けないとダイアログが出てきた場合、右クリックから開くようにすると次のダイアログが出るので、Open を選択してください。
次に、NI-VISA を入れます。同様に Mac 版の 19.0 を入れます。この際、Included Editions は Runtime にすれば十分です。Full でも良いですが、PyVISA だけの使用であれば不要です。 www.ni.com
NI-VISA_Runtime_19.0.0.dmg を開くと NI-VISA_Runtime_19.0.0.pkg が現れるので、これも同様にインストールしてください。再起動は多分必要ありません。
Homebrew 環境の場合、pip
から入れてください。Python 3 であれば pip3
です。
$ pip3 install pyvisa
PyVISA とともに pyvisa-info
というコマンドがインストールされるので、これが /Library/Frameworks/visa.framework/visa
にある NI-VISA を自動的に検出できていれば成功です。
$ pyvisa-info Machine Details: Platform ID: Darwin-19.5.0-x86_64-i386-64bit Processor: i386 Python: Implementation: CPython Executable: /usr/local/opt/python/bin/python3.7 Version: 3.7.6 Compiler: Clang 11.0.0 (clang-1100.0.33.16) Bits: 64bit Build: Dec 30 2019 19:38:26 (#default) Unicode: UCS4 PyVISA Version: 1.10.1 Backends: ni: Version: 1.10.1 (bundled with PyVISA) #1: /Library/Frameworks/visa.framework/visa: found by: auto bitness: 64 Vendor: National Instruments Impl. Version: 19922944 Spec. Version: 5244928
もし abort したというエラーが出る場合、System Preferences の Security & Privacy で NI 製のソフトウェアがブロックされていないか確認してください。もしこの画像のようにブロックされている場合、鍵を外して Allow を押して、許可してやりましょう。
先述したコマンド例の繰り返しになりますが、VISA に対応しているはずの適当な実験装置を USB ケーブルで Mac に接続し、次のように真似して *IDN?
コマンドを送信してみましょう。普通の装置は後述の SCPI というコマンド体系に準拠しているはずで、ほとんどの装置は *IDN?
コマンドに対して機種情報を返します。
$ ipython In [1]: import visa In [2]: rm = visa.ResourceManager() In [3]: rm.list_resources() Out[3]: ('USB0::0x0699::0x041B::C022756::INSTR',) In [4]: usb = rm.open_resource(rm.list_resources()[0]) In [5]: usb.query('*IDN?') Out[5]: 'TEKTRONIX,MSO4102B-L,C022756,CF:91.1CT FV:v2.90 \n'
これで、Tektronix の MSO4102B-L という機種でシリアルナンバー(S/N)C022756 のものが繋がっているというのが分かります。ファームウェアのバージョンがおそらく 2.90 なのだと思います。
さて、周辺機器の接続情報だけ得ても面白くないので、*IDN?
以外の SCPI について調べましょう。Wikipedia の記事にもあるように、SCPI は実験室で使うような測定装置とやり取りするための標準的なコマンドの文法の規格です。メーカーが異なっても、例えば Tektronix でも Keithley でも岩通でも、SCPI で制御できる装置は似たようなコマンドで動作させることができます。
例えば上述の Tektronix のオシロスコープの電圧表示範囲を変更してみましょう。文法を調べるには、例えば「MSO4102 programmer's manual」などで Google 検索すると PDF が出てくるはずです。次のページが出てきたので、PDF をここから入手しましょう。
マニュアルを読むと、このような説明が出てきます。
CH<x>? Returns vertical parameters for the specified channel
それでは、実際にやってみましょう。ここで注意するのは、<x>
の部分は適切な値に置き換えよという意味です。?
が最後についているのは、問い合わせのコマンドということです。つまり、返り値があります。
In [6]: usb.query('CH1?') Out[6]: '0;10.0000;"No probe detected";"";1.0000;"V";50.0000;"Other";0.0E+0;0.0E+0;1.0000E+9;DC;0.0E+0;0.0E+0;0;-2.9600;1.0000;"V";50.0000;""\n'
この読み方はマニュアルを参照するとして、例えば縦軸の分割幅は 1.0000 V であり、オフセットが -2.9600 V だということが分かります。カップリングは DC で終端は 50.0000 Ω です。
次に、電圧のオフセットを変更してみましょう。マニュアルによると、文法は CH<x>:OFFSet <NR3>
および CH<x>:OFFSet?
です。ここで小文字は省略可能という意味です。また <NR3>
は 2.0E-3
などの指数表示を意味します。(<NR1>
は整数値、<NR2>
は小数です。)
In [15]: usb.write('CH1:OFFS 1.23E-1') Out[15]: (18, <StatusCode.success: 0>) In [16]: usb.query('CH1:OFFS?') Out[16]: '123.0000E-3\n' In [17]: voffset_ch1 = float(usb.query('CH1:OFFS?')[:-1]) In [18]: voffset_ch1 Out[19]: 0.123 In [20]: usb.write('CH1:OFFS %.2E' % voffset_ch1)
動作確認時を除いて、実際にプログラム中に書くときは省略せずに全て書くことをお勧めします。コマンドの可読性が増すからです。
次に波形を取得してみましょう。簡単のため、データフォーマットは ASCII にします。
In [31]: usb.write('WFMOutpre:ENCdg ASCii') In [32]: usb.write('DATA:SOURCE CH1') In [33]: data = usb.query('WAVFRM?') In [34]: data[:250] Out[34]: '2;16;ASCII;RI;MSB;"Ch1, DC coupling, 1.000V/div, 4.000ms/div, 1000000 points, Sample mode";1000000;Y;LINEAR;"s";40.0000E-9;-20.0000E-3;0;"V";156.2500E-6;29.6960E+3;123.0000E-3;TIME;ANALOG;0.0E+0;0.0E+0;0.0E+0;27648,27904,27392,27648,27648,27904,27648'
あとは、マニュアルを読んでこのデータを波形情報に戻してみましょう。
USB 端子を持っていても、VISA に対応していない機器があります。その多くは USB 端子の後ろに USB to Serial converter と呼ばれる、USB とシリアル通信(RS-232C)を変換するチップが搭載されています。このような機器は PyVISA ではなく PySerial を使って制御します。
また、USB 端子ではなく RS-232C 端子しかない機器もあるでしょう。これには、USB-RS232C の変換ケーブルを使用します。変換チップには様々なメーカーのものが存在しますが、FTDI 社製のものが一般的です。また FTDI 製であれば macOS でも Windows でも Linux でもデバイスドライバーのインストールなしに動作しますので、例えば Buffalo のこのケーブルは確実に動作します。
Mac に FTDI 製のチップを持つ周辺機器、もしくは FTDI 製チップの使われている変換ケーブルで RS-232C の機器を接続したときは、/dev/
以下にデバイスファイルが作成されます。
例えば Keithley 社製のある機器の場合、FTDI のチップが使われているため次のように表示されます。表示されるデバイスファイル名はチップのシリアルナンバーにしたがって異なるものになります(Mac の場合)。
$ system_profiler SPUSBDataType (略) USB 3.0 Hi-Speed Bus: Host Controller Location: Built-in USB Host Controller Driver: AppleUSBXHCI PCI Device ID: 0x1e31 PCI Revision ID: 0x0004 PCI Vendor ID: 0x8086 Bus Number: 0x14 USB HS SERIAL CONVERTER: Product ID: 0x6001 Vendor ID: 0x0403 (Future Technology Devices International Limited) Version: 4.00 Serial Number: FT123456 Speed: Up to 12 Mb/sec Manufacturer: FTDI Location ID: 0x14100000 / 1 Current Available (mA): 500 Current Required (mA): 44 $ ls /dev/tty.usbserial* /dev/tty.usbserial-FT123456
PySerial を入れると、同様に SCPI のコマンドで制御することができるようになります。
import serial keithley = serial.Serial(port="/dev/tty.usbserial-FT123456", baudrate=57600,timeout=1,writeTimeout=1) keithley.write('*RST\n') keithley.write(':SENS:FUNC "VOLT"\n') keithley.write(':SOUR:FUNC VOLT\n') keithley.write(':OUTP ON\n')
ここで、RS-232C の装置の場合は baudrate という値の設定をその機種ごとに揃えて必要があります(今の例の場合、57600)。装置のマニュアルに必ず書いてあるはずですので、読むようにしましょう。また使用する改行コードも機種ごとに異なるため、今の場合は \n
を使用していますが、これもマニュアルで確認してください。