Archived
1
0
Fork 0
This repository has been archived on 2024-02-06. You can view files and clone it, but cannot push or open issues or pull requests.
SMS-Geography/gap.ipynb
2022-06-17 19:56:34 +09:00

919 lines
33 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"id": "d3cf5102-a75e-4223-ac77-d7638661c6af",
"metadata": {},
"source": [
"# SMS水面抜け"
]
},
{
"cell_type": "markdown",
"id": "fb09a37b-e0a0-49ec-a139-8aab8634afd7",
"metadata": {},
"source": [
"## 準備\n",
"高速化のために[numpy](https://numpy.org/doc/stable/reference/index.html#reference)と[pytorch](https://pytorch.org/docs/stable/index.html)を使います"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ee560598-d34e-41b1-8510-3abf0dd35d9f",
"metadata": {},
"outputs": [],
"source": [
"!pip install numpy torch tqdm sms-gap==0.1.0"
]
},
{
"cell_type": "markdown",
"id": "6f3888db-40f8-4404-b61e-fa6f74984140",
"metadata": {},
"source": [
"次に、必要なpackageをimportします"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6e6e4ef0-6601-4bc1-9a12-e0c673710d0d",
"metadata": {},
"outputs": [],
"source": [
"# cudaを使う場合は次の命令をuncommentしてください\n",
"#%set_env SMS_PYTORCH_DEVICE=cuda"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "c11636cf-a5c8-4bf7-851c-c2461268da5d",
"metadata": {},
"outputs": [],
"source": [
"import time # 実行時間を計るため\n",
"from tqdm.notebook import tqdm # progress bar\n",
"import numpy as np\n",
"import torch\n",
"from itertools import combinations as combin\n",
"import operator as op\n",
"import logging\n",
"from functools import reduce\n",
"from sms.gap import find_x, find_z, find_neigh, find_all, find_in_result, verify, frange, f32, binsearch\n",
"logger = logging.getLogger('SMS-gap')\n",
"\n",
"def hook():\n",
" from memorylib import Dolphin\n",
" global d, dolphin\n",
" d = dolphin = Dolphin()\n",
" assert dolphin.find_dolphin(), 'Dolphin not found'\n",
" assert dolphin.init_shared_memory(), 'MEM1 not found'\n",
" assert dolphin.read_ram(0, 3).tobytes() == b'GMS', 'Current game is not Sunshine'\n",
"\n",
"import struct\n",
"read_struct = lambda addr, fmt: struct.unpack(fmt, d.read_ram(addr-0x80000000, struct.calcsize(fmt)))\n",
"read_ptr = lambda addr: d.read_uint32(addr)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4a265298-e7cc-4b83-bd03-427c8529289a",
"metadata": {},
"outputs": [],
"source": [
"# 後からdeviceを変更したい時は次のようにpackageをreloadする必要があります\n",
"## 使うdevice\n",
"#%set_env SMS_PYTORCH_DEVICE=cpu\n",
"#import importlib\n",
"#import sms.gap\n",
"#importlib.reload(sms.gap)\n",
"#from sms.gap import find_x, find_z, find_neigh, find_all, find_in_result, verify, frange, f32"
]
},
{
"cell_type": "markdown",
"id": "17755dd0-79c4-4f89-a8d0-453bc3193fc4",
"metadata": {},
"source": [
"## 境界を指定"
]
},
{
"cell_type": "markdown",
"id": "668d9d1b-01fa-46c2-9b86-727bd98580c7",
"metadata": {},
"source": [
"### 方法1: 座標で指定"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "2972ffee-a928-4d93-889f-e6d33da3092d",
"metadata": {},
"outputs": [],
"source": [
"bd = (\n",
" (-6000, -33900),\n",
" ( 6200, 32700),\n",
")"
]
},
{
"attachments": {
"f124c718-30d3-4d16-b195-31462045b3df.png": {
"image/png": "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"
}
},
"cell_type": "markdown",
"id": "971f32c6-c0a6-45b2-a82e-acc335f0c55a",
"metadata": {},
"source": [
"### 方法2: 二つの三角形の座標(hex形式)で指定\n",
"[Dolphin-memory-engine](https://github.com/aldelaro5/Dolphin-memory-engine)\n",
"を使う場合、次のように設定すれば水面の三角形の座標をhex形式で取得できます。\n",
"\n",
"![image.png](attachment:f124c718-30d3-4d16-b195-31462045b3df.png)\n",
"\n",
"Level 2について、 \n",
"水面三角形を調べる場合は`E4`にし、 \n",
"普通の床三角形を調べる場合は`E0`にします。"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "3cc8afd9-1797-48ed-9466-9ae0090391ba",
"metadata": {},
"outputs": [],
"source": [
"# 三角形1のhex\n",
"raw1 = 'C5 BB 80 00 00 00 00 00 C7 04 6C 00 C5 BB 80 00 00 00 00 00 46 FF 78 00 45 C1 C0 00 00 00 00 00 46 FF 78 00'"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "c2248666-4d53-49ad-9e6e-d96fdbd2e80a",
"metadata": {},
"outputs": [],
"source": [
"# 三角形2のhex\n",
"raw2 = 'C5 BB 80 00 00 00 00 00 C7 04 6C 00 45 C1 C0 00 00 00 00 00 46 FF 78 00 45 C1 C0 00 00 00 00 00 C7 04 6C 00'"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "96353351-0bec-44c8-a154-8b4136369d3f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"三角形1の座標:\n",
" [[ -6000. -33900.]\n",
" [ -6000. 32700.]\n",
" [ 6200. 32700.]]\n",
"三角形2の座標:\n",
" [[ -6000. -33900.]\n",
" [ 6200. 32700.]\n",
" [ 6200. -33900.]]\n",
"\n",
"境界: ((-6000.0, -33900.0), (6200.0, 32700.0))\n"
]
}
],
"source": [
"tri1, tri2 = (\n",
" np.frombuffer(bytes.fromhex(raw), '>f').reshape(-1, 3)[:3, [0,2]]\n",
" for raw in (raw1, raw2)\n",
")\n",
"print('三角形1の座標:\\n', tri1)\n",
"print('三角形2の座標:\\n', tri2)\n",
"\n",
"bds = reduce(op.__and__, (\n",
" set(map(\n",
" frozenset, combin(map(tuple, tri), 2)\n",
" ))\n",
" for tri in (tri1, tri2)\n",
")) \n",
"assert len(bds)>0, '入力した三角形に共通の頂点座標がない'\n",
"if len(bds)>1: logger.warning('入力した三角形に共通の頂点座標が2個以上存在する')\n",
"bd = tuple(next(iter(bds)))\n",
"print('\\n境界:', bd)"
]
},
{
"cell_type": "markdown",
"id": "59c1482e-c69c-4757-8c63-c6c773ac26d4",
"metadata": {},
"source": [
"### 方法3: memorylibを用いてDolphinから直接に読み込む\n",
"サンシャインを起動して`hook()`を実行します"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "212e86c8-65b1-485f-aec9-2b58d23c3587",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2932239377344 0x2aab71623c0\n"
]
}
],
"source": [
"hook()"
]
},
{
"cell_type": "markdown",
"id": "5a63a7d9-78cb-4172-a159-ab6bb3ab5abc",
"metadata": {},
"source": [
"調べるのは水面ならば`offset`を`0xE4`に、普通の床ならば`0xE0`にします"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "abf3085c-0537-49d2-9cd9-7aa4ffa97bf6",
"metadata": {},
"outputs": [],
"source": [
"offset = 0xE4"
]
},
{
"cell_type": "markdown",
"id": "eda9c35b-04ce-4100-8845-24bf46c1f0a5",
"metadata": {},
"source": [
"Dolphinで一つ目の水面/床三角形に移動し、次の命令を実行します"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "a59abfbf-acd8-432c-811f-874762815508",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[ -6000., -33900.],\n",
" [ -6000., 32700.],\n",
" [ 6200., 32700.]])"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tri1 = np.array(read_struct(read_ptr(read_ptr(0x8040A378)+offset)+0x10, '>9f')).reshape(3, 3)[:, [0,2]]\n",
"tri1"
]
},
{
"cell_type": "markdown",
"id": "1c3fa7be-8fb0-40bd-b812-d91145963288",
"metadata": {},
"source": [
"次に、Dolphinで二つ目の水面/床三角形に移動し、次の命令を実行します"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "d0ab10e3-1a52-4175-9453-b252b8971143",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([[ -6000., -33900.],\n",
" [ 6200., 32700.],\n",
" [ 6200., -33900.]])"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"tri2 = np.array(read_struct(read_ptr(read_ptr(0x8040A378)+offset)+0x10, '>9f')).reshape(3, 3)[:, [0,2]]\n",
"tri2"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "602def54-7516-421d-a069-9f3c1f4987fa",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"境界: ((-6000.0, -33900.0), (6200.0, 32700.0))\n"
]
}
],
"source": [
"bds = reduce(op.__and__, (\n",
" set(map(\n",
" frozenset, combin(map(tuple, tri), 2)\n",
" ))\n",
" for tri in (tri1, tri2)\n",
")) \n",
"assert len(bds)>0, '入力した三角形に共通の頂点座標がない'\n",
"if len(bds)>1: logger.warning('入力した三角形に共通の頂点座標が2個以上存在する')\n",
"bd = tuple(next(iter(bds)))\n",
"print('境界:', bd)"
]
},
{
"cell_type": "markdown",
"id": "adf87d26-a957-4724-a85b-58b6322ca540",
"metadata": {},
"source": [
"## 探索\n",
"注意逆算の誤差によりFalse Positive/False Negativeが発生する可能性があります"
]
},
{
"cell_type": "markdown",
"id": "ea3afb8c-7849-4897-a92a-c181f6e2c5b6",
"metadata": {},
"source": [
"### 近傍の探索"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "0b0e6e62-97e5-422b-8bb5-c1cd6599a732",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"実行時間: 0.133(秒)\n"
]
}
],
"source": [
"axis = 'x' # x軸に沿って探索する\n",
"xC = -1000 # 探索の中心(x座標)\n",
"R = 50 # 探索の半径\n",
"max_count = 1e8 # 最大1億件探索する\n",
"\n",
"t0 = time.time()\n",
"xzz, valid = find_neigh(axis, xC, 50, bd, max_count)\n",
"print('実行時間: %.3f(秒)'%(time.time()-t0))"
]
},
{
"cell_type": "markdown",
"id": "767e8380-15f3-4c93-bba6-34e714cd4182",
"metadata": {},
"source": [
"#### すり抜けできるx座標の個数"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "8cbf1362-3829-4535-bf1d-d9c033f3a622",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor(652310)"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"valid.sum()"
]
},
{
"cell_type": "markdown",
"id": "5b52eaf8-9fcc-4e65-86c0-67aa1f97151c",
"metadata": {},
"source": [
"#### xC=-1000を中心に最も近い10+10件を表示"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "83547a60-8aaa-4a1e-a30d-ed79f799b515",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"x\t\tz Min\t\tz Max\n",
"-1000.0003\t-6604.9204\t-6604.92\n",
"-1000.00037\t-6604.9204\t-6604.92\n",
"-1000.0004\t-6604.9204\t-6604.92\n",
"-1000.0005\t-6604.9204\t-6604.92\n",
"-1000.00055\t-6604.9204\t-6604.92\n",
"-1000.0006\t-6604.9204\t-6604.92\n",
"-1000.0007\t-6604.9204\t-6604.92\n",
"-1000.0017\t-6604.928\t-6604.9277\n",
"-1000.0018\t-6604.928\t-6604.9277\n",
"-1000.00183\t-6604.928\t-6604.9277\n",
"\n",
"x\t\tz Min\t\tz Max\n",
"-999.99927\t-6604.9126\t-6604.912\n",
"-999.9992\t-6604.9126\t-6604.912\n",
"-999.99915\t-6604.9126\t-6604.912\n",
"-999.9991\t-6604.9126\t-6604.912\n",
"-999.999\t-6604.9126\t-6604.912\n",
"-999.99896\t-6604.9126\t-6604.912\n",
"-999.9989\t-6604.9126\t-6604.912\n",
"-999.99884\t-6604.9126\t-6604.912\n",
"-999.9988\t-6604.9126\t-6604.912\n",
"-999.99774\t-6604.905\t-6604.9043\n"
]
}
],
"source": [
"idxC = binsearch(xzz[:, 0], xC)\n",
"idxVC = valid[:idxC].sum()\n",
"xzzV = xzz[valid]\n",
"\n",
"header = ('x', 'z Min', 'z Max') if axis=='x' else ('z', 'x Min', 'x Max')\n",
"print(*header, sep='\\t\\t')\n",
"for r in xzzV[:idxVC][-10:].flip(0).cpu().numpy():\n",
" print(*r, sep='\\t')\n",
"\n",
"print()\n",
"print(*header, sep='\\t\\t')\n",
"for r in xzzV[idxVC:][:10].cpu().numpy():\n",
" print(*r, sep='\\t')"
]
},
{
"cell_type": "markdown",
"id": "2e3f3f94-4293-41ba-a948-f1948c5c91d5",
"metadata": {},
"source": [
"#### 結果をcsvファイルに保存"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "02b2dba6-e840-4397-aafc-41f4a3a82d7e",
"metadata": {},
"outputs": [],
"source": [
"with open('gap.csv', 'w') as fw:\n",
" print(*header, sep=',', file=fw)\n",
" for p in xzzV.cpu().numpy():\n",
" print(*p, sep=',', file=fw)"
]
},
{
"cell_type": "markdown",
"id": "94c1ae12-951d-4272-a60e-20e17674bfeb",
"metadata": {},
"source": [
"### 全探索\n",
"探索効率のために、探索の領域を二つに分けてそれぞれx軸とz軸に沿って探索することにします"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "88400bb3-4b7d-46ac-ab44-73fd0e45d3f6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"実行時間: 14.402(秒)\n",
"すり抜け可能/探索したx座標の個数: 17,028,477 / 49,272,585\n",
"すり抜け可能/探索したz座標の個数: 8,641,209 / 49,622,817\n"
]
}
],
"source": [
"t0 = time.time()\n",
"\n",
"# 探索\n",
"xzz, zxx = find_all(bd)\n",
"# 結果\n",
"xzzValid = xzz[:,1] <= xzz[:,2]\n",
"zxxValid = zxx[:,1] <= zxx[:,2]\n",
"xzzV = xzz[xzzValid]\n",
"zxxV = zxx[zxxValid]\n",
"\n",
"print('実行時間: %.3f(秒)'%(time.time()-t0))\n",
"print(f'すり抜け可能/探索したx座標の個数: {xzzV.shape[0]:,} / {xzz.shape[0]:,}')\n",
"print(f'すり抜け可能/探索したz座標の個数: {zxxV.shape[0]:,} / {zxx.shape[0]:,}')"
]
},
{
"cell_type": "markdown",
"id": "c450c35e-d8f8-4bf1-a549-8223152b9dce",
"metadata": {},
"source": [
"例えば、コロロの水面の場合、x=197.4539\\~6199.9985まではx軸に沿って探索し、それ以外(z=-33900\\~-11320)はz軸に沿って探索します。"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "1a0cb7bb-0bc5-4659-b998-f567e42336aa",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\t x\t\tz Min\t z Max\n",
"tensor([[ 197.4539, -67.9980, -67.9971],\n",
" [ 197.4539, -67.9980, -67.9971],\n",
" [ 197.4539, -67.9980, -67.9971],\n",
" ...,\n",
" [ 6199.9966, 32699.9805, 32699.9805],\n",
" [ 6199.9971, 32699.9805, 32699.9824],\n",
" [ 6199.9985, 32699.9902, 32699.9902]])\n",
"\t z\t\tx Min\t x Max\n",
"tensor([[-3.3900e+04, -6.0000e+03, -6.0000e+03],\n",
" [-3.3900e+04, -6.0000e+03, -6.0000e+03],\n",
" [-3.3900e+04, -6.0000e+03, -6.0000e+03],\n",
" ...,\n",
" [-1.1320e+03, 2.5457e+00, 2.5461e+00],\n",
" [-1.1320e+03, 2.5457e+00, 2.5461e+00],\n",
" [-1.1320e+03, 2.5457e+00, 2.5461e+00]])\n"
]
}
],
"source": [
"print('\\t x\\t\\tz Min\\t z Max')\n",
"print(xzzV)\n",
"print('\\t z\\t\\tx Min\\t x Max')\n",
"print(zxxV)"
]
},
{
"cell_type": "markdown",
"id": "8c8df25d-198b-4a01-a4ca-e78b05c62e36",
"metadata": {},
"source": [
"#### 結果を保存(ファイルサイズが大きいので注意!)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "64b5b5e1-bc2e-4963-a91f-b397f45065af",
"metadata": {},
"outputs": [],
"source": [
"torch.save((xzzV, zxxV), 'result.pt')"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "525c997b-04c8-405c-8890-3c3cd61ec286",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-rw-r--r-- 1 sup39 None 294M Jun 17 16:28 result.pt\n"
]
}
],
"source": [
"!ls -lh result.pt\n",
"# コロロの水面抜け可能座標をファイルに保存すると294MBなります"
]
},
{
"cell_type": "markdown",
"id": "9b65254d-290c-4efa-9c70-e20614e99d11",
"metadata": {},
"source": [
"#### 結果をcsvファイルに保存\n",
"ファイルが非常に大きくなるのでおすすめしません!\n",
"\n",
"例えばコロロの水面の場合、合計約750MBになりました。\n",
"ファイルサイズが大きすぎてExcelなどでは開けない可能性が高いので、\n",
"保存するとしたら`torch.save()`を使うことをおすすめします。"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a351ba22-7127-4eee-8d47-b76441fcd7e8",
"metadata": {},
"outputs": [],
"source": [
"for sfx, rsfx, a in zip('xz', 'zx', (xzzV, zxxV)):\n",
" with open(f'result-{sfx}.csv', 'w') as fw:\n",
" print(sfx, rsfx+' Min', rsfx+' Max', sep=',', file=fw)\n",
" for p in tqdm(a.cpu().numpy()):\n",
" print(*p, sep=',', file=fw)"
]
},
{
"cell_type": "markdown",
"id": "bef3029d-7ee3-4942-8a78-ba9bbf90c915",
"metadata": {},
"source": [
"#### 全探索の結果で調べる"
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "0f074fcb-e8f5-46e4-9c7b-ab84de096d80",
"metadata": {},
"outputs": [],
"source": [
"# 保存した結果を読み込む\n",
"xzzV, zxxV = torch.load('result.pt')"
]
},
{
"cell_type": "markdown",
"id": "5cad741f-da63-42b6-aa9f-0ad2d27ab746",
"metadata": {},
"source": [
"##### 特定のx座標"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "e85c9f26-21e8-4de3-bf7f-d4b0c5a7ffca",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[-1000.0004, -6604.9204, -6604.9199]])"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"find_in_result('x', f32(-1000.00037), xzzV, zxxV)\n",
"# x, z Min, z Max"
]
},
{
"cell_type": "markdown",
"id": "23cd14d8-19f7-4b58-b4e6-b7d48c5afaec",
"metadata": {},
"source": [
"##### 特定のz座標"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "cf5fcdf5-a093-44f6-94c2-2f80ee52877e",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[-6604.9204, -1000.0007, -1000.0003]])"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"find_in_result('z', -6604.9204, xzzV, zxxV)\n",
"# z, x Min, x Max"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "e0d500a7-a75c-4aaf-a67d-356d2e10196c",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([], size=(0, 3))"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 何も返さなかったら該当なし\n",
"find_in_result('z', -6604, xzzV, zxxV)"
]
},
{
"cell_type": "markdown",
"id": "990345d9-f2eb-484b-b3a6-d8e64d4a725d",
"metadata": {},
"source": [
"##### 近傍での探索"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "85e8bc03-21cd-49e9-9cb7-cafb1971efa0",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[ 950.0003, 4040.1663, 4040.1667],\n",
" [ 950.0004, 4040.1663, 4040.1667],\n",
" [ 950.0004, 4040.1663, 4040.1667],\n",
" ...,\n",
" [1049.9994, 4586.0605, 4586.0610],\n",
" [1049.9995, 4586.0605, 4586.0610],\n",
" [1049.9996, 4586.0605, 4586.0610]])"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"find_in_result('x', frange(950, 1050), xzzV, zxxV)"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "40aac4c5-a26f-4d42-a408-6c2e39c41053",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"tensor([[ 950.0059, 383.9348, 383.9353],\n",
" [ 950.0059, 383.9348, 383.9353],\n",
" [ 950.0060, 383.9348, 383.9353],\n",
" ...,\n",
" [1049.9987, 402.2517, 402.2522],\n",
" [1049.9988, 402.2517, 402.2522],\n",
" [1049.9989, 402.2517, 402.2522]])"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"r = find_in_result('z', frange(950, 1050), xzzV, zxxV)\n",
"r"
]
},
{
"cell_type": "markdown",
"id": "c2d819b6-5c84-4af4-b29d-256ff11c5633",
"metadata": {},
"source": [
"##### 結果をcsv形式でexport"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "3ee934fe-262f-44b0-ba5f-1a275a77e826",
"metadata": {},
"outputs": [],
"source": [
"axis = 'z'\n",
"\n",
"header = ('x', 'z Min', 'z Max') if axis=='x' else ('z', 'x Min', 'x Max')\n",
"with open('gap.csv', 'w') as fw:\n",
" print(*header, sep=',', file=fw)\n",
" for p in r.cpu().numpy():\n",
" print(*p, sep=',', file=fw)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e6ac3de6-9487-42dd-8d49-92a7ba77e5b5",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"id": "bc3d0d67-9534-4e1f-b08a-ee452c59f93e",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "b746ed07-0ce1-4859-8e0c-1ab3b1bd2056",
"metadata": {},
"source": [
"## LICENSE"
]
},
{
"cell_type": "raw",
"id": "37eb0a0d-4c0a-4eb6-b55e-2fc8048b6682",
"metadata": {},
"source": [
"Copyright (c) 2022 sup39[サポミク]\n",
"\n",
"Permission is hereby granted, free of charge, to any person\n",
"obtaining a copy of this software and associated documentation\n",
"files (the \"Software\"), to deal in the Software without\n",
"restriction, including without limitation the rights to use,\n",
"copy, modify, merge, publish, distribute, sublicense, and/or sell\n",
"copies of the Software, and to permit persons to whom the\n",
"Software is furnished to do so, subject to the following\n",
"conditions:\n",
"\n",
"The above copyright notice and this permission notice shall be\n",
"included in all copies or substantial portions of the Software.\n",
"\n",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n",
"EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n",
"OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n",
"NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n",
"HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n",
"WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n",
"FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n",
"OTHER DEALINGS IN THE SOFTWARE."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f7ef093f-0100-4c55-be94-26727769e189",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}