Skip to content

Commit

Permalink
Add score matrix report
Browse files Browse the repository at this point in the history
Change-Id: I9f1581873422012135e3b791e7e5ff31dfa3b616
  • Loading branch information
adrien-berchet committed Nov 23, 2020
1 parent 4a4269e commit 7d891ff
Show file tree
Hide file tree
Showing 12 changed files with 419 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
ignore=version.py

[MESSAGES CONTROL]
disable=bad-continuation,fixme,invalid-name,len-as-condition,no-else-return,empty-docstring
disable=bad-continuation,fixme,invalid-name,len-as-condition,no-else-return,empty-docstring,too-many-lines

[FORMAT]
# Maximum number of characters on a single line.
Expand Down
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ global-exclude *.py[co] .DS_Store

include src/version.py
include src/morphval/templates/*
include src/synthesis_workflow/defaults/morphval_default_config.yaml
include src/synthesis_workflow/defaults/*
1 change: 1 addition & 0 deletions doc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ help:
pdftocairo -png -r 300 -f 1 -l 1 ../tests/data/in_small_O1/out/validation/path_distance_fit.pdf source/autoapi/tasks/validation/path_distance_fit
pdftocairo -png -r 300 -f 1 -l 1 ../tests/data/in_vacuum/out/validation/morphometrics/morphometrics_basal_dendrite.pdf source/autoapi/tasks/validation/morphometrics
pdftocairo -png -r 300 -f 1 -l 1 ../tests/data/in_vacuum/out/validation/vacuum_morphologies.pdf source/autoapi/tasks/vacuum_synthesis/vacuum_morphologies
pdftocairo -png -r 300 -f 1 -l 1 ../tests/data/in_small_O1/out/validation/score_matrix_reports.pdf source/autoapi/tasks/validation/score_matrix_reports

# Generate dependency graphs
cd ../tests/data/in_small_O1; synthesis_workflow -dg ../../../doc/source/autoapi/tasks/workflows/ValidateSynthesis.dot ValidateSynthesis; cd ../../../doc
Expand Down
94 changes: 94 additions & 0 deletions src/synthesis_workflow/defaults/score_matrix_default_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{
"neurite": {
"number_of_bifurcations": [
"sum"
],
"number_of_sections_per_neurite": [
"mean",
"sum"
],
"number_of_terminations": [
"sum"
],
"partition_asymmetry": [
"mean",
"sum"
],
"partition_asymmetry_length": [
"mean",
"sum"
],
"remote_bifurcation_angles": [
"mean"
],
"section_areas": [
"mean",
"sum"
],
"section_bif_branch_orders": [
"max",
"mean"
],
"section_bif_lengths": [
"min",
"max",
"mean"
],
"section_bif_radial_distances": [
"max",
"mean"
],
"section_branch_orders": [
"max",
"mean"
],
"section_lengths": [
"min",
"max",
"mean",
"sum"
],
"section_path_distances": [
"min",
"max",
"mean"
],
"section_radial_distances": [
"min",
"max",
"mean"
],
"section_strahler_orders": [
"mean"
],
"section_term_branch_orders": [
"max",
"mean"
],
"section_term_lengths": [
"min",
"max",
"mean"
],
"section_term_radial_distances": [
"max",
"mean"
],
"section_tortuosity": [
"min",
"max",
"mean"
],
"section_volumes": [
"mean",
"sum"
],
"total_length_per_neurite": [
"mean"
]
},
"neurite_type": [
"APICAL_DENDRITE",
"BASAL_DENDRITE"
]
}
103 changes: 93 additions & 10 deletions src/synthesis_workflow/tasks/validation.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Luigi tasks for validation of synthesis."""
import json
import logging
from pathlib import Path

Expand All @@ -11,16 +12,6 @@
from voxcell import VoxelData

from morphval import validation_main as morphval_validation
from synthesis_workflow.tools import load_circuit
from synthesis_workflow.validation import convert_mvd3_to_morphs_df
from synthesis_workflow.validation import parse_log
from synthesis_workflow.validation import plot_collage
from synthesis_workflow.validation import plot_density_profiles
from synthesis_workflow.validation import plot_morphometrics
from synthesis_workflow.validation import plot_path_distance_fits
from synthesis_workflow.validation import plot_scale_statistics
from synthesis_workflow.validation import SYNTH_MORPHOLOGY_PATH
from synthesis_workflow.validation import VacuumCircuit
from synthesis_workflow.tasks.circuit import CreateAtlasLayerAnnotations
from synthesis_workflow.tasks.circuit import CreateAtlasPlanes
from synthesis_workflow.tasks.config import CircuitConfig
Expand All @@ -42,6 +33,18 @@
from synthesis_workflow.tasks.synthesis import BuildSynthesisDistributions
from synthesis_workflow.tasks.synthesis import Synthesize
from synthesis_workflow.tasks.vacuum_synthesis import VacuumSynthesize
from synthesis_workflow.tools import load_circuit
from synthesis_workflow.vacuum_synthesis import VACUUM_SYNTH_MORPHOLOGY_PATH
from synthesis_workflow.validation import convert_mvd3_to_morphs_df
from synthesis_workflow.validation import parse_log
from synthesis_workflow.validation import plot_collage
from synthesis_workflow.validation import plot_density_profiles
from synthesis_workflow.validation import plot_morphometrics
from synthesis_workflow.validation import plot_path_distance_fits
from synthesis_workflow.validation import plot_scale_statistics
from synthesis_workflow.validation import plot_score_matrix
from synthesis_workflow.validation import SYNTH_MORPHOLOGY_PATH
from synthesis_workflow.validation import VacuumCircuit


L = logging.getLogger(__name__)
Expand Down Expand Up @@ -601,3 +604,83 @@ def run(self):
def output(self):
""""""
return ValidationLocalTarget(self.output_path)


@copy_params(
mtypes=ParamLink(SynthesisConfig),
morphology_path=ParamLink(PathConfig),
nb_jobs=ParamLink(RunnerConfig),
)
class PlotScoreMatrix(WorkflowTask):
"""Create score matrix reports.
The generated images are like the following:
.. image:: score_matrix_reports-1.png
Attributes:
mtypes (list(str)): List of mtypes to plot.
morphology_path (str): Column name to use in the DF from ApplySubstitutionRules.
nb_jobs (int): Number of jobs.
"""

config_path = luigi.OptionalParameter(default=None)
"""str: (optional) Path to the configuration file. Use default configuration if not provided."""

output_path = luigi.Parameter(default="score_matrix_reports.pdf")
"""str: Path to the output file."""

in_atlas = BoolParameter(default=False)
"""bool: Trigger atlas case."""

def requires(self):
""""""
if self.in_atlas:
test_task = ConvertMvd3()
else:
test_task = VacuumSynthesize()
return {
"ref": ApplySubstitutionRules(),
"test": test_task,
}

def run(self):
""""""
L.debug("Score matrix output path = %s", self.output().path)

ref_morphs_df = pd.read_csv(self.input()["ref"].path)
if self.in_atlas:
test_morphs_df = pd.read_csv(self.input()["test"].path)
file_path_col_name = SYNTH_MORPHOLOGY_PATH
else:
test_morphs_df = pd.read_csv(self.input()["test"]["out_morphs_df"].path)
file_path_col_name = VACUUM_SYNTH_MORPHOLOGY_PATH

if self.config_path is not None:
with open(self.config_path) as f:
config = json.load(f)
else:
with pkg_resources.resource_stream(
"synthesis_workflow", "defaults/score_matrix_default_config.json"
) as f:
config = json.load(f)

ref_morphs_df = ref_morphs_df[["name", "mtype", self.morphology_path]].rename(
columns={self.morphology_path: "filepath"}
)
test_morphs_df = test_morphs_df[["name", "mtype", file_path_col_name]].rename(
columns={file_path_col_name: "filepath"}
)

plot_score_matrix(
ref_morphs_df,
test_morphs_df,
self.output().ppath,
config,
mtypes=self.mtypes,
nb_jobs=self.nb_jobs,
)

def output(self):
""""""
return ValidationLocalTarget(self.output_path)
15 changes: 15 additions & 0 deletions src/synthesis_workflow/tasks/workflows.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from synthesis_workflow.tasks.validation import PlotMorphometrics
from synthesis_workflow.tasks.validation import PlotPathDistanceFits
from synthesis_workflow.tasks.validation import PlotScales
from synthesis_workflow.tasks.validation import PlotScoreMatrix
from synthesis_workflow.validation import plot_morphometrics


Expand Down Expand Up @@ -54,6 +55,11 @@ class ValidateSynthesis(WorkflowWrapperTask):
)
"""bool: Trigger morphology validation reports."""

with_score_matrix_reports = BoolParameter(
default=True, description="Trigger score matrix reports."
)
"""bool: Trigger score matrix reports."""

def requires(self):
""""""
tasks = [GetSynthesisInputs()]
Expand All @@ -69,6 +75,8 @@ def requires(self):
tasks.append(PlotScales())
if self.with_morphology_validation_reports:
tasks.append(MorphologyValidationReports())
if self.with_score_matrix_reports:
tasks.append(PlotScoreMatrix())
return tasks


Expand All @@ -95,6 +103,11 @@ class ValidateVacuumSynthesis(WorkflowWrapperTask):
)
"""bool: Trigger density profiles."""

with_score_matrix_reports = BoolParameter(
default=True, description="Trigger score matrix reports."
)
"""bool: Trigger score matrix reports."""

def requires(self):
""""""
tasks = [GetSynthesisInputs()]
Expand All @@ -104,6 +117,8 @@ def requires(self):
tasks.append(PlotVacuumMorphologies())
if self.with_density_profiles:
tasks.append(PlotDensityProfiles(in_atlas=False))
if self.with_score_matrix_reports:
tasks.append(PlotScoreMatrix(in_atlas=False))
return tasks


Expand Down
Loading

0 comments on commit 7d891ff

Please sign in to comment.