<commit_before>package scalismo.statisticalmodel

import java.io.File

import scalismo.ScalismoTestSuite
import scalismo.geometry._3D
import scalismo.io.{ ImageIO, MeshIO, StatismoIO }
import scalismo.mesh.{ MeshMetrics, TriangleMesh }
import scalismo.numerics.{ Sampler, UniformMeshSampler3D }
import scalismo.registration.LandmarkRegistration
import scalismo.statisticalmodel.asm._
import scalismo.statisticalmodel.dataset.DataCollection

class ActiveShapeModelTests extends ScalismoTestSuite {

  describe("An active shape model") {
    it("Can be built, transformed and correctly fitted from/to artificial data") {

      val imagePreprocessor = GaussianGradientImagePreprocessor(0.1f)
      val featureExtractor = NormalDirectionFeatureExtractor(10, 1f)
      def samplerPerMesh(mesh: TriangleMesh): Sampler[_3D] = UniformMeshSampler3D(mesh, 1000, 42)
      val searchMethod = NormalDirectionSearchPointSampler(30, 6)
      val fittingConfig = FitConfiguration(featureDistanceThreshold = 2f, pointDistanceThreshold = 3f, modelCoefficientBounds = 3f)

      val shapeModel = StatismoIO.readStatismoMeshModel(new File(getClass.getResource(s"/asmData/model.h5").getPath)).get
      val nbFiles = 7
      val meshes = (0 until nbFiles).map(i => MeshIO.readMesh(new File(getClass.getResource(s"/asmData/$i.stl").getPath)).get)
      val images = (0 until nbFiles).map(i => ImageIO.read3DScalarImage[Float](new File(getClass.getResource(s"/asmData/$i.vtk").getPath)).get)

      val trainMeshes = meshes.drop(1)
      val trainImages = images.drop(1)
      val targetImage = images(0)
      val targetMesh = meshes(0)

      val dc = DataCollection.fromMeshSequence(shapeModel.referenceMesh, trainMeshes)._1.get
      val trainingData = trainImages zip dc.dataItems.map(_.transformation)

      val asm = ActiveShapeModel.trainModel(shapeModel, trainingData.toIterator, imagePreprocessor, featureExtractor, samplerPerMesh)

      // align the model
      val alignment = LandmarkRegistration.rigid3DLandmarkRegistration((asm.statisticalModel.mean.points zip targetMesh.points).toIndexedSeq)
      val alignedASM = asm.transform(alignment)

      // fit
      val fitIterator = alignedASM.fitIterator(targetImage, alignedASM.statisticalModel.mean, searchMethod, fittingConfig, 50)
      val fit = fitIterator.toSeq.last.get.mesh

      assert(MeshMetrics.diceCoefficient(fit, targetMesh) > 0.95)
    }
  }

}<commit_msg>minor modifications to ASM unit test<commit_after>package scalismo.statisticalmodel

import java.io.File

import scalismo.ScalismoTestSuite
import scalismo.geometry._3D
import scalismo.io.{ ImageIO, MeshIO, StatismoIO }
import scalismo.mesh.{ MeshMetrics, TriangleMesh }
import scalismo.numerics.{ Sampler, UniformMeshSampler3D }
import scalismo.registration.LandmarkRegistration
import scalismo.statisticalmodel.asm._
import scalismo.statisticalmodel.dataset.DataCollection

class ActiveShapeModelTests extends ScalismoTestSuite {

  describe("An active shape model") {
    it("Can be built, transformed and correctly fitted from/to artificial data") {

      val imagePreprocessor = GaussianGradientImagePreprocessor(0.1f)
      // number of points should usually be an odd number, so that the profiles are centered on the profiled points
      val featureExtractor = NormalDirectionFeatureExtractor(11, 1f)
      def samplerPerMesh(mesh: TriangleMesh): Sampler[_3D] = UniformMeshSampler3D(mesh, 1000, 42)
      val searchMethod = NormalDirectionSearchPointSampler(31, 6)
      val fittingConfig = FitConfiguration(featureDistanceThreshold = 2f, pointDistanceThreshold = 3f, modelCoefficientBounds = 3f)

      val shapeModel = StatismoIO.readStatismoMeshModel(new File(getClass.getResource(s"/asmData/model.h5").getPath)).get
      val nbFiles = 7
      // use iterators so files are only loaded when required (and memory can be reclaimed after use)
      val meshes = (0 until nbFiles).toIterator map(i => MeshIO.readMesh(new File(getClass.getResource(s"/asmData/$i.stl").getPath)).get)
      val images = (0 until nbFiles).toIterator map{i => println(s"read $i"); ImageIO.read3DScalarImage[Float](new File(getClass.getResource(s"/asmData/$i.vtk").getPath)).get}

      val targetImage = images.next()
      val targetMesh = meshes.next()
      val trainMeshes = meshes
      val trainImages = images

      val dc = DataCollection.fromMeshSequence(shapeModel.referenceMesh, trainMeshes.toIndexedSeq)._1.get
      val trainingData = trainImages zip dc.dataItems.toIterator.map(_.transformation)

      val asm = ActiveShapeModel.trainModel(shapeModel, trainingData, imagePreprocessor, featureExtractor, samplerPerMesh)

      // align the model
      val alignment = LandmarkRegistration.rigid3DLandmarkRegistration((asm.statisticalModel.mean.points zip targetMesh.points).toIndexedSeq)
      val alignedASM = asm.transform(alignment)

      // fit
      val fitIterator = alignedASM.fitIterator(targetImage, alignedASM.statisticalModel.mean, searchMethod, fittingConfig, 50)
      val fit = fitIterator.toSeq.last.get.mesh

      assert(MeshMetrics.diceCoefficient(fit, targetMesh) > 0.95)
    }
  }

}
{'fraction_non_alphanumeric': 0.09014634146341463, 'fraction_numerical': 0.013658536585365854, 'mean_word_length': 4.670353982300885, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3021071', 'n_tokens_mistral': 1565, 'n_tokens_neox': 1476, 'n_words': 334}