mtex 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mtex/__init__.py +94 -0
- mtex/analysis/__init__.py +34 -0
- mtex/analysis/cluster.py +308 -0
- mtex/analysis/data/__init__.py +1 -0
- mtex/analysis/data/cie1931.py +478 -0
- mtex/analysis/denoising.py +511 -0
- mtex/analysis/dislocations.py +105 -0
- mtex/analysis/elasticity.py +372 -0
- mtex/analysis/embedding.py +424 -0
- mtex/analysis/gbnd.py +223 -0
- mtex/analysis/gbnd3d.py +116 -0
- mtex/analysis/kernels.py +181 -0
- mtex/analysis/mechanics.py +286 -0
- mtex/analysis/optics.py +137 -0
- mtex/analysis/optimalsample.py +445 -0
- mtex/analysis/pf2odf.py +464 -0
- mtex/analysis/taylor.py +397 -0
- mtex/analysis/texture.py +345 -0
- mtex/analysis/variational.py +300 -0
- mtex/docpages/CrystalGeometry/CrystalDirections.py +231 -0
- mtex/docpages/CrystalGeometry/CrystalOperations.py +351 -0
- mtex/docpages/CrystalGeometry/CrystalReferenceSystem.py +243 -0
- mtex/docpages/CrystalGeometry/CrystalShapeSmorf.py +151 -0
- mtex/docpages/CrystalGeometry/CrystalShapes.py +349 -0
- mtex/docpages/CrystalGeometry/CrystalSymmetries.py +267 -0
- mtex/docpages/CrystalGeometry/FundamentalSector.py +157 -0
- mtex/docpages/CrystalGeometry/LatticeMetric.py +226 -0
- mtex/docpages/CrystalGeometry/QuasiCrystals.py +166 -0
- mtex/docpages/CrystalGeometry/SymmetryAlignment.py +150 -0
- mtex/docpages/CrystalOrientations/DefinitionAsCoordinateTransform.py +213 -0
- mtex/docpages/CrystalOrientations/MTEXvsBungeConvention.py +201 -0
- mtex/docpages/CrystalOrientations/OrientationDefinition.py +186 -0
- mtex/docpages/CrystalOrientations/OrientationEmbeddings.py +279 -0
- mtex/docpages/CrystalOrientations/OrientationExport.py +180 -0
- mtex/docpages/CrystalOrientations/OrientationFibre.py +311 -0
- mtex/docpages/CrystalOrientations/OrientationFundamentalRegion.py +271 -0
- mtex/docpages/CrystalOrientations/OrientationGrid.py +179 -0
- mtex/docpages/CrystalOrientations/OrientationImport.py +133 -0
- mtex/docpages/CrystalOrientations/OrientationInversePoleFigure.py +172 -0
- mtex/docpages/CrystalOrientations/OrientationPoleFigure.py +144 -0
- mtex/docpages/CrystalOrientations/OrientationStandard.py +266 -0
- mtex/docpages/CrystalOrientations/OrientationSymmetry.py +176 -0
- mtex/docpages/CrystalOrientations/OrientationVisualization3d.py +118 -0
- mtex/docpages/CrystalOrientations/OrientationVisualizationSections.py +127 -0
- mtex/docpages/CrystalOrientations/SpecimenSymmetry.py +145 -0
- mtex/docpages/EBSD3Analysis/EBSD3Analysis.py +249 -0
- mtex/docpages/EBSD3Analysis/EBSD3Plotting.py +240 -0
- mtex/docpages/EBSD3Analysis/Grains3D.py +174 -0
- mtex/docpages/EBSD3Analysis/Grains3DBoundaries.py +199 -0
- mtex/docpages/EBSD3Analysis/Grains3DOperations.py +222 -0
- mtex/docpages/EBSD3Analysis/Grains3DProperties.py +300 -0
- mtex/docpages/EBSD3Analysis/Grains3DReconstruction.py +159 -0
- mtex/docpages/EBSD3Analysis/Grains3DSmoothing.py +224 -0
- mtex/docpages/EBSD3Analysis/NeperInterface.py +211 -0
- mtex/docpages/EBSDAnalysis/EBSD2ODF.py +371 -0
- mtex/docpages/EBSDAnalysis/EBSDAdvancedMaps.py +254 -0
- mtex/docpages/EBSDAnalysis/EBSDDenoising.py +325 -0
- mtex/docpages/EBSDAnalysis/EBSDExport.py +158 -0
- mtex/docpages/EBSDAnalysis/EBSDFilling.py +333 -0
- mtex/docpages/EBSDAnalysis/EBSDGROD.py +276 -0
- mtex/docpages/EBSDAnalysis/EBSDGrid.py +453 -0
- mtex/docpages/EBSDAnalysis/EBSDIPFMap.py +255 -0
- mtex/docpages/EBSDAnalysis/EBSDImport.py +250 -0
- mtex/docpages/EBSDAnalysis/EBSDIndex.py +178 -0
- mtex/docpages/EBSDAnalysis/EBSDInter.py +174 -0
- mtex/docpages/EBSDAnalysis/EBSDInterfaceHDF5.py +268 -0
- mtex/docpages/EBSDAnalysis/EBSDKAM.py +241 -0
- mtex/docpages/EBSDAnalysis/EBSDMapsAndImages.py +283 -0
- mtex/docpages/EBSDAnalysis/EBSDOrientationAnalysis.py +211 -0
- mtex/docpages/EBSDAnalysis/EBSDOrientationPlots.py +215 -0
- mtex/docpages/EBSDAnalysis/EBSDPerceptualKey.py +141 -0
- mtex/docpages/EBSDAnalysis/EBSDPlotting.py +157 -0
- mtex/docpages/EBSDAnalysis/EBSDProfile.py +155 -0
- mtex/docpages/EBSDAnalysis/EBSDPseudoSymmetry.py +278 -0
- mtex/docpages/EBSDAnalysis/EBSDReferenceFrame.py +307 -0
- mtex/docpages/EBSDAnalysis/EBSDSelect.py +204 -0
- mtex/docpages/EBSDAnalysis/EBSDSharpPlot.py +295 -0
- mtex/docpages/EBSDAnalysis/EBSDSimulation.py +180 -0
- mtex/docpages/EBSDAnalysis/EBSDSpatialTransform.py +295 -0
- mtex/docpages/EBSDAnalysis/EBSDTrueEbsd.py +284 -0
- mtex/docpages/Elasticity/AnisotropicTheory.py +281 -0
- mtex/docpages/Elasticity/CPOSeismicProperties.py +248 -0
- mtex/docpages/Elasticity/IsotropicTheory.py +321 -0
- mtex/docpages/Elasticity/WaveVelocities.py +467 -0
- mtex/docpages/GeneralConcepts/ClusterDemo.py +149 -0
- mtex/docpages/GeneralConcepts/Contribute2Doc.py +81 -0
- mtex/docpages/GeneralConcepts/DensityEstimation.py +369 -0
- mtex/docpages/GeneralConcepts/GeneralConceptsConfiguration.py +99 -0
- mtex/docpages/GeneralConcepts/GeneralConceptsOptions.py +96 -0
- mtex/docpages/GeneralConcepts/Glossary.py +261 -0
- mtex/docpages/GeneralConcepts/Installation.py +311 -0
- mtex/docpages/GeneralConcepts/ListsAndIndexing.py +114 -0
- mtex/docpages/GeneralConcepts/MATLABtoPython.py +257 -0
- mtex/docpages/GeneralConcepts/MTEXScripts.py +100 -0
- mtex/docpages/GeneralConcepts/NotationAndConventions.py +185 -0
- mtex/docpages/GeneralConcepts/OptimalKernel.py +253 -0
- mtex/docpages/GeneralConcepts/Properties.py +162 -0
- mtex/docpages/GeneralConcepts/PythonDevelopers.py +172 -0
- mtex/docpages/GeneralConcepts/changelog.py +22 -0
- mtex/docpages/GrainBoundaries/BoundaryCurvature.py +278 -0
- mtex/docpages/GrainBoundaries/BoundaryIntersections.py +144 -0
- mtex/docpages/GrainBoundaries/BoundaryMisorientations.py +201 -0
- mtex/docpages/GrainBoundaries/BoundaryNormalDistribution.py +377 -0
- mtex/docpages/GrainBoundaries/BoundaryPlots.py +274 -0
- mtex/docpages/GrainBoundaries/BoundaryProperties.py +365 -0
- mtex/docpages/GrainBoundaries/BoundarySelect.py +208 -0
- mtex/docpages/GrainBoundaries/CSLBoundaries.py +402 -0
- mtex/docpages/GrainBoundaries/GrainSmoothing.py +258 -0
- mtex/docpages/GrainBoundaries/GrainSmoothingAdvanced.py +357 -0
- mtex/docpages/GrainBoundaries/QuadruplePoints.py +182 -0
- mtex/docpages/GrainBoundaries/SubGrainBoundaries.py +231 -0
- mtex/docpages/GrainBoundaries/TiltAndTwistBoundaries.py +251 -0
- mtex/docpages/GrainBoundaries/TriplePoints.py +246 -0
- mtex/docpages/GrainBoundaries/TwinningBoundaries.py +216 -0
- mtex/docpages/Grains/Dream3dGrains.py +100 -0
- mtex/docpages/Grains/EllipseBasedParameters.py +359 -0
- mtex/docpages/Grains/GrainExport.py +298 -0
- mtex/docpages/Grains/GrainMerge.py +291 -0
- mtex/docpages/Grains/GrainNeighbours.py +235 -0
- mtex/docpages/Grains/GrainOrientationParameters.py +428 -0
- mtex/docpages/Grains/GrainReconstruction.py +382 -0
- mtex/docpages/Grains/GrainReconstructionAdvanced.py +316 -0
- mtex/docpages/Grains/GrainReconstructionMCL.py +162 -0
- mtex/docpages/Grains/GrainSpatialPlots.py +340 -0
- mtex/docpages/Grains/Grain_dispersion_axes.py +317 -0
- mtex/docpages/Grains/HullBasedParameters.py +164 -0
- mtex/docpages/Grains/ProjectionBasedParameters.py +402 -0
- mtex/docpages/Grains/SelectingGrains.py +341 -0
- mtex/docpages/Grains/ShapeParameters.py +341 -0
- mtex/docpages/Misorientations/AngleDistributionFunction.py +177 -0
- mtex/docpages/Misorientations/AxisDistributionFunction.py +231 -0
- mtex/docpages/Misorientations/MisorientationDistributionFunction.py +228 -0
- mtex/docpages/Misorientations/MisorientationGrainExchangeSym.py +163 -0
- mtex/docpages/Misorientations/MisorientationTheory.py +359 -0
- mtex/docpages/Misorientations/Twinning.py +195 -0
- mtex/docpages/ODFAnalysis/BinghamODFs.py +244 -0
- mtex/docpages/ODFAnalysis/DetectionOfSampleSymmetry.py +209 -0
- mtex/docpages/ODFAnalysis/EulerAngleSections.py +212 -0
- mtex/docpages/ODFAnalysis/FibreODFs.py +225 -0
- mtex/docpages/ODFAnalysis/ODFCharacteristics.py +157 -0
- mtex/docpages/ODFAnalysis/ODFComponents.py +175 -0
- mtex/docpages/ODFAnalysis/ODFExport.py +198 -0
- mtex/docpages/ODFAnalysis/ODFImport.py +215 -0
- mtex/docpages/ODFAnalysis/ODFInversePoleFigure.py +158 -0
- mtex/docpages/ODFAnalysis/ODFModeling.py +155 -0
- mtex/docpages/ODFAnalysis/ODFPlot.py +218 -0
- mtex/docpages/ODFAnalysis/ODFPoleFigure.py +165 -0
- mtex/docpages/ODFAnalysis/ODFShapes.py +159 -0
- mtex/docpages/ODFAnalysis/ODFTheory.py +189 -0
- mtex/docpages/ODFAnalysis/RadialODFs.py +165 -0
- mtex/docpages/ODFAnalysis/RandomSampling.py +354 -0
- mtex/docpages/ODFAnalysis/SO3FunHarmonicRepresentation.py +225 -0
- mtex/docpages/ODFAnalysis/SigmaSections.py +260 -0
- mtex/docpages/PhaseTransitions/GrainGraphBasedReconstruction.py +338 -0
- mtex/docpages/PhaseTransitions/LowLevelParentGrainReconstruction.py +388 -0
- mtex/docpages/PhaseTransitions/MaParentGrainReconstruction.py +407 -0
- mtex/docpages/PhaseTransitions/MaParentGrainReconstructionAdvanced.py +461 -0
- mtex/docpages/PhaseTransitions/MartensiteVariants.py +309 -0
- mtex/docpages/PhaseTransitions/OrientationRelationshipFit.py +274 -0
- mtex/docpages/PhaseTransitions/ParentChildVariants.py +197 -0
- mtex/docpages/PhaseTransitions/PhaseTransitions.py +129 -0
- mtex/docpages/PhaseTransitions/TiBetaReconstruction.py +273 -0
- mtex/docpages/PhaseTransitions/TransformationTexture.py +184 -0
- mtex/docpages/PhaseTransitions/TriplePointBasedReconstruction.py +298 -0
- mtex/docpages/Plasticity/DislocationSystems.py +185 -0
- mtex/docpages/Plasticity/GND.py +316 -0
- mtex/docpages/Plasticity/Lankford.py +227 -0
- mtex/docpages/Plasticity/SachsModel.py +139 -0
- mtex/docpages/Plasticity/SchmidFactor.py +304 -0
- mtex/docpages/Plasticity/SingleSlipModel.py +228 -0
- mtex/docpages/Plasticity/SlipSystems.py +148 -0
- mtex/docpages/Plasticity/SlipTransmission.py +231 -0
- mtex/docpages/Plasticity/TaylorHex.py +227 -0
- mtex/docpages/Plasticity/TaylorModel.py +220 -0
- mtex/docpages/Plasticity/TextureEvolution.py +196 -0
- mtex/docpages/Plasticity/TwinningTutorial.py +174 -0
- mtex/docpages/Plasticity/VPSCImport.py +135 -0
- mtex/docpages/Plasticity/WBV.py +299 -0
- mtex/docpages/Plotting/Annotations.py +202 -0
- mtex/docpages/Plotting/AxesAlignment.py +225 -0
- mtex/docpages/Plotting/ColorMaps.py +186 -0
- mtex/docpages/Plotting/CombinedPlots.py +204 -0
- mtex/docpages/Plotting/ContourPlots.py +144 -0
- mtex/docpages/Plotting/Legends.py +73 -0
- mtex/docpages/Plotting/Multiplot.py +115 -0
- mtex/docpages/Plotting/PlotTypes.py +154 -0
- mtex/docpages/Plotting/PlottingExport.py +146 -0
- mtex/docpages/Plotting/SphericalProjections.py +185 -0
- mtex/docpages/Plotting/TransparencyDemo.py +213 -0
- mtex/docpages/PoleFigureAnalysis/PoleFigure2ODF.py +246 -0
- mtex/docpages/PoleFigureAnalysis/PoleFigure2ODFAmbiguity.py +475 -0
- mtex/docpages/PoleFigureAnalysis/PoleFigure2ODFGhostCorrection.py +242 -0
- mtex/docpages/PoleFigureAnalysis/PoleFigureCorrection.py +282 -0
- mtex/docpages/PoleFigureAnalysis/PoleFigureDubna.py +239 -0
- mtex/docpages/PoleFigureAnalysis/PoleFigureExport.py +186 -0
- mtex/docpages/PoleFigureAnalysis/PoleFigureImport.py +198 -0
- mtex/docpages/PoleFigureAnalysis/PoleFigurePlot.py +146 -0
- mtex/docpages/PoleFigureAnalysis/PoleFigureRefinement.py +265 -0
- mtex/docpages/PoleFigureAnalysis/PoleFigureSantaFe.py +203 -0
- mtex/docpages/PoleFigureAnalysis/PoleFigureSimulation.py +215 -0
- mtex/docpages/Rotations/RotationDefinition.py +278 -0
- mtex/docpages/Rotations/RotationFibre.py +192 -0
- mtex/docpages/Rotations/RotationImproper.py +159 -0
- mtex/docpages/Rotations/RotationOperations.py +204 -0
- mtex/docpages/Rotations/RotationPlotting.py +126 -0
- mtex/docpages/Rotations/RotationRepresentations.py +212 -0
- mtex/docpages/Rotations/RotationSpinTensor.py +243 -0
- mtex/docpages/Rotations/RotationTangentSpace.py +178 -0
- mtex/docpages/SO3Functions/HarmonicApproximationTheory.py +308 -0
- mtex/docpages/SO3Functions/RBFApproximationTheory.py +351 -0
- mtex/docpages/SO3Functions/SO3FunApproximationTheory.py +307 -0
- mtex/docpages/SO3Functions/SO3FunConcept.py +146 -0
- mtex/docpages/SO3Functions/SO3FunConvolution.py +359 -0
- mtex/docpages/SO3Functions/SO3FunDefinition.py +202 -0
- mtex/docpages/SO3Functions/SO3FunOperations.py +248 -0
- mtex/docpages/SO3Functions/SO3FunQuadrature.py +266 -0
- mtex/docpages/SO3Functions/SO3FunSymmetricFunctions.py +219 -0
- mtex/docpages/SO3Functions/SO3FunVectorField.py +341 -0
- mtex/docpages/SO3Functions/SO3FunVectorValued.py +248 -0
- mtex/docpages/SO3Functions/SO3Kernels.py +492 -0
- mtex/docpages/SO3Functions/WignerFunctions.py +186 -0
- mtex/docpages/SphericalFunctions/S1FunHarmonics.py +301 -0
- mtex/docpages/SphericalFunctions/S2Bingham.py +183 -0
- mtex/docpages/SphericalFunctions/S2FunApproximationInterpolation.py +141 -0
- mtex/docpages/SphericalFunctions/S2FunAxisField.py +107 -0
- mtex/docpages/SphericalFunctions/S2FunConcept.py +133 -0
- mtex/docpages/SphericalFunctions/S2FunHarmonicRepresentation.py +182 -0
- mtex/docpages/SphericalFunctions/S2FunOperations.py +251 -0
- mtex/docpages/SphericalFunctions/S2FunPlotting.py +153 -0
- mtex/docpages/SphericalFunctions/S2FunQuadrature.py +121 -0
- mtex/docpages/SphericalFunctions/S2FunRadon.py +173 -0
- mtex/docpages/SphericalFunctions/S2FunSampling.py +231 -0
- mtex/docpages/SphericalFunctions/S2FunSym.py +117 -0
- mtex/docpages/SphericalFunctions/S2FunVectorField.py +171 -0
- mtex/docpages/SphericalFunctions/S2FunVectorValued.py +185 -0
- mtex/docpages/SphericalFunctions/S2Kernels.py +261 -0
- mtex/docpages/SphericalFunctions/SphericalHarmonics.py +145 -0
- mtex/docpages/Tensors/BirefringenceDemo.py +414 -0
- mtex/docpages/Tensors/MagneticAnisotropy.py +217 -0
- mtex/docpages/Tensors/PiezoElectricity.py +187 -0
- mtex/docpages/Tensors/TensorArithmetics.py +228 -0
- mtex/docpages/Tensors/TensorAverage.py +247 -0
- mtex/docpages/Tensors/TensorDefinition.py +274 -0
- mtex/docpages/Tensors/TensorImport.py +144 -0
- mtex/docpages/Tensors/TensorVisualisation.py +174 -0
- mtex/docpages/Tutorials/BoundaryTutorial.py +202 -0
- mtex/docpages/Tutorials/EBSDTutorial.py +235 -0
- mtex/docpages/Tutorials/GrainTutorial.py +290 -0
- mtex/docpages/Tutorials/ODFTutorial.py +268 -0
- mtex/docpages/Tutorials/PoleFigureTutorial.py +192 -0
- mtex/docpages/Vectors/VectorDefinition.py +182 -0
- mtex/docpages/Vectors/VectorGrids.py +166 -0
- mtex/docpages/Vectors/VectorsAxes.py +227 -0
- mtex/docpages/Vectors/VectorsDensityEstimation.py +415 -0
- mtex/docpages/Vectors/VectorsExport.py +127 -0
- mtex/docpages/Vectors/VectorsImport.py +129 -0
- mtex/docpages/Vectors/VectorsOperations.py +183 -0
- mtex/functions/__init__.py +72 -0
- mtex/functions/bingham.py +476 -0
- mtex/functions/characteristics.py +940 -0
- mtex/functions/density.py +315 -0
- mtex/functions/discrepancy.py +622 -0
- mtex/functions/funcs.py +29 -0
- mtex/functions/funops.py +401 -0
- mtex/functions/halfwidth.py +583 -0
- mtex/functions/handles.py +585 -0
- mtex/functions/harmonicarithmetic.py +34 -0
- mtex/functions/harmonics.py +519 -0
- mtex/functions/kde.py +211 -0
- mtex/functions/kernelfunctions.py +1125 -0
- mtex/functions/kernels.py +1263 -0
- mtex/functions/lsqr.py +68 -0
- mtex/functions/nfft.py +150 -0
- mtex/functions/polefigure.py +846 -0
- mtex/functions/quadrature.py +322 -0
- mtex/functions/rbf.py +802 -0
- mtex/functions/rbfinterpolation.py +156 -0
- mtex/functions/s1fun.py +339 -0
- mtex/functions/s2axisfield.py +215 -0
- mtex/functions/s2fun.py +530 -0
- mtex/functions/s2funclass.py +78 -0
- mtex/functions/s2funtri.py +152 -0
- mtex/functions/s2vectorfield.py +513 -0
- mtex/functions/so3fun.py +567 -0
- mtex/functions/so3funclass.py +35 -0
- mtex/functions/so3vectorfield.py +915 -0
- mtex/functions/transforms.py +971 -0
- mtex/geometry/__init__.py +94 -0
- mtex/geometry/_array.py +170 -0
- mtex/geometry/arguments.py +24 -0
- mtex/geometry/crystalaxes.py +178 -0
- mtex/geometry/crystalshape.py +584 -0
- mtex/geometry/csl.py +193 -0
- mtex/geometry/data/__init__.py +0 -0
- mtex/geometry/data/cif/4060300.cif +397 -0
- mtex/geometry/data/cif/4060301.cif +316 -0
- mtex/geometry/data/cif/5000035.cif +72 -0
- mtex/geometry/data/cif/Ag-Silver.cif +248 -0
- mtex/geometry/data/cif/Al-Aluminum.cif +240 -0
- mtex/geometry/data/cif/Al2O3-Corundum.cif +83 -0
- mtex/geometry/data/cif/C-Diamond.cif +226 -0
- mtex/geometry/data/cif/Cr-Chromium.cif +152 -0
- mtex/geometry/data/cif/Cu-Copper.cif +248 -0
- mtex/geometry/data/cif/Fe-Iron-Austenite.cif +250 -0
- mtex/geometry/data/cif/Fe-Iron-alpha.cif +154 -0
- mtex/geometry/data/cif/Fe-Iron-beta.cif +154 -0
- mtex/geometry/data/cif/Fe-Iron-delta.cif +154 -0
- mtex/geometry/data/cif/Fe-Iron-gamma.cif +248 -0
- mtex/geometry/data/cif/GaAs.cif +149 -0
- mtex/geometry/data/cif/Hematite.cif +84 -0
- mtex/geometry/data/cif/LaB6.cif +91 -0
- mtex/geometry/data/cif/Magnetite.cif +232 -0
- mtex/geometry/data/cif/Mg-Magnesium.cif +75 -0
- mtex/geometry/data/cif/Mn-Manganese-gamma.cif +227 -0
- mtex/geometry/data/cif/Mo-Molybdenum-bcc.cif +131 -0
- mtex/geometry/data/cif/Mo-Molybdenum-fcc.cif +227 -0
- mtex/geometry/data/cif/NaCl-Halite.cif +232 -0
- mtex/geometry/data/cif/Ni-Nickel-cubic.cif +264 -0
- mtex/geometry/data/cif/Ni-Nickel-hexagonal.cif +69 -0
- mtex/geometry/data/cif/Rhabdite.cif +142 -0
- mtex/geometry/data/cif/Si-Silicon.cif +249 -0
- mtex/geometry/data/cif/Ti-Titanium-alpha.cif +79 -0
- mtex/geometry/data/cif/Ti-Titanium-beta.cif +154 -0
- mtex/geometry/data/cif/ZrO2-Baddeleyite.cif +42 -0
- mtex/geometry/data/cif/crystal.phl +181 -0
- mtex/geometry/data/cif/olivin.cif +77 -0
- mtex/geometry/data/cif/quartz.cif +63 -0
- mtex/geometry/data/crystalshapes.py +172 -0
- mtex/geometry/data/pointgroupnames.py +98 -0
- mtex/geometry/display.py +148 -0
- mtex/geometry/fibre.py +408 -0
- mtex/geometry/framepair.py +20 -0
- mtex/geometry/frames.py +1076 -0
- mtex/geometry/frametransform.py +75 -0
- mtex/geometry/funcs.py +124 -0
- mtex/geometry/gridlayout.py +109 -0
- mtex/geometry/grids/__init__.py +0 -0
- mtex/geometry/grids/fibonacci.py +77 -0
- mtex/geometry/grids/gridsearch.py +343 -0
- mtex/geometry/grids/healpix.py +38 -0
- mtex/geometry/grids/localgrids.py +111 -0
- mtex/geometry/grids/orientationtree.py +185 -0
- mtex/geometry/grids/s1grid.py +124 -0
- mtex/geometry/grids/s2grid.py +306 -0
- mtex/geometry/grids/search.py +162 -0
- mtex/geometry/grids/so3grid.py +307 -0
- mtex/geometry/grids/superfibonacci.py +130 -0
- mtex/geometry/homochoric.py +115 -0
- mtex/geometry/hull.py +155 -0
- mtex/geometry/install.py +28 -0
- mtex/geometry/kernels.py +1108 -0
- mtex/geometry/latticetype.py +60 -0
- mtex/geometry/miller.py +210 -0
- mtex/geometry/orientation.py +552 -0
- mtex/geometry/orientationregion.py +335 -0
- mtex/geometry/parent2child.py +580 -0
- mtex/geometry/plane.py +180 -0
- mtex/geometry/plottingconvention.py +308 -0
- mtex/geometry/products.py +110 -0
- mtex/geometry/quaternion.py +717 -0
- mtex/geometry/representations.py +292 -0
- mtex/geometry/s2triangulation.py +93 -0
- mtex/geometry/session.py +136 -0
- mtex/geometry/settings.py +114 -0
- mtex/geometry/slipsystem.py +485 -0
- mtex/geometry/spatialtransform.py +786 -0
- mtex/geometry/sphericalregion.py +524 -0
- mtex/geometry/standardorientations.py +299 -0
- mtex/geometry/symmetry.py +497 -0
- mtex/geometry/symmetryops.py +383 -0
- mtex/geometry/symreduce.py +111 -0
- mtex/geometry/tangent.py +518 -0
- mtex/geometry/units.py +7 -0
- mtex/geometry/vector3d.py +890 -0
- mtex/geometry/vocabulary.py +51 -0
- mtex/io/__init__.py +31 -0
- mtex/io/ang.py +196 -0
- mtex/io/cif.py +112 -0
- mtex/io/completer.py +291 -0
- mtex/io/crc.py +162 -0
- mtex/io/ctf.py +147 -0
- mtex/io/exportebsd.py +526 -0
- mtex/io/exportodf.py +127 -0
- mtex/io/exportorientation.py +72 -0
- mtex/io/exportpolefigure.py +36 -0
- mtex/io/generic.py +97 -0
- mtex/io/h5.py +840 -0
- mtex/io/h5array.py +125 -0
- mtex/io/hdf5_config/Bruker.json +59 -0
- mtex/io/hdf5_config/EDAX.json +230 -0
- mtex/io/hdf5_config/EDAXh5.json +78 -0
- mtex/io/hdf5_config/EMSphInx.json +69 -0
- mtex/io/hdf5_config/Oxford.json +82 -0
- mtex/io/hdf5_config/ThermoFisher.json +47 -0
- mtex/io/importscript.py +150 -0
- mtex/io/inspect.py +439 -0
- mtex/io/kernels.py +493 -0
- mtex/io/load.py +528 -0
- mtex/io/load3d.py +265 -0
- mtex/io/loadgrains3d.py +172 -0
- mtex/io/loadodf.py +155 -0
- mtex/io/loadpolefigure.py +419 -0
- mtex/io/loadtensor.py +94 -0
- mtex/io/opendoc.py +164 -0
- mtex/io/orientations.py +76 -0
- mtex/io/osc.py +205 -0
- mtex/io/polefigureformats.py +827 -0
- mtex/io/sampledata.json +1521 -0
- mtex/io/sampledata.py +531 -0
- mtex/io/table.py +170 -0
- mtex/io/vectors.py +119 -0
- mtex/io/vocabulary.py +104 -0
- mtex/maps/__init__.py +48 -0
- mtex/maps/boundary.py +870 -0
- mtex/maps/boundaryresampling.py +394 -0
- mtex/maps/calcgrains.py +241 -0
- mtex/maps/criteria.py +266 -0
- mtex/maps/decomposition.py +385 -0
- mtex/maps/dynprop.py +33 -0
- mtex/maps/ebsd.py +678 -0
- mtex/maps/fmc.py +514 -0
- mtex/maps/funcs.py +56 -0
- mtex/maps/grains.py +686 -0
- mtex/maps/gridify.py +321 -0
- mtex/maps/hexgrid.py +63 -0
- mtex/maps/intragranular.py +500 -0
- mtex/maps/kernels.py +1698 -0
- mtex/maps/lattice.py +460 -0
- mtex/maps/mapimage.py +534 -0
- mtex/maps/phaselist.py +231 -0
- mtex/maps/polygon.py +269 -0
- mtex/maps/pseudosym.py +93 -0
- mtex/maps/quadruple.py +121 -0
- mtex/maps/reconstruction.py +1014 -0
- mtex/maps/registration.py +253 -0
- mtex/maps/segment.py +128 -0
- mtex/maps/shape.py +431 -0
- mtex/maps/simulate.py +171 -0
- mtex/maps/smoothing.py +304 -0
- mtex/maps/traces.py +201 -0
- mtex/maps/trueebsd.py +632 -0
- mtex/maps/variantgraph.py +395 -0
- mtex/maps3d/__init__.py +12 -0
- mtex/maps3d/calcgrains3d.py +191 -0
- mtex/maps3d/ebsd3.py +278 -0
- mtex/maps3d/grain3boundary.py +296 -0
- mtex/maps3d/grain3d.py +419 -0
- mtex/maps3d/intragranular3d.py +183 -0
- mtex/maps3d/neper.py +194 -0
- mtex/maps3d/orientfaces.py +99 -0
- mtex/maps3d/section3d.py +179 -0
- mtex/maps3d/smoothing3d.py +163 -0
- mtex/maps3d/voxellattice.py +162 -0
- mtex/plotting/__init__.py +167 -0
- mtex/plotting/colormaps.py +213 -0
- mtex/plotting/directionkeys.py +471 -0
- mtex/plotting/distributionplot.py +116 -0
- mtex/plotting/fibreplot.py +38 -0
- mtex/plotting/grainplots.py +128 -0
- mtex/plotting/kernelplot.py +122 -0
- mtex/plotting/kernels.py +235 -0
- mtex/plotting/keywords.py +102 -0
- mtex/plotting/mapplot.py +1118 -0
- mtex/plotting/maps.py +395 -0
- mtex/plotting/mtexfigure.py +641 -0
- mtex/plotting/orientationkeys.py +474 -0
- mtex/plotting/patalakey.py +204 -0
- mtex/plotting/planarkey.py +158 -0
- mtex/plotting/polarplot.py +311 -0
- mtex/plotting/polefigureplot.py +292 -0
- mtex/plotting/poles.py +82 -0
- mtex/plotting/render3d.py +295 -0
- mtex/plotting/richdisplay.py +84 -0
- mtex/plotting/scene3d.py +339 -0
- mtex/plotting/sectionplot.py +474 -0
- mtex/plotting/sections.py +590 -0
- mtex/plotting/sectorfold.py +263 -0
- mtex/plotting/shapeplot.py +327 -0
- mtex/plotting/space.py +256 -0
- mtex/plotting/spaceplot.py +891 -0
- mtex/plotting/spherical.py +601 -0
- mtex/plotting/sphericalplot.py +1436 -0
- mtex/plotting/tensorplot.py +125 -0
- mtex/plotting/vocabulary.py +29 -0
- mtex/plotting/volumeplot.py +400 -0
- mtex/tensors/__init__.py +12 -0
- mtex/tensors/kernels.py +326 -0
- mtex/tensors/tensor.py +1203 -0
- mtex/wizard/__init__.py +21 -0
- mtex/wizard/__main__.py +18 -0
- mtex/wizard/binning.py +61 -0
- mtex/wizard/browser.py +552 -0
- mtex/wizard/callbacks.py +745 -0
- mtex/wizard/desktop.py +70 -0
- mtex/wizard/icon.svg +23 -0
- mtex/wizard/phases.py +287 -0
- mtex/wizard/pictogram.py +289 -0
- mtex/wizard/scriptview.py +175 -0
- mtex/wizard/state.py +125 -0
- mtex/wizard/views.py +687 -0
- mtex/wizard/window.py +261 -0
- mtex-1.0.0.dist-info/METADATA +190 -0
- mtex-1.0.0.dist-info/RECORD +506 -0
- mtex-1.0.0.dist-info/WHEEL +4 -0
- mtex-1.0.0.dist-info/entry_points.txt +2 -0
- mtex-1.0.0.dist-info/licenses/LICENSE +340 -0
mtex/__init__.py
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"""MTEX: the crystallographic texture analysis toolbox
|
|
2
|
+
|
|
3
|
+
The Python port of MTEX: crystal symmetry and orientations, EBSD maps, grains and their
|
|
4
|
+
boundaries, pole figures, orientation distribution functions and tensors, in one flat
|
|
5
|
+
namespace, with MATLAB's names
|
|
6
|
+
|
|
7
|
+
from mtex import *
|
|
8
|
+
cs = crystalFrame('m-3m')
|
|
9
|
+
ori = orientation.byEuler(30*degree, 50*degree, 10*degree, cs)
|
|
10
|
+
ebsd = mtexdata('forsterite')
|
|
11
|
+
grains = calcGrains(ebsd('indexed'))
|
|
12
|
+
|
|
13
|
+
The namespace is assembled from the layers, each importing only those above it
|
|
14
|
+
|
|
15
|
+
mtex.geometry vectors, rotations, orientations, point groups, frames, Miller indices, grids
|
|
16
|
+
mtex.functions harmonics, kernels, functions on S2 and SO(3), ODFs, pole figures
|
|
17
|
+
mtex.tensors the tensor container, its algebra and the physical tensors
|
|
18
|
+
mtex.maps EBSD maps, grains, grain boundaries, parent grain reconstruction
|
|
19
|
+
mtex.maps3d maps of volumes: EBSD3, 3D grains and boundaries
|
|
20
|
+
mtex.analysis what iterates or optimises: pole figure inversion, elasticity, Taylor, ...
|
|
21
|
+
mtex.io loadEBSD, loadPoleFigure, export, mtexdata, openDoc
|
|
22
|
+
mtex.plotting plot, plotPF, plotIPF, plotSection, the colour keys (matplotlib, the plot extra)
|
|
23
|
+
|
|
24
|
+
Help
|
|
25
|
+
|
|
26
|
+
help(orientation) what a class or function is and takes
|
|
27
|
+
openDoc('GrainReconstruction') a documentation page as a script to run
|
|
28
|
+
mtexdata() the sample data sets
|
|
29
|
+
|
|
30
|
+
The documentation is at https://mtex-toolbox.github.io
|
|
31
|
+
"""
|
|
32
|
+
from importlib.metadata import PackageNotFoundError as _PackageNotFoundError, version as _version
|
|
33
|
+
|
|
34
|
+
# the version of the installed distribution
|
|
35
|
+
try:
|
|
36
|
+
__version__ = _version("mtex")
|
|
37
|
+
except _PackageNotFoundError:
|
|
38
|
+
__version__ = "unknown"
|
|
39
|
+
|
|
40
|
+
from typing import TYPE_CHECKING
|
|
41
|
+
|
|
42
|
+
from . import geometry as _geometry
|
|
43
|
+
from . import maps as _maps
|
|
44
|
+
from . import maps3d as _maps3d
|
|
45
|
+
from . import functions as _functions
|
|
46
|
+
from . import tensors as _tensors
|
|
47
|
+
from . import analysis as _analysis
|
|
48
|
+
from . import io as _io
|
|
49
|
+
from . import plotting as _plotting
|
|
50
|
+
from .geometry import * # noqa: F401,F403
|
|
51
|
+
from .maps import * # noqa: F401,F403
|
|
52
|
+
from .maps3d import * # noqa: F401,F403
|
|
53
|
+
from .functions import * # noqa: F401,F403
|
|
54
|
+
from .tensors import * # noqa: F401,F403
|
|
55
|
+
from .analysis import * # noqa: F401,F403
|
|
56
|
+
from .io import * # noqa: F401,F403
|
|
57
|
+
from .plotting import * # noqa: F401,F403
|
|
58
|
+
from .wizard import importWizard # noqa: F401
|
|
59
|
+
|
|
60
|
+
# the one flat namespace, the layers in the order they import each other
|
|
61
|
+
__all__ = []
|
|
62
|
+
__all__ += _geometry.__all__
|
|
63
|
+
__all__ += _maps.__all__
|
|
64
|
+
__all__ += _maps3d.__all__
|
|
65
|
+
__all__ += _functions.__all__
|
|
66
|
+
__all__ += _tensors.__all__
|
|
67
|
+
__all__ += _analysis.__all__
|
|
68
|
+
__all__ += _io.__all__
|
|
69
|
+
__all__ += _plotting.__all__
|
|
70
|
+
__all__ += ["importWizard", "xvector", "yvector", "zvector"]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# the displays of a notebook and of the IPython terminal, when mtex is imported in one
|
|
74
|
+
from .plotting.richdisplay import registerDisplays as _registerDisplays
|
|
75
|
+
_registerDisplays()
|
|
76
|
+
|
|
77
|
+
# in IPython, the strings a call takes completed inside its quotes
|
|
78
|
+
from .io.completer import registerCompleter as _registerCompleter
|
|
79
|
+
_registerCompleter()
|
|
80
|
+
|
|
81
|
+
# the user's saved settings, what MATLAB keeps in mtex_settings.m
|
|
82
|
+
from .geometry.settings import loadSettings as _loadSettings
|
|
83
|
+
_loadSettings()
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
# xvector, yvector, zvector are fresh on every access
|
|
87
|
+
def __getattr__(name):
|
|
88
|
+
if name in ("xvector", "yvector", "zvector"):
|
|
89
|
+
return getattr(_geometry, name)
|
|
90
|
+
raise AttributeError(name)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if TYPE_CHECKING:
|
|
94
|
+
from .geometry.vector3d import xvector, yvector, zvector
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""the analysis layer: the algorithms that iterate or optimise over the cores, from the
|
|
2
|
+
pole figure inversion to the denoising of a map"""
|
|
3
|
+
from .elasticity import (velocity, energyVector, YoungsModulus, linearCompressibility, volumeCompressibility,
|
|
4
|
+
shearModulus, PoissonRatio, bulkModulus, isotropicShearModulus, HashinShtrikmanModulus,
|
|
5
|
+
hashinShtrikmanBounds)
|
|
6
|
+
from .mechanics import (meanStress, deviatoric, deviatoricStress, deviatoricStrain, equivalentStress, equivalentStrain,
|
|
7
|
+
octahedralStrain, axisRatios, maxStrain, calcShearStress, SchmidFactor, CauchyStrain,
|
|
8
|
+
GreenStrain, strainRate, spin, angularVelocityVector, rotationRate, vorticity, spinTensorOf,
|
|
9
|
+
dislocationDensity)
|
|
10
|
+
from .optics import refractiveIndex, birefringence, opticalAxis, spectralTransmission
|
|
11
|
+
from .taylor import calcTaylor, linearProgram, linprogCentre, TaylorModel
|
|
12
|
+
from .texture import calcTensor, calcLankford, calcKearnsFactor, SO3FunSBF, doEulerStep
|
|
13
|
+
from .pf2odf import MLSSolver, zeroRangeMethod, calcODF, calcODFIterative
|
|
14
|
+
from .embedding import embedding, embeddingSpec, double, setDouble
|
|
15
|
+
from .optimalsample import optimalSample, OptimalSampleResult
|
|
16
|
+
from .cluster import calcCluster, classix, knnRadius
|
|
17
|
+
from .variational import EBSDFilter, splineFilter, halfQuadraticFilter, l1TVFilter, infimalConvolutionFilter
|
|
18
|
+
from .dislocations import fitDislocationSystems
|
|
19
|
+
from .denoising import meanFilter, medianFilter, KuwaharaFilter
|
|
20
|
+
from .gbnd import calcGBNDKernel
|
|
21
|
+
from .gbnd3d import calcGBND
|
|
22
|
+
|
|
23
|
+
__all__ = ["velocity", "energyVector", "YoungsModulus", "linearCompressibility", "volumeCompressibility",
|
|
24
|
+
"shearModulus", "PoissonRatio", "bulkModulus", "isotropicShearModulus", "HashinShtrikmanModulus",
|
|
25
|
+
"hashinShtrikmanBounds", "meanStress", "deviatoric", "deviatoricStress", "deviatoricStrain",
|
|
26
|
+
"equivalentStress", "equivalentStrain", "octahedralStrain", "axisRatios", "maxStrain", "calcShearStress",
|
|
27
|
+
"SchmidFactor", "CauchyStrain", "GreenStrain", "strainRate", "spin", "angularVelocityVector", "rotationRate",
|
|
28
|
+
"vorticity", "spinTensorOf", "dislocationDensity", "refractiveIndex", "birefringence", "opticalAxis",
|
|
29
|
+
"spectralTransmission", "calcTaylor", "linearProgram", "linprogCentre", "TaylorModel", "calcTensor",
|
|
30
|
+
"calcLankford", "calcKearnsFactor", "SO3FunSBF", "doEulerStep", "MLSSolver", "zeroRangeMethod", "calcODF",
|
|
31
|
+
"calcODFIterative", "embedding", "embeddingSpec", "double", "setDouble", "optimalSample",
|
|
32
|
+
"OptimalSampleResult", "calcCluster", "classix", "knnRadius", "EBSDFilter", "splineFilter",
|
|
33
|
+
"halfQuadraticFilter", "l1TVFilter", "infimalConvolutionFilter", "fitDislocationSystems", "meanFilter",
|
|
34
|
+
"medianFilter", "KuwaharaFilter", "calcGBND", "calcGBNDKernel"]
|
mtex/analysis/cluster.py
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# clustering directions and orientations (MATLAB vector3d/calcCluster, orientation/calcCluster,
|
|
2
|
+
# extern/classix; docs/plans/functions.md F6, ported 2026-09-22)
|
|
3
|
+
#
|
|
4
|
+
# cId, center = calcCluster(v) CLASSIX on the coordinates
|
|
5
|
+
# cId, center = calcCluster(ori, method='classix', radius=, minPoints=)
|
|
6
|
+
# cId, center = calcCluster(ori) the modes of the density, MATLAB's default
|
|
7
|
+
# cId, center = calcCluster(ori, method='hierarchical', maxAngle=15*degree, numCluster=)
|
|
8
|
+
# labels = classix(X, radius, minPts=, mergeScale=1.5)
|
|
9
|
+
#
|
|
10
|
+
# CLASSIX (Chen and Guettel, Fast and explainable clustering based on sorting,
|
|
11
|
+
# arXiv:2202.01456): the data is centred, scaled by its median norm and sorted along its
|
|
12
|
+
# first principal axis; every point joins the first group whose centre lies within radius;
|
|
13
|
+
# groups whose centres lie within mergeScale times the radius are merged; a cluster below
|
|
14
|
+
# minPts points is dissolved into the nearest larger one. Directions cluster on their
|
|
15
|
+
# coordinates, axes on the rank one tensor that identifies v with -v, orientations on the
|
|
16
|
+
# isometric embedding that carries the symmetry. The hierarchical method merges the closest
|
|
17
|
+
# pair of centres until the count or the angle is reached; the density method takes the
|
|
18
|
+
# modes the orientations ascend to.
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import numpy as np
|
|
22
|
+
|
|
23
|
+
from ..geometry.orientation import orientation
|
|
24
|
+
from ..geometry.quaternion import rotation
|
|
25
|
+
from ..geometry.units import degree
|
|
26
|
+
from ..geometry.vector3d import vector3d
|
|
27
|
+
from ..geometry.install import install
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# ------------------------------------------------------------------ CLASSIX
|
|
31
|
+
|
|
32
|
+
# the entries of one block of distances when the small clusters are dissolved
|
|
33
|
+
DISSOLVE_BLOCK = 1 << 22
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def classix(X, radius, minPts=1, mergeScale=1.5, mergeTiny=True):
|
|
37
|
+
"""one cluster label per row of X, counted from zero"""
|
|
38
|
+
X = np.asarray(X, dtype=float)
|
|
39
|
+
if X.ndim == 1:
|
|
40
|
+
X = X[:, None]
|
|
41
|
+
n, d = X.shape
|
|
42
|
+
if n == 0:
|
|
43
|
+
return np.zeros(0, dtype=int)
|
|
44
|
+
if radius <= 0:
|
|
45
|
+
raise ValueError("the radius must be positive")
|
|
46
|
+
# centre by the mean, scale by the median norm
|
|
47
|
+
x = X - X.mean(axis=0)
|
|
48
|
+
scale = np.median(np.linalg.norm(x, axis=1))
|
|
49
|
+
x = x / (scale if scale > 0 else 1.0)
|
|
50
|
+
# the scores along the first principal axis, oriented deterministically
|
|
51
|
+
if d == 1:
|
|
52
|
+
u = x[:, 0].copy()
|
|
53
|
+
else:
|
|
54
|
+
vals, vecs = np.linalg.eigh(x.T @ x)
|
|
55
|
+
u = x @ vecs[:, np.argmax(np.abs(vals))]
|
|
56
|
+
u = u * (1.0 if u[0] == 0 else -np.sign(u[0]))
|
|
57
|
+
perm = np.argsort(u, kind="stable")
|
|
58
|
+
x, u = x[perm], u[perm]
|
|
59
|
+
halfN = np.sum(x * x, axis=1) / 2
|
|
60
|
+
halfR2 = radius ** 2 / 2
|
|
61
|
+
# aggregation: the first group within the radius takes the point
|
|
62
|
+
label = np.full(n, -1)
|
|
63
|
+
centres, sizes = [], []
|
|
64
|
+
for i in range(n):
|
|
65
|
+
if label[i] >= 0:
|
|
66
|
+
continue
|
|
67
|
+
lab = len(centres)
|
|
68
|
+
centres.append(i)
|
|
69
|
+
sizes.append(1)
|
|
70
|
+
label[i] = lab
|
|
71
|
+
hi = np.searchsorted(u, u[i] + radius, side="right")
|
|
72
|
+
if hi <= i + 1:
|
|
73
|
+
continue
|
|
74
|
+
window = slice(i + 1, hi)
|
|
75
|
+
close = (label[window] < 0) & (halfN[window] - x[window] @ x[i] <= halfR2 - halfN[i])
|
|
76
|
+
idx = np.flatnonzero(close) + i + 1
|
|
77
|
+
label[idx] = lab
|
|
78
|
+
sizes[lab] += idx.size
|
|
79
|
+
centres, sizes = np.array(centres), np.array(sizes)
|
|
80
|
+
ng = len(centres)
|
|
81
|
+
# merge the group centres within mergeScale times the radius by union find
|
|
82
|
+
gx, gu, gh = x[centres], u[centres], halfN[centres]
|
|
83
|
+
parent = np.arange(ng)
|
|
84
|
+
|
|
85
|
+
def find(a):
|
|
86
|
+
while parent[a] != a:
|
|
87
|
+
parent[a] = parent[parent[a]]
|
|
88
|
+
a = parent[a]
|
|
89
|
+
return a
|
|
90
|
+
|
|
91
|
+
mr = mergeScale * radius
|
|
92
|
+
for i in range(ng):
|
|
93
|
+
if not mergeTiny and sizes[i] < minPts:
|
|
94
|
+
continue
|
|
95
|
+
hi = np.searchsorted(gu, gu[i] + mr, side="right")
|
|
96
|
+
if hi <= i + 1:
|
|
97
|
+
continue
|
|
98
|
+
window = slice(i + 1, hi)
|
|
99
|
+
close = gh[window] - gx[window] @ gx[i] <= mr ** 2 / 2 - gh[i]
|
|
100
|
+
if not mergeTiny:
|
|
101
|
+
close &= sizes[window] >= minPts
|
|
102
|
+
ri = find(i)
|
|
103
|
+
for j in np.flatnonzero(close) + i + 1:
|
|
104
|
+
rj = find(j)
|
|
105
|
+
if ri != rj:
|
|
106
|
+
if ri < rj:
|
|
107
|
+
parent[rj] = ri
|
|
108
|
+
else:
|
|
109
|
+
parent[ri] = rj
|
|
110
|
+
ri = rj
|
|
111
|
+
gLabel, counts = _renumber(np.array([find(k) for k in range(ng)]), sizes)
|
|
112
|
+
# dissolve the clusters below minPts into the nearest group of a large enough cluster
|
|
113
|
+
if np.any(counts < minPts):
|
|
114
|
+
fixed = gLabel.copy()
|
|
115
|
+
large = counts[fixed] >= minPts
|
|
116
|
+
if np.any(large):
|
|
117
|
+
# every group of a small cluster to the nearest group of a large one, in blocks of rows
|
|
118
|
+
small = np.flatnonzero(~large)
|
|
119
|
+
step = max(1, DISSOLVE_BLOCK // len(gh))
|
|
120
|
+
for a in range(0, len(small), step):
|
|
121
|
+
g = small[a:a + step]
|
|
122
|
+
dist = gh - gx[g] @ gx.T
|
|
123
|
+
dist[:, ~large] = np.inf
|
|
124
|
+
gLabel[g] = fixed[np.argmin(dist, axis=1)]
|
|
125
|
+
gLabel, counts = _renumber(gLabel, sizes)
|
|
126
|
+
out = np.empty(n, dtype=int)
|
|
127
|
+
out[perm] = gLabel[label]
|
|
128
|
+
return out
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# the labels renamed to 0..K-1, in order of appearance, with the points per cluster
|
|
132
|
+
def _renumber(gLabel, sizes):
|
|
133
|
+
uniq, inv = np.unique(gLabel, return_inverse=True)
|
|
134
|
+
counts = np.bincount(inv, weights=sizes, minlength=len(uniq)).astype(int)
|
|
135
|
+
return inv, counts
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def knnRadius(X, k=10, sub=1500):
|
|
139
|
+
"""the median distance to the tenth nearest neighbour of a subsample, the estimate CLASSIX suggests"""
|
|
140
|
+
from scipy.spatial import cKDTree
|
|
141
|
+
X = np.asarray(X, dtype=float)
|
|
142
|
+
n = len(X)
|
|
143
|
+
if n <= k + 1:
|
|
144
|
+
return 1.0
|
|
145
|
+
idx = np.arange(n) if n <= sub else np.unique(np.round(np.linspace(0, n - 1, sub)).astype(int))
|
|
146
|
+
d, _ = cKDTree(X).query(X[idx], k=k + 1)
|
|
147
|
+
return float(np.median(d[:, -1]))
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
# ------------------------------------------------------------------ the clusters of directions and orientations
|
|
151
|
+
|
|
152
|
+
def calcCluster(x, *args, method=None, radius=None, minPoints=None, mergeScale=1.5, numCluster=None, maxAngle=None,
|
|
153
|
+
halfwidth=5 * degree, weights=None, resolution=2.5 * degree, verbose=False):
|
|
154
|
+
"""the clusters of directions or orientations: one cluster id per element, counted from
|
|
155
|
+
zero, and the centre of every cluster
|
|
156
|
+
|
|
157
|
+
cId, center = calcCluster(v) directions by CLASSIX
|
|
158
|
+
cId, center = calcCluster(ori, method='classix', radius=0.1, minPoints=15)
|
|
159
|
+
cId, center = calcCluster(ori) the modes of the density
|
|
160
|
+
cId, center = calcCluster(ori, method='hierarchical', maxAngle=15*degree)
|
|
161
|
+
cId, center = calcCluster(v, method='hierarchical', numCluster=5)
|
|
162
|
+
"""
|
|
163
|
+
for a in args:
|
|
164
|
+
if isinstance(a, str):
|
|
165
|
+
method = a
|
|
166
|
+
isOri = isinstance(x, orientation)
|
|
167
|
+
if method is None:
|
|
168
|
+
method = "odf" if isOri else "classix"
|
|
169
|
+
if method == "classix":
|
|
170
|
+
return _classixCluster(x, radius, minPoints, mergeScale)
|
|
171
|
+
if method == "hierarchical":
|
|
172
|
+
return _hierarchical(x, numCluster, maxAngle, weights, resolution)
|
|
173
|
+
if method == "odf":
|
|
174
|
+
if not isOri:
|
|
175
|
+
raise ValueError("the density method clusters orientations; use 'classix' or 'hierarchical' for directions")
|
|
176
|
+
return _densityCluster(x, halfwidth, weights, numCluster)
|
|
177
|
+
raise ValueError("the method is 'classix', 'hierarchical' or 'odf'")
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _classixCluster(x, radius, minPoints, mergeScale):
|
|
181
|
+
n = x.size
|
|
182
|
+
if isinstance(x, orientation):
|
|
183
|
+
from .embedding import embedding
|
|
184
|
+
X = embedding(x.flatten()).double()
|
|
185
|
+
r = 0.5 * knnRadius(X) / np.max(np.std(X, axis=0)) if radius is None else float(radius)
|
|
186
|
+
else:
|
|
187
|
+
v = x.flatten()
|
|
188
|
+
xyz = v.normalize().data
|
|
189
|
+
if v.antipodal:
|
|
190
|
+
X = np.stack([xyz[:, 0] ** 2, xyz[:, 1] ** 2, xyz[:, 2] ** 2, xyz[:, 0] * xyz[:, 1], xyz[:, 0] * xyz[:, 2], xyz[:, 1] * xyz[:, 2]], axis=1)
|
|
191
|
+
else:
|
|
192
|
+
X = xyz
|
|
193
|
+
r = 2 * knnRadius(X) if radius is None else float(radius)
|
|
194
|
+
mp = max(1, round(n / 100)) if minPoints is None else int(minPoints)
|
|
195
|
+
cId = classix(X, r, minPts=mp, mergeScale=mergeScale)
|
|
196
|
+
return cId.reshape(x.shape), _centers(x, cId)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
# the mean of every cluster, as the elements are: an axis mean for axes, a symmetry reduced
|
|
200
|
+
# mean for orientations
|
|
201
|
+
def _centers(x, cId):
|
|
202
|
+
K = int(cId.max()) + 1 if cId.size else 0
|
|
203
|
+
flat = x.flatten()
|
|
204
|
+
if isinstance(x, orientation):
|
|
205
|
+
q = np.stack([rotation(flat[cId == c].mean().data).data.reshape(4) for c in range(K)]) if K else np.zeros((0, 4))
|
|
206
|
+
return orientation(rotation(q), x.CS, x.SS, antipodal=x.antipodal)
|
|
207
|
+
data = np.stack([flat[cId == c].mean().data.reshape(3) for c in range(K)]) if K else np.zeros((0, 3))
|
|
208
|
+
return vector3d(data, antipodal=x.antipodal, frame=x.frame)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
# the modes of the density the orientations ascend to, the largest numCluster of them
|
|
212
|
+
def _densityCluster(o, halfwidth, weights, numCluster):
|
|
213
|
+
from ..functions.characteristics import calcComponents
|
|
214
|
+
from ..functions.density import calcDensity
|
|
215
|
+
flat = o.flatten()
|
|
216
|
+
odf = calcDensity(flat, weights=weights, halfwidth=halfwidth)
|
|
217
|
+
modes, vol, cId = calcComponents(odf, seed=flat, weights=weights)
|
|
218
|
+
K = min(20 if numCluster is None else int(numCluster), modes.size)
|
|
219
|
+
cId = np.asarray(cId).astype(float)
|
|
220
|
+
cId[cId >= K] = np.nan
|
|
221
|
+
center = modes[:K]
|
|
222
|
+
# the points too far from their centre, beyond twice the mean angle, are dropped
|
|
223
|
+
for i in range(K):
|
|
224
|
+
mask = cId == i
|
|
225
|
+
if not np.any(mask):
|
|
226
|
+
continue
|
|
227
|
+
omega = flat[mask].angle(center[i])
|
|
228
|
+
far = np.flatnonzero(mask)[omega > 2 * np.mean(omega)]
|
|
229
|
+
cId[far] = np.nan
|
|
230
|
+
return cId.reshape(o.shape), center
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# the closest pair of centres merged, the mean weighted by the points behind them, until
|
|
234
|
+
# the number of clusters or the angle between the centres is reached; a large list is
|
|
235
|
+
# binned on a grid first
|
|
236
|
+
def _hierarchical(x, numCluster, maxAngle, weights, resolution):
|
|
237
|
+
flat = x.flatten()
|
|
238
|
+
n = flat.size
|
|
239
|
+
w = np.ones(n) if weights is None else np.asarray(weights, dtype=float).ravel()
|
|
240
|
+
isOri = isinstance(x, orientation)
|
|
241
|
+
if n > 1000 and isOri:
|
|
242
|
+
from ..geometry.grids.so3grid import equispacedSO3Grid
|
|
243
|
+
g = equispacedSO3Grid(x.CS, x.SS, resolution=resolution)
|
|
244
|
+
ind, _ = g.find(flat)
|
|
245
|
+
gw = np.bincount(np.asarray(ind).ravel(), weights=w, minlength=g.size)
|
|
246
|
+
keep = gw > 0
|
|
247
|
+
_, center = _hierarchical(g.subGrid(keep), numCluster, maxAngle, gw[keep], resolution)
|
|
248
|
+
cId = _nearest(flat, center)
|
|
249
|
+
center = _centers(x, cId)
|
|
250
|
+
cId = _nearest(flat, center)
|
|
251
|
+
counts = np.bincount(cId, minlength=center.size)
|
|
252
|
+
order = np.argsort(-counts, kind="stable")
|
|
253
|
+
rank = np.empty_like(order)
|
|
254
|
+
rank[order] = np.arange(order.size)
|
|
255
|
+
cId = rank[cId]
|
|
256
|
+
center = center[order][counts[order] > 0]
|
|
257
|
+
return cId.reshape(x.shape), center
|
|
258
|
+
nTarget = 2 if numCluster is None else int(numCluster)
|
|
259
|
+
cosMax = -np.inf if maxAngle is None else np.cos(maxAngle)
|
|
260
|
+
members = [[i] for i in range(n)]
|
|
261
|
+
# the coordinates of the centres, one row each, the merged ones kept but never read again
|
|
262
|
+
C = np.array(flat.data.reshape(n, -1), dtype=float)
|
|
263
|
+
d = _similarity(flat, flat)
|
|
264
|
+
np.fill_diagonal(d, -np.inf)
|
|
265
|
+
alive = np.ones(n, dtype=bool)
|
|
266
|
+
while np.count_nonzero(alive) > nTarget:
|
|
267
|
+
k = int(np.argmax(d))
|
|
268
|
+
i, j = divmod(k, n)
|
|
269
|
+
if d[i, j] < cosMax:
|
|
270
|
+
break
|
|
271
|
+
members[i] += members[j]
|
|
272
|
+
members[j] = []
|
|
273
|
+
alive[j] = False
|
|
274
|
+
sel = np.array(members[i])
|
|
275
|
+
centre = flat[sel].mean(weights=w[sel])
|
|
276
|
+
C[i] = centre.data.reshape(-1)
|
|
277
|
+
dd = _similarity(centre, flat._new(C)).ravel()
|
|
278
|
+
dd[~alive] = -np.inf
|
|
279
|
+
dd[i] = -np.inf
|
|
280
|
+
d[i, :] = dd
|
|
281
|
+
d[:, i] = dd
|
|
282
|
+
d[j, :] = -np.inf
|
|
283
|
+
d[:, j] = -np.inf
|
|
284
|
+
cId = np.empty(n, dtype=int)
|
|
285
|
+
keep = np.flatnonzero(alive)
|
|
286
|
+
for c, i in enumerate(keep):
|
|
287
|
+
cId[members[i]] = c
|
|
288
|
+
center = flat._new(C[keep])
|
|
289
|
+
return cId.reshape(x.shape), center
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
# the cosine of the angle between every pair, reduced by the symmetry
|
|
293
|
+
def _similarity(a, b):
|
|
294
|
+
A, B = a.reshape(-1, 1), b.reshape(1, -1)
|
|
295
|
+
return np.cos(A.angle(B))
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def _nearest(x, center):
|
|
299
|
+
return np.argmin(x.reshape(-1, 1).angle(center.reshape(1, -1)), axis=1)
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def _install():
|
|
303
|
+
install((vector3d, orientation), calcCluster)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
_install()
|
|
307
|
+
|
|
308
|
+
__all__ = ["calcCluster", "classix", "knnRadius"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""the data tables of the function layer"""
|