Compare commits

..

160 Commits

Author SHA1 Message Date
ton 19d2a6dc9e update 2026-09-05 21:15:34 +07:00
ton 23b23cca9a update 2026-09-05 13:22:21 +07:00
ton 046d3ce4e6 up version 2026-09-05 12:08:24 +07:00
ton 4f79b444d2 Merge pull request 'V0.6.10 garage presigned url' (#15) from v0.6.10-Garage_presigned_url into v0.6.10
Reviewed-on: #15
2026-09-05 05:04:51 +00:00
ton 599765d7ef update 2026-09-05 10:27:31 +07:00
ton 9ad732c436 update 2026-09-05 10:00:36 +07:00
ton 25ca9b96a2 update 2026-09-04 14:05:36 +07:00
ton 2827d22616 update 2026-09-04 13:58:28 +07:00
ton 151e4e74cf update 2026-09-01 14:35:57 +07:00
ton 42b66366ae update 2026-09-01 12:21:17 +07:00
ton b0761fae75 update 2026-09-01 12:21:02 +07:00
ton f9e952e5ed update 2026-09-01 12:06:41 +07:00
ton 397885511a add eventSink 2026-09-01 12:03:50 +07:00
ton ee8ade1189 update 2026-08-31 15:52:40 +07:00
ton 20c51cf39f update 2026-08-30 10:46:39 +07:00
ton f09a53b6c3 update 2026-08-29 19:25:04 +07:00
ton c078948a7c update 2026-08-29 19:12:14 +07:00
ton 3780eb41df update 2026-08-29 18:47:45 +07:00
ton c28b7ebf84 Merge pull request 'V0.6.2' (#14) from v0.6.2 into main
Reviewed-on: #14
2026-08-29 02:58:21 +00:00
ton 27fd52fa71 Merge pull request 'V0.6.2 fix precompile' (#13) from v0.6.2-fix_precompile into v0.6.2
Reviewed-on: #13
2026-08-29 02:56:16 +00:00
ton f88656172c object lifecycle works 2026-08-29 09:52:33 +07:00
ton 5c1b70107a slash works 2026-08-29 09:24:30 +07:00
ton 2b2b7a378e works 2026-08-29 09:00:21 +07:00
ton 3fb7457f61 1st commit 2026-08-29 08:22:46 +07:00
ton 1fc0f790d9 update 2026-08-28 19:48:29 +07:00
ton a559824faa update 2026-08-28 18:40:33 +07:00
ton d74635c47a update 2026-08-28 18:33:21 +07:00
ton 9d6a943503 update 2026-08-28 14:34:55 +07:00
ton c1c83eba77 update 2026-08-28 14:31:26 +07:00
ton dee5649254 update 2026-08-28 14:23:18 +07:00
ton fc62098071 update 2026-08-28 12:49:38 +07:00
ton 99996c1b04 update 2026-08-28 11:08:34 +07:00
ton 4466320927 update 2026-08-28 08:30:46 +07:00
ton ff757c19dd update 2026-08-28 08:29:07 +07:00
ton c4741140f5 update 2026-08-28 08:28:35 +07:00
ton 27703c3324 update docs 2026-08-28 08:25:21 +07:00
ton 86b8582584 update 2026-08-28 07:52:07 +07:00
ton 32cd21e1ee update 2026-08-28 07:47:12 +07:00
ton 517a08365d update 2026-08-27 20:47:33 +07:00
ton d032cec0b2 fix garageS3 2026-08-27 20:46:23 +07:00
ton 64575d81b5 add garageS3 feature 2026-08-27 19:40:21 +07:00
ton fb54fddf10 update 2026-08-25 16:51:04 +07:00
ton 407447831a update 2026-07-24 20:23:54 +07:00
ton c475eb169c update 2026-07-24 20:12:54 +07:00
ton d1a279cca2 update 2026-07-24 20:09:21 +07:00
ton bf3b65ee7b update 2026-07-24 17:35:31 +07:00
ton 360d64c474 update 2026-07-24 16:42:23 +07:00
ton 41a354fa73 update 2026-07-24 15:34:02 +07:00
ton 801596fa7f update 2026-07-24 14:32:44 +07:00
ton 2fbe9d6e1a update 2026-07-24 13:21:04 +07:00
ton 2c2690e5dd update 2026-07-24 13:18:35 +07:00
ton 95db5f877d up version 2026-07-24 13:04:04 +07:00
ton 7e2ddd846e update 2026-07-24 13:03:40 +07:00
ton ab113acde5 up version 2026-07-24 12:45:55 +07:00
ton 7391f0f2ce add execute_postgres_sql 2026-07-24 12:45:14 +07:00
ton 01f4e52c64 Merge pull request 'v0.5.0-add_llmutils' (#12) from v0.5.0-add_llmutils into main
Reviewed-on: #12
2026-07-15 09:21:25 +00:00
ton 35acfe5b70 update 2026-07-15 16:21:03 +07:00
ton e1ebbf370e update 2026-07-15 15:55:20 +07:00
ton 1fd3fa1bee update 2026-07-15 15:50:09 +07:00
ton 9721a393bc update 2026-07-15 15:49:34 +07:00
ton 1db8e4e383 Merge pull request 'v0.5.0' (#11) from v0.5.0 into main
Reviewed-on: #11
2026-07-15 04:23:05 +00:00
ton c51dfc549c Merge pull request 'up version' (#10) from v0.5.0-add_llmutils into v0.5.0
Reviewed-on: #10
2026-07-15 04:22:51 +00:00
ton f0ad6a3e48 up version 2026-07-15 11:22:24 +07:00
ton 07d5d0f885 Merge pull request 'v0.5.0' (#9) from v0.5.0 into main
Reviewed-on: #9
2026-07-15 04:21:03 +00:00
ton c829bf65f6 Merge pull request 'v0.5.0-add_llmutils' (#8) from v0.5.0-add_llmutils into v0.5.0
Reviewed-on: #8
2026-07-15 04:20:13 +00:00
ton b09efc9068 update 2026-07-15 11:16:30 +07:00
ton 6fb2d5f82b update 2026-07-15 08:29:21 +07:00
ton 55cc0f78c9 update 2026-07-15 07:49:21 +07:00
ton 73ec3bbb04 update 2026-07-15 07:19:01 +07:00
ton 1ad46c6e18 update 2026-07-15 07:11:09 +07:00
ton 95954249ce update 2026-07-14 18:13:31 +07:00
ton a15630619a update 2026-07-14 13:00:39 +07:00
ton f28405f3f1 update 2026-07-13 21:23:21 +07:00
ton d658d9a25b update 2026-07-13 21:22:38 +07:00
ton edad442242 update 2026-07-13 21:06:09 +07:00
ton c56fc7366c update 2026-07-13 10:24:29 +07:00
ton c4eeb99aba update 2026-07-12 10:48:01 +07:00
ton bd5022c8bc update compat 2026-07-05 17:37:41 +07:00
ton db84b1c398 update 2026-07-05 07:05:11 +07:00
ton f8f8410259 fix clean json 2026-07-04 09:09:56 +07:00
ton 956adf0b93 update 2026-07-03 20:54:16 +07:00
ton 0f2a33bcdd update 2026-07-03 20:30:24 +07:00
ton b8f84846bb update 2026-07-03 18:33:45 +07:00
ton adf6264061 fix dictify 2026-07-03 18:32:41 +07:00
ton 08f19f17a2 fix clean json response 2026-07-03 12:24:40 +07:00
ton 8a4e882dc1 add new func() 2026-06-30 22:02:17 +07:00
ton fb7942a965 add new function 2026-06-30 21:02:25 +07:00
ton e54454b099 update 2026-06-27 17:16:21 +07:00
ton dac98ab38c update 2026-06-27 17:15:36 +07:00
ton 1e8149aa6f update 2026-06-27 17:09:27 +07:00
ton 8f12c29a78 update 2026-06-27 16:53:55 +07:00
ton e3d09e6ebd update docs 2026-06-27 16:00:31 +07:00
ton f33f4f0790 up version 2026-06-24 12:55:40 +07:00
ton fcf2044dd9 Merge pull request 'update' (#7) from v0.4.0-dictify_key into main
Reviewed-on: #7
2026-06-24 05:33:31 +00:00
ton 05d8cb9c02 update 2026-06-24 12:29:01 +07:00
ton 13de2f90ff update 2026-06-07 17:22:24 +07:00
ton 22fe810f63 update 2026-06-07 17:20:52 +07:00
ton abdf6cf3b8 Merge pull request 'update' (#6) from add_generateupdateSQL into main
Reviewed-on: #6
2026-06-07 09:32:41 +00:00
ton f2ba243df0 update 2026-06-07 16:27:08 +07:00
ton bb2851332a Merge pull request 'update' (#5) from add_generateupdateSQL into main
Reviewed-on: #5
2026-06-07 09:20:55 +00:00
ton 00225f3a06 update 2026-06-07 16:16:52 +07:00
ton 7cb0bd077f Merge pull request 'update' (#4) from add_generateupdateSQL into main
Reviewed-on: #4
2026-06-07 09:04:33 +00:00
ton 0ba2aa310e update 2026-06-07 15:32:49 +07:00
ton 1916668c6e Merge pull request 'add_generateupdateSQL' (#3) from add_generateupdateSQL into main
Reviewed-on: #3
2026-06-07 06:57:28 +00:00
ton 919800da42 add generateUpdateSQL 2026-06-07 13:56:07 +07:00
ton 947580a2ec update 2026-06-07 13:46:04 +07:00
ton 688b9a22b6 add generateUpdateSQL 2026-06-07 13:43:47 +07:00
ton 76ce0fc54f Merge pull request 'usability' (#2) from usability into main
Reviewed-on: #2
2026-05-29 04:17:51 +00:00
ton b8bd06f386 update generateUpdateSQL 2026-05-29 11:16:34 +07:00
ton e08b6ab54d update 2026-02-28 11:40:35 +07:00
ton 830e9bcc5f update 2026-02-22 18:24:52 +07:00
ton 52d991bbf3 Merge pull request 'v0.3.1' (#1) from v0.3.1 into main
Reviewed-on: #1
2025-12-17 05:43:32 +00:00
ton 35c2b4c211 use JSON instead of JSON3 2025-12-17 12:39:18 +07:00
ton 170b0bad15 update 2025-11-22 10:45:08 +07:00
ton fbedd507fc update 2025-11-22 09:05:06 +07:00
ton 0e36b8db90 remove MQTT dependency 2025-08-01 06:04:17 +07:00
ton 13fcf06503 update 2025-07-23 07:10:28 +07:00
narawat lamaiin 066d72553f update 2025-07-18 07:54:50 +07:00
narawat lamaiin b3e8df7287 update 2025-07-17 11:48:16 +07:00
narawat lamaiin c5f3fda2ba update 2025-07-14 13:49:04 +07:00
narawat lamaiin adab61dca8 update 2025-07-14 08:54:46 +07:00
narawat lamaiin 09615a6909 mark new version 2025-06-10 10:49:11 +07:00
ton 92c5930e9a Merge pull request 'v0.3.0' (#6) from v0.3.0 into main
Reviewed-on: #6
2025-06-10 03:39:42 +00:00
narawat lamaiin 5b4c1c1471 update 2025-06-10 10:38:51 +07:00
narawat lamaiin fc3edd7b8f update 2025-06-10 10:29:57 +07:00
narawat lamaiin 93aa0ee1ac update 2025-06-10 10:16:31 +07:00
narawat lamaiin 42378714a0 mark new version 2025-06-10 09:31:00 +07:00
ton 759f022c98 Merge pull request 'v0.2.4' (#5) from v0.2.4 into main
Reviewed-on: #5
2025-06-10 02:27:09 +00:00
narawat lamaiin 5af4d481f2 update 2025-06-10 09:25:41 +07:00
narawat lamaiin 221bb5beb7 update 2025-06-09 06:34:29 +07:00
narawat lamaiin 5a89e86120 update 2025-06-03 10:08:40 +07:00
narawat lamaiin e351a92680 mark new version 2025-05-24 08:52:50 +07:00
ton 83cd0cfea3 Merge pull request 'v0.2.3' (#4) from v0.2.3 into main
Reviewed-on: #4
2025-05-24 01:47:53 +00:00
narawat lamaiin 9e29f611df update 2025-05-24 08:42:50 +07:00
narawat lamaiin d8ea4b70a9 update 2025-05-04 20:56:36 +07:00
narawat lamaiin 150ddac2c0 add extractTextBetweenString 2025-04-30 12:59:14 +07:00
narawat lamaiin 5108ad1f6b update 2025-04-25 21:12:14 +07:00
narawat lamaiin 14766ae171 update 2025-04-13 21:45:47 +07:00
narawat lamaiin ccd91a7b6f update 2025-04-07 05:20:05 +07:00
narawat lamaiin a894ad85ba update 2025-04-04 15:04:19 +07:00
narawat lamaiin 1da05f5cae update 2025-03-31 21:30:29 +07:00
narawat lamaiin 562f528c01 update 2025-03-27 13:09:20 +07:00
narawat lamaiin 840b0e6205 update 2025-03-22 09:41:39 +07:00
tonaerospace cb4d01c612 update 2025-03-20 16:05:39 +07:00
tonaerospace e6344f1a92 mark new version 2025-03-17 09:54:32 +07:00
ton 3082c261c7 Merge pull request 'v0.2.2' (#3) from v0.2.2 into main
Reviewed-on: #3
2025-03-14 12:17:37 +00:00
tonaerospace abf1966b95 update 2025-03-14 19:15:13 +07:00
tonaerospace d163105d93 update 2025-03-14 18:45:44 +07:00
tonaerospace 092215c3be update 2025-03-14 05:07:14 +07:00
tonaerospace d521bafd43 update 2025-03-14 04:41:53 +07:00
tonaerospace 491eb8fd31 update 2025-03-12 14:34:14 +07:00
tonaerospace a35cb48bef update 2025-03-12 14:09:13 +07:00
tonaerospace 512fa4fd9d update 2025-03-11 00:14:51 +07:00
tonaerospace 25385c0798 update 2025-03-10 09:13:45 +07:00
tonaerospace fa33531d5f update 2025-03-09 22:06:33 +07:00
narawat lamaiin ce1af8b382 update 2025-03-07 12:33:13 +07:00
narawat lamaiin e8bee5c9db update 2025-03-07 08:23:36 +07:00
narawat lamaiin 8ce9aece1a update 2025-03-02 12:12:15 +07:00
narawat lamaiin 8b6d73f65e mark new version 2025-03-02 08:29:31 +07:00
ton 6fb1c6dbff Merge pull request 'WIP v0.2.1-dev' (#2) from v0.2.1-dev into main
Reviewed-on: #2
2025-01-25 07:39:23 +00:00
40 changed files with 5781 additions and 7337 deletions
+41
View File
@@ -0,0 +1,41 @@
# 1. Garage Web Admin UI
garage-ui.yiem.cc {
reverse_proxy 192.168.88.106:3909
}
# 2. Garage S3 API (Path-Style & Single Domain)
s3-api.yiem.cc {
# CORS: handle OPTIONS preflight
@options method OPTIONS {
header Access-Control-Request-Method *
}
handle @options {
respond * 204
}
# CORS headers on all responses
header {
Access-Control-Allow-Origin "*"
Access-Control-Allow-Methods "GET, PUT, POST, DELETE, OPTIONS"
Access-Control-Allow-Headers "*"
Access-Control-Max-Age "86400"
}
reverse_proxy 192.168.88.106:3900 {
header_up Host {host}
}
}
# 3. Garage S3 WEB (Path-Style & Single Domain)
s3-web.yiem.cc {
# /bucket -> /bucket/
@bucket_root path_regexp bucket_root ^/([^/]+)$
redir @bucket_root /{http.regexp.bucket_root.1}/ 301
# /bucket/... -> Garage
@bucket path_regexp bucket ^/([^/]+)(/.*)?$
rewrite @bucket {http.regexp.bucket.2}
reverse_proxy 192.168.88.106:3902 {
header_up Host {http.regexp.bucket.1}.s3-web.yiem.cc
}
}
+675 -145
View File
File diff suppressed because it is too large Load Diff
+30 -4
View File
@@ -1,17 +1,43 @@
name = "GeneralUtils" name = "GeneralUtils"
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe" uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
authors = ["tonaerospace <tonaerospace.etc@gmail.com>"] version = "0.6.10"
version = "0.2.1" authors = ["tonaerospace <tonaerospace.etc@gmail.com"]
[deps] [deps]
AWS = "fbe9abb3-538b-5e4e-ba9e-bc94f4f92ebc"
AWSS3 = "1c724243-ef5b-51ab-93f4-b0a88ac62a95"
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1" Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
MQTTClient = "985f35cc-2c3d-4943-b8c1-f0931d5f0959" HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
LibPQ = "194296ae-ab2e-5f79-8cd4-7183a0a5a0d1"
MbedTLS = "739be429-bea8-5141-9913-cc70e7f3736d"
NATS = "55e73f9c-eeeb-467f-b4cc-a633fde63d2a"
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
PrettyPrinting = "54e16d92-306c-5ea0-a30b-337be88ac337" PrettyPrinting = "54e16d92-306c-5ea0-a30b-337be88ac337"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce"
StringDistances = "88034a9c-02f8-509d-84a9-84ec65e18404"
URIs = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[compat]
AWS = "1.99.0"
AWSS3 = "0.11.6"
Base64 = "1.11.0"
Graphs = "1.14.0"
HTTP = "2.5.0 - 2.9.9"
JSON = "1.3.0 - 1.9.9"
LibPQ = "1.18.0"
MbedTLS = "1.1.10"
NATS = "0.1.0"
OrderedCollections = "2.0.1"
Revise = "3.13.2"
StringDistances = "1.0.0"
URIs = "1.7.0"
+5
View File
@@ -0,0 +1,5 @@
Todo:
- [WORKING] update with JSON
Change from previous version:
- replace JSON3 with JSON
+79
View File
@@ -0,0 +1,79 @@
using NATS, JSON3
connection = NATS.connect("nats.yiem.cc:4222")
sub1 = NATS.reply(connection, "some_subject"; queue_group="group1") do msg
payload = copy(JSON3.read(msg.payload))
println(payload)
println(msg.reply_to)
# publish(connection, msg.reply_to, "ACK")
return JSON3.write(Dict(:a=>"wassup"))
end
using NATS, JSON3, GeneralUtils
connection = NATS.connect("nats.yiem.cc:4222")
msgMeta = GeneralUtils.generate_msgMeta(
"text2textinstruct_medium.inference.api.v1";
msgPurpose= "inference",
senderName= "yiemagent",
senderId= GeneralUtils.uuid4snakecase(),
receiverName= "text2textinstruct",
)
llmHttpTimeout = 60
outgoingMsg = Dict(
:msgMeta=> msgMeta,
:payload=> Dict(
:text=> "Wassup buddy!",
:kwargs=> Dict(
:max_tokens=> 2048,
:stop=> ["<|im_end|>"],
:temperature=> 0.2,
),
:llmHttpTimeout=>llmHttpTimeout,
)
)
r = NATS.request(String, connection, "text2textinstruct_medium.inference.api.v1",
JSON3.write(outgoingMsg); timer=Timer(llmHttpTimeout))
using NATS, JSON3, GeneralUtils
connection = NATS.connect("nats.yiem.cc:4222")
msgMeta = GeneralUtils.generate_msgMeta(
"tonpc.containerServices",
msgPurpose="reset container",
senderName= "",
)
outgoingMsg = Dict(
:msgMeta=> msgMeta,
:payload=> "docker container restart ollama-instance-2",
)
# may be I can't use NATS request inside NATS reply??
r = NATS.request(String, connection, msgMeta[:sendTopic], JSON3.write(outgoingMsg); timer=Timer(10))
BIN
View File
Binary file not shown.
+52
View File
@@ -0,0 +1,52 @@
# ==========================================
# Garage Storage Engine Configuration
# ==========================================
# Core storage directories
metadata_dir = "/var/lib/garage/meta"
data_dir = "/var/lib/garage/data"
# LMDB is recommended for production performance
db_engine = "lmdb"
metadata_auto_snapshot_interval = "6h"
# Multi-node ready setup:
# Set to 1 for initial single node. Update to 3 when adding Node 2 and Node 3 later.
replication_factor = 1
compression_level = 2
# ==========================================
# Network & Node Identity Configuration
# ==========================================
# Bind to all interfaces for host network mode
rpc_bind_addr = "[::]:3901"
# IMPORTANT: Set to Node 1's publicly reachable IP or DNS name (e.g., 192.168.1.10:3901 or 203.0.113.10:3901)
rpc_public_addr = "192.168.88.106:3901"
# Generate with: openssl rand -hex 32 (MUST BE IDENTICAL ON ALL NODES IN CLUSTER)
rpc_secret = "3cf7a4d1da5d7b024a06db7fe6d73e2c160c6de640fda69b0b964d98678155a7"
# ==========================================
# Service APIs
# ==========================================
[s3_api]
s3_region = "garage"
api_bind_addr = "0.0.0.0:3900"
root_domain = ".s3-api.yiem.cc"
[s3_web]
bind_addr = "0.0.0.0:3902"
root_domain = ".s3-web.yiem.cc"
index = "index.html"
[k2v_api]
api_bind_addr = "0.0.0.0:3904"
[admin]
api_bind_addr = "0.0.0.0:3903"
# Generate with: openssl rand -hex 16
admin_token = "fd92f47a7c1ce8b072b06bb19dbc3fef"
metrics_token = "27d29618cc436a23ec7d842392fdf74b"
+48
View File
@@ -0,0 +1,48 @@
services:
garage:
image: dxflrs/garage:v2.3.0
container_name: garage
restart: unless-stopped
network_mode: "host"
volumes:
- ./garage.toml:/etc/garage.toml:ro
- garage_meta:/var/lib/garage/meta
- garage_data:/var/lib/garage/data
environment:
- RUST_LOG=garage=trace
healthcheck:
test: ["CMD", "/garage", "status"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
webui:
image: khairul169/garage-webui:latest
container_name: garage-webui
restart: unless-stopped
network_mode: "host"
volumes:
- ./garage.toml:/etc/garage.toml:ro
environment:
API_BASE_URL: "http://127.0.0.1:3903"
S3_ENDPOINT_URL: "https://s3-api.yiem.cc"
# Format: "username:bcrypt_hash" (generate via: htpasswd -nbBC 10 "admin" "yourpassword")
AUTH_USER_PASS: "admin:$$2y$$10$$fhEucJHW8N5p8NL7Gv4Bi.FZVngbq/zatVDCjl.V.xNtj5q1PNUZW"
depends_on:
garage:
condition: service_healthy
volumes:
garage_meta:
driver: local
driver_opts:
type: none
o: bind
device: ./data/meta
garage_data:
driver: local
driver_opts:
type: none
o: bind
device: ./data/storage
+2
View File
@@ -0,0 +1,2 @@
# dummy main.jl so i can do GeneralUtils precompile
using GeneralUtils
+147
View File
@@ -0,0 +1,147 @@
This is my frontend code folder: /home/ton/docker-apps/sommpanion/agent-frontend/
Log from my frontend browser console:
[NATS] Requesting from: sommpanion.5c1c85ad_44f8_49a7_a9a5_b7a7dface0db.agentBackend.v1.inbox payload: {"correlation_id":"5c1c85ad-44f8-49a7-a9a5-b7a7dface0db","msg_id":"FCA61ED2C63C4EDBB179378CEA010421","timestamp":"2026-09-05T11:44:52.208Z","send_to":"sommpanion.5c1c85ad_44f8_49a7_a9a5_b7a7dface0db.agentBackend.v1.inbox","msg_purpose":"chat","sender_name":"chat-webapp","sender_id":"5c1c85ad-44f8-49a7-a9a5-b7a7dface0db","receiver_name":"","receiver_id":"","reply_to":"sommpanion.frontend.agentfrontend.v1.inbox.5c1c85ad-44f8-49a7-a9a5-b7a7dface0db","reply_to_msg_id":"","broker_url":"wss://natsws.yiem.cc","metadata":{},"payloads":[{"id":"25F52E33F1284B58B4D76454C4DA2E96","dataname":"msg","payload_type":"dictionary","transport":"direct","encoding":"base64","size":97,"data":"eyJyb2xlIjoidXNlciIsImNvbnRlbnQiOlt7InR5cGUiOiJ0ZXh0IiwidGV4dCI6ImRvIHlvdSBoYXZlIHJlZCB3aW5lIGZyb20gRnJhbmNlIHVuZGVyIDEwMDA/In1dfQ==","metadata":{"payload_bytes":97}}]}
natsClient.js:44 [NATS] Status event: pingTimer 1
natsClient.js:174 [NATS] Request response: {broker_url: 'nats.yiem.cc', correlation_id: 'b9ebec8b-a4e3-432e-895d-8a099d92a5d1', metadata: {…}, msg_id: '860671db_fb1b_456f_a00f_c787c915e208', msg_purpose: 'chat', …}broker_url: "nats.yiem.cc"correlation_id: "b9ebec8b-a4e3-432e-895d-8a099d92a5d1"metadata: [[Prototype]]: Objectmsg_id: "860671db_fb1b_456f_a00f_c787c915e208"msg_purpose: "chat"payloads: Array(1)0: data: "https://s3-api.yiem.cc/sommpanion/reply?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T114737Z&X-Amz-SignedHeaders=host&X-Amz-Signature=d5249d804b46114baf6e6436e2f8d8a22bc362422373a601de03ce8606edbbbf"dataname: "reply"encoding: "none"id: "13e9a0c4-fc4c-4d95-a9e0-6a9ae1f8219d"payload_type: "dictionary"size: 162786transport: "link"[[Prototype]]: Objectconstructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()__proto__: (...)get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()length: 1[[Prototype]]: Array(0)at: ƒ at()concat: ƒ concat()constructor: ƒ Array()copyWithin: ƒ copyWithin()entries: ƒ entries()every: ƒ every()fill: ƒ fill()filter: ƒ filter()find: ƒ find()findIndex: ƒ findIndex()findLast: ƒ findLast()findLastIndex: ƒ findLastIndex()flat: ƒ flat()flatMap: ƒ flatMap()forEach: ƒ forEach()includes: ƒ (item, from_index)indexOf: ƒ (item, from_index)join: ƒ join()keys: ƒ keys()lastIndexOf: ƒ (item, from_index)length: 0map: ƒ map()pop: ƒ pop()push: ƒ push()reduce: ƒ reduce()reduceRight: ƒ reduceRight()reverse: ƒ reverse()shift: ƒ shift()slice: ƒ slice()some: ƒ some()sort: ƒ sort()splice: ƒ splice()toLocaleString: ƒ toLocaleString()toReversed: ƒ toReversed()toSorted: ƒ toSorted()toSpliced: ƒ toSpliced()toString: ƒ toString()unshift: ƒ unshift()values: ƒ values()with: ƒ with()Symbol(Symbol.iterator): ƒ values()Symbol(Symbol.unscopables): {at: true, copyWithin: true, entries: true, fill: true, find: true, …}[[Prototype]]: Objectreceiver_id: ""receiver_name: ""reply_to: ""reply_to_msg_id: "FCA61ED2C63C4EDBB179378CEA010421"send_to: "_INBOX.P79XUSKPYH9E88Z9RM5QA1.P79XUSKPYH9E88Z9RM5QIN"sender_id: "828ef5e5-5d8e-47e2-8c48-736d99375af7"sender_name: "sommpanion_agent_backend"timestamp: "2026-09-05T18:47:37.858"[[Prototype]]: Object
msghandler-csr.js:95 [2026-09-05T11:47:36.857Z] [Correlation: b9ebec8b-a4e3-432e-895d-8a099d92a5d1] Processing received message
msghandler-csr.js:95 [2026-09-05T11:47:36.857Z] [Correlation: b9ebec8b-a4e3-432e-895d-8a099d92a5d1] smartunpack: envelope has 1 payloads
msghandler-csr.js:95 [2026-09-05T11:47:36.857Z] [Correlation: b9ebec8b-a4e3-432e-895d-8a099d92a5d1] smartunpack: Processing 1 payloads
msghandler-csr.js:95 [2026-09-05T11:47:36.858Z] [Correlation: b9ebec8b-a4e3-432e-895d-8a099d92a5d1] smartunpack: Processing payload 1/1: dataname=reply, type=dictionary, transport=link
msghandler-csr.js:95 [2026-09-05T11:47:36.858Z] [Correlation: b9ebec8b-a4e3-432e-895d-8a099d92a5d1] Link transport - fetching 'reply' from URL: https://s3-api.yiem.cc/sommpanion/reply?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T114737Z&X-Amz-SignedHeaders=host&X-Amz-Signature=d5249d804b46114baf6e6436e2f8d8a22bc362422373a601de03ce8606edbbbf
:5173/#chat:1 Access to fetch at 'https://s3-api.yiem.cc/sommpanion/reply?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T114737Z&X-Amz-SignedHeaders=host&X-Amz-Signature=d5249d804b46114baf6e6436e2f8d8a22bc362422373a601de03ce8606edbbbf' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
msghandler-csr.js:274 GET https://s3-api.yiem.cc/sommpanion/reply?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T114737Z&X-Amz-SignedHeaders=host&X-Amz-Signature=d5249d804b46114baf6e6436e2f8d8a22bc362422373a601de03ce8606edbbbf net::ERR_FAILED 200 (OK)
fetchWithBackoff @ msghandler-csr.js:274
smartunpack @ msghandler-csr.js:582
processIncomingMessage @ Chat.svelte:136
handleSend @ Chat.svelte:301
await in handleSend
handleSend @ ChatInput.svelte:21
handleKeydown @ ChatInput.svelte:34
handle_event_propagation @ events.js:278
msghandler-csr.js:95 [2026-09-05T11:47:36.962Z] [Correlation: b9ebec8b-a4e3-432e-895d-8a099d92a5d1] Attempt 1 failed: TypeError - Failed to fetch
:5173/#chat:1 Access to fetch at 'https://s3-api.yiem.cc/sommpanion/reply?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T114737Z&X-Amz-SignedHeaders=host&X-Amz-Signature=d5249d804b46114baf6e6436e2f8d8a22bc362422373a601de03ce8606edbbbf' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
msghandler-csr.js:274 GET https://s3-api.yiem.cc/sommpanion/reply?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T114737Z&X-Amz-SignedHeaders=host&X-Amz-Signature=d5249d804b46114baf6e6436e2f8d8a22bc362422373a601de03ce8606edbbbf net::ERR_FAILED 200 (OK)
fetchWithBackoff @ msghandler-csr.js:274
await in fetchWithBackoff
smartunpack @ msghandler-csr.js:582
processIncomingMessage @ Chat.svelte:136
handleSend @ Chat.svelte:301
await in handleSend
handleSend @ ChatInput.svelte:21
handleKeydown @ ChatInput.svelte:34
handle_event_propagation @ events.js:278
msghandler-csr.js:95 [2026-09-05T11:47:37.110Z] [Correlation: b9ebec8b-a4e3-432e-895d-8a099d92a5d1] Attempt 2 failed: TypeError - Failed to fetch
:5173/#chat:1 Access to fetch at 'https://s3-api.yiem.cc/sommpanion/reply?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T114737Z&X-Amz-SignedHeaders=host&X-Amz-Signature=d5249d804b46114baf6e6436e2f8d8a22bc362422373a601de03ce8606edbbbf' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
msghandler-csr.js:274 GET https://s3-api.yiem.cc/sommpanion/reply?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T114737Z&X-Amz-SignedHeaders=host&X-Amz-Signature=d5249d804b46114baf6e6436e2f8d8a22bc362422373a601de03ce8606edbbbf net::ERR_FAILED 200 (OK)
fetchWithBackoff @ msghandler-csr.js:274
await in fetchWithBackoff
smartunpack @ msghandler-csr.js:582
processIncomingMessage @ Chat.svelte:136
handleSend @ Chat.svelte:301
await in handleSend
handleSend @ ChatInput.svelte:21
handleKeydown @ ChatInput.svelte:34
handle_event_propagation @ events.js:278
msghandler-csr.js:95 [2026-09-05T11:47:37.359Z] [Correlation: b9ebec8b-a4e3-432e-895d-8a099d92a5d1] Attempt 3 failed: TypeError - Failed to fetch
:5173/#chat:1 Access to fetch at 'https://s3-api.yiem.cc/sommpanion/reply?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T114737Z&X-Amz-SignedHeaders=host&X-Amz-Signature=d5249d804b46114baf6e6436e2f8d8a22bc362422373a601de03ce8606edbbbf' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
msghandler-csr.js:274 GET https://s3-api.yiem.cc/sommpanion/reply?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T114737Z&X-Amz-SignedHeaders=host&X-Amz-Signature=d5249d804b46114baf6e6436e2f8d8a22bc362422373a601de03ce8606edbbbf net::ERR_FAILED 200 (OK)
fetchWithBackoff @ msghandler-csr.js:274
await in fetchWithBackoff
smartunpack @ msghandler-csr.js:582
processIncomingMessage @ Chat.svelte:136
handleSend @ Chat.svelte:301
await in handleSend
handleSend @ ChatInput.svelte:21
handleKeydown @ ChatInput.svelte:34
handle_event_propagation @ events.js:278
msghandler-csr.js:95 [2026-09-05T11:47:37.801Z] [Correlation: b9ebec8b-a4e3-432e-895d-8a099d92a5d1] Attempt 4 failed: TypeError - Failed to fetch
:5173/#chat:1 Access to fetch at 'https://s3-api.yiem.cc/sommpanion/reply?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T114737Z&X-Amz-SignedHeaders=host&X-Amz-Signature=d5249d804b46114baf6e6436e2f8d8a22bc362422373a601de03ce8606edbbbf' from origin 'http://localhost:5173' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
msghandler-csr.js:274 GET https://s3-api.yiem.cc/sommpanion/reply?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T114737Z&X-Amz-SignedHeaders=host&X-Amz-Signature=d5249d804b46114baf6e6436e2f8d8a22bc362422373a601de03ce8606edbbbf net::ERR_FAILED 200 (OK)
fetchWithBackoff @ msghandler-csr.js:274
await in fetchWithBackoff
smartunpack @ msghandler-csr.js:582
processIncomingMessage @ Chat.svelte:136
handleSend @ Chat.svelte:301
await in handleSend
handleSend @ ChatInput.svelte:21
handleKeydown @ ChatInput.svelte:34
handle_event_propagation @ events.js:278
msghandler-csr.js:95 [2026-09-05T11:47:38.641Z] [Correlation: b9ebec8b-a4e3-432e-895d-8a099d92a5d1] Attempt 5 failed: TypeError - Failed to fetch
Chat.svelte:162 Failed to process incoming message Error: Failed to fetch data after 5 attempts
at fetchWithBackoff (msghandler-csr.js:293:11)
at async Object.smartunpack (msghandler-csr.js:582:36)
at async Module.track_reactivity_loss (async.js:179:14)
at async processIncomingMessage (Chat.svelte:136:12)
Here is my backend log folder:
/home/ton/docker-apps/sommpanion/agent-backend/log/
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 429 KiB

-911
View File
@@ -1,911 +0,0 @@
# This file is machine-generated - editing it directly is not advised
julia_version = "1.9.1"
manifest_format = "2.0"
project_hash = "91349a0eb57aed703e8465e44731cca768229f09"
[[deps.AbstractFFTs]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "8bc0aaec0ca548eb6cf5f0d7d16351650c1ee956"
uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c"
version = "1.3.2"
weakdeps = ["ChainRulesCore"]
[deps.AbstractFFTs.extensions]
AbstractFFTsChainRulesCoreExt = "ChainRulesCore"
[[deps.Adapt]]
deps = ["LinearAlgebra", "Requires"]
git-tree-sha1 = "76289dc51920fdc6e0013c872ba9551d54961c24"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.6.2"
weakdeps = ["StaticArrays"]
[deps.Adapt.extensions]
AdaptStaticArraysExt = "StaticArrays"
[[deps.ArgCheck]]
git-tree-sha1 = "a3a402a35a2f7e0b87828ccabbd5ebfbebe356b4"
uuid = "dce04be8-c92d-5529-be00-80e4d2c0e197"
version = "2.3.0"
[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
version = "1.1.1"
[[deps.Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
[[deps.Atomix]]
deps = ["UnsafeAtomics"]
git-tree-sha1 = "c06a868224ecba914baa6942988e2f2aade419be"
uuid = "a9b6321e-bd34-4604-b9c9-b65b8de01458"
version = "0.1.0"
[[deps.BFloat16s]]
deps = ["LinearAlgebra", "Printf", "Random", "Test"]
git-tree-sha1 = "dbf84058d0a8cbbadee18d25cf606934b22d7c66"
uuid = "ab4f0b2a-ad5b-11e8-123f-65d77653426b"
version = "0.4.2"
[[deps.BangBang]]
deps = ["Compat", "ConstructionBase", "InitialValues", "LinearAlgebra", "Requires", "Setfield", "Tables"]
git-tree-sha1 = "e28912ce94077686443433c2800104b061a827ed"
uuid = "198e06fe-97b7-11e9-32a5-e1d131e6ad66"
version = "0.3.39"
[deps.BangBang.extensions]
BangBangChainRulesCoreExt = "ChainRulesCore"
BangBangDataFramesExt = "DataFrames"
BangBangStaticArraysExt = "StaticArrays"
BangBangStructArraysExt = "StructArrays"
BangBangTypedTablesExt = "TypedTables"
[deps.BangBang.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
TypedTables = "9d95f2ec-7b3d-5a63-8d20-e2491e220bb9"
[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
[[deps.Baselet]]
git-tree-sha1 = "aebf55e6d7795e02ca500a689d326ac979aaf89e"
uuid = "9718e550-a3fa-408a-8086-8db961cd8217"
version = "0.1.1"
[[deps.CEnum]]
git-tree-sha1 = "eb4cb44a499229b3b8426dcfb5dd85333951ff90"
uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82"
version = "0.4.2"
[[deps.CUDA]]
deps = ["AbstractFFTs", "Adapt", "BFloat16s", "CEnum", "CUDA_Driver_jll", "CUDA_Runtime_Discovery", "CUDA_Runtime_jll", "CompilerSupportLibraries_jll", "ExprTools", "GPUArrays", "GPUCompiler", "KernelAbstractions", "LLVM", "LazyArtifacts", "Libdl", "LinearAlgebra", "Logging", "Preferences", "Printf", "Random", "Random123", "RandomNumbers", "Reexport", "Requires", "SparseArrays", "SpecialFunctions", "UnsafeAtomicsLLVM"]
git-tree-sha1 = "442d989978ed3ff4e174c928ee879dc09d1ef693"
uuid = "052768ef-5323-5732-b1bb-66c8b64840ba"
version = "4.3.2"
[[deps.CUDA_Driver_jll]]
deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"]
git-tree-sha1 = "498f45593f6ddc0adff64a9310bb6710e851781b"
uuid = "4ee394cb-3365-5eb0-8335-949819d2adfc"
version = "0.5.0+1"
[[deps.CUDA_Runtime_Discovery]]
deps = ["Libdl"]
git-tree-sha1 = "bcc4a23cbbd99c8535a5318455dcf0f2546ec536"
uuid = "1af6417a-86b4-443c-805f-a4643ffb695f"
version = "0.2.2"
[[deps.CUDA_Runtime_jll]]
deps = ["Artifacts", "CUDA_Driver_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "5248d9c45712e51e27ba9b30eebec65658c6ce29"
uuid = "76a88914-d11a-5bdc-97e0-2f5a05c973a2"
version = "0.6.0+0"
[[deps.CUDNN_jll]]
deps = ["Artifacts", "CUDA_Runtime_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "2918fbffb50e3b7a0b9127617587afa76d4276e8"
uuid = "62b44479-cb7b-5706-934f-f13b2eb2e645"
version = "8.8.1+0"
[[deps.Calculus]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad"
uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9"
version = "0.5.1"
[[deps.ChainRules]]
deps = ["Adapt", "ChainRulesCore", "Compat", "Distributed", "GPUArraysCore", "IrrationalConstants", "LinearAlgebra", "Random", "RealDot", "SparseArrays", "Statistics", "StructArrays"]
git-tree-sha1 = "1cdf290d4feec68824bfb84f4bfc9f3aba185647"
uuid = "082447d4-558c-5d27-93f4-14fc19e9eca2"
version = "1.51.1"
[[deps.ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "e30f2f4e20f7f186dc36529910beaedc60cfa644"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.16.0"
[[deps.CommonSubexpressions]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7"
uuid = "bbf7d656-a473-5ed7-a52c-81e309532950"
version = "0.3.0"
[[deps.Compat]]
deps = ["UUIDs"]
git-tree-sha1 = "7a60c856b9fa189eb34f5f8a6f6b5529b7942957"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "4.6.1"
weakdeps = ["Dates", "LinearAlgebra"]
[deps.Compat.extensions]
CompatLinearAlgebraExt = "LinearAlgebra"
[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
version = "1.0.2+0"
[[deps.CompositionsBase]]
git-tree-sha1 = "802bb88cd69dfd1509f6670416bd4434015693ad"
uuid = "a33af91c-f02d-484b-be07-31d278c5ca2b"
version = "0.1.2"
[deps.CompositionsBase.extensions]
CompositionsBaseInverseFunctionsExt = "InverseFunctions"
[deps.CompositionsBase.weakdeps]
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
[[deps.ConstructionBase]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "738fec4d684a9a6ee9598a8bfee305b26831f28c"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
version = "1.5.2"
[deps.ConstructionBase.extensions]
ConstructionBaseIntervalSetsExt = "IntervalSets"
ConstructionBaseStaticArraysExt = "StaticArrays"
[deps.ConstructionBase.weakdeps]
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
[[deps.ContextVariablesX]]
deps = ["Compat", "Logging", "UUIDs"]
git-tree-sha1 = "25cc3803f1030ab855e383129dcd3dc294e322cc"
uuid = "6add18c4-b38d-439d-96f6-d6bc489c04c5"
version = "0.1.3"
[[deps.DataAPI]]
git-tree-sha1 = "e8119c1a33d267e16108be441a287a6981ba1630"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.14.0"
[[deps.DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "d1fff3a548102f48987a52a2e0d114fa97d730f0"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.13"
[[deps.DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"
[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
[[deps.DefineSingletons]]
git-tree-sha1 = "0fba8b706d0178b4dc7fd44a96a92382c9065c2c"
uuid = "244e2a9f-e319-4986-a169-4d1fe445cd52"
version = "0.1.2"
[[deps.DelimitedFiles]]
deps = ["Mmap"]
git-tree-sha1 = "9e2f36d3c96a820c678f2f1f1782582fcf685bae"
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"
version = "1.9.1"
[[deps.DiffResults]]
deps = ["StaticArraysCore"]
git-tree-sha1 = "782dd5f4561f5d267313f23853baaaa4c52ea621"
uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5"
version = "1.1.0"
[[deps.DiffRules]]
deps = ["IrrationalConstants", "LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"]
git-tree-sha1 = "23163d55f885173722d1e4cf0f6110cdbaf7e272"
uuid = "b552c78f-8df3-52c6-915a-8e097449b14b"
version = "1.15.1"
[[deps.Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
[[deps.Distributions]]
deps = ["FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns", "Test"]
git-tree-sha1 = "eead66061583b6807652281c0fbf291d7a9dc497"
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
version = "0.25.90"
[deps.Distributions.extensions]
DistributionsChainRulesCoreExt = "ChainRulesCore"
DistributionsDensityInterfaceExt = "DensityInterface"
[deps.Distributions.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d"
[[deps.DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.9.3"
[[deps.Downloads]]
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
version = "1.6.0"
[[deps.DualNumbers]]
deps = ["Calculus", "NaNMath", "SpecialFunctions"]
git-tree-sha1 = "5837a837389fccf076445fce071c8ddaea35a566"
uuid = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74"
version = "0.6.8"
[[deps.ExprTools]]
git-tree-sha1 = "c1d06d129da9f55715c6c212866f5b1bddc5fa00"
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
version = "0.1.9"
[[deps.FLoops]]
deps = ["BangBang", "Compat", "FLoopsBase", "InitialValues", "JuliaVariables", "MLStyle", "Serialization", "Setfield", "Transducers"]
git-tree-sha1 = "ffb97765602e3cbe59a0589d237bf07f245a8576"
uuid = "cc61a311-1640-44b5-9fba-1b764f453329"
version = "0.2.1"
[[deps.FLoopsBase]]
deps = ["ContextVariablesX"]
git-tree-sha1 = "656f7a6859be8673bf1f35da5670246b923964f7"
uuid = "b9860ae5-e623-471e-878b-f6a53c775ea6"
version = "0.1.1"
[[deps.FileWatching]]
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
[[deps.FillArrays]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "Statistics"]
git-tree-sha1 = "fc86b4fd3eff76c3ce4f5e96e2fdfa6282722885"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "1.0.0"
[[deps.Flux]]
deps = ["Adapt", "CUDA", "ChainRulesCore", "Functors", "LinearAlgebra", "MLUtils", "MacroTools", "NNlib", "NNlibCUDA", "OneHotArrays", "Optimisers", "Preferences", "ProgressLogging", "Random", "Reexport", "SparseArrays", "SpecialFunctions", "Statistics", "Zygote", "cuDNN"]
git-tree-sha1 = "3e2c3704c2173ab4b1935362384ca878b53d4c34"
uuid = "587475ba-b771-5e3f-ad9e-33799f191a9c"
version = "0.13.17"
[deps.Flux.extensions]
AMDGPUExt = "AMDGPU"
FluxMetalExt = "Metal"
[deps.Flux.weakdeps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
Metal = "dde4c033-4e86-420c-a63e-0dd931031962"
[[deps.ForwardDiff]]
deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"]
git-tree-sha1 = "00e252f4d706b3d55a8863432e742bf5717b498d"
uuid = "f6369f11-7733-5829-9624-2563aa707210"
version = "0.10.35"
weakdeps = ["StaticArrays"]
[deps.ForwardDiff.extensions]
ForwardDiffStaticArraysExt = "StaticArrays"
[[deps.Functors]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "478f8c3145bb91d82c2cf20433e8c1b30df454cc"
uuid = "d9f16b24-f501-4c13-a1f2-28368ffc5196"
version = "0.4.4"
[[deps.Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
[[deps.GPUArrays]]
deps = ["Adapt", "GPUArraysCore", "LLVM", "LinearAlgebra", "Printf", "Random", "Reexport", "Serialization", "Statistics"]
git-tree-sha1 = "2e57b4a4f9cc15e85a24d603256fe08e527f48d1"
uuid = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7"
version = "8.8.1"
[[deps.GPUArraysCore]]
deps = ["Adapt"]
git-tree-sha1 = "2d6ca471a6c7b536127afccfa7564b5b39227fe0"
uuid = "46192b85-c4d5-4398-a991-12ede77f4527"
version = "0.1.5"
[[deps.GPUCompiler]]
deps = ["ExprTools", "InteractiveUtils", "LLVM", "Libdl", "Logging", "Scratch", "TimerOutputs", "UUIDs"]
git-tree-sha1 = "cb090aea21c6ca78d59672a7e7d13bd56d09de64"
uuid = "61eb1bfa-7361-4325-ad38-22787b887f55"
version = "0.20.3"
[[deps.HypergeometricFunctions]]
deps = ["DualNumbers", "LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"]
git-tree-sha1 = "84204eae2dd237500835990bcade263e27674a93"
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
version = "0.3.16"
[[deps.IRTools]]
deps = ["InteractiveUtils", "MacroTools", "Test"]
git-tree-sha1 = "eac00994ce3229a464c2847e956d77a2c64ad3a5"
uuid = "7869d1d1-7146-5819-86e3-90919afe41df"
version = "0.4.10"
[[deps.InitialValues]]
git-tree-sha1 = "4da0f88e9a39111c2fa3add390ab15f3a44f3ca3"
uuid = "22cec73e-a1b8-11e9-2c92-598750a2cf9c"
version = "0.3.1"
[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
[[deps.IrrationalConstants]]
git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.2.2"
[[deps.IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"
[[deps.JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "abc9885a7ca2052a736a600f7fa66209f96506e1"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.4.1"
[[deps.JSON3]]
deps = ["Dates", "Mmap", "Parsers", "SnoopPrecompile", "StructTypes", "UUIDs"]
git-tree-sha1 = "84b10656a41ef564c39d2d477d7236966d2b5683"
uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
version = "1.12.0"
[[deps.JuliaVariables]]
deps = ["MLStyle", "NameResolution"]
git-tree-sha1 = "49fb3cb53362ddadb4415e9b73926d6b40709e70"
uuid = "b14d175d-62b4-44ba-8fb7-3064adc8c3ec"
version = "0.2.4"
[[deps.KernelAbstractions]]
deps = ["Adapt", "Atomix", "InteractiveUtils", "LinearAlgebra", "MacroTools", "PrecompileTools", "SparseArrays", "StaticArrays", "UUIDs", "UnsafeAtomics", "UnsafeAtomicsLLVM"]
git-tree-sha1 = "b48617c5d764908b5fac493cd907cf33cc11eec1"
uuid = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
version = "0.9.6"
[[deps.LLVM]]
deps = ["CEnum", "LLVMExtra_jll", "Libdl", "Printf", "Unicode"]
git-tree-sha1 = "5007c1421563108110bbd57f63d8ad4565808818"
uuid = "929cbde3-209d-540e-8aea-75f648917ca0"
version = "5.2.0"
[[deps.LLVMExtra_jll]]
deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "1222116d7313cdefecf3d45a2bc1a89c4e7c9217"
uuid = "dad2f222-ce93-54a1-a47d-0025e8a3acab"
version = "0.0.22+0"
[[deps.LazyArtifacts]]
deps = ["Artifacts", "Pkg"]
uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
[[deps.LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
version = "0.6.3"
[[deps.LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
version = "7.84.0+0"
[[deps.LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
[[deps.LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
version = "1.10.2+0"
[[deps.Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
[[deps.LinearAlgebra]]
deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
[[deps.LogExpFunctions]]
deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "0a1b7c2863e44523180fdb3146534e265a91870b"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.23"
[deps.LogExpFunctions.extensions]
LogExpFunctionsChainRulesCoreExt = "ChainRulesCore"
LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables"
LogExpFunctionsInverseFunctionsExt = "InverseFunctions"
[deps.LogExpFunctions.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
[[deps.Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
[[deps.MLStyle]]
git-tree-sha1 = "bc38dff0548128765760c79eb7388a4b37fae2c8"
uuid = "d8e11817-5142-5d16-987a-aa16d5891078"
version = "0.4.17"
[[deps.MLUtils]]
deps = ["ChainRulesCore", "Compat", "DataAPI", "DelimitedFiles", "FLoops", "NNlib", "Random", "ShowCases", "SimpleTraits", "Statistics", "StatsBase", "Tables", "Transducers"]
git-tree-sha1 = "3504cdb8c2bc05bde4d4b09a81b01df88fcbbba0"
uuid = "f1d291b0-491e-4a28-83b9-f70985020b54"
version = "0.4.3"
[[deps.MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "42324d08725e200c23d4dfb549e0d5d89dede2d2"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.10"
[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
[[deps.MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
version = "2.28.2+0"
[[deps.MicroCollections]]
deps = ["BangBang", "InitialValues", "Setfield"]
git-tree-sha1 = "629afd7d10dbc6935ec59b32daeb33bc4460a42e"
uuid = "128add7d-3638-4c79-886c-908ea0c25c34"
version = "0.1.4"
[[deps.Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "f66bdc5de519e8f8ae43bdc598782d35a25b1272"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.1.0"
[[deps.Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
[[deps.MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
version = "2022.10.11"
[[deps.NNlib]]
deps = ["Adapt", "Atomix", "ChainRulesCore", "GPUArraysCore", "KernelAbstractions", "LinearAlgebra", "Pkg", "Random", "Requires", "Statistics"]
git-tree-sha1 = "72240e3f5ca031937bd536182cb2c031da5f46dd"
uuid = "872c559c-99b0-510c-b3b7-b6c96a88d5cd"
version = "0.8.21"
[deps.NNlib.extensions]
NNlibAMDGPUExt = "AMDGPU"
[deps.NNlib.weakdeps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
[[deps.NNlibCUDA]]
deps = ["Adapt", "CUDA", "LinearAlgebra", "NNlib", "Random", "Statistics", "cuDNN"]
git-tree-sha1 = "f94a9684394ff0d325cc12b06da7032d8be01aaf"
uuid = "a00861dc-f156-4864-bf3c-e6376f28a68d"
version = "0.2.7"
[[deps.NaNMath]]
deps = ["OpenLibm_jll"]
git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "1.0.2"
[[deps.NameResolution]]
deps = ["PrettyPrint"]
git-tree-sha1 = "1a0fa0e9613f46c9b8c11eee38ebb4f590013c5e"
uuid = "71a1bf82-56d0-4bbc-8a3c-48b961074391"
version = "0.1.5"
[[deps.NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
version = "1.2.0"
[[deps.OneHotArrays]]
deps = ["Adapt", "ChainRulesCore", "Compat", "GPUArraysCore", "LinearAlgebra", "NNlib"]
git-tree-sha1 = "5e4029759e8699ec12ebdf8721e51a659443403c"
uuid = "0b1bfda6-eb8a-41d2-88d8-f5af5cad476f"
version = "0.2.4"
[[deps.OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"
version = "0.3.21+4"
[[deps.OpenLibm_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"
version = "0.8.1+0"
[[deps.OpenSpecFun_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
version = "0.5.5+0"
[[deps.Optimisers]]
deps = ["ChainRulesCore", "Functors", "LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "6a01f65dd8583dee82eecc2a19b0ff21521aa749"
uuid = "3bd65402-5787-11e9-1adc-39752487f4e2"
version = "0.2.18"
[[deps.OrderedCollections]]
git-tree-sha1 = "d321bf2de576bf25ec4d3e4360faca399afca282"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.6.0"
[[deps.PDMats]]
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"]
git-tree-sha1 = "67eae2738d63117a196f497d7db789821bce61d1"
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
version = "0.11.17"
[[deps.Parsers]]
deps = ["Dates", "SnoopPrecompile"]
git-tree-sha1 = "478ac6c952fddd4399e71d4779797c538d0ff2bf"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.5.8"
[[deps.Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
version = "1.9.0"
[[deps.PrecompileTools]]
deps = ["Preferences"]
git-tree-sha1 = "9673d39decc5feece56ef3940e5dafba15ba0f81"
uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
version = "1.1.2"
[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "7eb1686b4f04b82f96ed7a4ea5890a4f0c7a09f1"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.4.0"
[[deps.PrettyPrint]]
git-tree-sha1 = "632eb4abab3449ab30c5e1afaa874f0b98b586e4"
uuid = "8162dcfd-2161-5ef2-ae6c-7681170c5f98"
version = "0.2.0"
[[deps.Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
[[deps.ProgressLogging]]
deps = ["Logging", "SHA", "UUIDs"]
git-tree-sha1 = "80d919dee55b9c50e8d9e2da5eeafff3fe58b539"
uuid = "33c8b6b6-d38a-422a-b730-caa89a2f386c"
version = "0.1.4"
[[deps.QuadGK]]
deps = ["DataStructures", "LinearAlgebra"]
git-tree-sha1 = "6ec7ac8412e83d57e313393220879ede1740f9ee"
uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
version = "2.8.2"
[[deps.REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
[[deps.Random]]
deps = ["SHA", "Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
[[deps.Random123]]
deps = ["Random", "RandomNumbers"]
git-tree-sha1 = "552f30e847641591ba3f39fd1bed559b9deb0ef3"
uuid = "74087812-796a-5b5d-8853-05524746bad3"
version = "1.6.1"
[[deps.RandomNumbers]]
deps = ["Random", "Requires"]
git-tree-sha1 = "043da614cc7e95c703498a491e2c21f58a2b8111"
uuid = "e6cf234a-135c-5ec9-84dd-332b85af5143"
version = "1.5.3"
[[deps.RealDot]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "9f0a1b71baaf7650f4fa8a1d168c7fb6ee41f0c9"
uuid = "c1ae055f-0cd5-4b69-90a6-9a35b1a98df9"
version = "0.1.0"
[[deps.Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"
[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.3.0"
[[deps.Rmath]]
deps = ["Random", "Rmath_jll"]
git-tree-sha1 = "f65dcb5fa46aee0cf9ed6274ccbd597adc49aa7b"
uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa"
version = "0.7.1"
[[deps.Rmath_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6ed52fdd3382cf21947b15e8870ac0ddbff736da"
uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f"
version = "0.4.0+0"
[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
version = "0.7.0"
[[deps.Scratch]]
deps = ["Dates"]
git-tree-sha1 = "30449ee12237627992a99d5e30ae63e4d78cd24a"
uuid = "6c6a2e73-6563-6170-7368-637461726353"
version = "1.2.0"
[[deps.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
[[deps.Setfield]]
deps = ["ConstructionBase", "Future", "MacroTools", "StaticArraysCore"]
git-tree-sha1 = "e2cc6d8c88613c05e1defb55170bf5ff211fbeac"
uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46"
version = "1.1.1"
[[deps.ShowCases]]
git-tree-sha1 = "7f534ad62ab2bd48591bdeac81994ea8c445e4a5"
uuid = "605ecd9f-84a6-4c9e-81e2-4798472b76a3"
version = "0.1.0"
[[deps.SimpleTraits]]
deps = ["InteractiveUtils", "MacroTools"]
git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231"
uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
version = "0.9.4"
[[deps.SnoopPrecompile]]
deps = ["Preferences"]
git-tree-sha1 = "e760a70afdcd461cf01a575947738d359234665c"
uuid = "66db9d55-30c0-4569-8b51-7e840670fc0c"
version = "1.0.3"
[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
[[deps.SortingAlgorithms]]
deps = ["DataStructures"]
git-tree-sha1 = "a4ada03f999bd01b3a25dcaa30b2d929fe537e00"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "1.1.0"
[[deps.SparseArrays]]
deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
[[deps.SpecialFunctions]]
deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "ef28127915f4229c971eb43f3fc075dd3fe91880"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "2.2.0"
weakdeps = ["ChainRulesCore"]
[deps.SpecialFunctions.extensions]
SpecialFunctionsChainRulesCoreExt = "ChainRulesCore"
[[deps.SplittablesBase]]
deps = ["Setfield", "Test"]
git-tree-sha1 = "e08a62abc517eb79667d0a29dc08a3b589516bb5"
uuid = "171d559e-b47b-412a-8079-5efa626c420e"
version = "0.1.15"
[[deps.StaticArrays]]
deps = ["LinearAlgebra", "Random", "StaticArraysCore", "Statistics"]
git-tree-sha1 = "832afbae2a45b4ae7e831f86965469a24d1d8a83"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.5.26"
[[deps.StaticArraysCore]]
git-tree-sha1 = "6b7ba252635a5eff6a0b0664a41ee140a1c9e72a"
uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
version = "1.4.0"
[[deps.Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
version = "1.9.0"
[[deps.StatsAPI]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "45a7769a04a3cf80da1c1c7c60caf932e6f4c9f7"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.6.0"
[[deps.StatsBase]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "75ebe04c5bed70b91614d684259b661c9e6274a4"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.34.0"
[[deps.StatsFuns]]
deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"]
git-tree-sha1 = "f625d686d5a88bcd2b15cd81f18f98186fdc0c9a"
uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
version = "1.3.0"
[deps.StatsFuns.extensions]
StatsFunsChainRulesCoreExt = "ChainRulesCore"
StatsFunsInverseFunctionsExt = "InverseFunctions"
[deps.StatsFuns.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
[[deps.StructArrays]]
deps = ["Adapt", "DataAPI", "GPUArraysCore", "StaticArraysCore", "Tables"]
git-tree-sha1 = "521a0e828e98bb69042fec1809c1b5a680eb7389"
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
version = "0.6.15"
[[deps.StructTypes]]
deps = ["Dates", "UUIDs"]
git-tree-sha1 = "ca4bccb03acf9faaf4137a9abc1881ed1841aa70"
uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
version = "1.10.0"
[[deps.SuiteSparse]]
deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"]
uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9"
[[deps.SuiteSparse_jll]]
deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"]
uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
version = "5.10.1+6"
[[deps.TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
version = "1.0.3"
[[deps.TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"
[[deps.Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits", "Test"]
git-tree-sha1 = "1544b926975372da01227b382066ab70e574a3ec"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.10.1"
[[deps.Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
version = "1.10.0"
[[deps.Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[[deps.TimerOutputs]]
deps = ["ExprTools", "Printf"]
git-tree-sha1 = "f548a9e9c490030e545f72074a41edfd0e5bcdd7"
uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
version = "0.5.23"
[[deps.Transducers]]
deps = ["Adapt", "ArgCheck", "BangBang", "Baselet", "CompositionsBase", "DefineSingletons", "Distributed", "InitialValues", "Logging", "Markdown", "MicroCollections", "Requires", "Setfield", "SplittablesBase", "Tables"]
git-tree-sha1 = "a66fb81baec325cf6ccafa243af573b031e87b00"
uuid = "28d57a85-8fef-5791-bfe6-a80928e7c999"
version = "0.4.77"
[deps.Transducers.extensions]
TransducersBlockArraysExt = "BlockArrays"
TransducersDataFramesExt = "DataFrames"
TransducersLazyArraysExt = "LazyArrays"
TransducersOnlineStatsBaseExt = "OnlineStatsBase"
TransducersReferenceablesExt = "Referenceables"
[deps.Transducers.weakdeps]
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
OnlineStatsBase = "925886fa-5bf2-5e8e-b522-a9147a512338"
Referenceables = "42d2dcc6-99eb-4e98-b66c-637b7d73030e"
[[deps.UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[[deps.Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
[[deps.UnsafeAtomics]]
git-tree-sha1 = "6331ac3440856ea1988316b46045303bef658278"
uuid = "013be700-e6cd-48c3-b4a1-df204f14c38f"
version = "0.2.1"
[[deps.UnsafeAtomicsLLVM]]
deps = ["LLVM", "UnsafeAtomics"]
git-tree-sha1 = "ea37e6066bf194ab78f4e747f5245261f17a7175"
uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249"
version = "0.1.2"
[[deps.Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
version = "1.2.13+0"
[[deps.Zygote]]
deps = ["AbstractFFTs", "ChainRules", "ChainRulesCore", "DiffRules", "Distributed", "FillArrays", "ForwardDiff", "GPUArrays", "GPUArraysCore", "IRTools", "InteractiveUtils", "LinearAlgebra", "LogExpFunctions", "MacroTools", "NaNMath", "PrecompileTools", "Random", "Requires", "SparseArrays", "SpecialFunctions", "Statistics", "ZygoteRules"]
git-tree-sha1 = "5be3ddb88fc992a7d8ea96c3f10a49a7e98ebc7b"
uuid = "e88e6eb3-aa80-5325-afca-941959d7151f"
version = "0.6.62"
[deps.Zygote.extensions]
ZygoteColorsExt = "Colors"
ZygoteDistancesExt = "Distances"
ZygoteTrackerExt = "Tracker"
[deps.Zygote.weakdeps]
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c"
[[deps.ZygoteRules]]
deps = ["ChainRulesCore", "MacroTools"]
git-tree-sha1 = "977aed5d006b840e2e40c0b48984f7463109046d"
uuid = "700de1a5-db45-46bc-99cf-38207098b444"
version = "0.2.3"
[[deps.cuDNN]]
deps = ["CEnum", "CUDA", "CUDNN_jll"]
git-tree-sha1 = "f65490d187861d6222cb38bcbbff3fd949a7ec3e"
uuid = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd"
version = "1.0.4"
[[deps.libblastrampoline_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"
version = "5.8.0+0"
[[deps.nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
version = "1.48.0+0"
[[deps.p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
version = "17.4.0+0"
-11
View File
@@ -1,11 +0,0 @@
name = "GeneralUtils"
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
authors = ["tonaerospace <tonaerospace.etc@gmail.com>"]
version = "0.1.0"
[deps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
-81
View File
@@ -1,81 +0,0 @@
module GeneralUtils
export noNegative!, randomWithProb, randomChoiceWithProb, findIndex, limitvalue
include("interface.jl")
using .interface
#------------------------------------------------------------------------------------------------100
""" version 0.0.1
Todo:
- []
Change from version:
-
All features
"""
end # generalUtils
-813
View File
@@ -1,813 +0,0 @@
module interface
export noNegative!, randomWithProb, randomChoiceWithProb, findIndex, limitvalue, replaceMoreThan,
replaceLessThan, cartesianAssign!, sumAlongDim3, matMul_3Dto3D_manyTo1batch,
matMul_3Dto4D_batchwise
using JSON3, DataStructures, Distributions, Flux, CUDA
#------------------------------------------------------------------------------------------------100
noNegative!(a::AbstractVector) = replace!(x -> x < 0 ? 0 : x, a)
findNotZero(x::AbstractVector) = findall( (!iszero).(x) )
replaceMoreThan(i, target) = i > target ? target : i
replaceLessThan(i, target) = i < target ? target : i
precision(x::Array{<:Array}) = ( std(mean.(x)) / mean(mean.(x)) ) * 100
precision(x::Array) = std(x) / mean(x) * 100
replaceAt!(x::AbstractVector, ind::Number, value::Number) = x[ind] = value
notZero(x::AbstractVector) = (!iszero).(x)
Zero(x::AbstractVector) = iszero.(x)
isNan(x::AbstractVector) = isnan.(x)
isInf(x::Number) = abs(x) === Inf
isInf(x::AbstractVector) = isinf.(x)
isLess(x::AbstractVector, target::Number) = isless.(x, target)
isMore(x::Number, target::Number) = x > target
isMore(x::AbstractVector, target::Number) = isMore.(x, target)
absolute(x::AbstractVector) = abs.(x)
vecEleMul(x::AbstractVector, y::AbstractVector) = x .* y
vecEleMul(x::Number, y::AbstractVector) = x .* y
expDecay(initialValue::Number, decayFactor::Number, timePass::Number) =
initialValue * (1 - decayFactor)^timePass
mul!(x::AbstractVector, y::AbstractVector) = x .*= y
mul(x::AbstractVector, y::AbstractVector) = x .* y
ReLu(x::Number) = max(0, x)
updateVector!(x::AbstractVector, target::Number) = x .= target
updateVector!(x::AbstractVector, target::AbstractArray) = x .= target
function selectAdd!(x::AbstractVector, ind::AbstractVector, value::AbstractVector)
@. x = x + (ind * value)
end
""" findIndex(input::String, target::Char)
Find target index inside a collection.
Return 1) Bool array of matched target
2) CartesianIndex of every matched target
"""
function findIndex(input::String, target::Char)
match_position = []
for i in input
if i == target
append!(match_position, 1)
else
append!(match_position, 0)
end
end
match_index = findall(isequal.(match_position, 1))
return match_position, match_index
end
function findIndex(input::Array, target::Number)
match_position = isequal.(input, target)
match_index = findall(match_position)
return match_position, match_index
end
# function findIndex(input::Array, target::Array)
# match_position = isone.(zeros(length(input)))
# for i in target
# match_position = match_position + isequal.(input, i)
# end
# match_position = replaceMoreThan.(match_position, 1)
# match_index = findall(isone.(match_position)) # Findall donot work with Int64 vector [1, 0, 0, 1].
# # It only works with BitVector. isone() converts Int64 vector [1, 0, 0, 1] into
# # BitVector [1, 0, 0, 1]
# return match_position, match_index
# end
function findIndex(input::Array, target::Symbol)
match_position = isequal.(input, target)
match_index = findall(match_position)
return match_position, match_index
end
function findIndex(collection::Array{String}, target::String)
match_position = isequal.(collection, target)
match_index = findall(match_position)
return match_position, match_index
end
function findIndex(collection::Array{String}, target::Array{String})
match_position = nothing
match_index = nothing
for i in target
match_pos = isequal.(collection, i)
match_ind = findall(match_pos)
if match_position === nothing
match_position = match_pos
else
match_position = hcat(match_position, match_pos)
end
if match_index === nothing
match_index = match_ind
else
match_index = hcat(match_index, match_ind)
end
end
return match_position, match_index
end
function findIndex(collection::OrderedDict, target::Symbol)
collection_keys = keys(collection)
collection_keys_array = [i for i in collection_keys]
match_position = isequal.(collection_keys_array, target)
match_index = findall(match_position)
return match_position, match_index
end
function findMax(collection::AbstractVector)
maxValue, maxIndex = findmax(collection)
matchPosition = isequal.(collection, maxValue)
return maxValue, maxIndex, matchPosition
end
""" read_textfile_by_index(folder_path::String, read_file_number::Integer=1)
with multiple text file in a folder,
this function read x_th text file in a folder (filename is sorted by OS)
# Example
utils.read_textfile_by_index(cleaned_data_path, 2)
read 2nd txt file in a folder
"""
function read_textfile_by_index(folder_path::String, read_file_number::Integer=1)
if isdir(folder_path)
filenumber = length(readdir(folder_path))
if read_file_number > filenumber
error("you specified read_file_number = $read_file_number which is out
of range, the cleaned data folder has only $filenumber files")
return nothing, nothing, nothing
else
content = 0
# open each file in the directory and read
filename = readdir(folder_path, join=true, sort=false)[read_file_number]
f = open(filename)
content = readlines(f)
# content = read(f)
close(f)
end
return read_file_number, filename, content
else
error("ERROR no file or folder at $folder_path")
return nothing, nothing, nothing
end
end
#------------------------------------------------------------------------------------------------100
""" Array_to_JSON3_str(data::AbstractArray)
encode Array to JSON3 String
# Example
a = [1.23 4.7889; 9987.1 -123.07; -0.0027 -6.75]
json3_str = Array_to_JSON3_str(a)
json3_str = {"Array":[1.23,9987.1,-0.0027,4.7889,-123.07,-6.75],"size":[3,2]}
"""
function Array_to_JSON3_str(data::AbstractArray)
d = Dict("Array"=> data, "size"=>size(data))
json3_str = JSON3.write(d)
return json3_str
end
#------------------------------------------------------------------------------------------------100
""" JSON3_str_to_Array(json3_str::String)
decode JSON3 String to Array
# Example
json3_str = {"Array":[1.23,9987.1,-0.0027,4.7889,-123.07,-6.75],"size":[3,2]}
a = JSON3_str_to_Array(json3_str)
a = [1.23 4.7889; 9987.1 -123.07; -0.0027 -6.75]
"""
function JSON3_str_to_Array(json3_str::String)
d = JSON3.read(json3_str)
array = reshape(Array(d.Array), (d.size[1], d.size[2]))
return array
end
#------------------------------------------------------------------------------------------------100
""" Convert JSON3.read object to OrderedDict
# Example
dict = dictionary(["a"=>4, "b"=>6])
OrDict = OrderedDict(dict)
jsonString = JSON3.write(OrDict) # use jsonString to exchange. One can save it to file or send it thru pub/sub
jsonObject = JSON3.read(jsonString)
OrDict2 = JSON3read_to_OrDict(jsonObject) # example here
Adict2 = dictionary(OrDict2)
Andyferris's github https://github.com/andyferris/Dictionaries.jl
"""
function JSON3read_to_OrDict(x)
dict = OrderedDict()
for (k, v) in x
k = string(k)
dict[k] = v
end
return dict
end
#------------------------------------------------------------------------------------------------100
"""
print time of cpu executtion at the line inwhich this macro is used
"""
macro timeline(expr)
quote
print("line ", $(__source__.line), ": ")
@time $(esc(expr))
end
end
batchindex(batch_counter::Number, batch_size::Number; offset=0) =
(offset + (batch_counter-1) * batch_size + 1) : offset + (batch_counter * batch_size)
function flip_true_false(x::Bool)
if x == true
x = false
elseif x == false
x = true
else
error("undefined condition line $(@__LINE__)")
end
return x
end
function flip_true_false(x::Int)
if x == 1
x = 0
elseif x == 0
x = 1
else
throw("not define input of type $(typeof(x)) yet")
end
return x
end
"""
Return drawed index
# Example
drawed_index = randomWithProb([0.5, 0.2, 0.3])
"""
randomWithProb(probability::AbstractVector) = rand(Distributions.Categorical(probability)) # return drawed index
"""
Draw from choices according to its probability.
Probability range is 0.0 to 1.0 and all probability must summed up to 1
(may get probability from NNlib's softmax function)
# Example
draw = draw_choices([true, false, nothing], [0.5, 0.2, 0.3])
"""
function randomChoiceWithProb(choices::Array, probability::Array)
if length(choices) != length(probability)
error("random is not possible, choices array length != probability array length")
elseif sum(probability) != 1.0
error("probability does not sum to 1.0")
end
return choices[randomWithProb(probability)]
end
function randomChoiceOnTarget(target::Number, targetMatch::Number, choices::AbstractVector,
probability::AbstractVector)
if length(choices) != length(probability)
throw("random is not possible, choices array length != probability array length")
end
return target == targetMatch ? randomChoiceWithProb(choices, probability) : target
# dist = Distributions.Categorical(probability)
# draw_result = choices[rand(dist)]
end
function randomChoiceOnTarget(target::AbstractVector, choiceList::AbstractVector,
probability::AbstractVector)
return randomChoiceOnTarget.(target, 1, (choiceList,), (probability,))
end
function linearly_weighted_avg(a::Array)
total = 0.0
for (i, v) in enumerate(a)
total = total + (i * v)
end
return total / sum(a)
end
""" Convert String that is holded inside a variable to Symbol
# Example
x = "hello" # x is a variable holding String "hello" \n
y = variable_to_symbol(x) # y holds :hello
"""
function variable_str_to_symbol(variable)
semi = :($variable)
symbol = Symbol(semi)
return symbol
end
""" get useable type of specified fieldname inside a composite struct
# Example
julia> @Base.kwdef mutable struct some_struct
a::Union{Bool, Nothing} = nothing
b::Union{Float64, Nothing} = nothing
c::Union{Int64, AbstractFloat} = 3.5
d::Union{String, Nothing} = nothing
end
julia> a = some_struct()
julia> fieldname_useable_type(some_struct, :c) =result=> [Int64, Float64]
"""
function fieldname_useable_type(somestruct, fieldname::Symbol;
test_types=[2.0, 2, true, :h, "str", 'c', missing, nothing])::Vector{DataType}
new_instance = somestruct()
useable_type = []
for i in test_types
try
new_instance.:($fieldname) = i
type = typeof(new_instance.:($fieldname))
if type ∉ useable_type
push!(useable_type, type)
end
catch
end
end
return useable_type
end
function randomNoRepeat(drawOptions::Array, draw_number::Integer;
exclude_list::Union{AbstractArray,Nothing}=nothing)
draw_option = copy(drawOptions)
draw_option = isnothing(exclude_list) ? draw_option :
filter!(x -> x ∉ exclude_list, draw_option)
shuffle!(draw_option)
drawed_items = []
while length(drawed_items) < draw_number
push!(drawed_items, pop!(draw_option))
end
return drawed_items
end
""" using cron to schedule backup job by
1. sudo nano /etc/crontab <<< this is a system-wide cron file
2. to execute julia file @ 2.00am everyday add the following line at the buttom of the file
0 2 * * * root julia-1.7 /home/syncthing_backup_script.jl
Requirements using Dates
"""
function folderBackup(sourceFolderAbsolutePath::String, # absolute path to folder to be backuped
backupFolderAbsolutePath::String; # absolute path to folder used to store backup file
totalBackupFiles::Integer=7, # total backup file, the oldest will be deleted
containerName::Union{Array{String}, Nothing}=nothing) # container using source_folder
sep = (Sys.iswindows() ? "\\" : '/')
if sourceFolderAbsolutePath[end] == sep
sourceFolderAbsolutePath = sourceFolderAbsolutePath[1:end-1]
end
if backupFolderAbsolutePath[end] != sl
backupFolderAbsolutePath = backupFolderAbsolutePath * sep
end
if isdir(backupFolderAbsolutePath)
else
mkpath(backupFolderAbsolutePath)
end
# stop running docker container service
if containerName !== nothing
println("stop running services")
for i in containerName
try run(`docker stop $i`) catch; end
sleep(10) # wait for services to stop
end
end
# do backup
println("doing backup now")
timestamp = string(Dates.now())
name = split(sourceFolderAbsolutePath, sep)[end] * "--"
filename = name * timestamp * ".zip" # resulting compressed filename
run(`chmod -R a+rwx $sourceFolderAbsolutePath`)
# zip -r [destination+filename] [source folder to be zipped]
run(`zip -r $(backupFolderAbsolutePath * filename) $sourceFolderAbsolutePath`)
# check if total backup file is more than user specified, if yes, delete the oldest backup
backupFiles = readdir(backupFolderAbsolutePath)
while length(backupFiles) > totalBackupFiles
run(`rm $(backupFolderAbsolutePath * backupFiles[1])`)
backupFiles = readdir(backupFolderAbsolutePath)
end
# start docker services
if containerName !== nothing
println("start services")
for i in containerName
try run(`docker start $i`) catch; end
sleep(10) # wait for services to stop
end
end
end
function lowerclip!(data::AbstractVector, lowerbound::Number)
replace!(x -> x < lowerbound ? lowerbound : x, data)
end
function upperclip!(data::AbstractVector, upperbound::Number)
replace!(x -> x > upperbound ? upperbound : x, data)
end
function normalise(x::AbstractArray, mu, std)
ϵ = oftype(x[1], 1e-5)
μ = mu
# σ = std(x, dims=dims, mean=μ, corrected=false) # use this when Zygote#478 gets merged
σ = std
return (x .- μ) ./ (σ .+ ϵ)
end
function minMaxScaler(x::AbstractVector)
min = findmin(x)[1]
max = findmax(x)[1]
scaler(a::Number, min::Number, max::Number) = (a-min) / (max-min)
return scaler.(x, min, max)
end
""" a = [-1e200, -1e-200, 1e200, 1e-200] \n
result = vtclamp.(a, 1e-6, 1e6, -1e6, -1e-6)
"""
function customclamp(x::Number, poslo::Number, poshi::Number,
neglo::Number, neghi::Number)
signx = sign(x)
if signx == -1
if neghi < x < 0
return neghi
elseif x < neglo
return neglo
else
return x
end
elseif signx == +1
if poshi < x
return poshi
elseif 0 < x < poslo
return poslo
else
return x
end
end
end
function unitVec(x::AbstractVector)
y = √(sum(x.^2))
return x./y
end
function replaceAt!(x::AbstractVector, ind::AbstractVector, value::Number)
for i in ind
x[i] = value
end
end
function signbitVec(x::AbstractVector)
sign = signbit.(x) * 1
signVec = replace(s -> s == 0 ? -1 : s, sign)
return signVec
end
function deleteall!(x::AbstractVector)
for i in 1:length(x)
deleteat!(x, 1)
end
end
""" Select specific range of vectors in a dict, return a new dict
# Example
dict = Dict(:a => [1:5...],
:b => [6:10...])
call -> selectRange(dict, 1:3)
return -> Dict{Any, Any} with 2 entries:
:a => [1, 2, 3]
:b => [6, 7, 8]
"""
function selectRange(d::Dict{Symbol, <:AbstractVector}, range)
newDict = Dict{Symbol, AbstractVector}()
for (k, v) in d
newDict[k] = v[range]
end
return newDict
end
""" Assign value to a given Dict by array of keys
# Example
d = Dict(
:a1=> Dict(:c=> 5),
:a2=> Dict(
:k=> 10,
:b=> Dict(
:s=> "target",
)
)
)
index = [:a2, :b, :s] \n
assignDict!(d, [:a2, :b, :s], "wow")
return 1 if no target key in a given dict.
"""
function assignDict!(dict::Dict, accessArray::Array{Symbol}, valueToAssign)
wd = nothing
for i in accessArray
println(i)
if i != accessArray[end]
if wd === nothing && haskey(dict, i)
wd = Ref(dict[i])
elseif wd.x !== nothing && haskey(wd.x, i)
wd = Ref(wd.x[i])
else
return 1 # error, no target key in a given dict.
end
else
wd.x[i] = valueToAssign
return 0
end
end
end
""" convert hour(0-23), minute(0-59) into julia time object
# Example
time
"""
function iTime(h::Integer, m::Integer)
if h == 0
h = 12
ampm = "am"
elseif 1 <= h <= 11
ampm = "am"
elseif h == 12
ampm = "pm"
elseif 13 <= h <= 23
h = h - 12
ampm = "pm"
else
error("hour out of range")
end
m = m < 10 ? "0$m" : m
t = "$h:$m$ampm"
return Time(t, "HH:MMp")
end
""" replace a number according to the limit
if value is lower than lowerbound return lowerbound replacement value
if value is more than upperbound return upperbound replacement value
# Example
limitvalue(4, (-5 => 0), (5 => 5))
"""
function limitvalue(v::Number, lowerbound::Pair, upperbound::Pair)
lwLimit, lwReplace = lowerbound
upLimit, upReplace = upperbound
if v < lwLimit
v = lwReplace
elseif v > upLimit
v = upReplace
else
end
return v
end
""" ELEMENT-wise multiply of each slice of 3D input matrix ,a, to all slice of 3D another matrix ,b, and
concatenate at the 4th dimension.
Example
julia> input = rand(32, 32, 128) # batch at 3rd dim
julia> weight = rand(32, 32, 1024)
julia> r = matMul_3Dto3D_manyTo1batch(input, weight);
julia> size(r)
(32, 32, 1024, 128)
"""
function matMul_3Dto3D_manyTo1batch(a::Array, b::Array; resultStorage::Union{Array, Nothing}=nothing)
asize = [size(a)...]
bsize = [size(b)...]
if resultStorage === nothing
resultStorage = similar(a, eltype(b), bsize[1], bsize[2], bsize[3], asize[3])
end
c = [slice .* b for slice in eachslice(a, dims=3)]
resultStorage .= cat(c..., dims=4)
return resultStorage
end
""" GPU version of batchMatEleMul
Example
julia> using Flux, CUDA
julia> device = Flux.CUDA.functional() ? gpu : cpu
julia> if device == gpu CUDA.device!(0) end
julia> input = rand(32, 32, 128) |> gpu # 128-batches
julia> weight = rand(32, 32, 1024) |> gpu # 1-batch
julia> r = batchMatEleMul_gpu(input, weight);
julia> size(r)
(32, 32, 1024, 128)
"""
function matMul_3Dto3D_manyTo1batch(a::CuArray, b::CuArray;
resultStorage::Union{CuArray, Nothing}=nothing, threads=128)
asize = [size(a)...]
bsize = [size(b)...]
if resultStorage === nothing
resultStorage = similar(a, eltype(b), bsize[1], bsize[2], bsize[3], asize[3]) |> gpu
end
CUDA.@sync begin
@cuda threads=threads matMul_3Dto3D_manyTo1batch_gpu!(a, b, resultStorage)
end
return resultStorage
end
function matMul_3Dto3D_manyTo1batch_gpu!(a::CuArray, b::CuArray, resultStorage::CuArray)
_, _, _, p = size(resultStorage)
index = threadIdx().x # this example only requires linear indexing, so just use `x`
stride = blockDim().x
for i in index:stride:p
view(resultStorage, :, :, :, i) .= view(a, :, :, i) .* b
end
return nothing
end
""" ELEMENT-wise multiply of each slice of 3D input matrix ,a, to all batch of another 4D matrix ,b, and
concatenate at the 4th dimension.
Example
julia>
julia> a = rand(2,2,3) # 3-batches
julia> b = rand(2,2,4,3) # 3-batches
julia> r = GeneralUtils.matMul_3Dto4D_batchwise(a, b);
julia> size(r)
(2, 2, 4, 3)
"""
function matMul_3Dto4D_batchwise(a::Array, b::Array; resultStorage::Union{Array, Nothing}=nothing)
asize = [size(a)...]
bsize = [size(b)...]
if asize[end] != bsize[end]
error("batch number of a and b must be equal")
end
if resultStorage === nothing
resultStorage = zeros(bsize[1], bsize[2], bsize[3], asize[3])
end
for i in 1:asize[3]
view(resultStorage, :, :, :, i) .= a[:, :, i] .* b[:, :, :, i]
end
return resultStorage
end
#TODO
function matMul_4Dto4D_batchwise(a::Array, b::Array;
resultStorage::Union{Array, Nothing}=nothing)
error("this function is under constrution")
asize = [size(a)...]
bsize = [size(b)...]
if asize[end] != bsize[end]
error("batch number of a and b must be equal")
end
if resultStorage === nothing
resultStorage = zeros(bsize[1], bsize[2], bsize[3], asize[3])
end
end
""" assign matrix b to matrix a according to matrix b's CartesianIndex
"""
cartesianAssign!(a::CuArray, b::CuArray) = @cuda cartesianAssign!(a, b)
function cartesianAssign!(a, b)
for (i, v) in enumerate(b)
a[CartesianIndices(b)[i].I...] = v
end
return nothing
end
function sumAlongDim3(a::Array)
totalDim = length(size(a))
if totalDim == 3
d1, d2, d3 = size(a)
r = zeros(1, 1, d3)
for i in 1:d3
view(r, 1, 1, i) .= sum(a[:, :, i])
end
elseif totalDim == 4
d1, d2, d3, d4 = size(a)
r = zeros(1, 1, d3, d4)
for j in 1:d4
for i in 1:d3
view(r, 1, 1, i, j) .= sum(a[:, :, i, j])
end
end
else
error("this condition is not define yet")
end
return r
end
end # module
View File
-911
View File
@@ -1,911 +0,0 @@
# This file is machine-generated - editing it directly is not advised
julia_version = "1.9.1"
manifest_format = "2.0"
project_hash = "91349a0eb57aed703e8465e44731cca768229f09"
[[deps.AbstractFFTs]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "8bc0aaec0ca548eb6cf5f0d7d16351650c1ee956"
uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c"
version = "1.3.2"
weakdeps = ["ChainRulesCore"]
[deps.AbstractFFTs.extensions]
AbstractFFTsChainRulesCoreExt = "ChainRulesCore"
[[deps.Adapt]]
deps = ["LinearAlgebra", "Requires"]
git-tree-sha1 = "76289dc51920fdc6e0013c872ba9551d54961c24"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.6.2"
weakdeps = ["StaticArrays"]
[deps.Adapt.extensions]
AdaptStaticArraysExt = "StaticArrays"
[[deps.ArgCheck]]
git-tree-sha1 = "a3a402a35a2f7e0b87828ccabbd5ebfbebe356b4"
uuid = "dce04be8-c92d-5529-be00-80e4d2c0e197"
version = "2.3.0"
[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
version = "1.1.1"
[[deps.Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
[[deps.Atomix]]
deps = ["UnsafeAtomics"]
git-tree-sha1 = "c06a868224ecba914baa6942988e2f2aade419be"
uuid = "a9b6321e-bd34-4604-b9c9-b65b8de01458"
version = "0.1.0"
[[deps.BFloat16s]]
deps = ["LinearAlgebra", "Printf", "Random", "Test"]
git-tree-sha1 = "dbf84058d0a8cbbadee18d25cf606934b22d7c66"
uuid = "ab4f0b2a-ad5b-11e8-123f-65d77653426b"
version = "0.4.2"
[[deps.BangBang]]
deps = ["Compat", "ConstructionBase", "InitialValues", "LinearAlgebra", "Requires", "Setfield", "Tables"]
git-tree-sha1 = "e28912ce94077686443433c2800104b061a827ed"
uuid = "198e06fe-97b7-11e9-32a5-e1d131e6ad66"
version = "0.3.39"
[deps.BangBang.extensions]
BangBangChainRulesCoreExt = "ChainRulesCore"
BangBangDataFramesExt = "DataFrames"
BangBangStaticArraysExt = "StaticArrays"
BangBangStructArraysExt = "StructArrays"
BangBangTypedTablesExt = "TypedTables"
[deps.BangBang.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
TypedTables = "9d95f2ec-7b3d-5a63-8d20-e2491e220bb9"
[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
[[deps.Baselet]]
git-tree-sha1 = "aebf55e6d7795e02ca500a689d326ac979aaf89e"
uuid = "9718e550-a3fa-408a-8086-8db961cd8217"
version = "0.1.1"
[[deps.CEnum]]
git-tree-sha1 = "eb4cb44a499229b3b8426dcfb5dd85333951ff90"
uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82"
version = "0.4.2"
[[deps.CUDA]]
deps = ["AbstractFFTs", "Adapt", "BFloat16s", "CEnum", "CUDA_Driver_jll", "CUDA_Runtime_Discovery", "CUDA_Runtime_jll", "CompilerSupportLibraries_jll", "ExprTools", "GPUArrays", "GPUCompiler", "KernelAbstractions", "LLVM", "LazyArtifacts", "Libdl", "LinearAlgebra", "Logging", "Preferences", "Printf", "Random", "Random123", "RandomNumbers", "Reexport", "Requires", "SparseArrays", "SpecialFunctions", "UnsafeAtomicsLLVM"]
git-tree-sha1 = "442d989978ed3ff4e174c928ee879dc09d1ef693"
uuid = "052768ef-5323-5732-b1bb-66c8b64840ba"
version = "4.3.2"
[[deps.CUDA_Driver_jll]]
deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"]
git-tree-sha1 = "498f45593f6ddc0adff64a9310bb6710e851781b"
uuid = "4ee394cb-3365-5eb0-8335-949819d2adfc"
version = "0.5.0+1"
[[deps.CUDA_Runtime_Discovery]]
deps = ["Libdl"]
git-tree-sha1 = "bcc4a23cbbd99c8535a5318455dcf0f2546ec536"
uuid = "1af6417a-86b4-443c-805f-a4643ffb695f"
version = "0.2.2"
[[deps.CUDA_Runtime_jll]]
deps = ["Artifacts", "CUDA_Driver_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "5248d9c45712e51e27ba9b30eebec65658c6ce29"
uuid = "76a88914-d11a-5bdc-97e0-2f5a05c973a2"
version = "0.6.0+0"
[[deps.CUDNN_jll]]
deps = ["Artifacts", "CUDA_Runtime_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "2918fbffb50e3b7a0b9127617587afa76d4276e8"
uuid = "62b44479-cb7b-5706-934f-f13b2eb2e645"
version = "8.8.1+0"
[[deps.Calculus]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad"
uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9"
version = "0.5.1"
[[deps.ChainRules]]
deps = ["Adapt", "ChainRulesCore", "Compat", "Distributed", "GPUArraysCore", "IrrationalConstants", "LinearAlgebra", "Random", "RealDot", "SparseArrays", "Statistics", "StructArrays"]
git-tree-sha1 = "1cdf290d4feec68824bfb84f4bfc9f3aba185647"
uuid = "082447d4-558c-5d27-93f4-14fc19e9eca2"
version = "1.51.1"
[[deps.ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "e30f2f4e20f7f186dc36529910beaedc60cfa644"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.16.0"
[[deps.CommonSubexpressions]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7"
uuid = "bbf7d656-a473-5ed7-a52c-81e309532950"
version = "0.3.0"
[[deps.Compat]]
deps = ["UUIDs"]
git-tree-sha1 = "7a60c856b9fa189eb34f5f8a6f6b5529b7942957"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "4.6.1"
weakdeps = ["Dates", "LinearAlgebra"]
[deps.Compat.extensions]
CompatLinearAlgebraExt = "LinearAlgebra"
[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
version = "1.0.2+0"
[[deps.CompositionsBase]]
git-tree-sha1 = "802bb88cd69dfd1509f6670416bd4434015693ad"
uuid = "a33af91c-f02d-484b-be07-31d278c5ca2b"
version = "0.1.2"
[deps.CompositionsBase.extensions]
CompositionsBaseInverseFunctionsExt = "InverseFunctions"
[deps.CompositionsBase.weakdeps]
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
[[deps.ConstructionBase]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "738fec4d684a9a6ee9598a8bfee305b26831f28c"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
version = "1.5.2"
[deps.ConstructionBase.extensions]
ConstructionBaseIntervalSetsExt = "IntervalSets"
ConstructionBaseStaticArraysExt = "StaticArrays"
[deps.ConstructionBase.weakdeps]
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
[[deps.ContextVariablesX]]
deps = ["Compat", "Logging", "UUIDs"]
git-tree-sha1 = "25cc3803f1030ab855e383129dcd3dc294e322cc"
uuid = "6add18c4-b38d-439d-96f6-d6bc489c04c5"
version = "0.1.3"
[[deps.DataAPI]]
git-tree-sha1 = "e8119c1a33d267e16108be441a287a6981ba1630"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.14.0"
[[deps.DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "d1fff3a548102f48987a52a2e0d114fa97d730f0"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.13"
[[deps.DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"
[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
[[deps.DefineSingletons]]
git-tree-sha1 = "0fba8b706d0178b4dc7fd44a96a92382c9065c2c"
uuid = "244e2a9f-e319-4986-a169-4d1fe445cd52"
version = "0.1.2"
[[deps.DelimitedFiles]]
deps = ["Mmap"]
git-tree-sha1 = "9e2f36d3c96a820c678f2f1f1782582fcf685bae"
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"
version = "1.9.1"
[[deps.DiffResults]]
deps = ["StaticArraysCore"]
git-tree-sha1 = "782dd5f4561f5d267313f23853baaaa4c52ea621"
uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5"
version = "1.1.0"
[[deps.DiffRules]]
deps = ["IrrationalConstants", "LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"]
git-tree-sha1 = "23163d55f885173722d1e4cf0f6110cdbaf7e272"
uuid = "b552c78f-8df3-52c6-915a-8e097449b14b"
version = "1.15.1"
[[deps.Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
[[deps.Distributions]]
deps = ["FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns", "Test"]
git-tree-sha1 = "eead66061583b6807652281c0fbf291d7a9dc497"
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
version = "0.25.90"
[deps.Distributions.extensions]
DistributionsChainRulesCoreExt = "ChainRulesCore"
DistributionsDensityInterfaceExt = "DensityInterface"
[deps.Distributions.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d"
[[deps.DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.9.3"
[[deps.Downloads]]
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
version = "1.6.0"
[[deps.DualNumbers]]
deps = ["Calculus", "NaNMath", "SpecialFunctions"]
git-tree-sha1 = "5837a837389fccf076445fce071c8ddaea35a566"
uuid = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74"
version = "0.6.8"
[[deps.ExprTools]]
git-tree-sha1 = "c1d06d129da9f55715c6c212866f5b1bddc5fa00"
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
version = "0.1.9"
[[deps.FLoops]]
deps = ["BangBang", "Compat", "FLoopsBase", "InitialValues", "JuliaVariables", "MLStyle", "Serialization", "Setfield", "Transducers"]
git-tree-sha1 = "ffb97765602e3cbe59a0589d237bf07f245a8576"
uuid = "cc61a311-1640-44b5-9fba-1b764f453329"
version = "0.2.1"
[[deps.FLoopsBase]]
deps = ["ContextVariablesX"]
git-tree-sha1 = "656f7a6859be8673bf1f35da5670246b923964f7"
uuid = "b9860ae5-e623-471e-878b-f6a53c775ea6"
version = "0.1.1"
[[deps.FileWatching]]
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
[[deps.FillArrays]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "Statistics"]
git-tree-sha1 = "fc86b4fd3eff76c3ce4f5e96e2fdfa6282722885"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "1.0.0"
[[deps.Flux]]
deps = ["Adapt", "CUDA", "ChainRulesCore", "Functors", "LinearAlgebra", "MLUtils", "MacroTools", "NNlib", "NNlibCUDA", "OneHotArrays", "Optimisers", "Preferences", "ProgressLogging", "Random", "Reexport", "SparseArrays", "SpecialFunctions", "Statistics", "Zygote", "cuDNN"]
git-tree-sha1 = "3e2c3704c2173ab4b1935362384ca878b53d4c34"
uuid = "587475ba-b771-5e3f-ad9e-33799f191a9c"
version = "0.13.17"
[deps.Flux.extensions]
AMDGPUExt = "AMDGPU"
FluxMetalExt = "Metal"
[deps.Flux.weakdeps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
Metal = "dde4c033-4e86-420c-a63e-0dd931031962"
[[deps.ForwardDiff]]
deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"]
git-tree-sha1 = "00e252f4d706b3d55a8863432e742bf5717b498d"
uuid = "f6369f11-7733-5829-9624-2563aa707210"
version = "0.10.35"
weakdeps = ["StaticArrays"]
[deps.ForwardDiff.extensions]
ForwardDiffStaticArraysExt = "StaticArrays"
[[deps.Functors]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "478f8c3145bb91d82c2cf20433e8c1b30df454cc"
uuid = "d9f16b24-f501-4c13-a1f2-28368ffc5196"
version = "0.4.4"
[[deps.Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
[[deps.GPUArrays]]
deps = ["Adapt", "GPUArraysCore", "LLVM", "LinearAlgebra", "Printf", "Random", "Reexport", "Serialization", "Statistics"]
git-tree-sha1 = "2e57b4a4f9cc15e85a24d603256fe08e527f48d1"
uuid = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7"
version = "8.8.1"
[[deps.GPUArraysCore]]
deps = ["Adapt"]
git-tree-sha1 = "2d6ca471a6c7b536127afccfa7564b5b39227fe0"
uuid = "46192b85-c4d5-4398-a991-12ede77f4527"
version = "0.1.5"
[[deps.GPUCompiler]]
deps = ["ExprTools", "InteractiveUtils", "LLVM", "Libdl", "Logging", "Scratch", "TimerOutputs", "UUIDs"]
git-tree-sha1 = "cb090aea21c6ca78d59672a7e7d13bd56d09de64"
uuid = "61eb1bfa-7361-4325-ad38-22787b887f55"
version = "0.20.3"
[[deps.HypergeometricFunctions]]
deps = ["DualNumbers", "LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"]
git-tree-sha1 = "84204eae2dd237500835990bcade263e27674a93"
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
version = "0.3.16"
[[deps.IRTools]]
deps = ["InteractiveUtils", "MacroTools", "Test"]
git-tree-sha1 = "eac00994ce3229a464c2847e956d77a2c64ad3a5"
uuid = "7869d1d1-7146-5819-86e3-90919afe41df"
version = "0.4.10"
[[deps.InitialValues]]
git-tree-sha1 = "4da0f88e9a39111c2fa3add390ab15f3a44f3ca3"
uuid = "22cec73e-a1b8-11e9-2c92-598750a2cf9c"
version = "0.3.1"
[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
[[deps.IrrationalConstants]]
git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.2.2"
[[deps.IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"
[[deps.JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "abc9885a7ca2052a736a600f7fa66209f96506e1"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.4.1"
[[deps.JSON3]]
deps = ["Dates", "Mmap", "Parsers", "SnoopPrecompile", "StructTypes", "UUIDs"]
git-tree-sha1 = "84b10656a41ef564c39d2d477d7236966d2b5683"
uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
version = "1.12.0"
[[deps.JuliaVariables]]
deps = ["MLStyle", "NameResolution"]
git-tree-sha1 = "49fb3cb53362ddadb4415e9b73926d6b40709e70"
uuid = "b14d175d-62b4-44ba-8fb7-3064adc8c3ec"
version = "0.2.4"
[[deps.KernelAbstractions]]
deps = ["Adapt", "Atomix", "InteractiveUtils", "LinearAlgebra", "MacroTools", "PrecompileTools", "SparseArrays", "StaticArrays", "UUIDs", "UnsafeAtomics", "UnsafeAtomicsLLVM"]
git-tree-sha1 = "b48617c5d764908b5fac493cd907cf33cc11eec1"
uuid = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
version = "0.9.6"
[[deps.LLVM]]
deps = ["CEnum", "LLVMExtra_jll", "Libdl", "Printf", "Unicode"]
git-tree-sha1 = "5007c1421563108110bbd57f63d8ad4565808818"
uuid = "929cbde3-209d-540e-8aea-75f648917ca0"
version = "5.2.0"
[[deps.LLVMExtra_jll]]
deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "1222116d7313cdefecf3d45a2bc1a89c4e7c9217"
uuid = "dad2f222-ce93-54a1-a47d-0025e8a3acab"
version = "0.0.22+0"
[[deps.LazyArtifacts]]
deps = ["Artifacts", "Pkg"]
uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
[[deps.LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
version = "0.6.3"
[[deps.LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
version = "7.84.0+0"
[[deps.LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
[[deps.LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
version = "1.10.2+0"
[[deps.Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
[[deps.LinearAlgebra]]
deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
[[deps.LogExpFunctions]]
deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "0a1b7c2863e44523180fdb3146534e265a91870b"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.23"
[deps.LogExpFunctions.extensions]
LogExpFunctionsChainRulesCoreExt = "ChainRulesCore"
LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables"
LogExpFunctionsInverseFunctionsExt = "InverseFunctions"
[deps.LogExpFunctions.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
[[deps.Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
[[deps.MLStyle]]
git-tree-sha1 = "bc38dff0548128765760c79eb7388a4b37fae2c8"
uuid = "d8e11817-5142-5d16-987a-aa16d5891078"
version = "0.4.17"
[[deps.MLUtils]]
deps = ["ChainRulesCore", "Compat", "DataAPI", "DelimitedFiles", "FLoops", "NNlib", "Random", "ShowCases", "SimpleTraits", "Statistics", "StatsBase", "Tables", "Transducers"]
git-tree-sha1 = "3504cdb8c2bc05bde4d4b09a81b01df88fcbbba0"
uuid = "f1d291b0-491e-4a28-83b9-f70985020b54"
version = "0.4.3"
[[deps.MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "42324d08725e200c23d4dfb549e0d5d89dede2d2"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.10"
[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
[[deps.MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
version = "2.28.2+0"
[[deps.MicroCollections]]
deps = ["BangBang", "InitialValues", "Setfield"]
git-tree-sha1 = "629afd7d10dbc6935ec59b32daeb33bc4460a42e"
uuid = "128add7d-3638-4c79-886c-908ea0c25c34"
version = "0.1.4"
[[deps.Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "f66bdc5de519e8f8ae43bdc598782d35a25b1272"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.1.0"
[[deps.Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
[[deps.MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
version = "2022.10.11"
[[deps.NNlib]]
deps = ["Adapt", "Atomix", "ChainRulesCore", "GPUArraysCore", "KernelAbstractions", "LinearAlgebra", "Pkg", "Random", "Requires", "Statistics"]
git-tree-sha1 = "72240e3f5ca031937bd536182cb2c031da5f46dd"
uuid = "872c559c-99b0-510c-b3b7-b6c96a88d5cd"
version = "0.8.21"
[deps.NNlib.extensions]
NNlibAMDGPUExt = "AMDGPU"
[deps.NNlib.weakdeps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
[[deps.NNlibCUDA]]
deps = ["Adapt", "CUDA", "LinearAlgebra", "NNlib", "Random", "Statistics", "cuDNN"]
git-tree-sha1 = "f94a9684394ff0d325cc12b06da7032d8be01aaf"
uuid = "a00861dc-f156-4864-bf3c-e6376f28a68d"
version = "0.2.7"
[[deps.NaNMath]]
deps = ["OpenLibm_jll"]
git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "1.0.2"
[[deps.NameResolution]]
deps = ["PrettyPrint"]
git-tree-sha1 = "1a0fa0e9613f46c9b8c11eee38ebb4f590013c5e"
uuid = "71a1bf82-56d0-4bbc-8a3c-48b961074391"
version = "0.1.5"
[[deps.NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
version = "1.2.0"
[[deps.OneHotArrays]]
deps = ["Adapt", "ChainRulesCore", "Compat", "GPUArraysCore", "LinearAlgebra", "NNlib"]
git-tree-sha1 = "5e4029759e8699ec12ebdf8721e51a659443403c"
uuid = "0b1bfda6-eb8a-41d2-88d8-f5af5cad476f"
version = "0.2.4"
[[deps.OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"
version = "0.3.21+4"
[[deps.OpenLibm_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"
version = "0.8.1+0"
[[deps.OpenSpecFun_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
version = "0.5.5+0"
[[deps.Optimisers]]
deps = ["ChainRulesCore", "Functors", "LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "6a01f65dd8583dee82eecc2a19b0ff21521aa749"
uuid = "3bd65402-5787-11e9-1adc-39752487f4e2"
version = "0.2.18"
[[deps.OrderedCollections]]
git-tree-sha1 = "d321bf2de576bf25ec4d3e4360faca399afca282"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.6.0"
[[deps.PDMats]]
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"]
git-tree-sha1 = "67eae2738d63117a196f497d7db789821bce61d1"
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
version = "0.11.17"
[[deps.Parsers]]
deps = ["Dates", "SnoopPrecompile"]
git-tree-sha1 = "478ac6c952fddd4399e71d4779797c538d0ff2bf"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.5.8"
[[deps.Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
version = "1.9.0"
[[deps.PrecompileTools]]
deps = ["Preferences"]
git-tree-sha1 = "9673d39decc5feece56ef3940e5dafba15ba0f81"
uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
version = "1.1.2"
[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "7eb1686b4f04b82f96ed7a4ea5890a4f0c7a09f1"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.4.0"
[[deps.PrettyPrint]]
git-tree-sha1 = "632eb4abab3449ab30c5e1afaa874f0b98b586e4"
uuid = "8162dcfd-2161-5ef2-ae6c-7681170c5f98"
version = "0.2.0"
[[deps.Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
[[deps.ProgressLogging]]
deps = ["Logging", "SHA", "UUIDs"]
git-tree-sha1 = "80d919dee55b9c50e8d9e2da5eeafff3fe58b539"
uuid = "33c8b6b6-d38a-422a-b730-caa89a2f386c"
version = "0.1.4"
[[deps.QuadGK]]
deps = ["DataStructures", "LinearAlgebra"]
git-tree-sha1 = "6ec7ac8412e83d57e313393220879ede1740f9ee"
uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
version = "2.8.2"
[[deps.REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
[[deps.Random]]
deps = ["SHA", "Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
[[deps.Random123]]
deps = ["Random", "RandomNumbers"]
git-tree-sha1 = "552f30e847641591ba3f39fd1bed559b9deb0ef3"
uuid = "74087812-796a-5b5d-8853-05524746bad3"
version = "1.6.1"
[[deps.RandomNumbers]]
deps = ["Random", "Requires"]
git-tree-sha1 = "043da614cc7e95c703498a491e2c21f58a2b8111"
uuid = "e6cf234a-135c-5ec9-84dd-332b85af5143"
version = "1.5.3"
[[deps.RealDot]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "9f0a1b71baaf7650f4fa8a1d168c7fb6ee41f0c9"
uuid = "c1ae055f-0cd5-4b69-90a6-9a35b1a98df9"
version = "0.1.0"
[[deps.Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"
[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.3.0"
[[deps.Rmath]]
deps = ["Random", "Rmath_jll"]
git-tree-sha1 = "f65dcb5fa46aee0cf9ed6274ccbd597adc49aa7b"
uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa"
version = "0.7.1"
[[deps.Rmath_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6ed52fdd3382cf21947b15e8870ac0ddbff736da"
uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f"
version = "0.4.0+0"
[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
version = "0.7.0"
[[deps.Scratch]]
deps = ["Dates"]
git-tree-sha1 = "30449ee12237627992a99d5e30ae63e4d78cd24a"
uuid = "6c6a2e73-6563-6170-7368-637461726353"
version = "1.2.0"
[[deps.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
[[deps.Setfield]]
deps = ["ConstructionBase", "Future", "MacroTools", "StaticArraysCore"]
git-tree-sha1 = "e2cc6d8c88613c05e1defb55170bf5ff211fbeac"
uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46"
version = "1.1.1"
[[deps.ShowCases]]
git-tree-sha1 = "7f534ad62ab2bd48591bdeac81994ea8c445e4a5"
uuid = "605ecd9f-84a6-4c9e-81e2-4798472b76a3"
version = "0.1.0"
[[deps.SimpleTraits]]
deps = ["InteractiveUtils", "MacroTools"]
git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231"
uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
version = "0.9.4"
[[deps.SnoopPrecompile]]
deps = ["Preferences"]
git-tree-sha1 = "e760a70afdcd461cf01a575947738d359234665c"
uuid = "66db9d55-30c0-4569-8b51-7e840670fc0c"
version = "1.0.3"
[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
[[deps.SortingAlgorithms]]
deps = ["DataStructures"]
git-tree-sha1 = "a4ada03f999bd01b3a25dcaa30b2d929fe537e00"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "1.1.0"
[[deps.SparseArrays]]
deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
[[deps.SpecialFunctions]]
deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "ef28127915f4229c971eb43f3fc075dd3fe91880"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "2.2.0"
weakdeps = ["ChainRulesCore"]
[deps.SpecialFunctions.extensions]
SpecialFunctionsChainRulesCoreExt = "ChainRulesCore"
[[deps.SplittablesBase]]
deps = ["Setfield", "Test"]
git-tree-sha1 = "e08a62abc517eb79667d0a29dc08a3b589516bb5"
uuid = "171d559e-b47b-412a-8079-5efa626c420e"
version = "0.1.15"
[[deps.StaticArrays]]
deps = ["LinearAlgebra", "Random", "StaticArraysCore", "Statistics"]
git-tree-sha1 = "832afbae2a45b4ae7e831f86965469a24d1d8a83"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.5.26"
[[deps.StaticArraysCore]]
git-tree-sha1 = "6b7ba252635a5eff6a0b0664a41ee140a1c9e72a"
uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
version = "1.4.0"
[[deps.Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
version = "1.9.0"
[[deps.StatsAPI]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "45a7769a04a3cf80da1c1c7c60caf932e6f4c9f7"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.6.0"
[[deps.StatsBase]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "75ebe04c5bed70b91614d684259b661c9e6274a4"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.34.0"
[[deps.StatsFuns]]
deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"]
git-tree-sha1 = "f625d686d5a88bcd2b15cd81f18f98186fdc0c9a"
uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
version = "1.3.0"
[deps.StatsFuns.extensions]
StatsFunsChainRulesCoreExt = "ChainRulesCore"
StatsFunsInverseFunctionsExt = "InverseFunctions"
[deps.StatsFuns.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
[[deps.StructArrays]]
deps = ["Adapt", "DataAPI", "GPUArraysCore", "StaticArraysCore", "Tables"]
git-tree-sha1 = "521a0e828e98bb69042fec1809c1b5a680eb7389"
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
version = "0.6.15"
[[deps.StructTypes]]
deps = ["Dates", "UUIDs"]
git-tree-sha1 = "ca4bccb03acf9faaf4137a9abc1881ed1841aa70"
uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
version = "1.10.0"
[[deps.SuiteSparse]]
deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"]
uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9"
[[deps.SuiteSparse_jll]]
deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"]
uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
version = "5.10.1+6"
[[deps.TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
version = "1.0.3"
[[deps.TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"
[[deps.Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits", "Test"]
git-tree-sha1 = "1544b926975372da01227b382066ab70e574a3ec"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.10.1"
[[deps.Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
version = "1.10.0"
[[deps.Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[[deps.TimerOutputs]]
deps = ["ExprTools", "Printf"]
git-tree-sha1 = "f548a9e9c490030e545f72074a41edfd0e5bcdd7"
uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
version = "0.5.23"
[[deps.Transducers]]
deps = ["Adapt", "ArgCheck", "BangBang", "Baselet", "CompositionsBase", "DefineSingletons", "Distributed", "InitialValues", "Logging", "Markdown", "MicroCollections", "Requires", "Setfield", "SplittablesBase", "Tables"]
git-tree-sha1 = "a66fb81baec325cf6ccafa243af573b031e87b00"
uuid = "28d57a85-8fef-5791-bfe6-a80928e7c999"
version = "0.4.77"
[deps.Transducers.extensions]
TransducersBlockArraysExt = "BlockArrays"
TransducersDataFramesExt = "DataFrames"
TransducersLazyArraysExt = "LazyArrays"
TransducersOnlineStatsBaseExt = "OnlineStatsBase"
TransducersReferenceablesExt = "Referenceables"
[deps.Transducers.weakdeps]
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
OnlineStatsBase = "925886fa-5bf2-5e8e-b522-a9147a512338"
Referenceables = "42d2dcc6-99eb-4e98-b66c-637b7d73030e"
[[deps.UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[[deps.Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
[[deps.UnsafeAtomics]]
git-tree-sha1 = "6331ac3440856ea1988316b46045303bef658278"
uuid = "013be700-e6cd-48c3-b4a1-df204f14c38f"
version = "0.2.1"
[[deps.UnsafeAtomicsLLVM]]
deps = ["LLVM", "UnsafeAtomics"]
git-tree-sha1 = "ea37e6066bf194ab78f4e747f5245261f17a7175"
uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249"
version = "0.1.2"
[[deps.Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
version = "1.2.13+0"
[[deps.Zygote]]
deps = ["AbstractFFTs", "ChainRules", "ChainRulesCore", "DiffRules", "Distributed", "FillArrays", "ForwardDiff", "GPUArrays", "GPUArraysCore", "IRTools", "InteractiveUtils", "LinearAlgebra", "LogExpFunctions", "MacroTools", "NaNMath", "PrecompileTools", "Random", "Requires", "SparseArrays", "SpecialFunctions", "Statistics", "ZygoteRules"]
git-tree-sha1 = "5be3ddb88fc992a7d8ea96c3f10a49a7e98ebc7b"
uuid = "e88e6eb3-aa80-5325-afca-941959d7151f"
version = "0.6.62"
[deps.Zygote.extensions]
ZygoteColorsExt = "Colors"
ZygoteDistancesExt = "Distances"
ZygoteTrackerExt = "Tracker"
[deps.Zygote.weakdeps]
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c"
[[deps.ZygoteRules]]
deps = ["ChainRulesCore", "MacroTools"]
git-tree-sha1 = "977aed5d006b840e2e40c0b48984f7463109046d"
uuid = "700de1a5-db45-46bc-99cf-38207098b444"
version = "0.2.3"
[[deps.cuDNN]]
deps = ["CEnum", "CUDA", "CUDNN_jll"]
git-tree-sha1 = "f65490d187861d6222cb38bcbbff3fd949a7ec3e"
uuid = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd"
version = "1.0.4"
[[deps.libblastrampoline_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"
version = "5.8.0+0"
[[deps.nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
version = "1.48.0+0"
[[deps.p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
version = "17.4.0+0"
-11
View File
@@ -1,11 +0,0 @@
name = "GeneralUtils"
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
authors = ["tonaerospace <tonaerospace.etc@gmail.com>"]
version = "0.1.0"
[deps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
-81
View File
@@ -1,81 +0,0 @@
module GeneralUtils
export noNegative!, randomWithProb, randomChoiceWithProb, findIndex, limitvalue
include("interface.jl")
using .interface
#------------------------------------------------------------------------------------------------100
""" version 0.0.2
Todo:
- []
Change from version:
-
All features
"""
end # generalUtils
-841
View File
@@ -1,841 +0,0 @@
module interface
export noNegative!, randomWithProb, randomChoiceWithProb, findIndex, limitvalue, replaceMoreThan,
replaceLessThan, cartesianAssign!, sumAlongDim3, matMul_3Dto3D_manyTo1batch,
matMul_3Dto4D_batchwise
using JSON3, DataStructures, Distributions, Flux, CUDA
#------------------------------------------------------------------------------------------------100
noNegative!(a::AbstractVector) = replace!(x -> x < 0 ? 0 : x, a)
findNotZero(x::AbstractVector) = findall( (!iszero).(x) )
replaceMoreThan(i, target) = i > target ? target : i
replaceLessThan(i, target) = i < target ? target : i
precision(x::Array{<:Array}) = ( std(mean.(x)) / mean(mean.(x)) ) * 100
precision(x::Array) = std(x) / mean(x) * 100
replaceAt!(x::AbstractVector, ind::Number, value::Number) = x[ind] = value
notZero(x::AbstractVector) = (!iszero).(x)
Zero(x::AbstractVector) = iszero.(x)
isNan(x::AbstractVector) = isnan.(x)
isInf(x::Number) = abs(x) === Inf
isInf(x::AbstractVector) = isinf.(x)
isLess(x::AbstractVector, target::Number) = isless.(x, target)
isMore(x::Number, target::Number) = x > target
isMore(x::AbstractVector, target::Number) = isMore.(x, target)
absolute(x::AbstractVector) = abs.(x)
vecEleMul(x::AbstractVector, y::AbstractVector) = x .* y
vecEleMul(x::Number, y::AbstractVector) = x .* y
expDecay(initialValue::Number, decayFactor::Number, timePass::Number) =
initialValue * (1 - decayFactor)^timePass
mul!(x::AbstractVector, y::AbstractVector) = x .*= y
mul(x::AbstractVector, y::AbstractVector) = x .* y
ReLu(x::Number) = max(0, x)
updateVector!(x::AbstractVector, target::Number) = x .= target
updateVector!(x::AbstractVector, target::AbstractArray) = x .= target
function selectAdd!(x::AbstractVector, ind::AbstractVector, value::AbstractVector)
@. x = x + (ind * value)
end
""" findIndex(input::String, target::Char)
Find target index inside a collection.
Return 1) Bool array of matched target
2) CartesianIndex of every matched target
"""
function findIndex(input::String, target::Char)
match_position = []
for i in input
if i == target
append!(match_position, 1)
else
append!(match_position, 0)
end
end
match_index = findall(isequal.(match_position, 1))
return match_position, match_index
end
function findIndex(input::Array, target::Number)
match_position = isequal.(input, target)
match_index = findall(match_position)
return match_position, match_index
end
# function findIndex(input::Array, target::Array)
# match_position = isone.(zeros(length(input)))
# for i in target
# match_position = match_position + isequal.(input, i)
# end
# match_position = replaceMoreThan.(match_position, 1)
# match_index = findall(isone.(match_position)) # Findall donot work with Int64 vector [1, 0, 0, 1].
# # It only works with BitVector. isone() converts Int64 vector [1, 0, 0, 1] into
# # BitVector [1, 0, 0, 1]
# return match_position, match_index
# end
function findIndex(input::Array, target::Symbol)
match_position = isequal.(input, target)
match_index = findall(match_position)
return match_position, match_index
end
function findIndex(collection::Array{String}, target::String)
match_position = isequal.(collection, target)
match_index = findall(match_position)
return match_position, match_index
end
function findIndex(collection::Array{String}, target::Array{String})
match_position = nothing
match_index = nothing
for i in target
match_pos = isequal.(collection, i)
match_ind = findall(match_pos)
if match_position === nothing
match_position = match_pos
else
match_position = hcat(match_position, match_pos)
end
if match_index === nothing
match_index = match_ind
else
match_index = hcat(match_index, match_ind)
end
end
return match_position, match_index
end
function findIndex(collection::OrderedDict, target::Symbol)
collection_keys = keys(collection)
collection_keys_array = [i for i in collection_keys]
match_position = isequal.(collection_keys_array, target)
match_index = findall(match_position)
return match_position, match_index
end
function findMax(collection::AbstractVector)
maxValue, maxIndex = findmax(collection)
matchPosition = isequal.(collection, maxValue)
return maxValue, maxIndex, matchPosition
end
""" read_textfile_by_index(folder_path::String, read_file_number::Integer=1)
with multiple text file in a folder,
this function read x_th text file in a folder (filename is sorted by OS)
# Example
utils.read_textfile_by_index(cleaned_data_path, 2)
read 2nd txt file in a folder
"""
function read_textfile_by_index(folder_path::String, read_file_number::Integer=1)
if isdir(folder_path)
filenumber = length(readdir(folder_path))
if read_file_number > filenumber
error("you specified read_file_number = $read_file_number which is out
of range, the cleaned data folder has only $filenumber files")
return nothing, nothing, nothing
else
content = 0
# open each file in the directory and read
filename = readdir(folder_path, join=true, sort=false)[read_file_number]
f = open(filename)
content = readlines(f)
# content = read(f)
close(f)
end
return read_file_number, filename, content
else
error("ERROR no file or folder at $folder_path")
return nothing, nothing, nothing
end
end
#------------------------------------------------------------------------------------------------100
""" Array_to_JSON3_str(data::AbstractArray)
encode Array to JSON3 String
# Example
a = [1.23 4.7889; 9987.1 -123.07; -0.0027 -6.75]
json3_str = Array_to_JSON3_str(a)
json3_str = {"Array":[1.23,9987.1,-0.0027,4.7889,-123.07,-6.75],"size":[3,2]}
"""
function Array_to_JSON3_str(data::AbstractArray)
d = Dict("Array"=> data, "size"=>size(data))
json3_str = JSON3.write(d)
return json3_str
end
#------------------------------------------------------------------------------------------------100
""" JSON3_str_to_Array(json3_str::String)
decode JSON3 String to Array
# Example
json3_str = {"Array":[1.23,9987.1,-0.0027,4.7889,-123.07,-6.75],"size":[3,2]}
a = JSON3_str_to_Array(json3_str)
a = [1.23 4.7889; 9987.1 -123.07; -0.0027 -6.75]
"""
function JSON3_str_to_Array(json3_str::String)
d = JSON3.read(json3_str)
array = reshape(Array(d.Array), (d.size[1], d.size[2]))
return array
end
#------------------------------------------------------------------------------------------------100
""" Convert JSON3.read object to OrderedDict
# Example
dict = dictionary(["a"=>4, "b"=>6])
OrDict = OrderedDict(dict)
jsonString = JSON3.write(OrDict) # use jsonString to exchange. One can save it to file or send it thru pub/sub
jsonObject = JSON3.read(jsonString)
OrDict2 = JSON3read_to_OrDict(jsonObject) # example here
Adict2 = dictionary(OrDict2)
Andyferris's github https://github.com/andyferris/Dictionaries.jl
"""
function JSON3read_to_OrDict(x)
dict = OrderedDict()
for (k, v) in x
k = string(k)
dict[k] = v
end
return dict
end
#------------------------------------------------------------------------------------------------100
"""
print time of cpu executtion at the line inwhich this macro is used
"""
macro timeline(expr)
quote
print("line ", $(__source__.line), ": ")
@time $(esc(expr))
end
end
batchindex(batch_counter::Number, batch_size::Number; offset=0) =
(offset + (batch_counter-1) * batch_size + 1) : offset + (batch_counter * batch_size)
function flip_true_false(x::Bool)
if x == true
x = false
elseif x == false
x = true
else
error("undefined condition line $(@__LINE__)")
end
return x
end
function flip_true_false(x::Int)
if x == 1
x = 0
elseif x == 0
x = 1
else
throw("not define input of type $(typeof(x)) yet")
end
return x
end
"""
Return drawed index
# Example
drawed_index = randomWithProb([0.5, 0.2, 0.3])
"""
randomWithProb(probability::AbstractVector) = rand(Distributions.Categorical(probability)) # return drawed index
"""
Draw from choices according to its probability.
Probability range is 0.0 to 1.0 and all probability must summed up to 1
(may get probability from NNlib's softmax function)
# Example
draw = draw_choices([true, false, nothing], [0.5, 0.2, 0.3])
"""
function randomChoiceWithProb(choices::Array, probability::Array)
if length(choices) != length(probability)
error("random is not possible, choices array length != probability array length")
elseif sum(probability) != 1.0
error("probability does not sum to 1.0")
end
return choices[randomWithProb(probability)]
end
function randomChoiceOnTarget(target::Number, targetMatch::Number, choices::AbstractVector,
probability::AbstractVector)
if length(choices) != length(probability)
throw("random is not possible, choices array length != probability array length")
end
return target == targetMatch ? randomChoiceWithProb(choices, probability) : target
# dist = Distributions.Categorical(probability)
# draw_result = choices[rand(dist)]
end
function randomChoiceOnTarget(target::AbstractVector, choiceList::AbstractVector,
probability::AbstractVector)
return randomChoiceOnTarget.(target, 1, (choiceList,), (probability,))
end
function linearly_weighted_avg(a::Array)
total = 0.0
for (i, v) in enumerate(a)
total = total + (i * v)
end
return total / sum(a)
end
""" Convert String that is holded inside a variable to Symbol
# Example
x = "hello" # x is a variable holding String "hello" \n
y = variable_to_symbol(x) # y holds :hello
"""
function variable_str_to_symbol(variable)
semi = :($variable)
symbol = Symbol(semi)
return symbol
end
""" get useable type of specified fieldname inside a composite struct
# Example
julia> @Base.kwdef mutable struct some_struct
a::Union{Bool, Nothing} = nothing
b::Union{Float64, Nothing} = nothing
c::Union{Int64, AbstractFloat} = 3.5
d::Union{String, Nothing} = nothing
end
julia> a = some_struct()
julia> fieldname_useable_type(some_struct, :c) =result=> [Int64, Float64]
"""
function fieldname_useable_type(somestruct, fieldname::Symbol;
test_types=[2.0, 2, true, :h, "str", 'c', missing, nothing])::Vector{DataType}
new_instance = somestruct()
useable_type = []
for i in test_types
try
new_instance.:($fieldname) = i
type = typeof(new_instance.:($fieldname))
if type ∉ useable_type
push!(useable_type, type)
end
catch
end
end
return useable_type
end
function randomNoRepeat(drawOptions::Array, draw_number::Integer;
exclude_list::Union{AbstractArray,Nothing}=nothing)
draw_option = copy(drawOptions)
draw_option = isnothing(exclude_list) ? draw_option :
filter!(x -> x ∉ exclude_list, draw_option)
shuffle!(draw_option)
drawed_items = []
while length(drawed_items) < draw_number
push!(drawed_items, pop!(draw_option))
end
return drawed_items
end
""" using cron to schedule backup job by
1. sudo nano /etc/crontab <<< this is a system-wide cron file
2. to execute julia file @ 2.00am everyday add the following line at the buttom of the file
0 2 * * * root julia-1.7 /home/syncthing_backup_script.jl
Requirements using Dates
"""
function folderBackup(sourceFolderAbsolutePath::String, # absolute path to folder to be backuped
backupFolderAbsolutePath::String; # absolute path to folder used to store backup file
totalBackupFiles::Integer=7, # total backup file, the oldest will be deleted
containerName::Union{Array{String}, Nothing}=nothing) # container using source_folder
sep = (Sys.iswindows() ? "\\" : '/')
if sourceFolderAbsolutePath[end] == sep
sourceFolderAbsolutePath = sourceFolderAbsolutePath[1:end-1]
end
if backupFolderAbsolutePath[end] != sl
backupFolderAbsolutePath = backupFolderAbsolutePath * sep
end
if isdir(backupFolderAbsolutePath)
else
mkpath(backupFolderAbsolutePath)
end
# stop running docker container service
if containerName !== nothing
println("stop running services")
for i in containerName
try run(`docker stop $i`) catch; end
sleep(10) # wait for services to stop
end
end
# do backup
println("doing backup now")
timestamp = string(Dates.now())
name = split(sourceFolderAbsolutePath, sep)[end] * "--"
filename = name * timestamp * ".zip" # resulting compressed filename
run(`chmod -R a+rwx $sourceFolderAbsolutePath`)
# zip -r [destination+filename] [source folder to be zipped]
run(`zip -r $(backupFolderAbsolutePath * filename) $sourceFolderAbsolutePath`)
# check if total backup file is more than user specified, if yes, delete the oldest backup
backupFiles = readdir(backupFolderAbsolutePath)
while length(backupFiles) > totalBackupFiles
run(`rm $(backupFolderAbsolutePath * backupFiles[1])`)
backupFiles = readdir(backupFolderAbsolutePath)
end
# start docker services
if containerName !== nothing
println("start services")
for i in containerName
try run(`docker start $i`) catch; end
sleep(10) # wait for services to stop
end
end
end
function lowerclip!(data::AbstractVector, lowerbound::Number)
replace!(x -> x < lowerbound ? lowerbound : x, data)
end
function upperclip!(data::AbstractVector, upperbound::Number)
replace!(x -> x > upperbound ? upperbound : x, data)
end
function normalise(x::AbstractArray, mu, std)
ϵ = oftype(x[1], 1e-5)
μ = mu
# σ = std(x, dims=dims, mean=μ, corrected=false) # use this when Zygote#478 gets merged
σ = std
return (x .- μ) ./ (σ .+ ϵ)
end
function minMaxScaler(x::AbstractVector)
min = findmin(x)[1]
max = findmax(x)[1]
scaler(a::Number, min::Number, max::Number) = (a-min) / (max-min)
return scaler.(x, min, max)
end
""" a = [-1e200, -1e-200, 1e200, 1e-200] \n
result = vtclamp.(a, 1e-6, 1e6, -1e6, -1e-6)
"""
function customclamp(x::Number, poslo::Number, poshi::Number,
neglo::Number, neghi::Number)
signx = sign(x)
if signx == -1
if neghi < x < 0
return neghi
elseif x < neglo
return neglo
else
return x
end
elseif signx == +1
if poshi < x
return poshi
elseif 0 < x < poslo
return poslo
else
return x
end
end
end
function unitVec(x::AbstractVector)
y = √(sum(x.^2))
return x./y
end
function replaceAt!(x::AbstractVector, ind::AbstractVector, value::Number)
for i in ind
x[i] = value
end
end
function signbitVec(x::AbstractVector)
sign = signbit.(x) * 1
signVec = replace(s -> s == 0 ? -1 : s, sign)
return signVec
end
function deleteall!(x::AbstractVector)
for i in 1:length(x)
deleteat!(x, 1)
end
end
""" Select specific range of vectors in a dict, return a new dict
# Example
dict = Dict(:a => [1:5...],
:b => [6:10...])
call -> selectRange(dict, 1:3)
return -> Dict{Any, Any} with 2 entries:
:a => [1, 2, 3]
:b => [6, 7, 8]
"""
function selectRange(d::Dict{Symbol, <:AbstractVector}, range)
newDict = Dict{Symbol, AbstractVector}()
for (k, v) in d
newDict[k] = v[range]
end
return newDict
end
""" Assign value to a given Dict by array of keys
# Example
d = Dict(
:a1=> Dict(:c=> 5),
:a2=> Dict(
:k=> 10,
:b=> Dict(
:s=> "target",
)
)
)
index = [:a2, :b, :s] \n
assignDict!(d, [:a2, :b, :s], "wow")
return 1 if no target key in a given dict.
"""
function assignDict!(dict::Dict, accessArray::Array{Symbol}, valueToAssign)
wd = nothing
for i in accessArray
println(i)
if i != accessArray[end]
if wd === nothing && haskey(dict, i)
wd = Ref(dict[i])
elseif wd.x !== nothing && haskey(wd.x, i)
wd = Ref(wd.x[i])
else
return 1 # error, no target key in a given dict.
end
else
wd.x[i] = valueToAssign
return 0
end
end
end
""" convert hour(0-23), minute(0-59) into julia time object
# Example
time
"""
function iTime(h::Integer, m::Integer)
if h == 0
h = 12
ampm = "am"
elseif 1 <= h <= 11
ampm = "am"
elseif h == 12
ampm = "pm"
elseif 13 <= h <= 23
h = h - 12
ampm = "pm"
else
error("hour out of range")
end
m = m < 10 ? "0$m" : m
t = "$h:$m$ampm"
return Time(t, "HH:MMp")
end
""" replace a number according to the limit
if value is lower than lowerbound return lowerbound replacement value
if value is more than upperbound return upperbound replacement value
# Example
limitvalue(4, (-5 => 0), (5 => 5))
"""
function limitvalue(v::Number, lowerbound::Pair, upperbound::Pair)
lwLimit, lwReplace = lowerbound
upLimit, upReplace = upperbound
if v < lwLimit
v = lwReplace
elseif v > upLimit
v = upReplace
else
end
return v
end
""" assign matrix b to matrix a according to matrix b's CartesianIndex
"""
cartesianAssign!(a::CuArray, b::CuArray) = @cuda cartesianAssign!(a, b)
function cartesianAssign!(a, b)
for (i, v) in enumerate(b)
a[CartesianIndices(b)[i].I...] = v
end
return nothing
end
function sumAlongDim3(a::Array)
totalDim = length(size(a))
if totalDim == 3
d1, d2, d3 = size(a)
r = zeros(1, 1, d3)
for i in 1:d3
view(r, 1, 1, i) .= sum(a[:, :, i])
end
elseif totalDim == 4
d1, d2, d3, d4 = size(a)
r = zeros(1, 1, d3, d4)
for j in 1:d4
for i in 1:d3
view(r, 1, 1, i, j) .= sum(a[:, :, i, j])
end
end
else
error("this condition is not define yet")
end
return r
end
""" ELEMENT-wise multiply of each slice of 3D input matrix ,a, to all slice of 3D another matrix ,b, and
concatenate at the 4th dimension.
Example
julia> input = rand(32, 32, 128) # batch at 3rd dim
julia> weight = rand(32, 32, 1024)
julia> r = matMul_3Dto3D_manyTo1batch(input, weight);
julia> size(r)
(32, 32, 1024, 128)
"""
function matMul_3Dto3D_manyTo1batch(a::Array, b::Array; resultStorage::Union{Array, Nothing}=nothing)
asize = [size(a)...]
bsize = [size(b)...]
if resultStorage === nothing
resultStorage = similar(a, eltype(b), bsize[1], bsize[2], bsize[3], asize[3])
end
c = [slice .* b for slice in eachslice(a, dims=3)]
resultStorage .= cat(c..., dims=4)
return resultStorage
end
# function matMul_3Dto3D_manyTo1batch(a::CuArray, b::CuArray; # XXX working code
# resultStorage::Union{CuArray, Nothing}=nothing, threads=256)
# asize = [size(a)...]
# bsize = [size(b)...]
# if resultStorage === nothing
# resultStorage = similar(a, eltype(b), bsize[1], bsize[2], bsize[3], asize[3]) |> gpu
# end
# CUDA.@sync begin
# @cuda threads=threads matMul_3Dto3D_manyTo1batch_gpu!(a, b, resultStorage)
# end
# return resultStorage
# end
# function matMul_3Dto3D_manyTo1batch_gpu!(a, b, resultStorage) # XXX working code
# _, _, _, p = size(resultStorage)
# index = threadIdx().x # this example only requires linear indexing, so just use `x`
# stride = blockDim().x
# for i in index:stride:p
# view(resultStorage, :, :, :, i) .= view(a, :, :, i) .* b
# end
# return nothing
# end
""" GPU kernel
"""
function matMul_3Dto3D_manyTo1batch_gpu!(a, b, resultStorage)
_, _, batch = size(a) # This kernel use 1 thread per batch
i = (blockIdx().x - 1) * blockDim().x + threadIdx().x
if i <= batch # guard against unused threads to accessing memory out of bound
# @cuprintln("thread $i")
view(resultStorage, :, :, :, i) .= view(a, :, :, i) .* b
end
return nothing
end
""" GPU version of batchMatEleMul
Example
julia> using Flux, CUDA
julia> device = Flux.CUDA.functional() ? gpu : cpu
julia> if device == gpu CUDA.device!(0) end
julia> input = rand(32, 32, 128) |> gpu; # 128-batches
julia> weight = rand(32, 32, 1024) |> gpu; # 1-batch
julia> r = matMul_3Dto3D_manyTo1batch(input, weight);
julia> size(r)
(32, 32, 1024, 128)
"""
function matMul_3Dto3D_manyTo1batch(a::CuArray, b::CuArray;
resultStorage::Union{CuArray, Nothing}=nothing)
asize = [size(a)...]
bsize = [size(b)...]
if resultStorage === nothing
resultStorage = similar(a, eltype(b), bsize[1], bsize[2], bsize[3], asize[3]) |> gpu
end
kernel = @cuda launch=false matMul_3Dto3D_manyTo1batch_gpu!(a, b, resultStorage)
config = launch_configuration(kernel.fun)
# threads to be launched. Since one can't launch exact thread number the kernel needs,
# one just launch threads more than this kernel needs then use a guard inside the kernel
# to prevent unused threads to access memory.
threads = min(1024, config.threads) # most NVIDIA gpu has 1024 threads per block
blocks = cld(asize[3], threads) # This kernel use 1 thread per batch
CUDA.@sync begin
kernel(a, b, resultStorage; threads, blocks)
end
return resultStorage
end
""" ELEMENT-wise multiply of each slice of 3D input matrix ,a, to all batch of another 4D matrix ,b, and
concatenate at the 4th dimension.
Example
julia>
julia> a = rand(2,2,3) # 3-batches
julia> b = rand(2,2,4,3) # 3-batches
julia> r = GeneralUtils.matMul_3Dto4D_batchwise(a, b);
julia> size(r)
(2, 2, 4, 3)
"""
function matMul_3Dto4D_batchwise(a::Array, b::Array; resultStorage::Union{Array, Nothing}=nothing)
asize = [size(a)...]
bsize = [size(b)...]
if asize[end] != bsize[end]
error("batch number of a and b must be equal")
end
if resultStorage === nothing
resultStorage = zeros(bsize[1], bsize[2], bsize[3], asize[3])
end
for i in 1:asize[3]
view(resultStorage, :, :, :, i) .= a[:, :, i] .* b[:, :, :, i]
end
return resultStorage
end
end # module
View File
-911
View File
@@ -1,911 +0,0 @@
# This file is machine-generated - editing it directly is not advised
julia_version = "1.9.2"
manifest_format = "2.0"
project_hash = "168be3100b37ab8a45dff337b2c1caa16b5ecd26"
[[deps.AbstractFFTs]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "8bc0aaec0ca548eb6cf5f0d7d16351650c1ee956"
uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c"
version = "1.3.2"
weakdeps = ["ChainRulesCore"]
[deps.AbstractFFTs.extensions]
AbstractFFTsChainRulesCoreExt = "ChainRulesCore"
[[deps.Adapt]]
deps = ["LinearAlgebra", "Requires"]
git-tree-sha1 = "76289dc51920fdc6e0013c872ba9551d54961c24"
uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
version = "3.6.2"
weakdeps = ["StaticArrays"]
[deps.Adapt.extensions]
AdaptStaticArraysExt = "StaticArrays"
[[deps.ArgCheck]]
git-tree-sha1 = "a3a402a35a2f7e0b87828ccabbd5ebfbebe356b4"
uuid = "dce04be8-c92d-5529-be00-80e4d2c0e197"
version = "2.3.0"
[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
version = "1.1.1"
[[deps.Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
[[deps.Atomix]]
deps = ["UnsafeAtomics"]
git-tree-sha1 = "c06a868224ecba914baa6942988e2f2aade419be"
uuid = "a9b6321e-bd34-4604-b9c9-b65b8de01458"
version = "0.1.0"
[[deps.BFloat16s]]
deps = ["LinearAlgebra", "Printf", "Random", "Test"]
git-tree-sha1 = "dbf84058d0a8cbbadee18d25cf606934b22d7c66"
uuid = "ab4f0b2a-ad5b-11e8-123f-65d77653426b"
version = "0.4.2"
[[deps.BangBang]]
deps = ["Compat", "ConstructionBase", "InitialValues", "LinearAlgebra", "Requires", "Setfield", "Tables"]
git-tree-sha1 = "e28912ce94077686443433c2800104b061a827ed"
uuid = "198e06fe-97b7-11e9-32a5-e1d131e6ad66"
version = "0.3.39"
[deps.BangBang.extensions]
BangBangChainRulesCoreExt = "ChainRulesCore"
BangBangDataFramesExt = "DataFrames"
BangBangStaticArraysExt = "StaticArrays"
BangBangStructArraysExt = "StructArrays"
BangBangTypedTablesExt = "TypedTables"
[deps.BangBang.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
TypedTables = "9d95f2ec-7b3d-5a63-8d20-e2491e220bb9"
[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
[[deps.Baselet]]
git-tree-sha1 = "aebf55e6d7795e02ca500a689d326ac979aaf89e"
uuid = "9718e550-a3fa-408a-8086-8db961cd8217"
version = "0.1.1"
[[deps.CEnum]]
git-tree-sha1 = "eb4cb44a499229b3b8426dcfb5dd85333951ff90"
uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82"
version = "0.4.2"
[[deps.CUDA]]
deps = ["AbstractFFTs", "Adapt", "BFloat16s", "CEnum", "CUDA_Driver_jll", "CUDA_Runtime_Discovery", "CUDA_Runtime_jll", "CompilerSupportLibraries_jll", "ExprTools", "GPUArrays", "GPUCompiler", "KernelAbstractions", "LLVM", "LazyArtifacts", "Libdl", "LinearAlgebra", "Logging", "Preferences", "Printf", "Random", "Random123", "RandomNumbers", "Reexport", "Requires", "SparseArrays", "SpecialFunctions", "UnsafeAtomicsLLVM"]
git-tree-sha1 = "442d989978ed3ff4e174c928ee879dc09d1ef693"
uuid = "052768ef-5323-5732-b1bb-66c8b64840ba"
version = "4.3.2"
[[deps.CUDA_Driver_jll]]
deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "Pkg"]
git-tree-sha1 = "498f45593f6ddc0adff64a9310bb6710e851781b"
uuid = "4ee394cb-3365-5eb0-8335-949819d2adfc"
version = "0.5.0+1"
[[deps.CUDA_Runtime_Discovery]]
deps = ["Libdl"]
git-tree-sha1 = "bcc4a23cbbd99c8535a5318455dcf0f2546ec536"
uuid = "1af6417a-86b4-443c-805f-a4643ffb695f"
version = "0.2.2"
[[deps.CUDA_Runtime_jll]]
deps = ["Artifacts", "CUDA_Driver_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "5248d9c45712e51e27ba9b30eebec65658c6ce29"
uuid = "76a88914-d11a-5bdc-97e0-2f5a05c973a2"
version = "0.6.0+0"
[[deps.CUDNN_jll]]
deps = ["Artifacts", "CUDA_Runtime_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "2918fbffb50e3b7a0b9127617587afa76d4276e8"
uuid = "62b44479-cb7b-5706-934f-f13b2eb2e645"
version = "8.8.1+0"
[[deps.Calculus]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad"
uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9"
version = "0.5.1"
[[deps.ChainRules]]
deps = ["Adapt", "ChainRulesCore", "Compat", "Distributed", "GPUArraysCore", "IrrationalConstants", "LinearAlgebra", "Random", "RealDot", "SparseArrays", "Statistics", "StructArrays"]
git-tree-sha1 = "1cdf290d4feec68824bfb84f4bfc9f3aba185647"
uuid = "082447d4-558c-5d27-93f4-14fc19e9eca2"
version = "1.51.1"
[[deps.ChainRulesCore]]
deps = ["Compat", "LinearAlgebra", "SparseArrays"]
git-tree-sha1 = "e30f2f4e20f7f186dc36529910beaedc60cfa644"
uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
version = "1.16.0"
[[deps.CommonSubexpressions]]
deps = ["MacroTools", "Test"]
git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7"
uuid = "bbf7d656-a473-5ed7-a52c-81e309532950"
version = "0.3.0"
[[deps.Compat]]
deps = ["UUIDs"]
git-tree-sha1 = "7a60c856b9fa189eb34f5f8a6f6b5529b7942957"
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
version = "4.6.1"
weakdeps = ["Dates", "LinearAlgebra"]
[deps.Compat.extensions]
CompatLinearAlgebraExt = "LinearAlgebra"
[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
version = "1.0.5+0"
[[deps.CompositionsBase]]
git-tree-sha1 = "802bb88cd69dfd1509f6670416bd4434015693ad"
uuid = "a33af91c-f02d-484b-be07-31d278c5ca2b"
version = "0.1.2"
[deps.CompositionsBase.extensions]
CompositionsBaseInverseFunctionsExt = "InverseFunctions"
[deps.CompositionsBase.weakdeps]
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
[[deps.ConstructionBase]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "738fec4d684a9a6ee9598a8bfee305b26831f28c"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
version = "1.5.2"
[deps.ConstructionBase.extensions]
ConstructionBaseIntervalSetsExt = "IntervalSets"
ConstructionBaseStaticArraysExt = "StaticArrays"
[deps.ConstructionBase.weakdeps]
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
[[deps.ContextVariablesX]]
deps = ["Compat", "Logging", "UUIDs"]
git-tree-sha1 = "25cc3803f1030ab855e383129dcd3dc294e322cc"
uuid = "6add18c4-b38d-439d-96f6-d6bc489c04c5"
version = "0.1.3"
[[deps.DataAPI]]
git-tree-sha1 = "e8119c1a33d267e16108be441a287a6981ba1630"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.14.0"
[[deps.DataStructures]]
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
git-tree-sha1 = "d1fff3a548102f48987a52a2e0d114fa97d730f0"
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
version = "0.18.13"
[[deps.DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"
[[deps.Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
[[deps.DefineSingletons]]
git-tree-sha1 = "0fba8b706d0178b4dc7fd44a96a92382c9065c2c"
uuid = "244e2a9f-e319-4986-a169-4d1fe445cd52"
version = "0.1.2"
[[deps.DelimitedFiles]]
deps = ["Mmap"]
git-tree-sha1 = "9e2f36d3c96a820c678f2f1f1782582fcf685bae"
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"
version = "1.9.1"
[[deps.DiffResults]]
deps = ["StaticArraysCore"]
git-tree-sha1 = "782dd5f4561f5d267313f23853baaaa4c52ea621"
uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5"
version = "1.1.0"
[[deps.DiffRules]]
deps = ["IrrationalConstants", "LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"]
git-tree-sha1 = "23163d55f885173722d1e4cf0f6110cdbaf7e272"
uuid = "b552c78f-8df3-52c6-915a-8e097449b14b"
version = "1.15.1"
[[deps.Distributed]]
deps = ["Random", "Serialization", "Sockets"]
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
[[deps.Distributions]]
deps = ["FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SparseArrays", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns", "Test"]
git-tree-sha1 = "eead66061583b6807652281c0fbf291d7a9dc497"
uuid = "31c24e10-a181-5473-b8eb-7969acd0382f"
version = "0.25.90"
[deps.Distributions.extensions]
DistributionsChainRulesCoreExt = "ChainRulesCore"
DistributionsDensityInterfaceExt = "DensityInterface"
[deps.Distributions.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d"
[[deps.DocStringExtensions]]
deps = ["LibGit2"]
git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d"
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
version = "0.9.3"
[[deps.Downloads]]
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
version = "1.6.0"
[[deps.DualNumbers]]
deps = ["Calculus", "NaNMath", "SpecialFunctions"]
git-tree-sha1 = "5837a837389fccf076445fce071c8ddaea35a566"
uuid = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74"
version = "0.6.8"
[[deps.ExprTools]]
git-tree-sha1 = "c1d06d129da9f55715c6c212866f5b1bddc5fa00"
uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04"
version = "0.1.9"
[[deps.FLoops]]
deps = ["BangBang", "Compat", "FLoopsBase", "InitialValues", "JuliaVariables", "MLStyle", "Serialization", "Setfield", "Transducers"]
git-tree-sha1 = "ffb97765602e3cbe59a0589d237bf07f245a8576"
uuid = "cc61a311-1640-44b5-9fba-1b764f453329"
version = "0.2.1"
[[deps.FLoopsBase]]
deps = ["ContextVariablesX"]
git-tree-sha1 = "656f7a6859be8673bf1f35da5670246b923964f7"
uuid = "b9860ae5-e623-471e-878b-f6a53c775ea6"
version = "0.1.1"
[[deps.FileWatching]]
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
[[deps.FillArrays]]
deps = ["LinearAlgebra", "Random", "SparseArrays", "Statistics"]
git-tree-sha1 = "fc86b4fd3eff76c3ce4f5e96e2fdfa6282722885"
uuid = "1a297f60-69ca-5386-bcde-b61e274b549b"
version = "1.0.0"
[[deps.Flux]]
deps = ["Adapt", "CUDA", "ChainRulesCore", "Functors", "LinearAlgebra", "MLUtils", "MacroTools", "NNlib", "NNlibCUDA", "OneHotArrays", "Optimisers", "Preferences", "ProgressLogging", "Random", "Reexport", "SparseArrays", "SpecialFunctions", "Statistics", "Zygote", "cuDNN"]
git-tree-sha1 = "3e2c3704c2173ab4b1935362384ca878b53d4c34"
uuid = "587475ba-b771-5e3f-ad9e-33799f191a9c"
version = "0.13.17"
[deps.Flux.extensions]
AMDGPUExt = "AMDGPU"
FluxMetalExt = "Metal"
[deps.Flux.weakdeps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
Metal = "dde4c033-4e86-420c-a63e-0dd931031962"
[[deps.ForwardDiff]]
deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"]
git-tree-sha1 = "00e252f4d706b3d55a8863432e742bf5717b498d"
uuid = "f6369f11-7733-5829-9624-2563aa707210"
version = "0.10.35"
weakdeps = ["StaticArrays"]
[deps.ForwardDiff.extensions]
ForwardDiffStaticArraysExt = "StaticArrays"
[[deps.Functors]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "478f8c3145bb91d82c2cf20433e8c1b30df454cc"
uuid = "d9f16b24-f501-4c13-a1f2-28368ffc5196"
version = "0.4.4"
[[deps.Future]]
deps = ["Random"]
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
[[deps.GPUArrays]]
deps = ["Adapt", "GPUArraysCore", "LLVM", "LinearAlgebra", "Printf", "Random", "Reexport", "Serialization", "Statistics"]
git-tree-sha1 = "2e57b4a4f9cc15e85a24d603256fe08e527f48d1"
uuid = "0c68f7d7-f131-5f86-a1c3-88cf8149b2d7"
version = "8.8.1"
[[deps.GPUArraysCore]]
deps = ["Adapt"]
git-tree-sha1 = "2d6ca471a6c7b536127afccfa7564b5b39227fe0"
uuid = "46192b85-c4d5-4398-a991-12ede77f4527"
version = "0.1.5"
[[deps.GPUCompiler]]
deps = ["ExprTools", "InteractiveUtils", "LLVM", "Libdl", "Logging", "Scratch", "TimerOutputs", "UUIDs"]
git-tree-sha1 = "cb090aea21c6ca78d59672a7e7d13bd56d09de64"
uuid = "61eb1bfa-7361-4325-ad38-22787b887f55"
version = "0.20.3"
[[deps.HypergeometricFunctions]]
deps = ["DualNumbers", "LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"]
git-tree-sha1 = "84204eae2dd237500835990bcade263e27674a93"
uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a"
version = "0.3.16"
[[deps.IRTools]]
deps = ["InteractiveUtils", "MacroTools", "Test"]
git-tree-sha1 = "eac00994ce3229a464c2847e956d77a2c64ad3a5"
uuid = "7869d1d1-7146-5819-86e3-90919afe41df"
version = "0.4.10"
[[deps.InitialValues]]
git-tree-sha1 = "4da0f88e9a39111c2fa3add390ab15f3a44f3ca3"
uuid = "22cec73e-a1b8-11e9-2c92-598750a2cf9c"
version = "0.3.1"
[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
[[deps.IrrationalConstants]]
git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2"
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
version = "0.2.2"
[[deps.IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"
[[deps.JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "abc9885a7ca2052a736a600f7fa66209f96506e1"
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
version = "1.4.1"
[[deps.JSON3]]
deps = ["Dates", "Mmap", "Parsers", "SnoopPrecompile", "StructTypes", "UUIDs"]
git-tree-sha1 = "84b10656a41ef564c39d2d477d7236966d2b5683"
uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
version = "1.12.0"
[[deps.JuliaVariables]]
deps = ["MLStyle", "NameResolution"]
git-tree-sha1 = "49fb3cb53362ddadb4415e9b73926d6b40709e70"
uuid = "b14d175d-62b4-44ba-8fb7-3064adc8c3ec"
version = "0.2.4"
[[deps.KernelAbstractions]]
deps = ["Adapt", "Atomix", "InteractiveUtils", "LinearAlgebra", "MacroTools", "PrecompileTools", "SparseArrays", "StaticArrays", "UUIDs", "UnsafeAtomics", "UnsafeAtomicsLLVM"]
git-tree-sha1 = "b48617c5d764908b5fac493cd907cf33cc11eec1"
uuid = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
version = "0.9.6"
[[deps.LLVM]]
deps = ["CEnum", "LLVMExtra_jll", "Libdl", "Printf", "Unicode"]
git-tree-sha1 = "5007c1421563108110bbd57f63d8ad4565808818"
uuid = "929cbde3-209d-540e-8aea-75f648917ca0"
version = "5.2.0"
[[deps.LLVMExtra_jll]]
deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl", "TOML"]
git-tree-sha1 = "1222116d7313cdefecf3d45a2bc1a89c4e7c9217"
uuid = "dad2f222-ce93-54a1-a47d-0025e8a3acab"
version = "0.0.22+0"
[[deps.LazyArtifacts]]
deps = ["Artifacts", "Pkg"]
uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
[[deps.LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
version = "0.6.3"
[[deps.LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
version = "7.84.0+0"
[[deps.LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
[[deps.LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
version = "1.10.2+0"
[[deps.Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
[[deps.LinearAlgebra]]
deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
[[deps.LogExpFunctions]]
deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"]
git-tree-sha1 = "0a1b7c2863e44523180fdb3146534e265a91870b"
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
version = "0.3.23"
[deps.LogExpFunctions.extensions]
LogExpFunctionsChainRulesCoreExt = "ChainRulesCore"
LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables"
LogExpFunctionsInverseFunctionsExt = "InverseFunctions"
[deps.LogExpFunctions.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
[[deps.Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
[[deps.MLStyle]]
git-tree-sha1 = "bc38dff0548128765760c79eb7388a4b37fae2c8"
uuid = "d8e11817-5142-5d16-987a-aa16d5891078"
version = "0.4.17"
[[deps.MLUtils]]
deps = ["ChainRulesCore", "Compat", "DataAPI", "DelimitedFiles", "FLoops", "NNlib", "Random", "ShowCases", "SimpleTraits", "Statistics", "StatsBase", "Tables", "Transducers"]
git-tree-sha1 = "3504cdb8c2bc05bde4d4b09a81b01df88fcbbba0"
uuid = "f1d291b0-491e-4a28-83b9-f70985020b54"
version = "0.4.3"
[[deps.MacroTools]]
deps = ["Markdown", "Random"]
git-tree-sha1 = "42324d08725e200c23d4dfb549e0d5d89dede2d2"
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
version = "0.5.10"
[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
[[deps.MbedTLS_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
version = "2.28.2+0"
[[deps.MicroCollections]]
deps = ["BangBang", "InitialValues", "Setfield"]
git-tree-sha1 = "629afd7d10dbc6935ec59b32daeb33bc4460a42e"
uuid = "128add7d-3638-4c79-886c-908ea0c25c34"
version = "0.1.4"
[[deps.Missings]]
deps = ["DataAPI"]
git-tree-sha1 = "f66bdc5de519e8f8ae43bdc598782d35a25b1272"
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
version = "1.1.0"
[[deps.Mmap]]
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
[[deps.MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
version = "2022.10.11"
[[deps.NNlib]]
deps = ["Adapt", "Atomix", "ChainRulesCore", "GPUArraysCore", "KernelAbstractions", "LinearAlgebra", "Pkg", "Random", "Requires", "Statistics"]
git-tree-sha1 = "72240e3f5ca031937bd536182cb2c031da5f46dd"
uuid = "872c559c-99b0-510c-b3b7-b6c96a88d5cd"
version = "0.8.21"
[deps.NNlib.extensions]
NNlibAMDGPUExt = "AMDGPU"
[deps.NNlib.weakdeps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
[[deps.NNlibCUDA]]
deps = ["Adapt", "CUDA", "LinearAlgebra", "NNlib", "Random", "Statistics", "cuDNN"]
git-tree-sha1 = "f94a9684394ff0d325cc12b06da7032d8be01aaf"
uuid = "a00861dc-f156-4864-bf3c-e6376f28a68d"
version = "0.2.7"
[[deps.NaNMath]]
deps = ["OpenLibm_jll"]
git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4"
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
version = "1.0.2"
[[deps.NameResolution]]
deps = ["PrettyPrint"]
git-tree-sha1 = "1a0fa0e9613f46c9b8c11eee38ebb4f590013c5e"
uuid = "71a1bf82-56d0-4bbc-8a3c-48b961074391"
version = "0.1.5"
[[deps.NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
version = "1.2.0"
[[deps.OneHotArrays]]
deps = ["Adapt", "ChainRulesCore", "Compat", "GPUArraysCore", "LinearAlgebra", "NNlib"]
git-tree-sha1 = "5e4029759e8699ec12ebdf8721e51a659443403c"
uuid = "0b1bfda6-eb8a-41d2-88d8-f5af5cad476f"
version = "0.2.4"
[[deps.OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"
version = "0.3.21+4"
[[deps.OpenLibm_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"
version = "0.8.1+0"
[[deps.OpenSpecFun_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
version = "0.5.5+0"
[[deps.Optimisers]]
deps = ["ChainRulesCore", "Functors", "LinearAlgebra", "Random", "Statistics"]
git-tree-sha1 = "6a01f65dd8583dee82eecc2a19b0ff21521aa749"
uuid = "3bd65402-5787-11e9-1adc-39752487f4e2"
version = "0.2.18"
[[deps.OrderedCollections]]
git-tree-sha1 = "d321bf2de576bf25ec4d3e4360faca399afca282"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.6.0"
[[deps.PDMats]]
deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"]
git-tree-sha1 = "67eae2738d63117a196f497d7db789821bce61d1"
uuid = "90014a1f-27ba-587c-ab20-58faa44d9150"
version = "0.11.17"
[[deps.Parsers]]
deps = ["Dates", "SnoopPrecompile"]
git-tree-sha1 = "478ac6c952fddd4399e71d4779797c538d0ff2bf"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.5.8"
[[deps.Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
version = "1.9.2"
[[deps.PrecompileTools]]
deps = ["Preferences"]
git-tree-sha1 = "9673d39decc5feece56ef3940e5dafba15ba0f81"
uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
version = "1.1.2"
[[deps.Preferences]]
deps = ["TOML"]
git-tree-sha1 = "7eb1686b4f04b82f96ed7a4ea5890a4f0c7a09f1"
uuid = "21216c6a-2e73-6563-6e65-726566657250"
version = "1.4.0"
[[deps.PrettyPrint]]
git-tree-sha1 = "632eb4abab3449ab30c5e1afaa874f0b98b586e4"
uuid = "8162dcfd-2161-5ef2-ae6c-7681170c5f98"
version = "0.2.0"
[[deps.Printf]]
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
[[deps.ProgressLogging]]
deps = ["Logging", "SHA", "UUIDs"]
git-tree-sha1 = "80d919dee55b9c50e8d9e2da5eeafff3fe58b539"
uuid = "33c8b6b6-d38a-422a-b730-caa89a2f386c"
version = "0.1.4"
[[deps.QuadGK]]
deps = ["DataStructures", "LinearAlgebra"]
git-tree-sha1 = "6ec7ac8412e83d57e313393220879ede1740f9ee"
uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
version = "2.8.2"
[[deps.REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
[[deps.Random]]
deps = ["SHA", "Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
[[deps.Random123]]
deps = ["Random", "RandomNumbers"]
git-tree-sha1 = "552f30e847641591ba3f39fd1bed559b9deb0ef3"
uuid = "74087812-796a-5b5d-8853-05524746bad3"
version = "1.6.1"
[[deps.RandomNumbers]]
deps = ["Random", "Requires"]
git-tree-sha1 = "043da614cc7e95c703498a491e2c21f58a2b8111"
uuid = "e6cf234a-135c-5ec9-84dd-332b85af5143"
version = "1.5.3"
[[deps.RealDot]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "9f0a1b71baaf7650f4fa8a1d168c7fb6ee41f0c9"
uuid = "c1ae055f-0cd5-4b69-90a6-9a35b1a98df9"
version = "0.1.0"
[[deps.Reexport]]
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "1.2.2"
[[deps.Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
version = "1.3.0"
[[deps.Rmath]]
deps = ["Random", "Rmath_jll"]
git-tree-sha1 = "f65dcb5fa46aee0cf9ed6274ccbd597adc49aa7b"
uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa"
version = "0.7.1"
[[deps.Rmath_jll]]
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
git-tree-sha1 = "6ed52fdd3382cf21947b15e8870ac0ddbff736da"
uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f"
version = "0.4.0+0"
[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
version = "0.7.0"
[[deps.Scratch]]
deps = ["Dates"]
git-tree-sha1 = "30449ee12237627992a99d5e30ae63e4d78cd24a"
uuid = "6c6a2e73-6563-6170-7368-637461726353"
version = "1.2.0"
[[deps.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
[[deps.Setfield]]
deps = ["ConstructionBase", "Future", "MacroTools", "StaticArraysCore"]
git-tree-sha1 = "e2cc6d8c88613c05e1defb55170bf5ff211fbeac"
uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46"
version = "1.1.1"
[[deps.ShowCases]]
git-tree-sha1 = "7f534ad62ab2bd48591bdeac81994ea8c445e4a5"
uuid = "605ecd9f-84a6-4c9e-81e2-4798472b76a3"
version = "0.1.0"
[[deps.SimpleTraits]]
deps = ["InteractiveUtils", "MacroTools"]
git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231"
uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d"
version = "0.9.4"
[[deps.SnoopPrecompile]]
deps = ["Preferences"]
git-tree-sha1 = "e760a70afdcd461cf01a575947738d359234665c"
uuid = "66db9d55-30c0-4569-8b51-7e840670fc0c"
version = "1.0.3"
[[deps.Sockets]]
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
[[deps.SortingAlgorithms]]
deps = ["DataStructures"]
git-tree-sha1 = "a4ada03f999bd01b3a25dcaa30b2d929fe537e00"
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
version = "1.1.0"
[[deps.SparseArrays]]
deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"]
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
[[deps.SpecialFunctions]]
deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
git-tree-sha1 = "ef28127915f4229c971eb43f3fc075dd3fe91880"
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
version = "2.2.0"
weakdeps = ["ChainRulesCore"]
[deps.SpecialFunctions.extensions]
SpecialFunctionsChainRulesCoreExt = "ChainRulesCore"
[[deps.SplittablesBase]]
deps = ["Setfield", "Test"]
git-tree-sha1 = "e08a62abc517eb79667d0a29dc08a3b589516bb5"
uuid = "171d559e-b47b-412a-8079-5efa626c420e"
version = "0.1.15"
[[deps.StaticArrays]]
deps = ["LinearAlgebra", "Random", "StaticArraysCore", "Statistics"]
git-tree-sha1 = "832afbae2a45b4ae7e831f86965469a24d1d8a83"
uuid = "90137ffa-7385-5640-81b9-e52037218182"
version = "1.5.26"
[[deps.StaticArraysCore]]
git-tree-sha1 = "6b7ba252635a5eff6a0b0664a41ee140a1c9e72a"
uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
version = "1.4.0"
[[deps.Statistics]]
deps = ["LinearAlgebra", "SparseArrays"]
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
version = "1.9.0"
[[deps.StatsAPI]]
deps = ["LinearAlgebra"]
git-tree-sha1 = "45a7769a04a3cf80da1c1c7c60caf932e6f4c9f7"
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
version = "1.6.0"
[[deps.StatsBase]]
deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"]
git-tree-sha1 = "75ebe04c5bed70b91614d684259b661c9e6274a4"
uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
version = "0.34.0"
[[deps.StatsFuns]]
deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"]
git-tree-sha1 = "f625d686d5a88bcd2b15cd81f18f98186fdc0c9a"
uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
version = "1.3.0"
[deps.StatsFuns.extensions]
StatsFunsChainRulesCoreExt = "ChainRulesCore"
StatsFunsInverseFunctionsExt = "InverseFunctions"
[deps.StatsFuns.weakdeps]
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
[[deps.StructArrays]]
deps = ["Adapt", "DataAPI", "GPUArraysCore", "StaticArraysCore", "Tables"]
git-tree-sha1 = "521a0e828e98bb69042fec1809c1b5a680eb7389"
uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
version = "0.6.15"
[[deps.StructTypes]]
deps = ["Dates", "UUIDs"]
git-tree-sha1 = "ca4bccb03acf9faaf4137a9abc1881ed1841aa70"
uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
version = "1.10.0"
[[deps.SuiteSparse]]
deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"]
uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9"
[[deps.SuiteSparse_jll]]
deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"]
uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
version = "5.10.1+6"
[[deps.TOML]]
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
version = "1.0.3"
[[deps.TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"
[[deps.Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits", "Test"]
git-tree-sha1 = "1544b926975372da01227b382066ab70e574a3ec"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.10.1"
[[deps.Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
version = "1.10.0"
[[deps.Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[[deps.TimerOutputs]]
deps = ["ExprTools", "Printf"]
git-tree-sha1 = "f548a9e9c490030e545f72074a41edfd0e5bcdd7"
uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
version = "0.5.23"
[[deps.Transducers]]
deps = ["Adapt", "ArgCheck", "BangBang", "Baselet", "CompositionsBase", "DefineSingletons", "Distributed", "InitialValues", "Logging", "Markdown", "MicroCollections", "Requires", "Setfield", "SplittablesBase", "Tables"]
git-tree-sha1 = "a66fb81baec325cf6ccafa243af573b031e87b00"
uuid = "28d57a85-8fef-5791-bfe6-a80928e7c999"
version = "0.4.77"
[deps.Transducers.extensions]
TransducersBlockArraysExt = "BlockArrays"
TransducersDataFramesExt = "DataFrames"
TransducersLazyArraysExt = "LazyArrays"
TransducersOnlineStatsBaseExt = "OnlineStatsBase"
TransducersReferenceablesExt = "Referenceables"
[deps.Transducers.weakdeps]
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
OnlineStatsBase = "925886fa-5bf2-5e8e-b522-a9147a512338"
Referenceables = "42d2dcc6-99eb-4e98-b66c-637b7d73030e"
[[deps.UUIDs]]
deps = ["Random", "SHA"]
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[[deps.Unicode]]
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
[[deps.UnsafeAtomics]]
git-tree-sha1 = "6331ac3440856ea1988316b46045303bef658278"
uuid = "013be700-e6cd-48c3-b4a1-df204f14c38f"
version = "0.2.1"
[[deps.UnsafeAtomicsLLVM]]
deps = ["LLVM", "UnsafeAtomics"]
git-tree-sha1 = "ea37e6066bf194ab78f4e747f5245261f17a7175"
uuid = "d80eeb9a-aca5-4d75-85e5-170c8b632249"
version = "0.1.2"
[[deps.Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
version = "1.2.13+0"
[[deps.Zygote]]
deps = ["AbstractFFTs", "ChainRules", "ChainRulesCore", "DiffRules", "Distributed", "FillArrays", "ForwardDiff", "GPUArrays", "GPUArraysCore", "IRTools", "InteractiveUtils", "LinearAlgebra", "LogExpFunctions", "MacroTools", "NaNMath", "PrecompileTools", "Random", "Requires", "SparseArrays", "SpecialFunctions", "Statistics", "ZygoteRules"]
git-tree-sha1 = "5be3ddb88fc992a7d8ea96c3f10a49a7e98ebc7b"
uuid = "e88e6eb3-aa80-5325-afca-941959d7151f"
version = "0.6.62"
[deps.Zygote.extensions]
ZygoteColorsExt = "Colors"
ZygoteDistancesExt = "Distances"
ZygoteTrackerExt = "Tracker"
[deps.Zygote.weakdeps]
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
Distances = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c"
[[deps.ZygoteRules]]
deps = ["ChainRulesCore", "MacroTools"]
git-tree-sha1 = "977aed5d006b840e2e40c0b48984f7463109046d"
uuid = "700de1a5-db45-46bc-99cf-38207098b444"
version = "0.2.3"
[[deps.cuDNN]]
deps = ["CEnum", "CUDA", "CUDNN_jll"]
git-tree-sha1 = "f65490d187861d6222cb38bcbbff3fd949a7ec3e"
uuid = "02a925ec-e4fe-4b08-9a7e-0d78e3d38ccd"
version = "1.0.4"
[[deps.libblastrampoline_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"
version = "5.8.0+0"
[[deps.nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
version = "1.48.0+0"
[[deps.p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
version = "17.4.0+0"
-12
View File
@@ -1,12 +0,0 @@
name = "GeneralUtils"
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
authors = ["tonaerospace <tonaerospace.etc@gmail.com>"]
version = "0.1.0"
[deps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
-81
View File
@@ -1,81 +0,0 @@
module GeneralUtils
export noNegative!, randomWithProb, randomChoiceWithProb, findIndex, limitvalue
include("interface.jl")
using .interface
#------------------------------------------------------------------------------------------------100
""" version 0.0.3
Todo:
- [*1] cartesianAssign for different matrix dimension
Change from version: 0.0.2
-
All features
"""
end # generalUtils
File diff suppressed because it is too large Load Diff
View File
+3 -10
View File
@@ -2,7 +2,7 @@ module GeneralUtils
export # struct export # struct
mqttClientInstance, # mqttClientInstance,
# function # function
noNegative!, randomWithProb, randomChoiceWithProb, findIndex, limitvalue noNegative!, randomWithProb, randomChoiceWithProb, findIndex, limitvalue
@@ -21,19 +21,12 @@ using .llmUtil
include("interface.jl") include("interface.jl")
using .interface using .interface
include("garageS3.jl")
using .garageS3
#------------------------------------------------------------------------------------------------100 #------------------------------------------------------------------------------------------------100
""" version 0.0.4
Todo:
- [*1] cartesianAssign for different matrix dimension
Change from version: 0.0.3
-
All features
"""
+650 -660
View File
File diff suppressed because it is too large Load Diff
+256 -132
View File
@@ -1,14 +1,140 @@
module dbUtil module dbUtil
export dictToPostgresKeyValueString, generateInsertSQL, generateUpdateSQL export dictToPostgresKeyValueString, generateInsertSQL, generateUpdateSQL, find_text_vector_similarity,
execute_postgres_sql
using JSON3, DataStructures, Distributions, Random, Dates, UUIDs, MQTTClient, DataFrames, using JSON, DataStructures, Distributions, Random, Dates, UUIDs, DataFrames,
SHA SHA, NATS, LibPQ
using ..util using ..util
#[PENDING] update code to use JSON
# ---------------------------------------------- 100 --------------------------------------------- # # ---------------------------------------------- 100 --------------------------------------------- #
""" Execute SQL against a PostgreSQL database using LibPQ connection string.
# Arguments
- `pg_conn_str::AbstractString`: PostgreSQL connection string in format "host=... port=... dbname=... user=... password=..."
- `sql::AbstractString`: SQL query to execute
# Returns
- `LibPQ.Result` on success, `nothing` on failure
# Example
```julia
pg_conn_str = "host=localhost port=5432 dbname=mydb user=myuser password=mypass"
sql = "SELECT * FROM wine;"
result = execute_postgres_sql(pg_conn_str, sql)
```
"""
function execute_postgres_sql(pg_conn_str::T, sql::T) where {T<:AbstractString}
db_connection = LibPQ.Connection(pg_conn_str)
result = nothing
try
result = LibPQ.execute(db_connection, sql)
catch e
@error e
LibPQ.close(db_connection)
end
LibPQ.close(db_connection)
return result
end
""" find_text_vector_similarity
Find the most similar text records in a PostgreSQL database using vector embeddings and cosine similarity.
This function computes an embedding for the input text using the provided embedding function,
then queries the database to find records with the most similar vector representations using
PostgreSQL's cosine similarity operator (`<->`).
# Arguments
- `text::AbstractString`: The input text to find similar records for
- `tablename::AbstractString`: Name of the database table containing the embedding column
- `embeddingColumnName::AbstractString`: Name of the column storing vector embeddings
- `executesql::Function`: Function that executes SQL queries and returns results
- `get_embedding::Function`: Function that generates embeddings for text inputs
# Keyword Arguments
- `limit::Integer=1`: Maximum number of similar records to return
# Returns
- `DataFrame`: Database records ordered by similarity (most similar first), including a `distance` column
where smaller values indicate higher similarity
# Example
```julia
# Assume you have embedding and SQL execution functions
text = "a rich structured red wine"
tablename = "wine"
embeddingColumnName = "description_embedding"
df = find_text_vector_similarity(
text, tablename, embeddingColumnName,
executesql, get_embedding;
limit = 5
)
# Result contains columns from the table plus a 'distance' column
# where distance = 1 - cosine_similarity (smaller = more similar)
```
"""
function find_text_vector_similarity(text::T1, tablename::T2, embeddingColumnName::T3,
executesql::Function, get_embedding;
limit::Integer=1
)::DataFrame where {T1<:AbstractString, T2<:AbstractString, T3<:AbstractString}
# get embedding from LLM service
_embedding = get_embedding([text])
_embedding = _embedding["data"][1]["embedding"]
_embedding = "$_embedding"
embedding = _embedding[4:end] # remove 'Any' from Any[...]
# check whether there is close enough vector already store in executesql. if no, add, else skip
sql = """
SELECT *, $embeddingColumnName <-> '$embedding' as distance
FROM $tablename
ORDER BY distance LIMIT $limit;
"""
response = executesql(sql)
df = DataFrame(response)
return df
end
"""
dictToPostgresKeyValueString - Convert dictionary to PostgreSQL key-value string format
This function takes a dictionary and converts it into a PostgreSQL-compatible key-value string
format suitable for storage in a TEXT field. The output format uses curly braces with comma-separated
key-value pairs, where string values are quoted.
# Function Workflow:
1. Iterates through dictionary key-value pairs
2. Handles nested dictionaries by recursively converting them
3. Wraps string values in double quotes
4. Formats numeric and other values without quotes
5. Returns a PostgreSQL-compatible key-value string enclosed in curly braces
# Arguments:
- `dict::Dict` - Dictionary containing key-value pairs to convert
# Return:
- A String in PostgreSQL key-value format: "{key1: value1, key2: \"value2\", ...}"
# Example
```jldoctest
julia> data = Dict{String, Any}(
"name" => "John",
"age" => 30,
"city" => "New York"
);
julia> dictToPostgresKeyValueString(data)
"{\"name\": \"John\", \"age\": 30, \"city\": \"New York\"}"
```
"""
function dictToPostgresKeyValueString(dict) function dictToPostgresKeyValueString(dict)
parts = [] parts = []
for (k, v) in dict for (k, v) in dict
@@ -26,61 +152,71 @@ end
""" Get characters between specified characters. """ generateInsertSQL - Generate SQL INSERT statement from dictionary data
# Arguments This function constructs a SQL INSERT statement by extracting values for specified columns
- `text::T` from a dictionary and formatting them into a valid PostgreSQL INSERT query.
a text being searched
- `startChar::Char` # Function Workflow:
start character 1. Iterates through the dictionary key-value pairs
- `endChar::Char` 2. Filters keys to only include those present in `columnToInsert`
end character 3. Collects column names and their corresponding values
# Keyword Arguments 4. Constructs the final SQL INSERT statement
- `endCharLocation::String`
end character position after startChar. Can be "next" or "end". "next" means the closed # Arguments:
endChar just after startChar. "end" means the furthest endChar. - `table_name::String` - Name of the database table to insert into
- `includeChar::Bool` - `columnToInsert::Vector{Symbol}` - List of column names to include in the INSERT statement
whether to include the startChar and endChar. Default is true - `data::Dict{Symbol, Any}` - Dictionary containing column-value pairs for the insert
# Return
the characters between specified characters. # Return:
- A String containing the SQL INSERT statement
# Example # Example
```jldoctest ```jldoctest
julia> using Revise julia> using UUIDs
julia> using GeneralUtils
julia> insert_data = Dict(
:grape => "NA",
:acidity => "0",
:tannin => "0",
:country => "NA",
:description => "NA",
:region => "NA",
:winery => "ccc",
:intensity => "0",
:sweetness => "0",
:tasting_notes => "NA",
:wine_name => "new_wine",
:wine_id => "9e1deb6a-d57f-4d2c-abbe-da813f4e91ad",
:wine_type => "NA",
:other_attributes => "{\"attribute3\":{\"attribute5\":666,\"attribute4\":\"text\"},\"attribute1\":\"hello world\",\"attribute2\":555}",
:fizziness => "0",
:serving_temperature => "0",
:additional_search_term => "{NA1,NA2}")
```
# TODO
- [] update docs
# Signature # Insert a single record with specific columns
table_name = "wine"
columnToInsert = [:acidity, :tannin, :country, :region, :winery]
data = Dict{Symbol, Any}(
:grape => "Cabernet Sauvignon",
:acidity => "medium", # using descriptive scale (low/medium/full)
:tannin => "medium-plus", # common wine descriptor
:country => "France",
:description => "A rich and structured red wine with notes of blackcurrant, cedar, and subtle oak.",
:region => "Bordeaux",
:winery => "Château Margaux",
:intensity => "medium", # intensity is usually low/medium/full
:sweetness => "dry", # dry/medium-dry/medium/medium-sweet/sweet
:tasting_notes => "Blackberry, graphite, tobacco, vanilla, and subtle earth.",
:wine_name => "Château Margaux Grand Cru",
:wine_id => "8f3c7a2e-1b4d-4a9f-9c2e-4a8b3d6e5f7a", # UUID-like (valid hex)
:wine_type => "Red",
:other_attributes => Dict{String, Any}(
"vintage" => 2018,
"alcohol_percent" => 13.5,
"ph" => 3.6,
" aging_years" => 24, # years in barrel
" producer_code" => "CM-GRAND"
),
:fizziness => "still",
:serving_temperature => "16–18°C",
:additional_search_term => ["Cabernet", "Bordeaux red", "premium wine", "CabSav"]
)
julia> generateInsertSQL(table_name, columnToInsert, data)
"INSERT INTO wine (acidity, tannin, country, region, winery) VALUES ('medium', 'medium-plus', 'France', 'Bordeaux', 'Château Margaux');"
```
""" """
function generateInsertSQL(table_name::String, columnToInsert::Vector{Symbol}, function generateInsertSQL(table_name::String, columnToInsert::Vector{Symbol}, data::Dict{Symbol, Any})
insert_data::Dict{Symbol, Any})
columns = String[] columns = String[]
values = String[] values = String[]
for (key, value) in insert_data for (key, value) in data
if key ∈ columnToInsert if key ∈ columnToInsert
push!(columns, string(key)) push!(columns, string(key))
push!(values, "'$value'") #[] number should not wrapped in '' value_str = isa(value, AbstractString) ? "'$value'" : "$value"
push!(values, value_str)
end end
end end
@@ -89,113 +225,101 @@ function generateInsertSQL(table_name::String, columnToInsert::Vector{Symbol},
return "INSERT INTO $table_name ($columns_str) VALUES ($values_str);" return "INSERT INTO $table_name ($columns_str) VALUES ($values_str);"
end end
# function generateInsertSQL(table_name::String, insert_data::Dict{Symbol, Any})
# columns = String[]
# values = String[]
# for (key, value) in insert_data function generateInsertSQL(table_name::String, data::AbstractDict{String, Any})
# push!(columns, string(key)) columns = String[]
# if key == :other_attributes values = String[]
# push!(values, "'$value'")
# else
# push!(values, "'$value'")
# end
# end
# columns_str = join(columns, ", ") for (key, value) in data
# values_str = join(values, ", ") push!(columns, string(key))
value_str = isa(value, AbstractString) ? "'$value'" : "$value"
# return "INSERT INTO $table_name ($columns_str) VALUES ($values_str);" push!(values, value_str)
# end
"""
example:
insert_data = Dict(
:grape => "NA",
:acidity => "0",
:tannin => "0",
:country => "NA",
:description => "NA",
:region => "NA",
:winery => "ccc",
:intensity => "0",
:sweetness => "0",
:tasting_notes => "NA",
:wine_name => "new_wine",
:wine_id => "9e1deb6a-d57f-4d2c-abbe-da813f4e91ad",
:wine_type => "NA",
:other_attributes => "{\"attribute3\":{\"attribute5\":666,\"attribute4\":\"text\"},\"attribute1\":\"hello world\",\"attribute2\":555}",
:fizziness => "0",
:serving_temperature => "0",
:additional_search_term => "{NA1,NA2}")
id_keys is the primary key columns
"""
# function generateUpdateSQL(table_name::String, update_data::Dict{Symbol, Any}, id_keys::Vector{Symbol})
# set_clauses = String[]
# where_clauses = String[]
# for (key, value) in update_data
# if key in id_keys
# push!(where_clauses, "$key = '$value'")
# else
# if key == :other_attributes
# push!(set_clauses, "$key = '$value'")
# else
# push!(set_clauses, "$key = '$value'")
# end
# end
# end
# set_clause = join(set_clauses, ", ")
# where_clause = join(where_clauses, " AND ")
# return "UPDATE $table_name SET $set_clause WHERE $where_clause;"
# end
function generateUpdateSQL(table_name::String, columnToUpdate::Vector{Symbol},
updatedata::Dict{Symbol, Any}, id_keys::Vector{Symbol})
set_clauses = String[]
where_clauses = String[]
for (key, value) in updatedata
if key in id_keys
push!(where_clauses, "$key = '$value'")
else
if key ∈ columnToUpdate # update only specified columns
push!(set_clauses, "$key = '$value'")
end
end
end end
set_clause = join(set_clauses, ", ") columns_str = join(columns, ", ")
where_clause = join(where_clauses, " AND ") values_str = join(values, ", ")
return "UPDATE $table_name SET $set_clause WHERE $where_clause;" return "INSERT INTO $table_name ($columns_str) VALUES ($values_str);"
end end
# ---------------------------------------------- 100 --------------------------------------------- #
""" generateUpdateSQL - Generate SQL UPDATE statement from dictionary data
This function constructs a SQL UPDATE statement by updating multiple columns
based on a primary key condition.
# Arguments:
- `table_name::String` - Name of the database table to update
- `pk_column::Symbol` - The primary key column name
- `pk_value` - The primary key value (used in WHERE clause)
- `data::Dict{Symbol, Any}` - Dictionary containing column-value pairs to update
# Return:
- A String containing the SQL UPDATE statement
# Example
```jldoctest
julia> using UUIDs
# Update multiple columns using a dictionary
table_name = "wine"
pk_column = :wine_id
pk_value = "8f3c7a2e-1b4d-4a9f-9c2e-4a8b3d6e5f7a"
data = Dict{Symbol, Any}(
:acidity => "full",
:tannin => "medium",
:country => "Italy"
)
julia> generateUpdateSQL(table_name, pk_column, pk_value, data)
"UPDATE wine SET acidity = 'full', tannin = 'medium', country = 'Italy' WHERE wine_id = '8f3c7a2e-1b4d-4a9f-9c2e-4a8b3d6e5f7a';"
```
"""
function generateUpdateSQL(table_name::String, pk_column::String, pk_value,
data::AbstractDict{String, Any})
# Build SET clause
set_parts = String[]
for (key, value) in data
if key ∉ [pk_column]
value_str = isa(value, AbstractString) ? "'$value'" : "$value"
push!(set_parts, "$(string(key)) = $value_str")
end
end
set_clause = join(set_parts, ", ")
# Handle primary key value
pk_val_str = isa(pk_value, AbstractString) ? "'$pk_value'" : "$pk_value"
return "UPDATE $table_name SET $set_clause WHERE $pk_column = $pk_val_str;"
end
function generateUpdateSQL(table_name::String, pk_dict::AbstractDict{String, Any},
data::AbstractDict{String, Any})
# Build SET clause
set_parts = String[]
for (key, value) in data
if key ∉ keys(pk_dict)
value_str = isa(value, AbstractString) ? "'$value'" : "$value"
push!(set_parts, "$(string(key)) = $value_str")
end
end
set_clause = join(set_parts, ", ")
# Build WHERE clause for composite keys
where_parts = String[]
for (col, val) in pk_dict
val_str = isa(val, AbstractString) ? "'$val'" : "$val"
push!(where_parts, "$(string(col)) = $val_str")
end
where_clause = join(where_parts, " AND ")
return "UPDATE $table_name SET $set_clause WHERE $where_clause;"
end
end # module end # module
+565
View File
@@ -0,0 +1,565 @@
module garageS3
export
LifecycleExpiration, build_lifecycle_xml,
GarageStorage, s3PutFile, s3GetFile, s3ListFiles, s3DeleteFile,
s3SetLifecycleExpiration, s3GetLifecycle, s3DeleteLifecycle,
s3SignUrl, s3SignUrlWeb
using AWS
@service S3
using AWSS3
using Dates: Dates
using URIs: URIs
using OrderedCollections: OrderedDict
using MbedTLS: digest, MD_SHA256
using Base64: bytes2hex
# ---------------------------------------------- 100 --------------------------------------------- #
# Garage uses Path-Style routing (https://s3-api.my-domain.com/bucket/key).
# this file use local AWS config
""" Example
storage1 = GeneralUtils.GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e", # key ID (create at garage-ui.yiem.cc)
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1", # key ID's secret key
"sommpanion"
)
# Safe to run inside concurrent HTTP handlers (e.g., Oxygen.jl, HTTP.jl)
# use UUID as filename because GarageS3 requires unique filename for each uploaded object
urls = GeneralUtils.s3PutFile(storage1, "transferjob-(GeneralUtils.uuid4snakecase())", "{\"status\": \"inactive\"}")
key = GeneralUtils.s3ListFiles(storage)
println("Read back: ", data)
println("Bucket keys: ", key)
# test with curl
curl -v \
-H 'Host: testbucket.s3-web.yiem.cc' \
http://192.168.88.106:3902/users-1002.json
# test with API
data = String(GeneralUtils.s3GetFile(storage, key[1]))
# test with a browser (urls.web)
https://s3-web.mydomain.com/my_bucket_name/users-1005.json
"""
# ===================================================================
# 1. Custom GarageConfig Definition (Thread-Safe, No Global State)
# ===================================================================
mutable struct SimpleCredentials
access_key_id::String
secret_key::String
token::String
end
mutable struct GarageConfig <: AWS.AbstractAWSConfig
endpoint::String
region::String
credentials::SimpleCredentials
end
# Required extensions for AWS.jl pipeline
AWS.refresh!(c::SimpleCredentials; force::Bool=false) = c
AWS.credentials(c::SimpleCredentials) = c
AWS.check_credentials(c::SimpleCredentials) = c
AWS.region(aws::GarageConfig) = aws.region
AWS.credentials(aws::GarageConfig) = aws.credentials
""" Generate the full service URL including the resource path for a Garage S3 request.
# Arguments
- `aws::GarageConfig`
The Garage configuration containing the endpoint.
- `service::String`
The AWS service name (e.g., `"s3"`).
- `resource::String`
The S3 resource path (e.g., `"/bucket/key"`).
# Return
- `String`: The full URL combining the endpoint and resource path.
"""
function AWS.generate_service_url(aws::GarageConfig, service::String, resource::String)
endpoint = strip(aws.endpoint, '/')
resource_path = startswith(resource, '/') ? resource : "/" * resource
return string(endpoint, resource_path)
end
# ===================================================================
# 2. Thread-Safe Storage Client Wrapper
# ===================================================================
""" Create a thread-safe Garage S3 storage client.
# Arguments
- `endpoint::String`
The Garage S3 API endpoint URL (e.g., `"https://s3-api.yiem.cc"`).
- `key::String`
The Garage access key ID (created via garage-ui).
- `secret::String`
The secret key corresponding to the access key.
- `bucket::String`
The name of the S3 bucket to use.
# Keyword Arguments
- `region::String = "garage"`
The region identifier for the Garage instance.
# Return
- `GarageStorage`: A thread-safe storage client instance.
# Examples
```jldoctest
julia> storage = GarageStorage("https://s3-api.yiem.cc", "GKb08015", "55114ff94828febca1", "sommpanion-s3")
GarageStorage(GarageConfig(...), "sommpanion-s3")
```
"""
mutable struct GarageStorage
config::GarageConfig
bucket::String
end
function GarageStorage(endpoint::String, key::String, secret::String, bucket::String; region::String="garage")
creds = SimpleCredentials(key, secret, "")
config = GarageConfig(endpoint, region, creds)
return GarageStorage(config, bucket)
end
""" Upload an object to the Garage S3 bucket (callable struct).
# Arguments
- `key::String`
The object key (name) in the bucket.
- `data::Union{String, Vector{UInt8}}`
The data to upload.
# Return
- `NamedTuple{(:api, :web)}`: A tuple with `api` and `web` URLs.
# Examples
```jldoctest
julia> storage1 = GarageStorage("https://s3-api.yiem.cc", "GKb08015", "55114ff94828febca1", "sommpanion-s3")
julia> s3PutFile1 = s3PutFile(storage1)
julia> downloadUrl = s3PutFile1("test.json", "{\"status\": \"active\"}")
Successfully uploaded: test.json
julia> downloadUrl.api
"https://s3-api.yiem.cc/sommpanion-s3/test.json"
julia> downloadUrl.web
"https://s3-web.yiem.cc/sommpanion-s3/test.json"
```
"""
mutable struct s3PutFile
storage::GarageStorage
end
function (pf::s3PutFile)(key::String, data::Union{String, Vector{UInt8}}
)::NamedTuple{(:api, :web), Tuple{String, String}}
AWSS3.s3_put(pf.storage.config, pf.storage.bucket, key, data)
println("Successfully uploaded: ", key)
# object url
api = "$(pf.storage.config.endpoint)/$(pf.storage.bucket)/$key"
# file download URL using browser
web = replace(api, "s3-api" => "s3-web")
return (api=api, web=web)
end
""" Upload an object to the Garage S3 bucket.
# Arguments
- `storage::GarageStorage`
The storage client instance.
- `key::String`
The object key (name) in the bucket.
- `data::Union{String, Vector{UInt8}}`
The data to upload.
# Return
- `NamedTuple{(:api, :web)}`: A tuple with `api` and `web` URLs.
# Examples
```julia
julia> result = s3PutFile(storage, "test.json", "{\"status\": \"active\"}")
Successfully uploaded: test.json
julia> result.api
"https://s3-api.yiem.cc/sommpanion-s3/test.json"
julia> result.web
"https://s3-web.yiem.cc/sommpanion-s3/test.json"
```
"""
function s3PutFile(storage::GarageStorage, key::String, data::Union{String, Vector{UInt8}}
)::NamedTuple{(:api, :web), Tuple{String, String}}
AWSS3.s3_put(storage.config, storage.bucket, key, data)
println("Successfully uploaded: ", key)
# object url
api = "$(storage.config.endpoint)/$(storage.bucket)/$key"
# file download URL using browser
web = replace(api, "s3-api" => "s3-web")
return (api=api, web=web)
end
""" Download an object from the Garage S3 bucket.
# Arguments
- `storage::GarageStorage`
The storage client instance.
- `key::String`
The object key (name) in the bucket.
# Return
- `Vector{UInt8}`: The raw bytes of the downloaded object.
# Examples
```julia
julia> data = String(s3GetFile(storage, "test.json"))
"\"{\\\"status\\\": \\\"active\\\"}\""
```
"""
function s3GetFile(storage::GarageStorage, key::String)::Union{Vector{UInt8}, Nothing}
try
return AWSS3.s3_get(storage.config, storage.bucket, key; raw=true)
catch
return nothing
end
end
""" List all object keys in the Garage S3 bucket.
# Arguments
- `storage::GarageStorage`
The storage client instance.
# Return
- `Vector{String}`: A list of object keys (file names) in the bucket.
# Examples
```julia
julia> keys = s3ListFiles(storage)
3-element Vector{String}:
"test1.json"
"test2.json"
"users-1002.json"
```
"""
function s3ListFiles(storage::GarageStorage)
# Use delimiter="" to get all individual keys (no grouping by "directory")
objects = AWSS3.s3_list_objects(storage.config, storage.bucket; delimiter="")
return [obj["Key"] for obj in objects]
end
""" Delete an object from the Garage S3 bucket.
# Arguments
- `storage::GarageStorage`
The storage client instance.
- `key::String`
The object key (name) to delete.
# Examples
```julia
julia> s3DeleteFile(storage, "test.json")
```
"""
function s3DeleteFile(storage::GarageStorage, key::String)
AWSS3.s3_delete(storage.config, storage.bucket, key)
end
"""
s3SignUrl(storage, key, seconds=3600; verb="GET", content_type="application/octet-stream", signature_version="v4") -> String
Generate a pre-signed URL for an object in the Garage S3 bucket.
A pre-signed URL grants temporary access without AWS credentials. Signature is computed
using AWS Signature Version 4 (HMAC-SHA256).
# Arguments
- `storage::GarageStorage`: Storage client from `GarageStorage(endpoint, key, secret, bucket)`.
- `key::String`: Object key. Supports nested paths like `"folder/subfolder/file.txt"`.
- `seconds::Int`: URL validity in seconds. Default: 3600.
# Keyword Arguments
- `verb::String = "GET"`: HTTP method (`"GET"` downloads, `"PUT"` uploads).
- `content_type::String = "application/octet-stream"`: Required `Content-Type` header.
For PUT, set to the file's MIME type (`"image/png"`, `"application/json"`, etc.).
- `signature_version::String = "v4"`: Always use `"v4"` (v2 is deprecated).
# Return
`String`: The pre-signed URL.
# Examples
```julia
using GeneralUtils: GarageStorage, s3SignUrl, s3ListFiles, s3PutFile
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"sommpanion"
)
# Upload — PUT with curl
url = s3SignUrl(storage, "photo.jpg", 3600; verb="PUT", content_type="image/jpeg")
# curl -X PUT -T "/path/to/photo.jpg" -H 'Host: s3-api.yiem.cc' -H 'Content-Type: image/jpeg' <url>
# Download — GET with curl
url = s3SignUrl(storage, "photo.jpg", 3600; verb="GET")
# curl <url> → returns file content
# Upload JSON
url = s3SignUrl(storage, "data/config.json", 3600; verb="PUT", content_type="application/json")
# curl -X PUT -T "/tmp/config.json" -H 'Host: s3-api.yiem.cc' -H 'Content-Type: application/json' <url>
# Delete
url = s3SignUrl(storage, "photo.jpg", 3600; verb="DELETE")
# curl -X DELETE url
# Multiple uploads (chat app)
urls = [s3SignUrl(storage, "chat/\$(GeneralUtils.uuid4snakecase())", 300;
verb="PUT", content_type="image/png")
for _ in 1:10]
# Signature differs by verb and content_type
url_get = s3SignUrl(storage, "file.txt", 3600; verb="GET")
url_put = s3SignUrl(storage, "file.txt", 3600; verb="PUT", content_type="text/plain")
```
# Notes
- URLs are valid until `seconds` expires; they can be used **multiple times** (not one-time).
- Server clocks must be within ~5 minutes of the Garage server (UTC time in signature).
- PUT uploads require the client's `Content-Type` to match `content_type`.
- For browser CORS uploads, configure Garage bucket CORS rules for `Origin` and `Method`.
"""
function s3SignUrl(
storage::GarageStorage,
key::String,
seconds::Int=3600;
verb::String="GET",
content_type::String="application/octet-stream",
signature_version::String="v4",
)::String
config = storage.config
creds = config.credentials
bucket = storage.bucket
region = config.region
endpoint = strip(config.endpoint, '/')
scheme = "AWS4"
algorithm = "HMAC-SHA256"
terminator = "aws4_request"
service = "s3"
now_datetime = Dates.now(Dates.UTC)
datetime_stamp = Dates.format(now_datetime, "YYYYmmddTHHMMSS\\Z")
date_stamp = Dates.format(now_datetime, "YYYYmmdd")
scope = "$date_stamp/$region/$service/$terminator"
headers = OrderedDict{String,String}("Host" => URIs.URI(endpoint).host)
if verb == "PUT"
headers["Content-Type"] = content_type
end
sort!(headers; by=name -> lowercase(name))
canonical_header_names = join(map(name -> lowercase(name), collect(keys(headers))), ";")
query = OrderedDict{String,String}(
"X-Amz-Expires" => string(seconds),
"X-Amz-Algorithm" => "$scheme-$algorithm",
"X-Amz-Credential" => "$(creds.access_key_id)/$scope",
"X-Amz-Date" => datetime_stamp,
"X-Amz-SignedHeaders" => canonical_header_names,
)
if !isempty(creds.token)
query["X-Amz-Security-Token"] = creds.token
end
canonical_headers = join(
map(
header -> "$(lowercase(header.first)):$(lowercase(header.second))\n",
collect(headers),
),
)
resource_path = "/$bucket/$key"
# Build canonical query string: sort by key=value pair lexicographically,
# URL-encoding each key and value (matching Garage's uri_encode)
sorted_q = sort(
[URIs.escapeuri(k) * "=" * URIs.escapeuri(v) for (k, v) in pairs(query)],
by=lowercase,
)
canonical_query = join(sorted_q, "&")
canonical_request = string(
"$verb\n",
resource_path,
"\n",
canonical_query,
"\n",
canonical_headers,
"\n",
canonical_header_names,
"\n",
"UNSIGNED-PAYLOAD",
)
string_to_sign = string(
"$scheme-$algorithm\n",
"$datetime_stamp\n",
"$scope\n",
bytes2hex(digest(MD_SHA256, canonical_request)),
)
key_secret_bytes = Vector{UInt8}(string(scheme, creds.secret_key))
key_date = digest(MD_SHA256, date_stamp, key_secret_bytes)
key_region = digest(MD_SHA256, region, key_date)
key_service = digest(MD_SHA256, service, key_region)
key_signing = digest(MD_SHA256, terminator, key_service)
signature = digest(MD_SHA256, string_to_sign, key_signing)
query["X-Amz-Signature"] = bytes2hex(signature)
query_string = URIs.escapeuri(query)
return "$(endpoint)/$bucket/$key?$query_string"
end
""" Generate a pre-signed URL using the Garage S3 web endpoint (s3-web).
Useful for direct browser access — URLs look like
`https://s3-web.yiem.cc/bucket/key?X-Amz-Signature=...`
Arguments and keyword arguments are the same as `s3SignUrl`.
"""
function s3SignUrlWeb(
storage::GarageStorage,
key::String,
seconds::Int=3600;
verb::String="GET",
content_type::String="application/octet-stream",
signature_version::String="v4",
)::String
web_endpoint = replace(storage.config.endpoint, "s3-api" => "s3-web")
web_creds = SimpleCredentials(
storage.config.credentials.access_key_id,
storage.config.credentials.secret_key,
storage.config.credentials.token,
)
web_config = GarageConfig(web_endpoint, storage.config.region, web_creds)
web_storage = GarageStorage(web_config, storage.bucket)
return s3SignUrl(web_storage, key, seconds; verb, content_type, signature_version)
end
# ===================================================================
# 3. Bucket Lifecycle Configuration
# ===================================================================
""" Lifecycle expiration configuration for a bucket.
# Fields
- `prefix::String`: Object key prefix this rule applies to.
- `days::Int`: Number of days after object creation to expire/delete.
- `enabled::Bool`: Whether the rule is active (default: `true`).
- `id::String`: Unique identifier for the rule (default: auto-generated).
"""
mutable struct LifecycleExpiration
prefix::String
days::Int
enabled::Bool
id::String
end
function LifecycleExpiration(prefix::String, days::Int; enabled::Bool=true, id::String="")
rule_id = isempty(id) ? "expire-" * replace(prefix, "/" => "_") * "-" * string(days) * "d" : id
return LifecycleExpiration(prefix, days, enabled, rule_id)
end
""" Build the XML body for a PutBucketLifecycleConfiguration request.
Supports a single rule with expiration by prefix.
"""
function build_lifecycle_xml(rule::LifecycleExpiration)::String
status = rule.enabled ? "Enabled" : "Disabled"
return """<?xml version="1.0" encoding="UTF-8"?>
<LifecycleConfiguration>
<Rule>
<ID>$(rule.id)</ID>
<Filter>
<Prefix>$(rule.prefix)</Prefix>
</Filter>
<Status>$status</Status>
<Expiration>
<Days>$(rule.days)</Days>
</Expiration>
</Rule>
</LifecycleConfiguration>"""
end
""" Set bucket lifecycle expiration rule.
# Arguments
- `storage::GarageStorage`: The storage client instance.
- `rule::LifecycleExpiration`: The lifecycle expiration rule.
# Returns
- `Dict{String, Any}`: Parsed response from the server.
# Example
```julia
rule = LifecycleExpiration("uploads/", 30)
s3SetLifecycleExpiration(storage, rule)
```
"""
function s3SetLifecycleExpiration(storage::GarageStorage, rule::LifecycleExpiration)
xml_body = build_lifecycle_xml(rule)
args = Dict{String,Any}("body" => xml_body)
return S3.put_bucket_lifecycle_configuration(storage.bucket, args; aws_config=storage.config)
end
""" Get the bucket lifecycle configuration.
# Arguments
- `storage::GarageStorage`: The storage client instance.
# Returns
- `Dict{String, Any}`: Parsed lifecycle configuration, or `nothing` if no lifecycle is configured.
# Example
```julia
config = s3GetLifecycle(storage)
```
"""
function s3GetLifecycle(storage::GarageStorage)::Union{Dict{String,Any},Nothing}
try
return S3.get_bucket_lifecycle_configuration(storage.bucket; aws_config=storage.config)
catch e
if isa(e, AWS.AWSException) && e.code == "NoSuchLifecycleConfiguration"
return nothing
end
rethrow(e)
end
end
""" Delete the bucket lifecycle configuration.
# Arguments
- `storage::GarageStorage`: The storage client instance.
# Returns
- `Dict{String, Any}`: Parsed response from the server.
# Example
```julia
s3DeleteLifecycle(storage)
```
"""
function s3DeleteLifecycle(storage::GarageStorage)
return S3.delete_bucket_lifecycle(storage.bucket; aws_config=storage.config)
end
end # module GarageS3
+736 -142
View File
File diff suppressed because it is too large Load Diff
+1052 -173
View File
File diff suppressed because it is too large Load Diff
+554 -238
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -0,0 +1,3 @@
{
"julia.environmentPath": "/appfolder/app/dev/GeneralUtils/test"
}
+41
View File
@@ -0,0 +1,41 @@
# This file is machine-generated - editing it directly is not advised
julia_version = "1.11.4"
manifest_format = "2.0"
project_hash = "71d91126b5a1fb1020e1098d9d492de2a4438fd2"
[[deps.Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
version = "1.11.0"
[[deps.InteractiveUtils]]
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
version = "1.11.0"
[[deps.Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
version = "1.11.0"
[[deps.Markdown]]
deps = ["Base64"]
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
version = "1.11.0"
[[deps.Random]]
deps = ["SHA"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
version = "1.11.0"
[[deps.SHA]]
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
version = "0.7.0"
[[deps.Serialization]]
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
version = "1.11.0"
[[deps.Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
version = "1.11.0"
+2
View File
@@ -0,0 +1,2 @@
[deps]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
+130
View File
@@ -0,0 +1,130 @@
curl -X PUT -H "Content-Type: application/json" \
-d '{"test": "data"}' \
"https://s3-api.yiem.cc/sommpanion/pcimage.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260904%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260904T103745Z&X-Amz-Expires=300&X-Amz-Security-Token=&X-Amz-SignedHeaders=host&X-Amz-Signature=0e195a48f824a2f8ffcb06461396cd6a8bddd5b61d93e9006f947ae10ecf525f"
curl -v -X PUT -T "/home/ton/docker-apps/sommpanion/etc/GeneralUtils/photo.jpg" \
-H 'Host: s3-api.yiem.cc' \
-H 'Content-Type: image/jpeg' \
"https://s3-api.yiem.cc/sommpanion/photo.jpg?X-Amz-Expires=300&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260905%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260905T030315Z&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=1107a31f36f8b8ceb9663d69b9a7be7733df14d019e700e750944cbdad50df5d"
read
./garage.toml
./Caddyfile
./src/garageS3.jl
julia> url = GeneralUtils.s3_sign_url(storage1, "photo.jpg", 36000; verb="PUT", content_type="image/jpeg")
"https://s3-api.yiem.cc/sommpanion/photo.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260904%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260904T145004Z&X-Amz-Expires=36000&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=92cd634dbb0f66db4b8b039ef5939c138203de260e8342fe27ef78979d90a824"
---
ton@server12vm-dev:~/docker-apps/sommpanion/etc/AWS.jl$
curl -v -X PUT -T "/home/ton/docker-apps/sommpanion/etc/GeneralUtils/photo.jpg" \
-H 'Host: s3-api.yiem.cc' \
-H 'Content-Type: image/jpeg' \
"https://s3-api.yiem.cc/sommpanion/photo.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260904%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260904T152217Z&X-Amz-Expires=36000&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=7eb874abb813427a71beab956514c3a0539cacf765013aa194be8517dd081f02"
Note: Unnecessary use of -X or --request, PUT is already inferred.
* Trying 110.77.160.154:443...
* Connected to s3-api.yiem.cc (110.77.160.154) port 443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: /etc/ssl/certs
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_CHACHA20_POLY1305_SHA256
* ALPN: server accepted h2
* Server certificate:
* subject: CN=s3-api.yiem.cc
* start date: Aug 27 04:27:02 2026 GMT
* expire date: Nov 25 04:27:01 2026 GMT
* subjectAltName: host "s3-api.yiem.cc" matched cert's "s3-api.yiem.cc"
* issuer: C=US; O=Let's Encrypt; CN=YE2
* SSL certificate verify ok.
* using HTTP/2
* h2h3 [:method: PUT]
* h2h3 [:path: /sommpanion/photo.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260904%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260904T152217Z&X-Amz-Expires=36000&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=7eb874abb813427a71beab956514c3a0539cacf765013aa194be8517dd081f02]
* h2h3 [:scheme: https]
* h2h3 [:authority: s3-api.yiem.cc]
* h2h3 [user-agent: curl/7.88.1]
* h2h3 [accept: */*]
* h2h3 [content-type: image/jpeg]
* h2h3 [content-length: 439490]
* Using Stream ID: 1 (easy handle 0x559a08824c80)
> PUT /sommpanion/photo.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260904%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260904T152217Z&X-Amz-Expires=36000&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=7eb874abb813427a71beab956514c3a0539cacf765013aa194be8517dd081f02 HTTP/2
> Host: s3-api.yiem.cc
> user-agent: curl/7.88.1
> accept: */*
> content-type: image/jpeg
> content-length: 439490
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* We are completely uploaded and fine
< HTTP/2 403
< access-control-allow-origin: *
< alt-svc: h3=":443"; ma=2592000
< content-type: application/xml
< date: Fri, 04 Sep 2026 15:23:13 GMT
< via: 1.1 Caddy
< content-length: 190
<
* Connection #0 to host s3-api.yiem.cc left intact
<?xml version="1.0" encoding="UTF-8"?><Error><Code>AccessDenied</Code><Message>Forbidden: Invalid signature</Message><Resource>/sommpanion/photo.jpg</Resource><Region>garage</Region></Error>
2026-09-04T15:23:13.796037Z INFO garage_api_common::generic_server: 110.77.160.154 (via 192.168.88.21:57926) PUT /sommpanion/photo.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260904%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260904T152217Z&X-Amz-Expires=36000&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=7eb874abb813427a71beab956514c3a0539cacf765013aa194be8517dd081f02
2026-09-04T15:23:13.796077Z DEBUG garage_api_common::generic_server: Request { method: PUT, uri: /sommpanion/photo.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260904%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260904T152217Z&X-Amz-Expires=36000&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=7eb874abb813427a71beab956514c3a0539cacf765013aa194be8517dd081f02, version: HTTP/1.1, headers: {"host": "s3-api.yiem.cc", "user-agent": "curl/7.88.1", "content-length": "439490", "accept": "*/*", "content-type": "image/jpeg", "via": "2.0 Caddy", "x-forwarded-for": "110.77.160.154", "x-forwarded-host": "s3-api.yiem.cc", "x-forwarded-proto": "https", "accept-encoding": "gzip"}, body: Body(Streaming) }
2026-09-04T15:23:13.796181Z DEBUG garage_api_common::generic_server: Endpoint: PutObject
2026-09-04T15:23:13.796461Z INFO garage_api_common::generic_server: error 403 Forbidden, Forbidden: Invalid signature in response to 110.77.160.154 (via 192.168.88.21:57926) PUT /sommpanion/photo.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=GKb080154a2e5b19100b1b2c6e%2F20260904%2Fgarage%2Fs3%2Faws4_request&X-Amz-Date=20260904T152217Z&X-Amz-Expires=36000&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=7eb874abb813427a71beab956514c3a0539cacf765013aa194be8517dd081f02
-44
View File
@@ -1,44 +0,0 @@
using Revise
using GeneralUtils, MQTTClient, JSON3
mqttMsgReceiveTopic = ["/receivetopic_1", "/receivetopic_2"]
mqttMsgReceiveChannel = (ch1=Channel(8), ch2=Channel(32))
keepaliveChannel = Channel(8)
function onMsgCallback(topic, payload)
jobj = JSON3.read(String(payload))
incomingMqttMsg = copy(jobj) # convert json object into julia dictionary recursively
if occursin("topic_1", topic)
put!(mqttMsgReceiveChannel[:ch1], incomingMqttMsg)
elseif occursin("topic_2", topic)
put!(mqttMsgReceiveChannel[:ch2], incomingMqttMsg)
elseif occursin("keepalive", topic)
put!(keepaliveChannel, incomingMqttMsg)
else
println("undefined condition ", @__FILE__, " ", @__LINE__)
end
end
mqttInstance = GeneralUtils.mqttClientInstance_v2(
"mqtt.yiem.cc",
mqttMsgReceiveTopic,
mqttMsgReceiveChannel,
keepaliveChannel,
onMsgCallback
)
_ = GeneralUtils.checkMqttConnection!(mqttInstance)
println("GeneralUtils test done")
+693
View File
@@ -0,0 +1,693 @@
using Test
using GeneralUtils
using GeneralUtils.garageS3
using HTTP
@testset "garageS3.jl" begin
# --- SimpleCredentials ---
@testset "SimpleCredentials construction" begin
creds = GeneralUtils.garageS3.SimpleCredentials("AKIAIOSFODNN7EXAMPLE", "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY", "sessiontoken")
@test creds.access_key_id == "AKIAIOSFODNN7EXAMPLE"
@test creds.secret_key == "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
@test creds.token == "sessiontoken"
end
@testset "SimpleCredentials AWS extensions" begin
creds = GeneralUtils.garageS3.SimpleCredentials("key1", "secret1", "token1")
@test GeneralUtils.garageS3.AWS.credentials(creds) === creds
@test GeneralUtils.garageS3.AWS.check_credentials(creds) === creds
@test GeneralUtils.garageS3.AWS.refresh!(creds; force=false) === creds
@test GeneralUtils.garageS3.AWS.refresh!(creds) === creds
end
# --- GarageConfig ---
@testset "GarageConfig construction" begin
creds = GeneralUtils.garageS3.SimpleCredentials("key", "secret", "")
config = GeneralUtils.garageS3.GarageConfig("https://s3-api.example.com", "us-east-1", creds)
@test config.endpoint == "https://s3-api.example.com"
@test config.region == "us-east-1"
@test config.credentials === creds
@test config isa GeneralUtils.garageS3.AWS.AbstractAWSConfig
end
@testset "GarageConfig AWS extensions" begin
creds = GeneralUtils.garageS3.SimpleCredentials("key", "secret", "")
config = GeneralUtils.garageS3.GarageConfig("https://s3-api.example.com", "garage", creds)
@test GeneralUtils.garageS3.AWS.region(config) == "garage"
@test GeneralUtils.garageS3.AWS.credentials(config) === creds
end
# --- GeneralUtils.garageS3.AWS.generate_service_url ---
@testset "generate_service_url with resource starting with /" begin
creds = GeneralUtils.garageS3.SimpleCredentials("key", "secret", "")
config = GeneralUtils.garageS3.GarageConfig("https://s3-api.example.com", "garage", creds)
url = GeneralUtils.garageS3.AWS.generate_service_url(config, "s3", "/mybucket/key")
@test url == "https://s3-api.example.com/mybucket/key"
end
@testset "generate_service_url with resource NOT starting with /" begin
creds = GeneralUtils.garageS3.SimpleCredentials("key", "secret", "")
config = GeneralUtils.garageS3.GarageConfig("https://s3-api.example.com", "garage", creds)
url = GeneralUtils.garageS3.AWS.generate_service_url(config, "s3", "mybucket/key")
@test url == "https://s3-api.example.com/mybucket/key"
end
@testset "generate_service_url strips trailing slashes from endpoint" begin
creds = GeneralUtils.garageS3.SimpleCredentials("key", "secret", "")
config = GeneralUtils.garageS3.GarageConfig("https://s3-api.example.com/", "garage", creds)
url = GeneralUtils.garageS3.AWS.generate_service_url(config, "s3", "/bucket/key")
@test url == "https://s3-api.example.com/bucket/key"
end
@testset "generate_service_url with multiple trailing slashes" begin
creds = GeneralUtils.garageS3.SimpleCredentials("key", "secret", "")
config = GeneralUtils.garageS3.GarageConfig("https://s3-api.example.com///", "garage", creds)
url = GeneralUtils.garageS3.AWS.generate_service_url(config, "s3", "/bucket/key")
@test url == "https://s3-api.example.com/bucket/key"
end
@testset "generate_service_url preserves http endpoint" begin
creds = GeneralUtils.garageS3.SimpleCredentials("key", "secret", "")
config = GeneralUtils.garageS3.GarageConfig("http://localhost:3900", "garage", creds)
url = GeneralUtils.garageS3.AWS.generate_service_url(config, "s3", "/bucket/key")
@test url == "http://localhost:3900/bucket/key"
end
@testset "generate_service_url with http endpoint and trailing slash" begin
creds = GeneralUtils.garageS3.SimpleCredentials("key", "secret", "")
config = GeneralUtils.garageS3.GarageConfig("http://localhost:3900/", "garage", creds)
url = GeneralUtils.garageS3.AWS.generate_service_url(config, "s3", "/bucket/key")
@test url == "http://localhost:3900/bucket/key"
end
# --- GarageStorage ---
@testset "GarageStorage default region" begin
storage = GarageStorage("https://s3-api.example.com", "key123", "secret123", "mybucket")
@test storage.bucket == "mybucket"
@test storage.config.region == "garage"
@test storage.config.endpoint == "https://s3-api.example.com"
end
@testset "GarageStorage custom region" begin
storage = GarageStorage("https://s3-api.example.com", "key123", "secret123", "mybucket"; region="custom-region")
@test storage.config.region == "custom-region"
end
@testset "GarageStorage endpoint without https" begin
storage = GarageStorage("http://localhost:3900", "key", "secret", "mybucket")
@test storage.config.endpoint == "http://localhost:3900"
end
@testset "GarageStorage credentials are SimpleCredentials" begin
storage = GarageStorage("https://s3-api.example.com", "mykey", "mysecret", "mybucket")
@test storage.config.credentials isa GeneralUtils.garageS3.SimpleCredentials
@test storage.config.credentials.access_key_id == "mykey"
@test storage.config.credentials.secret_key == "mysecret"
@test storage.config.credentials.token == ""
end
@testset "GarageStorage returns correct struct type" begin
storage = GarageStorage("https://s3-api.example.com", "key", "secret", "bucket")
@test storage isa GarageStorage
end
# --- s3PutFile callable struct ---
@testset "s3PutFile callable struct type is correct" begin
storage = GarageStorage("https://s3-api.example.com", "key", "secret", "bucket")
uploader = s3PutFile(storage)
@test uploader isa s3PutFile
end
@testset "s3PutFile callable struct construction stores storage" begin
storage = GarageStorage("https://s3-api.example.com", "key", "secret", "bucket")
uploader = s3PutFile(storage)
@test uploader.storage === storage
end
# --- Integration tests with real Garage server ---
@testset "integration: full CRUD lifecycle" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "testrunner-$(GeneralUtils.uuid4snakecase()).json"
test_data = "{\"status\": \"testing\", \"runner\": \"runtests\"}"
# Test s3PutFile(storage, key, data) - successful upload
result = s3PutFile(storage, test_key, test_data)
@test result !== nothing
@test haskey(result, :api)
@test haskey(result, :web)
@test occursin("testbucket", result.api)
@test occursin("s3-api", result.api)
@test occursin("s3-web", result.web)
# Test s3GetFile - retrieve the uploaded data
downloaded = s3GetFile(storage, test_key)
@test downloaded !== nothing
@test downloaded isa Vector{UInt8}
@test String(downloaded) == test_data
# Test s3ListFiles - verify key appears in listing
keys = s3ListFiles(storage)
@test test_key in keys
# Test s3PutFile callable struct
test_key2 = "testrunner-callable-$(GeneralUtils.uuid4snakecase()).json"
callable_result = s3PutFile(storage)(test_key2, "callable-data")
@test callable_result !== nothing
@test callable_result.api != ""
@test callable_result.web != ""
# Verify callable upload
downloaded2 = s3GetFile(storage, test_key2)
@test String(downloaded2) == "callable-data"
# Test s3DeleteFile
s3DeleteFile(storage, test_key)
deleted_data = s3GetFile(storage, test_key)
@test deleted_data === nothing
# Cleanup callable test object
s3DeleteFile(storage, test_key2)
deleted_data2 = s3GetFile(storage, test_key2)
@test deleted_data2 === nothing
end
@testset "integration: nested key CRUD - single level" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "single/slash/test-$(GeneralUtils.uuid4snakecase()).json"
test_data = "{\"level\": 1, \"nested\": true}"
# Upload nested key
result = s3PutFile(storage, test_key, test_data)
@test result isa NamedTuple
@test haskey(result, :api)
@test haskey(result, :web)
@test occursin("single/slash/", result.api)
@test occursin("single/slash/", result.web)
# Download and verify
downloaded = s3GetFile(storage, test_key)
@test downloaded !== nothing
@test String(downloaded) == test_data
# Verify in listing
keys = s3ListFiles(storage)
@test test_key in keys
# Delete and verify gone
s3DeleteFile(storage, test_key)
@test s3GetFile(storage, test_key) === nothing
end
@testset "integration: nested key CRUD - multi level" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "deep/nested/folder/subfolder/test-$(GeneralUtils.uuid4snakecase()).json"
test_data = "{\"deeply\": \"nested\", \"path\": \"deep/nested/folder/subfolder/\"}"
# Upload deeply nested key
result = s3PutFile(storage, test_key, test_data)
@test result isa NamedTuple
@test occursin("deep/nested/folder/subfolder/", result.api)
@test occursin("s3-api", result.api)
@test occursin("s3-web", result.web)
# Download and verify
downloaded = s3GetFile(storage, test_key)
@test downloaded !== nothing
@test String(downloaded) == test_data
# Verify in listing
keys = s3ListFiles(storage)
@test test_key in keys
# Delete and verify gone
s3DeleteFile(storage, test_key)
@test s3GetFile(storage, test_key) === nothing
end
@testset "integration: nested key with callable struct" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "callable/nested/test-$(GeneralUtils.uuid4snakecase()).json"
test_data = "{\"callable\": true, \"nested\": true}"
uploader = s3PutFile(storage)
result = uploader(test_key, test_data)
@test result isa NamedTuple
@test occursin("callable/nested/", result.api)
downloaded = s3GetFile(storage, test_key)
@test String(downloaded) == test_data
s3DeleteFile(storage, test_key)
@test s3GetFile(storage, test_key) === nothing
end
@testset "integration: s3GetFile returns nothing for missing key" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
result = s3GetFile(storage, "nonexistent-key-$(GeneralUtils.uuid4snakecase()).json")
@test result === nothing
end
@testset "integration: binary data upload and download" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "testrunner-binary-$(GeneralUtils.uuid4snakecase()).bin"
binary_data = UInt8[0x00, 0x01, 0x02, 0xFF, 0xFE, 0xFD, 0x48, 0x65, 0x6c, 0x6c, 0x6f]
result = s3PutFile(storage, test_key, binary_data)
@test result !== nothing
downloaded = s3GetFile(storage, test_key)
@test downloaded == binary_data
s3DeleteFile(storage, test_key)
@test s3GetFile(storage, test_key) === nothing
end
@testset "integration: s3ListFiles returns vector of strings" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "testrunner-list-$(GeneralUtils.uuid4snakecase()).txt"
s3PutFile(storage, test_key, "list-test-data")
keys = s3ListFiles(storage)
@test keys isa Vector{String}
@test test_key in keys
s3DeleteFile(storage, test_key)
end
@testset "integration: url format validation" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "testrunner-url-$(GeneralUtils.uuid4snakecase()).json"
result = s3PutFile(storage, test_key, "url-test")
@test startswith(result.api, "https://s3-api.yiem.cc/testbucket/")
@test occursin("/$test_key", result.api)
@test startswith(result.web, "https://s3-web.yiem.cc/testbucket/")
@test occursin("/$test_key", result.web)
s3DeleteFile(storage, test_key)
end
# --- Lifecycle configuration tests ---
@testset "LifecycleExpiration construction with default ID" begin
rule = LifecycleExpiration("uploads/", 30)
@test rule.prefix == "uploads/"
@test rule.days == 30
@test rule.enabled == true
@test rule.id == "expire-uploads_-30d"
end
@testset "LifecycleExpiration construction with custom ID" begin
rule = LifecycleExpiration("data/", 7; id="my-rule")
@test rule.prefix == "data/"
@test rule.days == 7
@test rule.enabled == true
@test rule.id == "my-rule"
end
@testset "LifecycleExpiration with disabled flag" begin
rule = LifecycleExpiration("temp/", 1; enabled=false)
@test rule.enabled == false
end
@testset "LifecycleExpiration with nested prefix" begin
rule = LifecycleExpiration("deep/nested/", 90)
@test rule.prefix == "deep/nested/"
end
@testset "build_lifecycle_xml generates valid XML" begin
rule = LifecycleExpiration("test/", 14; id="test-rule")
xml = build_lifecycle_xml(rule)
@test occursin("<?xml version=\"1.0\"", xml)
@test occursin("<LifecycleConfiguration>", xml)
@test occursin("<ID>test-rule</ID>", xml)
@test occursin("<Prefix>test/</Prefix>", xml)
@test occursin("<Status>Enabled</Status>", xml)
@test occursin("<Days>14</Days>", xml)
@test occursin("</LifecycleConfiguration>", xml)
end
@testset "build_lifecycle_xml generates disabled rule XML" begin
rule = LifecycleExpiration("temp/", 1; enabled=false)
xml = build_lifecycle_xml(rule)
@test occursin("<Status>Disabled</Status>", xml)
end
@testset "integration: lifecycle CRUD - set and get" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
# Should return nothing when no lifecycle is set
lc = s3GetLifecycle(storage)
@test lc === nothing
# Set lifecycle
rule = LifecycleExpiration("lifecycle-test/", 45)
s3SetLifecycleExpiration(storage, rule)
# Should return configuration after setting
lc = s3GetLifecycle(storage)
@test lc !== nothing
@test haskey(lc, "Rule")
# Delete lifecycle
s3DeleteLifecycle(storage)
# Should return nothing after deletion
lc = s3GetLifecycle(storage)
@test lc === nothing
end
@testset "integration: lifecycle with nested prefix" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
rule = LifecycleExpiration("a/b/c/", 20; id="nested-rule")
s3SetLifecycleExpiration(storage, rule)
lc = s3GetLifecycle(storage)
@test lc !== nothing
@test haskey(lc, "Rule")
s3DeleteLifecycle(storage)
@test s3GetLifecycle(storage) === nothing
end
@testset "integration: lifecycle enabled/disabled toggle" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
# Set enabled rule
rule1 = LifecycleExpiration("toggle/", 10; enabled=true)
s3SetLifecycleExpiration(storage, rule1)
lc = s3GetLifecycle(storage)
@test lc !== nothing
# Override with disabled rule
rule2 = LifecycleExpiration("toggle/", 10; enabled=false)
s3SetLifecycleExpiration(storage, rule2)
lc = s3GetLifecycle(storage)
@test lc !== nothing
s3DeleteLifecycle(storage)
end
# --- Pre-signed URL tests ---
@testset "s3SignUrl returns a string" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
url = s3SignUrl(storage, "test.json", 3600)
@test url isa String
@test !isempty(url)
end
@testset "s3SignUrl URL format contains correct endpoint, bucket, key" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
url = s3SignUrl(storage, "mykey.json", 1800)
@test occursin("https://s3-api.yiem.cc", url)
@test occursin("/testbucket/mykey.json?", url)
end
@testset "s3SignUrl contains required query parameters" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
url = s3SignUrl(storage, "test.json", 3600)
@test occursin("X-Amz-Algorithm=AWS4-HMAC-SHA256", url)
@test occursin("X-Amz-Expires=3600", url)
@test occursin("X-Amz-Credential=", url)
@test occursin("X-Amz-Date=", url)
@test occursin("X-Amz-SignedHeaders=", url)
@test occursin("X-Amz-Signature=", url)
end
@testset "s3SignUrl with custom expiry duration" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
url = s3SignUrl(storage, "test.json", 600)
@test occursin("X-Amz-Expires=600", url)
end
@testset "s3SignUrl with GET verb produces different signature than default" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
url_get = s3SignUrl(storage, "test.json", 3600; verb="GET")
url_default = s3SignUrl(storage, "test.json", 3600)
@test occursin("X-Amz-Signature=", url_get)
@test occursin("X-Amz-Signature=", url_default)
@test occursin("X-Amz-Algorithm=AWS4-HMAC-SHA256", url_get)
end
@testset "s3SignUrl with PUT verb and content_type" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
url_put = s3SignUrl(storage, "upload.json", 300; verb="PUT", content_type="application/json")
url_get = s3SignUrl(storage, "upload.json", 300; verb="GET")
@test occursin("X-Amz-Signature=", url_put)
@test occursin("X-Amz-Signature=", url_get)
end
@testset "s3SignUrl with special characters in key" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "folder/sub folder/file with spaces.json"
url = s3SignUrl(storage, test_key, 3600)
@test occursin("testbucket/", url)
end
@testset "s3SignUrl with deeply nested key" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "a/b/c/d/e/deep-file.json"
url = s3SignUrl(storage, test_key, 3600)
@test occursin("/testbucket/a/b/c/d/e/deep-file.json", url)
end
@testset "integration: pre-signed URL can download existing file" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "testrunner-presign-$(GeneralUtils.uuid4snakecase()).json"
test_data = "{\"presign\": true, \"test\": \"$(GeneralUtils.uuid4snakecase())\"}"
s3PutFile(storage, test_key, test_data)
url = s3SignUrl(storage, test_key, 300)
@test occursin("https://s3-api.yiem.cc/testbucket/", url)
s3DeleteFile(storage, test_key)
end
# --- s3SignUrl end-to-end: PUT upload, GET download, DELETE ---
@testset "integration: s3SignUrl PUT upload via pre-signed URL" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "testrunner-signurl-put-$(GeneralUtils.uuid4snakecase()).json"
test_data = "{\"signed\": true, \"upload\": \"put\"}"
content_type = "application/json"
# Generate pre-signed URL for PUT
put_url = s3SignUrl(storage, test_key, 300; verb="PUT", content_type=content_type)
@test occursin("X-Amz-Signature=", put_url)
@test occursin("X-Amz-Algorithm=AWS4-HMAC-SHA256", put_url)
@test occursin("X-Amz-SignedHeaders=", put_url)
# Upload via HTTP request using the signed URL
response = HTTP.request(
"PUT",
put_url,
["Content-Type" => content_type],
test_data
)
@test response.status == 200
# Verify upload via s3GetFile
downloaded = s3GetFile(storage, test_key)
@test downloaded !== nothing
@test String(downloaded) == test_data
# Cleanup
s3DeleteFile(storage, test_key)
end
@testset "integration: s3SignUrl GET download via pre-signed URL" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "testrunner-signurl-get-$(GeneralUtils.uuid4snakecase()).json"
test_data = "{\"signed\": true, \"download\": \"get\"}"
# Upload via s3PutFile first
s3PutFile(storage, test_key, test_data)
# Generate pre-signed URL for GET
get_url = s3SignUrl(storage, test_key, 300; verb="GET")
@test occursin("X-Amz-Signature=", get_url)
@test occursin("X-Amz-Algorithm=AWS4-HMAC-SHA256", get_url)
# Download via HTTP GET request using the signed URL
response = HTTP.request("GET", get_url)
@test response.status == 200
@test String(response.body) == test_data
# Cleanup
s3DeleteFile(storage, test_key)
end
@testset "integration: s3SignUrl DELETE via pre-signed URL" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
test_key = "testrunner-signurl-delete-$(GeneralUtils.uuid4snakecase()).json"
test_data = "{\"signed\": true, \"delete\": true}"
# Upload first
s3PutFile(storage, test_key, test_data)
# Verify it exists
@test s3GetFile(storage, test_key) !== nothing
# Generate pre-signed URL for DELETE
delete_url = s3SignUrl(storage, test_key, 300; verb="DELETE")
@test occursin("X-Amz-Signature=", delete_url)
@test occursin("X-Amz-Algorithm=AWS4-HMAC-SHA256", delete_url)
# Delete via HTTP DELETE request using the signed URL
response = HTTP.request("DELETE", delete_url)
@test response.status == 204
# Verify deletion
@test s3GetFile(storage, test_key) === nothing
end
@testset "integration: s3SignUrlWeb generates web endpoint URL" begin
storage = GarageStorage(
"https://s3-api.yiem.cc",
"GKb080154a2e5b19100b1b2c6e",
"a2c6b1379c2f731d3e6e5a408dd4d6cffca7511717675f55114ff94828febca1",
"testbucket"
)
url = s3SignUrlWeb(storage, "web-test.json", 3600)
@test url isa String
@test occursin("https://s3-web.yiem.cc", url)
@test occursin("/testbucket/web-test.json?", url)
@test occursin("X-Amz-Signature=", url)
end
end
Binary file not shown.

After

Width:  |  Height:  |  Size: 429 KiB