now I can plot next way:
```dataviewjs
// Load .obsidian/scripts/myplot.js
if (!window.__myPlotLoaded) {
const code = await app.vault.adapter.read(
app.vault.configDir + '/scripts/myplot.js'
);
eval(code);
}
function gamma(x) {
if (x < 0.5) {
return Math.PI / (Math.sin(Math.PI * x) * gamma(1 - x));
}
x -= 1;
const g = 7;
const c = [
0.99999999999980993, 676.5203681218851, -1259.1392167224028,
771.32342877765313, -176.61502916214059, 12.507343278686905,
-0.13857109526572012, 9.9843695780195716e-6, 1.5056327351493116e-7
];
let sum = c[0];
for (let i = 1; i < c.length; i++) sum += c[i] / (x + i);
const t = x + g + 0.5;
return Math.sqrt(2 * Math.PI) * Math.pow(t, x + 0.5) * Math.exp(-t) * sum;
};
const data = [
{
fn: gamma,
name: 'Г(x)', line: { color: 'blue' }
},
{
fn: Math.sin,
name: 'sin(x)', line: { color: 'red' }
}
];
const layout = {
title: 'Gamma and sinus',
showlegend: true,
xaxis: { title: 'x', range: [0.1, 6]}, // here range is necessary
yaxis: { title: 'y', range: [-5, 20]} // here range is optional
};
window.myPlotly(this.container, data, layout);
```
I add .obsidian/scripts/myplot.js:
// .obsidian/scripts/myplot.js
const STEPS = 600;
function generatePoints(fn, xMin, xMax, steps = STEPS) {
const xs = [];
const ys = [];
const step = (xMax - xMin) / steps;
for (let x = xMin; x <= xMax; x += step) {
const y = fn(x);
if (isFinite(y) && Math.abs(y) < 1e10) {
xs.push(x);
ys.push(y);
} else {
xs.push(x);
ys.push(null);
}
}
return { xs, ys };
}
function prepareTracks(data, layout) {
const plotlyData = [];
const layoutRange = layout?.xaxis?.range;
for (let i = 0; i < data.length; i++) {
const { fn, ...rest } = data[i];
if (typeof fn !== 'function') {
throw new Error(`data[${i}]: fn не задана или не является функцией`);
}
const xMin = layoutRange?.[0];
const xMax = layoutRange?.[1];
if (typeof xMin !== 'number' || typeof xMax !== 'number') {
throw new Error(`data[${i}]: задайте xMin/xMax в треке или xaxis.range в layout`);
}
if (xMin >= xMax) {
throw new Error(`data[${i}]: xMin должен быть меньше xMax`);
}
const { xs, ys } = generatePoints(fn, xMin, xMax);
plotlyData.push({ ...rest, x: xs, y: ys });
}
return plotlyData;
}
window.myPlotly = function(container, data, layout) {
const Plotly = app.plugins.plugins['obsidian-plotly']?.Plotly;
if (!Plotly) {
throw new Error('Плагин obsidian-plotly не найден или не загружен');
}
let plotlyData;
try {
plotlyData = prepareTracks(data, layout);
} catch (e) {
container.createEl('pre', { text: `myPlotly error: ${e.message}` });
return;
}
window.renderPlotly(container, plotlyData, layout);
const plotDiv = container.querySelector('.js-plotly-plot') ?? container;
plotDiv.on('plotly_relayout', (eventData) => {
const newXMin = eventData['xaxis.range[0]'];
const newXMax = eventData['xaxis.range[1]'];
if (newXMin === undefined || newXMax === undefined) return;
const indices = data.map((_, i) => i);
const newXs = [];
const newYs = [];
for (const { fn } of data) {
const { xs, ys } = generatePoints(fn, newXMin, newXMax);
newXs.push(xs);
newYs.push(ys);
}
Plotly.restyle(plotDiv, { x: newXs, y: newYs }, indices);
});
};
// register
window.__myPlotLoaded = true;
It will be useful if you integrate it in Plotly plugin
now I can plot next way:
I add .obsidian/scripts/myplot.js:
It will be useful if you integrate it in Plotly plugin