読者です 読者をやめる 読者になる 読者になる

retryするデコレータ

失敗してもretryするデコレータを書いてたら、頭の体操みたいなコードができました。 機能要件は、試行の最大回数と試行の時間間隔をデコレートするときに指定できるように…

それから、下記のコードはf文字列を使っているので python3.6+です。

from functools import wraps
from time import sleep, time

def retry(count=0, delay=0):
    def _retry(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            _delay = delay
            _time = time()
            for c in range(count):
                print(f'time: {time()-_time:.1f}')
                success = func(*args, **kwargs)
                if success or c == count-1:
                    break
                sleep(_delay)
                _delay *= delay
            return success
        return wrapper
    return _retry

try_count = 0
@retry(count=3, delay=1.5)
def unstable_func(threshold):
    global try_count
    try_count += 1
    print(f'try count: {try_count}')
    return True if try_count > threshold else False

if __name__ == '__main__':
    print(f'unstable_func is {"succeeded" if unstable_func(3) else "failed"}')
    print()
    print(f'unstable_func is {"succeeded" if unstable_func(3) else "failed"}')

実行結果は

time: 0.0
try count: 1
time: 1.5
try count: 2
time: 3.8
try count: 3
unstable_func is failed

time: 0.0
try count: 4
unstable_func is succeeded

実際に使うときは、ちゃんとしたライブラリを使いましょう!

株式会社はてなに入社しました

株式会社はてなに入社しました

株式会社はてなに入社しました - hitode909の日記

openFrameworksでプロジェクション

f:id:uitspitss:20170314020609j:plain

はじめに

2014年のクリスマス前に、openFrameworksを使って、プロジェクションをやりました。 今更ながら、記事にまとめます。

個人的には、コードも含めて載せたいところですが、 今までコードを載せるための作業をしようとして、公開ができていなかったので、 この記事では、コードは載せずに簡単な解説や製作に使用したaddon、参考にしたページなどを書きたいと思います。 2年ちょっと前に開発したもので、addonなどはもっと適したaddonが出ていることもあったりすると思いますので、 そのあたりは参考程度に読んでいただいた方がよいかもしれません。

動画

簡単な解説

  1. 動画の下部にある、横長の窓の前を通る人の影をwebカメラで取得して、その人影をopenFrameworks内の平面に白い人影として投影している。
  2. 投影された人影はopenFrameworks内の物体に何かしらの影響を与える。

さらに、以下の3つのシーンをインターバルで回してバリエーションを持たせている。

  • 上から落ちてくる雪の結晶を上空へ返す
  • 人影が乗る半月のシーソー
  • 人影のオーナメントが飾られるクリスマスツリー

使用したaddon

  • ofxOpenCv → openFrameworksの標準addonだったはず。OpenCVの差分処理で、人の影の取得などに。
  • ofxCv → 人の影の取得など。クリスマスツリーの影の取得は、一定時間取得された人の影をオーナメントにするという動作にするため、時間軸にもある意味の積算が必要になったので、そのようなところはこの addon を使いました。
  • ofxBox2d → 雪の結晶の動きなど。
  • ofxTrueTypeFontUC → 雪の結晶のシーンで、日本語の文字列を表示するのに使いました。
  • ofxGui → 影の取得範囲をその場で調整できるように簡単な調整用GUIを作っていました。
  • ofxTween → 半月シーソのシーンで、背景のドットの表示のイージング(アニメーション)に。

参考にしたwebページなど

  • Media Art II 2013 第6回:openFrameworks Addonを使う 2 – ofxOpenCV と ofxCv → 言わずと知れた田所さんの講義ノート。雪のシーンで人影から出ているパーティクルとかは例を見ながら作ったコードにちょっと手を加えたくらいでできています。

  • Night LightsopenFrameworksの青い本にも載っているYesYesNoの作品。影を取得してopenFrameworksの空間に持っていく作品の先駆的なものです。

  • Immersive Shadow → こちらも openFrameworksの文脈でよく名前をお見かけする藤本さんの作品。当時の自分は、影は本物だと思い込んでいたのですが、今見ると投影した映像に組み込まれているようです。結果的にはこの作品のオマージュです。

エコなプロジェクション

実験的なところで、予算もかけることができなかったので、以下のようなエコな仕様で行ないました。

  • 差分で影を取得するwebカメラBSW32KM03」 → 当時出ていたwebカメラの中で割と明るく撮れるということで購入していたような気がします。最初、窓が横長だったので、 広角な「BSW200MBK」を使ったら、 予想以上に広角すぎて、BSW32KM03にしたのを覚えています。
  • 投影用のプロジェクタ「EPSONのEB-W18あたり」 → 使用したプロジェクターの型番までは覚えていないのですが、ビジネスユースの一般的なプロジェクターを使いました。 明るさを稼ぐために2台に映像をスプリットして、投影する実験もしました。ただ、当日、位置調整がうまくいかず、1台で投影しました。 f:id:uitspitss:20170314020638j:plain

人の目で見るくらいであれば、割とそのあたりに転がっているプロジェクターで壁面に投影すると、意外と見れるものだったりします。 ただ、動画や写真に撮るとやはり画が暗いな、という印象を受けます。

その他、MBAの動作中の画像など…

f:id:uitspitss:20170314020650j:plain f:id:uitspitss:20170314020704j:plain

ASI120MC-S + Raspberry Pi2 で星空定点撮影

allskyについて

アルデバラン食20170109

以前に書いた記事で載せた動画は、MBAoaCapture というソフトを使って撮影していました。 ASI120MC-Sのフレームレートは、100μsを切ることもあるので、ちょっとした長さの動画でも、すごいデータ量になるので、 ライブビューをしながらタイミングを見計らってシャッターを切っていくほうがデータ容量を圧迫しないで使える気がします。

ただ、この方法は流星群などの長時間の天文現象の撮影や、日常的な星空撮影には少し面倒に感じることも多いはずです。 そう思う人は他にもいるようで、githubに定点撮影用のプログラムがありましたので、それを使ってテスト撮影してみました。

thomasjacquin/allsky

このallskyでは、Raspberry Pi に ASI系のカメラをつなげて、コンパイルしたプログラム(コマンド)を走らせると定点撮影をしてくれます。 コンパイルには少し時間がかかるので、インストール作業は事前にやっていた方が良いです。

テスト撮影の様子

f:id:uitspitss:20170312212646j:plain

この画像は、テスト撮影日の次の日の朝に撮った画像です。

テスト撮影日の夜中から天気が悪くなる予報が出ていたので、 適当なアクリルカバーをかぶせています。 それから、本当は、モバイルバッテリーから給電をして、独立状態にしたかったのですが、 充電が足りなかったので、コンセントからの給電にしました。

そして、当日もうひとつの問題が発生!

allskyのプログラムが、撮影した画像を上書きしかしてくれない…。 定点観測用に作られたプログラムのようなので、 おそらく、撮影画像を残していくような設定があるはずですが、 時間もなかったので、下記のプログラムを一緒に走らせてテスト撮影しました。

テスト撮影の結果

10秒露光の10秒間インターバル撮影だったので、計4154枚ありますが、そのうちの2枚を載せます。 設定を詰めれずにテスト撮影に入ってしまったので、若干ホワイトバランスがおかしいです…。

この画像は、設置直後の撮影画像なので、アクリルカバーを通していない画です。

f:id:uitspitss:20170312212713j:plain

小三つ星も写っているので、まぁまぁといった感じでしょうか。

アクリルカバーを付けた後はこんな感じです。

f:id:uitspitss:20170312212727j:plain

思った以上に、Raspberry Pi のインジケータのLEDが反射してしまっています。 インジケータ部分は何かで隠すようにしたほうが良いみたいです。 それと、カバーは半球状のものが手頃な価格で売っているのでそちらを使うべきでしょう。 それから、撮影した画像で、ほぼ1枚おきに画像下部に黒帯が付いてしまいました。 おそらく、変なタイミングでコピーがかかってしまった画像ということだと思います。 このあたりは、いろいろと改善の余地がありそうです。

ということで、設定を詰めれば星空定点撮影には使えそうですね。

余談ですが、この情報を今年のしぶんぎ座流星群前に知っていたのですが、その準備をする時間がなかったんです。 そのせいで、寒空の中、しぶんぎ座流星群を5、6時間撮影することになりました。 しかも、今年のしぶんぎ座流星群はそれほど活発でもなかったですしね!

node.js+ScratchX+Digisparkでプログラミング教室をやった

始めに

過去にも似たタイトルの記事を書いています。 過去記事はこの教室で使うプログラムの開発記事になっていました。 今回の記事が一連の開発の締めということになります。

f:id:uitspitss:20170312013219j:plain

プログラミング教室に向けての準備物(プログラム)

uitspitss/electron_scratchX-digispark

この自作プログラムが ScratchX と Digispark をつなげていて、 ScratchX で組むプログラムの中に、 Digispark の動作を 組み込むことができるようになっています。

f:id:uitspitss:20170312012751j:plain

ScratchX 上での実際のプログラムは以下のような感じです。 一番下の紫色の「白(白)で点灯」のブロックが自作ブロック。

f:id:uitspitss:20170312012846p:plain

対象

  • 小学生〜高校生 → 小学1年生〜中学2年生の8名が参加
  • プログラミングの経験は問わず → Scratchを触ったことがある子、初めて触る子といました。
  • ちなみに男女の内訳は、男5、女3

教室のおおまかな流れ

  • Scratchの使い方等の説明
  • プログラミング、プログラムの説明
  • プログラムを作成(ハンズオン)
  • フルカラーLEDで色の再現1(ハンズオン)
  • 光の三原色
  • カラーピッカーの紹介
  • フルカラーLEDで色の再現2(ハンズオン)
  • ループ処理
  • 変数
  • 条件分岐処理
  • 自由にプログラムを作成(ハンズオン)
  • Digisparkにプログラムを書き込み(私がArduino言語に書き換えて書き込み)

スライド

プログラムの説明のところは、真面目な人が見ると「?」と思うところがあるかもしれません…。 最後の方の太陽系の図は、今回の教室とは関係がないのですが、 学術的な方でもプログラミングを使うよ、という話をするために入れました。

プログラミング教室の様子

こんな環境でやりました。 ※プログラミングとは関係ないですが、Wi-Fi環境を用意しましょう!

f:id:uitspitss:20170312012919j:plain

以下、2つの画像は受講者が組んだプログラムです。

これは中学2年生が組んだプログラムです。 条件分岐処理が細かく使われています。

f:id:uitspitss:20170312013042j:plain

こちらは忘れてしまいましたが、小学校高学年か中学生くらいだったような気がします。 無限ループに入れるのは、Digisparkへ書き込むためにこちらが指示したものですが、 条件分岐処理とループ処理をうまく組み合わせられていると思います。

f:id:uitspitss:20170312013055j:plain

所感

今回の教室の目的は以下の3つでした。

  1. プログラミングの学習を家庭でも継続してもらうためのオンライン開発環境「Scratch(ScratchX)」
  2. プログラミングでよく使われる処理をどれくらい理解できるのか(変数、条件分岐処理、ループ処理)
  3. 科学のテイストを入れるための「光の三原色」

1については、こちらが準備する形でScratchXを使える環境に持っていくことができましたが、 最終的には、このLEDプログラミングを家庭でできるように、手軽に開発環境を作れることが目標だったので、 その点は至らずな結果になってしまいました。 一応は作ることができますが、手順が少し煩雑になってしまっているのと、環境に依存することがあるようです。

2については、たった2時間の講座だったので、そこまでできないだろうと思っていましたが、 子供たちの飲み込みが早くて、ほとんどクリアできました。 具体的には、小学校中学年くらいで変数、条件分岐処理、ループ処理が使えるくらい、 中学生になると、条件分岐処理やループ処理が入れ子になっているプログラムが書けていました。

3については、科学のテイストを入れるためにフルカラーLEDを選んだところもありました。 ロボットプログラミングが広くやられているところで、子供たちの興味を引くことができるか、 不安なところでしたが、ほとんどの子供たちは自ら進んでプログラムを組んでくれていました。 カラーピッカーを使うというところは、教室の1週間くらい前に入れることを決めたのですが、 これを入れたことで、参加者が最終的なプログラム制作するところで満足いくものにすることができたのかなと思います。 特に、女の子には色作りがハマったようで、最終的なプログラムはどれもRGB値が細かい数値で書かれていました。

他にも運営的にはどうだろうか、とか細かなところもありましたが割愛です。 この記事が誰かのお役に立てれば幸いです。

3/7高松空港→成田空港

覚えておきたいことなので…

飛行機は高松空港18:45発、成田空港20:05着。

座席は17Aで飛行機の左翼付近。 左の窓を見ると、左翼が見えていた。

飛行機は定刻通りに離陸。 高松空港を飛び立つと北東方向へ飛んで行くようだった。

空港の辺りはもうすっかり暗くなっていて、 滑走路のライトが明るく見えたり、 左翼の上にプリントされている文字が空港の照明の当たり具合によって、見えたり見えなかったりしていた。

飛行機が離陸して高度が上がっていくと、窓の外の空の色が少しずつ明るくなっていく。 日没後のように紺から深いオレンジ色へのグラデーションの空。

そして、左翼の先の少し上に明るい星。 内合前の金星が見えた。

手荷物の中にデジカメがあったのに、クロークに入れてしまっっていたので取り出せず、スマホのシャッター音を気にして画像が取れなかった…

その後は、進路を東の方へ変えたようで、 金星は飛行機の後方の方に行ってしまった。

着陸の30分前くらいから、成田空港に入るために、 飛行機が進路を東から北西方向に変えた。

すると、左翼から前方に4,50度のところに金星が見えた。このくらいの時間になると、金星の高度も大分下がったようで、目線と同じか、それよりも低い位置で見えた。空は、オレンジ色は見えなくなったが、それでも濃い青のあたりのグラデーションが見えた。

窓を覗き見る感じで、少し上の方を見てみると、火星が見えていた。これで、一等星くらいは見えるのだろうと思って、金星や火星が見えていた方向よりも南より、空の高いところを探しても、明るい星が見当たらなかった。たぶん、もっと高い位置に見えているのだと思った。というのも、地上ではとっくに見えなくなっている金星が目線と同じくらいの高さに見えているのだから。

それからも、一等星の星が見えてこないのかなと、時間を置いては確認をしてみたが見えなかった。 ただ、金星と同じ高さくらいに明るい星が見えていた。方向は金星から90度弱南方向。 あれはカノープスだったはず。 今、stellariumで3/7 19:30頃の空を確認すると、金星の高度は約2度、カノープスの高度は1.5度くらい。

明るさは、火星とほぼ同じくらいに見えた。

今回、この飛行機に乗ったのは本当に偶然だった。

  • 金星が内合前だった。宵の明星。
  • 火星が地球の接近の半年以上後だった。接近後はどんどんと夕方空、西の方に見えてくるので。
  • 春先で、カノープスが早めに正中する時期だった。カノープスはオリオン座からほぼ天の南極方向。
  • 離陸前に見れたのは、高松空港発だったからかもしれない。仮に松山空港発だったら、もう少し東寄りに進路を取りそうな気がする。
  • 確か羽田空港着は東京湾を北上していくようなルートだったはずなので、成田空港着だったからカノープスが見れたのかもしれない。
  • 天気がまずまずの晴れだった。

今、考えられるだけでもいくつかの条件が重なっていたようで、ほんとにラッキーだった。

内合前の金星を見るために、夕方のフライトを狙うのは比較的やりやすそうなので、次の機会はちゃんと写真を撮りたい。

特定の文字列を含むツイートを削除する

twitterで行なっていたテストが終わったので、テストでしていたツイートを削除しました。 今回はtwitterAPI,requests_oauthlibを使いました。

from requests_oauthlib import OAuth1Session
import json
import re
from time import sleep

def main():
    CONSUMER_KEY = ''
    CONSUMER_SECRET = ''
    ACCESS_TOKEN = ''
    ACCESS_SECRET = ''

    twitter = OAuth1Session(CONSUMER_KEY,
                            client_secret = CONSUMER_SECRET,
                            resource_owner_key = ACCESS_TOKEN,
                            resource_owner_secret = ACCESS_SECRET)

    req = twitter.get('https://api.twitter.com/1.1/statuses/user_timeline.json',
                      params = {'count': 100})

    user_timeline = json.loads(req.text)
    for tweet in user_timeline:
        if re.search(r'テストテスト!', tweet['text']):
            print(tweet['text'])
            del_req = twitter.post('https://api.twitter.com/1.1/statuses/destroy/{}.json'.format(tweet['id']))
            print('DELETE:', json.loads(del_req.text)['id'])
            sleep(2)


if __name__ == '__main__':
    main()

さくっと使えればよかったので、とりあえずユーザータイムラインから100ツイートごとに拾ってきて削除。 ステータスコードのチェックなども入れるとなおよいでしょう。

実行結果

テストテスト!
DELETE: 826774781261275136

参考

POST statuses/destroy/:id — Twitter Developers

GET statuses/user_timeline — Twitter Developers

user_timelineって直近の3200ツイートまでしか遡れないんですね。