Skip to content

Commit

Permalink
Merge pull request #16 from mastodon-sc/add-mother-id-column
Browse files Browse the repository at this point in the history
Add import of tags, radius and links to CSV importer
  • Loading branch information
tinevez authored Sep 23, 2024
2 parents 10efa19 + b4165ca commit 064ab80
Show file tree
Hide file tree
Showing 6 changed files with 437 additions and 34 deletions.
186 changes: 173 additions & 13 deletions src/main/java/org/mastodon/mamut/io/csv/CSVImporter.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,19 @@
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import java.util.stream.Collectors;

import org.apache.commons.lang3.tuple.Pair;
import org.mastodon.RefPool;
import org.mastodon.collection.IntRefMap;
import org.mastodon.collection.RefCollection;
import org.mastodon.collection.ref.IntRefHashMap;
import org.mastodon.feature.Dimension;
import org.mastodon.feature.Feature;
import org.mastodon.feature.FeatureModel;
Expand All @@ -49,11 +56,16 @@
import org.mastodon.feature.Multiplicity;
import org.mastodon.feature.io.FeatureSerializer;
import org.mastodon.io.FileIdToObjectMap;
import org.mastodon.mamut.io.importer.ModelImporter;
import org.mastodon.mamut.model.Link;
import org.mastodon.mamut.model.Model;
import org.mastodon.mamut.model.ModelGraph;
import org.mastodon.mamut.model.Spot;
import org.mastodon.model.tag.TagSetStructure;
import org.mastodon.properties.IntPropertyMap;
import org.mastodon.tracking.mamut.detection.DetectionQualityFeature;
import org.mastodon.ui.coloring.GlasbeyLut;
import org.mastodon.util.TagSetUtils;
import org.scijava.plugin.Plugin;
import org.scijava.util.VersionUtils;

Expand All @@ -64,7 +76,7 @@

import net.imglib2.algorithm.Algorithm;

public class CSVImporter implements Algorithm
public class CSVImporter extends ModelImporter implements Algorithm
{

public static final String PLUGIN_VERSION = VersionUtils.getVersion( CSVImporter.class );
Expand All @@ -83,10 +95,16 @@ public class CSVImporter implements Algorithm

private final String qualityColumnName;

private final String radiusColumnName;

private final String idColumnName;

private final String parentIdColumnName;

private final String labelColumnName;

private final String tagColumnName;

private final double radius;

private final double xOrigin;
Expand All @@ -109,12 +127,16 @@ private CSVImporter(
final String zColumnName,
final String frameColumnName,
final String qualityColumName,
final String radiusColumnName,
final String idColumnName,
final String parentIdColumnName,
final String labelColumnName,
final String tagColumnName,
final double xOrigin,
final double yOrigin,
final double zOrigin )
{
super( model );
this.model = model;
this.filePath = filePath;
this.separator = separator;
Expand All @@ -124,8 +146,11 @@ private CSVImporter(
this.zColumnName = zColumnName;
this.frameColumnName = frameColumnName;
this.qualityColumnName = qualityColumName;
this.radiusColumnName = radiusColumnName;
this.idColumnName = idColumnName;
this.parentIdColumnName = parentIdColumnName;
this.labelColumnName = labelColumnName;
this.tagColumnName = tagColumnName;
this.xOrigin = xOrigin;
this.yOrigin = yOrigin;
this.zOrigin = zOrigin;
Expand Down Expand Up @@ -196,11 +221,10 @@ public boolean process()
.withSeparator( separator )
.withIgnoreQuotations( true )
.build();
try
try (final CSVReader reader = new CSVReaderBuilder( new FileReader( filePath ) )
.withCSVParser( parser )
.build())
{
final CSVReader reader = new CSVReaderBuilder( new FileReader( filePath ) )
.withCSVParser( parser )
.build();
final Iterator< String[] > it = reader.iterator();

/*
Expand Down Expand Up @@ -267,6 +291,10 @@ public boolean process()
? null
: DetectionQualityFeature.getOrRegister( model.getFeatureModel(), graph.vertices().getRefPool() );

Integer radiuscol = null;
if ( null != radiusColumnName && !radiusColumnName.isEmpty() )
radiuscol = headerMap.get( radiusColumnName );

Integer idcol = null;
if ( null != idColumnName && !idColumnName.isEmpty() )
idcol = headerMap.get( idColumnName );
Expand All @@ -275,18 +303,37 @@ public boolean process()
? null
: OriginalIdFeature.getOrRegister( model.getFeatureModel(), graph.vertices().getRefPool() );

Integer parentIdcol = null;
if ( null != parentIdColumnName && !parentIdColumnName.isEmpty() )
parentIdcol = headerMap.get( parentIdColumnName );

Integer labelcol = null;
if ( null != labelColumnName && !labelColumnName.isEmpty() )
labelcol = headerMap.get( labelColumnName );

Integer tagcol = null;
if ( null != tagColumnName && !tagColumnName.isEmpty() )
tagcol = headerMap.get( tagColumnName );

TagSetStructure.TagSet importedTagSet = null;
if ( null != tagcol )
importedTagSet = parseTagsFromFile( parser, tagcol );

IntRefMap< Spot > spotMap = new IntRefHashMap<>( model.getGraph().vertices().getRefPool(), -1 );

/*
* Iterate over the rest of lines.
*/

final WriteLock lock = graph.getLock().writeLock();
lock.lock();
final Spot vref = graph.vertexRef();
final Spot parentVertexRef = graph.vertexRef();
final Link edgeRef = graph.edgeRef();
final double[] pos = new double[ 3 ];
startImport();
if ( null != tagcol )
model.getTagSetModel().pauseListeners();

try
{
Expand All @@ -298,30 +345,46 @@ public boolean process()

try
{
pos[ 0 ] = Double.parseDouble( record[ xcol ] ) + xOrigin;
pos[ 1 ] = Double.parseDouble( record[ ycol ] ) + yOrigin;
pos[ 2 ] = Double.parseDouble( record[ zcol ] ) + zOrigin;
final int t = Integer.parseInt( record[ framecol ] );
pos[ 0 ] = Double.parseDouble( record[ xcol ].trim() ) + xOrigin;
pos[ 1 ] = Double.parseDouble( record[ ycol ].trim() ) + yOrigin;
pos[ 2 ] = Double.parseDouble( record[ zcol ].trim() ) + zOrigin;
final int t = Integer.parseInt( record[ framecol ].trim() );

double r = radius;
if ( null != radiuscol )
r = Double.parseDouble( record[ radiuscol ].trim() );

final Spot spot = graph.addVertex( vref ).init( t, pos, radius );
final Spot spot = graph.addVertex( vref ).init( t, pos, r );
if ( null != idcol )
{
final int id = Integer.parseInt( record[ idcol ] );
final int id = Integer.parseInt( record[ idcol ].trim() );
originalIdFeature.set( spot, id );
if ( null != parentIdcol )
spotMap.put( id, spot );
if ( null == labelcol )
spot.setLabel( "" + id );
}

if ( null != labelcol )
{
spot.setLabel( record[ labelcol ] );
String label = record[ labelcol ].trim();
spot.setLabel( label );
}

double q = 1.;
if ( null != qualitycol )
{
q = Double.parseDouble( record[ qualitycol ] );
q = Double.parseDouble( record[ qualitycol ].trim() );
qualityFeature.set( spot, q );
}

if ( null != tagcol )
{
String label = record[ tagcol ].trim();
TagSetStructure.Tag tag = TagSetUtils.findTag( importedTagSet, label );
TagSetUtils.tagSpot( model, importedTagSet, tag, spot );
TagSetUtils.tagLinks( model, importedTagSet, tag, spot.incomingEdges() );
}
}
catch ( final NumberFormatException nfe )
{
Expand All @@ -330,11 +393,18 @@ public boolean process()
continue;
}
}
if ( null != parentIdcol )
parseLinksFromFile( parser, spotMap, idcol, vref, parentIdcol, parentVertexRef, edgeRef );
}
finally
{
lock.unlock();
graph.releaseRef( vref );
graph.releaseRef( parentVertexRef );
graph.releaseRef( edgeRef );
if ( null != tagcol )
model.getTagSetModel().resumeListeners();
finishImport();
}
}
catch ( final FileNotFoundException e )
Expand All @@ -343,6 +413,12 @@ public boolean process()
e.printStackTrace();
return false;
}
catch ( final IOException e )
{
errorMessage = "Error reading file " + filePath;
e.printStackTrace();
return false;
}

/*
* Return.
Expand All @@ -351,6 +427,63 @@ public boolean process()
return true;
}

private void parseLinksFromFile( final CSVParser parser, final IntRefMap< Spot > spotMap, final int idCol, final Spot spotRef,
final int parentIdcol, final Spot parentSpotRef, final Link edgeRef )
{
try (final CSVReader readerTags = new CSVReaderBuilder( new FileReader( filePath ) )
.withCSVParser( parser )
.build())
{
Iterator< String[] > csvIterator = readerTags.iterator();
csvIterator.next();
while ( csvIterator.hasNext() )
{
final String[] line = csvIterator.next();
final int spotId = Integer.parseInt( line[ idCol ].trim() );
final Spot spot = spotMap.get( spotId, spotRef );
final int parentId = Integer.parseInt( line[ parentIdcol ].trim() );
final Spot parent = spotMap.get( parentId, parentSpotRef );
if ( parent != null && spot != null )
model.getGraph().addEdge( parent, spot, edgeRef ).init();
}
}
catch ( final IOException e )
{
errorMessage = "Error reading file " + filePath;
e.printStackTrace();
}
}

private TagSetStructure.TagSet parseTagsFromFile( final CSVParser parser, int labelcol )
{
try (final CSVReader readerTags = new CSVReaderBuilder( new FileReader( filePath ) )
.withCSVParser( parser )
.build())
{
Iterator< String[] > csvIterator = readerTags.iterator();

Set< String > tags = new HashSet<>();
csvIterator.next();
while ( csvIterator.hasNext() )
{
final String[] line = csvIterator.next();
String tag = line[ labelcol ].trim();
tags.add( tag );
}
GlasbeyLut glasbeyLut = new GlasbeyLut();
List< Pair< String, Integer > > tagsAndColors =
tags.stream().map( tag -> Pair.of( tag, glasbeyLut.next() ) ).collect( Collectors.toList() );

return TagSetUtils.addNewTagSetToModel( model, "Imported Tags", tagsAndColors );
}
catch ( final IOException e )
{
errorMessage = "Error reading file " + filePath;
e.printStackTrace();
return null;
}
}

@Override
public String getErrorMessage()
{
Expand Down Expand Up @@ -447,10 +580,16 @@ public static class Builder

private String qualityColumnName;

private String radiusColumnName;

private String idColumnName;

private String parentIdColumnName;

private String labelColumnName;

private String tagColumnName;

private double xOrigin = 0.;

private double yOrigin = 0.;
Expand Down Expand Up @@ -507,18 +646,36 @@ public Builder qualityColumnName( final String qualityColumnName )
return this;
}

public Builder radiusColumnName( final String radiusColumnName )
{
this.radiusColumnName = radiusColumnName;
return this;
}

public Builder idColumnName( final String idColumnName )
{
this.idColumnName = idColumnName;
return this;
}

public Builder parentIdColumnName( final String parentIdColumnName )
{
this.parentIdColumnName = parentIdColumnName;
return this;
}

public Builder labelColumnName( final String labelColumnName )
{
this.labelColumnName = labelColumnName;
return this;
}

public Builder tagColumnName( final String tagColumnName )
{
this.tagColumnName = tagColumnName;
return this;
}

public Builder xOrigin( final double xOrigin )
{
this.xOrigin = xOrigin;
Expand Down Expand Up @@ -608,8 +765,11 @@ public CSVImporter get()
zColumnName,
frameColumnName,
qualityColumnName,
radiusColumnName,
idColumnName,
parentIdColumnName,
labelColumnName,
tagColumnName,
xOrigin,
yOrigin,
zOrigin );
Expand Down
Loading

0 comments on commit 064ab80

Please sign in to comment.