first commit.

This commit is contained in:
2022-06-20 17:51:03 +09:00
commit 03456410f8
297 changed files with 26335 additions and 0 deletions

View File

@@ -0,0 +1,142 @@
import React, { useState } from "react";
import { Link } from "react-router-dom";
import { MultiLang } from "../config";
import BrainCoordinateUtil, { BrainCoordinate, ConversionType } from "./lib/BrainCoordinateUtil";
interface Props {
lang: MultiLang;
}
const NimgcenterBrainConv: React.FC<Props> = (props: Props) => {
const defaultInputFormat = "\\d+\\.?\\d*";
const defaultOutputFormat = "%x,%y,%z\\n";
const [inputFormat, setInputFormat] = useState<string>(defaultInputFormat);
const [inputArea, setInputArea] = useState<string>("");
const [outputFormat, setOutputFormat] = useState<string>(defaultOutputFormat);
const [outputArea, setOutputArea] = useState<string>("");
const [conversionType, setConversionType] = useState<ConversionType>("icbm_spm2tal");
const parseInput = (input: string, format: string): BrainCoordinate[] => {
const ret: BrainCoordinate[] = [];
const regObj = new RegExp(format, "g");
const values = input.match(regObj) || [];
for (let i = 0; i + 2 < values.length; i += 3) {
ret.push({ x: parseFloat(values[i]), y: parseFloat(values[i + 1]), z: parseFloat(values[i + 2]) });
}
return ret;
};
const formatNumber = (value: number): string => {
const digit = 4;
const width = 7;
const ret = value.toFixed(digit);
return ret.length < width ? " ".repeat(width - ret.length) + ret : ret;
};
const onChangeInputFormat = (event: React.ChangeEvent<HTMLInputElement>) => {
setInputFormat(event.target.value);
};
const onClickDefaultInputFormatButton = (event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
setInputFormat(defaultInputFormat);
};
const onChangeInputArea = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
setInputArea(event.target.value);
};
const onChangeOutputFormat = (event: React.ChangeEvent<HTMLInputElement>) => {
setOutputFormat(event.target.value);
};
const onClickDefaultOutputFormatButton = (event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
setOutputFormat(defaultOutputFormat);
};
const onChangeMatrixType = (event: React.ChangeEvent<HTMLSelectElement>) => {
if (BrainCoordinateUtil.isConversionType(event.target.value)) {
setConversionType(event.target.value as ConversionType);
}
};
const onClickClearButton = (event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
setInputArea("");
setOutputArea("");
};
const onClickConvertButton = (event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
const inputValues = parseInput(inputArea, inputFormat);
const outputValues = inputValues.map((inputValue) => BrainCoordinateUtil.convertCoordinate(conversionType, inputValue));
const outputTextArea = outputValues
.map((value) => {
return outputFormat.replace("%x", formatNumber(value.x)).replace("%y", formatNumber(value.y)).replace("%z", formatNumber(value.z)).replace("\\n", "\n");
})
.join("");
setOutputArea(outputTextArea);
};
const matrix = BrainCoordinateUtil.getConversionMatrix(conversionType);
const matrixArea = "Conversion Matrix:\n" + matrix.map((vect) => " " + vect.map((value) => formatNumber(value)).join(", ")).join("\n");
return (
<div style={{ textAlign: "center" }}>
<div style={{ background: "navajowhite", padding: "3px 0" }}>
Brain Coordinate Converter is able to convert list of brain coordinate. <Link to="./howtouse.php">How To Use</Link>
</div>
<table style={{ textAlign: "left" }}>
<tbody>
<tr>
<td>
<b>Input format: (Regular expression).</b>
<br />
<input type="text" value={inputFormat} onChange={onChangeInputFormat} />
<input type="button" onClick={onClickDefaultInputFormatButton} value="Default" />
</td>
<td>
<b>Output format: (%x,%y,%z is replaced. and \n)</b>
<br />
<input type="text" value={outputFormat} onChange={onChangeOutputFormat} />
<input type="button" onClick={onClickDefaultOutputFormatButton} value="Default" />
</td>
</tr>
<tr>
<td>
<b>Input:</b>
<br />
<textarea cols={37} rows={10} wrap="off" value={inputArea} onChange={onChangeInputArea} />
</td>
<td>
<b>Results:</b>
<br />
<textarea cols={37} rows={10} wrap="off" value={outputArea} readOnly />
</td>
</tr>
<tr>
<td>
<select size={8} onChange={onChangeMatrixType} value={conversionType}>
{BrainCoordinateUtil.getConversionTypes().map((type) => (
<option key={type} value={type}>
{BrainCoordinateUtil.getConversionLabel(type)}
</option>
))}
</select>
</td>
<td>
<textarea cols={37} rows={5} wrap="off" value={matrixArea} readOnly />
</td>
</tr>
<tr>
<td>
<input type="button" onClick={onClickConvertButton} value="Convert" />
</td>
<td>
<input type="button" onClick={onClickClearButton} value="Clear" />
</td>
</tr>
</tbody>
</table>
</div>
);
};
export default NimgcenterBrainConv;

View File

@@ -0,0 +1,34 @@
import React from "react";
import { Helmet } from "react-helmet-async";
import { Navigate, Route, Routes } from "react-router-dom";
import PageNotFound from "../common/lib/PageNotFound";
import XoopsCode from "../common/lib/XoopsCode";
import { MultiLang } from "../config";
import jsonHowToUse from "./assets/howtouse.json";
import jsonUtilities from "./assets/utilities.json";
import NimgcenterBrainConv from "./NimgcenterBrainConv";
interface Props {
lang: MultiLang;
}
const NimgcenterUtilities: React.FC<Props> = (props: Props) => {
const { lang } = props;
return (
<>
<Helmet>
<title>NIMG Utilities</title>
</Helmet>
<Routes>
<Route path="" element={<XoopsCode lang={lang} text={jsonUtilities[lang]} dohtml={true} />} />
<Route path="brain_conv/" element={<NimgcenterBrainConv lang={lang} />} />
<Route path="brain_conv/howtouse.php" element={<XoopsCode lang={lang} text={jsonHowToUse[lang]} dohtml={true} />} />
<Route path="index.php" element={<Navigate to="/modules/xnpnimgcenter/utilities/" />} />
<Route path="brain_conv/index.php" element={<Navigate to="/modules/xnpnimgcenter/utilities/brain_conv/" />} />
<Route path="*" element={<PageNotFound lang={lang} />} />
</Routes>
</>
);
};
export default NimgcenterUtilities;

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"en":"<h1>\n Utilities\n<\/h1><br \/>\n<br \/>\n<table class=\"outer\">\n <tbody>\n <tr>\n <td width=\"10%\" style=\"vertical-align:middle; text-align:center;\">\n <a href=\"\/modules\/xnpnimgcenter\/utilities\/brain_conv\/\"><img src=\"\/modules\/xnpnimgcenter\/utilities\/images\/brain_conv_ss.png\" alt=\"brainconv\" \/><\/a>\n <\/td>\n <td width=\"90%\">\n <a href=\"\/modules\/xnpnimgcenter\/utilities\/brain_conv\/\">Brain Coordinate Converter<\/a><br \/>\n This utility is able to mutually convert several types of brain coordinates(Requires JavaScript).<br \/>\n <a href=\"\/modules\/xnpnimgcenter\/utilities\/brain_conv\/howtouse.php\">How to use<\/a>\n <\/td>\n <\/tr>\n <\/tbody>\n<\/table>","ja":"<h1>\n ユーティリティ\n<\/h1><br \/>\n<br \/>\n<table class=\"outer\">\n <tbody>\n <tr>\n <td width=\"10%\" style=\"vertical-align:middle; text-align:center;\">\n <a href=\"\/modules\/xnpnimgcenter\/utilities\/brain_conv\/\"><img src=\"\/modules\/xnpnimgcenter\/utilities\/images\/brain_conv_ss.png\" alt=\"brainconv\" \/><\/a>\n <\/td>\n <td width=\"90%\">\n <a href=\"\/modules\/xnpnimgcenter\/utilities\/brain_conv\/\">脳座標変換ツール<\/a><br \/>\n 数種類の脳座間の変換が行えます要Javascript。<br \/>\n <a href=\"\/modules\/xnpnimgcenter\/utilities\/brain_conv\/howtouse.php\">使い方<\/a>\n <\/td>\n <\/tr>\n <\/tbody>\n<\/table>"}

View File

@@ -0,0 +1,152 @@
export interface BrainCoordinate {
x: number;
y: number;
z: number;
}
export type ConversionType = "icbm_spm2tal" | "tal2icbm_spm" | "icbm_fsl2tal" | "tal2icbm_fsl" | "icbm_other2tal" | "tal2icbm_other";
type ConversionVector = readonly [number, number, number, number];
type ConversionMatrix = readonly [ConversionVector, ConversionVector, ConversionVector, ConversionVector];
interface ConversionMatrixData {
[key: string]: {
label: string;
matrix: ConversionMatrix;
};
}
const conversionMatrix: ConversionMatrixData = {
icbm_spm2tal: {
label: "icbm_spm => Talairach",
matrix: [
[0.9254, 0.0024, -0.0118, -1.0207],
[-0.0048, 0.9316, -0.0871, -1.7667],
[0.0152, 0.0883, 0.8924, 4.0926],
[0.0, 0.0, 0.0, 1.0],
],
},
tal2icbm_spm: {
label: "Talairach => icbm_spm",
matrix: [
[1.0804, -0.0041, 0.0139, 1.0387],
[0.0038, 1.0636, 0.1039, 1.4579],
[-0.0188, -0.1052, 1.1101, -4.748],
[0.0, 0.0, 0.0, 1.0],
],
},
icbm_fsl2tal: {
label: "icbm_fsl => Talairach",
matrix: [
[0.9464, 0.0034, -0.0026, -1.068],
[-0.0083, 0.9479, -0.058, -1.0239],
[0.0053, 0.0617, 0.901, 3.1883],
[0.0, 0.0, 0.0, 1.0],
],
},
tal2icbm_fsl: {
label: "Talairach => icbm_fsl",
matrix: [
[1.0566, -0.004, 0.0028, 1.1155],
[0.0088, 1.0505, 0.0677, 0.8694],
[-0.0068, -0.0719, 1.1052, -3.6047],
[0.0, 0.0, 0.0, 1.0],
],
},
icbm_other2tal: {
label: "other(SPM99,Brain Voyager) => Talairach",
matrix: [
[0.9357, 0.0029, -0.0072, -1.0423],
[-0.0065, 0.9396, -0.0726, -1.394],
[0.0103, 0.0752, 0.8967, 3.6475],
[0.0, 0.0, 0.0, 1.0],
],
},
tal2icbm_other: {
label: "Talairach => other(SPM99,Brain Voyager)",
matrix: [
[1.0686, -0.004, 0.0083, 1.0782],
[0.0064, 1.0574, 0.0857, 1.1682],
[-0.0128, -0.0886, 1.1079, -4.178],
[0.0, 0.0, 0.0, 1.0],
],
},
/*
tal2mni: {
label: 'Talairach => MNI(Matthew Brett,99)',
matrix: null // See also, http://eeg.sourceforge.net/doc_m2html/bioelectromagnetism/tal2mni.html
},
mni2tal: {
label: 'MNI => Talairach(Matthew Brett,99)',
matrix: null // See also, http://eeg.sourceforge.net/doc_m2html/bioelectromagnetism/mni2tal.html
}
*/
};
const isConversionType = (type: string): boolean => {
return type in conversionMatrix;
};
const getConversionTypes = (): ConversionType[] => {
return Object.keys(conversionMatrix) as ConversionType[];
};
const getConversionLabel = (type: ConversionType): string => {
return conversionMatrix[type].label;
};
const getConversionMatrix = (type: ConversionType): ConversionMatrix => {
return conversionMatrix[type].matrix;
};
const mulMatrix = (mat: ConversionMatrix, vec: ConversionVector): ConversionVector => {
return [mat[0][0] * vec[0] + mat[0][1] * vec[1] + mat[0][2] * vec[2] + mat[0][3] * vec[3], mat[1][0] * vec[0] + mat[1][1] * vec[1] + mat[1][2] * vec[2] + mat[1][3] * vec[3], mat[2][0] * vec[0] + mat[2][1] * vec[1] + mat[2][2] * vec[2] + mat[2][3] * vec[3], mat[3][0] * vec[0] + mat[3][1] * vec[1] + mat[3][2] * vec[2] + mat[3][3] * vec[3]];
};
const convertCoordinate = (type: ConversionType, coord: BrainCoordinate): BrainCoordinate => {
const vec: ConversionVector = [coord.x, coord.y, coord.z, 1.0];
const res = mulMatrix(conversionMatrix[type].matrix, vec);
return { x: res[0], y: res[1], z: res[2] };
};
/*
function mni2tal(v) {
if (v[2] < 0) {
return new Array(
0.9900 * v[0],
0.9688 * v[1] + 0.0420 * v[2],
-0.0485 * v[1] + 0.8390 * v[2]
);
} else {
return new Array(
0.9900 * v[0],
0.9688 * v[1] + 0.0460 * v[2],
-0.0485 * v[1] + 0.9189 * v[2]
);
}
}
function tal2mni(v) {
if (v[2] < 0) {
return new Array(
1.0101 * v[0],
0.9688 * v[1] + 0.0460 * v[2],
-0.0485 * v[1] + 0.9189 * v[2]
);
} else {
return new Array(
1.0101 * v[0],
0.9712 * v[1] + 0.0501 * v[2],
-0.0485 * v[1] + 0.8390 * v[2]
);
}
}
*/
const BrainCoordinateUtil = {
isConversionType,
getConversionTypes,
getConversionLabel,
getConversionMatrix,
convertCoordinate,
};
export default BrainCoordinateUtil;