From 0bb0f4c03418f1e4344f92851cd82688d025c1ea Mon Sep 17 00:00:00 2001 From: Leszek Grzanka Date: Sat, 29 Nov 2025 20:42:57 +0100 Subject: [PATCH 01/13] feat: implement Geant4 dataset cache management and status monitoring --- src/Geant4Worker/Geant4DatasetCacheService.ts | 318 ++++++++++++++++++ src/Geant4Worker/useDatasetCacheStatus.ts | 90 +++++ .../Simulation/Geant4DatasetDownload.tsx | 192 ++++++++++- .../Modal/DatasetsFullInfoModal.tsx | 114 ++++++- 4 files changed, 699 insertions(+), 15 deletions(-) create mode 100644 src/Geant4Worker/Geant4DatasetCacheService.ts create mode 100644 src/Geant4Worker/useDatasetCacheStatus.ts diff --git a/src/Geant4Worker/Geant4DatasetCacheService.ts b/src/Geant4Worker/Geant4DatasetCacheService.ts new file mode 100644 index 000000000..5b0d66445 --- /dev/null +++ b/src/Geant4Worker/Geant4DatasetCacheService.ts @@ -0,0 +1,318 @@ +/** + * Service to detect and manage Geant4 dataset cache status in IndexedDB. + * The Emscripten preload scripts store datasets in IndexedDB with: + * - Database name: EM_PRELOAD_CACHE + * - Store: METADATA (contains package UUIDs and chunk counts) + * - Store: PACKAGES (contains the actual data chunks) + */ + +// Dataset information matching what's in the preload scripts +// Note: The actual key in IndexedDB is: metadata/ +// where PACKAGE_PATH is URL-encoded current page path +export const GEANT4_DATASETS = [ + { + name: 'G4EMLOW8.6.1', + // The suffix that appears in the metadata key (after any path prefix) + keySuffix: '/memfs/18333901/geant-web-application/build/data/G4EMLOW8.6.1.data', + approximateSizeMB: 580 + }, + { + name: 'G4ENSDFSTATE3.0', + keySuffix: '/memfs/18333901/geant-web-application/build/data/G4ENSDFSTATE3.0.data', + approximateSizeMB: 0.1 + }, + { + name: 'G4NDL4.7.1', + keySuffix: '/memfs/18333901/geant-web-application/build/data/G4NDL4.7.1.data', + approximateSizeMB: 583 + }, + { + name: 'G4PARTICLEXS4.1', + keySuffix: '/memfs/18333901/geant-web-application/build/data/G4PARTICLEXS4.1.data', + approximateSizeMB: 103 + }, + { + name: 'G4SAIDDATA2.0', + keySuffix: '/memfs/18333901/geant-web-application/build/data/G4SAIDDATA2.0.data', + approximateSizeMB: 0.8 + }, + { + name: 'PhotonEvaporation6.1', + keySuffix: '/memfs/18333901/geant-web-application/build/data/PhotonEvaporation6.1.data', + approximateSizeMB: 47 + } +] as const; + +export const TOTAL_DATASET_SIZE_MB = GEANT4_DATASETS.reduce( + (sum, ds) => sum + ds.approximateSizeMB, + 0 +); + +const DB_NAME = 'EM_PRELOAD_CACHE'; +const DB_VERSION = 1; +const METADATA_STORE_NAME = 'METADATA'; +const PACKAGES_STORE_NAME = 'PACKAGES'; + +export interface DatasetCacheStatus { + name: string; + isCached: boolean; + approximateSizeMB: number; +} + +export interface CacheStatusResult { + datasets: DatasetCacheStatus[]; + allCached: boolean; + cachedCount: number; + totalCount: number; + estimatedCachedSizeMB: number; + estimatedTotalSizeMB: number; +} + +export interface StorageEstimate { + usedMB: number; + quotaMB: number; + percentUsed: number; +} + +/** + * Opens the IndexedDB database used by Emscripten for caching + */ +async function openDatabase(): Promise { + if (typeof indexedDB === 'undefined') { + console.warn('[CacheService] IndexedDB is not available'); + + return null; + } + + return new Promise((resolve, reject) => { + console.log(`[CacheService] Opening IndexedDB database: ${DB_NAME}`); + const openRequest = indexedDB.open(DB_NAME, DB_VERSION); + + openRequest.onupgradeneeded = event => { + // Database doesn't exist yet or needs upgrade - this means no cache + console.log('[CacheService] Database upgrade needed - creating stores'); + const db = (event.target as IDBOpenDBRequest).result; + // Create stores if they don't exist (they won't have data anyway) + + if (!db.objectStoreNames.contains(PACKAGES_STORE_NAME)) { + db.createObjectStore(PACKAGES_STORE_NAME); + } + + if (!db.objectStoreNames.contains(METADATA_STORE_NAME)) { + db.createObjectStore(METADATA_STORE_NAME); + } + }; + + openRequest.onsuccess = event => { + const db = (event.target as IDBOpenDBRequest).result; + console.log(`[CacheService] Database opened successfully. Object stores: ${Array.from(db.objectStoreNames).join(', ')}`); + resolve(db); + }; + + openRequest.onerror = () => { + console.warn('[CacheService] Failed to open IndexedDB:', openRequest.error); + resolve(null); + }; + }); +} + +/** + * Checks if a specific dataset is cached in IndexedDB by looking for any key ending with the suffix + */ +async function checkDatasetCachedByKeySuffix( + db: IDBDatabase, + keySuffix: string, + datasetName: string, + allMetadataKeys: string[] +): Promise { + // Find any key that ends with our suffix (after removing 'metadata/' prefix) + const matchingKey = allMetadataKeys.find(key => { + // Keys are stored as 'metadata/' + // We need to check if the key ends with our keySuffix + const keyWithoutPrefix = key.replace(/^metadata\//, ''); + // The keyWithoutPrefix might be URL-encoded, so try both + const decoded = decodeURIComponent(keyWithoutPrefix); + + return keyWithoutPrefix.endsWith(keySuffix) || decoded.endsWith(keySuffix); + }); + + if (matchingKey) { + console.log(`[CacheService] Dataset ${datasetName}: Found matching key "${matchingKey}"`); + // Verify it has valid metadata + const result = await getMetadataValue(db, matchingKey); + + if (result && result.uuid) { + console.log( + `[CacheService] Dataset ${datasetName}: CACHED (uuid: ${result.uuid}, chunkCount: ${result.chunkCount})` + ); + + return true; + } + } + + console.log( + `[CacheService] Dataset ${datasetName}: NOT CACHED (no matching key for suffix "${keySuffix}")` + ); + + return false; +} + +/** + * Get the metadata value for a specific key + */ +async function getMetadataValue( + db: IDBDatabase, + key: string +): Promise<{ uuid: string; chunkCount: number } | null> { + return new Promise(resolve => { + try { + const transaction = db.transaction([METADATA_STORE_NAME], 'readonly'); + const metadata = transaction.objectStore(METADATA_STORE_NAME); + const getRequest = metadata.get(key); + + getRequest.onsuccess = () => { + resolve(getRequest.result || null); + }; + + getRequest.onerror = () => { + resolve(null); + }; + } catch { + resolve(null); + } + }); +} + +/** + * Lists all keys in the METADATA store for debugging + */ +async function listAllMetadataKeys(db: IDBDatabase): Promise { + return new Promise(resolve => { + try { + const transaction = db.transaction([METADATA_STORE_NAME], 'readonly'); + const metadata = transaction.objectStore(METADATA_STORE_NAME); + const getAllKeysRequest = metadata.getAllKeys(); + + getAllKeysRequest.onsuccess = () => { + const keys = getAllKeysRequest.result as string[]; + console.log(`[CacheService] All METADATA keys (${keys.length}):`, keys); + resolve(keys); + }; + + getAllKeysRequest.onerror = () => { + console.warn('[CacheService] Error listing metadata keys:', getAllKeysRequest.error); + resolve([]); + }; + } catch (error) { + console.warn('[CacheService] Exception listing metadata keys:', error); + resolve([]); + } + }); +} + +/** + * Checks the cache status of all Geant4 datasets + */ +export async function checkAllDatasetsCacheStatus(): Promise { + console.log('[CacheService] Starting cache status check...'); + const db = await openDatabase(); + + if (!db) { + console.warn('[CacheService] Database not available, returning all uncached'); + + return { + datasets: GEANT4_DATASETS.map(ds => ({ + name: ds.name, + isCached: false, + approximateSizeMB: ds.approximateSizeMB + })), + allCached: false, + cachedCount: 0, + totalCount: GEANT4_DATASETS.length, + estimatedCachedSizeMB: 0, + estimatedTotalSizeMB: TOTAL_DATASET_SIZE_MB + }; + } + + try { + // First, list all metadata keys for debugging + const allKeys = await listAllMetadataKeys(db); + console.log('[CacheService] Found metadata keys:', allKeys); + + const datasetStatuses: DatasetCacheStatus[] = await Promise.all( + GEANT4_DATASETS.map(async ds => { + const isCached = await checkDatasetCachedByKeySuffix( + db, + ds.keySuffix, + ds.name, + allKeys + ); + + return { + name: ds.name, + isCached, + approximateSizeMB: ds.approximateSizeMB + }; + }) + ); + + const cachedDatasets = datasetStatuses.filter(ds => ds.isCached); + + const result: CacheStatusResult = { + datasets: datasetStatuses, + allCached: cachedDatasets.length === GEANT4_DATASETS.length, + cachedCount: cachedDatasets.length, + totalCount: GEANT4_DATASETS.length, + estimatedCachedSizeMB: cachedDatasets.reduce((sum, ds) => sum + ds.approximateSizeMB, 0), + estimatedTotalSizeMB: TOTAL_DATASET_SIZE_MB + }; + + console.log('[CacheService] Cache status result:', result); + + return result; + } finally { + db.close(); + } +} + +/** + * Gets browser storage estimate using the Storage API + */ +export async function getStorageEstimate(): Promise { + if (!navigator.storage || !navigator.storage.estimate) { + return null; + } + + try { + const estimate = await navigator.storage.estimate(); + const usedMB = (estimate.usage ?? 0) / (1024 * 1024); + const quotaMB = (estimate.quota ?? 0) / (1024 * 1024); + + return { + usedMB, + quotaMB, + percentUsed: quotaMB > 0 ? (usedMB / quotaMB) * 100 : 0 + }; + } catch { + return null; + } +} + +/** + * Clears all cached Geant4 datasets from IndexedDB + */ +export async function clearDatasetCache(): Promise { + return new Promise(resolve => { + if (typeof indexedDB === 'undefined') { + resolve(false); + + return; + } + + const deleteRequest = indexedDB.deleteDatabase(DB_NAME); + + deleteRequest.onsuccess = () => resolve(true); + deleteRequest.onerror = () => resolve(false); + deleteRequest.onblocked = () => resolve(false); + }); +} diff --git a/src/Geant4Worker/useDatasetCacheStatus.ts b/src/Geant4Worker/useDatasetCacheStatus.ts new file mode 100644 index 000000000..527a7ceba --- /dev/null +++ b/src/Geant4Worker/useDatasetCacheStatus.ts @@ -0,0 +1,90 @@ +import { useCallback, useEffect, useState } from 'react'; + +import { + CacheStatusResult, + checkAllDatasetsCacheStatus, + clearDatasetCache, + getStorageEstimate, + StorageEstimate, + TOTAL_DATASET_SIZE_MB +} from './Geant4DatasetCacheService'; + +export interface UseDatasetCacheStatusResult { + /** Cache status for all datasets */ + cacheStatus: CacheStatusResult | null; + /** Browser storage estimate */ + storageEstimate: StorageEstimate | null; + /** Whether the cache status is being loaded */ + isLoading: boolean; + /** Whether all datasets are cached */ + allCached: boolean; + /** Number of cached datasets */ + cachedCount: number; + /** Total number of datasets */ + totalCount: number; + /** Estimated size in MB that would need to be downloaded */ + downloadSizeNeededMB: number; + /** Refresh the cache status */ + refresh: () => Promise; + /** Clear all cached datasets */ + clearCache: () => Promise; +} + +/** + * Hook to check and monitor Geant4 dataset cache status + */ +export function useDatasetCacheStatus(): UseDatasetCacheStatusResult { + const [cacheStatus, setCacheStatus] = useState(null); + const [storageEstimate, setStorageEstimate] = useState(null); + const [isLoading, setIsLoading] = useState(true); + + const refresh = useCallback(async () => { + setIsLoading(true); + + try { + const [status, storage] = await Promise.all([ + checkAllDatasetsCacheStatus(), + getStorageEstimate() + ]); + setCacheStatus(status); + setStorageEstimate(storage); + } catch (error) { + console.error('Failed to check dataset cache status:', error); + } finally { + setIsLoading(false); + } + }, []); + + const clearCache = useCallback(async () => { + const success = await clearDatasetCache(); + + if (success) { + await refresh(); + } + + return success; + }, [refresh]); + + useEffect(() => { + refresh(); + }, [refresh]); + + const allCached = cacheStatus?.allCached ?? false; + const cachedCount = cacheStatus?.cachedCount ?? 0; + const totalCount = cacheStatus?.totalCount ?? 0; + const downloadSizeNeededMB = allCached + ? 0 + : TOTAL_DATASET_SIZE_MB - (cacheStatus?.estimatedCachedSizeMB ?? 0); + + return { + cacheStatus, + storageEstimate, + isLoading, + allCached, + cachedCount, + totalCount, + downloadSizeNeededMB, + refresh, + clearCache + }; +} diff --git a/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx b/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx index 51f10f585..31ff2bfcc 100644 --- a/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx +++ b/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx @@ -1,24 +1,31 @@ // Full credits to @kmichalik +import CachedIcon from '@mui/icons-material/Cached'; import CheckIcon from '@mui/icons-material/Check'; +import CloudDownloadIcon from '@mui/icons-material/CloudDownload'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import StorageIcon from '@mui/icons-material/Storage'; import { AccordionDetails, AccordionSummary, Box, Button, + Chip, + CircularProgress, LinearProgress, ToggleButton, + Tooltip, Typography, useTheme } from '@mui/material'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { DatasetDownloadStatus, DatasetStatus, DownloadManagerStatus } from '../../../Geant4Worker/Geant4DatasetDownloadManager'; +import { useDatasetCacheStatus } from '../../../Geant4Worker/useDatasetCacheStatus'; import { useDialog } from '../../../services/DialogService'; import StyledAccordion from '../../../shared/components/StyledAccordion'; import { StyledExclusiveToggleButtonGroup } from '../../../shared/components/StyledExclusiveToggleButtonGroup'; @@ -71,6 +78,145 @@ function DatasetCurrentStatus(props: { status: DatasetStatus }) { ); } +/** + * Component to display cache status with visual indicators + */ +function CacheStatusIndicator({ showDebugInfo = false }: { showDebugInfo?: boolean }) { + const { + isLoading, + allCached, + cachedCount, + totalCount, + downloadSizeNeededMB, + storageEstimate, + refresh, + cacheStatus + } = useDatasetCacheStatus(); + + // Log cache status for debugging + useEffect(() => { + console.log('[CacheStatusIndicator] Cache status updated:', { + isLoading, + allCached, + cachedCount, + totalCount, + downloadSizeNeededMB, + datasets: cacheStatus?.datasets + }); + }, [isLoading, allCached, cachedCount, totalCount, downloadSizeNeededMB, cacheStatus]); + + if (isLoading) { + return ( + + + + Checking cache status... + + + ); + } + + return ( + + + {allCached ? ( + + } + label='Cached' + color='success' + size='small' + variant='filled' + /> + + ) : cachedCount > 0 ? ( + + } + label={`Partially cached (${cachedCount}/${totalCount})`} + color='warning' + size='small' + variant='filled' + /> + + ) : ( + + } + label='Not cached' + color='error' + size='small' + variant='filled' + /> + + )} + + {storageEstimate && ( + + } + label={`${storageEstimate.usedMB.toFixed(0)} MB used`} + size='small' + variant='outlined' + /> + + )} + + + } + label='Refresh' + size='small' + variant='outlined' + onClick={refresh} + sx={{ cursor: 'pointer' }} + /> + + + + {/* Show individual dataset status */} + {cacheStatus && cacheStatus.datasets.length > 0 && ( + + {cacheStatus.datasets.map(ds => ( + + ))} + + )} + + {!allCached && ( + + {cachedCount > 0 + ? `~${downloadSizeNeededMB.toFixed(0)} MB remaining to download` + : `~${downloadSizeNeededMB.toFixed(0)} MB download required (may take several minutes)`} + + )} + + {showDebugInfo && cacheStatus && ( + + Debug: {cachedCount}/{totalCount} cached, allCached={String(allCached)} + + )} + + ); +} + export function Geant4DatasetDownloadSelector(props: { geant4DatasetType: Geant4DatasetsType; setGeant4DatasetType: (type: Geant4DatasetsType) => void; @@ -139,6 +285,24 @@ export function Geant4Datasets(props: Geant4DatasetsProps) { const theme = useTheme(); const { geant4DownloadManagerState, geant4DatasetStates, geant4DatasetDownloadStart } = props; const [open, setOpen] = useState(true); + const { allCached, refresh } = useDatasetCacheStatus(); + + // Refresh cache status when download finishes + useEffect(() => { + if (geant4DownloadManagerState === DownloadManagerStatus.FINISHED) { + console.log('[Geant4Datasets] Download finished, refreshing cache status...'); + // Add a small delay to ensure IndexedDB is updated + setTimeout(() => refresh(), 1000); + } + }, [geant4DownloadManagerState, refresh]); + + const buttonText = allCached ? 'Load from cache' : 'Start download'; + const buttonIcon = allCached ? : ; + + const showDownloadButton = geant4DownloadManagerState === DownloadManagerStatus.IDLE; + const showDownloadProgress = + geant4DownloadManagerState === DownloadManagerStatus.WORKING || + geant4DownloadManagerState === DownloadManagerStatus.FINISHED; return ( - {geant4DownloadManagerState === DownloadManagerStatus.IDLE && ( + {/* Always show cache status indicator */} + + + {showDownloadButton && ( )} - {geant4DatasetStates.map(status => ( - - ))} + + {showDownloadProgress && + geant4DatasetStates.map(status => ( + + ))} + {geant4DownloadManagerState === DownloadManagerStatus.ERROR && ( Failed to download datasets. Please check your connection and try again. diff --git a/src/WrapperApp/components/Simulation/Modal/DatasetsFullInfoModal.tsx b/src/WrapperApp/components/Simulation/Modal/DatasetsFullInfoModal.tsx index 3da546abc..1c3b4df17 100644 --- a/src/WrapperApp/components/Simulation/Modal/DatasetsFullInfoModal.tsx +++ b/src/WrapperApp/components/Simulation/Modal/DatasetsFullInfoModal.tsx @@ -1,15 +1,24 @@ +import CachedIcon from '@mui/icons-material/Cached'; +import CloudDownloadIcon from '@mui/icons-material/CloudDownload'; +import StorageIcon from '@mui/icons-material/Storage'; import { Alert, + Box, Button, + Chip, + CircularProgress, Paper, Table, TableBody, TableCell, TableContainer, TableHead, - TableRow + TableRow, + Tooltip, + Typography } from '@mui/material'; +import { useDatasetCacheStatus } from '../../../../Geant4Worker/useDatasetCacheStatus'; import { ConcreteDialogProps, CustomDialog @@ -48,6 +57,101 @@ const datasetSummaries = [ } ]; +/** + * Component to display current cache status in the dialog + */ +function CacheStatusSection() { + const { + isLoading, + allCached, + cachedCount, + totalCount, + downloadSizeNeededMB, + storageEstimate, + cacheStatus + } = useDatasetCacheStatus(); + + if (isLoading) { + return ( + + + Checking cache status... + + ); + } + + return ( + + + Current Cache Status: + + + {allCached ? ( + } + label='All datasets cached' + color='success' + size='small' + /> + ) : cachedCount > 0 ? ( + } + label={`${cachedCount}/${totalCount} datasets cached`} + color='warning' + size='small' + /> + ) : ( + } + label='No datasets cached' + color='error' + size='small' + /> + )} + + {storageEstimate && ( + + } + label={`${storageEstimate.usedMB.toFixed(0)} MB / ${(storageEstimate.quotaMB / 1024).toFixed(1)} GB`} + size='small' + variant='outlined' + /> + + )} + + + {!allCached && ( + + {cachedCount > 0 + ? `~${downloadSizeNeededMB.toFixed(0)} MB remaining to download` + : `~${downloadSizeNeededMB.toFixed(0)} MB total download required`} + + )} + + {cacheStatus && cacheStatus.datasets.length > 0 && ( + + {cacheStatus.datasets.map(ds => ( + + ))} + + )} + + ); +} + export function DatasetsFullInfoDialog({ onClose }: ConcreteDialogProps) { return ( + - Currently there is no indicator showing if you have already downloaded the - datasets. Each time you start a new simulation with FULL datasets option, - you have to press 'Start Download' button. If the datasets are already in - your browser storage, the datasets will be loaded from cache. + The cache status indicator shows which datasets are stored in your browser. + When all datasets are cached, loading will be nearly instant. Otherwise, + datasets will be downloaded from S3 storage. Date: Sat, 29 Nov 2025 22:18:30 +0100 Subject: [PATCH 02/13] refactor: update dataset cache management to use dataFile instead of keySuffix --- src/Geant4Worker/Geant4DatasetCacheService.ts | 77 ++++++++----------- 1 file changed, 33 insertions(+), 44 deletions(-) diff --git a/src/Geant4Worker/Geant4DatasetCacheService.ts b/src/Geant4Worker/Geant4DatasetCacheService.ts index 5b0d66445..0e9819614 100644 --- a/src/Geant4Worker/Geant4DatasetCacheService.ts +++ b/src/Geant4Worker/Geant4DatasetCacheService.ts @@ -4,45 +4,33 @@ * - Database name: EM_PRELOAD_CACHE * - Store: METADATA (contains package UUIDs and chunk counts) * - Store: PACKAGES (contains the actual data chunks) + * + * Cache keys are constructed as: metadata/ + * where PACKAGE_PATH is URL-encoded window.location.pathname + '/' + * and PACKAGE_NAME comes from the preload script (e.g., '/memfs/.../G4EMLOW8.6.1.data') + * + * We detect cached datasets by matching the .data file suffix in IndexedDB keys. */ -// Dataset information matching what's in the preload scripts -// Note: The actual key in IndexedDB is: metadata/ -// where PACKAGE_PATH is URL-encoded current page path -export const GEANT4_DATASETS = [ - { - name: 'G4EMLOW8.6.1', - // The suffix that appears in the metadata key (after any path prefix) - keySuffix: '/memfs/18333901/geant-web-application/build/data/G4EMLOW8.6.1.data', - approximateSizeMB: 580 - }, - { - name: 'G4ENSDFSTATE3.0', - keySuffix: '/memfs/18333901/geant-web-application/build/data/G4ENSDFSTATE3.0.data', - approximateSizeMB: 0.1 - }, - { - name: 'G4NDL4.7.1', - keySuffix: '/memfs/18333901/geant-web-application/build/data/G4NDL4.7.1.data', - approximateSizeMB: 583 - }, - { - name: 'G4PARTICLEXS4.1', - keySuffix: '/memfs/18333901/geant-web-application/build/data/G4PARTICLEXS4.1.data', - approximateSizeMB: 103 - }, - { - name: 'G4SAIDDATA2.0', - keySuffix: '/memfs/18333901/geant-web-application/build/data/G4SAIDDATA2.0.data', - approximateSizeMB: 0.8 - }, - { - name: 'PhotonEvaporation6.1', - keySuffix: '/memfs/18333901/geant-web-application/build/data/PhotonEvaporation6.1.data', - approximateSizeMB: 47 - } +// Dataset configurations with file identifiers (the .data filename used in cache keys) +// These match the actual dataset files from the Geant4 data packages +const DATASET_CONFIGS = [ + { name: 'G4EMLOW8.6.1', dataFile: 'G4EMLOW8.6.1.data', approximateSizeMB: 580 }, + { name: 'G4ENSDFSTATE3.0', dataFile: 'G4ENSDFSTATE3.0.data', approximateSizeMB: 0.1 }, + { name: 'G4NDL4.7.1', dataFile: 'G4NDL4.7.1.data', approximateSizeMB: 583 }, + { name: 'G4PARTICLEXS4.1', dataFile: 'G4PARTICLEXS4.1.data', approximateSizeMB: 103 }, + { name: 'G4SAIDDATA2.0', dataFile: 'G4SAIDDATA2.0.data', approximateSizeMB: 0.8 }, + { name: 'PhotonEvaporation6.1', dataFile: 'PhotonEvaporation6.1.data', approximateSizeMB: 47 } ] as const; +export const GEANT4_DATASETS = DATASET_CONFIGS.map(config => ({ + name: config.name, + dataFile: config.dataFile, + approximateSizeMB: config.approximateSizeMB +})); + +console.log('[CacheService] Initialized GEANT4_DATASETS:', GEANT4_DATASETS); + export const TOTAL_DATASET_SIZE_MB = GEANT4_DATASETS.reduce( (sum, ds) => sum + ds.approximateSizeMB, 0 @@ -117,23 +105,24 @@ async function openDatabase(): Promise { } /** - * Checks if a specific dataset is cached in IndexedDB by looking for any key ending with the suffix + * Checks if a specific dataset is cached in IndexedDB by looking for any key ending with the dataFile + * The cache keys end with the .data filename (e.g., 'G4EMLOW8.6.1.data') */ -async function checkDatasetCachedByKeySuffix( +async function checkDatasetCachedByDataFile( db: IDBDatabase, - keySuffix: string, + dataFile: string, datasetName: string, allMetadataKeys: string[] ): Promise { - // Find any key that ends with our suffix (after removing 'metadata/' prefix) + // Find any key that ends with our dataFile (after removing 'metadata/' prefix) const matchingKey = allMetadataKeys.find(key => { // Keys are stored as 'metadata/' - // We need to check if the key ends with our keySuffix + // where PACKAGE_NAME ends with the dataFile (e.g., '/memfs/.../G4EMLOW8.6.1.data') const keyWithoutPrefix = key.replace(/^metadata\//, ''); // The keyWithoutPrefix might be URL-encoded, so try both const decoded = decodeURIComponent(keyWithoutPrefix); - return keyWithoutPrefix.endsWith(keySuffix) || decoded.endsWith(keySuffix); + return keyWithoutPrefix.endsWith(dataFile) || decoded.endsWith(dataFile); }); if (matchingKey) { @@ -151,7 +140,7 @@ async function checkDatasetCachedByKeySuffix( } console.log( - `[CacheService] Dataset ${datasetName}: NOT CACHED (no matching key for suffix "${keySuffix}")` + `[CacheService] Dataset ${datasetName}: NOT CACHED (no matching key for dataFile "${dataFile}")` ); return false; @@ -241,9 +230,9 @@ export async function checkAllDatasetsCacheStatus(): Promise const datasetStatuses: DatasetCacheStatus[] = await Promise.all( GEANT4_DATASETS.map(async ds => { - const isCached = await checkDatasetCachedByKeySuffix( + const isCached = await checkDatasetCachedByDataFile( db, - ds.keySuffix, + ds.dataFile, ds.name, allKeys ); From 34f0a569eb94b0d4c68e9fdfc29b58bd21cc6011 Mon Sep 17 00:00:00 2001 From: Leszek Grzanka Date: Mon, 1 Dec 2025 10:37:45 +0100 Subject: [PATCH 03/13] Implement feature X to enhance user experience and optimize performance --- public/examples/ex8.json | 104 ++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 40 deletions(-) diff --git a/public/examples/ex8.json b/public/examples/ex8.json index 8ff4beccf..420a88512 100644 --- a/public/examples/ex8.json +++ b/public/examples/ex8.json @@ -75,12 +75,7 @@ } }, "ViewPanel": { - "cameraMatrix": [ - 0.07426714888874009, 0, 0.9972383820310657, 0, 0.1890359579236641, - 0.9818692455756362, -0.014078039800121761, 0, -0.9791576978239105, - 0.18955944870338465, 0.07292062945044075, 0, -27.694761919291807, - 5.361550864645869, 2.0625068629119263, 1 - ] + "cameraMatrix": [0.07426714888874009,0,0.9972383820310657,0,0.1890359579236641,0.9818692455756362,-0.014078039800121761,0,-0.9791576978239105,0.18955944870338465,0.07292062945044075,0,-27.694761919291807,5.361550864645869,2.0625068629119263,1] } }, "history": { @@ -106,8 +101,8 @@ "visible": true, "geometryData": { "geometryType": "HollowCylinderGeometry", - "position": [0, 0, 0], - "rotation": [0, 0, 0], + "position": [0,0,0], + "rotation": [0,0,0], "parameters": { "innerRadius": 0, "radius": 6, @@ -123,8 +118,8 @@ "visible": true, "geometryData": { "geometryType": "HollowCylinderGeometry", - "position": [0, 0, 0], - "rotation": [0, 0, 0], + "position": [0,0,0], + "rotation": [0,0,0], "parameters": { "innerRadius": 0, "radius": 5.5, @@ -140,8 +135,8 @@ "visible": true, "geometryData": { "geometryType": "HollowCylinderGeometry", - "position": [0, 0, -0.5], - "rotation": [0, 0, 0], + "position": [0,0,-0.5], + "rotation": [0,0,0], "parameters": { "innerRadius": 0, "radius": 5, @@ -157,8 +152,7 @@ "density": 1, "geant4_name": "G4_WATER" } - } - ], + }], "simulationMaterial": { "icru": 1000, "name": "VACUUM", @@ -166,8 +160,7 @@ "density": 0, "geant4_name": "G4_Galactic" } - } - ], + }], "simulationMaterial": { "icru": 0, "name": "BLACK HOLE", @@ -175,8 +168,7 @@ "density": 0, "geant4_name": "BlackHole" } - } - ] + }] }, "zoneManager": { "uuid": "368269D3-6F9B-4241-84A0-5D908D10E196", @@ -198,8 +190,8 @@ "visible": false, "geometryData": { "geometryType": "BoxGeometry", - "position": [0, 0, 10.5], - "rotation": [0, 0, 0], + "position": [0,0,10.5], + "rotation": [0,0,0], "parameters": { "width": 0, "height": 0, @@ -225,8 +217,8 @@ "visible": true, "geometryData": { "geometryType": "Cyl", - "position": [0, 0, -0.5], - "rotation": [0, 0, 0], + "position": [0,0,-0.5], + "rotation": [0,0,0], "parameters": { "radius": 5, "innerRadius": 0, @@ -244,8 +236,8 @@ "visible": true, "geometryData": { "geometryType": "Mesh", - "position": [0, 0, -0.5], - "rotation": [0, 0, 0], + "position": [0,0,-0.5], + "rotation": [0,0,0], "parameters": { "width": 0.5, "height": 5, @@ -264,8 +256,8 @@ "visible": true, "geometryData": { "geometryType": "Cyl", - "position": [0, 0, -10.55], - "rotation": [0, 0, 0], + "position": [0,0,-10.55], + "rotation": [0,0,0], "parameters": { "radius": 5, "innerRadius": 0, @@ -283,8 +275,8 @@ "visible": true, "geometryData": { "geometryType": "Cyl", - "position": [0, 0, 4.85], - "rotation": [0, 0, 0], + "position": [0,0,4.85], + "rotation": [0,0,0], "parameters": { "radius": 5, "innerRadius": 0, @@ -339,8 +331,7 @@ "icru": 1000, "density": 0, "color": 196613 - } - ], + }], "selectedMaterials": { "a2f08097-a999-4a4f-8371-e919e2f999a7": 1 }, @@ -422,7 +413,7 @@ { "name": "FluenceProtons", "type": "Quantity", - "uuid": "7e44cf79-4ee1-4ea1-9ac0-7095c96ffdd1", + "uuid": "66459cef-5e3b-4a7f-be48-82dbc77c010d", "filter": "f96f7542-143f-4c2c-b7ca-8a121ea2f631", "keyword": "Fluence", "histogramNBins": 100, @@ -495,8 +486,7 @@ { "id": 2, "name": "Proton" - } - ], + }], "kineticEnergyLow": 1, "kineticEnergyHigh": 10, "kineticEnergyUnit": "MeV" @@ -1353,8 +1343,21 @@ }, "filterType": "particle" } - } - ] + }, + { + "name": "fluenceNeutron", + "dimensions": 1, + "axisDim1": { + "name": "Position (Z)", + "unit": "cm", + "values": [-10.525,-10.475,-10.425,-10.375,-10.325,-10.275,-10.225,-10.175,-10.125,-10.075,-10.025,-9.975,-9.925,-9.875,-9.825,-9.775,-9.725,-9.675,-9.625,-9.575,-9.525,-9.475,-9.425,-9.375,-9.325,-9.275,-9.225,-9.175,-9.125,-9.075,-9.025,-8.975,-8.925,-8.875,-8.825,-8.775,-8.725,-8.675,-8.625,-8.575,-8.525,-8.475,-8.425,-8.375,-8.325,-8.275,-8.225,-8.175,-8.125,-8.075,-8.025,-7.975,-7.925,-7.875,-7.824999999999999,-7.775,-7.725,-7.675000000000001,-7.625,-7.575,-7.525,-7.475,-7.425,-7.375,-7.325,-7.275,-7.225,-7.175,-7.125,-7.074999999999999,-7.025,-6.975,-6.925000000000001,-6.875,-6.825,-6.775,-6.725,-6.675,-6.625,-6.574999999999999,-6.525,-6.475,-6.425000000000001,-6.375,-6.325,-6.275,-6.225,-6.175,-6.125,-6.075,-6.025,-5.975,-5.925,-5.875,-5.824999999999999,-5.775,-5.7250000000000005,-5.675,-5.625,-5.575,-5.525,-5.4750000000000005,-5.425000000000001,-5.375,-5.325,-5.275,-5.2250000000000005,-5.175000000000001,-5.125,-5.075,-5.025,-4.975,-4.925,-4.875,-4.825,-4.775,-4.725,-4.675,-4.625,-4.574999999999999,-4.5249999999999995,-4.475,-4.425,-4.375,-4.324999999999999,-4.2749999999999995,-4.2250000000000005,-4.175000000000001,-4.125,-4.075,-4.025,-3.9750000000000005,-3.9250000000000007,-3.875,-3.825,-3.7750000000000004,-3.7249999999999996,-3.675,-3.625,-3.575,-3.5250000000000004,-3.4749999999999996,-3.425,-3.375,-3.3249999999999993,-3.2749999999999995,-3.2249999999999996,-3.175,-3.125,-3.0749999999999993,-3.0249999999999995,-2.9750000000000005,-2.9250000000000007,-2.875,-2.825,-2.7750000000000004,-2.7250000000000005,-2.6750000000000007,-2.625,-2.575,-2.5250000000000004,-2.4749999999999996,-2.4250000000000007,-2.375,-2.3249999999999993,-2.2750000000000004,-2.2249999999999996,-2.1750000000000007,-2.125,-2.0749999999999993,-2.0250000000000004,-1.9749999999999996,-1.924999999999999,-1.875,-1.8249999999999993,-1.7749999999999986,-1.7250000000000014,-1.6750000000000007,-1.625,-1.575000000000001,-1.5250000000000004,-1.4749999999999996,-1.4250000000000007,-1.375,-1.3249999999999993,-1.2750000000000004,-1.2249999999999996,-1.1750000000000007,-1.125,-1.0749999999999993,-1.0250000000000004,-0.9749999999999996,-0.9250000000000007,-0.875,-0.8249999999999993,-0.7750000000000004,-0.7249999999999996,-0.6749999999999989,-0.625,-0.5749999999999993,-0.5249999999999986,-0.4750000000000014,-0.42499999999999893,-0.375,-0.3249999999999993,-0.27500000000000036,-0.22499999999999964,-0.1750000000000007,-0.125,-0.07499999999999929,-0.02499999999999858,0.025000000000000355,0.07500000000000107,0.125,0.17499999999999893,0.22499999999999964,0.2749999999999986,0.3249999999999993,0.375,0.4250000000000007,0.47499999999999964,0.5250000000000004,0.5749999999999993,0.625,0.6749999999999989,0.7250000000000014,0.7749999999999986,0.8250000000000011,0.875,0.9250000000000007,0.9749999999999996,1.0250000000000004,1.0749999999999993,1.125,1.1750000000000007,1.2250000000000014,1.2750000000000004,1.325000000000001,1.375,1.424999999999999,1.4749999999999996,1.5249999999999986,1.5749999999999993,1.625,1.6750000000000007,1.7249999999999996,1.7750000000000004,1.8249999999999993,1.875,1.924999999999999,1.9750000000000014,2.0249999999999986,2.075000000000001,2.125,2.1750000000000007,2.2249999999999996,2.2750000000000004,2.3249999999999993,2.375,2.4250000000000007,2.4750000000000014,2.5250000000000004,2.575000000000001,2.625,2.674999999999999,2.7249999999999996,2.7749999999999986,2.8249999999999993,2.875,2.9250000000000007,2.9749999999999996,3.0250000000000004,3.0749999999999993,3.125,3.174999999999999,3.2250000000000014,3.2749999999999986,3.325000000000001,3.375,3.4250000000000007,3.4749999999999996,3.5250000000000004,3.5749999999999993,3.625,3.6750000000000007,3.7250000000000014,3.7750000000000004,3.825000000000001,3.875,3.924999999999999,3.9749999999999996,4.024999999999999,4.074999999999999,4.125,4.175000000000001,4.225,4.275,4.324999999999999,4.375,4.424999999999999,4.475000000000001,4.524999999999999,4.575000000000001,4.625,4.675000000000001,4.725,4.775,4.824999999999999,4.875,4.925000000000001,4.975000000000001,5.025,5.075000000000001,5.125,5.174999999999999,5.225,5.274999999999999,5.324999999999999,5.375,5.425000000000001,5.475,5.524999999999999,5.574999999999999,5.625,5.675000000000001,5.725000000000001,5.774999999999999,5.824999999999999,5.875,5.925000000000001,5.975000000000001,6.025000000000002,6.074999999999999,6.125,6.175000000000001,6.225000000000001,6.274999999999999,6.325000000000003,6.375,6.424999999999997,6.475000000000001,6.524999999999999,6.574999999999999,6.625,6.675000000000001,6.724999999999998,6.774999999999999,6.824999999999999,6.875,6.925000000000001,6.975000000000001,7.024999999999999,7.074999999999999,7.125,7.175000000000001,7.225000000000001,7.275000000000002,7.324999999999999,7.375,7.425000000000001,7.475000000000001,7.524999999999999,7.575000000000003,7.625,7.674999999999997,7.725000000000001,7.774999999999999,7.824999999999999,7.875,7.925000000000001,7.974999999999998,8.024999999999999,8.075,8.125,8.175,8.225000000000001,8.274999999999999,8.325,8.375,8.425,8.475000000000001,8.525000000000002,8.575,8.625,8.675,8.725000000000001,8.774999999999999,8.825000000000003,8.875,8.924999999999997,8.975000000000001,9.024999999999999,9.075,9.125,9.175,9.224999999999998,9.274999999999999,9.325,9.375,9.425] + }, + "data": { + "name": "fluenceNeutron", + "unit": "percm2/prim", + "values": [0.0013586174907669832,0.0013585602970397066,0.001297853360989075,0.001279560930912162,0.001262726199561601,0.001246870705757278,0.0012881864729499374,0.0012852053171444845,0.0012944406733857525,0.0013028800128127825,0.0013064446359644006,0.001394147960616963,0.001396059982511218,0.0014421383029460414,0.001396307402444841,0.0013915749366144436,0.0014080076749072635,0.0013739694573043225,0.001345406566550983,0.001378742180802962,0.001335980288092602,0.0014842974392903787,0.001381883562007952,0.0013111698061027345,0.001338481721458401,0.001398009916525107,0.0014512446772699476,0.0014238826224540035,0.0014516015892302235,0.001418719072875611,0.0014736748116735794,0.0014403830494672755,0.001421979336661383,0.00141189074668596,0.0014833361915327235,0.001410133041302654,0.0014106355475021854,0.0015039615710442835,0.0014853384974600826,0.0015621085061323595,0.001509103584290561,0.0015327008729761856,0.0014580007976079876,0.001501489258409687,0.0015821421186319115,0.001598436792165804,0.0016777449927734814,0.0017029831269574206,0.00166855599807796,0.0015956933088946633,0.0017038423214850152,0.0016642584199664814,0.001660301501428113,0.0017422537972940524,0.0017716093936862869,0.0017555771295312155,0.0017521842072378295,0.0017143779783673231,0.001767314359198832,0.0018054735695189833,0.0017570007183623463,0.0017374733019692155,0.0017523644412331802,0.001743542628765408,0.001760170823731822,0.001840673766419147,0.0018519411023803312,0.0018195621627933175,0.0018668544658135026,0.0019191321254584171,0.0018285364035891551,0.0018435059403008405,0.0018549129193669146,0.0019383677265510514,0.0019290834529561561,0.0019525013894508977,0.0019471337703078327,0.0020252711160008052,0.0019337726726130701,0.001910697873553473,0.002013332703672448,0.0019458421583213959,0.00197258930028617,0.0019802467328413056,0.00195408048688983,0.002011006352093603,0.0021069227521162944,0.0020990949071866107,0.002042372751847745,0.001976759724169616,0.0020241436262046037,0.002086974293786418,0.0020185403797275936,0.002015958233178295,0.00204476741169781,0.0019696783775917776,0.001960378011716945,0.001970300582474966,0.0019394789601137024,0.0019495292596112804,0.0019323721025201535,0.002009734015760059,0.0019687655460598544,0.0020511906210717717,0.0020691297124241274,0.0021468194880499562,0.0021205561813329673,0.0020396495715059703,0.002084264287076838,0.0021169135565519115,0.0020739243822350574,0.002075139101610106,0.002075717276280275,0.002122287871239681,0.0020653445506999793,0.0020877523617025026,0.0020605003564190603,0.0020445735687315797,0.002049146543184863,0.0020998650911842566,0.0021442628337070345,0.0022032024824865035,0.002189644820523095,0.0022503422096437683,0.0022663902008900417,0.0023341930085453394,0.0022804803037031274,0.0022561060100103427,0.002313441042565557,0.002260367098461858,0.0021562541218142646,0.0022034216479213773,0.0022295994370462,0.0023025649787184895,0.002168784125664237,0.002084564129581987,0.0021136105161829372,0.0021657529849455548,0.0022752569774279773,0.0022521180176444913,0.0022960780512701205,0.0023334283846156573,0.002284896336036287,0.002304673472912988,0.0023233921624620413,0.0023170801626751906,0.0023984074761496466,0.0023647503934969235,0.002336051171339145,0.002427352500140771,0.002414285662153907,0.0024462830128911856,0.0024652114994118475,0.002477072236238946,0.002422066500871576,0.002448189055300519,0.002386871101851488,0.0023675941685738894,0.0023384863233761456,0.0022742689896181143,0.0023509337795657452,0.0024001648164459015,0.00241343724083852,0.0024540044126963663,0.0024048912852311236,0.0023578440415015934,0.0023692853022024072,0.0023620411992823216,0.0024042670962507035,0.0023789909965479987,0.002337763705748916,0.002322395307203802,0.0023695693237819875,0.002396227489792075,0.002461979480206216,0.0025580498759938575,0.002479287028327186,0.002510504720658075,0.0025719239773873584,0.0025501157034606404,0.0024968002801825286,0.002541220724125552,0.0025674097678068087,0.00254568470515666,0.0025270242498475182,0.0025729510023619335,0.0025586542041410583,0.002653328919558925,0.0027032946661487522,0.0025747026335317448,0.0024986463150286735,0.002492208394319413,0.002459370650764523,0.00249730165941018,0.0025962337548595597,0.0025543196083490953,0.0025942182410246227,0.0025685042256077713,0.0024664606616357286,0.0025072624453557116,0.0024965703722528336,0.002468835904219124,0.002509380046073892,0.0025643234845778968,0.002555142407876501,0.0024772824737142826,0.0024955155074912663,0.00252284405144651,0.0026515732875279086,0.002633961246010997,0.0026057693700693094,0.002555376152019355,0.0025559599309497387,0.0026846069713107766,0.0028300192657880786,0.0025885298012127103,0.002567968841023542,0.0026054089128086134,0.00254056238288585,0.002532754938150843,0.002585182874617712,0.0026237880537064305,0.002630986308795418,0.0025966825068573715,0.0026204408155680657,0.0025503896527599244,0.002598776947942916,0.0025546007643589053,0.0026373614588477475,0.0026323250838459294,0.0025427950027694587,0.0025332127539842465,0.0023773763034334303,0.0024862541206393213,0.002449636037655651,0.002530101182273939,0.0025177294283554898,0.0024704834668071054,0.0024809643354211535,0.0025124282552653598,0.002520654037242411,0.0025557816777916392,0.0025389879990840823,0.002544722345722902,0.00254675168222957,0.002555816060654869,0.0025406740810325393,0.0025446824935249895,0.0026983932770946327,0.0026365907746639817,0.0025555198207269396,0.0025340470151006267,0.0025432022178095317,0.0025576178318992516,0.002468907816788933,0.0025940445475723024,0.002636131603187675,0.002617229206283153,0.0025445603535755607,0.0024952818855915474,0.0025208085417154757,0.002537541570173662,0.0025966505812201096,0.002606149131705206,0.0025695220340425473,0.0025834153570605985,0.0025527530719268872,0.0026025916204469152,0.0026018277652476605,0.002569626439304997,0.0025887386740164804,0.0025999952786491536,0.0025855546790236085,0.0025309945274202663,0.002462178726180644,0.0024448404091397665,0.002536815464199708,0.0025078712958907425,0.0026374956657837334,0.0025452595110921823,0.0025450139755602424,0.00257159424125701,0.002581214513899598,0.002585381604907393,0.002631652818843655,0.002582037011164811,0.0025981350505637976,0.0027042126247847475,0.002638767478633561,0.0026914092306208125,0.0026846696908316547,0.0025867310287355353,0.0025252691204286533,0.002607769191272568,0.002747833661519559,0.002668509246785019,0.0026298955062578843,0.002720085787655736,0.002796455399932278,0.002622704825104637,0.002657496084703433,0.0026296245680582533,0.0025783359592253603,0.0025457864250819275,0.0025290638915559417,0.002575454619988223,0.0026018633404397756,0.0026099673764950113,0.002520054851171945,0.002546370636445346,0.002529845560042722,0.002530029207372644,0.0025604473499014927,0.002494786292371014,0.0025095136930213574,0.002486009574485666,0.0025335469079558453,0.0025656242754579913,0.0026334664315211514,0.002635304639519435,0.0025529691080096624,0.0024826886535956193,0.0025130008367772487,0.002628981288672424,0.0024962649243107557,0.0025294135064963127,0.0025481916399308405,0.002559210719914553,0.002638676766200926,0.002668607592506974,0.002646952708686493,0.0026135643704641017,0.0026201758814340037,0.0025816394815266212,0.0025251455227761573,0.002554940164528235,0.00255203862874208,0.0025138206064436535,0.0024866665682694534,0.0024801745739291272,0.0026918353745179467,0.002572323695769356,0.002532929438854141,0.0025573545452264824,0.002547284986047924,0.0025070506191462558,0.0025274372997768683,0.0024994544109441653,0.002626787653367227,0.0025090836290179107,0.0025303031237952035,0.002427101913812969,0.00242364632744179,0.0025134793010505815,0.002483254568218941,0.0025842711079498842,0.0025160528222017958,0.002417304621100028,0.002420296891251702,0.0024886306446811647,0.002556562493262769,0.002673529127639421,0.0025951867505315386,0.0025814076997109575,0.002624580352875512,0.0026449462032876524,0.002709505513563803,0.002728514024783527,0.002693614033310787,0.002685446720584668,0.0026773171624616,0.002699421429626917,0.0026499181119067306,0.002620187613509808,0.0027301444753855355,0.0026593461513115023,0.0027116047421093187,0.002723000707328187,0.0027120750047160322,0.0026648876805882805,0.002720799343928935,0.00271182710859854,0.0026820152103704774,0.002741446267874873,0.0027744995815364376,0.0027280410844990792,0.0027773119826661665,0.0029238593825965387,0.0028162181894801144,0.00288294801188059,0.0029482535980893607,0.002850991718930837,0.0028893061484189337,0.002887131875292075,0.0028861553314602725,0.0028545401181209323,0.0029436195587643366,0.002952357957778102,0.002993530397620603,0.003469144253829751] + } + }] }, { "name": "YZ_Mesh", @@ -29107,8 +29110,29 @@ }, "filterType": "particle" } - } - ] - } - ] -} + }] + }, + { + "name": "XY_Mesh", + "pages": [ + { + "name": "fluence", + "dimensions": 2, + "axisDim1": { + "name": "Position (X)", + "unit": "cm", + "values": [-5.05,-4.95,-4.85,-4.75,-4.65,-4.55,-4.45,-4.35,-4.25,-4.15,-4.05,-3.95,-3.8499999999999996,-3.75,-3.65,-3.55,-3.45,-3.3499999999999996,-3.25,-3.15,-3.05,-2.95,-2.85,-2.75,-2.6500000000000004,-2.55,-2.45,-2.3499999999999996,-2.25,-2.1500000000000004,-2.0500000000000003,-1.9500000000000002,-1.85,-1.75,-1.65,-1.5500000000000003,-1.4500000000000002,-1.35,-1.25,-1.15,-1.0499999999999998,-0.9499999999999993,-0.8500000000000005,-0.75,-0.6500000000000004,-0.5499999999999998,-0.4500000000000002,-0.34999999999999964,-0.25,-0.15000000000000036,-0.04999999999999982,0.04999999999999982,0.15000000000000036,0.25,0.35000000000000053,0.4500000000000002,0.5500000000000007,0.6499999999999995,0.75,0.8499999999999996,0.9499999999999993,1.0499999999999998,1.1500000000000004,1.25,1.3499999999999996,1.4500000000000002,1.5500000000000007,1.6500000000000004,1.75,1.8500000000000005,1.9499999999999993,2.05,2.1499999999999995,2.25,2.3499999999999996,2.45,2.55,2.6500000000000004,2.75,2.8500000000000005,2.95,3.0500000000000007,3.1499999999999986,3.25,3.3499999999999996,3.4499999999999993,3.5500000000000007,3.6500000000000004,3.75,3.8499999999999996,3.9499999999999993,4.050000000000001,4.15,4.25,4.350000000000001,4.449999999999999,4.549999999999999,4.65,4.75,4.85] + }, + "axisDim2": { + "name": "Position (Y)", + "unit": "cm", + "values": [-5.05,-4.95,-4.85,-4.75,-4.65,-4.55,-4.45,-4.35,-4.25,-4.15,-4.05,-3.95,-3.8499999999999996,-3.75,-3.65,-3.55,-3.45,-3.3499999999999996,-3.25,-3.15,-3.05,-2.95,-2.85,-2.75,-2.6500000000000004,-2.55,-2.45,-2.3499999999999996,-2.25,-2.1500000000000004,-2.0500000000000003,-1.9500000000000002,-1.85,-1.75,-1.65,-1.5500000000000003,-1.4500000000000002,-1.35,-1.25,-1.15,-1.0499999999999998,-0.9499999999999993,-0.8500000000000005,-0.75,-0.6500000000000004,-0.5499999999999998,-0.4500000000000002,-0.34999999999999964,-0.25,-0.15000000000000036,-0.04999999999999982,0.04999999999999982,0.15000000000000036,0.25,0.35000000000000053,0.4500000000000002,0.5500000000000007,0.6499999999999995,0.75,0.8499999999999996,0.9499999999999993,1.0499999999999998,1.1500000000000004,1.25,1.3499999999999996,1.4500000000000002,1.5500000000000007,1.6500000000000004,1.75,1.8500000000000005,1.9499999999999993,2.05,2.1499999999999995,2.25,2.3499999999999996,2.45,2.55,2.6500000000000004,2.75,2.8500000000000005,2.95,3.0500000000000007,3.1499999999999986,3.25,3.3499999999999996,3.4499999999999993,3.5500000000000007,3.6500000000000004,3.75,3.8499999999999996,3.9499999999999993,4.050000000000001,4.15,4.25,4.350000000000001,4.449999999999999,4.549999999999999,4.65,4.75,4.85] + }, + "data": { + "name": "fluence", + "unit": "percm2/prim", + "values": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00638998761205802,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001471901917299672,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0013842360977750084,0.0005993053052334495,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.002235460932987602,0.00626644029995875,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000008403839591857356,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000020175411402633334,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500005364925552,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0050012787654897944,0,0.0025743188071741785,0.0030775113395339194,0,0,0,0,0,0,0,0,0.005002396820883705,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00007045806688398156,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005000060085546075,0,0,0,0.00500074446599687,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001986828182626878,0.0028927501210563853,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.010000586748746685,0,0,0,0,0,0.015001730545032746,0,0.005154215167225015,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001311201544530466,0.005774219458172745,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00502707019175119,0,0,0,0,0,0.005001088265923625,0,0,0.005001041972347065,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.004372334287209844,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500014336646215,0.00500102041476183,0.00500008279749661,0,0,0.00500091780379451,0.010002702386026185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005000808998249235,0,0,0,0.005001342425060915,0.0050001306712317995,0.005000495907400844,0,0,0.005000320757612145,0.010001932890350756,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500033513429004,0,0,0,0,0,0.00500009296027707,0,0.0050001242149992995,0,0,0.015001800343709227,0.005000165031239065,0,0.00591345810157057,0.004293606448467236,0.0050025757557196,0.010000780137357999,0.005001035175873675,0,0.005000090477528075,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005430436837942535,0,0,0,0,0.005000054006286689,0,0.00500058028193665,0.01000425044540021,0.01000118632662149,0.005000007361152595,0,0.00500024640093809,0.014167451733489546,0,0.010000795986400985,0,0.00500006111141558,0,0.020002633844831728,0,0,0.004224214058437003,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0069832371077185856,0,0.005000885761951215,0,0,0,0,0,0,0.00782714732625547,0.00717413873677291,0,0.011188395779501545,0.00500018135057117,0.00500009511429893,0.01500126791601266,0.010000125190743905,0.005000159042075635,0.005000406446498925,0.00530068070149354,0.0050004956983117094,0,0.0007815346472096725,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000548689167337527,0,0.005000345713833275,0.00500082659836456,0,0.0019012460026973134,0.008518731149979336,0.02121103907801432,0.019382386903620263,0.015001337861633164,0.01195030148715155,0.015001694592139495,0,0,0.00500034737685662,0,0,0,0.0050001617877571,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00005594349884329195,0,0.00500033737715154,0.010002118582377576,0,0.001727187703366711,0.0059643749420963555,0,0.00500004948765611,0.005000094089482645,0.01000650166223669,0.023643318173353495,0.00500100280953848,0.010721496267866814,0.00928916765355381,0.02883817176247306,0.00500065798417424,0.00500018461411065,0,0.015003180312886031,0.00500125321801847,0.005000202705768355,0,0,0.005000414557961885,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0006866558456648795,0.0054242601755452,0.015006816303884465,0.010001698213001946,0.020002594066929644,0.0097259619142652,0.030780159475806295,0.020956186226796375,0.02649471698659885,0.027038657091350355,0.021326990007133735,0.014331562646628094,0.00538213592343094,0.00500018401887639,0,0,0,0,0,0,0,0,0,0,0.005000944323491155,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0050039752724585955,0.005001170456700615,0.0050014867243987505,0.010001387838533625,0.005001478973626606,0.0050009067313602105,0.02000264645994596,0.015002334242015235,0.0060671280968823404,0.023936709824313597,0.015003528199424184,0.025005232418594703,0.015001404736483556,0.02000555956435942,0.02902267849317561,0.03236923128224402,0.011370927831598075,0.020002006688935835,0.015004969237815333,0.010000730620946615,0.010005074658890235,0.005000048843459815,0.005003060371525445,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0050007731663817044,0,0,0.010003942677878744,0,0.005000488283024915,0,0.005000047491656885,0.010002849211942114,0.01000058964062371,0.015003469196224969,0.015016956828334507,0.03438142742351409,0.020001221985816504,0.035003071594469276,0.02857886774681093,0.01653481559354237,0.01000043266567332,0.010001152351504936,0.02003952917980575,0.010001131641053875,0,0.00500039359774579,0,0.0050004119194458855,0.005000946057687125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500003346301965,0.005001083097443425,0,0.006288588027194165,0.01000045987010227,0.01000306828125913,0.025004108586432032,0.02887940298103274,0.06257229548405005,0.02513071752418615,0.03562614579757698,0.03500751146408692,0.04000681543156415,0.04011853362583471,0.03000487550627562,0.010000740217870396,0.014213030959061734,0.01564663747254162,0.010000996627285291,0.020167495921746662,0.01000009146453439,0.0050000312014008,0.01000203582886367,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005000773251532356,0,0.0011901557932405171,0,0,0,0,0.00500086710249688,0.02079628566441131,0.010000286536380026,0.00500090146124424,0.0150023093355816,0.02000302550588638,0.02500130019188768,0.040005600535049854,0.03197648539694816,0.04000529989215082,0.03000912497347068,0.05011649576628785,0.035031363141392435,0.020002630006037324,0.015315054766757069,0.01500180778096865,0.00330349720622036,0.0074220287562239305,0.005000130087892855,0.00500121839813427,0,0.0050004803219014906,0,0,0,0.005000276408173385,0,0,0,0,0,0,0,0,0.0050198516233337254,0.0032761385972662426,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.004054580011792678,0,0,0,0,0,0,0,0,0,0.00005363768635916645,0,0,0,0,0,0,0,0.004074409011320685,0,0,0.005000337684678315,0,0.010001952622005894,0.010544191446741359,0.03502221151277749,0.020001777084681274,0.01789526551021492,0.04400611428145343,0.035159411390128924,0.060319801486084394,0.028030858571994156,0.04500469342328553,0.0702220636132648,0.0501208852168128,0.03218691022833387,0.025036239567352292,0.010000869947712746,0.04504371129638475,0.01022816514302277,0.01000053091483707,0.01000329484396994,0,0.005001108101826955,0,0,0.005000361275919824,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001228223040666367,0.005895865299701525,0.004376450541173079,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.010000754495478735,0,0,0,0.020004683986063334,0.010000764555980386,0.02039432056887832,0.020000810871117908,0.02000159453177159,0.02000301715186241,0.06476909534726324,0.050932022655685,0.04001493837612252,0.07288405126376944,0.06318561117757701,0.055004838911624304,0.0586097361410595,0.018768600082863796,0.045328923882708434,0.03878377269288316,0.03500502593076251,0.030004846609493364,0.00500116832189133,0.025056466212626468,0.010398492507196155,0.01117781396536202,0,0.005000141939440635,0,0,0,0,0,0,0,0.0020167156163796002,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0006565891089297754,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.010000478428442655,0.02320333320774783,0.03000244951465927,0.025003229231434703,0.025001712069205925,0.03898746581299575,0.04544880870190611,0.06000477217441745,0.030002326461448472,0.060521468265127706,0.0815519966192786,0.09236365015098885,0.06001290943715095,0.0508412702884003,0.04127483092814562,0.020003257443020415,0.0250007037055342,0.015000704671934236,0.020002822227725283,0.025783719316306387,0.010002503798612434,0.01000035328746929,0.004915112740835735,0.0021570499076361614,0,0,0,0,0,0,0.004986842965236323,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.001911300637265568,0.00572163008416493,0.0018434822232713784,0,0,0,0,0.005000888401518215,0,0,0,0.010001059318126561,0.01572813245092589,0.001704671590776408,0.045005228505709156,0.015003626799185401,0.04446963934573235,0.04180295319769063,0.04000847830529244,0.03348939310926622,0.06400763151322114,0.11002730245029896,0.0800162817289858,0.07112035383714314,0.05917160587232435,0.05001094415233395,0.07068643942999805,0.05571622951474245,0.050009034913888,0.030007248205679123,0.01000122811161149,0.010001553234462286,0.015001483163033274,0.00500094251136888,0,0.005001729644529901,0.00500089510218896,0,0,0,0.000873855912078669,0.00632759762640341,0.004808722600726892,0.004530078970383373,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0017579982575252266,0,0,0,0,0,0,0.0037888086742890728,0.00584699010107529,0.0022465177847037364,0,0.00500029343021396,0.014108784860918456,0.030004283204259116,0.0250031760135139,0.025003940427342913,0.07152413656751509,0.0340965621566813,0.045007903408423436,0.0700114727105782,0.08500968732790785,0.11530978949941925,0.10987473414714541,0.07501485460820731,0.050006624161344305,0.10428331404566879,0.05809560521145766,0.0873257278146381,0.051632373660371045,0.03522755720155396,0.04967254194545563,0.037999090649799304,0.00500232356503918,0.00500006647443631,0.010001315051369095,0.010001018977489085,0,0,0,0,0,0,0,0,0.0013426515715139365,0.00536515149520343,0.005332196346480405,0.0023914282207102154,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500087506376626,0.0050001082413638894,0.00500048857672043,0.015003471194112574,0.01000025935850255,0.01681905671109063,0.015003319194834719,0.03995415822165963,0.053790534847889204,0.03500591730482926,0.09000909373244305,0.06118753397900435,0.1388470691916146,0.1384306034370579,0.13434360913610985,0.0845769255255115,0.1001266842011652,0.0954732111807592,0.07001097961105045,0.0575438455172595,0.03838188556940388,0.0642879266580068,0.05909138165441835,0.02242662467291596,0.0250027994524374,0.01998216110528666,0,0.0050004858049883995,0.005000054320544865,0.006384185727837609,0.00500638658679283,0,0.005000067984262715,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.004973982698380441,0.005000794379401925,0,0,0.010001121981480234,0.00500118778782428,0.00500061562292869,0.032229842977525576,0.041232368900028495,0.034062609569572556,0.0700097207640796,0.02500328187878643,0.0723457083310918,0.11078875109385981,0.12232859829126305,0.12672627112331905,0.1132065532162909,0.1607496919203921,0.11742846588288569,0.1334219211823606,0.0791581506524226,0.084700529146479,0.1165828160999021,0.023017862026990427,0.034645141112689154,0.05509387529343645,0.01504932621810165,0.04268265859476409,0.010002245561059461,0.005000047367008565,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0056028960679390845,0.0025684041491505303,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.004025031218719142,0.0053823646864907355,0.00032782186990773705,0.0036296036365475117,0,0,0,0.000028186628297005288,0,0,0.005000450849179935,0.01000057129460569,0.005000231917486315,0.00500042431131071,0.01500050945935776,0.03529932859837738,0.04941521428369702,0.05887187595721905,0.1054801394451273,0.06658738202018795,0.15550408046780545,0.12385446726405765,0.18972180036131162,0.09674822025203415,0.1959127748358642,0.12052602305731296,0.13377407192775323,0.1264614703145414,0.08310621340071905,0.09358494519060584,0.03786998557213574,0.03181762597997508,0.026799449795520673,0.016078336030853926,0.0050002327620593395,0.0152511298724635,0.00500017724488503,0.001353354158036295,0.0056091057485170605,0.008453474238155751,0.0010932958000166796,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0002944558179909917,0.002788005018638888,0.003289074035637013,0,0,0,0,0.0050013078212248156,0.005000241381396,0.01500521811760023,0.018174516845659534,0.015477754131111417,0.015001324844416354,0.030001268510737127,0.02000672576808604,0.035216842875689505,0.0803662321531943,0.10887170797213834,0.0956017987939897,0.12001500181525705,0.19018171322657096,0.16829970618583237,0.1942691759723164,0.1462118142381677,0.120221479212854,0.1400207172396707,0.10417689884488379,0.13417962930629326,0.09321670236931084,0.0741240743995886,0.035283637325519195,0.02647246360091434,0.04355898235871698,0.02000236389722943,0.015006060911406055,0.0050004230801744005,0.005000436614100451,0.0099008377583734,0.002096813132540923,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500019443974645,0.005313327302358495,0.005000074301290355,0.010000802933532314,0.01000161800457024,0.00500385751263122,0.01629290688302824,0.03350706433642995,0.03500407333175605,0.0601303588789403,0.0731209673996428,0.079399344942426,0.0956281841491865,0.1050112017740334,0.16742095968495288,0.16177261819186864,0.1927427109318264,0.1802037938475053,0.16547775210227889,0.14657096275731768,0.15196726143942002,0.0833995379192467,0.1255798055495873,0.08952353499931585,0.04591340783867491,0.049115751530706304,0.030003963859050877,0.00500025486283891,0.010000502092165534,0.02396340151613759,0.0074157544337083705,0,0.005000049063309315,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00519557949679816,0.00039939954547807643,0,0,0,0.00664072612579361,0.008360101308831934,0.023767244264424933,0.02824882692895062,0.03721306846018071,0.03676917498792622,0.0753359428065502,0.0802349767972987,0.06531229751264571,0.1450757080965426,0.0856103122943048,0.2269719070384589,0.17326202437221988,0.18406438492345836,0.1911461526342389,0.181823819891987,0.15004277755820916,0.1579134686936043,0.1300940805921944,0.10631621192136449,0.0924059007979395,0.0847013918318332,0.030001947287077117,0.03500359520402955,0.030068106784813364,0.01000122552299559,0.00500010710244779,0.01000200819664575,0,0.005000491766928885,0.003665747248190607,0.0038163792466336384,0.00018156013083422292,0.006064662738417125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.004606627292584498,0.0015797935391568664,0,0,0.0053780046949534945,0.017077405333330936,0.005000078463494155,0.021956733810551844,0.01000126249498217,0.026147113314850447,0.0672079829495433,0.08159334303681665,0.12416824755793546,0.11225152909703837,0.17829604997452433,0.1588257505525454,0.17992761221387396,0.23144600491167863,0.22260048184067546,0.2271474386801598,0.1871107516254596,0.19181198129227633,0.1818275360598245,0.13682783190366735,0.10577039158765524,0.126230939162026,0.075685217484445,0.0700160558599546,0.05000842593816465,0.03612282418914315,0,0,0,0.010000840142330316,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0014144161610784895,0.0027231727083049445,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005001697696839985,0.005000300392736299,0.006422270888905256,0.004245514282374551,0.016137075272131342,0.02396324114401155,0.0750059013491655,0.078708893823799,0.1000143885916419,0.10015284440336965,0.14912536651831684,0.2119354483341257,0.23262721660888477,0.2505794378367286,0.22001099246505937,0.27273618492667717,0.1930358911538251,0.16229805834723965,0.19314949087769945,0.13757190340442854,0.12787195803267676,0.1215162975750759,0.07764033854658539,0.0908328745357602,0.03500459711762897,0.034211395987203554,0.015794700679479603,0.01500208603180848,0,0.010000595239483864,0,0.005000583565072145,0,0,0,0,0,0,0,0,0,0,0,0,0.004783712464121251,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005000920933103605,0,0,0.005001618048027225,0.005002616108528325,0.00500026015502648,0.02665550598320912,0.008333725356552735,0.04833237711813098,0.055317126161114595,0.0903498069739572,0.07893654408189085,0.1620138875621303,0.129084581101719,0.213976838478447,0.2091977456152059,0.2160315092858958,0.20996389006551208,0.25496542882133494,0.19232498369321624,0.22294333811340525,0.219397385943493,0.13753071636619404,0.1603162498724057,0.09506913334057644,0.0723557476159123,0.0590963385152113,0.035003048107496854,0.025653645911532023,0.015004476148644369,0.005795166481992675,0.010455313712567796,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0004896209726463356,0.006262753713343735,0,0.028243046340057414,0.004221645556792214,0.01187715221074166,0.02329979458006395,0.04899341936581514,0.04065575662062551,0.07001396023514381,0.08475730302276195,0.165704547721529,0.1208857673052037,0.18502810633567102,0.1904386701541779,0.2769641081849362,0.24572325502509562,0.24338980662487933,0.24464130802443265,0.2638158321794138,0.24780206314648398,0.19399424165562354,0.1605919988949006,0.14035302208691175,0.11857101401614821,0.069202826286088,0.06026431805716575,0.0639983457915703,0.021014392672397738,0.025675189100901878,0.01203667082028362,0.0045147136974675005,0,0,0.00500005660662288,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0051340767616875095,0,0,0.00522238176821125,0.00500014521284337,0.005000095450625205,0,0,0.021639907860439914,0.02337224933505205,0.010002098446277686,0.06079519729368066,0.0703027620972032,0.09016621950782931,0.09584142860871775,0.15810339675402535,0.1583328491398561,0.21585924428784106,0.2713636871371979,0.27294698399651107,0.28826010085069476,0.33556866596385815,0.23947293523962448,0.23103568779235265,0.24658991851308018,0.21268626492834525,0.1265176837005518,0.16522788405094196,0.0910416692031161,0.05187938241824595,0.064018492798879,0.03650269121672201,0.035608458253505025,0.015001670099947316,0.0051435748988057,0,0,0.0050006973139480005,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0009655128890777901,0.006586475044330615,0.0003400437813709504,0,0,0,0,0,0.015001069684787094,0.010001204333827594,0.01000032930303119,0.04001243606078475,0.055006389843284896,0.07009139676055395,0.1001296311163116,0.09960027371944274,0.23707205955809685,0.21950306190203228,0.2121685304971661,0.2794165583738883,0.26501780198881164,0.22420846189477175,0.2400087036657748,0.32139044106236825,0.28922576776369646,0.19004197352126426,0.17657951554841825,0.18855541776474094,0.09506053420992745,0.105497160408945,0.07154630459971326,0.098056091738253,0.0506409042219427,0.015001170705804529,0.005004107956218791,0.010000631387282086,0,0.005021858919971225,0.005001406854789735,0,0,0.0028796213781539207,0.004591680173108744,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005546433738894635,0.006378096045774315,0.016593351462188512,0.020693222617945692,0,0.051228980539939906,0.03754373424291114,0.11459563150709384,0.11979933335209739,0.11720110413185314,0.16692200323249987,0.2018704113804582,0.2165094394391429,0.23075272771865002,0.2514986140157255,0.3607155144730544,0.31619024402011875,0.2839504074619249,0.22397238180977416,0.2369748932845712,0.1734288289951749,0.13705258013229624,0.14886673407466652,0.09874376925601695,0.0807640942083385,0.0583920134217665,0.04509925639235707,0.015000276367522486,0.010000730189811926,0.00500024346580866,0.005001938410457275,0,0.01012827907533696,0.00676105445975277,0,0.00500319111885043,0.000974417725592442,0.005533644886909959,0.003155486090787001,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0050007805426217095,0.005000069234525175,0,0,0.005000418993964995,0.0010169699551815276,0.031498981610892256,0.028539311529500164,0.020816188762302183,0.045011013646397945,0.07001203049476375,0.12450417890611279,0.07609005526297645,0.21642797518068,0.2507575689463578,0.20801959688522462,0.26157378525443087,0.32466093792167333,0.33548613978836844,0.27881515067105545,0.3024493146223261,0.22929671001115776,0.2007205906712669,0.18641249681848315,0.16015651217455745,0.13076539357187225,0.1215204265008812,0.08665751197831466,0.0500072494523937,0.025003229220440685,0.020008908425727508,0.010003157531581375,0.004050824983461736,0,0,0,0.005001132484537105,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500150495892899,0,0.010000228126590039,0.005001283078224895,0.005001193301281565,0.01000293315247691,0.030006361576262623,0.05858973583890226,0.09100246960588054,0.0950147257767083,0.09019820875334156,0.17070298964940508,0.175050698301981,0.2122064447578014,0.22708341300620521,0.295874999540158,0.3098559950462349,0.36559930313607075,0.34254957890241916,0.2487669642017865,0.29547395428152606,0.1826259627084208,0.15955799294708553,0.1102653093171755,0.1287050919180041,0.07279901408220135,0.0538855260619324,0.030334945080582362,0.060781457201715,0.00609882093726773,0.025954051957868148,0.005000010538151225,0,0,0.0033404969310373064,0.0036554634851883065,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0100150694307813,0.005001455719460145,0.00500155469716803,0.00500025883979841,0.019804626342906806,0.03172484050577056,0.02500212380902866,0.050005919379264296,0.100519789999493,0.12006566979343991,0.12507209653086454,0.1611102643706341,0.20325262052355425,0.2954353490628379,0.22939034932837676,0.3630539780801051,0.33581388215056385,0.2926655114337251,0.3199937079474131,0.26600773152900753,0.2135170876943131,0.23340876516355616,0.18997554029207828,0.157319057277471,0.0950219709045026,0.11236402282945285,0.032368983874165126,0.03072083396621327,0.022788897940478375,0.028815987840488486,0.011192094618045146,0.0013177955966358094,0,0.00029633799098428837,0.005000167025296475,0,0.00500002437961459,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00768061400143671,0.004088404052555477,0.007827421466118865,0.010005265413078366,0.01527668711673227,0.00985172250888428,0.02506812470844835,0.0650111954320301,0.0914465142360149,0.1500330742895909,0.0980922634561681,0.11621342672259545,0.23830891569304608,0.17884567357589873,0.28147789825620795,0.3847692684928817,0.2755515336411441,0.34696107205575044,0.2404778094587194,0.2890286293761342,0.2617966610960714,0.18442774550982735,0.13535735880043606,0.1689313412679204,0.12958644038560815,0.04537541008514386,0.06301607517405265,0.027098254864702232,0.03787114967680784,0.021320773329149046,0,0,0.0050002135302868,0,0,0,0.005000620296098015,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0011583610639568625,0.00009387834072163234,0.012375578794798935,0.033200399669120584,0.01000256982942015,0.01524874100992234,0.05444286571307194,0.05606452871137364,0.060480524773334855,0.11003517919712574,0.14543907109193543,0.1469273359859798,0.15001907251471538,0.19265448206249225,0.33086580812895555,0.3001803405725798,0.3756188665250809,0.34394977336437366,0.2660979871496857,0.2959728971083508,0.2259654647228788,0.1872512004406238,0.1730707299120911,0.15389597033792823,0.13537268518122622,0.07001119217181526,0.0810447243347597,0.03500561306510133,0.025002212874848186,0.015000950912004214,0.005001068396832675,0.005003291812312155,0.005000041152342335,0.00500005663136399,0.005000326799330135,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0013453814142460724,0.005589686680534855,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.011563997324680355,0.010000106130244475,0,0.005000148704765905,0.012117763323345994,0.041477176125142054,0.045006259649394094,0.06500443875625725,0.1400217968789289,0.1130821264388144,0.14552125203011285,0.18300816959154836,0.183941086080894,0.23339917516940328,0.26330044945117076,0.2591112713125175,0.28321744437720753,0.3052315986108944,0.2761439070873972,0.2551597435208745,0.1806451686452796,0.11983345503911226,0.13001987594225395,0.1208705062363814,0.0682444371368653,0.04897697379462139,0.04528495884707813,0.020001793910772534,0.01500329305086136,0.01000184665657782,0.00500003396640668,0.00693954543297437,0.0061194278727524695,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00004152369380650467,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005000008141814996,0.005000362472257155,0.00500103557953446,0.008687918737071471,0.00812856662838715,0.018817698629484805,0.025020393419231755,0.08003069758951165,0.07514824293441595,0.07523180458988445,0.18145156571567983,0.16554515806587955,0.21234635342596989,0.21678006272552253,0.257031397682038,0.23533394454409495,0.273242404793911,0.32014211286903355,0.27507830932208677,0.23505143157487224,0.25227664488565454,0.1655722511725248,0.094557447863084,0.09287235938615356,0.06958130421375125,0.057737778363745745,0.020001993100474742,0.00500115663102462,0.020002425883853245,0,0.00500151983372028,0,0,0,0,0,0.002475112208864102,0.0018171931897431523,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005000732374919385,0,0.03489268667910528,0.01196047763673858,0.01118697984696182,0.03500531963090768,0.0902112217025336,0.07845070927457726,0.13001970858205125,0.1556762344782471,0.21543814811571846,0.20491816656497955,0.1558868645390377,0.2565782014942092,0.34667993136567565,0.24518776388573937,0.30147972274554685,0.2555481366576719,0.17585527815839214,0.19799593890557932,0.0984000004680413,0.1254763961720525,0.12461412879017014,0.050454199688597746,0.07803351506233405,0.05287494129859025,0.03515640830807833,0.0100068955026672,0.010000930378505041,0.005000673920617425,0,0,0.00500041820271532,0,0,0,0.003446747307470279,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000021172803852629297,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0276465789152221,0.010001596771482664,0.033783595354671084,0.0613938169112604,0.05810425018982005,0.06722729566571896,0.11001619131118041,0.16543979221666597,0.21796477617557986,0.2235790835037916,0.23008187102950584,0.29963676576641407,0.2565389437163755,0.2243046506257699,0.277189159312294,0.26279712777924574,0.19757882257937853,0.2293985676132894,0.21816966430293724,0.1318300317818667,0.09001488449916235,0.07521090393090035,0.03993972166744607,0.035005095339013755,0.020001970191211794,0.00500012015054946,0,0.00500013468047341,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0004620870234735351,0.00578235776492658,0.0016719154297024617,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500098525168227,0.005362529233929009,0.0006377240356510456,0,0.00026066094098292685,0.011535570040102824,0.025001883074019765,0.010002297809864256,0.020003709591338376,0.0510947939371092,0.077689405578847,0.07299857070630815,0.1140023258329225,0.1484771200077118,0.1501426997950264,0.21466733930428777,0.19800704063428626,0.255463064081606,0.21488566499937692,0.2789630515094886,0.26865224931683035,0.2343467787050449,0.1364723495879882,0.16082064757004555,0.12477835022855462,0.10240653424777449,0.11990025233793335,0.087203400109329,0.044382286513348294,0.015015077117897535,0.0500299808989589,0.02000413980959898,0.005000173362245695,0.005000922014448745,0,0,0,0,0.00611818641829429,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0025940472612650217,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0001953295447598137,0.00596889213909961,0,0,0,0.005000176545126425,0,0.00500029009714397,0.020002608039808082,0.01500226785248686,0.017268734450579484,0.056596112712887454,0.031922480391835775,0.06010453349821335,0.13338063765782324,0.18002561942906606,0.16194761898292934,0.22242703299698324,0.2111691368059673,0.17577766635206005,0.180998573529205,0.1983866213050314,0.16363646081719288,0.1357295602333148,0.11717273648629685,0.14027455875843203,0.1352702283684378,0.0822004583324407,0.05220627012233675,0.0701822939299416,0.0140603552254467,0.030946102466042083,0.01000019923246226,0.005000314980647935,0.005000088389031665,0,0.00500060976671759,0.0050007192359694695,0,0.0008366422984016886,0,0,0,0,0,0,0,0,0,0,0,0,0.00003712215234549414,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0050002489118001646,0.009915036637404031,0,0.010001718293396014,0.0050000789398140545,0.025045314118457118,0.040003971646291006,0.03866046303859108,0.0500170521643466,0.04000773053439637,0.08001540826085535,0.06854618940038494,0.1401428138663789,0.15055344363843218,0.15549324571842585,0.23502863191177503,0.18621180189639644,0.16003635816145842,0.20190766635984636,0.17048393705827963,0.16636287977190195,0.14325433297653264,0.13313718514817105,0.0932222724868137,0.030003083214923832,0.05003039280656,0.03500681384865139,0.03000582018889861,0.015002721324512146,0.005000462451258371,0,0.005000879581707935,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0010314692962942395,0.006663909494782256,0,0.00500074224994941,0.00008638074093427614,0.010003574855233595,0.020001835138021867,0.00500001134024073,0.010000148588446934,0.025006224968765072,0.020001649368057955,0.04484697815448662,0.0951674725780485,0.1000343116422666,0.09416012996082015,0.1224621967240076,0.1755231853682704,0.23220883028921843,0.14543962621102288,0.2102683661051054,0.19236467016880457,0.20592632806221536,0.1843479854106389,0.15204307960811955,0.1309842402832733,0.1212040222845053,0.10001937927054824,0.04500675190114761,0.045004609082883916,0.050013669265924196,0.020003640596968304,0.015001743333056271,0.020195236844127516,0.005096495063344305,0.01000246081474355,0.0050001880218775345,0,0,0.0050014724044182305,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500003418741248,0.005001265704805835,0.005000240641705415,0,0.00500037675567913,0.00500082673106136,0.025003341127705848,0.020001564846363715,0.05047050565861,0.07158694950690175,0.03504324068915813,0.092002926485324,0.11077358957032245,0.10553662270474369,0.1553690040057873,0.14132770414063972,0.15182907026530978,0.17715499957003555,0.2191625242269462,0.1350771894351083,0.11927841841203185,0.12727637845374254,0.10508515576779505,0.0943933055492472,0.07425552299684085,0.0700251230425423,0.0200028495247113,0.025005053486122402,0.03137515206822545,0.020001434472528293,0.005001058845726705,0,0,0,0.00500005542229569,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500036558268963,0,0,0,0.025003196508244663,0.020000894604413098,0.030003922992761386,0.035013260652466315,0.06462622409767875,0.0750149862455199,0.06301105867657986,0.11387780762432305,0.16030975606776707,0.1517198757358503,0.14267800992504823,0.18060450043144982,0.16400399672442295,0.12501646129387334,0.1091480076029118,0.10003622618248516,0.0681906138438127,0.07729512633016675,0.055137860623876746,0.0625681537539701,0.01000026492624734,0.03251682244516235,0.01683609541977163,0.001785089964474115,0,0.005000791750802025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.01985759949296175,0.02508394447130187,0.05992560168149115,0.018769757859179566,0.0500122107240498,0.07028676334559089,0.0723710450944062,0.08504879594188164,0.09501374558470614,0.11190961128871729,0.17501221575444223,0.13209050622384091,0.10873637261759479,0.12088400452847584,0.11201195121963385,0.06468469020748435,0.07000635909214074,0.0544174514145785,0.03214464926251458,0.03463538653451267,0.02292656378116515,0.032284724917384135,0.010000494939637509,0.00652404592791208,0.010000247623083503,0.006397437664503866,0.00019080229321152703,0,0,0,0,0,0,0,0,0,0,0,0,0.0032385273269409636,0.0036166417173830873,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00605459942354964,0,0,0.005000482178312594,0,0.010001172192061675,0,0.012116639985470346,0.02000744277056693,0.030004093644510475,0.020241191913502855,0.02500436435424868,0.0550361565504704,0.08577136029334866,0.07614849034042845,0.11595268285911166,0.1327919516445632,0.11260083609112793,0.10482521606153254,0.0783604361915643,0.0832528504976239,0.07802915450797315,0.0575574837040047,0.04162995386632514,0.01874536372848065,0.02917360057257244,0.020002583230408127,0.025002465512418668,0.005002066798233215,0.01000014646957245,0.01133751167574018,0.010469884104435815,0,0.001433862085300084,0,0.003698201712139326,0.0026916868961860746,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.010000452717291535,0.020003301776928155,0.01000682550099954,0.00500048761395676,0.05094755531875925,0.05951418246403394,0.027396964736219002,0.037110622210930345,0.0656436003581832,0.08894194685255045,0.10330540417696012,0.0883809457169761,0.09273697219080106,0.08369285548355325,0.08109348206456975,0.0713407281298915,0.09769240536383215,0.0790269914883686,0.056904273947956156,0.0581197871511796,0.040817367922829105,0.010001818305695756,0.020001158345723868,0.01000226967500292,0.005001343765783755,0,0.010919703362801096,0,0.010001168045999655,0,0.00500042059998167,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00687890569164229,0,0,0,0.045006452398167265,0.005720059716100095,0.015001237202439174,0.03500604600732523,0.02500411265604585,0.09001490213591255,0.045004661412082245,0.0600135494649414,0.0941714557877795,0.07103227237682269,0.09500874784773776,0.07086321402174099,0.11501603472453781,0.061243475750446245,0.03933263995727539,0.03500872402793752,0.04000659712466731,0.030018809546355715,0.02429652621656076,0.02000300507546257,0.0050000540241998005,0,0.01000091565937304,0.01677273024646305,0.00441575179316316,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500020112882384,0,0.01000071439740891,0.010000849494599125,0.007743403843477895,0.017932106305359765,0.025128282205143744,0.020007120534380276,0.047164353363486136,0.050006705773953754,0.04677926896661892,0.06001320161009345,0.06285976663186206,0.0535734596399632,0.046125555828903285,0.058891849713061904,0.05585678229957469,0.0500090206849203,0.03500573047827157,0.04001097850056249,0.0350020365046328,0.015001737036660856,0.010000624505973105,0,0.025003883637989652,0.0050026474079995255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005000541284687525,0,0.00500022099860445,0.010002102146223425,0.01000097610960202,0.04000305982099061,0.035002591531474836,0.01712861690990877,0.030004423462407795,0.028228383164501387,0.040005613655495854,0.08099472905748731,0.05966440998277314,0.07133030375208214,0.0500075056948955,0.06001042489989965,0.03065206850319658,0.04435689412006926,0.0550045813561788,0.02500330239634856,0.02000451697122341,0.010002140821872105,0.015006735430618215,0.005000866251084035,0,0.005002482999205685,0.005012657379741275,0.011544498030749546,0,0.005000099812269505,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005000209114099745,0,0,0.01000033959980094,0.015007186282132455,0.015002339227038326,0.02000261291893028,0.01500566461173135,0.018585536183588557,0.027139010395871077,0.015001126471560645,0.05540898530362125,0.03450579976842648,0.06088665295316615,0.07058184172334425,0.03500221921775194,0.025006582264319805,0.02500305293459237,0.06790373844612285,0.012119041623040356,0.01645350611924933,0.025191553764973815,0.025002958962616936,0.015000632530127076,0.005000393741179865,0,0,0,0.009110627336759021,0.0004513313612582043,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000314096179827696,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.010001481607198331,0.0037090433779886295,0.01639921632816473,0.0100004951786227,0,0.015001973211668181,0.01500575925813339,0.03874382444557526,0.025066755468145983,0.03508617297053296,0.025005548252044037,0.020002453644969567,0.030020650075377516,0.029649655625595524,0.00875572809849892,0.006245603239665905,0.030003888851153983,0.023552858456081797,0.015002874505024539,0,0,0.00579317375554172,0.005000157184207845,0,0.002973032443592427,0.0020277778859087315,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00511923847452863,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.002399024498611843,0.005409231450023325,0,0,0.00500037452013754,0,0,0.005000021332200395,0.005000696439891776,0.010000467028877899,0.00890744289731074,0.0010949171343173395,0.010001691680724706,0.020003812252245193,0.020002768032516743,0.010003889055599144,0.02627012385370039,0.005137567186804015,0.030004193396228493,0.03000361461256115,0.0236629111548161,0.03503487034813662,0.026596330895050486,0.025003986249159255,0.015000464489546951,0.010000800873948884,0.02000101883083514,0.020004399460555326,0.020017171057217523,0,0.00022794243948941352,0.005000210074285665,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.002213460361072559,0.002733129068284964,0,0,0,0,0,0,0,0.00500072544149316,0,0,0.010002410014351091,0,0,0.015002730616236493,0,0.019299955603009115,0.015001399701088354,0.007661696449364111,0.01000034118932674,0.02500558137266121,0.021814355799754152,0.025001496423616917,0.026001418973757445,0.01969642693610119,0.0250023004523345,0.005000602121317945,0.01000193027426445,0.00500002011806304,0,0,0,0,0,0.005001061557550575,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0009428915315695409,0,0,0,0,0,0,0,0,0.0050006780582231005,0,0,0.005000385183875305,0.005003612021054385,0.00500172988696909,0.010048690913026565,0.010001610855802685,0.011659954427613386,0.015002193572694071,0.01500200298700515,0.020001071140565735,0.020005370549264795,0.02006437944979599,0.025036206168938712,0.010001296920657815,0.02500184701801019,0.01500164304354151,0.005000510112345181,0.010001144589464715,0,0.010001508504071834,0,0.004089761881238883,0.0050000184425255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500074733928253,0.00500108419344806,0,0.005002042655967169,0.01000136170560869,0.0150053526130892,0.010001924938252036,0.005000218303171836,0.00500015606975156,0.005000357693798785,0.00520215667308622,0.015001248649463804,0.015004271729909004,0.020002033940776577,0.01500431716350089,0.005131208770849259,0.010001125521937625,0,0.010001049323571981,0.005000328450161665,0.0009103756384105875,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0022553315499095907,0.003769463625705987,0,0,0,0,0,0,0.01000050239134185,0,0,0.025652008059203837,0.005001098001832321,0.01000243731694962,0.0025943340080513996,0.01000322918246802,0.025007194138535933,0.015004173763498534,0.010002946508906766,0,0.010000873433957889,0.005000056815425295,0.005000006383578325,0.00698461591748635,0.003018641531172952,0,0.01000076741383628,0.005000145003429555,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000012130295625439361,0.00030893897383585964,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0007300960314089065,0,0,0,0,0,0,0,0,0.01500161339523015,0.01500411604487073,0.01000249219532472,0.010001587111173821,0.010000748604865871,0.012407010439725315,0.01000119935993461,0.015000571342118454,0.010002628773027425,0.010000857365810075,0.00500092676126556,0.005000522584881535,0.005000529527422986,0.0050001323134655,0.00500017716189662,0.007263946035744965,0,0.007958601214826664,0.00500014084592255,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500027478992704,0.00500069985791657,0.00500038971516555,0.005000021709000965,0,0.005000181189434615,0.005000051939131245,0.00500079999456628,0,0.0050005654699303,0.00500625267128494,0,0.007753390301666634,0.00500094199640265,0.010199605623552254,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.01500195880357029,0,0.010000937165942175,0.004522895719144331,0.00047813233344642654,0,0.023083649976699955,0.010000442326260205,0,0.0050004196659167,0.005013166145999795,0.005000297112542105,0,0.005192633378700235,0,0,0,0,0,0,0,0.001805274124580685,0.005208192773927631,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00510800536708641,0,0.000013998990438367606,0,0.00500010665043651,0,0,0,0.015000600323050884,0.01000061928994663,0.0050005565632676155,0,0,0,0.005002034318625925,0.011920372750259525,0,0,0,0,0,0,0.00519061612940843,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00993599874843963,0.0007089770468241249,0,0,0.00500025722474828,0.005000730289148415,0.005002317706641995,0.01000030468583097,0.00500011871000985,0,0,0,0,0,0,0.00500027557641264,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00001053052223328146,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005000901064541575,0,0,0,0,0,0,0,0.010110303654684665,0,0,0,0,0.00500045001182772,0,0,0,0,0.00500008740176081,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500057543884734,0,0.005000073998809905,0,0,0.00500032550858968,0,0.010000787990480865,0,0.00500069345797991,0,0,0.0050010667200045145,0,0,0.005000378985282165,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500191099117545,0,0,0,0,0,0,0,0,0.005000444296260185,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000029911979452457062,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0028948343031176657,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500030968540687,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0024761486353037975,0.000932854647131575,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005000116421578936,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00528812983581436,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005001517498662195,0,0,0,0,0,0,0,0,0,0,0,0,0.0017229195101092143,0.000660273226685855,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00500083858346533,0,0,0,0,0,0,0,0.00500122040087845,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2.293917370404761e-10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.005000179805693714,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0050012173739147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.000695592721474378,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0055293026548566895,0.0002686224792217635,0,0.0000552645368001781,0,0,0,0.0050024797553277454,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.00571333762433279,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0024404711570790772,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] + } + }] + }] +} \ No newline at end of file From 10a2227bae0afc96ff3706b8e31a6f04e0cc07b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81uaksz=20Kwinta?= Date: Sun, 7 Dec 2025 23:53:40 +0100 Subject: [PATCH 04/13] Rework vibecoding --- src/App.tsx | 2 + src/Geant4Worker/Geant4DatasetCacheService.ts | 70 +---- .../Geant4DatasetDownloadManager.ts | 136 ---------- src/Geant4Worker/Geant4DatasetManager.ts | 241 ++++++++++++++++++ src/Geant4Worker/Geant4WorkerCallbacks.ts | 12 +- src/Geant4Worker/useDatasetCacheStatus.ts | 90 ------- src/WrapperApp/WrapperApp.tsx | 10 - .../Simulation/Geant4DatasetDownload.tsx | 130 ++++------ .../Modal/DatasetsFullInfoModal.tsx | 14 +- .../Simulation/RunSimulationForm.tsx | 6 +- .../Simulation/RunSimulationPanel.tsx | 8 +- src/services/Geant4DatasetContextProvider.tsx | 17 ++ 12 files changed, 341 insertions(+), 395 deletions(-) delete mode 100644 src/Geant4Worker/Geant4DatasetDownloadManager.ts create mode 100644 src/Geant4Worker/Geant4DatasetManager.ts delete mode 100644 src/Geant4Worker/useDatasetCacheStatus.ts create mode 100644 src/services/Geant4DatasetContextProvider.tsx diff --git a/src/App.tsx b/src/App.tsx index 5ef027692..6b6129c1b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -9,6 +9,7 @@ import { ConfigProvider } from './config/ConfigService'; import { PythonConverterService } from './PythonConverter/PythonConverterService'; import { Auth } from './services/AuthService'; import { DialogProvider } from './services/DialogService'; +import { Geant4DatasetContextProvider } from './services/Geant4DatasetContextProvider'; import { Geant4LocalWorkerSimulationContextProvider } from './services/Geant4LocalWorkerSimulationContextProvider'; import { KeycloakAuth } from './services/KeycloakAuthService'; import { Loader } from './services/LoaderService'; @@ -102,6 +103,7 @@ function App() { , , , + , , , , diff --git a/src/Geant4Worker/Geant4DatasetCacheService.ts b/src/Geant4Worker/Geant4DatasetCacheService.ts index 0e9819614..acbd93c3f 100644 --- a/src/Geant4Worker/Geant4DatasetCacheService.ts +++ b/src/Geant4Worker/Geant4DatasetCacheService.ts @@ -12,9 +12,7 @@ * We detect cached datasets by matching the .data file suffix in IndexedDB keys. */ -// Dataset configurations with file identifiers (the .data filename used in cache keys) -// These match the actual dataset files from the Geant4 data packages -const DATASET_CONFIGS = [ +export const GEANT4_DATASETS = [ { name: 'G4EMLOW8.6.1', dataFile: 'G4EMLOW8.6.1.data', approximateSizeMB: 580 }, { name: 'G4ENSDFSTATE3.0', dataFile: 'G4ENSDFSTATE3.0.data', approximateSizeMB: 0.1 }, { name: 'G4NDL4.7.1', dataFile: 'G4NDL4.7.1.data', approximateSizeMB: 583 }, @@ -23,14 +21,6 @@ const DATASET_CONFIGS = [ { name: 'PhotonEvaporation6.1', dataFile: 'PhotonEvaporation6.1.data', approximateSizeMB: 47 } ] as const; -export const GEANT4_DATASETS = DATASET_CONFIGS.map(config => ({ - name: config.name, - dataFile: config.dataFile, - approximateSizeMB: config.approximateSizeMB -})); - -console.log('[CacheService] Initialized GEANT4_DATASETS:', GEANT4_DATASETS); - export const TOTAL_DATASET_SIZE_MB = GEANT4_DATASETS.reduce( (sum, ds) => sum + ds.approximateSizeMB, 0 @@ -49,7 +39,6 @@ export interface DatasetCacheStatus { export interface CacheStatusResult { datasets: DatasetCacheStatus[]; - allCached: boolean; cachedCount: number; totalCount: number; estimatedCachedSizeMB: number; @@ -65,20 +54,15 @@ export interface StorageEstimate { /** * Opens the IndexedDB database used by Emscripten for caching */ -async function openDatabase(): Promise { - if (typeof indexedDB === 'undefined') { - console.warn('[CacheService] IndexedDB is not available'); - - return null; - } - +async function openDatabase(): Promise { return new Promise((resolve, reject) => { - console.log(`[CacheService] Opening IndexedDB database: ${DB_NAME}`); + if (typeof indexedDB === 'undefined') { + reject('IndexedDB is not supported in this environment'); + } + const openRequest = indexedDB.open(DB_NAME, DB_VERSION); openRequest.onupgradeneeded = event => { - // Database doesn't exist yet or needs upgrade - this means no cache - console.log('[CacheService] Database upgrade needed - creating stores'); const db = (event.target as IDBOpenDBRequest).result; // Create stores if they don't exist (they won't have data anyway) @@ -93,13 +77,11 @@ async function openDatabase(): Promise { openRequest.onsuccess = event => { const db = (event.target as IDBOpenDBRequest).result; - console.log(`[CacheService] Database opened successfully. Object stores: ${Array.from(db.objectStoreNames).join(', ')}`); resolve(db); }; openRequest.onerror = () => { - console.warn('[CacheService] Failed to open IndexedDB:', openRequest.error); - resolve(null); + reject('Failed to open IndexedDB database'); }; }); } @@ -111,7 +93,6 @@ async function openDatabase(): Promise { async function checkDatasetCachedByDataFile( db: IDBDatabase, dataFile: string, - datasetName: string, allMetadataKeys: string[] ): Promise { // Find any key that ends with our dataFile (after removing 'metadata/' prefix) @@ -126,23 +107,13 @@ async function checkDatasetCachedByDataFile( }); if (matchingKey) { - console.log(`[CacheService] Dataset ${datasetName}: Found matching key "${matchingKey}"`); - // Verify it has valid metadata const result = await getMetadataValue(db, matchingKey); if (result && result.uuid) { - console.log( - `[CacheService] Dataset ${datasetName}: CACHED (uuid: ${result.uuid}, chunkCount: ${result.chunkCount})` - ); - return true; } } - console.log( - `[CacheService] Dataset ${datasetName}: NOT CACHED (no matching key for dataFile "${dataFile}")` - ); - return false; } @@ -184,16 +155,13 @@ async function listAllMetadataKeys(db: IDBDatabase): Promise { getAllKeysRequest.onsuccess = () => { const keys = getAllKeysRequest.result as string[]; - console.log(`[CacheService] All METADATA keys (${keys.length}):`, keys); resolve(keys); }; getAllKeysRequest.onerror = () => { - console.warn('[CacheService] Error listing metadata keys:', getAllKeysRequest.error); resolve([]); }; } catch (error) { - console.warn('[CacheService] Exception listing metadata keys:', error); resolve([]); } }); @@ -203,19 +171,15 @@ async function listAllMetadataKeys(db: IDBDatabase): Promise { * Checks the cache status of all Geant4 datasets */ export async function checkAllDatasetsCacheStatus(): Promise { - console.log('[CacheService] Starting cache status check...'); const db = await openDatabase(); if (!db) { - console.warn('[CacheService] Database not available, returning all uncached'); - return { datasets: GEANT4_DATASETS.map(ds => ({ name: ds.name, isCached: false, approximateSizeMB: ds.approximateSizeMB })), - allCached: false, cachedCount: 0, totalCount: GEANT4_DATASETS.length, estimatedCachedSizeMB: 0, @@ -226,16 +190,10 @@ export async function checkAllDatasetsCacheStatus(): Promise try { // First, list all metadata keys for debugging const allKeys = await listAllMetadataKeys(db); - console.log('[CacheService] Found metadata keys:', allKeys); const datasetStatuses: DatasetCacheStatus[] = await Promise.all( GEANT4_DATASETS.map(async ds => { - const isCached = await checkDatasetCachedByDataFile( - db, - ds.dataFile, - ds.name, - allKeys - ); + const isCached = await checkDatasetCachedByDataFile(db, ds.dataFile, allKeys); return { name: ds.name, @@ -249,15 +207,15 @@ export async function checkAllDatasetsCacheStatus(): Promise const result: CacheStatusResult = { datasets: datasetStatuses, - allCached: cachedDatasets.length === GEANT4_DATASETS.length, cachedCount: cachedDatasets.length, totalCount: GEANT4_DATASETS.length, - estimatedCachedSizeMB: cachedDatasets.reduce((sum, ds) => sum + ds.approximateSizeMB, 0), + estimatedCachedSizeMB: cachedDatasets.reduce( + (sum, ds) => sum + ds.approximateSizeMB, + 0 + ), estimatedTotalSizeMB: TOTAL_DATASET_SIZE_MB }; - console.log('[CacheService] Cache status result:', result); - return result; } finally { db.close(); @@ -293,9 +251,7 @@ export async function getStorageEstimate(): Promise { export async function clearDatasetCache(): Promise { return new Promise(resolve => { if (typeof indexedDB === 'undefined') { - resolve(false); - - return; + return resolve(false); } const deleteRequest = indexedDB.deleteDatabase(DB_NAME); diff --git a/src/Geant4Worker/Geant4DatasetDownloadManager.ts b/src/Geant4Worker/Geant4DatasetDownloadManager.ts deleted file mode 100644 index f8992242f..000000000 --- a/src/Geant4Worker/Geant4DatasetDownloadManager.ts +++ /dev/null @@ -1,136 +0,0 @@ -// Additional credits: -// - @kmichalik - -import { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from 'react'; - -import Geant4Worker from './Geant4Worker'; - -export enum DownloadManagerStatus { - IDLE, - WORKING, - FINISHED, - ERROR -} - -export enum DatasetDownloadStatus { - IDLE, - DOWNLOADING, - PROCESSING, - DONE -} - -const statusTypeMap: Record = { - downloading: DatasetDownloadStatus.DOWNLOADING, - preparing: DatasetDownloadStatus.PROCESSING, - done: DatasetDownloadStatus.DONE -}; - -export interface DatasetStatus { - name: string; - status: DatasetDownloadStatus; - done?: number; - total?: number; -} - -async function fetchProgress( - worker: Geant4Worker, - setDatasetStates: Dispatch>> -) { - if (!worker.getIsInitialized()) return; - - const progress = await worker.pollDatasetProgress(); - - if (progress) { - const newDatasetStates: Record = {}; - - for (const [datasetName, datasetProgress] of Object.entries(progress)) { - let status = statusTypeMap[datasetProgress.stage] ?? DatasetDownloadStatus.IDLE; - - newDatasetStates[datasetName] = { - name: datasetName, - status, - done: Math.floor(datasetProgress.progress * 100), - total: 100 - }; - } - - setDatasetStates(prev => ({ ...prev, ...newDatasetStates })); - } -} - -type StartDownloadArgs = { - worker: Geant4Worker; - managerState: DownloadManagerStatus; - setManagerState: Dispatch>; - setDatasetStates: Dispatch>>; - setIdle: Dispatch>; -}; - -function startDownload({ - worker, - managerState, - setManagerState, - setDatasetStates, - setIdle -}: StartDownloadArgs) { - if (managerState !== DownloadManagerStatus.IDLE || !worker.getIsInitialized()) { - return; - } - - const loadDepsPromise = worker.loadDeps(); - - const interval = setInterval(async () => { - await fetchProgress(worker, setDatasetStates); - }, 500); - - loadDepsPromise - .then(async () => { - clearInterval(interval); - - await fetchProgress(worker, setDatasetStates); - - setManagerState(DownloadManagerStatus.FINISHED); - worker.destroy(); - }) - .catch(error => { - console.error('Dataset download error:', error); - setManagerState(DownloadManagerStatus.ERROR); - clearInterval(interval); - }); - setManagerState(DownloadManagerStatus.WORKING); - setIdle(false); -} - -export function useDatasetDownloadManager() { - const [managerState, setManagerState] = useState( - DownloadManagerStatus.IDLE - ); - const [datasetStates, setDatasetStates] = useState>({}); - const [idle, setIdle] = useState(false); - const [worker] = useState(new Geant4Worker()); - const initCalledRef = useRef(false); - - useEffect(() => { - if (initCalledRef.current) return; - worker - .init() - .then(() => setIdle(true)) - .catch(error => { - setManagerState(DownloadManagerStatus.ERROR); - console.error('Failed to initialize Geant4 worker for dataset download:', error); - }); - initCalledRef.current = true; - }, [worker]); - - const startDownloadSimple = useCallback(() => { - if (!idle) return; - - startDownload({ worker, managerState, setManagerState, setDatasetStates, setIdle }); - }, [worker, idle, managerState]); - - return { - managerState, - datasetStates: Object.values(datasetStates), - startDownload: startDownloadSimple - }; -} diff --git a/src/Geant4Worker/Geant4DatasetManager.ts b/src/Geant4Worker/Geant4DatasetManager.ts new file mode 100644 index 000000000..00f5445fe --- /dev/null +++ b/src/Geant4Worker/Geant4DatasetManager.ts @@ -0,0 +1,241 @@ +// Additional credits: +// - @kmichalik + +import { + createContext, + Dispatch, + FC, + ReactNode, + SetStateAction, + useCallback, + useContext, + useEffect, + useRef, + useState +} from 'react'; + +import { + checkAllDatasetsCacheStatus, + clearDatasetCache, + GEANT4_DATASETS, + getStorageEstimate, + StorageEstimate, + TOTAL_DATASET_SIZE_MB +} from './Geant4DatasetCacheService'; +import Geant4Worker from './Geant4Worker'; + +export enum DownloadManagerStatus { + IDLE, + WORKING, + FINISHED, + ERROR +} + +export enum DatasetDownloadStatus { + IDLE, + DOWNLOADING, + PROCESSING, + DONE +} + +const statusTypeMap: Record = { + downloading: DatasetDownloadStatus.DOWNLOADING, + preparing: DatasetDownloadStatus.PROCESSING, + done: DatasetDownloadStatus.DONE +}; + +export interface DatasetStatus { + name: string; + status: DatasetDownloadStatus; + done?: number; + total?: number; + isCached: boolean; + totalSizeMB?: number; +} + +async function fetchProgress( + worker: Geant4Worker, + setDatasetStates: Dispatch>> +) { + if (!worker.getIsInitialized()) return; + + const progress = await worker.pollDatasetProgress(); + + if (progress) { + setDatasetStates(prev => { + const newStates: Record = { ...prev }; + + for (const [datasetName, datasetProgress] of Object.entries(progress)) { + let status = statusTypeMap[datasetProgress.stage] ?? DatasetDownloadStatus.IDLE; + + newStates[datasetName] = { + ...newStates[datasetName], + name: datasetName, + status, + done: Math.floor(datasetProgress.progress * 100), + total: 100 + }; + } + + return newStates; + }); + } +} + +type StartDownloadArgs = { + worker: Geant4Worker; + managerState: DownloadManagerStatus; + setManagerState: Dispatch>; + setDatasetStates: Dispatch>>; + setIdle: Dispatch>; +}; + +function startDownload({ + worker, + managerState, + setManagerState, + setDatasetStates, + setIdle +}: StartDownloadArgs) { + if (managerState !== DownloadManagerStatus.IDLE || !worker.getIsInitialized()) { + return; + } + + const loadDepsPromise = worker.loadDeps(); + + const interval = setInterval(async () => { + await fetchProgress(worker, setDatasetStates); + }, 500); + + loadDepsPromise + .then(async () => { + clearInterval(interval); + + await fetchProgress(worker, setDatasetStates); + + setManagerState(DownloadManagerStatus.FINISHED); + worker.destroy(); + }) + .catch(error => { + console.error('Dataset download error:', error); + setManagerState(DownloadManagerStatus.ERROR); + clearInterval(interval); + }); + setManagerState(DownloadManagerStatus.WORKING); + setIdle(false); +} + +export interface UseDatasetManagerResult { + managerState: DownloadManagerStatus; + datasetStatus: Record; + storageEstimate: StorageEstimate | null; + isLoading: boolean; + cachedCount: number; + totalCount: number; + downloadSizeNeededMB: number; + startDownload: () => void; + refresh: () => Promise; + clearCache: () => Promise; +} + +export function useDatasetManager(): UseDatasetManagerResult { + const [managerState, setManagerState] = useState( + DownloadManagerStatus.IDLE + ); + const [datasetStates, setDatasetStates] = useState>({}); + const [idle, setIdle] = useState(false); + const [worker] = useState(new Geant4Worker()); + const initCalledRef = useRef(false); + + const [storageEstimate, setStorageEstimate] = useState(null); + const [isLoading, setIsLoading] = useState(true); + const [cachedCount, setCachedCount] = useState(0); + const [totalCount, setTotalCount] = useState(0); + const [downloadSizeNeededMB, setDownloadSizeNeededMB] = useState(0); + + const refresh = useCallback(async () => { + setIsLoading(true); + + try { + const [status, storage] = await Promise.all([ + checkAllDatasetsCacheStatus(), + getStorageEstimate() + ]); + + const cachedCount = status?.cachedCount ?? 0; + const totalCount = status?.totalCount ?? 0; + const downloadSizeNeededMB = + cachedCount == totalCount + ? 0 + : TOTAL_DATASET_SIZE_MB - (status?.estimatedCachedSizeMB ?? 0); + + setCachedCount(cachedCount); + setTotalCount(totalCount); + setDownloadSizeNeededMB(downloadSizeNeededMB); + setStorageEstimate(storage); + setDatasetStates(prev => { + const newStates: Record = { ...prev }; + + for (const ds of GEANT4_DATASETS) { + newStates[ds.name] = { + name: ds.name, + status: prev[ds.name]?.status ?? DatasetDownloadStatus.IDLE, + isCached: status.datasets.find(s => s.name === ds.name)?.isCached ?? false, + totalSizeMB: ds.approximateSizeMB + }; + } + + return newStates; + }); + } catch (error) { + console.error('Failed to check dataset cache status:', error); + } finally { + setIsLoading(false); + } + }, []); + + const clearCache = useCallback(async () => { + const success = await clearDatasetCache(); + + if (success) { + await refresh(); + } + + return success; + }, [refresh]); + + useEffect(() => { + refresh(); + }, [refresh]); + + useEffect(() => { + if (initCalledRef.current) return; + worker + .init() + .then(() => setIdle(true)) + .catch(error => { + setManagerState(DownloadManagerStatus.ERROR); + console.error('Failed to initialize Geant4 worker for dataset download:', error); + }); + initCalledRef.current = true; + }, [worker]); + + const startDownloadSimple = useCallback(() => { + if (!idle) return; + + startDownload({ worker, managerState, setManagerState, setDatasetStates, setIdle }); + }, [worker, idle, managerState]); + + return { + managerState, + datasetStatus: datasetStates, + storageEstimate, + isLoading, + cachedCount, + totalCount, + downloadSizeNeededMB, + refresh, + clearCache, + startDownload: startDownloadSimple + }; +} diff --git a/src/Geant4Worker/Geant4WorkerCallbacks.ts b/src/Geant4Worker/Geant4WorkerCallbacks.ts index b6c18bba8..9ba694733 100644 --- a/src/Geant4Worker/Geant4WorkerCallbacks.ts +++ b/src/Geant4Worker/Geant4WorkerCallbacks.ts @@ -47,17 +47,17 @@ const initDatasets: Geant4WorkerCallbacksType = async args => { // This, in theory, could enable the app to run offline. try { downloadTracker.reset(); - downloadTracker.setCurrentDataset('G4ENSDFSTATE'); + downloadTracker.setCurrentDataset('G4ENSDFSTATE3.0'); await initG4ENSDFSTATE(wasmModule); - downloadTracker.setCurrentDataset('G4EMLOW'); + downloadTracker.setCurrentDataset('G4EMLOW8.6.1'); await initG4EMLOW(wasmModule); - downloadTracker.setCurrentDataset('G4NDL'); + downloadTracker.setCurrentDataset('G4NDL4.7.1'); await initG4NDL(wasmModule); - downloadTracker.setCurrentDataset('G4PARTICLEXS'); + downloadTracker.setCurrentDataset('G4PARTICLEXS4.1'); await initG4PARTICLEXS(wasmModule); - downloadTracker.setCurrentDataset('G4SAIDDATA'); + downloadTracker.setCurrentDataset('G4SAIDDATA2.0'); await initG4SAIDDATA(wasmModule); - downloadTracker.setCurrentDataset('PhotonEvaporation'); + downloadTracker.setCurrentDataset('PhotonEvaporation6.1'); await initPhotoEvaporation(wasmModule); } catch (error: unknown) { console.error('Error initializing lazy files:', (error as Error).message); diff --git a/src/Geant4Worker/useDatasetCacheStatus.ts b/src/Geant4Worker/useDatasetCacheStatus.ts deleted file mode 100644 index 527a7ceba..000000000 --- a/src/Geant4Worker/useDatasetCacheStatus.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { useCallback, useEffect, useState } from 'react'; - -import { - CacheStatusResult, - checkAllDatasetsCacheStatus, - clearDatasetCache, - getStorageEstimate, - StorageEstimate, - TOTAL_DATASET_SIZE_MB -} from './Geant4DatasetCacheService'; - -export interface UseDatasetCacheStatusResult { - /** Cache status for all datasets */ - cacheStatus: CacheStatusResult | null; - /** Browser storage estimate */ - storageEstimate: StorageEstimate | null; - /** Whether the cache status is being loaded */ - isLoading: boolean; - /** Whether all datasets are cached */ - allCached: boolean; - /** Number of cached datasets */ - cachedCount: number; - /** Total number of datasets */ - totalCount: number; - /** Estimated size in MB that would need to be downloaded */ - downloadSizeNeededMB: number; - /** Refresh the cache status */ - refresh: () => Promise; - /** Clear all cached datasets */ - clearCache: () => Promise; -} - -/** - * Hook to check and monitor Geant4 dataset cache status - */ -export function useDatasetCacheStatus(): UseDatasetCacheStatusResult { - const [cacheStatus, setCacheStatus] = useState(null); - const [storageEstimate, setStorageEstimate] = useState(null); - const [isLoading, setIsLoading] = useState(true); - - const refresh = useCallback(async () => { - setIsLoading(true); - - try { - const [status, storage] = await Promise.all([ - checkAllDatasetsCacheStatus(), - getStorageEstimate() - ]); - setCacheStatus(status); - setStorageEstimate(storage); - } catch (error) { - console.error('Failed to check dataset cache status:', error); - } finally { - setIsLoading(false); - } - }, []); - - const clearCache = useCallback(async () => { - const success = await clearDatasetCache(); - - if (success) { - await refresh(); - } - - return success; - }, [refresh]); - - useEffect(() => { - refresh(); - }, [refresh]); - - const allCached = cacheStatus?.allCached ?? false; - const cachedCount = cacheStatus?.cachedCount ?? 0; - const totalCount = cacheStatus?.totalCount ?? 0; - const downloadSizeNeededMB = allCached - ? 0 - : TOTAL_DATASET_SIZE_MB - (cacheStatus?.estimatedCachedSizeMB ?? 0); - - return { - cacheStatus, - storageEstimate, - isLoading, - allCached, - cachedCount, - totalCount, - downloadSizeNeededMB, - refresh, - clearCache - }; -} diff --git a/src/WrapperApp/WrapperApp.tsx b/src/WrapperApp/WrapperApp.tsx index fba847f76..b49bbbdc1 100644 --- a/src/WrapperApp/WrapperApp.tsx +++ b/src/WrapperApp/WrapperApp.tsx @@ -3,7 +3,6 @@ import { styled } from '@mui/material/styles'; import { SyntheticEvent, useEffect, useState } from 'react'; import { useConfig } from '../config/ConfigService'; -import { useDatasetDownloadManager } from '../Geant4Worker/Geant4DatasetDownloadManager'; import { useAuth } from '../services/AuthService'; import { useStore } from '../services/StoreService'; import { EditorToolbar } from '../ThreeEditor/components/Editor/EditorToolbar'; @@ -66,12 +65,6 @@ function WrapperApp() { const [providedInputFiles, setProvidedInputFiles] = useState(); const [highlightRunForm, setHighLightRunForm] = useState(false); - const { - managerState: geant4DownloadManagerState, - datasetStates: geant4DatasetStates, - startDownload: geant4DatasetDownload - } = useDatasetDownloadManager(); - useEffect(() => { if (Object.keys(providedInputFiles ?? {}).length > 0) { setHighLightRunForm(true); @@ -240,9 +233,6 @@ function WrapperApp() { clearInputFiles={() => setProvidedInputFiles(undefined)} runSimulation={runSimulation} setSource={setSimulationPanelPresentedSimulationsSource} - geant4DownloadManagerState={geant4DownloadManagerState} - geant4DatasetDownloadStart={geant4DatasetDownload} - geant4DatasetStates={geant4DatasetStates} geant4DatasetType={geant4DatasetType} setGeant4DatasetType={setGeant4DatasetType} /> diff --git a/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx b/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx index 31ff2bfcc..21c7fe041 100644 --- a/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx +++ b/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx @@ -23,10 +23,11 @@ import { useEffect, useState } from 'react'; import { DatasetDownloadStatus, DatasetStatus, - DownloadManagerStatus -} from '../../../Geant4Worker/Geant4DatasetDownloadManager'; -import { useDatasetCacheStatus } from '../../../Geant4Worker/useDatasetCacheStatus'; + DownloadManagerStatus, + useDatasetManager +} from '../../../Geant4Worker/Geant4DatasetManager'; import { useDialog } from '../../../services/DialogService'; +import { useSharedDatasetManager } from '../../../services/Geant4DatasetContextProvider'; import StyledAccordion from '../../../shared/components/StyledAccordion'; import { StyledExclusiveToggleButtonGroup } from '../../../shared/components/StyledExclusiveToggleButtonGroup'; @@ -35,22 +36,24 @@ export enum Geant4DatasetsType { FULL } -export interface Geant4DatasetsProps { - geant4DownloadManagerState: DownloadManagerStatus; - geant4DatasetStates: DatasetStatus[]; - geant4DatasetDownloadStart: () => void; - geant4DatasetType: Geant4DatasetsType; - setGeant4DatasetType: (type: Geant4DatasetsType) => void; -} - function DatasetCurrentStatus(props: { status: DatasetStatus }) { const { status } = props; + let icon = null; + + if (status.status === DatasetDownloadStatus.DONE) { + icon = ; + } else if (status.isCached) { + icon = ; + } else { + icon = ; + } + return ( {status.name} - {status.status === DatasetDownloadStatus.DONE && } + {icon} @@ -67,43 +70,16 @@ function DatasetCurrentStatus(props: { status: DatasetStatus }) { color='warning' /> )} - {status.status === DatasetDownloadStatus.IDLE && ( - - )} ); } -/** - * Component to display cache status with visual indicators - */ function CacheStatusIndicator({ showDebugInfo = false }: { showDebugInfo?: boolean }) { - const { - isLoading, - allCached, - cachedCount, - totalCount, - downloadSizeNeededMB, - storageEstimate, - refresh, - cacheStatus - } = useDatasetCacheStatus(); + const { isLoading, cachedCount, totalCount, downloadSizeNeededMB, storageEstimate, refresh } = + useDatasetManager(); - // Log cache status for debugging - useEffect(() => { - console.log('[CacheStatusIndicator] Cache status updated:', { - isLoading, - allCached, - cachedCount, - totalCount, - downloadSizeNeededMB, - datasets: cacheStatus?.datasets - }); - }, [isLoading, allCached, cachedCount, totalCount, downloadSizeNeededMB, cacheStatus]); + const allCached = cachedCount === totalCount; if (isLoading) { return ( @@ -179,22 +155,6 @@ function CacheStatusIndicator({ showDebugInfo = false }: { showDebugInfo?: boole - {/* Show individual dataset status */} - {cacheStatus && cacheStatus.datasets.length > 0 && ( - - {cacheStatus.datasets.map(ds => ( - - ))} - - )} - {!allCached && ( )} - - {showDebugInfo && cacheStatus && ( - - Debug: {cachedCount}/{totalCount} cached, allCached={String(allCached)} - - )} ); } @@ -281,11 +232,21 @@ export function Geant4DatasetDownloadSelector(props: { ); } -export function Geant4Datasets(props: Geant4DatasetsProps) { +export function Geant4Datasets() { const theme = useTheme(); - const { geant4DownloadManagerState, geant4DatasetStates, geant4DatasetDownloadStart } = props; const [open, setOpen] = useState(true); - const { allCached, refresh } = useDatasetCacheStatus(); + const { + managerState: geant4DownloadManagerState, + datasetStatus, + startDownload: geant4DatasetDownloadStart, + cachedCount, + totalCount, + refresh + } = useSharedDatasetManager(); + + const allCached = cachedCount === totalCount; + + console.log(datasetStatus); // Refresh cache status when download finishes useEffect(() => { @@ -293,16 +254,22 @@ export function Geant4Datasets(props: Geant4DatasetsProps) { console.log('[Geant4Datasets] Download finished, refreshing cache status...'); // Add a small delay to ensure IndexedDB is updated setTimeout(() => refresh(), 1000); + setOpen(false); } }, [geant4DownloadManagerState, refresh]); const buttonText = allCached ? 'Load from cache' : 'Start download'; - const buttonIcon = allCached ? : ; + const buttonIcon = allCached ? ( + + ) : ( + + ); const showDownloadButton = geant4DownloadManagerState === DownloadManagerStatus.IDLE; const showDownloadProgress = geant4DownloadManagerState === DownloadManagerStatus.WORKING || - geant4DownloadManagerState === DownloadManagerStatus.FINISHED; + geant4DownloadManagerState === DownloadManagerStatus.FINISHED || + cachedCount > 0; return ( - {/* Always show cache status indicator */} - + + + {showDownloadProgress && + Object.values(datasetStatus).map(status => ( + + ))} {showDownloadButton && ( - )} + + {showDownloadButton && ( + + )} + {cachedCount > 0 && ( + + )} + {geant4DownloadManagerState === DownloadManagerStatus.ERROR && ( From 916477695050adc27ca6010e169dba7d9e6a0577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81uaksz=20Kwinta?= Date: Sun, 14 Dec 2025 19:34:48 +0100 Subject: [PATCH 08/13] Reformat text and fix behaviour --- .../Simulation/Geant4DatasetDownload.tsx | 56 ++++++++----------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx b/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx index 607fcd356..f7ff57fe5 100644 --- a/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx +++ b/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx @@ -195,29 +195,21 @@ function CacheStatusIndicator() { /> - - - {cachedCount > 0 && storageEstimate && ( - - - {`${storageEstimate.usedMB.toFixed(0)} MB used`} - - - )} - {!allCached && ( + {storageEstimate && ( + - {cachedCount > 0 - ? `~${downloadSizeNeededMB.toFixed(0)} MB remaining to download` - : `~${downloadSizeNeededMB.toFixed(0)} MB download required (may take several minutes)`} + color='text.secondary' + sx={{ flexGrow: 1 }}> + {cachedCount > 0 && `${storageEstimate.usedMB.toFixed(0)} MB used`} + {!allCached && + (cachedCount > 0 + ? `, ~${downloadSizeNeededMB.toFixed(0)} MB remaining to download` + : `~${downloadSizeNeededMB.toFixed(0)} MB download required (may take several minutes)`)} - )} - + + )} ); } @@ -288,7 +280,6 @@ export function Geant4DatasetDownloadSelector(props: { export function Geant4Datasets() { const theme = useTheme(); - const [open, setOpen] = useState(true); const { managerState: geant4DownloadManagerState, datasetStatus, @@ -298,6 +289,7 @@ export function Geant4Datasets() { refresh, clearCache } = useSharedDatasetManager(); + const [open, setOpen] = useState(geant4DownloadManagerState !== DownloadManagerStatus.FINISHED); const allCached = cachedCount === totalCount; @@ -305,7 +297,6 @@ export function Geant4Datasets() { useEffect(() => { if (geant4DownloadManagerState === DownloadManagerStatus.FINISHED) { // Add a small delay to ensure IndexedDB is updated - setOpen(false); setTimeout(() => { refresh(); }, 5000); @@ -319,7 +310,7 @@ export function Geant4Datasets() { ); - const showDownloadButton = geant4DownloadManagerState === DownloadManagerStatus.IDLE; + const enableDownloadButton = geant4DownloadManagerState === DownloadManagerStatus.IDLE; const showDownloadProgress = geant4DownloadManagerState === DownloadManagerStatus.WORKING || geant4DownloadManagerState === DownloadManagerStatus.FINISHED || @@ -357,16 +348,15 @@ export function Geant4Datasets() { ))} - {showDownloadButton && ( - - )} + {cachedCount > 0 && ( )} diff --git a/src/WrapperApp/components/Simulation/Modal/DatasetsFullInfoModal.tsx b/src/WrapperApp/components/Simulation/Modal/DatasetsFullInfoModal.tsx index b7add2d45..9d0519504 100644 --- a/src/WrapperApp/components/Simulation/Modal/DatasetsFullInfoModal.tsx +++ b/src/WrapperApp/components/Simulation/Modal/DatasetsFullInfoModal.tsx @@ -17,6 +17,7 @@ import { Tooltip, Typography } from '@mui/material'; +import { useEffect } from 'react'; import { useSharedDatasetManager } from '../../../../services/Geant4DatasetContextProvider'; import { @@ -51,7 +52,7 @@ const datasetSummaries = [ 'Data evaluated from the SAID database for proton, neutron, pion inelastic, elastic, and charge exchange cross sections of nucleons below 3 GeV' }, { - name: 'G4PhotonEvaporation6.1', + name: 'PhotonEvaporation6.1', description: 'Data for photon emission and internal conversion following nuclear de-excitation, used by the photon evaporation model in radioactive decay and photo-nuclear processes.' } @@ -133,6 +134,12 @@ function CacheStatusSection() { } export function DatasetsFullInfoDialog({ onClose }: ConcreteDialogProps) { + const { datasetStatus, refresh } = useSharedDatasetManager(); + + useEffect(() => { + refresh(); + }, [refresh]); + return ( Name + Cached Description @@ -181,6 +189,9 @@ export function DatasetsFullInfoDialog({ onClose }: ConcreteDialogProps) { 'verticalAlign': 'top' }}> {ds.name} + + {datasetStatus[ds.name]?.cached ? 'Yes' : 'No'} + {ds.description} ))} From d6a6ca6bc6bafb4d22e8938ae0e49a9eb80bbb3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81uaksz=20Kwinta?= Date: Sun, 14 Dec 2025 21:58:36 +0100 Subject: [PATCH 10/13] Rework icons --- .../components/Simulation/Geant4DatasetDownload.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx b/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx index a5252b217..18f7ba6d4 100644 --- a/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx +++ b/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx @@ -4,6 +4,8 @@ import CachedIcon from '@mui/icons-material/Cached'; import CheckIcon from '@mui/icons-material/Check'; import CloudDownloadIcon from '@mui/icons-material/CloudDownload'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import PlaylistRemoveIcon from '@mui/icons-material/PlaylistRemove'; +import RefreshIcon from '@mui/icons-material/Refresh'; import StorageIcon from '@mui/icons-material/Storage'; import { AccordionDetails, @@ -41,7 +43,7 @@ function DatasetCurrentStatus(props: { status: DatasetStatus }) { const idleIcon = status.cached ? ( ) : ( - + ); const datasetStatusIcon: Map = new Map([ @@ -110,7 +112,7 @@ function DatasetCachedChip(props: DatasetCachedChipProps) { [DatasetChipType.CACHED]: { title: 'All datasets are cached in your browser. Loading will be quick!', chip: { - icon: , + icon: , label: 'Cached', color: 'primary' } @@ -183,7 +185,7 @@ function CacheStatusIndicator() { } + icon={} label='Refresh' size='small' variant='outlined' @@ -303,7 +305,7 @@ export function Geant4Datasets() { const buttonText = allCached ? 'Load from cache' : 'Start download'; const buttonIcon = allCached ? ( - + ) : ( ); @@ -359,7 +361,7 @@ export function Geant4Datasets() { From ac0d9ce95c729747de1109d5e5fb064dccb4835c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81uaksz=20Kwinta?= Date: Sun, 14 Dec 2025 22:56:35 +0100 Subject: [PATCH 11/13] Rework text in modal --- src/Geant4Worker/Geant4DatasetManager.ts | 3 +- .../Simulation/Geant4DatasetDownload.tsx | 8 +- .../Modal/DatasetsFullInfoModal.tsx | 108 ++---------------- 3 files changed, 15 insertions(+), 104 deletions(-) diff --git a/src/Geant4Worker/Geant4DatasetManager.ts b/src/Geant4Worker/Geant4DatasetManager.ts index 4044ce3c7..7f4be446b 100644 --- a/src/Geant4Worker/Geant4DatasetManager.ts +++ b/src/Geant4Worker/Geant4DatasetManager.ts @@ -1,7 +1,6 @@ // Additional credits: // - @kmichalik -import { ref } from 'process'; import { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from 'react'; import { @@ -202,7 +201,7 @@ export function useDatasetManager(): UseDatasetManagerResult { } return success; - }, [refresh]); + }, [refresh, worker]); useEffect(() => { refresh(); diff --git a/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx b/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx index 18f7ba6d4..5d94ffbd6 100644 --- a/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx +++ b/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx @@ -304,11 +304,7 @@ export function Geant4Datasets() { }, [geant4DownloadManagerState, refresh]); const buttonText = allCached ? 'Load from cache' : 'Start download'; - const buttonIcon = allCached ? ( - - ) : ( - - ); + const buttonIcon = allCached ? : ; const enableDownloadButton = geant4DownloadManagerState === DownloadManagerStatus.IDLE; const showDownloadProgress = @@ -361,7 +357,7 @@ export function Geant4Datasets() { diff --git a/src/WrapperApp/components/Simulation/Modal/DatasetsFullInfoModal.tsx b/src/WrapperApp/components/Simulation/Modal/DatasetsFullInfoModal.tsx index 9d0519504..14af44aaa 100644 --- a/src/WrapperApp/components/Simulation/Modal/DatasetsFullInfoModal.tsx +++ b/src/WrapperApp/components/Simulation/Modal/DatasetsFullInfoModal.tsx @@ -1,21 +1,13 @@ -import CachedIcon from '@mui/icons-material/Cached'; -import CloudDownloadIcon from '@mui/icons-material/CloudDownload'; -import StorageIcon from '@mui/icons-material/Storage'; import { Alert, - Box, Button, - Chip, - CircularProgress, Paper, Table, TableBody, TableCell, TableContainer, TableHead, - TableRow, - Tooltip, - Typography + TableRow } from '@mui/material'; import { useEffect } from 'react'; @@ -58,81 +50,6 @@ const datasetSummaries = [ } ]; -/** - * Component to display current cache status in the dialog - */ -function CacheStatusSection() { - const { isLoading, cachedCount, totalCount, downloadSizeNeededMB, storageEstimate } = - useSharedDatasetManager(); - - if (isLoading) { - return ( - - - Checking cache status... - - ); - } - - const allCached = cachedCount === totalCount; - - return ( - - - Current Cache Status: - - - {allCached ? ( - } - label='All datasets cached' - color='success' - size='small' - /> - ) : cachedCount > 0 ? ( - } - label={`${cachedCount}/${totalCount} datasets cached`} - color='warning' - size='small' - /> - ) : ( - } - label='No datasets cached' - color='error' - size='small' - /> - )} - - {storageEstimate && ( - - } - label={`${storageEstimate.usedMB.toFixed(0)} MB / ${(storageEstimate.quotaMB / 1024).toFixed(1)} GB`} - size='small' - variant='outlined' - /> - - )} - - - {!allCached && ( - - {cachedCount > 0 - ? `~${downloadSizeNeededMB.toFixed(0)} MB remaining to download` - : `~${downloadSizeNeededMB.toFixed(0)} MB total download required`} - - )} - - ); -} - export function DatasetsFullInfoDialog({ onClose }: ConcreteDialogProps) { const { datasetStatus, refresh } = useSharedDatasetManager(); @@ -147,28 +64,27 @@ export function DatasetsFullInfoDialog({ onClose }: ConcreteDialogProps) { title='FULL Geant4 Datasets Info' contentText={` Downloading the FULL Geant4 datasets can significantly speed up simulations by providing local access to essential data files. - Data files will be stored in your browser's IndexedDB storage. - Below is a summary of the datasets available for download:`} + Data files will be stored in your browser's IndexedDB storage.`} body={ <> - - The cache status indicator shows which datasets are stored in your browser. - When all datasets are cached, loading will be nearly instant. Otherwise, - datasets will be downloaded from S3 storage. + sx={{ mt: 1 }}> + Simulation input data and results may be removed if you close the browser + tab or restart your computer. In contrast, Geant4 datasets stored in your + browser's cache (IndexedDB) are saved on your drive and persist across + sessions. - Total size of downloaded datasets is about 2GB. Each time you clear your - browser data, you will need to re-download these datasets for optimal - simulation performance. + sx={{ mt: 1 }}> + If you clear your browser data (for example, using antivirus software or PC + cleanup tools), you'll need to download these datasets again to ensure + optimal simulation performance. + sx={{ mt: 1 }}> From 3f4c4e484ed4dcd9493942dc8b6c61d8569318f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81uaksz=20Kwinta?= Date: Sun, 14 Dec 2025 23:31:30 +0100 Subject: [PATCH 12/13] Copilots review --- src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx b/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx index 5d94ffbd6..83e3f51f9 100644 --- a/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx +++ b/src/WrapperApp/components/Simulation/Geant4DatasetDownload.tsx @@ -343,7 +343,7 @@ export function Geant4Datasets() { /> ))} - +