ブログ

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

TakeMe

Ubuntuのtarコマンドは除外の扱いが変わったのか?

古い記事を参考にtarコマンドを使用していたら除外がうまくいかないなど不都合に遭遇した。

古い記事を参考にTarコマンドの引数を扱ってはいけない。

えらい目にあった。
何ら新しいことはないだろうと思っていたtarコマンドでさえ仕様変更が起こっている。思ったように除外が効かなかった。
おおむねの作業の流れは非常にありがたい。


dir /home/takeme/backup
cd /
tar cvpzf "/home/takeme/backup/backup.tar.gz" --exclude="/proc" --exclude=/lost+found --exclude=/mnt --exclude=/sys --exclude=/home/takeme/backup /

今回は思ったところに除外が効いた。(ように見える)

≫ Read More

2023/06/07 コンピュータ   TakeMe

PyScriptはすぐに使えるのか?

CMSと組み合わせてもPyScriptはすぐに使えるのか非常に疑問だった。
一応バージョン番号付けが1未満になっている意図は察しつつ…。

デモのhello worldを張り付けてみたら以下のようになる。最初はpyscriptのライブラリを見込む必要がある。結構ロードするファイルサイズがでかいことが分かったので公開を中止した。
改めてspimle clockの方をインラインフレームで作り直した。

意図通りにはならない。

HTMLではコード中の改行を気にしない仕組みだからでないかと思われる。それ用に作られているCMSのエディタでは改行を気にしない。Pythonは改行とインデントを気にする。(違うのかな)
少し検討が必要かもしれないが、サンプルではMatplotlibの使用例を含んでおり、データをお客に見せるときにこれでよいのであれば使えるかもしれない。
念のため確認だが、依然としてChrome系統のブラウザで動作確認をして活発に更新されているのでわずかな変化で動作に問題が生じる可能性がある。
デモページの3d表示のサンプルも直前まで動いていたような気がしたが、今日は動いていない

≫ Read More

2023/06/06 コンピュータ   TakeMe
Tag:Python

Bodhi LinuxでAvalonia UIアプリの使用

最近 .NET 7.0 GUIアプリケーションがWindowsで開発できるようになってきている。割と便利だ。

GUIアプリケーションの作成にxamlを使用していると、最初は大変だったが慣れてくると割と便利だ。.NET Framework 4.5程度のときはMVVMの対応に割と時間がかかってイベントハンドラを記述するなんてやっていたが、最近はMVVMの対応が楽になった。
そして.NET MAUIやAvalonia UIやUno Platformはそれをマルチプラットフォームに拡張する。
例えば、Avaloinia UIのアプリケーションをUbuntu 20.04で実行してみた。

wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt update
sudo apt install aspcorenet-runtime-7.0
LC_ALL=C dotnet AvaloniaApplication1.Desktop.dll

LC_ALL=Cが大事みたい。

ただ、.NET Framework 4.x世代の安定した互換性に比べて.NET 5.0 .NET 6.0 .NET 7.0の機能の追加・廃止の速さは少し怖い
(.NET Framework 4.xもWindows 7 の最後における.NET Framework 4.8のシステム破壊(WPFアプリがクラッシュする問題)はあったが)

≫ Read More

2023/06/05 コンピュータ   TakeMe

Mondo Rescue をUbuntu 20.04でインストール

Mondo Rescue をUbuntu 20.04でインストールしてみた。しかし、依然としてefiには非対応である。どうしても使いたい場合には、バグを自分で修正する必要がある。

Ubuntu 20.04でMondo Rescueをインストールしてみることにした。
まずは、
sudo vim /etc/apt/sources.list.d/mondorescue.sources.list
内容は以下の2行。

deb http://www.mondorescue.org/ftp/ubuntu 20.04 contrib
deb-src http://www.mondorescue.org/ftp/ubuntu 20.04 contrib

この状態で、

sudo apt update 

を実行するとkey is not available: NO_PUBKEY 6BA8C2D220EBFB0Eなどの表示がでるので、

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 6BA8C2D220EBFB0E
sudo apt update
sudo apt install mondo
sudo apt install isolinux
sudo apt install xorriso

ここまで。さらに、
sudo vim /etc/mindi/mindi.conf
として

EXTRA_SPACE=1024000
BOOT_SIZE=307200

Ubuntuのgenisoimage はefi booting のディスク作成機能を持たないために、UEFI環境でbootディスクの作成には失敗する。らしい。

どうもこの続きがあってUFEI環境では
sudo apt install syslinux-efi
とxorrisoを自分でビルドするが示されている?

ディストリビューションによってはできるらしい。

インストールしてさらに
/usr/sbin/mindi
をテキストエディタ(vimなど)で開き ../libutil.c32を探す。
その行のcp $LDLINUXE64/../libutil.c32を
cp /usr/lib/syslinux/modules/efi64/libutil.c32
と変更してしまう。

                                # cp $LDLINUXE64/../libutil.c32 $efidir 2>> $LOGFILE || Die "Cannot copy $LDLINUXE64 to $efidir). Did you run out of disk space?"
                                cp /usr/lib/syslinux/modules/efi64/libutil.c32 $efidir 2>> $LOGFILE || Die "Cannot copy $LDLINUXE64 to $efidir). Did you run out of disk space?"

今のところインストールはできるがバックアップに成功するにはmindi.confでEXTRA_SPACEを結構大きく設定する必要がある。
上の例はConoha VPSでUbuntu 20.04をバックアップしたときのものである。UEFIでは今のところ無理(2023.06.11追記)

UEFIではバックアップまではできるが、リストアに成功していない。

≫ Read More

2023/06/03 コンピュータ   TakeMe

Windows 11 「アカウント>家族」が曲者

ローカルアカウントからMicrosoftアカウントに切り替えたいなーと思ったときにOffice 365 Familyなどを使っている場合には、注意があるようだ。

ローカルアカウントからMicrosoftアカウントに切り替えたいなーと思ったときにOffice 365 Familyなどを使っている場合には、ファミリーメンバーのアカウントが待機状態になっている。いつでも「設定」から有効にできるアカウントである。

この状態でも、(ファミリーメンバーに含まれているMicrosoftアカウントに含まれていれば)「このデバイスの他のユーザーがこのMicrosoftアカウントを使用しているため、ここに追加することはできません」と表示されて自分のアカウントもMicrosoftアカウントに切り替えることができなくなるのだ。
おそらく多くの人は自分で登録した覚えがないので、「???」となる。
 lusrmgr.mscを実行してデバイスに登録されている「ユーザー」を一覧表示させてみると初めて待機状態になっているアカウントがあることがわかる。長すぎるアカウント名は一部省略名が使われる。アイコンに下向き矢印が表示されている場合には、待機状態になっていて、「設定」>「アカウント」>「家族」から「サインインを許可する」ボタンをクリックすると有効になる。

十分に注意が必要だ。しかも、日本では発売が遅かったため日本語の情報が不足している。
「このデバイスの他のユーザーがこのMicrosoftアカウントを使用しているため、ここに追加することはできません」と表示されたら、 lusrmgr.mscで いったん待機アカウントを削除してやると、ローカルアカウントをマイクロソフトアカウントに変更できるようになる。英語のMicrosoftサポートコミュニティには2019年時点でこのような情報が入っている。

≫ Read More

2023/05/28 コンピュータ   TakeMe

C#でclassのフィールドなどをインデックスで扱う方法

C#でクラスメンバを扱うとき[index]のように扱えると便利だが,Marshalの関係でメンバ数を固定にしないといけない場合がある.その場合にもインデックスで変数を扱う方法を確認.

System.Reflection.dllを使用する.
例えばフィールドならFieldInfoクラスを使う.

下の例では,
(FieldInfo)typeof(SampleA).GetField("item" + (i + 1))
で取得できるFieldInfoを使ってGetValueを使う.

代入の時には,SetValueを使用することができる(プロパティならGetProperty / SetProperty).

GetField()で取得できるのはpublic属性が付いているものに限る.privateになっているフィールドを取ろうとすると例外が発生する.実行時でないとわからないのでわかりにくいバグを発生する.ただし,「public / private」に関係なくプロパティを取得することは仕様としてはできる.デバッガーはこの仕組みを利用してデバッグを行うことができる.
一人でプログラムしている場合には気にならないが,複数人でプログラムしている場合には,ほかの人の部品の公開意図のないものを扱ってしまうのは,ややリスクがある.
この方法でだけ変数を使用していた場合,Visual Studio などでは変数の使用を検知できないのでCS0414が発生する,

using System;
using System.Reflection;

namespace Sample1
{
    class Program
    {
        static void Main(string[] args)
        {
            SampleA sampleA = new SampleA()
            {
                item1 = 1,
                item2 = 2,
                item3 = 3,
            };

            SampleA sampleA2 = new SampleA()
            {
                item1 = 11,
                item2 = 12,
                item3 = 13,
            };

            
            for (int i = 0; i < 3; i++)
            {
                Int32 item = (Int32)((FieldInfo)typeof(SampleA).GetField("item" + (i + 1))).GetValue(sampleA);
                Console.WriteLine($"{item}");
            }

            for (int i = 0; i < 3; i++)
            {
                Int32 item = (Int32)((FieldInfo)typeof(SampleA).GetField("item" + (i + 1))).GetValue(sampleA2);
                Console.WriteLine($"{item}");
            }
        }
    }

    public class SampleA
    {
        public Int32 item1;
        public Int32 item2;
        public Int32 item3;
    }
}

Tupleもこんな感じに扱える.(もちろん,Tupleはフィールド名を明示的に指定できるので状況によっては少し使い方が変わるかもしれないが)

            Tuple<double, double, double> tuple = new Tuple<double, double, double>(0, 1, 2);

            for (int i = 0; i < 3; i++)
            {
                double item = (double)((PropertyInfo)typeof(Tuple<double, double, double>).GetProperty("Item" + (i + 1))).GetValue(tuple);
                Console.WriteLine($"{item}");
            }

さてGetField以外にGetFieldsなるものがある.これが,求める「インデックスで扱う」ためのメソッドである.

≫ Read More

2022/02/13 コンピュータ   TakeMe

PUDOステーションで番号入力

PUDOステーションの認証番号の入力は桁が多くて一字削除もやりにくい.
間違えると全部削除をしてしまう.
しかし,事前にQRコードなどが用意できれば簡単.

PUDOステーションはソフトや設定が更新できるみたい
近くのコンビニに導入されたとき直後は署名の表示の線が細くて読めなかったものがあった.

アマゾンなどで注文した場合には最初のころは受け取りバーコードをもらえていた気がするが
いまはバーコードはもらえないで認証番号を入力している.
桁が多くて難しい.

それが,QRコードなどのバーコードが入手できなくても認証番号を事前にQRコードなどに変換しておけばかざすだけで入力に代えてくれるようになっているらしい.
この方が入力が楽だ

≫ Read More

2021/10/02 日記   TakeMe

OxyPlotにHeatMapSeriesというのがある

OxyPlotにHeatMapSeriesというのがあるというのを知った.これまでは,Bitmapで自分で描いていた.

Bitmapで自分で描くより楽だ.例えばここのようなサンプルが良い.
下は参考ページのやり方・名前の取り方をほぼそのまま参照している.Windows Forms用に少し手直しが入っているのと,linearColorAxis1.Palette = OxyPalettes.Gray(10);を追加しているところくらいが異なる.(参考ではRainbowになっている?)
縦横に正弦波が0.5 秒おきに流れていく(感じ).

using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Series;
using OxyPlot.WindowsForms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HeatmapTest
{
    private OxyPlot.WindowsForms.PlotView plotView1;
        private PlotModel plotModelSpectrogram = new PlotModel();
        public HeatMapSeries heatMapSeries1 = new HeatMapSeries();
        private Double[,] Data = new Double[240, 250];
        private double t = 0;

        private System.Windows.Forms.Timer timer1;

        public Form1()
        {
            InitializeComponent();

            this.plotView1 = new OxyPlot.WindowsForms.PlotView();

            this.plotView1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.plotView1.Location = new System.Drawing.Point(0, 0);
            this.plotView1.Name = "plotView1";
            this.plotView1.PanCursor = System.Windows.Forms.Cursors.Hand;
            this.plotView1.Size = new System.Drawing.Size(633, 362);
            this.plotView1.TabIndex = 0;
            this.plotView1.Text = "plotView1";
            this.plotView1.ZoomHorizontalCursor = System.Windows.Forms.Cursors.SizeWE;
            this.plotView1.ZoomRectangleCursor = System.Windows.Forms.Cursors.SizeNWSE;
            this.plotView1.ZoomVerticalCursor = System.Windows.Forms.Cursors.SizeNS;

            this.Controls.Add(this.plotView1);

            plotModelSpectrogram.Title = "TEST";

            var linearColorAxis1 = new LinearColorAxis();
            linearColorAxis1.Palette = OxyPalettes.Gray(10);
            linearColorAxis1.Position = AxisPosition.Right;
            linearColorAxis1.Minimum = 0.0;
            linearColorAxis1.Maximum = 100;
            plotModelSpectrogram.Axes.Add(linearColorAxis1);


            var linearAxis1 = new LinearAxis();
            linearAxis1.Position = AxisPosition.Bottom;
            linearAxis1.IsAxisVisible = false;
            linearAxis1.IsZoomEnabled = false;
            plotModelSpectrogram.Axes.Add(linearAxis1);

            // Dummy
            var linearAxis_a = new LinearAxis();
            linearAxis_a.Position = AxisPosition.Bottom;
            linearAxis_a.Minimum = 0.0;
            linearAxis_a.Maximum = 120.0;
            linearAxis_a.Title = "Time s";
            linearAxis_a.IsZoomEnabled = false;
            plotModelSpectrogram.Axes.Add(linearAxis_a);

            var linearAxis2 = new LinearAxis();
            linearAxis2.Position = AxisPosition.Left;
            linearAxis2.IsAxisVisible = false;
            linearAxis2.IsZoomEnabled = false;
            plotModelSpectrogram.Axes.Add(linearAxis2);

            // Dummy
            var linearAxis_b = new LinearAxis();
            linearAxis_b.Position = AxisPosition.Left;
            linearAxis_b.Minimum = 0.0;
            linearAxis_b.Maximum = 1000.0;
            linearAxis_b.Title = "Frequency kHz";
            linearAxis_b.IsZoomEnabled = false;
            plotModelSpectrogram.Axes.Add(linearAxis_b);


            heatMapSeries1.Data = new double[240, 250];
            heatMapSeries1.X0 = 0.0;
            heatMapSeries1.X1 = 100.0;
            heatMapSeries1.Y0 = 0.0;
            heatMapSeries1.Y1 = 1000.0;

            plotModelSpectrogram.Series.Add(heatMapSeries1);
            this.plotView1.Model = plotModelSpectrogram;

            this.timer1 = new Timer();
            this.timer1.Interval = 500;
            this.timer1.Enabled = true;
            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            PlotSpectrogram();
        }

        private void AddLastData(Double[] data)
        {
            for (int i = 0; i < Data.GetLength(0) - 1; i++)
            {
                for (int j = 0; j < Data.GetLength(1); j++)
                {
                    Data[i, j] = Data[i + 1, j];
                }
            }
            for (int j = 0; j < Data.GetLength(1); j++)
            {
                Data[Data.GetLength(0) - 1, j] = data[j];
            }

            var pldata = new double[240, 250];
            Array.Copy(Data, pldata, Data.Length);
            heatMapSeries1.Data = pldata;
        }

        public void PlotSpectrogram()
        {
            Double[] data = new Double[Data.GetLength(1)];
            for (int i = 0; i < data.Length; i++)
            {
                data[i] = (50.0 + 20.0 * Math.Sin(0.2 * i) + 20.0 * Math.Sin(t));

            }
            t += 0.5;
            AddLastData(data);
            plotModelSpectrogram.InvalidatePlot(true);
        }
    }
}

≫ Read More

2021/06/07 コンピュータ   TakeMe

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);
        }
    }
}

≫ Read More

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の下に配置されるようになっている.若干の修正がある.

≫ Read More

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