Skip to content

hanslovsky/imklib

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DEPRECATED

Deprecation notice: This project was exploratory work. For current development, see saalfeldlab/imklib2.

imklib is an experimental library to explore the use of Kotlin extension functions and operator overloading for a NumPy like user experience for the ImgLib2 Java multi-dimensional image processing library.

For details, check source code, tests, and example:

package net.imglib2.imklib.examples

// import net.imglib2.imklib.extensions.* for RAI extensions
import net.imglib2.imklib.extensions.div
import net.imglib2.imklib.extensions.exp
import net.imglib2.img.array.ArrayImgs
import net.imglib2.imklib.extensions.iterable
import net.imglib2.imklib.extensions.minus
import net.imglib2.imklib.extensions.times
import net.imglib2.imklib.extensions.unaryMinus
import org.knowm.xchart.SwingWrapper
import org.knowm.xchart.XYChartBuilder
import org.knowm.xchart.style.Styler
import kotlin.math.sqrt


fun main() {
    val n = 1000
    val X = ArrayImgs.doubles(n.toLong()).let { it.forEachIndexed { index, t -> t.setReal(index.toDouble()) }; it } / n.toDouble() * 2.0 - 1.0
    val center = 0.3
    val chart = XYChartBuilder()
            .title("Density of normal distribution in interval [-1, 1] for various sigmas")
            .width(800)
            .height(600)
            .theme(Styler.ChartTheme.Matlab).build()
    for (sigma in doubleArrayOf(0.1, 0.3, 0.9, 1.5)) {
        val sigmaSq = sigma * sigma
        val diff = center - X
        val norm = 1.0 / sqrt(2 * Math.PI * sigmaSq)
        val y = norm * (-diff * diff / (2 * sigmaSq)).exp()
        chart.addSeries("Sigma=$sigma", X.iterable().map { it.realDouble }.toDoubleArray(), y.iterable().map { it.realDouble }.toDoubleArray())
    }
    SwingWrapper(chart).displayChart()

}

Or, run this with kscript:

#!/usr/bin/env kscript

@file:MavenRepository("imagej.public", "https://maven.imagej.net/content/groups/public")
@file:DependsOn("net.imglib2:imglib2:5.6.4-SNAPSHOT")
@file:DependsOn("net.imglib2:imklib:0.1.1-SNAPSHOT")
@file:DependsOn("org.janelia.saalfeldlab:n5-imglib2:3.2.0")
@file:DependsOn("org.janelia.saalfeldlab:n5-hdf5:1.0.3")
@file:DependsOn("sc.fiji:bigdataviewer-vistools:1.0.0-beta-13")
@file:DependsOn("net.imagej:ij:1.52k")
@file:DependsOn("net.imglib2:imglib2-ij:2.0.0-beta-45")

import java.nio.file.Files
import java.nio.file.Paths

import bdv.util.BdvFunctions
import bdv.util.BdvOptions
import bdv.util.volatiles.VolatileViews
import ij.ImagePlus
import kotlin.math.sqrt
import kotlin.random.Random
import net.imglib2.img.array.ArrayImgs
import net.imglib2.RandomAccessibleInterval
import net.imglib2.converter.ChannelARGBConverter
import net.imglib2.converter.Converters
import net.imglib2.converter.RealDoubleConverter
import net.imglib2.converter.readwrite.ARGBChannelSamplerConverter
import net.imglib2.img.display.imagej.ImageJFunctions
import net.imglib2.imklib.extensions.*
import net.imglib2.type.numeric.ARGBType
import net.imglib2.type.numeric.integer.IntType
import net.imglib2.type.numeric.integer.UnsignedByteType
import net.imglib2.type.numeric.real.DoubleType
import net.imglib2.util.Intervals
import net.imglib2.view.Views
import org.janelia.saalfeldlab.n5.hdf5.N5HDF5Reader
import org.janelia.saalfeldlab.n5.imglib2.N5Utils
import kotlin.math.max
import kotlin.math.min

val img = ArrayImgs.doubles(1, 2, 3)

fun raiFlatToString(rai: RandomAccessibleInterval<*>) = rai.iterable().joinToString(", ", prefix="${rai::class.java.simpleName}[", postfix="]")

println(raiFlatToString(img))
img += 3.0
println(raiFlatToString(img))
val img2 = Random(100L).let { rng -> img.copy().let {copy -> copy.iterable().forEach {it.timesAssign(rng.nextDouble())}; copy}}
img[0, 1, 2].set(Double.NaN)
println(raiFlatToString(img))
println(raiFlatToString(img2))
println(raiFlatToString(-img2))
// these will only work with next imligb2 release (>5.6.3)
println(raiFlatToString(img2 / img))
println(raiFlatToString(img2.exp()))
println(raiFlatToString(img2.apply({sqrt(it)})))

val checkerboards = ArrayImgs.ints((0 until 8).map { val first = it % 2; (0 until 8).map { first - (it % 2)  }.map { it * it } }.flatten().toIntArray(), 8, 8)
println(raiFlatToString(checkerboards))
println(raiFlatToString(checkerboards[ALL, 0]))
println(raiFlatToString(checkerboards[ALL, 1]))
println(raiFlatToString(checkerboards[SL, 0][SL(0, 7, 2)]))
println(raiFlatToString(checkerboards[SL, 1][SL(0, 7, 2)]))
println(raiFlatToString(checkerboards[SL, 0][SL(1, 7, 2)]))
println(raiFlatToString(checkerboards[SL, 1][SL(1, 7, 2)]))
println(raiFlatToString(checkerboards[+SL, 0]))
println(raiFlatToString(checkerboards[-SL, 0]))

val url = "https://www.dropbox.com/s/g4i5ey9yc281dif/bfly_crop.jpeg?raw=1"
// this does not work, throws
// java.lang.IllegalArgumentException: No compatible service: org.scijava.service.SciJavaServic
// val butterfly = ImageJ().io().open(url)
// println("img: $butterfly")
val imp = ImagePlus(url)
print("imp: $imp")
val factor = 3L
val rai = ImageJFunctions.wrapRGBA(imp)[SL..factor, SL..factor]
val butterflyBdv = BdvFunctions.show(rai, "butterfly", BdvOptions.options().is2D())
val vp = butterflyBdv.bdvHandle.viewerPanel
vp.visibilityAndGrouping.isGroupingEnabled = true
vp.visibilityAndGrouping.isFusedEnabled = false
vp.visibilityAndGrouping.addSourceToGroup(0, 0)
(0 until 3).forEach {
    val channel = Converters.convert(Converters.convert(rai, ARGBChannelSamplerConverter(it + 1)), {src, tgt -> tgt.set(src.get())}, IntType())
    val extended = Views.extendBorder(channel)
    val diffs = (0 until 2).map {
        val fwd = extended[Intervals.translate(rai, +1L, it)]
        val bck = extended[Intervals.translate(rai, -1L, it)]
        fwd - bck
    }
    val diffSquared = diffs.map { it * it }
    val magnitudeSquared = diffSquared.reduce { a, b -> a + b }
    val magnitude = Converters.convert(magnitudeSquared.apply { Math.sqrt(it) }, { src, tgt -> tgt.set(min(max(src.realDouble, 0.0), 255.0).toInt())}, UnsignedByteType())
    val magnitudeARGB = Converters.convert(magnitude, ChannelARGBConverter.converterListRGBA[it], ARGBType())
    BdvFunctions.show(magnitudeARGB, "Gradient channel $it", BdvOptions.options().addTo(butterflyBdv))
    vp.visibilityAndGrouping.addSourceToGroup(it + 1, 1)
}

println("Toggle image and gradient magnitude with `1' and `2' keys")

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published