public float3[] GetDeformationDelta(float3[] actuatorDeltas, int iterations, int relaxationIterations, float stopDelta, out float force, out float strain, out float actuatorStrain) { float3[] OldDeformed = CoarseNodes.ToList().ToArray(); Func <bool, Tuple <float, float> > SimulateStep = useActuators => { float MeanDelta = 0; float MeanStrain = 0; float3[] NewDeformed = new float3[NCoarseNodes]; float3[] Forces = new float3[NCoarseNodes]; for (int n1 = 0; n1 < NCoarseNodes; n1++) { float3 Force = new float3(0, 0, 0); float3 Pos1 = OldDeformed[n1]; int NeighborsStart = CoarseNeighborIDOffsets[n1]; int NeighborsEnd = CoarseNeighborIDOffsets[n1 + 1]; for (int i = NeighborsStart; i < NeighborsEnd; i++) { float3 Pos2 = OldDeformed[CoarseNeighborIDs[i]]; float OriLength = CoarseEdgeLengths[i]; float3 Diff = Pos1 - Pos2; float CurLength = Diff.Length(); float Delta = (OriLength - CurLength) * 0.1f; float3 DiffNorm; if (CurLength > 0) { DiffNorm = Diff / CurLength; } else { DiffNorm = new float3(1e-3f, 0, 0); } Force += DiffNorm * Delta; MeanStrain += Math.Abs(OriLength - CurLength); } if (useActuators && ConnectedToActuator[n1] >= 0) { float3 ActuatorPos = CoarseNodes[n1] + actuatorDeltas[ConnectedToActuator[n1]]; float3 Diff = ActuatorPos - Pos1; float CurLength = Diff.Length(); float Delta = CurLength * 0.2f; float3 DiffNorm = new float3(0, 0, 0); if (CurLength > 0) { DiffNorm = Diff / CurLength; } Force += DiffNorm * Delta; } NewDeformed[n1] = OldDeformed[n1] + Force; MeanDelta += Force.Length(); Forces[n1] = Force; } OldDeformed = NewDeformed; MeanDelta /= NCoarseNodes; MeanStrain /= NCoarseEdges; return(new Tuple <float, float>(MeanDelta, MeanStrain)); }; int Iteration = 0; while (true) { Tuple <float, float> Result = SimulateStep(true); force = Result.Item1; strain = Result.Item2; if (iterations <= 0 && stopDelta <= 0) { break; // Otherwise there is no end } if (++Iteration >= iterations && iterations > 0) { break; } if (Result.Item1 <= stopDelta) { break; } } for (int i = 0; i < relaxationIterations; i++) { Tuple <float, float> Result = SimulateStep(false); force = Result.Item1; strain = Result.Item2; } actuatorStrain = 0; for (int a = 0; a < NActuators; a++) { actuatorStrain += (OldDeformed[ActuatorNodes[a]] - (CoarseNodes[ActuatorNodes[a]] + actuatorDeltas[a])).Length(); } actuatorStrain /= NActuators; float3[] Deltas = new float3[NCoarseNodes]; for (int n = 0; n < NCoarseNodes; n++) { Deltas[n] = OldDeformed[n] - CoarseNodes[n]; } return(Deltas); }
private void ImageDisplay_OnMouseMove(object sender, MouseEventArgs e) { float2 Viewport2DPixels, Viewport2DWorld; bool HitTestResult; float3 Viewport3DWorld; GetMouseStats(e.GetPosition(ImageDisplay), out Viewport2DPixels, out Viewport2DWorld, out HitTestResult, out Viewport3DWorld); PreviewViewportMouseMove?.Invoke(Viewport2DPixels, Viewport2DWorld, HitTestResult, Viewport3DWorld, e); if (e.Handled) { return; } PutOnDevice(); float2 NewMousePos = new float2((float)e.GetPosition(ImageDisplay).X, (float)e.GetPosition(ImageDisplay).Y); float2 MouseDelta = NewMousePos - LastMousePos; LastMousePos = NewMousePos; if (IsMouseDraggingRotate || IsMouseDraggingPan) { RenderingEnabled = false; } if (IsMouseDraggingRotate) { float3 Axis = new float3(MouseDelta.Y, MouseDelta.X, 0); Matrix3 MAxis = Matrix3.RotateAxis(Axis, -(float)Math.Asin(Math.Min(1, Math.Max(-1, Axis.Length() / (Volume != null ? Volume.Dims.X / 4 : 1) / Math.Max(1, (float)Camera.Zoom))))); Matrix3 MEuler = Matrix3.Euler((float)Camera.AngleRot * Helper.ToRad, (float)Camera.AngleTilt * Helper.ToRad, (float)Camera.AnglePsi * Helper.ToRad).Transposed(); float3 NewAngles = Matrix3.EulerFromMatrix((MEuler * MAxis).Transposed()) * Helper.ToDeg; while (NewAngles.X < -360) { NewAngles.X += 360; } while (NewAngles.X > 360) { NewAngles.X -= 360; } while (NewAngles.Y < -360) { NewAngles.Y += 360; } while (NewAngles.Y > 360) { NewAngles.Y -= 360; } while (NewAngles.Z < -360) { NewAngles.Z += 360; } while (NewAngles.Z > 360) { NewAngles.Z -= 360; } Camera.AngleRot = (decimal)NewAngles.X; Camera.AngleTilt = (decimal)NewAngles.Y; Camera.AnglePsi = (decimal)NewAngles.Z; } if (IsMouseDraggingPan) { Camera.PanX += (decimal)MouseDelta.X / Camera.Zoom; Camera.PanY -= (decimal)MouseDelta.Y / Camera.Zoom; } if (IsMouseDraggingRotate || IsMouseDraggingPan) { RenderingEnabled = true; UpdateRendering(); } }
public static float3 MyEulerFromMatrix(Matrix3 a) { float3 rotated = a * (new float3(0, 0, 1)); return(new float3((float)(Math.PI + Math.Atan2(rotated.Y, rotated.X)), (float)(Math.Acos(rotated.Z / rotated.Length())), 0)); }
private async void ButtonWrite_OnClick(object sender, RoutedEventArgs e) { System.Windows.Forms.SaveFileDialog SaveDialog = new System.Windows.Forms.SaveFileDialog { Filter = "STAR Files|*.star" }; System.Windows.Forms.DialogResult ResultSave = SaveDialog.ShowDialog(); if (ResultSave.ToString() == "OK") { ExportPath = SaveDialog.FileName; } else { return; } bool Invert = (bool)CheckInvert.IsChecked; bool Normalize = (bool)CheckNormalize.IsChecked; bool Preflip = (bool)CheckPreflip.IsChecked; bool Relative = (bool)CheckRelative.IsChecked; bool Filter = (bool)CheckFilter.IsChecked; bool Manual = (bool)CheckManual.IsChecked; int BoxSize = (int)Options.Tasks.Export2DBoxSize; int NormDiameter = (int)Options.Tasks.Export2DParticleDiameter; bool DoVolumes = (bool)RadioVolume.IsChecked; if (!DoVolumes) { Options.Tasks.TomoSubReconstructPrerotated = true; } bool MakeSparse = (bool)CheckSparse.IsChecked; float3 AdditionalShiftAngstrom = (bool)CheckShiftParticles.IsChecked ? new float3((float)SliderShiftParticlesX.Value, (float)SliderShiftParticlesY.Value, (float)SliderShiftParticlesZ.Value) : new float3(0); ProgressWrite.Visibility = Visibility.Visible; ProgressWrite.IsIndeterminate = true; PanelButtons.Visibility = Visibility.Collapsed; PanelRemaining.Visibility = Visibility.Visible; foreach (var element in DisableWhileProcessing) { element.IsEnabled = false; } await Task.Run(() => { #region Get all movies that can potentially be used List <TiltSeries> ValidSeries = Series.Where(v => { if (!Filter && v.UnselectFilter && v.UnselectManual == null) { return(false); } if (!Manual && v.UnselectManual != null && (bool)v.UnselectManual) { return(false); } if (v.OptionsCTF == null) { return(false); } return(true); }).ToList(); List <string> ValidMovieNames = ValidSeries.Select(m => m.RootName).ToList(); #endregion #region Read table and intersect its micrograph set with valid movies Star TableIn; if (Options.Tasks.InputOnePerItem) { List <Star> Tables = new List <Star>(); foreach (var item in Series) { string StarPath = InputFolder + item.RootName + InputSuffix; if (File.Exists(StarPath)) { Star TableItem = new Star(StarPath); if (!TableItem.HasColumn("rlnMicrographName")) { TableItem.AddColumn("rlnMicrographName", item.Name); } else { TableItem.SetColumn("rlnMicrographName", Helper.ArrayOfConstant(item.Name, TableItem.RowCount)); } Tables.Add(TableItem); } } TableIn = new Star(Tables.ToArray()); } else { TableIn = new Star(ImportPath); } if (!TableIn.HasColumn("rlnMicrographName")) { throw new Exception("Couldn't find rlnMicrographName column."); } if (!TableIn.HasColumn("rlnCoordinateX")) { throw new Exception("Couldn't find rlnCoordinateX column."); } if (!TableIn.HasColumn("rlnCoordinateY")) { throw new Exception("Couldn't find rlnCoordinateY column."); } if (!TableIn.HasColumn("rlnCoordinateZ")) { throw new Exception("Couldn't find rlnCoordinateZ column."); } Dictionary <string, List <int> > Groups = new Dictionary <string, List <int> >(); { string[] ColumnMicNames = TableIn.GetColumn("rlnMicrographName"); for (int r = 0; r < ColumnMicNames.Length; r++) { if (!Groups.ContainsKey(ColumnMicNames[r])) { Groups.Add(ColumnMicNames[r], new List <int>()); } Groups[ColumnMicNames[r]].Add(r); } Groups = Groups.ToDictionary(group => Helper.PathToName(group.Key), group => group.Value); Groups = Groups.Where(group => ValidMovieNames.Any(n => group.Key.Contains(n))).ToDictionary(group => group.Key, group => group.Value); } bool[] RowsIncluded = new bool[TableIn.RowCount]; foreach (var group in Groups) { foreach (var r in group.Value) { RowsIncluded[r] = true; } } List <int> RowsNotIncluded = new List <int>(); for (int r = 0; r < RowsIncluded.Length; r++) { if (!RowsIncluded[r]) { RowsNotIncluded.Add(r); } } ValidSeries = ValidSeries.Where(v => Groups.Any(n => n.Key.Contains(v.RootName))).ToList(); if (ValidSeries.Count == 0) // Exit if there is nothing to export, otherwise errors will be thrown below { return; } #endregion #region Make sure all columns are there if (!TableIn.HasColumn("rlnMagnification")) { TableIn.AddColumn("rlnMagnification", "10000.0"); } else { TableIn.SetColumn("rlnMagnification", Helper.ArrayOfConstant("10000.0", TableIn.RowCount)); } if (!TableIn.HasColumn("rlnDetectorPixelSize")) { TableIn.AddColumn("rlnDetectorPixelSize", Options.Tasks.TomoSubReconstructPixel.ToString("F5", CultureInfo.InvariantCulture)); } else { TableIn.SetColumn("rlnDetectorPixelSize", Helper.ArrayOfConstant(Options.Tasks.TomoSubReconstructPixel.ToString("F5", CultureInfo.InvariantCulture), TableIn.RowCount)); } if (!TableIn.HasColumn("rlnCtfMaxResolution")) { TableIn.AddColumn("rlnCtfMaxResolution", "999.0"); } if (!TableIn.HasColumn("rlnImageName")) { TableIn.AddColumn("rlnImageName", "None"); } if (!TableIn.HasColumn("rlnCtfImage")) { TableIn.AddColumn("rlnCtfImage", "None"); } List <Star> SeriesTablesOut = new List <Star>(); #endregion if (IsCanceled) { return; } #region Create worker processes int NDevices = GPU.GetDeviceCount(); List <int> UsedDevices = Options.MainWindow.GetDeviceList(); List <int> UsedDeviceProcesses = Helper.Combine(Helper.ArrayOfFunction(i => UsedDevices.Select(d => d + i *NDevices).ToArray(), MainWindow.GlobalOptions.ProcessesPerDevice)).ToList(); WorkerWrapper[] Workers = new WorkerWrapper[GPU.GetDeviceCount() * MainWindow.GlobalOptions.ProcessesPerDevice]; foreach (var gpuID in UsedDeviceProcesses) { Workers[gpuID] = new WorkerWrapper(gpuID); Workers[gpuID].SetHeaderlessParams(new int2(Options.Import.HeaderlessWidth, Options.Import.HeaderlessHeight), Options.Import.HeaderlessOffset, Options.Import.HeaderlessType); Workers[gpuID].LoadGainRef(Options.Import.CorrectGain ? Options.Import.GainPath : "", Options.Import.GainFlipX, Options.Import.GainFlipY, Options.Import.GainTranspose, Options.Import.CorrectDefects ? Options.Import.DefectsPath : ""); } #endregion Star TableOut = null; { Dictionary <string, Star> MicrographTables = new Dictionary <string, Star>(); #region Get coordinates and angles float[] PosX = TableIn.GetColumn("rlnCoordinateX").Select(v => float.Parse(v, CultureInfo.InvariantCulture)).ToArray(); float[] PosY = TableIn.GetColumn("rlnCoordinateY").Select(v => float.Parse(v, CultureInfo.InvariantCulture)).ToArray(); float[] PosZ = TableIn.GetColumn("rlnCoordinateZ").Select(v => float.Parse(v, CultureInfo.InvariantCulture)).ToArray(); float[] ShiftX = TableIn.HasColumn("rlnOriginX") ? TableIn.GetColumn("rlnOriginX").Select(v => float.Parse(v, CultureInfo.InvariantCulture)).ToArray() : new float[TableIn.RowCount]; float[] ShiftY = TableIn.HasColumn("rlnOriginY") ? TableIn.GetColumn("rlnOriginY").Select(v => float.Parse(v, CultureInfo.InvariantCulture)).ToArray() : new float[TableIn.RowCount]; float[] ShiftZ = TableIn.HasColumn("rlnOriginZ") ? TableIn.GetColumn("rlnOriginZ").Select(v => float.Parse(v, CultureInfo.InvariantCulture)).ToArray() : new float[TableIn.RowCount]; if (Options.Tasks.TomoSubReconstructNormalizedCoords) { for (int r = 0; r < TableIn.RowCount; r++) { PosX[r] *= (float)Options.Tomo.DimensionsX * (float)Options.PixelSizeMean; PosY[r] *= (float)Options.Tomo.DimensionsY * (float)Options.PixelSizeMean; PosZ[r] *= (float)Options.Tomo.DimensionsZ * (float)Options.PixelSizeMean; } } else { for (int r = 0; r < TableIn.RowCount; r++) { PosX[r] = (PosX[r] - ShiftX[r]) * (float)Options.Tasks.InputPixelSize; PosY[r] = (PosY[r] - ShiftY[r]) * (float)Options.Tasks.InputPixelSize; PosZ[r] = (PosZ[r] - ShiftZ[r]) * (float)Options.Tasks.InputPixelSize; } } float[] AngleRot = TableIn.HasColumn("rlnAngleRot") && Options.Tasks.TomoSubReconstructPrerotated ? TableIn.GetColumn("rlnAngleRot").Select(v => float.Parse(v, CultureInfo.InvariantCulture)).ToArray() : new float[TableIn.RowCount]; float[] AngleTilt = TableIn.HasColumn("rlnAngleTilt") && Options.Tasks.TomoSubReconstructPrerotated ? TableIn.GetColumn("rlnAngleTilt").Select(v => float.Parse(v, CultureInfo.InvariantCulture)).ToArray() : new float[TableIn.RowCount]; float[] AnglePsi = TableIn.HasColumn("rlnAnglePsi") && Options.Tasks.TomoSubReconstructPrerotated ? TableIn.GetColumn("rlnAnglePsi").Select(v => float.Parse(v, CultureInfo.InvariantCulture)).ToArray() : new float[TableIn.RowCount]; if (TableIn.HasColumn("rlnOriginX")) { TableIn.RemoveColumn("rlnOriginX"); } if (TableIn.HasColumn("rlnOriginY")) { TableIn.RemoveColumn("rlnOriginY"); } if (TableIn.HasColumn("rlnOriginZ")) { TableIn.RemoveColumn("rlnOriginZ"); } if (AdditionalShiftAngstrom.Length() > 0) { for (int r = 0; r < TableIn.RowCount; r++) { Matrix3 R = Matrix3.Euler(AngleRot[r] * Helper.ToRad, AngleTilt[r] * Helper.ToRad, AnglePsi[r] * Helper.ToRad); float3 RotatedShift = R *AdditionalShiftAngstrom; PosX[r] += RotatedShift.X; PosY[r] += RotatedShift.Y; PosZ[r] += RotatedShift.Z; } } if (Options.Tasks.TomoSubReconstructPrerotated) { if (TableIn.HasColumn("rlnAngleRot")) { TableIn.RemoveColumn("rlnAngleRot"); TableIn.AddColumn("rlnAngleRot", "0"); } if (TableIn.HasColumn("rlnAngleTilt")) { TableIn.RemoveColumn("rlnAngleTilt"); TableIn.AddColumn("rlnAngleTilt", "0"); } if (TableIn.HasColumn("rlnAnglePsi")) { TableIn.RemoveColumn("rlnAnglePsi"); TableIn.AddColumn("rlnAnglePsi", "0"); } } #endregion Dispatcher.Invoke(() => ProgressWrite.MaxValue = ValidSeries.Count); //Dispatcher.Invoke(() => //{ // ProgressWrite.IsIndeterminate = true; // TextRemaining.Text = "?:??"; //}); Helper.ForEachGPU(ValidSeries, (series, gpuID) => { if (IsCanceled) { return; } Stopwatch ItemTime = new Stopwatch(); ItemTime.Start(); ProcessingOptionsTomoSubReconstruction ExportOptions = Options.GetProcessingTomoSubReconstruction(); #region Update row values List <int> GroupRows = Groups.First(n => n.Key.Contains(series.RootName)).Value; int pi = 0; foreach (var r in GroupRows) { TableIn.SetRowValue(r, "rlnCtfMaxResolution", series.CTFResolutionEstimate.ToString("F1", CultureInfo.InvariantCulture)); TableIn.SetRowValue(r, "rlnCoordinateX", (PosX[r] / (float)ExportOptions.BinnedPixelSizeMean).ToString("F3", CultureInfo.InvariantCulture)); TableIn.SetRowValue(r, "rlnCoordinateY", (PosY[r] / (float)ExportOptions.BinnedPixelSizeMean).ToString("F3", CultureInfo.InvariantCulture)); TableIn.SetRowValue(r, "rlnCoordinateZ", (PosZ[r] / (float)ExportOptions.BinnedPixelSizeMean).ToString("F3", CultureInfo.InvariantCulture)); #region Figure out relative or absolute path to sub-tomo and its CTF string PathSubtomo = series.SubtomoDir + $"{series.RootName}{ExportOptions.Suffix}_{pi:D7}_{ExportOptions.BinnedPixelSizeMean:F2}A.mrc"; string PathCTF = //MakeSparse ? //(series.SubtomoDir + $"{series.RootName}_{pi:D7}_ctf_{ExportOptions.BinnedPixelSizeMean:F2}A.tif") : (series.SubtomoDir + $"{series.RootName}{ExportOptions.Suffix}_{pi:D7}_ctf_{ExportOptions.BinnedPixelSizeMean:F2}A.mrc"); if (Relative) { Uri UriStar = new Uri(ExportPath); PathSubtomo = UriStar.MakeRelativeUri(new Uri(PathSubtomo)).ToString(); PathCTF = UriStar.MakeRelativeUri(new Uri(PathCTF)).ToString(); } #endregion TableIn.SetRowValue(r, "rlnImageName", PathSubtomo); TableIn.SetRowValue(r, "rlnCtfImage", PathCTF); pi++; } #endregion #region Populate micrograph table with rows for all exported particles Star MicrographTable = new Star(TableIn.GetColumnNames()); foreach (var r in GroupRows) { MicrographTable.AddRow(TableIn.GetRow(r).ToList()); } #endregion #region Finally, reconstruct the actual sub-tomos float3[] TomoPositions = Helper.Combine(GroupRows.Select(r => Helper.ArrayOfConstant(new float3(PosX[r], PosY[r], PosZ[r]), series.NTilts)).ToArray()); float3[] TomoAngles = Helper.Combine(GroupRows.Select(r => Helper.ArrayOfConstant(new float3(AngleRot[r], AngleTilt[r], AnglePsi[r]), series.NTilts)).ToArray()); if (DoVolumes) { Workers[gpuID].TomoExportParticles(series.Path, ExportOptions, TomoPositions, TomoAngles); //series.ReconstructSubtomos(ExportOptions, TomoPositions, TomoAngles); lock (MicrographTables) MicrographTables.Add(series.RootName, MicrographTable); } else { Star SeriesTable; Random Rand = new Random(123); int[] Subsets = Helper.ArrayOfFunction(i => Rand.Next(1, 3), GroupRows.Count); series.ReconstructParticleSeries(ExportOptions, TomoPositions, TomoAngles, Subsets, ExportPath, out SeriesTable); lock (MicrographTables) MicrographTables.Add(series.RootName, SeriesTable); } #endregion #region Add this micrograph's table to global collection, update remaining time estimate lock (MicrographTables) { Timings.Add(ItemTime.ElapsedMilliseconds / (float)UsedDeviceProcesses.Count); int MsRemaining = (int)(MathHelper.Mean(Timings) * (ValidSeries.Count - MicrographTables.Count)); TimeSpan SpanRemaining = new TimeSpan(0, 0, 0, 0, MsRemaining); Dispatcher.Invoke(() => TextRemaining.Text = SpanRemaining.ToString((int)SpanRemaining.TotalHours > 0 ? @"hh\:mm\:ss" : @"mm\:ss")); Dispatcher.Invoke(() => { ProgressWrite.IsIndeterminate = false; ProgressWrite.Value = MicrographTables.Count; }); } #endregion }, 1, UsedDeviceProcesses); if (MicrographTables.Count > 0) { TableOut = new Star(MicrographTables.Values.ToArray()); } } Thread.Sleep(10000); // Writing out particles is async, so if workers are killed immediately they may not write out everything foreach (var worker in Workers) { worker?.Dispose(); } if (IsCanceled) { return; } TableOut.Save(ExportPath); }); Close?.Invoke(); }