Module: CollectionObject::DwcExtensions

Extended by:
ActiveSupport::Concern
Included in:
CollectionObject, BiologicalCollectionObject
Defined in:
app/models/collection_object/dwc_extensions.rb

Instance Method Summary collapse

Instance Method Details

TODO: likeley a helper



193
194
195
196
197
198
199
200
201
202
# File 'app/models/collection_object/dwc_extensions.rb', line 193

def api_image_link(image)
  s = ENV['SERVER_NAME']
  if s.nil?
    s ||= 'http://127.0.0.1:3000'
  else
    s = 'https://' + s
  end

  s = s + '/api/v1/images/' + image.image_file_fingerprint # An experiment, use md5 as a proxy for id (also unique id)
end

#dwc_associated_mediaObject



183
184
185
# File 'app/models/collection_object/dwc_extensions.rb', line 183

def dwc_associated_media
  images.collect{|i| api_image_link(i) }.join(CollectionObject::DWC_DELIMITER).presence
end

#dwc_associated_taxaObject



188
189
190
# File 'app/models/collection_object/dwc_extensions.rb', line 188

def dwc_associated_taxa
  dwc_internal_attribute_for(:collection_object, :associatedTaxa)
end

#dwc_catalog_numberObject



463
464
465
# File 'app/models/collection_object/dwc_extensions.rb', line 463

def dwc_catalog_number
  catalog_number_cached # via delegation
end

#dwc_classObject



385
386
387
# File 'app/models/collection_object/dwc_extensions.rb', line 385

def dwc_class
  taxonomy['class']
end

#dwc_collection_codeObject



459
460
461
# File 'app/models/collection_object/dwc_extensions.rb', line 459

def dwc_collection_code
  catalog_number_namespace&.verbatim_short_name || catalog_number_namespace&.short_name
end

#dwc_coordinate_uncertainty_in_metersObject

TODO: extend to Georeferences when we understand how to describe spatial uncertainty



239
240
241
242
243
244
245
# File 'app/models/collection_object/dwc_extensions.rb', line 239

def dwc_coordinate_uncertainty_in_meters
  if georeference_attributes[:coordinateUncertaintyInMeters]
    georeference_attributes[:coordinateUncertaintyInMeters]
  else
    collecting_event&.verbatim_geolocation_uncertainty
  end
end

#dwc_countryObject



472
473
474
475
# File 'app/models/collection_object/dwc_extensions.rb', line 472

def dwc_country
  v = try(:collecting_event).try(:geographic_names)
  v[:country] if v
end

#dwc_countyObject



482
483
484
485
# File 'app/models/collection_object/dwc_extensions.rb', line 482

def dwc_county
  v = try(:collecting_event).try(:geographic_names)
  v[:county] if v
end

#dwc_date_identifiedObject

ISO 8601:2004(E).



365
366
367
# File 'app/models/collection_object/dwc_extensions.rb', line 365

def dwc_date_identified
  current_taxon_determination&.date.presence
end

#dwc_dayObject



547
548
549
550
# File 'app/models/collection_object/dwc_extensions.rb', line 547

def dwc_day
  return unless collecting_event
  collecting_event.start_date_day.presence
end

#dwc_decimal_latitudeObject



491
492
493
# File 'app/models/collection_object/dwc_extensions.rb', line 491

def dwc_decimal_latitude
  georeference_attributes[:decimalLatitude]
end

#dwc_decimal_longitudeObject



495
496
497
# File 'app/models/collection_object/dwc_extensions.rb', line 495

def dwc_decimal_longitude
  georeference_attributes[:decimalLongitude]
end

#dwc_end_day_of_yearObject



557
558
559
560
# File 'app/models/collection_object/dwc_extensions.rb', line 557

def dwc_end_day_of_year
  return unless collecting_event
  collecting_event.end_day_of_year.presence
end

#dwc_event_dateObject



524
525
526
527
528
529
530
531
532
533
534
535
# File 'app/models/collection_object/dwc_extensions.rb', line 524

def dwc_event_date
  return unless collecting_event

  %w{start_date end_date}
    .map { |d| %w{year month day}
    .map { |p| collecting_event["#{d}_#{p}"] }
    .map { |p| '%02d' % p if p } # At least two digits
    }
      .map { |d| d.compact.join('-') }
      .reject(&:blank?)
      .join('/').presence
end

#dwc_event_remarksObject



178
179
180
# File 'app/models/collection_object/dwc_extensions.rb', line 178

def dwc_event_remarks
  collecting_event&.notes&.collect {|n| n.text}&.join('|')
end

#dwc_event_timeObject



507
508
509
510
511
512
513
514
515
516
517
518
# File 'app/models/collection_object/dwc_extensions.rb', line 507

def dwc_event_time
  return unless collecting_event

  %w{start_time end_time}
    .map { |t| %w{hour minute second}
    .map { |p| collecting_event["#{t}_#{p}"] }
    .map { |p| '%02d' % p if p } # At least two digits
    }
      .map { |t| t.compact.join(':') }
      .reject(&:blank?)
      .join('/').presence
end

#dwc_familyObject



394
395
396
# File 'app/models/collection_object/dwc_extensions.rb', line 394

def dwc_family
  taxonomy['family']
end

#dwc_field_numberObject



337
338
339
340
# File 'app/models/collection_object/dwc_extensions.rb', line 337

def dwc_field_number
  return nil unless collecting_event
  collecting_event.identifiers.where(type: 'Identifier::Local::TripCode').first&.cached
end

#dwc_footprint_wktObject



212
213
214
# File 'app/models/collection_object/dwc_extensions.rb', line 212

def dwc_footprint_wkt
  georeference_attributes[:footprintWKT]
end

#dwc_genusObject



399
400
401
# File 'app/models/collection_object/dwc_extensions.rb', line 399

def dwc_genus
  taxonomy['genus'] && taxonomy['genus'].compact.join(' ').presence
end

#dwc_geodetic_datumObject



224
225
226
# File 'app/models/collection_object/dwc_extensions.rb', line 224

def dwc_geodetic_datum
  georeference_attributes[:geodeticDatum]
end

#dwc_georeference_protocolObject



576
577
578
# File 'app/models/collection_object/dwc_extensions.rb', line 576

def dwc_georeference_protocol
  georeference_attributes[:georeferenceProtocol]
end

#dwc_georeference_remarksObject



208
209
210
# File 'app/models/collection_object/dwc_extensions.rb', line 208

def dwc_georeference_remarks
  georeference_attributes[:georeferenceRemarks]
end

#dwc_georeference_sourcesObject



204
205
206
# File 'app/models/collection_object/dwc_extensions.rb', line 204

def dwc_georeference_sources
  georeference_attributes[:georeferenceSources]
end

#dwc_georeferenced_byObject



216
217
218
# File 'app/models/collection_object/dwc_extensions.rb', line 216

def dwc_georeferenced_by
  georeference_attributes[:georeferencedBy]
end

#dwc_georeferenced_dateObject

georeferenceDate technically could look at papertrail to see when geographic_area_id appeared



234
235
236
# File 'app/models/collection_object/dwc_extensions.rb', line 234

def dwc_georeferenced_date
  georeference_attributes[:georeferencedDate]
end

#dwc_higher_classificationObject



369
370
371
372
373
374
375
# File 'app/models/collection_object/dwc_extensions.rb', line 369

def dwc_higher_classification
  v = taxonomy.values.collect{|a| a.kind_of?(Array) ? a.second : a}
  v.shift
  v.pop
  v.compact
  v.join(CollectionObject::DWC_DELIMITER)
end

#dwc_identified_byObject



445
446
447
448
# File 'app/models/collection_object/dwc_extensions.rb', line 445

def dwc_identified_by
  # TaxonWorks allows for groups of determiners to collaborate on a single determination if they collectively came to a conclusion.
  current_taxon_determination&.determiners&.map(&:name)&.join(CollectionObject::DWC_DELIMITER).presence
end

#dwc_identified_by_idObject



450
451
452
453
# File 'app/models/collection_object/dwc_extensions.rb', line 450

def dwc_identified_by_id
  # TaxonWorks allows for groups of determiners to collaborate on a single determination if they collectively came to a conclusion.
  current_taxon_determination&.determiners&.map(&:orcid)&.join(CollectionObject::DWC_DELIMITER).presence
end

#dwc_individual_countObject

TODO: handle ranged lots



468
469
470
# File 'app/models/collection_object/dwc_extensions.rb', line 468

def dwc_individual_count
  total
end

#dwc_infraspecific_epithetObject



346
347
348
349
350
351
# File 'app/models/collection_object/dwc_extensions.rb', line 346

def dwc_infraspecific_epithet
  %w{variety form subspecies}.each do |n| # add more as observed
    return taxonomy[n].last if taxonomy[n]
  end
  nil
end

#dwc_institution_codeObject

we assert custody, NOT ownership



567
568
569
# File 'app/models/collection_object/dwc_extensions.rb', line 567

def dwc_institution_code
  repository.try(:acronym)
end

#dwc_institution_idObject

we assert custody, NOT ownership



572
573
574
# File 'app/models/collection_object/dwc_extensions.rb', line 572

def dwc_institution_id
  repository_url
end

#dwc_internal_attribute_for(target = :collection_object, dwc_term_name) ⇒ Object



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
# File 'app/models/collection_object/dwc_extensions.rb', line 267

def dwc_internal_attribute_for(target = :collection_object, dwc_term_name)
  return nil if dwc_term_name.nil?

  case target
  when  :collecting_event
    return nil unless collecting_event
    collecting_event.internal_attributes.includes(:predicate)
      .where(
        controlled_vocabulary_terms: {uri: ::DWC_ATTRIBUTE_URIS[dwc_term_name.to_sym] })
      .pluck(:value)&.join(', ').presence
  when :collection_object
    internal_attributes.includes(:predicate)
      .where(
        controlled_vocabulary_terms: {uri: ::DWC_ATTRIBUTE_URIS[dwc_term_name.to_sym] })
      .pluck(:value)&.join(', ').presence
  else
    nil
  end
end

#dwc_kingdomObject



377
378
379
# File 'app/models/collection_object/dwc_extensions.rb', line 377

def dwc_kingdom
  taxonomy['kingdom']
end

#dwc_life_stageObject

TODO: consider CVT attributes with Predicates linked to URIs



304
305
306
307
# File 'app/models/collection_object/dwc_extensions.rb', line 304

def dwc_life_stage
  biocuration_classes.tagged_with_uri(::DWC_ATTRIBUTE_URIS[:lifeStage])
    .pluck(:name)&.join(', ').presence # `.presence` is a Rails extension
end

#dwc_localityObject



487
488
489
# File 'app/models/collection_object/dwc_extensions.rb', line 487

def dwc_locality
  collecting_event.try(:verbatim_locality)
end

#dwc_maximum_depth_in_metersObject



295
296
297
# File 'app/models/collection_object/dwc_extensions.rb', line 295

def dwc_maximum_depth_in_meters
  dwc_internal_attribute_for(:collecting_event, :maximumDepthInMeters)
end

#dwc_maximum_elevation_in_metersObject



324
325
326
# File 'app/models/collection_object/dwc_extensions.rb', line 324

def dwc_maximum_elevation_in_meters
  collecting_event&.maximum_elevation
end

#dwc_minimum_depth_in_metersObject



291
292
293
# File 'app/models/collection_object/dwc_extensions.rb', line 291

def dwc_minimum_depth_in_meters
  dwc_internal_attribute_for(:collecting_event, :minimumDepthInMeters)
end

#dwc_minimum_elevation_in_metersObject



328
329
330
# File 'app/models/collection_object/dwc_extensions.rb', line 328

def dwc_minimum_elevation_in_meters
  collecting_event&.minimum_elevation
end

#dwc_monthObject



542
543
544
545
# File 'app/models/collection_object/dwc_extensions.rb', line 542

def dwc_month
  return unless collecting_event
  collecting_event.start_date_month.presence
end

#dwc_nomenclatural_codeObject



503
504
505
# File 'app/models/collection_object/dwc_extensions.rb', line 503

def dwc_nomenclatural_code
  current_otu.try(:taxon_name).try(:nomenclatural_code)
end

#dwc_occurrence_remarksObject



174
175
176
# File 'app/models/collection_object/dwc_extensions.rb', line 174

def dwc_occurrence_remarks
  notes.collect{|n| n.text}.join('|')
end

#dwc_occurrence_statusObject



169
170
171
# File 'app/models/collection_object/dwc_extensions.rb', line 169

def dwc_occurrence_status
  'present'
end

#dwc_orderObject



389
390
391
# File 'app/models/collection_object/dwc_extensions.rb', line 389

def dwc_order
  taxonomy['order']
end

#dwc_other_catalog_numbersObject



255
256
257
258
259
# File 'app/models/collection_object/dwc_extensions.rb', line 255

def dwc_other_catalog_numbers
  i = identifiers.where.not('type ilike ?', 'Identifier::Global::Uuid%').order(:position).to_a
  i.shift
  i.map(&:cached).join(CollectionObject::DWC_DELIMITER).presence
end

#dwc_phylumObject



381
382
383
# File 'app/models/collection_object/dwc_extensions.rb', line 381

def dwc_phylum
  taxonomy['phylum']
end

#dwc_preparationsObject



562
563
564
# File 'app/models/collection_object/dwc_extensions.rb', line 562

def dwc_preparations
  preparation_type_name
end

#dwc_previous_identificationsObject



261
262
263
264
265
# File 'app/models/collection_object/dwc_extensions.rb', line 261

def dwc_previous_identifications
  a = taxon_determinations.order(:position).to_a
  a.shift
  a.collect{|d| ApplicationController.helpers.label_for_taxon_determination(d)}.join(CollectionObject::DWC_DELIMITER).presence
end

#dwc_recorded_byObject

Definition: A list (concatenated and separated) of names of people, groups, or organizations responsible for recording the original Occurrence. The primary collector or observer, especially one who applies a personal identifier (recordNumber), should be listed first.

This was interpreted as collectors (in the field in this context), not those who recorded other aspects of the data.



419
420
421
422
423
424
425
426
427
428
429
430
# File 'app/models/collection_object/dwc_extensions.rb', line 419

def dwc_recorded_by
  v = nil
  if collecting_event
    v = collecting_event.collectors
      .order('roles.position')
      .map(&:name)
      .join(CollectionObject::DWC_DELIMITER)
      .presence
    v = collecting_event.verbatim_collectors.presence if v.blank?
  end
  v
end

#dwc_recorded_by_idObject

See dwc_recorded_by TODO: Expand to any GlobalIdentifier



434
435
436
437
438
439
440
441
442
443
# File 'app/models/collection_object/dwc_extensions.rb', line 434

def dwc_recorded_by_id
  if collecting_event
    collecting_event.collectors
      .order('roles.position')
      .map(&:orcid)
      .compact
      .join(CollectionObject::DWC_DELIMITER)
      .presence
  end
end

#dwc_sampling_protocolObject

TODO: Reconcile with Protocol (capital P) assignments



333
334
335
# File 'app/models/collection_object/dwc_extensions.rb', line 333

def dwc_sampling_protocol
  collecting_event&.verbatim_method
end

#dwc_scientific_nameObject



408
409
410
# File 'app/models/collection_object/dwc_extensions.rb', line 408

def dwc_scientific_name
  current_taxon_name.try(:cached_name_and_author_year)
end

#dwc_sexObject

TODO: consider CVT attributes with Predicates linked to URIs



310
311
312
313
# File 'app/models/collection_object/dwc_extensions.rb', line 310

def dwc_sex
  biocuration_classes.tagged_with_uri(::DWC_ATTRIBUTE_URIS[:sex])
    .pluck(:name)&.join(', ').presence
end

#dwc_specific_epithetObject



404
405
406
# File 'app/models/collection_object/dwc_extensions.rb', line 404

def dwc_specific_epithet
  taxonomy['species'] && taxonomy['species'].compact.join(' ').presence
end

#dwc_start_day_of_yearObject



552
553
554
555
# File 'app/models/collection_object/dwc_extensions.rb', line 552

def dwc_start_day_of_year
  return unless collecting_event
  collecting_event.start_day_of_year.presence
end

#dwc_state_provinceObject



477
478
479
480
# File 'app/models/collection_object/dwc_extensions.rb', line 477

def dwc_state_province
  v = try(:collecting_event).try(:geographic_names)
  v[:state] if v
end

#dwc_taxon_name_authorshipObject



412
413
414
# File 'app/models/collection_object/dwc_extensions.rb', line 412

def dwc_taxon_name_authorship
  current_taxon_name.try(:cached_author_year)
end

#dwc_taxon_rankObject



353
354
355
# File 'app/models/collection_object/dwc_extensions.rb', line 353

def dwc_taxon_rank
  current_taxon_name&.rank
end

#dwc_type_statusObject

holotype of Ctenomys sociabilis. Pearson O. P., and M. I. Christie. 1985. Historia Natural, 5(37):388, holotype of Pinus abies | holotype of Picea abies



358
359
360
361
362
# File 'app/models/collection_object/dwc_extensions.rb', line 358

def dwc_type_status
  type_materials.all.collect{|t|
    ApplicationController.helpers.label_for_type_material(t)
  }.join(CollectionObject::DWC_DELIMITER).presence
end

#dwc_verbatim_coordinatesObject



315
316
317
318
# File 'app/models/collection_object/dwc_extensions.rb', line 315

def dwc_verbatim_coordinates
  return nil unless collecting_event
  [collecting_event.verbatim_latitude, collecting_event.verbatim_longitude].compact.join(' ').presence
end

#dwc_verbatim_depthObject



299
300
301
# File 'app/models/collection_object/dwc_extensions.rb', line 299

def dwc_verbatim_depth
  dwc_internal_attribute_for(:collecting_event, :verbatimDepth)
end

#dwc_verbatim_elevationObject



320
321
322
# File 'app/models/collection_object/dwc_extensions.rb', line 320

def dwc_verbatim_elevation
  collecting_event&.verbatim_elevation
end

#dwc_verbatim_event_dateObject



520
521
522
# File 'app/models/collection_object/dwc_extensions.rb', line 520

def dwc_verbatim_event_date
  collecting_event&.verbatim_date
end

#dwc_verbatim_habitatObject



342
343
344
# File 'app/models/collection_object/dwc_extensions.rb', line 342

def dwc_verbatim_habitat
  collecting_event&.verbatim_habitat
end

#dwc_verbatim_labelObject

use buffered if any if not check CE verbatim_label



163
164
165
166
167
# File 'app/models/collection_object/dwc_extensions.rb', line 163

def dwc_verbatim_label
  b = [buffered_collecting_event, buffered_determinations, buffered_other_labels].compact
  return  b.join("\n\n") if b.present?
  collecting_event&.verbatim_label.presence
end

#dwc_verbatim_latitudeObject



247
248
249
# File 'app/models/collection_object/dwc_extensions.rb', line 247

def dwc_verbatim_latitude
  collecting_event&.verbatim_latitude
end

#dwc_verbatim_localityObject



499
500
501
# File 'app/models/collection_object/dwc_extensions.rb', line 499

def dwc_verbatim_locality
  collecting_event.try(:verbatim_locality)
end

#dwc_verbatim_longitudeObject



251
252
253
# File 'app/models/collection_object/dwc_extensions.rb', line 251

def dwc_verbatim_longitude
  collecting_event&.verbatim_longitude
end

#dwc_verbatim_srsObject



228
229
230
# File 'app/models/collection_object/dwc_extensions.rb', line 228

def dwc_verbatim_srs
  georeference_attributes[:dwcVerbatimSrs]
end

#dwc_water_bodyObject



287
288
289
# File 'app/models/collection_object/dwc_extensions.rb', line 287

def dwc_water_body
  dwc_internal_attribute_for(:collecting_event, :waterBody)
end

#dwc_yearObject



537
538
539
540
# File 'app/models/collection_object/dwc_extensions.rb', line 537

def dwc_year
  return unless collecting_event
  collecting_event.start_date_year.presence
end

#is_fossil?Boolean

Returns:

  • (Boolean)


157
158
159
# File 'app/models/collection_object/dwc_extensions.rb', line 157

def is_fossil?
  biocuration_classes.where(uri: DWC_FOSSIL_URI).any?
end

#set_georeference_attributesHash

Returns:

  • (Hash)


127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'app/models/collection_object/dwc_extensions.rb', line 127

def set_georeference_attributes
  case collecting_event&.dwc_georeference_source
  when :georeference
    collecting_event.preferred_georeference.dwc_georeference_attributes
  when :verbatim
    h = collecting_event.dwc_georeference_attributes

    if a = collecting_event&.attribute_updater(:verbatim_latitude)
      h[:georeferencedBy] = User.find(a).name
    end

    # verbatim_longitude could technically be different, but...
    h[:georeferencedDate] = collecting_event&.attribute_updated(:verbatim_latitude)

    h

  when :geographic_area
    h = collecting_event.geographic_area.dwc_georeference_attributes
    if a = collecting_event&.attribute_updater(:geographic_area_id)
      h[:georeferencedBy] = User.find(a).name
    end

    h[:georeferencedDate] = collecting_event&.attribute_updated(:geographic_area_id)

    h
  else
    {}
  end
end