EUGM 2014 - Stefan Höck (Zurich University of Applied Sciences): CyBy2: A modular Rich Client for...
description
Transcript of EUGM 2014 - Stefan Höck (Zurich University of Applied Sciences): CyBy2: A modular Rich Client for...
A modular Rich Client for managing
Chemical and Biological Data
Who we are
Group of about 15 research scientists
Medicinal chemistry
Organic synthesis
Organic analysis
Cheminformatics
Requirements
Chemical (structure-based) database
Client / Server architecture
Desktop application to access, search and
modify the database
Searching chemicals by (sub)structure
Flexible (modular) setup
CyBy2-Server
JChem for storing / retrieving chemicals
Derby database
Akka middleware
CyBy2-Client
Marvin Beans for drawing / displaying molecules
Modular design (based on Netbeans
platform)
Features
Grouping compounds in projects
Linking of additional data (files) with
compounds
Linking of biological assay data with
compounds
Fine grained control over user access rights
Main-View
Grid-View
Conditional Formatting
CyBy2-Users
S.Höck, R.Riedl, Chimia 2012, 66, 132
Programming
CyBy2 written completely in Scala
Multiparadigm (Object Oriented /
Functional)
CyBy2 written in purely functional style
Functional Programming
Functions as first class values
Immutability
Type safe
Thread safe
Powerful abstractions
Some code
•def atoms(m: Molecule): List[Atom] = ...
•def mass(a: Atom): Double = ...
•def mw(m: Molecule): Double =
• atoms(m).map(mass).sum
•Type inference + nicer syntax:
•def mw(m: Molecule) = atoms(m) map mass sum
Error handling
•def mass(a: Atom): Option[Double] = ...
•Option: Type safe handling of undefined values:
•Some(12.011) if value is defined, otherwise None.
•No more NullPointerExceptions.
•But:
•def mw(m: Molecule) = atoms(m) map mass sum
•Compilation error: Can't sum over Option.
Abstraction
•The Monoid Type Class
•trait Monoid[A] {
• def zero: A
• def add(a1: A, a2: A): A
•}
•Monoid instance for integer addition
•object IntMonoid extends Monoid[Int]{
• def zero: Int = 0
• def add(a1: Int, a2: Int): Int = a1 + a2
•}
Data Accumulation
•Start with Monoid zero and accumulate through Monoid add:
•def accum[A](as: List[A])(M: Monoid[A]): A =
• as.foldLeft(M.zero)(M.add)
•Scala's type class mechanism lets us pass the Monoid instance implicitly:
•def accum[A](as: List[A])(implicit M: Monoid[A]): A =
• as.foldLeft(M.zero)(M.add)
Data Accumulation
•class List[A] {
•
• def foldMap[B](f: A => B)(implicit M: Monoid[B]):B =
• foldLeft(M.zero)((b,a) => M.add(b, f(a)))
•
•}
•def mass(a: Atom): Double ...
•def mw(m: Molecule): Double = atoms(m) foldMap mass
Error accumulation
•An Option of a Monoid automatically defines a Monoid:
•def mass(a: Atom): Option[Double] = ...
•def mw(m: Molecule) = atoms(m) foldMap mass
•Plus error handling (accumulating error messages for free):
•def mass(a: Atom): Validation[Double] = ...
•def mw(m: Molecule) = atoms(m) foldMap mass
Molecular Formula
•type Formula = Map[Atom,Int]
•def singleAtom(a: Atom): Formula = Map(a -> 1)
•A Map with a Monoid as its value type defines another
Monoid:
•def formula(m: Molecule) = atoms(m) foldMap
singleAtom
Functional Programming
Referentially transparent (immutability)
Thread safe
Powerful abstractions
Interoperability with non-functional libraries can
be awkward and unsafe
S.Höck, R.Riedl, J. Cheminform. 2012, 4, 38
Thanks
The End
•Questions ?