| import { describe, it, expect } from 'vitest' |
| import { |
| convertWavelength, |
| interpolateData, |
| parseDIF, |
| extractMetadata, |
| } from './xrd-processing' |
|
|
| |
| |
| |
| describe('convertWavelength', () => { |
| it('returns same angle when wavelengths match', () => { |
| const result = convertWavelength(10.0, 0.6199, 0.6199) |
| expect(result).toBeCloseTo(10.0, 5) |
| }) |
|
|
| it('returns null for physically impossible conversion', () => { |
| |
| const result = convertWavelength(80.0, 0.5, 2.0) |
| expect(result).toBeNull() |
| }) |
|
|
| it('converts Cu Ka to synchrotron wavelength', () => { |
| const cuKa = 1.5406 |
| const synchrotron = 0.6199 |
| const theta = 20.0 |
|
|
| const result = convertWavelength(theta, cuKa, synchrotron) |
| expect(result).not.toBeNull() |
| |
| expect(result).toBeLessThan(theta) |
| expect(result).toBeGreaterThan(0) |
| }) |
|
|
| it('converts synchrotron to Cu Ka wavelength', () => { |
| const cuKa = 1.5406 |
| const synchrotron = 0.6199 |
| const theta = 10.0 |
|
|
| const result = convertWavelength(theta, synchrotron, cuKa) |
| expect(result).not.toBeNull() |
| |
| expect(result).toBeGreaterThan(theta) |
| }) |
|
|
| it('handles zero angle', () => { |
| const result = convertWavelength(0, 1.0, 2.0) |
| expect(result).toBeCloseTo(0, 5) |
| }) |
| }) |
|
|
| |
| |
| |
| describe('interpolateData', () => { |
| it('returns same data when target size matches', () => { |
| const x = [1, 2, 3] |
| const y = [10, 20, 30] |
| const result = interpolateData(x, y, 3) |
| expect(result.x).toEqual(x) |
| expect(result.y).toEqual(y) |
| }) |
|
|
| it('interpolates to larger size with linear strategy', () => { |
| const x = [0, 10] |
| const y = [0, 100] |
| const result = interpolateData(x, y, 11, 0, 10, 'linear') |
| expect(result.x).toHaveLength(11) |
| expect(result.y).toHaveLength(11) |
| |
| expect(result.y[5]).toBeCloseTo(50, 0) |
| }) |
|
|
| it('sets out-of-range values to zero', () => { |
| const x = [5, 10, 15] |
| const y = [100, 200, 300] |
| const result = interpolateData(x, y, 20, 0, 20, 'linear') |
| |
| expect(result.y[0]).toBe(0) |
| |
| expect(result.y[19]).toBe(0) |
| }) |
|
|
| it('supports cubic interpolation', () => { |
| const x = [0, 2, 4, 6, 8, 10] |
| const y = [0, 4, 16, 36, 64, 100] |
| const result = interpolateData(x, y, 11, 0, 10, 'cubic') |
| expect(result.x).toHaveLength(11) |
| expect(result.y).toHaveLength(11) |
| }) |
|
|
| it('handles single point input', () => { |
| const x = [5] |
| const y = [100] |
| const result = interpolateData(x, y, 10, 0, 10, 'linear') |
| expect(result.x).toHaveLength(10) |
| }) |
| }) |
|
|
| |
| |
| |
| describe('parseDIF', () => { |
| it('parses space-separated data', () => { |
| const text = '5.0 100.0\n10.0 200.0\n15.0 300.0\n' |
| const result = parseDIF(text) |
| expect(result.x).toEqual([5.0, 10.0, 15.0]) |
| expect(result.y).toEqual([100.0, 200.0, 300.0]) |
| }) |
|
|
| it('skips comment lines', () => { |
| const text = '# This is a comment\n5.0 100.0\n10.0 200.0\n' |
| const result = parseDIF(text) |
| expect(result.x).toHaveLength(2) |
| }) |
|
|
| it('skips metadata lines', () => { |
| const text = 'CELL PARAMETERS: 5.0 5.0 5.0 90 90 90\nSPACE GROUP: Fm-3m\n5.0 100.0\n' |
| const result = parseDIF(text) |
| expect(result.x).toEqual([5.0]) |
| }) |
|
|
| it('skips lines starting with underscore', () => { |
| const text = '_cell_length_a 5.431\n5.0 100.0\n' |
| const result = parseDIF(text) |
| expect(result.x).toEqual([5.0]) |
| }) |
|
|
| it('handles empty input', () => { |
| const result = parseDIF('') |
| expect(result.x).toEqual([]) |
| expect(result.y).toEqual([]) |
| }) |
|
|
| it('handles tab-separated data', () => { |
| const text = '5.0\t100.0\n10.0\t200.0\n' |
| const result = parseDIF(text) |
| expect(result.x).toEqual([5.0, 10.0]) |
| expect(result.y).toEqual([100.0, 200.0]) |
| }) |
|
|
| it('skips lines starting with letters', () => { |
| const text = 'Header line\n5.0 100.0\nAnother header\n10.0 200.0\n' |
| const result = parseDIF(text) |
| expect(result.x).toEqual([5.0, 10.0]) |
| }) |
| }) |
|
|
| |
| |
| |
| describe('extractMetadata', () => { |
| it('detects wavelength from numeric pattern', () => { |
| const text = '_diffrn_radiation_wavelength 0.6199\n' |
| const result = extractMetadata(text) |
| expect(result.wavelength).toBeCloseTo(0.6199, 4) |
| }) |
|
|
| it('detects Cu Ka radiation', () => { |
| const text = 'Radiation: Cu Ka\n' |
| const result = extractMetadata(text) |
| expect(result.wavelength).toBeCloseTo(1.5406, 4) |
| }) |
|
|
| it('detects Mo Ka radiation', () => { |
| const text = 'Radiation: Mo Ka\n' |
| const result = extractMetadata(text) |
| expect(result.wavelength).toBeCloseTo(0.7107, 4) |
| }) |
|
|
| it('extracts space group number', () => { |
| const text = '_symmetry_Int_Tables_number 225\n' |
| const result = extractMetadata(text) |
| expect(result.spaceGroup).toBe('225') |
| }) |
|
|
| it('extracts cell parameters', () => { |
| const text = 'CELL PARAMETERS: 5.431 5.431 5.431 90.0 90.0 90.0\n' |
| const result = extractMetadata(text) |
| expect(result.cellParams).not.toBeNull() |
| expect(result.cellParams).toContain('5.431') |
| }) |
|
|
| it('returns null for missing data', () => { |
| const result = extractMetadata('Some random text without metadata\n') |
| expect(result.wavelength).toBeNull() |
| expect(result.spaceGroup).toBeNull() |
| expect(result.cellParams).toBeNull() |
| }) |
|
|
| it('rejects wavelengths outside X-ray range', () => { |
| const text = 'wavelength: 0.001\n' |
| const result = extractMetadata(text) |
| expect(result.wavelength).toBeNull() |
| }) |
| }) |
|
|