diff --git a/+siibra/+internal/API.m b/+siibra/+internal/API.m index 9291c82..f54644a 100644 --- a/+siibra/+internal/API.m +++ b/+siibra/+internal/API.m @@ -5,7 +5,6 @@ %Endpoint = "https://siibra-api-stable.apps.hbp.eu/v1_0/" %EndpointV2 = "https://siibra-api-stable.apps.hbp.eu/v2_0" EndpointV3 = "https://siibra-api-stable.apps.hbp.eu/v3_0/" - %EndpointV3 = "https://siibra-api-prod.apps.tc.humanbrainproject.eu/v3_0/" end methods (Static) @@ -136,6 +135,31 @@ "®ion_id=" + region.Name; absoluteLink = siibra.internal.API.absoluteLinkV3(relativeLink); end + function features = regionalConnectivity(parcellation, type) + relativeLink = "feature/RegionalConnectivity"; + absoluteLink = siibra.internal.API.absoluteLinkV3(relativeLink); + parameters = ["parcellation_id=" + parcellation.Id, "type=" + type]; + features = siibra.internal.API.collectItemsAcrossPages(absoluteLink, parameters); + end + function absoluteLink = streamlineCountsForSubject(streamlineCounts, subject) + relativeLink = "feature/RegionalConnectivity/" + streamlineCounts.FeatureId + ... + "?parcellation_id=" + streamlineCounts.Parcellation.Id + ... + "&type=StreamlineCounts"; + + if ~isempty(subject) + relativeLink = relativeLink + "&subject=" + subject; + end + + absoluteLink = siibra.internal.API.absoluteLinkV3(relativeLink); + end + + function downloadFeature(path, featureId) + relativeLink = "feature/" + featureId + "/download"; + absoluteLink = siibra.internal.API.absoluteLinkV3(relativeLink); + siibra.internal.API.doWebsaveWithLongTimeout(path, absoluteLink); + end + + end end diff --git a/+siibra/+items/+features/ReceptorDensity.m b/+siibra/+items/+features/ReceptorDensity.m index 7074a23..c3bb3fc 100644 --- a/+siibra/+items/+features/ReceptorDensity.m +++ b/+siibra/+items/+features/ReceptorDensity.m @@ -25,11 +25,10 @@ siibra.internal.API.tabularFeature( ... obj.Region, ... obj.Id)); - fingerprintStruct = fingerprintJson.data.fingerprints; - receptors = fieldnames(fingerprintStruct); - means = arrayfun(@(i) fingerprintStruct.(receptors{i}).mean, 1:numel(receptors)); - stds = arrayfun(@(i) fingerprintStruct.(receptors{i}).std, 1:numel(receptors)); - fingerprints = table(means.', stds.', 'VariableNames', ["Mean", "Std"], 'RowNames', receptors); + data = fingerprintJson.data.data; + column_names = fingerprintJson.data.columns; + row_names = fingerprintJson.data.index; + fingerprints = array2table(data, 'VariableNames', column_names, 'RowNames', row_names ); end end end diff --git a/+siibra/+items/+features/StreamlineCounts.m b/+siibra/+items/+features/StreamlineCounts.m index 6a53583..7c7db0b 100644 --- a/+siibra/+items/+features/StreamlineCounts.m +++ b/+siibra/+items/+features/StreamlineCounts.m @@ -6,11 +6,8 @@ Parcellation (1, :) siibra.items.Parcellation Name (1, 1) string Cohort (1, 1) string - Subject (1, 1) string - Authors (1, :) string + Subjects (1, :) string Description (1, 1) string - % Citation (1, 1) string - Matrix uint8 FeatureId (1, 1) string end @@ -21,57 +18,29 @@ obj.Parcellation = parcellation; obj.Name = featureJson.name; obj.Cohort = featureJson.cohort; - obj.Subject = featureJson.subject; - obj.Authors = featureJson.authors; + obj.Subjects = featureJson.subjects; obj.Description = featureJson.description; - % obj.Citation = featureJson.citation; - obj.FeatureId = featureJson.x_id; + obj.FeatureId = featureJson.id; end - function connectivityMatrix = get.Matrix(obj) - featureIdNormalized = obj.FeatureId.replace("/", "-"); - matrixCachePath = siibra.internal.cache(featureIdNormalized + ".mat", "parcellation_features"); - if ~isfile(matrixCachePath) - matrixJson = siibra.internal.API.doWebreadWithLongTimeout( ... - siibra.internal.API.parcellationFeature( ... - obj.Parcellation.Atlas.Id, ... - obj.Parcellation.Id, ... - obj.FeatureId) ... - ); - encodedMatrix = matrixJson.matrix.content; - dim1 = matrixJson.matrix.x_height; - dim2 = matrixJson.matrix.x_width; - decodedMatrix = matlab.net.base64decode(encodedMatrix); - - % write decoded and compressed matrix to file - compressedMatrixCachePath = siibra.internal.cache(featureIdNormalized + ".bin.gzip", "parcellation_features"); - f = fopen(compressedMatrixCachePath, "w"); - fwrite(f, decodedMatrix); - fclose(f); - - % decompress file and read it again - binaryMatrixCachePath = siibra.internal.cache(featureIdNormalized + ".bin", "parcellation_features"); - gunzip(compressedMatrixCachePath, siibra.internal.cache("", "parcellation_features")); - f = fopen(binaryMatrixCachePath, "r"); - decompressedMatrix = fread(f, matrixJson.matrix.dtype); - fclose(f); - - % delete intermediate files - delete(compressedMatrixCachePath) - delete(binaryMatrixCachePath) - - matrix = reshape(decompressedMatrix, dim1, dim2); - - connectivityMatrix = array2table(matrix); - columnNameLengths = cellfun(@(n) strlength(n), matrixJson.columns); - columnNamesToBeTrimmed = matrixJson.columns(columnNameLengths > 63); - matrixJson.columns(columnNameLengths > 63) = cellfun(@(n) n(1:63), columnNamesToBeTrimmed, 'UniformOutput',false); - connectivityMatrix.Properties.VariableNames = matrixJson.columns; - connectivityMatrix.Properties.RowNames = matrixJson.columns; - % cache matrix - save(matrixCachePath, "connectivityMatrix"); - end - connectivityMatrix = load(matrixCachePath, "connectivityMatrix").connectivityMatrix; + function connectivityMatrix = connectivityMatrixForSubject(obj, subject) + response = siibra.internal.API.doWebreadWithLongTimeout( ... + siibra.internal.API.streamlineCountsForSubject( ... + obj, subject ... + ) ... + ); + matrixStruct = getfield(response.matrices, "x" + subject); + connectivityMatrix = array2table(matrixStruct.data, "VariableNames", {matrixStruct.columns.name}, 'RowNames', {matrixStruct.index.name}); + end + function connectivityMatrix = averagedConnectivityMatrix(obj) + % leaving the subject field empty gives us the averaged matrix + response = siibra.internal.API.doWebreadWithLongTimeout( ... + siibra.internal.API.streamlineCountsForSubject( ... + obj, string.empty ... + ) ... + ); + matrixStruct = response.matrices.x_average; + connectivityMatrix = array2table(matrixStruct.data, "VariableNames", {matrixStruct.columns.name}, 'RowNames', {matrixStruct.index.name}); end end end diff --git a/+siibra/+items/Parcellation.m b/+siibra/+items/Parcellation.m index b0364af..16ba3b1 100644 --- a/+siibra/+items/Parcellation.m +++ b/+siibra/+items/Parcellation.m @@ -84,22 +84,9 @@ parentRegion = obj.RegionTree.Nodes.Region(parentId); end - function features = getAllFeatures(obj) - error("API v3 has no features on parcellation level!"); - cached_file_name = siibra.internal.cache(obj.Name + ".mat", "parcellation_features"); - if ~isfile(cached_file_name) - features = siibra.internal.API.featuresForParcellation(obj.Atlas.Id, obj.Id); - save(cached_file_name, 'features'); - else - load(cached_file_name, 'features') - end - - end - function streamlineCounts = getStreamlineCounts(obj) - allFeatures = obj.getAllFeatures(); - streamlineCountIdx = arrayfun(@(e) strcmp(e.x_type,'siibra/features/connectivity/streamlineCounts'), allFeatures); - streamlineCounts = arrayfun(@(json) siibra.items.features.StreamlineCounts(obj, json), allFeatures(streamlineCountIdx)); + streamlineCountsJson = siibra.internal.API.regionalConnectivity(obj, "StreamlineCounts"); + streamlineCounts = arrayfun(@(json) siibra.items.features.StreamlineCounts(obj, json), streamlineCountsJson); end end diff --git a/step-by-step/01_atlases_and_brain_parcellations/06_spatial_properties_of_brain_regions.mlx b/step-by-step/01_atlases_and_brain_parcellations/06_spatial_properties_of_brain_regions.mlx index 8fefb15..86a3383 100644 Binary files a/step-by-step/01_atlases_and_brain_parcellations/06_spatial_properties_of_brain_regions.mlx and b/step-by-step/01_atlases_and_brain_parcellations/06_spatial_properties_of_brain_regions.mlx differ diff --git a/walkthrough.mlx b/walkthrough.mlx index 5b9ab96..ac83e1d 100644 Binary files a/walkthrough.mlx and b/walkthrough.mlx differ