Convert-Pheno

 view release on metacpan or  search on metacpan

lib/Convert/Pheno/CLI/Args.pm  view on Meta::CPAN

        my %supported_for_route =
          map { $_ => 1 } @{ $conversion_spec->{entities}{supported} };
        for my $entity (@entity_list) {
            $usage_error->(
                "The entity <$entity> is not supported by conversion <$method>"
            ) unless $supported_for_route{$entity};
        }
    }

    $usage_error->("The conversion <$method> does not support --stream")
      if $stream && !$conversion_spec->{streaming};

    my $id = time . substr( "00000$$", -5 );

    my %data = (
        out_dir                   => $out_dir,
        in_textfile               => 1,
        method                    => $method,
        sql2csv                   => $sql2csv ? 1 : 0,
        exposures_file            => $exposures_file,
        search                    => $search,

lib/Convert/Pheno/Operations.pm  view on Meta::CPAN

die "Public conversion registry <$registry_file> must define HTTP request fields\n"
  unless ref( $registry->{http_request_fields} ) eq 'HASH';

my %PUBLIC_CONVERSION = %{ $registry->{conversions} };

for my $name ( keys %PUBLIC_CONVERSION ) {
    my $spec = $PUBLIC_CONVERSION{$name};
    die "Conversion <$name> must contain an object specification\n"
      unless ref($spec) eq 'HASH';

    for my $field (qw(source target operation pipeline resources entities streaming http_enabled)) {
        die "Conversion <$name> is missing registry field <$field>\n"
          unless exists $spec->{$field};
    }

    die "Conversion <$name> has an invalid operation type\n"
      unless $spec->{operation} =~ /\A(?:bundle|direct|pipeline)\z/;
    die "Conversion <$name> must define a non-empty pipeline\n"
      unless ref( $spec->{pipeline} ) eq 'ARRAY' && @{ $spec->{pipeline} };
    die "Conversion <$name> must define SQLite resource requirements\n"
      unless ref( $spec->{resources} ) eq 'HASH'

lib/Convert/Pheno/Pipeline.pm  view on Meta::CPAN


our @EXPORT_OK = qw(run_conversion_pipeline);

sub run_conversion_pipeline {
    my ($converter) = @_;
    my $request = Convert::Pheno::ConversionRequest->from_converter($converter);
    my $spec    = $request->spec;

    die "Conversion <$spec->{name}> is not a compound pipeline\n"
      unless $spec->{operation} eq 'pipeline';
    die "Conversion <$spec->{name}> does not support streaming\n"
      if $converter->{stream} && !$spec->{streaming};

    my $execution = Convert::Pheno::ExecutionContext->new(
        { request => $request }
    );

    # OMOP file input is already emitted one participant at a time. Preserve
    # that bounded-memory path while applying the downstream BFF-to-PXF stage
    # in the output sink rather than materializing the full BFF intermediate.
    if ( $spec->{name} eq 'omop2pxf' && !$request->has_data ) {
        my ( $stage, $arguments ) = $execution->begin_next_stage;

share/schema/public-conversions.json  view on Meta::CPAN

    ]
  },
  "conversions": {
    "bff2csv": {
      "source": "beacon",
      "target": "csv",
      "operation": "direct",
      "pipeline": ["bff2csv"],
      "resources": { "sqlite": false },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "bff2jsonf": {
      "source": "beacon",
      "target": "jsonf",
      "operation": "direct",
      "pipeline": ["bff2jsonf"],
      "resources": { "sqlite": false },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "bff2jsonld": {
      "source": "beacon",
      "target": "jsonld",
      "operation": "direct",
      "pipeline": ["bff2jsonld"],
      "resources": { "sqlite": false },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "bff2omop": {
      "source": "beacon",
      "target": "omop",
      "operation": "direct",
      "pipeline": ["bff2omop"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "bff2pxf": {
      "source": "beacon",
      "target": "pxf",
      "operation": "direct",
      "pipeline": ["bff2pxf"],
      "resources": { "sqlite": false },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "cbioportal2bff": {
      "source": "cbioportal",
      "target": "beacon",
      "operation": "bundle",
      "pipeline": ["cbioportal2bff"],
      "resources": { "sqlite": true },
      "entities": { "default": ["individuals"], "supported": ["individuals", "biosamples", "datasets", "cohorts"], "primary": "individuals" },
      "streaming": false,
      "http_enabled": false
    },
    "cbioportal2omop": {
      "source": "cbioportal",
      "target": "omop",
      "operation": "pipeline",
      "pipeline": ["cbioportal2bff", "bff2omop"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": false
    },
    "cbioportal2pxf": {
      "source": "cbioportal",
      "target": "pxf",
      "operation": "pipeline",
      "pipeline": ["cbioportal2bff", "bff2pxf"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": false
    },
    "cdiscodm2bff": {
      "source": "cdisc-odm",
      "target": "beacon",
      "operation": "bundle",
      "pipeline": ["cdiscodm2bff"],
      "resources": { "sqlite": true },
      "entities": { "default": ["individuals"], "supported": ["individuals", "datasets", "cohorts"], "primary": "individuals" },
      "streaming": false,
      "http_enabled": false
    },
    "cdiscodm2omop": {
      "source": "cdisc-odm",
      "target": "omop",
      "operation": "pipeline",
      "pipeline": ["cdiscodm2bff", "bff2omop"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": false
    },
    "cdiscodm2pxf": {
      "source": "cdisc-odm",
      "target": "pxf",
      "operation": "pipeline",
      "pipeline": ["cdiscodm2bff", "bff2pxf"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": false
    },
    "datasetjson2bff": {
      "source": "dataset-json",
      "target": "beacon",
      "operation": "bundle",
      "pipeline": ["datasetjson2bff"],
      "resources": { "sqlite": false },
      "entities": { "default": ["individuals"], "supported": ["individuals", "datasets", "cohorts"], "primary": "individuals" },
      "streaming": false,
      "http_enabled": false
    },
    "datasetjson2omop": {
      "source": "dataset-json",
      "target": "omop",
      "operation": "pipeline",
      "pipeline": ["datasetjson2bff", "bff2omop"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": false
    },
    "datasetjson2pxf": {
      "source": "dataset-json",
      "target": "pxf",
      "operation": "pipeline",
      "pipeline": ["datasetjson2bff", "bff2pxf"],
      "resources": { "sqlite": false },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": false
    },
    "datasetxml2bff": {
      "source": "dataset-xml",
      "target": "beacon",
      "operation": "bundle",
      "pipeline": ["datasetxml2bff"],
      "resources": { "sqlite": false },
      "entities": { "default": ["individuals"], "supported": ["individuals", "datasets", "cohorts"], "primary": "individuals" },
      "streaming": false,
      "http_enabled": false
    },
    "datasetxml2omop": {
      "source": "dataset-xml",
      "target": "omop",
      "operation": "pipeline",
      "pipeline": ["datasetxml2bff", "bff2omop"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": false
    },
    "datasetxml2pxf": {
      "source": "dataset-xml",
      "target": "pxf",
      "operation": "pipeline",
      "pipeline": ["datasetxml2bff", "bff2pxf"],
      "resources": { "sqlite": false },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": false
    },
    "fhir2bff": {
      "source": "fhir",
      "target": "beacon",
      "operation": "bundle",
      "pipeline": ["fhir2bff"],
      "resources": { "sqlite": false },
      "entities": { "default": ["individuals"], "supported": ["individuals", "biosamples", "datasets", "cohorts"], "primary": "individuals" },
      "streaming": false,
      "http_enabled": true
    },
    "fhir2omop": {
      "source": "fhir",
      "target": "omop",
      "operation": "pipeline",
      "pipeline": ["fhir2bff", "bff2omop"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "fhir2pxf": {
      "source": "fhir",
      "target": "pxf",
      "operation": "pipeline",
      "pipeline": ["fhir2bff", "bff2pxf"],
      "resources": { "sqlite": false },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "csv2bff": {
      "source": "csv",
      "target": "beacon",
      "operation": "bundle",
      "pipeline": ["csv2bff"],
      "resources": { "sqlite": true },
      "entities": { "default": ["individuals"], "supported": ["individuals", "datasets", "cohorts"], "primary": "individuals" },
      "streaming": false,
      "http_enabled": false
    },
    "csv2omop": {
      "source": "csv",
      "target": "omop",
      "operation": "pipeline",
      "pipeline": ["csv2bff", "bff2omop"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": false
    },
    "csv2pxf": {
      "source": "csv",
      "target": "pxf",
      "operation": "pipeline",
      "pipeline": ["csv2bff", "bff2pxf"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": false
    },
    "omop2bff": {
      "source": "omop",
      "target": "beacon",
      "operation": "bundle",
      "pipeline": ["omop2bff"],
      "resources": { "sqlite": true },
      "entities": { "default": ["individuals"], "supported": ["individuals", "biosamples", "datasets", "cohorts"], "primary": "individuals" },
      "streaming": true,
      "http_enabled": true
    },
    "omop2pxf": {
      "source": "omop",
      "target": "pxf",
      "operation": "pipeline",
      "pipeline": ["omop2bff", "bff2pxf"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "openehr2bff": {
      "source": "openehr",
      "target": "beacon",
      "operation": "bundle",
      "pipeline": ["openehr2bff"],
      "resources": { "sqlite": false },
      "entities": { "default": ["individuals"], "supported": ["individuals", "datasets", "cohorts"], "primary": "individuals" },
      "streaming": false,
      "http_enabled": true
    },
    "openehr2pxf": {
      "source": "openehr",
      "target": "pxf",
      "operation": "pipeline",
      "pipeline": ["openehr2bff", "bff2pxf"],
      "resources": { "sqlite": false },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "pxf2bff": {
      "source": "pxf",
      "target": "beacon",
      "operation": "bundle",
      "pipeline": ["pxf2bff"],
      "resources": { "sqlite": true },
      "entities": { "default": ["individuals"], "supported": ["individuals", "biosamples", "datasets", "cohorts"], "primary": "individuals" },
      "streaming": false,
      "http_enabled": true
    },
    "pxf2csv": {
      "source": "pxf",
      "target": "csv",
      "operation": "direct",
      "pipeline": ["pxf2csv"],
      "resources": { "sqlite": false },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "pxf2jsonf": {
      "source": "pxf",
      "target": "jsonf",
      "operation": "direct",
      "pipeline": ["pxf2jsonf"],
      "resources": { "sqlite": false },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "pxf2jsonld": {
      "source": "pxf",
      "target": "jsonld",
      "operation": "direct",
      "pipeline": ["pxf2jsonld"],
      "resources": { "sqlite": false },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "pxf2omop": {
      "source": "pxf",
      "target": "omop",
      "operation": "pipeline",
      "pipeline": ["pxf2bff", "bff2omop"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": true
    },
    "redcap2bff": {
      "source": "redcap",
      "target": "beacon",
      "operation": "bundle",
      "pipeline": ["redcap2bff"],
      "resources": { "sqlite": true },
      "entities": { "default": ["individuals"], "supported": ["individuals", "datasets", "cohorts"], "primary": "individuals" },
      "streaming": false,
      "http_enabled": false
    },
    "redcap2omop": {
      "source": "redcap",
      "target": "omop",
      "operation": "pipeline",
      "pipeline": ["redcap2bff", "bff2omop"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": false
    },
    "redcap2pxf": {
      "source": "redcap",
      "target": "pxf",
      "operation": "pipeline",
      "pipeline": ["redcap2bff", "bff2pxf"],
      "resources": { "sqlite": true },
      "entities": { "default": [], "supported": [], "primary": null },
      "streaming": false,
      "http_enabled": false
    }
  }
}

t/15-convertpheno-orchestration.t  view on Meta::CPAN

    my ( undef, $tmp_file ) = tempfile();
    my $convert = Convert::Pheno->new(
        {
            method    => 'omop2bff',
            out_file  => $tmp_file,
            in_textfile => 0,
        }
    );
    $convert->{omop_cli} = 1;
    my $stream = Convert::Pheno::_dispatcher_open_stream_out($convert);
    ok( $stream->{fh}, '_dispatcher_open_stream_out opens output file in streaming mode' );
    close $stream->{fh};
}

{
    my $convert = Convert::Pheno->new(
        {
            method      => 'bff2pxf',
            in_textfile => 0,
            data        => { inline => 1 },
        }

t/23-cli-help.t  view on Meta::CPAN

        '-o', 'pxf', 'output.json' ],
    [ 'rejects comma-separated entities', qr/space-separated list/,
        '-ipxf', 't/pxf2bff/in/pxf.json', '-obff',
        '--entities', 'individuals,biosamples' ],
    [ 'rejects unknown BFF entities', qr/Unsupported entity <unknown>/,
        '-ipxf', 't/pxf2bff/in/pxf.json', '-obff', '--entities', 'unknown' ],
    [ 'rejects entity selection for non-BFF output',
        qr/<--entities> is only valid with BFF output/,
        '-ipxf', 't/pxf2bff/in/pxf.json', '-opxf', 'output.json',
        '--entities', 'individuals' ],
    [ 'rejects streaming for non-OMOP input',
        qr/<--stream> is only valid with <-iomop> and <-obff>/,
        '-ipxf', 't/pxf2bff/in/pxf.json', '-obff', 'output.json', '--stream' ],
    [ 'rejects unsupported openEHR to OMOP output',
        qr/openEHR input path currently supports only BFF or PXF output/,
        '-i', 'openehr', 't/openehr2bff/in/gecco_personendaten_patient.json',
        '-o', 'omop', '--ohdsi-db' ],
    [ 'rejects invalid default vital status values', qr/Unsupported value <MISSING>/,
        '-ibff', 't/bff2pxf/in/individuals.json', '-opxf', 'output.json',
        '--default-vital-status', 'MISSING' ],
    [ 'rejects malformed output-name overrides', qr/Invalid <--out-name> value/,

t/27-operation-registry.t  view on Meta::CPAN

    [ 'fhir2bff', 'bff2pxf' ],
    'registry defines FHIR to PXF as a compound conversion'
);
is_deeply(
    conversion_spec('fhir2omop')->{pipeline},
    [ 'fhir2bff', 'bff2omop' ],
    'registry defines FHIR to OMOP as a compound conversion'
);

my $omop_to_bff = conversion_spec('omop2bff');
ok( $omop_to_bff->{streaming}, 'registry defines streaming capability' );
is_deeply(
    $omop_to_bff->{entities}{supported},
    [ 'individuals', 'biosamples', 'datasets', 'cohorts' ],
    'registry defines supported Beacon entities'
);
ok( is_http_conversion('pxf2bff'), 'registry exposes in-memory PXF conversion over HTTP' );
ok( !is_http_conversion('redcap2bff'), 'registry keeps file-based REDCap conversion on the CLI' );

my $http_fields = http_request_fields();
ok(



( run in 1.652 second using v1.01-cache-2.11-cpan-5c0b1e786e0 )