public double[] ExtractProfile(int column, int profileIndex, TopographyProcessType type) { // some range checks if (column < 0) { return(InvalidProfile()); } if (column >= NumberOfColumns) { return(InvalidProfile()); } if (profileIndex < 0) { return(InvalidProfile()); } if (profileIndex > scanMetaData.NumberOfProfiles) { return(InvalidProfile()); // starts at 1 ! } if (profileIndex == 0) { return(ProcessTwoProfiles(AllProfiles(column, ScanDirection.Forward), AllProfiles(column, ScanDirection.Backward), type)); } return(ProcessTwoProfiles(SingleProfile(column, profileIndex, ScanDirection.Forward), SingleProfile(column, profileIndex, ScanDirection.Backward), type)); }
private static void WarpNmmProfiles(TopographyProcessType processType, List <IntensityProfile> tempList) { for (int profileIndex = 0; profileIndex < theData.MetaData.NumberOfProfiles; profileIndex++) { double[] xData = theData.ExtractProfile(options.XAxisDesignation, profileIndex + 1, processType); double[] zData = theData.ExtractProfile(options.ZAxisDesignation, profileIndex + 1, processType); // convert Xdata from meter to micrometer for (int i = 0; i < xData.Length; i++) { xData[i] = xData[i] * 1.0e6; } tempList.Add(new IntensityProfile(xData, zData)); } }
// overload in case the column index is known already public double[] ExtractProfile(int columnIndex, int profileIndex, TopographyProcessType type) { return(topographyData.ExtractProfile(columnIndex, profileIndex, type)); }
// this is the main method: returns the profile for a given symbol and index public double[] ExtractProfile(string columnSymbol, int profileIndex, TopographyProcessType type) { return(ExtractProfile(GetColumnIndexFor(columnSymbol), profileIndex, type)); }
public static void Main(string[] args) { Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); if (!CommandLine.Parser.Default.ParseArgumentsStrict(args, options)) { Console.WriteLine("*** ParseArgumentsStrict returned false"); } // consume the verbosity option if (options.BeQuiet == true) { ConsoleUI.BeSilent(); } else { ConsoleUI.BeVerbatim(); } // print a welcome message ConsoleUI.Welcome(); ConsoleUI.WriteLine(); // get the filename(s) fileNames = options.ListOfFileNames.ToArray(); if (fileNames.Length == 0) { ConsoleUI.ErrorExit("!Missing input file", 1); } // if no filetype was choosen, use default one if (!(options.convertBcr || options.convertPrDe || options.convertPrEn || options.convertPrf || options.convertSig || options.convertSmd || options.convertTxt || options.convertCsv || options.convertX3p)) { options.convertSig = true; // this should be convertBcr in the future } // read all relevant scan data ConsoleUI.StartOperation("Reading and evaluating files"); nmmFileNameObject = new NmmFileName(fileNames[0]); nmmFileNameObject.SetScanIndex(options.ScanIndex); theData = new NmmScanData(nmmFileNameObject); ConsoleUI.Done(); ConsoleUI.WriteLine(); if (options.DoHeydemann) { theData.ApplyHeydemannCorrection(); if (theData.HeydemannCorrectionApplied) { ConsoleUI.WriteLine($"Heydemann correction applied, span {theData.HeydemannCorrectionSpan * 1e9:F1} nm"); } else { ConsoleUI.WriteLine($"Heydemann correction not successful."); } ConsoleUI.WriteLine(); } // some checks of the provided CLA options if (options.ProfileIndex < 0) { options.ProfileIndex = 0; // automatically extract all profiles } if (options.ProfileIndex > theData.MetaData.NumberOfProfiles) { options.ProfileIndex = theData.MetaData.NumberOfProfiles; } topographyProcessType = TopographyProcessType.ForwardOnly; if (options.UseBack) { topographyProcessType = TopographyProcessType.BackwardOnly; } if (options.UseBoth) { topographyProcessType = TopographyProcessType.Average; } if (options.UseDiff) { topographyProcessType = TopographyProcessType.Difference; } if (theData.MetaData.ScanStatus == ScanDirectionStatus.ForwardOnly) { if (topographyProcessType != TopographyProcessType.ForwardOnly) { ConsoleUI.WriteLine("No backward scan data present, switching to forward only."); } topographyProcessType = TopographyProcessType.ForwardOnly; } if (theData.MetaData.ScanStatus == ScanDirectionStatus.Unknown) { ConsoleUI.ErrorExit("!Unknown scan type", 2); } if (theData.MetaData.ScanStatus == ScanDirectionStatus.NoData) { ConsoleUI.ErrorExit("!No scan data present", 3); } // now we can start to sort and format everything we need prf.CreationDate = theData.MetaData.CreationDate; prf.SampleIdentification = theData.MetaData.SampleIdentifier; prf.DeltaX = theData.MetaData.ScanFieldDeltaX * 1e6; prf.UserComment = options.UserComment; // extract the requested profile if (options.ProfileIndex != 0) { ProcessSingleProfile(options.ProfileIndex); return; } // (ProfileIndex == 0) => extract all profiles for (int i = 1; i <= theData.MetaData.NumberOfProfiles; i++) { ProcessSingleProfile(i); } }
static void Main(string[] args) { // parse command line arguments var options = new Options(); if (!CommandLine.Parser.Default.ParseArgumentsStrict(args, options)) { Console.WriteLine("*** ParseArgumentsStrict returned false"); } if (options.BeQuiet == true) { ConsoleUI.BeSilent(); } else { ConsoleUI.BeVerbatim(); } ConsoleUI.Welcome(); // get the filename(s) string[] fileNames = options.ListOfFileNames.ToArray(); if (fileNames.Length == 0) { ConsoleUI.ErrorExit("!Missing input file", 1); } // read all relevant scan data ConsoleUI.StartOperation("Reading and evaluating files"); NmmFileName nmmFileName = new NmmFileName(fileNames[0]); nmmFileName.SetScanIndex(options.ScanIndex); NmmScanData nmmScanData = new NmmScanData(nmmFileName); ConsoleUI.Done(); if (options.DoHeydemann) { nmmScanData.ApplyHeydemannCorrection(); if (nmmScanData.HeydemannCorrectionApplied) { ConsoleUI.WriteLine($"Heydemann correction applied, span {nmmScanData.HeydemannCorrectionSpan * 1e9:F1} nm"); } else { ConsoleUI.WriteLine($"Heydemann correction not successful."); } } // some checks of the provided CLA options if (options.ProfileIndex < 0) { options.ProfileIndex = 0; } if (options.ProfileIndex > nmmScanData.MetaData.NumberOfProfiles) { options.ProfileIndex = nmmScanData.MetaData.NumberOfProfiles; } TopographyProcessType topographyProcessType = TopographyProcessType.ForwardOnly; if (options.UseBack) { topographyProcessType = TopographyProcessType.BackwardOnly; } if (options.UseBoth) { topographyProcessType = TopographyProcessType.Average; } if (options.UseDiff) { topographyProcessType = TopographyProcessType.Difference; } if (nmmScanData.MetaData.ScanStatus == ScanDirectionStatus.ForwardOnly) { if (topographyProcessType != TopographyProcessType.ForwardOnly) { ConsoleUI.WriteLine("No backward scan data present, switching to forward only."); } topographyProcessType = TopographyProcessType.ForwardOnly; } if (nmmScanData.MetaData.ScanStatus == ScanDirectionStatus.Unknown) { ConsoleUI.ErrorExit("!Unknown scan type", 2); } if (nmmScanData.MetaData.ScanStatus == ScanDirectionStatus.NoData) { ConsoleUI.ErrorExit("!No scan data present", 3); } // now we can start to sort and format everything we need BcrWriter bcr = new BcrWriter(); bcr.Relaxed = !options.Strict; // overrules Relaxed ConsoleUI.WriteLine(bcr.Relaxed ? "Relaxed formatting" : "Strict formatting"); bcr.ForceIsoFormat = options.IsoFormat; ConsoleUI.WriteLine(bcr.ForceIsoFormat ? "ISO 25178-71 format" : "Legacy format"); // ISO 25178-71 file header bcr.CreationDate = nmmScanData.MetaData.CreationDate; bcr.ManufacurerId = nmmScanData.MetaData.InstrumentIdentifier; bcr.NumberOfPointsPerProfile = nmmScanData.MetaData.NumberOfDataPoints; if (options.ProfileIndex == 0) { bcr.NumberOfProfiles = nmmScanData.MetaData.NumberOfProfiles; bcr.YScale = nmmScanData.MetaData.ScanFieldDeltaY; ConsoleUI.WriteLine("Extract complete scanfield"); } else { bcr.NumberOfProfiles = 1; bcr.YScale = 0; ConsoleUI.WriteLine($"Extract single profile {options.ProfileIndex} only"); } bcr.XScale = nmmScanData.MetaData.ScanFieldDeltaX; bcr.ZScale = options.ZScale; // read actual topography data for given channel if (!nmmScanData.ColumnPresent(options.ChannelSymbol)) { ConsoleUI.ErrorExit($"!Channel {options.ChannelSymbol} not in scan data", 5); } double[] rawData = nmmScanData.ExtractProfile(options.ChannelSymbol, options.ProfileIndex, topographyProcessType); // level data DataLeveling levelObject; if (options.ProfileIndex == 0) { levelObject = new DataLeveling(rawData, nmmScanData.MetaData.NumberOfDataPoints, nmmScanData.MetaData.NumberOfProfiles); } else { levelObject = new DataLeveling(rawData, nmmScanData.MetaData.NumberOfDataPoints); } levelObject.BiasValue = options.Bias * 1.0e-6; // bias is given in µm on the command line double[] leveledTopographyData = levelObject.LevelData(MapOptionToReference(options.ReferenceMode)); // generate a dictionary with all relevant metadata for the ISO 25178-71 file trailer Dictionary <string, string> bcrMetaData = new Dictionary <string, string>(); bcrMetaData.Add("InputFile", nmmScanData.MetaData.BaseFileName); bcrMetaData.Add("ConvertedBy", $"{ConsoleUI.Title} version {ConsoleUI.Version}"); bcrMetaData.Add("UserComment", options.UserComment); bcrMetaData.Add("OperatorName", nmmScanData.MetaData.User); bcrMetaData.Add("Organisation", nmmScanData.MetaData.Organisation); bcrMetaData.Add("SampleIdentifier", nmmScanData.MetaData.SampleIdentifier); bcrMetaData.Add("SampleSpecies", nmmScanData.MetaData.SampleSpecies); bcrMetaData.Add("SampleSpecification", nmmScanData.MetaData.SampleSpecification); bcrMetaData.Add("SPMtechnique", nmmScanData.MetaData.SpmTechnique); bcrMetaData.Add("Probe", nmmScanData.MetaData.ProbeDesignation); bcrMetaData.Add("ZAxisSource", options.ChannelSymbol); bcrMetaData.Add("Trace", topographyProcessType.ToString()); if (options.ProfileIndex != 0) { bcrMetaData.Add("NumProfiles", $"{nmmScanData.MetaData.NumberOfProfiles}"); bcrMetaData.Add("ExtractedProfile", $"{options.ProfileIndex}"); } if (nmmScanData.MetaData.NumberOfScans > 1) { bcrMetaData.Add("NumberOfScans", $"{nmmScanData.MetaData.NumberOfScans}"); bcrMetaData.Add("Scan", $"{nmmScanData.MetaData.ScanIndex}"); } bcrMetaData.Add("ReferenceDatum", levelObject.LevelModeDescription); if (nmmScanData.HeydemannCorrectionApplied) { bcrMetaData.Add("HeydemannCorrection", $"Span {nmmScanData.HeydemannCorrectionSpan * 1e9:F1} nm"); } bcrMetaData.Add("EnvironmentMode", nmmScanData.MetaData.EnvironmentMode); bcrMetaData.Add("SampleTemperature", $"{nmmScanData.MetaData.SampleTemperature:F3} oC"); bcrMetaData.Add("AirTemperature", $"{nmmScanData.MetaData.AirTemperature:F3} oC"); bcrMetaData.Add("AirPressure", $"{nmmScanData.MetaData.BarometricPressure:F0} Pa"); bcrMetaData.Add("AirHumidity", $"{nmmScanData.MetaData.RelativeHumidity:F1} %"); bcrMetaData.Add("TemperatureGradient", $"{nmmScanData.MetaData.AirTemperatureGradient:F3} oC"); bcrMetaData.Add("TemperatureRange", $"{nmmScanData.MetaData.AirTemperatureDrift:F3} oC"); bcrMetaData.Add("ScanSpeed", $"{nmmScanData.MetaData.ScanSpeed * 1e6} um/s"); bcrMetaData.Add("AngularOrientation", $"{nmmScanData.MetaData.ScanFieldRotation:F3} grad"); bcrMetaData.Add("ScanFieldCenterX", $"{nmmScanData.MetaData.ScanFieldCenterZ * 1000:F3} mm"); bcrMetaData.Add("ScanFieldCenterY", $"{nmmScanData.MetaData.ScanFieldCenterY * 1000:F3} mm"); bcrMetaData.Add("ScanFieldCenterZ", $"{nmmScanData.MetaData.ScanFieldCenterZ * 1000:F3} mm"); bcrMetaData.Add("ScanFieldOriginX", $"{nmmScanData.MetaData.ScanFieldOriginX} m"); bcrMetaData.Add("ScanFieldOriginY", $"{nmmScanData.MetaData.ScanFieldOriginY} m"); bcrMetaData.Add("ScanFieldOriginZ", $"{nmmScanData.MetaData.ScanFieldOriginZ} m"); bcrMetaData.Add("ScanDuration", $"{nmmScanData.MetaData.ScanDuration.TotalSeconds:F0} s"); bcrMetaData.Add("GlitchedDataPoints", $"{nmmScanData.MetaData.NumberOfGlitchedDataPoints}"); bcrMetaData.Add("SpuriousDataLines", $"{nmmScanData.MetaData.SpuriousDataLines}"); for (int i = 0; i < nmmScanData.MetaData.ScanComments.Count; i++) { bcrMetaData.Add($"ScanComment{i + 1}", nmmScanData.MetaData.ScanComments[i]); } // ISO 25178-71 main section bcr.PrepareMainSection(leveledTopographyData); // ISO 25178-71 file trailer bcr.PrepareTrailerSection(bcrMetaData); // now generate output string outFileName; if (fileNames.Length >= 2) { outFileName = fileNames[1]; } else { outFileName = nmmFileName.GetFreeFileNameWithIndex("sdf"); } ConsoleUI.WritingFile(outFileName); if (!bcr.WriteToFile(outFileName)) { ConsoleUI.Abort(); ConsoleUI.ErrorExit("!could not write file", 4); } ConsoleUI.Done(); }
private double[] ProcessTwoProfiles(double[] fwdProfile, double[] bwdProfile, TopographyProcessType type) { if (fwdProfile.Length != bwdProfile.Length) { return(null); } double[] resultProfile = new double[fwdProfile.Length]; switch (type) { case TopographyProcessType.None: return(InvalidProfile()); case TopographyProcessType.ForwardOnly: return(fwdProfile); case TopographyProcessType.BackwardOnly: return(bwdProfile); case TopographyProcessType.Average: for (int i = 0; i < fwdProfile.Length; i++) { resultProfile[i] = (fwdProfile[i] + bwdProfile[i]) * 0.5; } break; case TopographyProcessType.Difference: for (int i = 0; i < fwdProfile.Length; i++) { resultProfile[i] = fwdProfile[i] - bwdProfile[i]; } break; } return(resultProfile); }