From 31c23a00a752b4503c54c441c7be148b78a1056f Mon Sep 17 00:00:00 2001 From: TingwenZhang Date: Sat, 17 May 2025 18:13:04 -0400 Subject: [PATCH 1/5] chore: shortened file names (#149) --- .../ZB.4-1.iq} | 0 .../ZB.4-10.iq} | 0 .../ZB.4-11.iq} | 0 .../ZB.4-12.iq} | 0 .../ZB.4-13.iq} | 0 .../ZB.4-14.iq} | 0 .../ZB.4-15.iq} | 0 .../ZB.4-16.iq} | 0 .../ZB.4-17.iq} | 0 .../ZB.4-18.iq} | 0 .../ZB.4-19.iq} | 0 .../ZB.4-2.iq} | 0 .../ZB.4-20.iq} | 0 .../ZB.4-3.iq} | 0 .../ZB.4-4.iq} | 0 .../ZB.4-5.iq} | 0 .../ZB.4-6.iq} | 0 .../ZB.4-7.iq} | 0 .../ZB.4-8.iq} | 0 .../ZB.4-9.iq} | 0 .../ZB.5-1.gr} | 0 .../ZB.5-10.gr} | 0 .../ZB.5-11.gr} | 0 .../ZB.5-12.gr} | 0 .../ZB.5-13.gr} | 0 .../ZB.5-14.gr} | 0 .../ZB.5-15.gr} | 0 .../ZB.5-16.gr} | 0 .../ZB.5-17.gr} | 0 .../ZB.5-18.gr} | 0 .../ZB.5-19.gr} | 0 .../ZB.5-2.gr} | 0 .../ZB.5-20.gr} | 0 .../ZB.5-3.gr} | 0 .../ZB.5-4.gr} | 0 .../ZB.5-5.gr} | 0 .../ZB.5-6.gr} | 0 .../ZB.5-7.gr} | 0 .../ZB.5-8.gr} | 0 .../ZB.5-9.gr} | 0 40 files changed, 0 insertions(+), 0 deletions(-) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-1.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-1.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-10.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-10.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-11.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-11.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-12.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-12.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-13.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-13.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-14.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-14.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-15.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-15.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-16.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-16.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-17.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-17.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-18.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-18.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-19.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-19.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-2.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-2.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-20.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-20.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-3.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-3.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-4.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-4.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-5.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-5.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-6.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-6.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-7.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-7.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-8.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-8.iq} (100%) rename examples/{mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-9.iq => mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-9.iq} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-1.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-1.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-10.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-10.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-11.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-11.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-12.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-12.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-13.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-13.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-14.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-14.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-15.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-15.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-16.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-16.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-17.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-17.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-18.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-18.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-19.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-19.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-2.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-2.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-20.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-20.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-3.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-3.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-4.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-4.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-5.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-5.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-6.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-6.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-7.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-7.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-8.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-8.gr} (100%) rename examples/{mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-9.gr => mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-9.gr} (100%) diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-1.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-1.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-1.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-1.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-10.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-10.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-10.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-10.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-11.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-11.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-11.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-11.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-12.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-12.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-12.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-12.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-13.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-13.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-13.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-13.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-14.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-14.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-14.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-14.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-15.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-15.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-15.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-15.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-16.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-16.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-16.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-16.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-17.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-17.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-17.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-17.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-18.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-18.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-18.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-18.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-19.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-19.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-19.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-19.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-2.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-2.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-2.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-2.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-20.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-20.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-20.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-20.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-3.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-3.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-3.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-3.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-4.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-4.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-4.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-4.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-5.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-5.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-5.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-5.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-6.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-6.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-6.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-6.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-7.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-7.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-7.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-7.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-8.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-8.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-8.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-8.iq diff --git a/examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-9.iq b/examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-9.iq similarity index 100% rename from examples/mix___ZnSe-w_0.4___BaTiO3_c-w_0.6/ZnSe-w_0.4___BaTiO3_c-w_0.6-9.iq rename to examples/mix-ZnSe-BaTiO3-0.4-0.6/ZB.4-9.iq diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-1.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-1.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-1.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-1.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-10.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-10.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-10.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-10.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-11.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-11.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-11.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-11.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-12.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-12.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-12.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-12.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-13.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-13.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-13.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-13.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-14.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-14.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-14.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-14.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-15.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-15.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-15.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-15.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-16.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-16.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-16.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-16.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-17.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-17.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-17.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-17.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-18.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-18.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-18.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-18.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-19.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-19.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-19.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-19.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-2.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-2.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-2.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-2.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-20.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-20.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-20.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-20.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-3.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-3.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-3.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-3.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-4.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-4.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-4.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-4.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-5.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-5.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-5.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-5.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-6.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-6.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-6.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-6.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-7.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-7.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-7.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-7.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-8.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-8.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-8.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-8.gr diff --git a/examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-9.gr b/examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-9.gr similarity index 100% rename from examples/mix___ZnSe-w_0.5___BaTiO3_c-w_0.5/ZnSe-w_0.5___BaTiO3_c-w_0.5-9.gr rename to examples/mix-ZnSe-BaTiO3-0.5-0.5/ZB.5-9.gr From 3af38ad0bd4d85dfbfbdfd0d67478609e9201be3 Mon Sep 17 00:00:00 2001 From: Simon Billinge Date: Wed, 18 Jun 2025 08:16:47 -0400 Subject: [PATCH 2/5] Migration into main (#154) * skpkg: setup CI after migrating tests, src, requirements, and .github folder (#151) * skpkg: migrate src folder * skpkg: migrate tests folder * skpkg: list dependencies in requirements folder * skpkg: add CI and issue/PR templates * skpkg: add pyproject.toml * skpkg: standardize files by removing examples and adding back necessary scripts * skpkg: modify copyright years and contributors in a missed file * style: changed line length to 115 and ran pre-commit again * fix: testing if adding .github/workflow will pass CI * [pre-commit.ci] auto fixes from pre-commit hooks --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * skpkg: add configuration files for pre-commit, readthedocs, codecov (#152) * skpkg: add config files for pre-commit * skpkg: add config files readthedocs, codecov, GitHub * style: remove stashed change indicators and modify code of conducts to pass pre-commit * skpkg: migrate documentation, README, and public static files (#153) * skpkg: migrate documentation * skpkg: add config files for authors, changelog, code of conduct, license * skpkg: add README.rst * skpkg: add news files * chore: add back necessary lines from the files * chore: fix files according to comments in the review --------- Co-authored-by: zmx27 <95781012+zmx27@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .codecov.yml | 8 +- .codespell/ignore_words.txt | 3 - .flake8 | 2 + .github/ISSUE_TEMPLATE/release_checklist.md | 31 +- .../pull_request_template.md | 15 + .../workflows/build-wheel-release-upload.yml | 6 +- .github/workflows/check-news-item.yml | 6 +- .../matrix-and-codecov-on-merge-to-main.yml | 4 +- .github/workflows/publish-docs-on-release.yml | 12 + .github/workflows/tests-on-pr.yml | 7 +- .gitignore | 8 +- .isort.cfg | 3 +- .pre-commit-config.yaml | 38 ++- .readthedocs.yaml | 13 + CHANGELOG.rst | 2 +- CODE_OF_CONDUCT.rst | 2 +- LICENSE.rst | 3 +- README.rst | 11 +- doc/source/conf.py | 43 ++- doc/source/index.rst | 24 +- doc/source/license.rst | 3 +- news/doc.rst | 23 ++ pyproject.toml | 6 +- requirements/build.txt | 0 requirements/docs.txt | 1 + src/diffpy/__init__.py | 3 +- src/diffpy/snmf/__init__.py | 7 +- src/diffpy/snmf/containers.py | 8 +- src/diffpy/snmf/factorizers.py | 3 +- src/diffpy/snmf/io.py | 5 +- src/diffpy/snmf/optimizers.py | 11 +- src/diffpy/snmf/polynomials.py | 6 +- src/diffpy/snmf/stretchednmfapp.py | 17 +- src/diffpy/snmf/subroutines.py | 50 ++- src/diffpy/snmf/version.py | 5 +- tests/test_containers.py | 130 +++++++- tests/test_optimizers.py | 47 ++- tests/test_subroutines.py | 309 ++++++++++++++++-- tests/test_version.py | 8 +- 39 files changed, 728 insertions(+), 155 deletions(-) create mode 100644 .github/PULL_REQUEST_TEMPLATE/pull_request_template.md create mode 100644 .github/workflows/publish-docs-on-release.yml create mode 100644 .readthedocs.yaml create mode 100644 news/doc.rst delete mode 100644 requirements/build.txt diff --git a/.codecov.yml b/.codecov.yml index 5a94096e..4af5eb24 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,14 +1,14 @@ coverage: status: - project: # more options at https://docs.codecov.com/docs/commit-status + project: # more options at https://docs.codecov.com/docs/commit-status default: target: auto # use the coverage from the base commit, fail if coverage is lower - threshold: 0% # allow the coverage to drop by + threshold: 0% # allow the coverage to drop by comment: layout: " diff, flags, files" behavior: default require_changes: false - require_base: false # [true :: must have a base report to post] - require_head: false # [true :: must have a head report to post] + require_base: false # [true :: must have a base report to post] + require_head: false # [true :: must have a head report to post] hide_project_coverage: false # [true :: only show coverage on the git diff aka patch coverage] diff --git a/.codespell/ignore_words.txt b/.codespell/ignore_words.txt index 9757d7c0..04b4fcfa 100644 --- a/.codespell/ignore_words.txt +++ b/.codespell/ignore_words.txt @@ -4,8 +4,5 @@ ;; abbreviation for "materials" often used in a journal title mater -;; alternative use of socioeconomic -socio-economic - ;; Frobenius norm used in np.linalg.norm fro diff --git a/.flake8 b/.flake8 index 2d2cb168..04d2d0b0 100644 --- a/.flake8 +++ b/.flake8 @@ -1,3 +1,5 @@ +# As of now, flake8 does not natively support configuration via pyproject.toml +# https://github.com/microsoft/vscode-flake8/issues/135 [flake8] exclude = .git, diff --git a/.github/ISSUE_TEMPLATE/release_checklist.md b/.github/ISSUE_TEMPLATE/release_checklist.md index 0f560278..6107962c 100644 --- a/.github/ISSUE_TEMPLATE/release_checklist.md +++ b/.github/ISSUE_TEMPLATE/release_checklist.md @@ -6,30 +6,41 @@ labels: "release" assignees: "" --- -### PyPI/GitHub release checklist: +### PyPI/GitHub rc-release preparation checklist: - [ ] All PRs/issues attached to the release are merged. - [ ] All the badges on the README are passing. - [ ] License information is verified as correct. If you are unsure, please comment below. - [ ] Locally rendered documentation contains all appropriate pages, including API references (check no modules are - missing), tutorials, and other human written text is up-to-date with any changes in the code. -- [ ] Installation instructions in the README, documentation and on the website (e.g., diffpy.org) are updated. + missing), tutorials, and other human-written text is up-to-date with any changes in the code. +- [ ] Installation instructions in the README, documentation, and the website are updated. - [ ] Successfully run any tutorial examples or do functional testing with the latest Python version. - [ ] Grammar and writing quality are checked (no typos). +- [ ] Install `pip install build twine`, run `python -m build` and `twine check dist/*` to ensure that the package can be built and is correctly formatted for PyPI release. -Please mention @sbillinge here when you are ready for PyPI/GitHub release. Include any additional comments necessary, such as -version information and details about the pre-release here: +Please tag the maintainer (e.g., @username) in the comment here when you are ready for the PyPI/GitHub release. Include any additional comments necessary, such as version information and details about the pre-release here: -### conda-forge release checklist: +### PyPI/GitHub full-release preparation checklist: - +- [ ] Create a new conda environment and install the rc from PyPI (`pip install ==??`) +- [ ] License information on PyPI is correct. +- [ ] Docs are deployed successfully to `https:///`. +- [ ] Successfully run all tests, tutorial examples or do functional testing. +Please let the maintainer know that all checks are done and the package is ready for full release. + +### conda-forge release preparation checklist: + + + +- [ ] Ensure that the full release has appeared on PyPI successfully. - [ ] New package dependencies listed in `conda.txt` and `test.txt` are added to `meta.yaml` in the feedstock. -- [ ] All relevant issues in the feedstock are addressed in the release PR. +- [ ] Close any open issues on the feedstock. Reach out to the maintainer if you have questions. +- [ ] Tag the maintainer for conda-forge release. ### Post-release checklist -- [ ] Run tutorial examples and conduct functional testing using the installation guide in the README. Attach screenshots/results as comments. -- [ ] Documentation (README, tutorials, API references, and websites) is deployed without broken links or missing figures. +- [ ] Run tutorial examples and conduct functional testing using the installation guide in the README. Attach screenshots/results as comments. +- [ ] Documentation (README, tutorials, API references, and websites) is deployed without broken links or missing figures. diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 00000000..1099d862 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,15 @@ +### What problem does this PR address? + + + +### What should the reviewer(s) do? + + + + diff --git a/.github/workflows/build-wheel-release-upload.yml b/.github/workflows/build-wheel-release-upload.yml index 0af554bc..110f95b6 100644 --- a/.github/workflows/build-wheel-release-upload.yml +++ b/.github/workflows/build-wheel-release-upload.yml @@ -4,13 +4,15 @@ on: workflow_dispatch: push: tags: - - '*' # Trigger on all tags initially, but tag and release privilege are verified in _build-wheel-release-upload.yml + - "*" # Trigger on all tags initially, but tag and release privilege are verified in _build-wheel-release-upload.yml jobs: release: - uses: Billingegroup/release-scripts/.github/workflows/_build-wheel-release-upload.yml@v0 + uses: scikit-package/release-scripts/.github/workflows/_build-wheel-release-upload.yml@v0 with: project: diffpy.snmf + c_extension: false + maintainer_GITHUB_username: sbillinge secrets: PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} PAT_TOKEN: ${{ secrets.PAT_TOKEN }} diff --git a/.github/workflows/check-news-item.yml b/.github/workflows/check-news-item.yml index 2f951515..1c7c14ff 100644 --- a/.github/workflows/check-news-item.yml +++ b/.github/workflows/check-news-item.yml @@ -3,10 +3,10 @@ name: Check for News on: pull_request_target: branches: - - main + - main jobs: - build: - uses: Billingegroup/release-scripts/.github/workflows/_check-news-item.yml@v0 + check-news-item: + uses: scikit-package/release-scripts/.github/workflows/_check-news-item.yml@v0 with: project: diffpy.snmf diff --git a/.github/workflows/matrix-and-codecov-on-merge-to-main.yml b/.github/workflows/matrix-and-codecov-on-merge-to-main.yml index 4f8649e8..5360214b 100644 --- a/.github/workflows/matrix-and-codecov-on-merge-to-main.yml +++ b/.github/workflows/matrix-and-codecov-on-merge-to-main.yml @@ -11,8 +11,8 @@ on: workflow_dispatch: jobs: - coverage: - uses: Billingegroup/release-scripts/.github/workflows/_matrix-and-codecov-on-merge-to-main.yml@v0 + matrix-coverage: + uses: scikit-package/release-scripts/.github/workflows/_matrix-and-codecov-on-merge-to-main.yml@v0 with: project: diffpy.snmf c_extension: false diff --git a/.github/workflows/publish-docs-on-release.yml b/.github/workflows/publish-docs-on-release.yml new file mode 100644 index 00000000..2f0efbc1 --- /dev/null +++ b/.github/workflows/publish-docs-on-release.yml @@ -0,0 +1,12 @@ +name: Deploy Documentation on Release + +on: + workflow_dispatch: + +jobs: + docs: + uses: scikit-package/release-scripts/.github/workflows/_publish-docs-on-release.yml@v0 + with: + project: diffpy.snmf + c_extension: false + headless: false diff --git a/.github/workflows/tests-on-pr.yml b/.github/workflows/tests-on-pr.yml index fabc1066..3c428bee 100644 --- a/.github/workflows/tests-on-pr.yml +++ b/.github/workflows/tests-on-pr.yml @@ -1,15 +1,12 @@ name: Tests on PR on: - push: - branches: - - main pull_request: workflow_dispatch: jobs: - validate: - uses: Billingegroup/release-scripts/.github/workflows/_tests-on-pr.yml@v0 + tests-on-pr: + uses: scikit-package/release-scripts/.github/workflows/_tests-on-pr.yml@v0 with: project: diffpy.snmf c_extension: false diff --git a/.gitignore b/.gitignore index a25212ea..099e2948 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ __pycache__/ .Python env/ build/ +_build/ develop-eggs/ dist/ downloads/ @@ -90,10 +91,3 @@ target/ # Ipython Notebook .ipynb_checkpoints - -# version information -setup.cfg -/src/diffpy/*/version.cfg - -# Rever -rever/ diff --git a/.isort.cfg b/.isort.cfg index e0926f42..86f162b8 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -1,4 +1,5 @@ [settings] -line_length = 115 +# Keep import statement below line_length character limit +line_length = 79 multi_line_output = 3 include_trailing_comma = True diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9cf0556f..0e4a84d1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,14 +1,14 @@ default_language_version: - python: python3 + python: python3 ci: - autofix_commit_msg: | - [pre-commit.ci] auto fixes from pre-commit hooks - autofix_prs: true - autoupdate_branch: 'pre-commit-autoupdate' - autoupdate_commit_msg: '[pre-commit.ci] pre-commit autoupdate' - autoupdate_schedule: monthly - skip: [no-commit-to-branch] - submodules: false + autofix_commit_msg: | + [pre-commit.ci] auto fixes from pre-commit hooks + autofix_prs: true + autoupdate_branch: "pre-commit-autoupdate" + autoupdate_commit_msg: "[pre-commit.ci] pre-commit autoupdate" + autoupdate_schedule: monthly + skip: [no-commit-to-branch] + submodules: false repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 @@ -47,6 +47,20 @@ repos: - repo: https://github.com/codespell-project/codespell rev: v2.3.0 hooks: - - id: codespell - additional_dependencies: - - tomli + - id: codespell + additional_dependencies: + - tomli + # prettier - multi formatter for .json, .yml, and .md files + - repo: https://github.com/pre-commit/mirrors-prettier + rev: f12edd9c7be1c20cfa42420fd0e6df71e42b51ea # frozen: v4.0.0-alpha.8 + hooks: + - id: prettier + additional_dependencies: + - "prettier@^3.2.4" + # docformatter - PEP 257 compliant docstring formatter + - repo: https://github.com/s-weigand/docformatter + rev: 5757c5190d95e5449f102ace83df92e7d3b06c6c + hooks: + - id: docformatter + additional_dependencies: [tomli] + args: [--in-place, --config, ./pyproject.toml] diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000..47f7a017 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,13 @@ +version: 2 + +build: + os: "ubuntu-22.04" + tools: + python: "latest" + +python: + install: + - requirements: requirements/docs.txt + +sphinx: + configuration: doc/source/conf.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9b8d9a18..8275360d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,5 +1,5 @@ ============= -Release Notes +Release notes ============= .. current developments diff --git a/CODE_OF_CONDUCT.rst b/CODE_OF_CONDUCT.rst index ff9c3561..e8199ca5 100644 --- a/CODE_OF_CONDUCT.rst +++ b/CODE_OF_CONDUCT.rst @@ -8,7 +8,7 @@ Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, +identity and expression, level of experience, education, socioeconomic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. diff --git a/LICENSE.rst b/LICENSE.rst index 74fd798d..a3c60094 100644 --- a/LICENSE.rst +++ b/LICENSE.rst @@ -1,7 +1,6 @@ BSD 3-Clause License -Copyright (c) 2023-2024, The Trustees of Columbia University -in the City of New York. +Copyright (c) 2023-2025, The Trustees of Columbia University in the City of New York. All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.rst b/README.rst index 2350f693..8e50f883 100644 --- a/README.rst +++ b/README.rst @@ -8,7 +8,7 @@ :target: https://diffpy.github.io/diffpy.snmf :height: 100px -|PyPi| |Forge| |PythonVersion| |PR| +|PyPI| |Forge| |PythonVersion| |PR| |CI| |Codecov| |Black| |Tracking| @@ -26,7 +26,7 @@ .. |PR| image:: https://img.shields.io/badge/PR-Welcome-29ab47ff -.. |PyPi| image:: https://img.shields.io/pypi/v/diffpy.snmf +.. |PyPI| image:: https://img.shields.io/pypi/v/diffpy.snmf :target: https://pypi.org/project/diffpy.snmf/ .. |PythonVersion| image:: https://img.shields.io/pypi/pyversions/diffpy.snmf @@ -132,4 +132,9 @@ Before contributing, please read our `Code of Conduct `_ or email Prof. Simon Billinge at sb2896@columbia.edu. +For more information on diffpy.snmf please visit the project `web-page `_ or email Simon J.L. Billinge group at sb2896@columbia.edu. + +Acknowledgements +---------------- + +``diffpy.snmf`` is built and maintained with `scikit-package `_. diff --git a/doc/source/conf.py b/doc/source/conf.py index 195ee2ff..3b12e7f1 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# diffpy.snmf documentation build configuration file, created by +# diffpy.snmf documentation build configuration file, created by # noqa: E501 # sphinx-quickstart on Thu Jan 30 15:49:41 2014. # # This file is execfile()d with the current directory set to its @@ -18,9 +18,15 @@ from importlib.metadata import version from pathlib import Path +# Attempt to import the version dynamically from GitHub tag. +try: + fullversion = version("diffpy.snmf") +except Exception: + fullversion = "No version found. The correct version will appear in the released version." # noqa: E501 + # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the -# documentation root, use Path().resolve() to make it absolute, like shown here. +# documentation root, use Path().resolve() to make it absolute, like shown here. # noqa: E501 # sys.path.insert(0, str(Path(".").resolve())) sys.path.insert(0, str(Path("../..").resolve())) sys.path.insert(0, str(Path("../../src").resolve())) @@ -43,6 +49,7 @@ "sphinx.ext.viewcode", "sphinx.ext.intersphinx", "sphinx_rtd_theme", + "sphinx_copybutton", "m2r", ] @@ -68,7 +75,6 @@ # |version| and |release|, also used in various other places throughout the # built documents. -fullversion = version(project) # The short X.Y version. version = "".join(fullversion.split(".post")[:1]) # The full version, including alpha/beta/rc tags. @@ -88,6 +94,11 @@ # substitute YEAR in the copyright string copyright = copyright.replace("%Y", year) +# For sphinx_copybutton extension. +# Do not copy "$" for shell commands in code-blocks. +copybutton_prompt_text = r"^\$ " +copybutton_prompt_is_regexp = True + # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ["build"] @@ -123,6 +134,14 @@ # html_theme = "sphinx_rtd_theme" +html_context = { + "display_github": True, + "github_user": "diffpy", + "github_repo": "diffpy.snmf", + "github_version": "main", + "conf_py_path": "/doc/source/", +} + # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. @@ -221,7 +240,13 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ("index", "diffpy.snmf.tex", "diffpy.snmf Documentation", ab_authors, "manual"), + ( + "index", + "diffpy.snmf.tex", + "diffpy.snmf Documentation", + ab_authors, + "manual", + ), ] # The name of an image file (relative to this directory) to place at the top of @@ -249,7 +274,15 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [("index", "diffpy.snmf", "diffpy.snmf Documentation", ab_authors, 1)] +man_pages = [ + ( + "index", + "diffpy.snmf", + "diffpy.snmf Documentation", + ab_authors, + 1, + ) +] # If true, show URL addresses after external links. # man_show_urls = False diff --git a/doc/source/index.rst b/doc/source/index.rst index b7755b07..0ad72619 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1,6 +1,11 @@ Welcome to SNMF's Documentation! ==================================== +``diffpy.snmf`` - Python package implementing the stretched NMF algorithm. + +| Software version |release| +| Last updated |today|. + ``SNMF``: This library implements the stretched non negative matrix factorization (sNMF) and sparse stretched NMF (ssNMF) algorithms described in the paper "Stretched Non-negative Matrix Factorization" by Ran Gu et al. (2023), which is referenced under the Citation section below. @@ -52,8 +57,9 @@ by citing the following paper in your publication: *npj Comput Mater* **10**, 193 (2024). +======= Authors -------- +======= ``snmf`` implements the algorithms described in ...., developed by members of the Billinge Group at Columbia University, Brookhaven National Laboratory, Stony Brook University, Nankai University, and Colorado State @@ -68,6 +74,19 @@ For a detailed list of contributors, check `here To get started, please go to :ref:`quick_start` +============ +Installation +============ + +See the `README `_ +file included with the distribution. + +================ +Acknowledgements +================ + +``diffpy.snmf`` is built and maintained with `scikit-package `_. + .. toctree:: :maxdepth: 3 :hidden: @@ -84,8 +103,9 @@ To get started, please go to :ref:`quick_start` .. include:: ../../CHANGELOG.rst +======= Indices -------- +======= * :ref:`genindex` * :ref:`search` diff --git a/doc/source/license.rst b/doc/source/license.rst index 573ccaf2..0ea5fba4 100644 --- a/doc/source/license.rst +++ b/doc/source/license.rst @@ -9,8 +9,7 @@ OPEN SOURCE LICENSE AGREEMENT ============================= BSD 3-Clause License -Copyright (c) 2023-2024, The Trustees of Columbia University in -the City of New York. +Copyright (c) 2023-2025, The Trustees of Columbia University in the City of New York. All Rights Reserved. Redistribution and use in source and binary forms, with or without diff --git a/news/doc.rst b/news/doc.rst new file mode 100644 index 00000000..b0ec659f --- /dev/null +++ b/news/doc.rst @@ -0,0 +1,23 @@ +**Added:** + +* + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* Support ``scikit-package`` Level 5 standard (https://scikit-package.github.io/scikit-package/). + +**Security:** + +* diff --git a/pyproject.toml b/pyproject.toml index fe6281b2..6a914219 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,17 +6,17 @@ build-backend = "setuptools.build_meta" name = "diffpy.snmf" dynamic=['version', 'dependencies'] authors = [ - { name="Simon J.L. Billinge group", email="simon.billinge@gmail.com" }, + { name="Simon J.L. Billinge group", email="sb2896@columbia.edu" }, ] maintainers = [ - { name="Simon J.L. Billinge group", email="simon.billinge@gmail.com" }, + { name="Simon J.L. Billinge group", email="sb2896@columbia.edu" }, ] description = "Python package implementing the stretched NMF algorithm." keywords = ['diffpy', 'PDF'] readme = "README.rst" requires-python = ">=3.11, <3.14" classifiers = [ - 'Development Status :: 4 - Beta', + 'Development Status :: 5 - Production/Stable', 'Environment :: Console', 'Intended Audience :: Developers', 'Intended Audience :: Science/Research', diff --git a/requirements/build.txt b/requirements/build.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/requirements/docs.txt b/requirements/docs.txt index ab17b1c8..5f34c6ed 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -1,4 +1,5 @@ sphinx sphinx_rtd_theme +sphinx-copybutton doctr m2r diff --git a/src/diffpy/__init__.py b/src/diffpy/__init__.py index 2baa1eaa..eded16c8 100644 --- a/src/diffpy/__init__.py +++ b/src/diffpy/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ############################################################################## # -# (c) 2024 The Trustees of Columbia University in the City of New York. +# (c) 2024-2025 The Trustees of Columbia University in the City of New York. # All rights reserved. # # File coded by: Billinge Group members and community contributors. @@ -12,7 +12,6 @@ # See LICENSE.rst for license information. # ############################################################################## - """Blank namespace package for module diffpy.""" diff --git a/src/diffpy/snmf/__init__.py b/src/diffpy/snmf/__init__.py index 9c7220bd..bb7f5a5a 100644 --- a/src/diffpy/snmf/__init__.py +++ b/src/diffpy/snmf/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python ############################################################################## # -# (c) 2024 The Trustees of Columbia University in the City of New York. +# (c) 2024-2025 The Trustees of Columbia University in the City of New York. # All rights reserved. # # File coded by: Billinge Group members and community contributors. @@ -12,11 +12,10 @@ # See LICENSE.rst for license information. # ############################################################################## - -"""A python package implementing the stretched NMF algorithm.""" +"""Python package implementing the stretched NMF algorithm.""" # package version -from diffpy.snmf.version import __version__ +from diffpy.snmf.version import __version__ # noqa # silence the pyflakes syntax checker assert __version__ or True diff --git a/src/diffpy/snmf/containers.py b/src/diffpy/snmf/containers.py index 1af960ad..00b09ea6 100644 --- a/src/diffpy/snmf/containers.py +++ b/src/diffpy/snmf/containers.py @@ -26,7 +26,7 @@ def __init__(self, grid, number_of_signals, id_number, perturbation=1e-3): self.id = int(id_number) def apply_stretch(self, m): - """Applies a stretching factor to a component + """Applies a stretching factor to a component. Parameters ---------- @@ -41,7 +41,11 @@ def apply_stretch(self, m): """ normalized_grid = np.arange(len(self.grid)) interpolate_intensity = lambda stretching_factor: np.interp( # noqa: E731 - normalized_grid / stretching_factor, normalized_grid, self.iq, left=0, right=0 + normalized_grid / stretching_factor, + normalized_grid, + self.iq, + left=0, + right=0, ) derivative_func = numdifftools.Derivative(interpolate_intensity) second_derivative_func = numdifftools.Derivative(derivative_func) diff --git a/src/diffpy/snmf/factorizers.py b/src/diffpy/snmf/factorizers.py index b4620fd4..a9db32ce 100644 --- a/src/diffpy/snmf/factorizers.py +++ b/src/diffpy/snmf/factorizers.py @@ -3,7 +3,8 @@ def lsqnonneg(stretched_component_matrix, target_signal): - """Finds the weights of stretched component signals under one-sided constraint. + """Finds the weights of stretched component signals under one-sided + constraint. Solves ``argmin_x || Ax - b ||_2`` for ``x>=0`` where A is the stretched_component_matrix and b is the target_signal vector. Finds the weights of component signals given undecomposed signal data and stretched diff --git a/src/diffpy/snmf/io.py b/src/diffpy/snmf/io.py index 12eb1b23..62614d05 100644 --- a/src/diffpy/snmf/io.py +++ b/src/diffpy/snmf/io.py @@ -39,7 +39,6 @@ def initialize_variables(data_input, number_of_components, data_type, sparsity=1 guess for the weight factor matrix, an initial guess for the stretching factor matrix, a parameter controlling smoothness of the solution, a parameter controlling sparseness of the solution, the matrix representing the smoothness term, and a matrix used to construct a hessian matrix. - """ signal_length = data_input.shape[0] number_of_signals = data_input.shape[1] @@ -74,7 +73,8 @@ def initialize_variables(data_input, number_of_components, data_type, sparsity=1 def load_input_signals(file_path=None): - """Processes a directory of a series of PDF/XRD patterns into a usable format. + """Processes a directory of a series of PDF/XRD patterns into a usable + format. Constructs a 2d array out of a directory of PDF/XRD patterns containing each files dependent variable column in a new column. Constructs a 1d array containing the grid values. @@ -92,7 +92,6 @@ def load_input_signals(file_path=None): The tuple whose first element is an R x M 2d array made of PDF/XRD patterns as each column; R is the length of the signal and M is the number of patterns. The tuple contains a 1d array containing the values of the grid points as its second element; Has length R. - """ if file_path is None: diff --git a/src/diffpy/snmf/optimizers.py b/src/diffpy/snmf/optimizers.py index d1a8e51f..81a1b6da 100644 --- a/src/diffpy/snmf/optimizers.py +++ b/src/diffpy/snmf/optimizers.py @@ -2,8 +2,14 @@ from scipy.optimize import minimize -def get_weights(stretched_component_gram_matrix, linear_coefficient, lower_bound, upper_bound): - """Finds the weights of stretched component signals under a two-sided constraint +def get_weights( + stretched_component_gram_matrix, + linear_coefficient, + lower_bound, + upper_bound, +): + """Finds the weights of stretched component signals under a two-sided + constraint. Solves min J(y) = (linear_coefficient)' * y + (1/2) * y' * (quadratic coefficient) * y where lower_bound <= y <= upper_bound and stretched_component_gram_matrix is symmetric positive definite. @@ -34,7 +40,6 @@ def get_weights(stretched_component_gram_matrix, linear_coefficient, lower_bound 1d array like The vector containing the weightings of the components needed to reconstruct a given input signal from the input set. Has length C - """ stretched_component_gram_matrix = np.asarray(stretched_component_gram_matrix) diff --git a/src/diffpy/snmf/polynomials.py b/src/diffpy/snmf/polynomials.py index c54ff215..a1949145 100644 --- a/src/diffpy/snmf/polynomials.py +++ b/src/diffpy/snmf/polynomials.py @@ -2,9 +2,8 @@ def compute_root(linear_coefficient, constant_term): - """ - Returns the largest real root of x^3+(linear_coefficient) * x + constant_term. If there are no real roots - return 0. + """Returns the largest real root of x^3+(linear_coefficient) * x + + constant_term. If there are no real roots return 0. Parameters ---------- @@ -18,7 +17,6 @@ def compute_root(linear_coefficient, constant_term): ndarray of floats The largest real root of x^3+(linear_coefficient) * x + constant_term if roots are real, else return 0 array - """ linear_coefficient = np.asarray(linear_coefficient) constant_term = np.asarray(constant_term) diff --git a/src/diffpy/snmf/stretchednmfapp.py b/src/diffpy/snmf/stretchednmfapp.py index f577b887..f62a9a5c 100644 --- a/src/diffpy/snmf/stretchednmfapp.py +++ b/src/diffpy/snmf/stretchednmfapp.py @@ -4,12 +4,18 @@ from diffpy.snmf.io import initialize_variables, load_input_signals from diffpy.snmf.subroutines import initialize_components, lift_data -ALLOWED_DATA_TYPES = ["powder_diffraction", "pd", "pair_distribution_function", "pdf"] +ALLOWED_DATA_TYPES = [ + "powder_diffraction", + "pd", + "pair_distribution_function", + "pdf", +] def create_parser(): parser = argparse.ArgumentParser( - prog="stretched_nmf", description="Stretched Nonnegative Matrix Factorization" + prog="stretched_nmf", + description="Stretched Nonnegative Matrix Factorization", ) parser.add_argument( "-i", @@ -44,7 +50,12 @@ def create_parser(): type=int, help="The number of component signals for the NMF decomposition. Must be an integer greater than 0", ) - parser.add_argument("-v", "--version", action="version", help="Print the software version number") + parser.add_argument( + "-v", + "--version", + action="version", + help="Print the software version number", + ) args = parser.parse_args() return args diff --git a/src/diffpy/snmf/subroutines.py b/src/diffpy/snmf/subroutines.py index ae7f7ef7..9d6a6562 100644 --- a/src/diffpy/snmf/subroutines.py +++ b/src/diffpy/snmf/subroutines.py @@ -7,7 +7,8 @@ def initialize_components(number_of_components, number_of_signals, grid_vector): - """Initializes ComponentSignals for each of the components in the decomposition. + """Initializes ComponentSignals for each of the components in the + decomposition. Parameters ---------- @@ -182,7 +183,8 @@ def update_weights(components, data_input, method=None): def reconstruct_signal(components, signal_idx): - """Reconstructs a specific signal from its weighted and stretched components. + """Reconstructs a specific signal from its weighted and stretched + components. Calculates the linear combination of stretched components where each term is the stretched component multiplied by its weight factor. @@ -209,7 +211,8 @@ def reconstruct_signal(components, signal_idx): def initialize_arrays(number_of_components, number_of_moments, signal_length): - """Generates the initial guesses for the weight, stretching, and component matrices. + """Generates the initial guesses for the weight, stretching, and component + matrices. Calculates the initial guesses for the component matrix, stretching factor matrix, and weight matrix. The initial guess for the component matrix is a random (signal_length) x (number_of_components) matrix where @@ -245,7 +248,12 @@ def initialize_arrays(number_of_components, number_of_moments, signal_length): def objective_function( - residual_matrix, stretching_factor_matrix, smoothness, smoothness_term, component_matrix, sparsity + residual_matrix, + stretching_factor_matrix, + smoothness, + smoothness_term, + component_matrix, + sparsity, ): """Defines the objective function of the algorithm and returns its value. @@ -322,7 +330,13 @@ def get_stretched_component(stretching_factor, component, signal_length): normalized_grid = np.arange(signal_length) def stretched_component_func(stretching_factor): - return np.interp(normalized_grid / stretching_factor, normalized_grid, component, left=0, right=0) + return np.interp( + normalized_grid / stretching_factor, + normalized_grid, + component, + left=0, + right=0, + ) derivative_func = numdifftools.Derivative(stretched_component_func) second_derivative_func = numdifftools.Derivative(derivative_func) @@ -394,10 +408,15 @@ def update_weights_matrix( stretched_components = np.zeros((signal_length, component_amount)) for n in range(component_amount): stretched_components[:, n] = get_stretched_component( - stretching_factor_matrix[n, i], component_matrix[:, n], signal_length + stretching_factor_matrix[n, i], + component_matrix[:, n], + signal_length, )[0] if method == "align": - weight = lsqnonneg(stretched_components[0:signal_length, :], data_input[0:signal_length, i]) + weight = lsqnonneg( + stretched_components[0:signal_length, :], + data_input[0:signal_length, i], + ) else: weight = get_weights( stretched_components[0:signal_length, :].T @ stretched_components[0:signal_length, :], @@ -410,9 +429,16 @@ def update_weights_matrix( def get_residual_matrix( - component_matrix, weights_matrix, stretching_matrix, data_input, moment_amount, component_amount, signal_length + component_matrix, + weights_matrix, + stretching_matrix, + data_input, + moment_amount, + component_amount, + signal_length, ): - """Obtains the residual matrix between the experimental data and calculated data. + """Obtains the residual matrix between the experimental data and calculated + data. Calculates the difference between the experimental data and the reconstructed experimental data created from the calculated components, weights, and stretching factors. For each experimental pattern, the stretched and @@ -465,7 +491,11 @@ def get_residual_matrix( residual = ( residual + weights_matrix[k, m] - * get_stretched_component(stretching_matrix[k, m], component_matrix[:, k], signal_length)[0] + * get_stretched_component( + stretching_matrix[k, m], + component_matrix[:, k], + signal_length, + )[0] ) residual_matrx[:, m] = residual return residual_matrx diff --git a/src/diffpy/snmf/version.py b/src/diffpy/snmf/version.py index 202bd54e..e198622b 100644 --- a/src/diffpy/snmf/version.py +++ b/src/diffpy/snmf/version.py @@ -1,18 +1,17 @@ #!/usr/bin/env python ############################################################################## # -# (c) 2024 The Trustees of Columbia University in the City of New York. +# (c) 2024-2025 The Trustees of Columbia University in the City of New York. # All rights reserved. # # File coded by: Billinge Group members and community contributors. # # See GitHub contributions for a more detailed list of contributors. -# https://github.com/diffpy/diffpy.snmf/graphs/contributors +# https://github.com/diffpy/diffpy.snmf/graphs/contributors # noqa: E501 # # See LICENSE.rst for license information. # ############################################################################## - """Definition of __version__.""" # We do not use the other three variables, but can be added back if needed. diff --git a/tests/test_containers.py b/tests/test_containers.py index 9595ae51..5b29dfef 100644 --- a/tests/test_containers.py +++ b/tests/test_containers.py @@ -50,7 +50,18 @@ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 0.88, [ - [1, 2.1364, 3.2727, 4.4091, 5.5455, 6.6818, 7.8182, 8.9545, 0, 0], + [ + 1, + 2.1364, + 3.2727, + 4.4091, + 5.5455, + 6.6818, + 7.8182, + 8.9545, + 0, + 0, + ], [0, -1.29, -2.58, -3.87, -5.165, -6.45, -7.74, -9.039, 0, 0], [0, 2.93, 5.869, 8.084, 11.739, 14.674, 17.608, 20.5437, 0, 0], ], @@ -77,9 +88,54 @@ ], 0.55, [ - [-2.9384, -1.9769, 0.9121, 0.6314, 0.8622, -2.4239, -0.2302, 1.9281, 0, 0, 0, 0, 0, 0], - [0, 2.07933, 38.632, 18.3748, 43.07305, -61.557, 26.005, -73.637, 0, 0, 0, 0, 0, 0], - [0, -7.56, -140.480, -66.81, -156.6293, 223.84, -94.564, 267.7734, 0, 0, 0, 0, 0, 0], + [ + -2.9384, + -1.9769, + 0.9121, + 0.6314, + 0.8622, + -2.4239, + -0.2302, + 1.9281, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0, + 2.07933, + 38.632, + 18.3748, + 43.07305, + -61.557, + 26.005, + -73.637, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0, + -7.56, + -140.480, + -66.81, + -156.6293, + 223.84, + -94.564, + 267.7734, + 0, + 0, + 0, + 0, + 0, + 0, + ], ], ), ( @@ -89,9 +145,45 @@ [0, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5], 0.987, [ - [0, 0.2533, 0.5066, 0.7599, 1.0132, 1.2665, 1.5198, 1.7730, 2.0263, 2.2796, 0], - [0, -0.2566, -0.5132, -0.7699, -1.0265, -1.2831, -1.5398, -1.7964, -2.0530, -2.3097, 0], - [0, 0.5200, 1.0400, 1.56005, 2.08007, 2.6000, 3.1201, 3.6401, 4.1601, 4.6801, 0], + [ + 0, + 0.2533, + 0.5066, + 0.7599, + 1.0132, + 1.2665, + 1.5198, + 1.7730, + 2.0263, + 2.2796, + 0, + ], + [ + 0, + -0.2566, + -0.5132, + -0.7699, + -1.0265, + -1.2831, + -1.5398, + -1.7964, + -2.0530, + -2.3097, + 0, + ], + [ + 0, + 0.5200, + 1.0400, + 1.56005, + 2.08007, + 2.6000, + 3.1201, + 3.6401, + 4.1601, + 4.6801, + 0, + ], ], ), ( @@ -100,7 +192,11 @@ 3, [-1, -2, -3, -4, -5, -6, -7, -8, -9], -0.4, - [[-1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]], + [ + [-1, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0], + ], ), ], ) @@ -116,8 +212,22 @@ def test_apply_stretch(grid, number_of_signals, id_number, iq, stretching_factor "grid, number_of_signals, id_number, iq, weight, expected", [ (np.arange(5), 2, 0, [0, 1, 2, 3, 4], 0.5, [0, 0.5, 1, 1.5, 2]), - (np.arange(5), 20, 2, [0, -1, -2, -3, -4], 0.25, [0, -0.25, -0.5, -0.75, -1]), - (np.arange(40), 200, 4, np.arange(0, 10, 0.25), 0.3, np.arange(0, 10, 0.25) * 0.3), + ( + np.arange(5), + 20, + 2, + [0, -1, -2, -3, -4], + 0.25, + [0, -0.25, -0.5, -0.75, -1], + ), + ( + np.arange(40), + 200, + 4, + np.arange(0, 10, 0.25), + 0.3, + np.arange(0, 10, 0.25) * 0.3, + ), (np.arange(1), 10, 2, [10.5, 11.5, -10.5], 0, [0, 0, 0]), ([-12, -10, -15], 5, 2, [-0.5, -1, -1.2], 0.9, [-0.45, -0.9, -1.08]), ([-12, -10, -15], 5, 2, [0, 0, 0], 0.9, [0, 0, 0]), diff --git a/tests/test_optimizers.py b/tests/test_optimizers.py index 31799150..53158692 100644 --- a/tests/test_optimizers.py +++ b/tests/test_optimizers.py @@ -9,12 +9,47 @@ ([[1, 0], [0, 1]], [1, 1], 0, 0, [0, 0]), ([[1, 0], [0, 1]], [1, 1], -1, 1, [-1, -1]), ([[1.75, 0], [0, 1.5]], [1, 1.2], -1, 1, [-0.571428571428571, -0.8]), - ([[0.75, 0.2], [0.2, 0.75]], [-0.1, -0.2], -1, 1, [0.066985645933014, 0.248803827751196]), - ([[2, -1, 0], [-1, 2, -1], [0, -1, 2]], [1, 1, 1], -10, 12, [-1.5, -2, -1.5]), - ([[2, -1, 0], [-1, 2, -1], [0, -1, 2]], [1, -1, -1], -10, 12, [0, 1, 1]), - ([[4, 0, 0, 0], [0, 3, 0, 0], [0, 0, 2, 0], [0, 0, 0, 1]], [-2, -3, -4, -1], 0, 1000, [0.5, 1, 2, 1]), + ( + [[0.75, 0.2], [0.2, 0.75]], + [-0.1, -0.2], + -1, + 1, + [0.066985645933014, 0.248803827751196], + ), + ( + [[2, -1, 0], [-1, 2, -1], [0, -1, 2]], + [1, 1, 1], + -10, + 12, + [-1.5, -2, -1.5], + ), + ( + [[2, -1, 0], [-1, 2, -1], [0, -1, 2]], + [1, -1, -1], + -10, + 12, + [0, 1, 1], + ), + ( + [[4, 0, 0, 0], [0, 3, 0, 0], [0, 0, 2, 0], [0, 0, 0, 1]], + [-2, -3, -4, -1], + 0, + 1000, + [0.5, 1, 2, 1], + ), ], ) -def test_get_weights(stretched_component_gram_matrix, linear_coefficient, lower_bound, upper_bound, expected): - actual = get_weights(stretched_component_gram_matrix, linear_coefficient, lower_bound, upper_bound) +def test_get_weights( + stretched_component_gram_matrix, + linear_coefficient, + lower_bound, + upper_bound, + expected, +): + actual = get_weights( + stretched_component_gram_matrix, + linear_coefficient, + lower_bound, + upper_bound, + ) assert actual == pytest.approx(expected, rel=1e-4, abs=1e-6) diff --git a/tests/test_subroutines.py b/tests/test_subroutines.py index 3b3e392c..6c1dd122 100644 --- a/tests/test_subroutines.py +++ b/tests/test_subroutines.py @@ -21,16 +21,51 @@ @pytest.mark.parametrize( "residual_matrix, stretching_factor_matrix, smoothness, smoothness_term, component_matrix, sparsity, expected", [ - ([[1, 2], [3, 4]], [[5, 6], [7, 8]], 1e11, [[1, 2], [3, 4]], [[1, 2], [3, 4]], 1, 2.574e14), - ([[11, 2], [31, 4]], [[5, 63], [7, 18]], 0.001, [[21, 2], [3, 4]], [[11, 22], [3, 40]], 1, 650.4576), - ([[1, 2], [3, 4]], [[5, 6], [7, 8]], 1e11, [[1, 2], [3, 4]], [[1, 2], [3, 4]], 0, 2.574e14), + ( + [[1, 2], [3, 4]], + [[5, 6], [7, 8]], + 1e11, + [[1, 2], [3, 4]], + [[1, 2], [3, 4]], + 1, + 2.574e14, + ), + ( + [[11, 2], [31, 4]], + [[5, 63], [7, 18]], + 0.001, + [[21, 2], [3, 4]], + [[11, 22], [3, 40]], + 1, + 650.4576, + ), + ( + [[1, 2], [3, 4]], + [[5, 6], [7, 8]], + 1e11, + [[1, 2], [3, 4]], + [[1, 2], [3, 4]], + 0, + 2.574e14, + ), ], ) def test_objective_function( - residual_matrix, stretching_factor_matrix, smoothness, smoothness_term, component_matrix, sparsity, expected + residual_matrix, + stretching_factor_matrix, + smoothness, + smoothness_term, + component_matrix, + sparsity, + expected, ): actual = objective_function( - residual_matrix, stretching_factor_matrix, smoothness, smoothness_term, component_matrix, sparsity + residual_matrix, + stretching_factor_matrix, + smoothness, + smoothness_term, + component_matrix, + sparsity, ) assert actual == pytest.approx(expected) @@ -73,7 +108,18 @@ def test_objective_function( [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 10, ( - [1, 2.1364, 3.2727, 4.4091, 5.5455, 6.6818, 7.8182, 8.9545, 0, 0], + [ + 1, + 2.1364, + 3.2727, + 4.4091, + 5.5455, + 6.6818, + 7.8182, + 8.9545, + 0, + 0, + ], [0, -1.29, -2.58, -3.87, -5.165, -6.45, -7.74, -9.039, 0, 0], [0, 2.93, 5.869, 8.084, 11.739, 14.674, 17.608, 20.5437, 0, 0], ), @@ -98,9 +144,54 @@ def test_objective_function( ], 14, ( - [-2.9384, -1.9769, 0.9121, 0.6314, 0.8622, -2.4239, -0.2302, 1.9281, 0, 0, 0, 0, 0, 0], - [0, 2.07933, 38.632, 18.3748, 43.07305, -61.557, 26.005, -73.637, 0, 0, 0, 0, 0, 0], - [0, -7.56, -140.480, -66.81, -156.6293, 223.84, -94.564, 267.7734, 0, 0, 0, 0, 0, 0], + [ + -2.9384, + -1.9769, + 0.9121, + 0.6314, + 0.8622, + -2.4239, + -0.2302, + 1.9281, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0, + 2.07933, + 38.632, + 18.3748, + 43.07305, + -61.557, + 26.005, + -73.637, + 0, + 0, + 0, + 0, + 0, + 0, + ], + [ + 0, + -7.56, + -140.480, + -66.81, + -156.6293, + 223.84, + -94.564, + 267.7734, + 0, + 0, + 0, + 0, + 0, + 0, + ], ), ), ( @@ -108,16 +199,56 @@ def test_objective_function( [0, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.25, 2.5], 11, ( - [0, 0.2533, 0.5066, 0.7599, 1.0132, 1.2665, 1.5198, 1.7730, 2.0263, 2.2796, 0], - [0, -0.2566, -0.5132, -0.7699, -1.0265, -1.2831, -1.5398, -1.7964, -2.0530, -2.3097, 0], - [0, 0.5200, 1.0400, 1.56005, 2.08007, 2.6000, 3.1201, 3.6401, 4.1601, 4.6801, 0], + [ + 0, + 0.2533, + 0.5066, + 0.7599, + 1.0132, + 1.2665, + 1.5198, + 1.7730, + 2.0263, + 2.2796, + 0, + ], + [ + 0, + -0.2566, + -0.5132, + -0.7699, + -1.0265, + -1.2831, + -1.5398, + -1.7964, + -2.0530, + -2.3097, + 0, + ], + [ + 0, + 0.5200, + 1.0400, + 1.56005, + 2.08007, + 2.6000, + 3.1201, + 3.6401, + 4.1601, + 4.6801, + 0, + ], ), ), ( -0.4, [-1, -2, -3, -4, -5, -6, -7, -8, -9], 9, - ([-1, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0]), + ( + [-1, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0], + ), ), ], ) @@ -172,10 +303,34 @@ def test_get_stretched_component(stretching_factor, component, signal_length, ex 3, [[0.9, 0.4, 0.5], [1, 0, 0.4], [0, 0, 0.98]], None, - [[1.0, 0.0900485, 0.0], [0.585632, 0.497497, 0.179719], [0.0, 0.52223655, 1.0]], + [ + [1.0, 0.0900485, 0.0], + [0.585632, 0.497497, 0.179719], + [0.0, 0.52223655, 1.0], + ], + ), + ( + 2, + 2, + [[0.5], [0.5]], + [[0, 0], [0, 0]], + [[0, 0], [0, 0]], + 1, + [[0.6], [0.4]], + "align", + [[0], [0]], + ), + ( + 1, + 3, + [[0.5, 0.3]], + [[1], [1.1], [1.3]], + [[1, 2], [2, 3], [3, 2]], + 2, + [[0.6, 0.4]], + None, + [[1, 1]], ), - (2, 2, [[0.5], [0.5]], [[0, 0], [0, 0]], [[0, 0], [0, 0]], 1, [[0.6], [0.4]], "align", [[0], [0]]), - (1, 3, [[0.5, 0.3]], [[1], [1.1], [1.3]], [[1, 2], [2, 3], [3, 2]], 2, [[0.6, 0.4]], None, [[1, 1]]), ( 2, 2, @@ -207,9 +362,23 @@ def test_get_stretched_component(stretching_factor, component, signal_length, ex 3, [[0.9, 0.4, 0.5], [1, 0, 0.4], [0, 0, 0.98]], "align", - [[1.281265, 0.104355, 0], [0.0, 0.0, 0.0], [0.239578, 0.965215, 1.162571]], + [ + [1.281265, 0.104355, 0], + [0.0, 0.0, 0.0], + [0.239578, 0.965215, 1.162571], + ], + ), + ( + 2, + 2, + [[0.5], [0.5]], + [[0, 0], [0, 0]], + [[0, 0], [0, 0]], + 1, + [[0.6], [0.4]], + "align", + [[0], [0]], ), - (2, 2, [[0.5], [0.5]], [[0, 0], [0, 0]], [[0, 0], [0, 0]], 1, [[0.6], [0.4]], "align", [[0], [0]]), ( 1, 3, @@ -262,7 +431,16 @@ def test_update_weights_matrix( 2, [[-9, -22], [-33, -44]], ), - ([[1, 2], [3, 4]], [[1], [1]], [[1], [1]], [[11, 22], [33, 44]], 1, 2, 2, [[-8, -22], [-26, -44]]), + ( + [[1, 2], [3, 4]], + [[1], [1]], + [[1], [1]], + [[11, 22], [33, 44]], + 1, + 2, + 2, + [[-8, -22], [-26, -44]], + ), ( [[1.1, 4.4], [1.2, 4.5], [14, 7.8]], [[0.4, 0.6], [0.75, 0.25]], @@ -351,13 +529,37 @@ def test_reconstruct_data(components): "data_input, lift, expected", [ # Correct structure: Each test case should be a tuple with three elements.pt - ([[1, -1, 1], [0, 0, 0], [2, 10, -3]], 1, [[4, 2, 4], [3, 3, 3], [5, 13, 0]]), - ([[1, -1, 1], [0, 0, 0], [2, 10, -3]], 0, [[1, -1, 1], [0, 0, 0], [2, 10, -3]]), - ([[1, -1, 1], [0, 0, 0], [2, 10, -3]], 0.5, [[2.5, 0.5, 2.5], [1.5, 1.5, 1.5], [3.5, 11.5, -1.5]]), - ([[1, -1, 1], [0, 0, 0], [2, 10, -3]], -1, [[4, 2, 4], [3, 3, 3], [5, 13, 0]]), - ([[0, 0, 0], [0, 0, 0], [0, 0, 0]], 100, [[0, 0, 0], [0, 0, 0], [0, 0, 0]]), + ( + [[1, -1, 1], [0, 0, 0], [2, 10, -3]], + 1, + [[4, 2, 4], [3, 3, 3], [5, 13, 0]], + ), + ( + [[1, -1, 1], [0, 0, 0], [2, 10, -3]], + 0, + [[1, -1, 1], [0, 0, 0], [2, 10, -3]], + ), + ( + [[1, -1, 1], [0, 0, 0], [2, 10, -3]], + 0.5, + [[2.5, 0.5, 2.5], [1.5, 1.5, 1.5], [3.5, 11.5, -1.5]], + ), + ( + [[1, -1, 1], [0, 0, 0], [2, 10, -3]], + -1, + [[4, 2, 4], [3, 3, 3], [5, 13, 0]], + ), + ( + [[0, 0, 0], [0, 0, 0], [0, 0, 0]], + 100, + [[0, 0, 0], [0, 0, 0], [0, 0, 0]], + ), ([[1.5, 2], [10.5, 1], [0.5, 2]], 1, [[2, 2.5], [11, 1.5], [1, 2.5]]), - ([[-10, -10.5], [-12.2, -12.2], [0, 0]], 1, [[2.2, 1.7], [0, 0], [12.2, 12.2]]), + ( + [[-10, -10.5], [-12.2, -12.2], [0, 0]], + 1, + [[2.2, 1.7], [0, 0], [12.2, 12.2]], + ), ], ) def test_lift_data(data_input, lift, expected): @@ -388,9 +590,30 @@ def test_initialize_componentstest_initialize_components(number_of_components, n # ([ComponentSignal([0,.5,1,1.5],20,0)],-2,20), # Raises an exception # ([ComponentSignal([0,.5,1,1.5],20,0)],1,0), # Raises an Exception # ([ComponentSignal([0,.5,1,1.5],20,0)],1,-3), # Raises an exception - ([ComponentSignal([0, 0.5, 1, 1.5], 20, 0), ComponentSignal([0, 0.5, 1, 1.5], 20, 1)], 2, 20), - ([ComponentSignal([0, 0.5, 1, 1.5], 20, 0), ComponentSignal([0, 0.5, 1, 21.5], 20, 1)], 2, 20), - ([ComponentSignal([0, 1, 1.5], 20, 0), ComponentSignal([0, 0.5, 1, 21.5], 20, 1)], 2, 20), + ( + [ + ComponentSignal([0, 0.5, 1, 1.5], 20, 0), + ComponentSignal([0, 0.5, 1, 1.5], 20, 1), + ], + 2, + 20, + ), + ( + [ + ComponentSignal([0, 0.5, 1, 1.5], 20, 0), + ComponentSignal([0, 0.5, 1, 21.5], 20, 1), + ], + 2, + 20, + ), + ( + [ + ComponentSignal([0, 1, 1.5], 20, 0), + ComponentSignal([0, 0.5, 1, 21.5], 20, 1), + ], + 2, + 20, + ), # ([ComponentSignal([0,.5,1,1.5],20,0),ComponentSignal([0,.5,1,1.5],20,1)],1,-3), # Negative signal length. Raises an exception # ([],1,20), # Empty components. Raises an Exception @@ -433,8 +656,19 @@ def test_construct_stretching_matrix(components, number_of_components, number_of ComponentSignal([0, 0.25, 0.5, 0.75, 1], 20, 2), ] ), - ([ComponentSignal([0.25], 20, 0), ComponentSignal([0.25], 20, 1), ComponentSignal([0.25], 20, 2)]), - ([ComponentSignal([0, 0.25, 0.5, 0.75, 1], 20, 0), ComponentSignal([0, 0.25, 0.5, 0.75, 1], 20, 1)]), + ( + [ + ComponentSignal([0.25], 20, 0), + ComponentSignal([0.25], 20, 1), + ComponentSignal([0.25], 20, 2), + ] + ), + ( + [ + ComponentSignal([0, 0.25, 0.5, 0.75, 1], 20, 0), + ComponentSignal([0, 0.25, 0.5, 0.75, 1], 20, 1), + ] + ), # ([ComponentSignal([[0, .25, .5, .75, 1],[0, .25, .5, .75, 1]], 20, 0), # ComponentSignal([[0, .25, .5, .75, 1],[0, .25, .5, .75, 1]], 20, 1)]), # iq is multidimensional. Expected to fail @@ -474,8 +708,19 @@ def test_construct_component_matrix(components): ComponentSignal([0, 0.25, 0.5, 0.75, 1], 20, 2), ] ), - ([ComponentSignal([0.25], 20, 0), ComponentSignal([0.25], 20, 1), ComponentSignal([0.25], 20, 2)]), - ([ComponentSignal([0, 0.25, 0.5, 0.75, 1], 20, 0), ComponentSignal([0, 0.25, 0.5, 0.75, 1], 20, 1)]), + ( + [ + ComponentSignal([0.25], 20, 0), + ComponentSignal([0.25], 20, 1), + ComponentSignal([0.25], 20, 2), + ] + ), + ( + [ + ComponentSignal([0, 0.25, 0.5, 0.75, 1], 20, 0), + ComponentSignal([0, 0.25, 0.5, 0.75, 1], 20, 1), + ] + ), # (ComponentSignal([], 20, 0)), # Expected to fail # ([]), #Expected to fail ], diff --git a/tests/test_version.py b/tests/test_version.py index eccc3cf3..cac08228 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -1,10 +1,10 @@ -"""Unit tests for __version__.py -""" +"""Unit tests for __version__.py.""" -import diffpy.snmf +import diffpy.snmf # noqa def test_package_version(): - """Ensure the package version is defined and not set to the initial placeholder.""" + """Ensure the package version is defined and not set to the initial + placeholder.""" assert hasattr(diffpy.snmf, "__version__") assert diffpy.snmf.__version__ != "0.0.0" From 1231d719955d661264006349e52cd95ae33f6b69 Mon Sep 17 00:00:00 2001 From: zmx27 <95781012+zmx27@users.noreply.github.com> Date: Wed, 18 Jun 2025 18:57:16 -0400 Subject: [PATCH 3/5] ci: add docformatter config to pyproject.toml and apply them to the files (#156) * ci: add docformatter config block and run pre-commit to apply them to files * chore: add news file for this change --- news/add-docformatter.rst | 23 +++++++++++++++++++++++ pyproject.toml | 5 +++++ src/diffpy/snmf/io.py | 7 ++++--- src/diffpy/snmf/optimizers.py | 4 ++-- src/diffpy/snmf/subroutines.py | 11 ++++++----- 5 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 news/add-docformatter.rst diff --git a/news/add-docformatter.rst b/news/add-docformatter.rst new file mode 100644 index 00000000..0df46db0 --- /dev/null +++ b/news/add-docformatter.rst @@ -0,0 +1,23 @@ +**Added:** + +* Add docformatter config block to the end of the pyproject.toml file. + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* + +**Security:** + +* diff --git a/pyproject.toml b/pyproject.toml index 6a914219..e30a9dea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,11 @@ exclude-file = ".codespell/ignore_lines.txt" ignore-words = ".codespell/ignore_words.txt" skip = "*.cif,*.dat" +[tool.docformatter] +recursive = true +wrap-summaries = 72 +wrap-descriptions = 72 + [tool.black] line-length = 115 include = '\.pyi?$' diff --git a/src/diffpy/snmf/io.py b/src/diffpy/snmf/io.py index 62614d05..18c3ca39 100644 --- a/src/diffpy/snmf/io.py +++ b/src/diffpy/snmf/io.py @@ -7,7 +7,8 @@ def initialize_variables(data_input, number_of_components, data_type, sparsity=1, smoothness=1e18): - """Determines the variables and initial values used in the SNMF algorithm. + """Determines the variables and initial values used in the SNMF + algorithm. Parameters ---------- @@ -73,8 +74,8 @@ def initialize_variables(data_input, number_of_components, data_type, sparsity=1 def load_input_signals(file_path=None): - """Processes a directory of a series of PDF/XRD patterns into a usable - format. + """Processes a directory of a series of PDF/XRD patterns into a + usable format. Constructs a 2d array out of a directory of PDF/XRD patterns containing each files dependent variable column in a new column. Constructs a 1d array containing the grid values. diff --git a/src/diffpy/snmf/optimizers.py b/src/diffpy/snmf/optimizers.py index 81a1b6da..ea4ecff1 100644 --- a/src/diffpy/snmf/optimizers.py +++ b/src/diffpy/snmf/optimizers.py @@ -8,8 +8,8 @@ def get_weights( lower_bound, upper_bound, ): - """Finds the weights of stretched component signals under a two-sided - constraint. + """Finds the weights of stretched component signals under a two- + sided constraint. Solves min J(y) = (linear_coefficient)' * y + (1/2) * y' * (quadratic coefficient) * y where lower_bound <= y <= upper_bound and stretched_component_gram_matrix is symmetric positive definite. diff --git a/src/diffpy/snmf/subroutines.py b/src/diffpy/snmf/subroutines.py index 9d6a6562..19abc6d5 100644 --- a/src/diffpy/snmf/subroutines.py +++ b/src/diffpy/snmf/subroutines.py @@ -211,8 +211,8 @@ def reconstruct_signal(components, signal_idx): def initialize_arrays(number_of_components, number_of_moments, signal_length): - """Generates the initial guesses for the weight, stretching, and component - matrices. + """Generates the initial guesses for the weight, stretching, and + component matrices. Calculates the initial guesses for the component matrix, stretching factor matrix, and weight matrix. The initial guess for the component matrix is a random (signal_length) x (number_of_components) matrix where @@ -255,7 +255,8 @@ def objective_function( component_matrix, sparsity, ): - """Defines the objective function of the algorithm and returns its value. + """Defines the objective function of the algorithm and returns its + value. Calculates the value of '(||residual_matrix||_F) ** 2 + smoothness * (||smoothness_term * stretching_factor_matrix.T||)**2 + sparsity * sum(component_matrix ** .5)' and returns its value. @@ -437,8 +438,8 @@ def get_residual_matrix( component_amount, signal_length, ): - """Obtains the residual matrix between the experimental data and calculated - data. + """Obtains the residual matrix between the experimental data and + calculated data. Calculates the difference between the experimental data and the reconstructed experimental data created from the calculated components, weights, and stretching factors. For each experimental pattern, the stretched and From 82a498c35312d6270c4fc337194a0bd91cd439d9 Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Tue, 20 Jan 2026 23:36:02 -0500 Subject: [PATCH 4/5] build: Add support for python 3.14 and remove support for python 3.11 --- news/python-version.rst | 23 +++++++++++++++++++++++ pyproject.toml | 4 ++-- 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 news/python-version.rst diff --git a/news/python-version.rst b/news/python-version.rst new file mode 100644 index 00000000..a037a121 --- /dev/null +++ b/news/python-version.rst @@ -0,0 +1,23 @@ +**Added:** + +* Support for Python 3.14 + +**Changed:** + +* + +**Deprecated:** + +* + +**Removed:** + +* Support for Python 3.11 + +**Fixed:** + +* + +**Security:** + +* diff --git a/pyproject.toml b/pyproject.toml index e30a9dea..30e30d30 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ maintainers = [ description = "Python package implementing the stretched NMF algorithm." keywords = ['diffpy', 'PDF'] readme = "README.rst" -requires-python = ">=3.11, <3.14" +requires-python = ">=3.12, <3.15" classifiers = [ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', @@ -25,9 +25,9 @@ classifiers = [ 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX', 'Operating System :: Unix', - 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', 'Topic :: Scientific/Engineering :: Physics', 'Topic :: Scientific/Engineering :: Chemistry', ] From d79aedc47f585df819a5f043adab1b3f217300eb Mon Sep 17 00:00:00 2001 From: stevenhua0320 Date: Tue, 20 Jan 2026 23:42:03 -0500 Subject: [PATCH 5/5] fix: fix name of requirements of file so that could be detected by workflow --- requirements/{test.txt => tests.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename requirements/{test.txt => tests.txt} (100%) diff --git a/requirements/test.txt b/requirements/tests.txt similarity index 100% rename from requirements/test.txt rename to requirements/tests.txt