ブログ

割とコンピュータよりの情報をお届けします。

Year 2021

Math.NET Numericsに機能が増えている

最近使っていないうちに Math.NET Numericsの機能が増えている.数値最小化問題を解けるようになっている.

MathNet.Numerics.Optimizationには数値最小化問題を解ける機能が備わっている.

最小化問題だが,符号を変えれば最大化問題も最小化問題になる.また,目的関数最小化(最適化)問題と呼ぶこともある.例えば以下のように使用できる.
最近の.NETには
var f1 = new Func<double, double>(x => sample(x));
というFuncという汎用のデリゲートがあるのが面白い.

using MathNet.Numerics.Optimization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            // 一次元探索
            var f1 = new Func<double, double>(x => sample(x));
            var obj = ObjectiveFunction.ScalarValue(f1);
            var r1 = GoldenSectionMinimizer.Minimum(obj, -100, 100, 1e-8, 1000, 10, 4, 4);

            Console.WriteLine($"{r1.FunctionInfoAtMinimum.Point:G16}");
            Console.WriteLine($"{r1.FunctionInfoAtMinimum.Value:G16}");

            // 多次元探索
            var f2 = new Func<MathNet.Numerics.LinearAlgebra.Vector<double>, double>(x => sample2(x));
            var obj2 = ObjectiveFunction.Value(f2);
            var init = MathNet.Numerics.LinearAlgebra.Vector<double>.Build;
            

            var r2 = NelderMeadSimplex.Minimum(obj2, init.Dense(new double[] { 0.0, 0.0 }));
            Console.WriteLine($"{r2.FunctionInfoAtMinimum.Point[0]:G16},{r2.FunctionInfoAtMinimum.Point[1]:G16}");
            Console.WriteLine($"{r2.FunctionInfoAtMinimum.Value:G16}");
        }

        static double sample(double x)
        {
            return (x - 3000) * (x - 3000);
        }

        static double sample2(MathNet.Numerics.LinearAlgebra.Vector<double> x)
        {
            return (x[0] - 1000) * (x[0] - 1000) + (x[1] - 3000) * (x[1] - 3000);
        }
    }
}

≫ 続きを読む

2021/05/09 コンピュータ   TakeMe

netDxfの使用例

netDxfを使ってみた.
なんということはないプログラム.

netDxfでdxfファイルを開いて円だけを抜き出し,半径でソートして,中心のX座標でソートして,中心のY座標でソートして順に表示するアプリを作ってみた.

using netDxf;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DxfProc
{
    class Program
    {
        static void Main(string[] args)
        {
            bool fileMode = false;
            string fileName = "";
            for (int i = 0; i < args.Length; i++) // もしコマンドライン引数で渡されたらファイルとして処理
            {
                {
                    fileMode = true;
                    fileName = args[i];
                }
            }
            DxfDocument dxf = null;

            if (fileMode)
            {
                dxf = DxfDocument.Load(fileName);
            }
            else
            {
                Int32 length = Int32.Parse(Console.ReadLine()); // get file size
                MemoryMappedFile shared_mem = MemoryMappedFile.OpenExisting("shared_mem", MemoryMappedFileRights.Read);
                Stream stream = shared_mem.CreateViewStream(0, length, MemoryMappedFileAccess.Read);
                dxf = DxfDocument.Load(stream);
            }
            var circles = dxf.Circles;

            var a = circles.OrderBy(p => p.Center.Y).OrderBy(p => p.Center.X).OrderBy(p => p.Radius);

            Console.WriteLine("Diameter,Center X, Center Y");
            foreach (var circle in a)
            {
                Console.WriteLine($"{circle.Radius*2:0.00000},{circle.Center.X:0.00000},{circle.Center.Y:0.00000}");
            }
        }
    }
}

ちなみに共有メモリを開くようにしている理由は?netDxfのライセンスの関係で本体アプリは別に作っていたから.例えばこんな感じ.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            string fileName = "Untitled.dxf";

            Process proc = new Process();
            ProcessStartInfo processStartInfo = new ProcessStartInfo()
            {
                FileName = "DxfProc.exe",
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                UseShellExecute = false,
            };

            FileInfo fileInfo = new FileInfo(fileName);
            var length = fileInfo.Length; // ファイルサイズ

            MemoryMappedFile share_mem = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, "shared_mem", length, MemoryMappedFileAccess.Read);

            proc.StartInfo = processStartInfo;
            proc.Start();

            proc.StandardInput.WriteLine(length);

            Console.Write(proc.StandardOutput.ReadToEnd());
            proc.WaitForExit();
            

            
        }
    }
}

最新のnetDxfはライセンスが変更になったのでこれがnugetに上がってくる頃にはこの対応は不要になると思う.最新訂正ではDxfDocumentの直下にCirclesはなくなりEntitiesの下に配置されるようになっている.若干の修正がある.

≫ 続きを読む

2021/04/19 コンピュータ   TakeMe

Openclipartが復帰していた

無償のクリップアートの提供サイトであるOpenclipartが復活していた.以前に停止していると書いたのは2019年だった.

知らないうちに,Openclipartが復活していた.

停止前にできていた簡単な編集を加えてからダウンロードするような機能はなくなっていて,2017年ころの状態に戻ったような感じである.ただ,ダウンロード機能は使える.
Openclipart APIなんていうのがあるけどどんな機能なのか?
アプリにクリップアート検索機能を追加するときに便利なような機能を提供しているのかな

≫ 続きを読む

2021/04/19 コンピュータ   TakeMe

Dokan.NET Bindingはまだまだ健在だった話

DokanはWindowsでデバイスドライバを作らなくても独自のファイルシステムを提供することができるソフト。そのDokanのユーザモードの部分を.NETで実装しやすくするのがDokan.NET Binding。Dokanの開発はずっと前に終わったと思っていた。その継続としてフォークされたDokanXも更新が止まっていた。

どうもDokanyがまだ健在である。そして,Dokan.NETもこのDokanyを使うように改修が続いている。

だいぶん前の「Dokan .netでファイルシステムを作って遊ぶ - Simple HashtableFS -(しょんぼり技術メモまいにちがしょんぼり)」というページの内容は古いがかなりその構成を維持したまま移行できるみたい(まったく同じとはいかない)。

// LinkedFS.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.Design.Serialization;
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;
using DokanNet;
using Linked;

namespace Linked
{
    public class LinkedFS : IDokanOperations
    {
        LinkedRecord root;

        #region Constructor
        /// <summary>
        /// コンストラクタ
        /// </summary>
        /// <param name="root">対象</param>
        public LinkedFS(ref LinkedRecord root)
        {
            this.root = root;
        }
        #endregion

        #region IDokanOperations
        public void Cleanup(string fileName, IDokanFileInfo info)
        {
        }

        public void CloseFile(string fileName, IDokanFileInfo info)
        {
        }

        public NtStatus CreateFile(string fileName, DokanNet.FileAccess access, FileShare share, FileMode mode, FileOptions options, FileAttributes attributes, IDokanFileInfo info)
        {
            if (fileName == "\\") // root 
            {
                info.IsDirectory = true;
                return DokanResult.Success;
            }
            else
            {
                switch (mode)
                {
                    case FileMode.Open:
                        {
                            string fileName2 = fileName.TrimStart('\\');
                            return RecursiveSearch(root, fileName2, ref info);
                        }
                    case FileMode.CreateNew:
                        {
                            string fileName2 = fileName.TrimStart('\\');
                            var fileInfo = new FileInformation(); // dummy fileInfo
                            LinkedRecord result = RecursiveSearchItem(root, fileName2, ref fileInfo, ref info);
                            if (result == null)
                            {
                                string[] data = fileName2.Split('\\');
                                string fileName3 = "";
                                for (int i = 0; i < data.Length - 1; i++)
                                {
                                    fileName3 += data[i];
                                    if (i < data.Length - 2)
                                    {
                                        fileName3 += "\\";
                                    }
                                }
                                string fileName4 = data[data.Length - 1];
                                result = RecursiveSearchItem(root, fileName3, ref fileInfo, ref info);
                                if (fileName3 == string.Empty)
                                    result = root;

                                if (result == null)
                                {
                                    return DokanResult.Error;
                                }
                                else
                                {
                                    var item = new LinkedRecord();
                                    item.IsDirectory = info.IsDirectory ? true : false;
                                    if (!item.IsDirectory)
                                        item.Contents = new List<byte>();

                                    item.Name = fileName4;
                                    result.LinkedItems.Add(item);
                                }
                                return DokanResult.Success;
                            }
                            else
                            {
                                return DokanResult.AlreadyExists;
                            }
                        }
                    default:
                        {
                            string fileName2 = fileName.TrimStart('\\');
                            return RecursiveSearch(root, fileName2, ref info);
                        }
                }
            }

            // return DokanResult.FileNotFound;
        }

        public NtStatus DeleteDirectory(string fileName, IDokanFileInfo info)
        {
            return DokanResult.NotImplemented;
        }

        public NtStatus DeleteFile(string fileName, IDokanFileInfo info)
        {
            return DokanResult.NotImplemented;
        }

        public NtStatus FindFiles(string fileName, out IList<FileInformation> files, IDokanFileInfo info)
        {
            files = new List<FileInformation>();

            if (fileName == "\\")
            {
                foreach (var item in root.LinkedItems)
                {
                    var finfo = new FileInformation
                    {
                        FileName = item.Name,
                        Attributes = item.IsDirectory ? FileAttributes.Directory : FileAttributes.Normal,
                        LastAccessTime = DateTime.Now,
                        LastWriteTime = null,
                        CreationTime = null,
                        Length = item.IsDirectory ? 0 : item.Contents.Count,
                    };
                    files.Add(finfo);
                }
                return DokanResult.Success;
            }
            else
            {
                string fileName2 = fileName.TrimStart('\\');
                var fileInfo = new FileInformation(); // dummy fileInfo
                LinkedRecord itemRoot = RecursiveSearchItem(root, fileName2, ref fileInfo, ref info);

                if (itemRoot == null)
                    return DokanResult.Error;

                foreach (var item in itemRoot.LinkedItems)
                {
                    var finfo = new FileInformation
                    {
                        FileName = item.Name,
                        Attributes = item.IsDirectory ? FileAttributes.Directory : FileAttributes.Normal,
                        LastAccessTime = DateTime.Now,
                        LastWriteTime = DateTime.Now,
                        CreationTime = null,
                        Length = item.IsDirectory ? 0 : item.Contents.Count,
                    };
                    files.Add(finfo);
                }

                return DokanResult.Success;
            }
        }

        public NtStatus GetFileInformation(
            string fileName,
            out FileInformation fileInfo,
            IDokanFileInfo info)
        {
            fileInfo = new FileInformation { FileName = fileName };

            if (fileName == "\\")
            {
                fileInfo.Attributes = FileAttributes.Directory;
                fileInfo.LastAccessTime = DateTime.Now;
                fileInfo.LastWriteTime = null;
                fileInfo.CreationTime = null;

                return DokanResult.Success;
            }

            string fileName2 = fileName.TrimStart('\\');
            LinkedRecord item = RecursiveSearchItem(root, fileName2, ref fileInfo, ref info);
            
            if (item == null)
                return DokanResult.Error;

            fileInfo.Attributes = item.IsDirectory ? FileAttributes.Directory : FileAttributes.Normal;
            fileInfo.LastAccessTime = DateTime.Now;
            fileInfo.LastWriteTime = DateTime.Now;
            fileInfo.CreationTime = DateTime.Now;
            fileInfo.FileName = item.Name;
            if (item.Contents != null)
                fileInfo.Length = item.Contents.Count;

            return DokanResult.Success;
        }

        public NtStatus ReadFile(
            string fileName,
            byte[] buffer,
            out int readBytes,
            long offset,
            IDokanFileInfo info)
        {
            readBytes = 0;

            string fileName2 = fileName.TrimStart('\\');
            var fileInfo = new FileInformation(); // dummy fileInfo
            LinkedRecord item = RecursiveSearchItem(root, fileName2, ref fileInfo, ref info);
            if (item == null)
                return DokanResult.FileNotFound;

            if (item.IsDirectory)
            {
                return DokanResult.NotADirectory;
            }

            {
                try
                {
                    // バイナリ列
                    byte[] raw = item.Contents.ToArray();
                    if (raw == null)
                    {
                        return DokanResult.Success;
                    }

                    // 超過チェック
                    if (offset >= raw.Length)
                    {
                        return DokanResult.Error;
                    }

                    // offsetから読み込むバイト数
                    long read_try_byte = (raw.Length - offset < buffer.Length) ? raw.Length - offset : buffer.Length;

                    // コピー
                    int i = 0;
                    for (i = 0; i < read_try_byte; i++)
                    {
                        buffer[i] = raw[offset + i];
                    }

                    readBytes = (int)i;

                    return DokanResult.Success;
                }
                catch (Exception)
                {
                    return DokanResult.Error;
                }
            }

        }

        public NtStatus SetEndOfFile(string fileName, long length, IDokanFileInfo info)
        {
            return DokanResult.Error;
        }

        public NtStatus SetAllocationSize(string fileName, long length, IDokanFileInfo info)
        {
            return DokanResult.Success;
        }

        public NtStatus SetFileAttributes(
            string filename,
            FileAttributes attr,
            IDokanFileInfo info)
        {
            return DokanResult.Error;
        }

        public NtStatus SetFileTime(
            string filename,
            DateTime? ctime,
            DateTime? atime,
            DateTime? mtime,
            IDokanFileInfo info)
        {
            return DokanResult.Error;
        }

        public NtStatus UnlockFile(string filename, long offset, long length, IDokanFileInfo info)
        {
            return DokanResult.Success;
        }

        public NtStatus Mounted(IDokanFileInfo info)
        {
            return DokanResult.Success;
        }

        public NtStatus LockFile(
            string filename,
            long offset,
            long length,
            IDokanFileInfo info)
        {
            return DokanResult.Success;
        }

        public NtStatus MoveFile(
            string fileName,
            string newName,
            bool replace,
            IDokanFileInfo info)
        {
            var lid_s = fileName.LastIndexOf('\\');
            var lid_d = newName.LastIndexOf('\\');
            if (fileName.Substring(0, lid_s) == newName.Substring(0, lid_d))
            {
                string fileName2 = fileName.TrimStart('\\');
                var fileInfo = new FileInformation(); // dummy fileInfo
                LinkedRecord item = RecursiveSearchItem(root, fileName2, ref fileInfo, ref info);
                if (item == null)
                    return DokanResult.FileNotFound;

                string newFileName2 = newName.TrimStart('\\');
                var newFileInfo = new FileInformation(); // dummy fileInfo
                LinkedRecord itemNew = RecursiveSearchItem(root, newFileName2, ref newFileInfo, ref info);
                if (itemNew != null)
                    return DokanResult.AlreadyExists;

                string[] data = newName.Split('\\');
                item.Name = data[data.Length - 1];
                return DokanResult.Success;
            }
            else
            {
                // 移動元
                string fileName2 = fileName.TrimStart('\\');
                var fileInfo = new FileInformation(); // dummy fileInfo
                LinkedRecord item = RecursiveSearchItem(root, fileName2, ref fileInfo, ref info);
                if (item == null)
                    return DokanResult.FileNotFound;
                // 移動元の親
                string fileName2Parent = fileName.Substring(0, lid_s).TrimStart('\\');
                var fileInfoParent = new FileInformation(); // dummy fileInfo
                LinkedRecord itemP = RecursiveSearchItem(root, fileName2Parent, ref fileInfoParent, ref info);
                if (itemP == null)
                {
                    if (fileName2Parent == string.Empty)
                    {
                        itemP = root;
                    }
                    else
                        return DokanResult.FileNotFound;
                }

                // 移動先
                string newFileName2 = newName.TrimStart('\\');
                var newFileInfo = new FileInformation(); // dummy fileInfo
                LinkedRecord itemNew = RecursiveSearchItem(root, newFileName2, ref newFileInfo, ref info);
                if (itemNew != null)
                    return DokanResult.AlreadyExists;

                // 移動先の親
                string newFileName2Parent = newName.Substring(0, lid_d).TrimStart('\\');
                var newFileInfoParent = new FileInformation(); // dummy fileInfo
                LinkedRecord itemNewP = RecursiveSearchItem(root, newFileName2Parent, ref newFileInfoParent, ref info);
                if (itemNewP == null)
                {
                    if (newFileName2Parent == string.Empty)
                    {
                        itemNewP = root;
                    }
                    else
                        return DokanResult.FileNotFound;
                }

                string[] data = newName.Split('\\');
                item.Name = data[data.Length - 1];
                itemNewP.LinkedItems.Add(item);
                itemP.LinkedItems.Remove(item);

                return DokanResult.Success;
            }
        }

        public NtStatus Unmounted(IDokanFileInfo info)
        {
            return DokanResult.Success;
        }

        public NtStatus GetDiskFreeSpace(
            out long freeBytesAvailable,
            out long totalBytes,
            out long totalFreeBytes,
            IDokanFileInfo info)
        {
            long currentSet = GC.GetTotalMemory(true);
            freeBytesAvailable = 1024 * 100 - currentSet;// 1024 * 10;// 512;
            totalBytes = 1024 * 100;
            totalFreeBytes = 1024 * 100 - currentSet;
            return DokanResult.Success;
        }

        public NtStatus WriteFile(
            string fileName,
            byte[] buffer,
            out int writtenBytes,
            long offset,
            IDokanFileInfo info)
        {
            writtenBytes = 0;

            var append = offset == -1;

            string fileName2 = fileName.TrimStart('\\');
            var fileInfo = new FileInformation(); // dummy fileInfo
            LinkedRecord item = RecursiveSearchItem(root, fileName2, ref fileInfo, ref info);
            if (item == null)
                return DokanResult.FileNotFound;

            if (info.Context == null)
            {
                if (!append)
                {
                    item.Contents.Clear();
                    item.Contents.AddRange(buffer);
                    writtenBytes = buffer.Length;
                }
            }
            else
            {
                return DokanResult.Error;
            }
            return DokanResult.Success;
        }

        public NtStatus GetVolumeInformation(out string volumeLabel, out FileSystemFeatures features,
            out string fileSystemName, out uint maximumComponentLength, IDokanFileInfo info)
        {
            volumeLabel = "LinkedFS";
            features = FileSystemFeatures.None;
            fileSystemName = "MASTER_DB";
            maximumComponentLength = 256;
            return DokanResult.Success;
        }

        public NtStatus GetFileSecurity(string fileName, out FileSystemSecurity security, AccessControlSections sections,
            IDokanFileInfo info)
        {
            security = null;
            return DokanResult.Error;
        }

        public NtStatus SetFileSecurity(string fileName, FileSystemSecurity security, AccessControlSections sections,
            IDokanFileInfo info)
        {
            return DokanResult.Error;
        }

        public NtStatus EnumerateNamedStreams(string fileName, IntPtr enumContext, out string streamName,
            out long streamSize, IDokanFileInfo info)
        {
            streamName = string.Empty;
            streamSize = 0;
            return DokanResult.NotImplemented;
        }

        public NtStatus FlushFileBuffers(
            string filename,
            IDokanFileInfo info)
        {
            return DokanResult.Success;
            //return DokanResult.Error;
        }

        public NtStatus FindStreams(string fileName, out IList<FileInformation> streams, IDokanFileInfo info)
        {
            streams = new FileInformation[0];
            return DokanResult.NotImplemented;
        }

        public NtStatus FindFilesWithPattern(string fileName, string searchPattern, out IList<FileInformation> files,
            IDokanFileInfo info)
        {
            files = new FileInformation[0];
            return DokanResult.NotImplemented;
        }
        #endregion

        private NtStatus RecursiveSearch(LinkedRecord root, string fileName, ref IDokanFileInfo info)
        {
            string[] data = fileName.Split('\\');
            for (Int32 i = 0; i < root.LinkedItems.Count; i++)
            {
                if (root.LinkedItems[i].Name == data[0])
                {
                    if (root.LinkedItems[i].IsDirectory == true)
                    {
                        var id = fileName.IndexOf('\\');
                        if (id < 0)
                        {
                            return DokanResult.Success;
                        }
                        else
                        {
                            string fileName_ = fileName.Substring(id).TrimStart('\\');
                            if (fileName_ == String.Empty)
                            {
                                return DokanResult.Success;
                            }
                            else
                            {
                                return RecursiveSearch(root.LinkedItems[i], fileName_, ref info);
                            }
                        }
                    }
                    else // ファイルである
                    {
                        if (data.Length > 1) // 要求がディレクトリである
                        {
                            return DokanResult.NotADirectory;
                        }
                        else
                        {
                            return DokanResult.Success;
                        }
                    }
                }
            }
            return DokanResult.FileNotFound;
        }

        private LinkedRecord RecursiveSearchItem(LinkedRecord root, string fileName, ref FileInformation fileInfo, ref IDokanFileInfo info)
        {
            string[] data = fileName.Split('\\');
            for (Int32 i = 0; i < root.LinkedItems.Count; i++)
            {
                if (root.LinkedItems[i].Name == data[0])
                {
                    if (root.LinkedItems[i].IsDirectory == true)
                    {
                        var id = fileName.IndexOf('\\');
                        if (id < 0)
                        {
                            return root.LinkedItems[i];
                        }
                        else
                        {
                            string fileName_ = fileName.Substring(id).TrimStart('\\');
                            if (fileName_ == String.Empty)
                            {
                                return root.LinkedItems[i];
                            }
                            else
                            {
                                return RecursiveSearchItem(root.LinkedItems[i], fileName_, ref fileInfo, ref info);
                            }
                        }
                    }
                    else // ファイルである
                    {
                        if (data.Length > 1) // 要求がディレクトリである
                        {
                            return null;
                        }
                        else
                        {
                            fileInfo.Attributes = FileAttributes.Normal;
                            fileInfo.CreationTime = System.DateTime.Now;
                            fileInfo.LastAccessTime = System.DateTime.Now;
                            fileInfo.LastWriteTime = System.DateTime.Now;
                            fileInfo.FileName = root.LinkedItems[i].Name;

                            // 長さ
                            //byte[] raw = root.LinkedItems[i].Contents.ToArray();
                            fileInfo.Length = root.LinkedItems[i].Contents.Count;// raw.Length;

                            return root.LinkedItems[i];
                        }
                    }
                }
            }
            return null;
        }


        
    }
}
// LinkedRecord.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;

namespace Linked
{
    public class LinkedRecord
    {
        private String name = "\\";
        public String Name {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        public Boolean IsDirectory { get; set; } = true;

        public List<LinkedRecord> LinkedItems { get; set; } = new List<LinkedRecord>();

        public List<Byte> Contents { get; set; } = null;//new List<byte>();
    }
}
 
//Program.cs
using DokanNet;
using DokanNet.Logging;
using Linked;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LinkedB
{
    class Program
    {
        static void Main(string[] args)
        {
            LinkedRecord root = new LinkedRecord();
            LinkedFS linkedFS = new LinkedFS(ref root);

            var dir = new LinkedRecord();
            dir.Name = "明治";
            dir.IsDirectory = true;
            root.LinkedItems.Add(dir);

            var file = new LinkedRecord();
            file.Name = "大正.txt";
            file.IsDirectory = false;
            file.Contents = Encoding.UTF8.GetBytes("昭和平成").ToList<Byte>();
            dir.LinkedItems.Add(file);

            linkedFS.Mount("X" + ":\\", /*DokanOptions.DebugMode | */DokanOptions.RemovableDrive, new NullLogger());
        }
    }
}

≫ 続きを読む

2021/04/11 コンピュータ   TakeMe

.NET Frameworkとネイティブdllが混ざったときの不具合追及

.NETでDllImportを使っていると例外が発生しないで突然「××は動作を停止しました。」と出てしまうことがある。最近この場面に遭遇した。

「××は動作を停止しました。」と出たときにWindowsコントロールの「信頼性の履歴の表示」に,APPCRASHというイベント名で記録が残る。
これは便利なのだが,例外の種類が0xc0000374になっていて発生頻度が割と低い場合には非常にデバッグが難しい。
これはヒープ破損らしい。
そもそも,.NET Framework 4.0からAccessViolationExceptionを検知できなくなっているらしい。そのため,例外をキャッチしてクラッシュログを残そうなどということができない。app.configに<legacyCorruptedStateExceptionsPolicy enabled="true"/>を追加することでこれは回避できる。
しかし,それだけでは見逃す。0xc0000374はヒープ破壊を起こした時に起きるというより,壊れているのを検知したときに起きる(実害が発生しそうなタイミングで起きる)ので問題のあるコードはもっと前に実行されていることがある。

そこで,Windows SDKに含まれるDebugging Tools for WindowsgflagsでPage Heapを有効にして置きexe.configの<runtime>要素内に<legacyCorruptedStateExceptionsPolicy enabled="true"/>を追加して,ヒープ破壊っぽいことが起きたらAccessViolationExceptionが上がるようにして例外をキャッチしてクラッシュログを残す。(といいらしい)

Page Heapは非常に重いが,例外発生の確実性が大幅に増す。

≫ 続きを読む

2021/04/09 コンピュータ   TakeMe

Python numpyでFFTを実行する.周波数軸はどうしたら4

前の記事ではnumpy.fft.fftfreqをプロットの時の範囲指定に使うことしか考えていなかったが,フィルタなどもできる.

numpy.fft.fftfreqによって生成した周波数軸とnumpy.whereを使うと周波数でフィルタリングが行える.
例えば,
Fzf = np.fft.fft(z);
Fz2f = np.where(np.abs(freq2) > 12, 0, Fzf)
などとすれば,周波数成分を取り除くことができる(0で埋めることができる).
np.fft.ifftで時間領域の信号に戻せば0で埋めた成分は消えている.

import numpy as np
import matplotlib.pyplot as plt

# 例の信号を作成
t = np.linspace(0.001, 4, 1000);
z = 0.1 + 0.2 * np.sin(t * 10 * 2 * np.pi) + 0.2 * np.sin(t * 33 * 2 * np.pi);

# サンプリング周波数
fsmp = 1 / (t[1] - t[0]);
# 解析時間
t_len = t.max() - t.min();

Fzf = np.fft.fft(z); # Fzfはfftした結果
Fz = Fzf / z.shape[0] * 2; # 折り返すのでパワーが2分の1になっている.
Fz[0] = Fz[0] / 2; # 平均成分は折り返さない.
Fz_abs = np.abs(Fz);


freq2 = np.fft.fftfreq(len(t), d=1.0/fsmp);# 周波数軸の生成

# abs(freq2)が12以上の成分をカット
Fz2f = np.where(np.abs(freq2) > 12, 0, Fzf) # filter
z_filtered = np.fft.ifft(Fz2f);
Fz2 = Fz2f / z.shape[0] * 2;
Fz2[0] = Fz2[0] / 2;
Fz2_abs = np.abs(Fz2);


plt.figure(1)
# 比較FFTプロット
plt.subplot(211);
plotrange = np.where(freq2 >= 0)
plt.plot(freq2[plotrange], Fz_abs[plotrange]);
plt.plot(freq2[plotrange], Fz2_abs[plotrange]);

# 比較波形プロット
plt.subplot(212);
plt.plot(t, z);
plt.plot(t, z_filtered);

plt.savefig("valuestar.work.177.png")

plt.show();


≫ 続きを読む

2021/04/03 コンピュータ   TakeMe
Tag:Python

「場所が利用できません」ダイアログ

買ったばかりの外付けSSDで昨日の朝「場所が利用できません」ダイアログが出るようになってしまった.

買ったばかりのUSB接続の外付けSSDを使い始めて3日目の出来事だった.
ダイアログの中身は「D:\にアクセスできません。 ファイルまたはディレクトリが壊れているため、読み取ることができません。」で,エクスプローラにドライブのアイコンは見えていて,ドライブ文字も割り当てられている.
スタートメニューの「Windows 管理ツール」の「コンピュータの管理」「ディスクの管理」で対象のドライブがNTFSでなくRAWになっていることを確認した.

「エラー チェック」もできない(D:のプロパティの「ツール」タブから)。この時点では,「エラーチェック」できない場合には「CHKDSK」も使えないと勝手に思っていた。
焦っていると何も考えられない。「NTFS」が「RAW」になっているから「NTFS」と認識させるだけでよいだろうと,「TestDisk」を使用してみていたが,うまくいかない.どうも理由は違ったらしい。

CHKDSK /F D:

で不具合は一応消えた。(怖いのでいったんリカバリツールでバックアップを取ってから)まだ使い始めたばかりの記憶装置だったから被害の範囲を覚えていたが,ある程度使った状態で起こると怖いな.

今回の教訓は「D:\にアクセスできません。 ファイルまたはディレクトリが壊れているため、読み取ることができません。」というダイアログの表示の場合には「TestDisk」で修正できる内容ではない可能性が高い.

≫ 続きを読む

2021/04/01 コンピュータ   TakeMe

Python numpyでFFTを実行する.周波数軸はどうしたら3

以前の記事「Python numpyでFFTを実行する.周波数軸はどうしたら」「Python numpyでFFTを実行する.周波数軸はどうしたら」ではlinspaceを使って周波数リストを出力していたのをnumpy.fft.fftfreqでもよいと書いていたが,,,

numpy.fft.fftfreqで作る次のようなコードではfreq2は途中でいきなり負に飛ぶことになり,plt.plot(freq2, Fz_abs);とするとプロットが汚くなる.xlimで範囲制限をしても枠外の点とつながった線が気になる.

import numpy as np
import matplotlib.pyplot as plt

# 例の信号を作成
t = np.linspace(0.001, 4, 1000);
z = 0.1 + 0.2 * np.sin(t * 10 * 2 * np.pi) + 0.2 * np.sin(t * 33 * 2 * np.pi);

# サンプリング周波数
fsmp = 1 / (t[1] - t[0]);
# 解析時間
t_len = t.max() - t.min();

Fz = np.fft.fft(z) / z.shape[0] * 2; # 折り返すのでパワーが2分の1になっている.
Fz[0] = Fz[0] / 2; # 平均成分は折り返さない.
Fz_abs = np.abs(Fz);

freq = np.linspace(0, fsmp - 1.0/(t_len + t[1] - t[0]), num=len(t));
freq2 = np.fft.fftfreq(len(t), d=1.0/fsmp);

plt.figure(1)
plt.plot(freq, Fz_abs);

plt.figure(2)
plt.plot(freq2, Fz_abs);
plt.xlim([0, 125])


plt.show();

たとえば,np.where(freq2 >= 0, freq2, np.nan)で選別してもよい.要素がNaNになっているとプロットに失敗するので描画されない(plt.figure(3)に示した).
もしくは,np.where(freq2 >=0)でインデックス列の状態にしておいてそれでプロット範囲を周波数で制限することも可能でplt.figure(4)に示した.

import numpy as np
import matplotlib.pyplot as plt

# 例の信号を作成
t = np.linspace(0.001, 4, 1000);
z = 0.1 + 0.2 * np.sin(t * 10 * 2 * np.pi) + 0.2 * np.sin(t * 33 * 2 * np.pi);

# サンプリング周波数
fsmp = 1 / (t[1] - t[0]);
# 解析時間
t_len = t.max() - t.min();

Fz = np.fft.fft(z) / z.shape[0] * 2; # 折り返すのでパワーが2分の1になっている.
Fz[0] = Fz[0] / 2; # 平均成分は折り返さない.
Fz_abs = np.abs(Fz);

freq = np.linspace(0, fsmp - 1.0/(t_len + t[1] - t[0]), num=len(t));
freq2 = np.fft.fftfreq(len(t), d=1.0/fsmp);

plt.figure(1)
plt.plot(freq, Fz_abs);

plt.figure(2)
plt.plot(freq2, Fz_abs);
plt.xlim([0, 125])

freq3 = np.where(freq2 >= 0, freq2, np.nan)
plt.figure(3)
plt.plot(freq3, Fz_abs);

plt.figure(4)
plotrange = np.where(freq2 >= 0)
plt.plot(freq2[plotrange], Fz_abs[plotrange]);

plt.show();

≫ 続きを読む

2021/03/30 コンピュータ   TakeMe
Tag:Python

Windows 10 2004以降のコルタナさんの仕様変更?

Windows 10 のアップデートをインストールしたら「コルタナさん」という呼びかけでコルタナさんがアクティブ化できなくなった.

最近サブに使っているパソコンにWindows 10の20H2が降ってきた.順次アップデートの配信がされているらしい.特に古いバージョンを使っている場合にはアップデートを勧めてくるみたい.
Windows 10 20H2のアップデートをインストールしたら「コルタナさん」という呼びかけでコルタナさんがアクティブ化できなくなっていることに気が付いた.

メインも2004になっていてすでに呼びかけでアクティブ化できなくなっていたようだ.そういえば,しばらく呼びかけていなかった.

しばらくこの仕様のままになるようだ.ただコルタナの設定では「今後のアップデートに追加されます。」と表示されるので
アップデートを期待しています.

≫ 続きを読む

2021/03/27 日記   TakeMe

WebView2ランタイムで音声読み上げ Vol. 2

WebView2なら音声読み上げを入れることができる.SAPIの代わりに使いたい場合には動的にJavaScriptを実行するようにならないといけないな。と思って修正.

SAPIの代わりに使う場合には,WebView2.CoreWebView2.ExecuteScriptAsyncを使えばよい.
例えとして下にサンプルを示す.
ただし,この例では毎回var synthes = new SpeechSynthesisUtterance()とやっているので注意して.オーバーヘッドが大きい.
もともとWindows 10の場合にはすでにSAPIがあるので読み上げ機能を使うだけでやるのは意味はない.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            string path = Directory.GetCurrentDirectory();

            path = path + @"\\index.html";

            this.webView21.Source = new Uri(path);
        }

        private async void button1_Click(object sender, EventArgs e)
        {
            string text =
                "var synthes = new SpeechSynthesisUtterance('こんにちは');" +
                "speechSynthesis.speak(synthes);";
            await this.webView21.CoreWebView2.ExecuteScriptAsync(text);
        }
    }
}


WebView2.CoreWebView2.ExecuteScriptAsyncがつかえるのはページを読み終わって表示し終わってからだと思う.その前に実行すると例外が発生すると思う.

SAPIだけでやる場合には以下のように行うのです.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            SpeechLib.SpVoice sp = new SpeechLib.SpVoice();
            sp.Speak("アレクサ。今なんじ");
        }
    }
}

≫ 続きを読む

2021/03/27 コンピュータ   TakeMe