にせねこメモ

はてなダイアリーがUTF-8じゃないので移ってきました。

Blenderとペパクラデザイナーを用いた球面に貼るステッカーの構成

2022/12/31のコミケ101において頒布された、サークル「kabesa*」の本に寄稿した記事を公開します。
biacco42.hatenablog.com

球面にステッカーを貼るということ

カッティングシートをカットすることでステッカーが作れる。車や店舗の窓などに貼ってあるあれである。平面やそれに近い形状ならばただ貼ればいいのだが、球面に貼るのは難しい。

この原因は、メルカトル図法などの平面地図と地球儀のアナロジーで理解できる。つまり、平面地図を球に貼ろうとすると、極に向かうにつれて絵柄が引き伸ばされているため、その部分にしわ寄せが来る。
ステッカーデザインで考えると、ステッカーの図柄中に広い面やループが存在する場合、球面に貼ると歪みが蓄積するため、きれいに貼れなかったり、図柄が歪んだりする。

球面に貼りやすいステッカーを作るには、分岐のある紐状にするのがよい。球面より十分に細い紐状の形であれば、局所的に見れば平面に貼るのに近くなるので、きれいに貼ることができる。ただし、歪みが蓄積するので図柄はずれていくことになる。

球面向けステッカーの構成

そのため、図柄をなるべく歪めずに、球面に貼れる形に構成することを考えたい。ここで「図柄を歪めない」というのは、ある視点から見た場合に平面と同じ図柄になるということを想定している。

ある視点から見た場合に平面と同じ図柄になる見た目の球体というのは、その視点から球体の表面へと図柄を透視投影することによって実現できる。図柄が投影された球体モデルの図柄部分のみを、立体の展開図のように展開できれば、歪みの少ない球体向けのステッカー用図柄が得られるはずである。

実際にやってみた

球体への投影にはBlender、投影した図柄の平面への展開はペパクラデザイナーを用いる。

球体への投影と展開用モデル作成

球体への図柄の投影と展開用モデル作成にはBlenderを用いる。
以下の説明はBlender 3.3.1 LTSの英語版UIを前提としている。また、基本操作については解説を省く。

事前準備
  • 3DビューポートのシェーディングをMaterial Previewにしておく。
3Dモデルとテクスチャの作成
  1. UV Sphereなどの球を用意する(以下、“MySphere”とする)。最終的には使わないのでメッシュはかなり細かくして良い。
  2. “MySphere”にマテリアルを追加し、シェーダーエディタを開く。[Principled BSDF]を削除し、代わりに[Emission]シェーダーを追加する。さらに[Image Texture]を追加して図柄の画像ファイル(“design.png”; 図1)を開く。
    図1 用意した図柄の元データ“design.png
  3. [Color]-[Color]間と[Emission]-[Surface]間を接続する(図2)。
    図2 シェーダーのノードの接続
  4. [Add Modifier]から[UV Project]モディファイヤを追加し、[UV Map]にデフォルトの“UVMap”を選択、[Object]はデフォルトカメラの“Camera”を設定する(図3)。
    図3 UV Projectモディファイアの設定
  5. カメラ“Camera”の位置を(0, 0, 5)とかに持っていき、回転も(0°, 0°, 0°)などにしてZ軸下側を見るようにする。
  6. テクスチャの画像を編集して、テクスチャの中心が中央に来るようにする。カメラを移動するとテクスチャの位置が動くものの、透視投影をする都合上、テクスチャが思った位置になるように移動させるのはテクスチャの方を編集したほうが良いかもしれない。
  7. [UV Project]モディファイヤの[Scale X]/[Scale Y]を利用してテクスチャの大きさを変更できるので、適当な大きさにする(図4)。
    図4 テクスチャ投影位置と大きさの調整
  8. 思ったような見た目になったら、展開用のモデルを作成する。Faceへのスナップ機能を使いながら、図柄を覆うようにメッシュを作成していく。作成したメッシュ(図5)は“MyMesh”という名前とする。
    図5 作成したメッシュ
  9. “MySphere”はもう使わないので非表示にする。
  10. “MyMesh”をUV展開する。[UV Editing]ワークスペースを開いてメッシュ全選択→[U]キー→[UV Unwrap]。
  11. “MyMesh”のマテリアルは“MySphere”に設定していたものと同一のものを指定する。
    モディファイヤとして[UV Project]を“MySphere”のときと同様に設定する。すると図6のような見た目となる。
    図6 作成した“MyMesh”にテクスチャ投影を設定した
  12. “MyMesh”のObject Dataプロパティの[UV Maps]に新規追加し、“proj”と名付ける。
    “proj”の右のカメラマークをクリックしてアクティブレンダーに設定。
    [UVProject]モディファイヤの[UV Map]を“proj”に変更。
  13. イメージエディタなどで“baked”というテクスチャを作成する。シェーダーエディターで[Image Texture]を追加し“baked”のテクスチャを開き、そのノードを選択状態にする(図7)。
    図7 ベイク用のテクスチャの選択
  14. [UV Editing]ワークスペースを開き、メッシュを全選択する。[UV Map]のアクティブレンダーを“proj”にしたまま(カメラマーク)、“UVMap”を選択状態にする(図8)。
    図8 ベイクのためのUVマップの設定
  15. Renderプロパティを開いて[Render Engine]を[Cycles]にし、[Bake]の下の[Bake Type]を[Emit]にして[Bake]を実行する。すると“baked”に結果が描かれる。
  16. “MyMesh”を選択して、[UVProject]モディファイアを削除。シェーダーエディタを開いて“baked”を使うように繋ぎ変える(図9)。
    図9 ベイクしたテクスチャを使うように設定
エクスポート
  1. “baked”という画像を“baked.png”としてファイルに保存する。
  2. “MyMesh”を選択し、[File]→[Export]→[Wavefront (.obj)]でエクスポートする。
  3. 設定画面で、(Limit to) [Selected Only]にチェック、[Forward Axis]を[Y]、[Up Axis]を[Z]にする。[Geometry]の[Materials]にチェックがあるのを確認してエクスポートを行う。

ペパクラデザイナーで展開図を作成

ペパクラデザイナー5で.objファイルを読み込む。

[設定(S)]→[テクスチャの設定(T)]から、設定したマテリアルを選択して[テクスチャ画像の指定...]を押し、“baked.png”を指定する(図10)。

図10 ペパクラデザイナーでモデルとテクスチャを読み込んだところ

ループがある場合は、切る辺を適当に指定してループがなくなるようにする。「切開する辺を指定する」ツールで切る辺を指定する(図11)。>

図11 切開する辺を指定したところ

その後、「展開」を押す。

すると展開される(図12)。

図12 展開した結果

[展開図ウィンドウ(E)]から[のりしろを表示する(F)]をオフ。
[辺の色の指定]ツールを開き、[選択対象]は[切り取り線]のみにチェックを入れ、[色選択]で淡い色を選択する。そして展開図の上をドラッグして切り取り線の色を薄くする。

これをPDF ([ファイル(F)]→[PDFファイルへの出力(D)])等で出力し、画像処理ソフトを使って閾値で2値化すると、カットするための図案が得られる。

結果

実際に得られた画像が図13である。

図13 作成したカット用図柄

これを元に実際にカットしたステッカーを図14に、球形のものに貼ってみた結果を図15に示す。

図14 カットしたステッカー
図15 りんごに貼ったところ

若干のズレがあるために隙間が開いているが、割といい感じになってると思う。

感想と課題

設計に用いたサイズと実際の球面の大きさが異なると、大きくても小さくても歪み方が変わるので、きれいに貼れない可能性がある。最終的なサイズがきっちり決まっている場合は、サイズをちゃんと計算した方がいいだろう。サイズが確定しない場合は、大きさを調整して試行錯誤してみたり、ループを断ち切った部分などは長めに伸ばしておいて、若干重なるように構成しても良いかもしれない。
ちなみに、今回は球体で行ったが、3Dモデルが用意できれば球面に限らずあらゆる立体に対応できるはずである。

また、この手法は、半球より大きな図柄は構成できない。加えて、端の方の歪みはかなり大きくなるため、正しく見える視点が限定される。そのため、全体に貼りたい場合などは別の手法が必要となるだろう。

他にも、今回はメッシュの張り替えを手で行っているが、これだけ単純な図柄でも結構面倒なので、さらに複雑な図柄だともっと大変なことになる。自動化してえなあ~。

参考

Ubuntu 22.04でハード構成を変更したらネットに繋がらなくなった話

まとめ

Ubuntu 22.04でインストール時に固定IPを設定した。
ハードウェア構成を変更したらネットに繋がらなくなった。
netplanの設定のインタフェース名が異なっていた。インタフェース名を修正したらつながった。

経緯

自宅でファイルサーバとして動かしてるマシン(Proliant MicroServer N54L)のOSを新しくして、Ubutu 22.04をインストールしてセットアップした。

インストール時にインストーラで固定IPを設定した。

それでしばらく使っていたが、ハードウェア構成を変更したらネットに繋がらなくなった。具体的にはPCIeの機器を外してグラボを取り付けたりした。

ここで、

sudo dhclient

とするとIPが取得できることが確認できた。

しかし、

sudo netplan apply

では取得できなかった。

結論

Bug #1881832 “Ubuntu server 20.04 fails to get IP address from D...” : Bugs : netplan.io package : Ubuntu
似たような現象に遭ってる人がいたので解決した。

結論としてはnetplanの設定ファイルのインタフェース名が異なっていた。

Ubuntuインストーラが生成した/etc/netplan/00-installer-config.yamlが変更されたのか、インタフェース自体の名前が変更になったのかは確認してないのではっきりわからないが、おそらく後者だと思われる。

PCIeを増設したり取り外したりした時など、ネットワークインターフェースの名前が変わる可能性があり、設定ファイルを見直す必要があるのかもしれない。

Pleroma 2.4.5→2.5.0の更新

概要

Pleromaの2.5.0がリリースされていたので更新した。
更新方法は次の記事に書かれていたので、それに従ったが、Elixirの更新が必要になったのでそこでつまづいた。

環境

Ubuntu 20.04 LTS
Pleroma 2.4.5 (ソースからインストール)

データベースのバックアップ

sudo systemctl stop pleroma
sudo -Hu postgres pg_dump -d pleroma -v --format=custom -f /home/nixeneko/pleroma_dev.20221225.pgdump

pleromaはデータベースの名前、/home/nixeneko/pleroma_dev.20221225.pgdumpは出力先ファイルの指定

Pleromaをv2.5.0へ更新

ソースをv2.5.0に更新する。

cd /opt/pleroma
sudo -Hu pleroma git pull
sudo -Hu pleroma git checkout v2.5.0

ここで、コンパイルに進もうと

sudo -Hu pleroma MIX_ENV=prod mix deps.get

とやってみたが、次のエラーがでた。

** (Mix) You're trying to run :pleroma on Elixir v1.9.1 but it has declared in its mix.exs file it supports only Elixir ~> 1.11

つまり、Elixirのバージョンが1.11以上でないといけないということだった。

Elixirの更新

Ubuntu 20.04 LTSで入るElixirのバージョンは1.9.1だが、Pleroma 2.5.0では1.11以上が必要らしい。
というわけで、Elixirのバージョンを上げる。

面倒なのでErlang Solutionsのリポジトリを使うことにした。

wget https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb
sudo dpkg -i erlang-solutions_2.0_all.deb
sudo apt update
sudo apt install erlang
sudo apt upgrade

Pleromaのコンパイル

ここでPleromaをコンパイルするのだが、ここでつまづいた。

まず依存するモジュールを取ってくるところで…

cd /opt/pleroma
sudo -Hu pleroma MIX_ENV=prod mix deps.get

次のエラーが出た。

Could not start Hex. Try fetching a new version with "mix local.hex" or uninstalling it with "mix archive.uninstall hex.ez"

mixが古いとのことなので、次のように実行した。

sudo -Hu pleroma MIX_ENV=prod mix local.hex

しかし、コンパイルしようとして、

sudo -Hu pleroma MIX_ENV=prod mix deps.get
sudo -Hu pleroma MIX_ENV=prod mix compile

としたところ、

** (Mix) Could not compile dependency :eblurhash, "/var/lib/pleroma/.mix/rebar3 bare compile --paths /opt/pleroma/_build/prod/lib/*/ebin" command failed. Errors may have been logged above. You can recompile this dependency with "mix deps.compile eblurhash", update it with "mix deps.update eblurhash" or clean it with "mix deps.clean eblurhash"

と出てeblurhashコンパイルできないということだった。

ここでしばらく途方に暮れていたのだが、救いの手はAkkomaが差しのべてくれた*1

このページのCompilation Troubleshootingにおいて、

If you ever encounter compilation issues during the updating of Akkoma, you can try these commands and see if they fix things:

  • mix deps.clean --all
  • mix local.rebar
  • mix local.hex
  • rm -r _build
https://akkoma.dev/sfr/akkoma

とするとよいとのこと。つまり、rebarを更新するのを忘れていたということになると思う。

というわけで、書かれている通りに

cd /opt/pleroma
sudo -Hu pleroma MIX_ENV=prod mix deps.clean --all
sudo -Hu pleroma MIX_ENV=prod mix local.rebar
sudo -Hu pleroma MIX_ENV=prod mix local.hex
sudo -Hu pleroma rm -r _build

を実行し、コンパイルを行うと…

sudo -Hu pleroma MIX_ENV=prod mix deps.get
sudo -Hu pleroma MIX_ENV=prod mix compile

無事コンパイルできた!!

その後、Migrationを行い、

sudo -Hu pleroma MIX_ENV=prod mix ecto.migrate

VACUUM ANALYZEをする。

sudo -Hu pleroma MIX_ENV=prod mix pleroma.database vacuum analyze

再起動して終了。

sudo systemctl start pleroma

いやーヒヤヒヤしました。

*1:普通にPleromaのサイトにも書いてあったけどなんかAkkomaの方が引っかかった、なんで?

Epicyon建ててみたメモ

AcrivityPubの一実装であるEpicyonサーバーを立ててみた。

Epicyon

EpicyonはActivityPubという規格に基づいて通信を行うSNSソフトウェアである。
ActivityPubを話すソフトウェアは互いに通信することができ、Mastodonなどと相互に通信ができる。

Epicyonは次のページにある。
https://epicyon.net/

特徴としては、JavaScriptを使っていないので、ページの動的な更新がされない、またリレーショナルデータベースなどを利用せず、データは普通のファイルとして保存されるそうだ。サーバーはPythonで書かれている。

インストールメモ

サーバーのセットアップ

VPS用意

WebARENA IndigoでUbuntu 22.04、メモリ1GBのインスタンス作成

DNSレコードを設定

ドメイン(以降の説明ではepicyon.example.comとする)にIPアドレスを設定。

ログイン

sshでログイン

とりあえず更新
sudo apt update
sudo apt upgrade
sudo reboot now

再ログイン

sshd設定
sudo nano /etc/ssh/sshd_config

次のような設定を行った。

port 10022 

LoginGraceTime 30
PermitRootLogin no
MaxAuthTries 3
MaxSessions 3

再起動

sudo sshd -t
sudo service sshd restart

ファイアウォールとかの設定は略。

Epicyonのインストール

諸々入れる
sudo apt install python3-socks imagemagick python3-setuptools python3-cryptography python3-dateutil python3-idna python3-requests python3-flake8 python3-django-timezone-field python3-pyqrcode python3-png python3-bandit libimage-exiftool-perl certbot nginx wget

インストールの説明だとtorもインストールすることになってるけど省いた。

ソースコードとってくる
cd /opt
sudo git clone https://gitlab.com/bashrc2/epicyon
ユーザーの追加
sudo useradd -r -s /bin/false -d /opt/epicyon -U epicyon
sudo chown -R epicyon:epicyon /opt/epicyon

なんかリンク張る。以降ドメインepicyon.example.comとする。

sudo mkdir /var/www/epicyon.example.com
sudo mkdir -p /opt/epicyon/accounts/newsmirror
sudo ln -s /opt/epicyon/accounts/newsmirror /var/www/epicyon.example.com
sudo chown -R epicyon:epicyon /opt/epicyon/accounts/

accounts/以下のownerがrootになっていたので変更した。

デーモンを作成
sudo nano /etc/systemd/system/epicyon.service

公式ページの説明にあるように次のような内容を貼り付ける

[Unit]
Description=epicyon
After=syslog.target
After=network.target

[Service]
Type=simple
User=epicyon
Group=epicyon
WorkingDirectory=/opt/epicyon
ExecStart=/usr/bin/python3 /opt/epicyon/epicyon.py --port 443 --proxy 7156 --domain epicyon.example.com -registration open --log_login_failures
Environment=USER=epicyon
Environment=PYTHONUNBUFFERED=true
Restart=always
StandardError=syslog
CPUQuota=80%
ProtectHome=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
ProtectKernelLogs=true
ProtectHostname=true
ProtectClock=true
ProtectProc=invisible
ProcSubset=pid
PrivateTmp=true
PrivateUsers=true
PrivateDevices=true
PrivateIPC=true
MemoryDenyWriteExecute=true
NoNewPrivileges=true
LockPersonality=true
RestrictRealtime=true
RestrictSUIDSGID=true
RestrictNamespaces=true
SystemCallArchitectures=native

[Install]
WantedBy=multi-user.target

YOUR_DOMAINだけ使うドメイン(ここでは仮にepicyon.example.com)に置換している。
ユーザー登録を無効化するにはExecStartのところの--registration open--registration closedに変更するといいっぽい。

有効化

sudo systemctl enable epicyon
sudo systemctl start epicyon
Webサーバーの設定
sudo nano /etc/nginx/sites-available/epicyon.example.com

公式の説明通りに次のような内容を貼り付ける。

server {
 listen 80;
 listen [::]:80;
 server_name epicyon.example.com;
 access_log /dev/null;
 error_log /dev/null;
 client_max_body_size 31m;
 client_body_buffer_size 128k;
 
 limit_conn conn_limit_per_ip 10;
 limit_req zone=req_limit_per_ip burst=10 nodelay;
 
 index index.html;
 rewrite ^ https://$server_name$request_uri? permanent;
 }
 
 server {
 listen 443 ssl;
 server_name epicyon.example.com;
 
 gzip on;
 gzip_disable "msie6";
 gzip_vary on;
 gzip_proxied any;
 gzip_min_length 1024;
 gzip_comp_level 6;
 gzip_buffers 16 8k;
 gzip_http_version 1.1;
 gzip_types text/plain text/css text/vcard text/vcard+xml application/json application/ld+json application/javascript text/xml application/xml application/rdf+xml application/xml+rss text/javascript;
 
 ssl_stapling off;
 ssl_stapling_verify off;
 #ssl on;
 ssl_certificate /etc/letsencrypt/live/epicyon.example.com/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/epicyon.example.com/privkey.pem;
 #ssl_dhparam /etc/ssl/certs/epicyon.example.com.dhparam;
 
 ssl_protocols TLSv1.2 TLSv1.3;
 ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
 ssl_prefer_server_ciphers on;
 ssl_session_cache shared:SSL:10m;
 ssl_session_tickets off;
 
 add_header Content-Security-Policy "default-src https:; script-src https: 'unsafe-inline'; style-src https: 'unsafe-inline'";
 add_header X-Frame-Options DENY;
 add_header X-Content-Type-Options nosniff;
 add_header X-XSS-Protection "1; mode=block";
 add_header X-Download-Options noopen;
 add_header X-Permitted-Cross-Domain-Policies none;
 add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;
 
 access_log /dev/null;
 error_log /dev/null;
 
 index index.html;
 
 location /newsmirror {
 root /var/www/YOUR_DOMAIN;
 try_files $uri =404;
 }
 
 keepalive_timeout 70;
 sendfile on;
 
 location / {
 proxy_http_version 1.1;
 client_max_body_size 31M;
 proxy_set_header Host $http_host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Forward-Proto http;
 proxy_set_header X-Nginx-Proxy true;
 proxy_temp_file_write_size 64k;
 proxy_connect_timeout 10080s;
 proxy_send_timeout 10080;
 proxy_read_timeout 10080;
 proxy_buffer_size 64k;
 proxy_buffers 16 32k;
 proxy_busy_buffers_size 64k;
 proxy_redirect off;
 proxy_request_buffering off;
 proxy_buffering off;
 proxy_pass http://localhost:7156;
 tcp_nodelay on;
 }
 } 

YOUR_DOMAINを使うドメインepicyon.example.com)に置換している。
ssl on;はwarning出たのでコメントアウトした。

これだけだとエラーでて動かないので、Nginxの設定を編集し

sudo nano /etc/nginx/nginx.conf

で、httpセクション内、includeの前に

	limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
	limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=50r/s;

とかを追加。

有効化

sudo ln -s /etc/nginx/sites-available/epicyon.example.com /etc/nginx/sites-enabled/
SSH対応
sudo systemctl stop nginx
sudo certbot certonly -n --server https://acme-v02.api.letsencrypt.org/directory --standalone -d epicyon.example.com --renew-by-default --agree-tos --email test@example.com
sudo systemctl start nginx

メールアドレスは適切に設定。


これで動き出すっぽい。
ダメな場合はNginxについてはsudo systemctl status nginx.servicesudo journalctl -xeu nginx.serviceなどで、Epicyonについてはsudo journalctl -f -u epicyonとかでログが見られるっぽい。

使う

これでブラウザからアクセスすると登録画面が出てきて使うことができる。

感想

WebクライアントのUIがこなれてない。デザインもあんまり分かりやすくないし、見た目もあんまりよくない気がする。

Mastodonとは通信ができたが、自分のメインのPleromaインスタンス(nixeneko.info)とはうまく疎通できなかった。Pleroma→Epicyonは配送できてもEpicyon→Pleromaは配送できなかった。Pleromaバージョンを上げればいいのかもしれないが…。

結局、試すには試したけど常用するには難しいかなという感じ。


さすがにWebクライアントが最新投稿を自動で取ってくるくらいはして欲しい気がする。とはいえ適当なアプリ使えばいいのかも。

自由ソフトウェア的な思想が結構強い雰囲気を感じる。好みは分かれるかもしれない。

特に、コミュニケーションを目的とせず、情報を配信するために自分でActivityPubサーバーを立てる時にはこういった選択肢は有用であると思われる。動かすのに強いマシンが要らないので。

ログインしてるのに、はてなブログの自分のページがログイン状態にならない

概要

  • Firefoxのアップデートにより、デフォルトでクロスサイトCookieが隔離されるようになった。
  • これによりはてなブログのページからはてなのログイン情報を取得できなくなり、ログインしていない表示になった。
  • FirefoxCookieブロックの設定を変更することで、問題は解消できる。

現象

Firefoxで、しばらく前から、はてなブログの自分のブログを開いても、自分のアカウント名が表示されず、「ログイン」というリンクの表示になっていた。

自分のはてなブログを開いてもログイン状態にならない

また一方で、「ログイン」をクリックすると、ログインされた状態で自分のダッシュボードに移動する。つまり、はてなブログにログインはしている状態である。

一度ログアウトして再度ログインし直したものの、改善は見られなかった。


これは、以前は次のように表示されていたものである。

ログイン状態でユーザーアカウントが正常に表示された場合

環境

解決方法

方法1: FirefoxのクロスサイトCookieの隔離をやめる

  1. Firefoxの「ツール(T)」「設定(S)」を開く。
  2. 「プライバシーとセキュリティ」タブを開く。
  3. 「強化型トラッキング防止機能」について、「カスタム(C)」のラジオボタンを選択。さらに、「Cookie (C)」の右側のドロップダウンボックスを選び「クロスサイトトラッキング Cookie」を選択する。
  4. 設定タブを閉じ、はてなブログのページを再読み込みする。
FirefoxでクロスサイトCookieを許可する設定

セキュリティ上の懸念が多少あるかもしれないものの、すべてのはてなブログのページについて当問題を一括で解決できる。

方法2: 個別サイトについて、強化型トラッキング防止機能をオフにするよう例外に追加する

  1. Firefoxで当該サイトを開く。
  2. アドレスバー左の盾マークをクリックする
  3. 「強化型トラッキング防止機能はこのサイトでオンです」の右のスイッチをクリックし、オフにする
強化型トラッキング防止機能をオフにする手順

次の図のような状態になると正常に表示される。

強化型トラッキング防止機能をオフにした状態

この方法のメリットとしては、設定したサイト以外のセキュリティは保たれるということがあるが、デメリットはサイトごとに個別に設定する必要があるということだ。はてなブログが複数ある場合、それら全てで設定を行う必要がある。

原因

Firefoxが、最近(2022年6月?)のアップデートで、デフォルトでクロスサイトCookieを隔離するように変更されたらしい。なので、自分のブログページはhatena.ne.jpドメインではないので、はてなブログのページからははてなのログイン情報が取得できなくなり、そのためログインがなされていないような表示になったのだと思われる。

これはSafariなどでは以前から発生していた状況らしい(参考サイト1参照)。

Private Reserve Inkの今

Private Reserve社のインク

Private Reserve社という、万年筆インクを製造している会社があった。
その会社が製造するインクは発色がよく、染料インクなので扱いやすく、混色も可能というものだった。
そのため、自分で好みの色のインクを調合できる店であるカキモリのInkstandにおいて、混色用のインクとして2017年頃まで使われていた。しかし、安定した入手が困難になったため、現在は独自の顔料系インクに切り替わっている。

入手困難だった理由

なぜインクが入手困難になったのか?

https://www.fountainpennetwork.com/forum/topic/355755-private-reserve-ink-status/
このフォーラムを追っていくと経緯が書いてある。フォーラムの記載によると、次のようなことがあったらしい。

まず、元々の会社のオーナーが逝去したとのことで、そのためインクが生産できなくなった。新しく生産されないため、在庫がなくなると入手困難状態になっていた。

その後、従業員であったDarla Aniline氏が2018年にPrivate Reserve社を購入し、一人会社として運営されていた。インク調合のレシピがほとんど残されていなかったので再生産が難しかったという事情もあり、配合を再現しようと化学者と共同して作業していたらしい。しかし、2020年9月にAniline氏も早逝。会社は機能停止したことになる。

新しいPrivate Reserve Ink

さて少し経って、Cult Pensという文具ショップのFacebook投稿によると、2021年3月に元々のものと同じレシピ(the original formula)で新しく製造・販売が開始されたとのこと。


私が気づいたときにはCult Pensで在庫切れになっいたが、その後在庫が復活したので、2021年8月にインクを購入した。
インクの瓶を箱から出して並べた写真

箱の底面
箱の側面
箱には製造者については書かれていないが、ヨーロッパで製造、アメリカで包装とあり、また www.PrivateReserveInkUSA.com というアドレスが書かれている。これにアクセスすると yafabrands.com のページにリダイレクトされる。これはYafaというアメリカの筆記具会社らしい。


探すとYafa社がPrivate Reserve社を買収したと書かれているPDFがあった。
https://www.yafa.com/outlet/images/Pen_world_article.pdf

というわけで、2021年3月ころからYafaブランドの元で新しく製造されたPrivate Reserveインクの流通が始まったらしいことが分かった。当分の間は安定した供給が見込めそうである。とりあえずは一安心という感じだ。

購入方法

日本からも、CultPensなどの日本へも配送してくれるネットショップで購入できる。しかし、私が2021年8月に購入した時は3つのボトルを購入して送料が1500円程度(恐らく14~15 USD)だったものの、現在購入しようとしたら安い運送方法の選択肢がなくなって5800円程度(たぶん50 USD)はかかるようで、躊躇している。

Ebayとかで購入する方が配送料が安い(3千円以内)っぽいので、今はそっちで購入するのがいいのかもしれない。もうちょっと円が強いときに買いたいが…。


ところで、私が混色に使っていたFoam Greenというインクを含む数色が、新体制では製造されなくなってしまったらしく、手元で今までと同じ色のインクを調合することが難しくなってしまった。別のインクを使って近い色にできるように試行錯誤しなければならない。まあそれは追い追い。

おまけ

This is a pencil.と書かれた鉛筆
Cult Pensでインクを購入した時、“This is a pencil.”と書かれた鉛筆がおまけに付いてきた。すき。
This is a pencilと書かれた鉛筆の拡大

2023-01-02追記

日本Amazonにあるじゃん!例→https://www.amazon.co.jp/-/PR17019/dp/B0B2MTLK7Z/
「Private Reserve Ink」や「プライベート リザーブ インク」などで検索してみてください。

Amazon Timestreamからboto3で一度に大量のデータを取得しようとしたが空データが返ってきた

問題の概要

AWSAmazon Timestreamというデータベースにセンサーデータを蓄積している。このデータをローカルにダウンロードして利用したい。
Pythonとboto3ライブラリを利用して、Timestreamのデータベースからそこそこ大量のデータを取得しようとしたところ、レスポンスのRowsが空だった。
データがある程度小さくなるクエリでやってみると、問題なくデータが取得できるのが確認できた。

原因

TimestreamQuety.Client.query()を呼び出す際に、MaxRowsキーワード引数を指定しないと、取得結果のサイズが1MB以上になる場合に、Rowsが空の状態でレスポンスが返ってくる。その代わり、NextTokenがレスポンスに含まれる。

Otherwise, the initial invocation of Query only returns a NextToken , which can then be used in subsequent calls to fetch the result set. To resume pagination, provide the NextToken value in the subsequent command.

TimestreamQuery — Boto3 Docs 1.21.37 documentation

要するに、取得するデータがでかいと1回で取得することができないようになっている。

対応

ページネーションする。

TimestreamQuety.Client.query()NextTokenを指定して呼び出すと、サイズが1MB未満になるような個数のデータ(Rows)が返される。
更にまだ未取得のデータがある場合には、次のデータに対応するNextTokenもレスポンスに含まれる。データをすべて取得してしまった場合には、レスポンスにはNextTokenが存在しないので、終了判定にも使える。


実際にはこういう手順になる。

  1. 取得したいデータが1MB以上になる場合、最初に呼び出すとNextTokenと空のRowsが得られる。
  2. このNextTokenを利用して1MB程度分のデータ(Rows)と次のデータに対応するNextTokenを得る。
  3. これをNextTokenがレスポンスに含まれなくなるまで続け、今までに返されたRowsをすべて合体させれば欲しいデータが得られる。

Python 3コード

Rowsだけ連結して返すみたいなPython 3コードを示す。

import json
import boto3
from botocore.config import Config

#リージョン名, ID, secret keyは省略
config = Config(region_name = '……') 
config.endpoint_discovery_enabled = True
timestream_query_client = boto3.client('timestream-query', 
        aws_access_key_id="……",
        aws_secret_access_key="……",
        config=config)

#クエリの例
QUERY = """SELECT "time", "measure_name", "measure_value::double" FROM "mydatabase"."mytable" AND time between '2021-01-01 00:00' and '2022-01-01 00:00' ORDER BY time ASC""" 

#データ取得用の関数
def getdata(next_token = None):
    if next_token: #next_tokenが指定された場合はNextTokenを指定してクエリ
        result = timestream_query_client.query(
            QueryString=QUERY,
            NextToken=next_token
        )
    else: #next_tokenなし=初回呼び出し
        result = timestream_query_client.query(
            QueryString=QUERY
        )
    
    ret_rows = result["Rows"] #list of data
    if "NextToken" in result: #次のページ(未取得データ)が存在する場合
        return ret_rows + getdata(result["NextToken"]) #再帰呼び出し
    else: #欲しいデータはすべて取得した場合
        return ret_rows 

rows = getdata()
print(len(rows))
print(rows[0])
問題点

途中経過を保存していないので、ダウンロード途中で失敗した際に、やり直すときには最初から取得しなおしになる。
かなりたくさんのデータを取ってくる必要があるのであれば、呼び出しの度に毎回(あるいは何回かに一度)データとNextTokenを保存するなどとして、レジュームができるようにした方がよさそう。

また、再帰呼び出ししてるけど末尾再帰になってないので再帰深くなると大変かもしれない。メモリも食うし。普通にループで処理した方が適してるかも。