Rhythm & Biology

Engineering, Science, et al.

macにLaTeXiT環境を整える

新しいmacbook proに買い換えてからLaTeXiT環境を整えていなかったので整備。
LaTeXiTがあれば資料に貼る用の綺麗な数式を簡単に作れる。

まず、brew(cask)にLaTeXiTがあるか調べたらあったのでそれを入れてみた。

$ brew search latexit
caskroom/cask/latexit

$ brew cask install latexit

で、これを起動しても動かない。
brewでLaTeXiTを入れても、そもそものTeX環境を自動では入れてくれないので、「pdflatexが無い」などと怒られる。

ではLaTeX環境をbrewで入れてみようとすると、どうやらMacTeXを入れることが推奨されている様子。

$ brew search latex
latex2html                         latex2rtf                          latexila                           latexml                            rtf2latex2e

If you meant "latex" specifically:
Installing TeX from source is weird and gross, requires a lot of patches,
and only builds 32-bit (and thus can't use Homebrew dependencies)

We recommend using a MacTeX distribution: https://www.tug.org/mactex/

You can install it with Homebrew-Cask:
  brew cask install mactex

MacTeXにはLaTeXiTも含まれている。
https://www.tug.org/mactex/mactex-download.html

MacTeX also installs Ghostscript, an open source version of Postscript, and it installs the GUI programs TeXShop, LaTeXiT, TeX Live Utility, BibDesk, and Excalibur, as well as an install package for cocoAspell, a spelling service which does not mark LaTeX commands as misspelled.

先ほどインストールしたLaTeXiTは無駄なので消してしまう。

$ brew cask uninstall latexit
==> Uninstalling Cask latexit
==> Removing App '/Applications/LaTeXiT.app'.

ここでようやくMacTeXをインストールする。ダウンロードにかなりの時間がかかるので気長に待つ。
また途中でsudoパスワードを聞かれるので入力する。

$ brew cask install mactex

以上で環境セットアップが完了。 f:id:aka_mythosil:20170714005920p:plain

odeintでMAPK cascadeのシミュレーション

odeintを試す題材としてMAPK cascadeのモデルを利用してみる。

成果物はここ → GitHub - mythosil/odeint-mapk

モデルの入手

モデルはBioModelsから取得。
BIOMD0000000010 - Kholodenko2000 - Ultrasensitivity and negative feedback bring oscillations in MAPK cascade

結果確認に利用するため、Online Simulatorでシミュレーション結果を入手。
ActionsBioModels Online Simulationと選択していけば良い。
Select all speciesにチェックを入れ、シミュレーションを実行する。
結果をgnuplotで表示するとこのようになる。

f:id:aka_mythosil:20170713002539p:plain

シミュレータ実装

まず必要なものをinclude。

#include <iostream>
#include <boost/array.hpp>
#include <boost/numeric/odeint.hpp>

次にsystemを作る。BioModelsから数式を写し書きする作業。

/**
 * @see https://www.ebi.ac.uk/biomodels-main/BIOMD0000000010
 */
struct MapkSystem {

  using StateType = boost::array<double, 8>;

  static constexpr StateType InitialState = {
      90.0,  // Mos
      10.0,  // Mos-P
      280.0, // Mek1
      10.0,  // Mek1-P
      10.0,  // Mek1-PP
      280.0, // Erk2
      10.0,  // Erk2-P
      10.0   // Erk2-PP
  };

  /* 係数定義は略 */

  void operator()(const StateType &x, StateType &dxdt, double t) {
    // d[Mos]/dt =
    //     - uVol*V1*Mos/((1+(Erk2-PP/Ki)^n)*(K1+Mos))
    //     + uVol*V2*Mos-P/(KK2+Mos-P)
    dxdt[0] =
        - V1 * x[0] / ((1.0 + pow(x[7] / Ki, n)) * (K1 + x[0]))
        + V2 * x[1] / (KK2 + x[1]);

    // d[Mos-P]/dt =
    //     uVol*V1*Mos/((1+(Erk2-PP/Ki)^n)*(K1+Mos))
    //     - uVol*V2*Mos-P/(KK2+Mos-P)
    dxdt[1] =
        V1 * x[0] / ((1.0 + pow(x[7] / Ki, n)) * (K1 + x[0]))
        - V2 * x[1] / (KK2 + x[1]);

    // d[Mek1]/dt =
    //     - uVol*k3*Mos-P*Mek1/(KK3+Mek1)
    //     + uVol*V6*Mek1-P/(KK6+Mek1-P)
    dxdt[2] =
        - k3 * x[1] * x[2] / (KK3 + x[2])
        + V6 * x[3] / (KK6 + x[3]);

    // d[Mek1-P]/dt =
    //     uVol*k3*Mos-P*Mek1/(KK3+Mek1)
    //     - uVol*k4*Mos-P*Mek1-P/(KK4+Mek1-P)
    //     + uVol*V5*Mek1-PP/(KK5+Mek1-PP)
    //     - uVol*V6*Mek1-P/(KK6+Mek1-P)
    dxdt[3] =
        k3 * x[1] * x[2] / (KK3 + x[2])
        - k4 * x[1] * x[3] / (KK4 + x[3])
        + V5 * x[4] / (KK5 + x[4])
        - V6 * x[3] / (KK6 + x[3]);

    // d[Mek1-PP]/dt =
    //     uVol*k4*Mos-P*Mek1-P/(KK4+Mek1-P)
    //     - uVol*V5*Mek1-PP/(KK5+Mek1-PP)
    dxdt[4] =
        k4 * x[1] * x[3] / (KK4 + x[3])
        - V5 * x[4] / (KK5 + x[4]);

    // d[Erk2]/dt =
    //     - uVol*k7*Mek1-PP*Erk2/(KK7+Erk2)
    //     + uVol*V10*Erk2-P/(KK10+Erk2-P)
    dxdt[5] =
        - k7 * x[4] * x[5] / (KK7 + x[5])
        + V10 * x[6] / (KK10 + x[6]);

    // d[Erk2-P]/dt =
    //     uVol*k7*Mek1-PP*Erk2/(KK7+Erk2)
    //     - uVol*k8*Mek1-PP*Erk2-P/(KK8+Erk2-P)
    //     + uVol*V9*Erk2-PP/(KK9+Erk2-PP)
    //     - uVol*V10*Erk2-P/(KK10+Erk2-P)
    dxdt[6] =
        k7 * x[4] * x[5] / (KK7 + x[5])
        - k8 * x[4] * x[6] / (KK8 + x[6])
        + V9 * x[7] / (KK9 + x[7])
        - V10 * x[6] / (KK10 + x[6]);

    // d[Erk2-PP]/dt =
    //     uVol*k8*Mek1-PP*Erk2-P/(KK8+Erk2-P)
    //     - uVol*V9*Erk2-PP/(KK9+Erk2-PP)
    dxdt[7] =
        k8 * x[4] * x[6] / (KK8 + x[6])
        - V9 * x[7] / (KK9 + x[7]);
  }

};

途中経過を表示するためobserverを用意する。標準出力にCSV形式で出力させる。

struct StdoutObserver {

  void operator()(const MapkSystem::StateType &x , const double t) {
    std::cout << t;

    auto size = x.size();
    for (auto i = 0; i < size; i++) {
      std::cout << " " << x[i];
    }

    std::cout << std::endl;
  }

};

RK4でシミュレーション実行。

int main(int argc, char **argv) {
  const double start = 0.0;
  const double duration = 1000.0;
  const double interval = 0.1;

  MapkSystem system;
  StdoutObserver observer;
  odeint::runge_kutta4<MapkSystem::StateType> stepper;

  auto state = MapkSystem::InitialState;

  odeint::integrate_const(stepper, system, state, start, duration, interval, std::ref(observer));

  return 0;
}

RK-Dopriならこう書く。ステップサイズをadaptiveにすることで、細かく刻むよりも実行時間を大幅に短縮できる。

int main(int argc, char **argv) {
  const double start = 0.0;
  const double duration = 1000.0;
  const double interval = 0.1;

  MapkSystem system;
  StdoutObserver observer;
  odeint::runge_kutta_dopri5<MapkSystem::StateType> stepper;
  auto controlledStepper = odeint::make_controlled(0.0001, 0.0001, stepper);

  auto state = MapkSystem::InitialState;

  odeint::integrate_adaptive(controlledStepper, system, state, start, duration, interval, std::ref(observer));

  return 0;
}

結果

Online Simulatorとほぼ同じ結果が得られている。

f:id:aka_mythosil:20170713002640p:plain

Next Step

陰解法も比較的容易に実装できるので試す。ヤコビ行列を用意する必要あり。
また、途中でイベントが挟まるようなモデルをodeintでどう扱うかも調べる。公式にはサポートされていないようなので、odeint自体に手を入れる必要がありそう。

Weld: Java SE環境でCDI利用

  • Java EEのアプリケーションコンテナを利用せず、Java SE環境でCDIを利用する方法。
  • CDIコンテナにはWeldを利用。

ソースコード

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mythosil</groupId>
    <artifactId>weldse</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.jboss.weld</groupId>
            <artifactId>weld-se</artifactId>
            <version>1.0.1-Final</version>
        </dependency>
    </dependencies>
</project>

WeldApplication.java

package com.mythosil.weldse;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;

@Singleton
public class WeldApplication {
    
    @Inject
    private Calc calc;
    
    public void run() {
        System.out.println(calc.add(1, 3));
    }
    
    @PostConstruct
    public void postConstruct() {
        System.out.println("WeldApplication: PostConstruct");
    }
    
    @PreDestroy
    public void preDestroy() {
        System.out.println("WeldApplication: PreDestroy");
    }
    
    public static void main(String[] args) {
        Weld weld = new Weld();
        WeldContainer container = weld.initialize();
        WeldApplication app = container.instance().select(WeldApplication.class).get();
        app.run();
        weld.shutdown();
    }
    
}

Calc.java

package com.mythosil.weldse;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class Calc {
    
    public int add(int a, int b) {
        return a + b;
    }
    
    @PostConstruct
    public void postConstruct() {
        System.out.println("Calc: PostConstruct");
    }
    
    @PreDestroy
    public void preDestroy() {
        System.out.println("Calc: PreDestroy");
    }
    
}

実行

$ mvn exec:java -Dexec.mainClass=com.mythosil.weldse.WeldApplication                                      [~/NetBeansProjects/weldse]
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building weldse 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- exec-maven-plugin:1.3.2:java (default-cli) @ weldse ---
[WARNING] Warning: killAfter is now deprecated. Do you need it ? Please comment on MEXEC-6.
70 [com.mythosil.weldse.WeldApplication.main()] INFO org.jboss.weld.Version - WELD-000900 1.0.1 (Final)
88 [com.mythosil.weldse.WeldApplication.main()] INFO org.jboss.weld.Bootstrap - WELD-000101 Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
570 [com.mythosil.weldse.WeldApplication.main()] WARN org.jboss.interceptor.model.InterceptionTypeRegistry - Class 'javax.ejb.PostActivate' not found, interception based on it is not enabled
571 [com.mythosil.weldse.WeldApplication.main()] WARN org.jboss.interceptor.model.InterceptionTypeRegistry - Class 'javax.ejb.PrePassivate' not found, interception based on it is not enabled
Calc: PostConstruct
WeldApplication: PostConstruct
4
WeldApplication: PreDestroy
Calc: PreDestroy
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.856 s
[INFO] Finished at: 2014-10-22T23:25:21+09:00
[INFO] Final Memory: 11M/114M
[INFO] ------------------------------------------------------------------------

CDI 2.0