func CreateManifestAndOutput(mergedPath, annotationPath, manifestPath, nestedSuffix string) (*AnnotationTracker, error) {

	// First, if we happen to be given a complete manifest, read it. If that
	// conforms to our old manifest format, use it. Just mark it non-nested.
	tracker, err := ReadNestedManifest(manifestPath, annotationPath, nestedSuffix)
	if err == nil {
		tracker.Nested = false
		return tracker, nil
	}

	// If we don't have an old-style manifest, process either the new simplified
	// manifest or, if none is given, process the folder contents.

	output := make([]ManifestEntry, 0)

	// Fetch any annotations that already exist, or create a file to hold them
	// if none yet do.
	annotations, err := OpenOrCreateAnnotationFile(annotationPath)
	if err != nil {
		return nil, err
	}

	// Now open the full manifest of files we want to critique.

	// If we actually passed a manifest file, assume it is valid and populate:
	if manifestPath != "" {
		rdr, _, err := bulkprocess.MaybeOpenFromGoogleStorage(manifestPath, global.storageClient)
		if err != nil {
			return nil, err
		}

		r := csv.NewReader(rdr)
		r.Comma = '\t'

		lines, err := r.ReadAll()
		if err != nil {
			return nil, err
		}

		for _, cols := range lines {
			entry := cols[0]
			anno, _ := annotations[DicomFilename(entry)]
			anno.Dicom = entry

			output = append(output, ManifestEntry{
				Dicom:      entry,
				Annotation: anno,
			})
		}

	} else {
		// If we did not pass a manifest file, list the directory and populate:
		files, err := ioutil.ReadDir(mergedPath)
		if err != nil {
			return nil, pfx.Err(err)
		}

		for _, f := range files {
			if f.IsDir() {
				continue
			}

			anno, _ := annotations[DicomFilename(f.Name())]

			output = append(output, ManifestEntry{
				Dicom:      f.Name(),
				Annotation: anno,
			})
		}
	}

	return &AnnotationTracker{Entries: output, AnnotationPath: annotationPath}, nil
}
// CreateManifestAndOutput lists all files in your main input directory and your
// output directory. It checks to see if the output file has already been
// created. If so, it reads the output and matches it with the input, returning
// pre-populated values.
CreateManifestAndOutput lists all files in your main input directory and your
output directory. It checks to see if the output file has already been
created. If so, it reads the output and matches it with the input, returning
pre-populated values.
// CreateManifestAndOutput lists all files in your main input directory and your // output directory . It checks to see if the output file has already been // created . If so it reads the output and matches it with the input returning // pre - populated values .
func CreateManifestAndOutput(mergedPath, annotationPath, manifestPath, nestedSuffix string) (*AnnotationTracker, error) {
	tracker, err := ReadNestedManifest(manifestPath, annotationPath, nestedSuffix)
	if err == nil {
		tracker.Nested = false
		return tracker, nil
	}
	output := make([]ManifestEntry, 0)
	annotations, err := OpenOrCreateAnnotationFile(annotationPath)
	if err != nil {
		return nil, err
	}
	if manifestPath != "" {
		rdr, _, err := bulkprocess.MaybeOpenFromGoogleStorage(manifestPath, global.storageClient)
		if err != nil {
			return nil, err
		}
		r := csv.NewReader(rdr)
		r.Comma = '\t'
		lines, err := r.ReadAll()
		if err != nil {
			return nil, err
		}
		for _, cols := range lines {
			entry := cols[0]
			anno, _ := annotations[DicomFilename(entry)]
			anno.Dicom = entry
			output = append(output, ManifestEntry{
				Dicom:      entry,
				Annotation: anno,
			})
		}
	} else {
		files, err := ioutil.ReadDir(mergedPath)
		if err != nil {
			return nil, pfx.Err(err)
		}
		for _, f := range files {
			if f.IsDir() {
				continue
			}
			anno, _ := annotations[DicomFilename(f.Name())]
			output = append(output, ManifestEntry{
				Dicom:      f.Name(),
				Annotation: anno,
			})
		}
	}
	return &AnnotationTracker{Entries: output, AnnotationPath: annotationPath}, nil
}
func CreateManifestAndOutput ( mergedPath , annotationPath , manifestPath , nestedSuffix string ) ( * AnnotationTracker , error ) { tracker , err := ReadNestedManifest ( manifestPath , annotationPath , nestedSuffix ) if err == nil { tracker . Nested = false return tracker , nil } output := make ( [ ] ManifestEntry , 0 ) annotations , err := OpenOrCreateAnnotationFile ( annotationPath ) if err != nil { return nil , err } if manifestPath != " " { rdr , _ , err := bulkprocess . MaybeOpenFromGoogleStorage ( manifestPath , global . storageClient ) if err != nil { return nil , err } r := csv . NewReader ( rdr ) r . Comma = '\t' lines , err := r . ReadAll ( ) if err != nil { return nil , err } for _ , cols := range lines { entry := cols [ 0 ] anno , _ := annotations [ DicomFilename ( entry ) ] anno . Dicom = entry output = append ( output , ManifestEntry { Dicom : entry , Annotation : anno , } ) } } else { files , err := ioutil . ReadDir ( mergedPath ) if err != nil { return nil , pfx . Err ( err ) } for _ , f := range files { if f . IsDir ( ) { continue } anno , _ := annotations [ DicomFilename ( f . Name ( ) ) ] output = append ( output , ManifestEntry { Dicom : f . Name ( ) , Annotation : anno , } ) } } return & AnnotationTracker { Entries : output , AnnotationPath : annotationPath } , nil }
CreateManifestAndOutput lists all files in your main input directory and your
output directory.
CreateManifestAndOutput lists all files in your main input directory and your output directory .
// First, if we happen to be given a complete manifest, read it. If that // conforms to our old manifest format, use it. Just mark it non-nested. // If we don't have an old-style manifest, process either the new simplified // manifest or, if none is given, process the folder contents. // Fetch any annotations that already exist, or create a file to hold them // if none yet do. // Now open the full manifest of files we want to critique. // If we actually passed a manifest file, assume it is valid and populate: // If we did not pass a manifest file, list the directory and populate: